abank 0.2.5 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abank
4
+ # acesso a base dados abank no bigquery
5
+ class Big
6
+ DF = '%Y-%m-%d'
7
+
8
+ # @return [Integer] contrato arrendamento em tratamento
9
+ attr_reader :ctpos
10
+
11
+ # (see CLI#criact)
12
+ def ct_cria
13
+ unless ct_existe?
14
+ dml("insert into #{BD}.re #{sql_contrato_mv}")
15
+ puts("CONTRATO #{opcao[:c]} #{bqnrs.zero? ? 'NAO ' : ''}INSERIDO")
16
+ end
17
+ # processar rendas sim/nao?
18
+ return unless bqnrs.positive? && opcao[:t]
19
+
20
+ # processa rendas associadas ao contrato arrendamento
21
+ ct_dados.re_insert
22
+ end
23
+
24
+ # @return [Boolean] contrato arrendamento ja existe sim/nao?
25
+ def ct_existe?
26
+ @ctlct = [{ ct: opcao[:c] }]
27
+ vaz = sql("select ct from #{BD}.re where ct in(#{str_lc}) and cnt=0").empty?
28
+ unless vaz
29
+ @bqnrs = 1
30
+ puts('CONTRATO JA EXISTE')
31
+ end
32
+ !vaz
33
+ end
34
+
35
+ # (see CLI#apagact)
36
+ def ct_apaga
37
+ @ctlct = [{ ct: opcao[:c] }]
38
+ re_delete_dml
39
+ end
40
+
41
+ # optem lista dados contrato arrendamento (inclui lista movimentos novos)
42
+ #
43
+ # @return [Big] acesso a base dados abank no bigquery
44
+ def ct_dados
45
+ ctlct.map! do |ctr|
46
+ opcao[:c] = ctr[:ct]
47
+ lre = sql(sql_last_re)[0]
48
+ ctr.merge(lre, mv: sql(sql_novo_mv(lre[:dl])))
49
+ end
50
+ self
51
+ end
52
+
53
+ # @param [Array] are lista rendas novas atual
54
+ # @return [Array<String>] lista rendas novas duma lista contratos arrendamento
55
+ def ct_rendas(lre = [])
56
+ while ctpos < ctlct.size
57
+ @mvpos = 0
58
+ lre += re_rendas
59
+ @ctpos += 1
60
+ end
61
+ lre
62
+ end
63
+
64
+ # @example sem dados movimentos
65
+ # [{ ct: 'r03000' }, ...]
66
+ # @example com dados movimentos
67
+ # [{ct: 'r03000', dc: '2020-03-01', ano: 2020, cnt: 0, dl: '2020-03-01', mv: [{dl: '2020-03-02', vl: 30}, ...] }]
68
+ # @return [Array<Hash>] lista dados contrato arrendamento (inclui lista movimentos novos)
69
+ def ctlct
70
+ @ctlct ||= []
71
+ end
72
+
73
+ # @return [String] texto formatado que representa lista de contratos arrendamento
74
+ def str_lc(sep = "'")
75
+ ctlct.map { |cid| sep + cid[:ct] + sep }.join(',')
76
+ end
77
+
78
+ # @return [String] sql para obter ultima renda do contrato arrendamento
79
+ def sql_last_re
80
+ 'select ct,DATE_SUB(DATE_SUB(dl,INTERVAL dias DAY),INTERVAL IF(cnt=0,0,cnt-1) MONTH) dc,ano,cnt,dl'\
81
+ ',CAST(REGEXP_EXTRACT(ct,r"\d+") as numeric)/100 vr '\
82
+ "from #{BD}.re where ct='#{opcao[:c]}' order by ano desc,cnt desc limit 1"
83
+ end
84
+
85
+ # @return [String] sql para obter movimentos novos (depois da ultima renda do contrato arrendamento)
86
+ def sql_novo_mv(mdl)
87
+ "select dl,vl from #{BD}.mv where ct='#{opcao[:c]}' and dl>='#{(mdl + 1).strftime(DF)}' order by dl,dv"
88
+ end
89
+
90
+ # @return [String] sql para obter dados do inicio contrato arrendamento
91
+ def sql_contrato_mv
92
+ cti = opcao[:c]
93
+ dat = opcao[:d]
94
+ if dat.empty?
95
+ 'select ct,EXTRACT(YEAR FROM DATE_TRUNC(dl,MONTH)) ano,0 cnt,DATE_TRUNC(dl,MONTH) dl,0 dias '\
96
+ "from #{BD}.mv where ct='#{cti}' order by dl limit 1"
97
+ else
98
+ "select '#{cti}' ct,EXTRACT(YEAR FROM DATE '#{dat}') ano,0 cnt,DATE '#{dat}' dl,0 dias"
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abank
4
+ # @see Big
5
+ class Big
6
+ # @return [Integer] movimento do contrato arrendamento em tratamento
7
+ attr_reader :mvpos
8
+
9
+ # (see CLI#recriare)
10
+ def re_atualiza
11
+ # [re]cria rendas novas/todas dos contratos ativos
12
+ @ctlct = sql("select distinct ct from #{BD}.re")
13
+ re_apaga.ct_dados.re_insert
14
+ end
15
+
16
+ # insere rendas associadas a lista contratos arrendamento no bigquery
17
+ def re_insert
18
+ @ctpos = 0
19
+ vls = ct_rendas.join(',')
20
+ if vls.empty?
21
+ puts('NAO EXISTEM RENDAS NOVAS')
22
+ else
23
+ dml("insert #{BD}.re VALUES#{vls}")
24
+ puts("RENDAS #{str_lc('')} CRIADAS #{bqnrs}")
25
+ end
26
+ end
27
+
28
+ # apaga rendas da lista de contrato arrendamento
29
+ #
30
+ # @return [Big] acesso a base dados abank no bigquery
31
+ def re_apaga
32
+ return self if !opcao[:t] || ctlct.empty?
33
+
34
+ # para nao apagar contrato arrendamento - somente as rendas
35
+ opcao[:t] = false
36
+
37
+ re_delete_dml
38
+ self
39
+ end
40
+
41
+ # @return [Array<String>] lista rendas novas dum contrato arrendamento
42
+ def re_rendas
43
+ lre = []
44
+ while mvpos < re_atual[:mv].size && re_saldo_mv?
45
+ lre << re_nova_renda
46
+ @mvpos += 1 unless re_saldo_mv?
47
+ end
48
+ lre
49
+ end
50
+
51
+ # @return [String] renda formatada (values.re)
52
+ def re_nova_renda
53
+ re_proximos_dados
54
+ "('#{re_atual[:ct]}',#{ano},#{cnt},'#{re_atual_mv[:dl].strftime(DF)}',#{dias})"
55
+ end
56
+
57
+ # @return [Hash] dados contrato arrendamento (inclui lista movimentos novos)
58
+ def re_proximos_dados
59
+ # valor renda paga retirada do movimento
60
+ re_atual_mv[:vl] -= re_atual[:vr]
61
+ dre = cnt.zero? ? Date.new(ano, 1, 1) : Date.new(ano, cnt, 1) >> 1
62
+ re_atual.merge!(ano: dre.year, cnt: dre.month)
63
+ end
64
+
65
+ # apaga rendas da lista de contratos arrendamento
66
+ def re_delete_dml
67
+ dml("delete from #{BD}.re where ct in(#{str_lc})#{opcao[:t] ? '' : ' and cnt>0'}")
68
+ puts("RENDAS #{str_lc('')} APAGADAS #{bqnrs}")
69
+ end
70
+
71
+ # @return [Boolean] movimento com saldo suficiente?
72
+ def re_saldo_mv?
73
+ re_atual_mv[:vl] >= re_atual[:vr]
74
+ end
75
+
76
+ # @return [Hash] dados contrato arrendamento atual (inclui lista movimentos novos)
77
+ def re_atual
78
+ ctlct[ctpos]
79
+ end
80
+
81
+ # @return [Hash] movimento atual contrato arrendamento
82
+ def re_atual_mv
83
+ re_atual[:mv][mvpos]
84
+ end
85
+
86
+ # @return [Integer] ano da renda
87
+ def ano
88
+ re_atual[:ano]
89
+ end
90
+
91
+ # @return [Integer] numero da renda (0-12)
92
+ def cnt
93
+ re_atual[:cnt]
94
+ end
95
+
96
+ # @return [Integer] dias atraso/antecipo neste pagamento renda
97
+ def dias
98
+ re_atual_mv[:dl].mjd - (Date.new(ano, cnt, 1) >> (re_atual[:dc].month - 1)).mjd
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require('roo')
4
+
5
+ module Abank
6
+ # @see Folha
7
+ class Folha < Big
8
+ # @return [Roo::Excelx] folha calculo a processar
9
+ # attr_reader :folha
10
+
11
+ # @return [Array] row folha calculo em processamento
12
+ attr_reader :rowfc
13
+
14
+ # @return [String] movimentos a inserir (values.mv)
15
+ attr_reader :mvvls
16
+
17
+ # acesso a folha calculo & base dados abank no bigquery
18
+ #
19
+ # @param [String] xls folha calculo a processar
20
+ # @param [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
21
+ # @option opcoes [Boolean] :s (false) apaga movimento similar? (mv)
22
+ # @option opcoes [Boolean] :e (false) apaga movimento igual? (mv)
23
+ # @option opcoes [Boolean] :i (false) insere movimento novo? (mv)
24
+ # @option opcoes [String] :v ('') data valor movimentos (mv)
25
+ # @option opcoes [String] :g ('') classificacao movimentos (mv)
26
+ def initialize(opcoes = {})
27
+ @opcao = super
28
+ @opcao[:s] = opcoes.fetch(:s, false)
29
+ @opcao[:e] = opcoes.fetch(:e, false)
30
+ @opcao[:i] = opcoes.fetch(:i, false)
31
+ @opcao[:v] = opcoes.fetch(:v, '')
32
+ @opcao[:g] = opcoes.fetch(:g, '')
33
+ # acumuladores necessitam init
34
+ @opcao[:k] = ''
35
+ @mvvls = ''
36
+ end
37
+
38
+ # @return [Roo::Excelx] folha calculo a processar
39
+ def folha
40
+ @folha ||= Roo::Spreadsheet.open(opcao[:f])
41
+ end
42
+
43
+ # carrega/mostra folha calculo
44
+ def processa_xls
45
+ puts("\n#{folha.info}")
46
+ folha.sheet(0).parse(header_search: ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor']) do |row|
47
+ puts(processa_linha) if ok?(row)
48
+ end
49
+ return unless opcao[:i]
50
+
51
+ # processa movimentos & atualiza rendas
52
+ mv_delete.mv_insert.ct_dados.re_insert
53
+ end
54
+
55
+ # @return [Integer] numero conta associado a folha calculo
56
+ # @example
57
+ # mov*.xlsx --> 1 --> conta-corrente
58
+ # movCard*.xlsx --> 2 --> conta-cartao
59
+ def conta
60
+ opcao[:f].match?(/card/i) ? 2 : 1
61
+ end
62
+
63
+ # @param [Hash] linha da folha calculo em processamento
64
+ # @return [Boolean] linha com valores para processar?
65
+ def ok?(linha)
66
+ @rowfc = linha.values
67
+ return false if rowfc[0].is_a?(String)
68
+
69
+ rowfc[2] = rowfc[2].strip
70
+ rowfc[3] = -1 * rowfc[3] if conta > 1
71
+ true
72
+ end
73
+
74
+ # @return [String] texto informativo formatado da linha processada
75
+ def processa_linha
76
+ # pesquisa existencia linha folha calculo no bigquery
77
+ # array.count = 0 ==> pode carregar esta linha
78
+ # array.count = 1 ==> mais testes necessarios
79
+ # array.count > 1 ==> nao pode carregar esta linha
80
+ sql(sql_existe_mv, [{}, {}])
81
+
82
+ if linha_naoexiste? then linha_base + values_mv
83
+ elsif linha_existe? then linha_existe
84
+ elsif linha_simila? then linha_similar
85
+ else linha_multiplas
86
+ end
87
+ end
88
+
89
+ # insere & classifica movimentos no bigquery
90
+ #
91
+ # @return [Big] acesso a base dados abank no bigquery
92
+ def mv_insert
93
+ unless mvvls.empty?
94
+ @mvvls = mvvls[1..] if mvvls[0] == ','
95
+ dml("insert #{BD}.mv VALUES#{mvvls}")
96
+ puts("MOVIMENTOS INSERIDOS #{bqnrs}")
97
+ mv_classifica if bqnrs.positive?
98
+ end
99
+ self
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Abank
4
+ # acesso a folha calculo & base dados abank no bigquery
5
+ class Folha < Big
6
+ # @return [Boolean] linha folha calculo nao existe no bigquery?
7
+ def linha_naoexiste?
8
+ bqres.empty?
9
+ end
10
+
11
+ # @return [Boolean] linha folha calculo existe no bigquery?
12
+ def linha_existe?
13
+ bqres.count == 1 && bqres.first[:ds].strip == rowfc[2]
14
+ end
15
+
16
+ # @return [Boolean] linha folha calculo existe parecida no bigquery?
17
+ def linha_simila?
18
+ bqres.count == 1 && bqres.first[:ds].strip != rowfc[2]
19
+ end
20
+
21
+ # @return [String] texto base formatado para display
22
+ def linha_base
23
+ "#{rowfc[0].strftime(DF)} #{format('%<v3>-34.34s %<v4>8.2f', v3: rowfc[2], v4: rowfc[3])}"
24
+ end
25
+
26
+ # @return [String] texto linha existente formatada para display
27
+ def linha_existe
28
+ add_kys if opcao[:e]
29
+ "#{linha_base} EXIS #{format('%<v1>20d', v1: bqres.first[:ky])}"
30
+ end
31
+
32
+ # @return [String] texto linha similar formatada para display
33
+ def linha_similar
34
+ add_kys if opcao[:s]
35
+ "#{linha_base} SIMI #{format('%<v1>-20.20s', v1: bqres.first[:ds].strip)}"
36
+ end
37
+
38
+ # @return [String] texto linha existencia multipla formatada para display
39
+ def linha_multiplas
40
+ "#{linha_base} MULT(#{bqres.count})"
41
+ end
42
+
43
+ # obtem chaves movimento (keysin.mv) para apagar
44
+ def add_kys
45
+ bqres.each { |row| opcao[:k] += ",#{row[:ky]}" }
46
+ end
47
+
48
+ # @return [String] sql para movimentos no bigquery
49
+ def sql_existe_mv
50
+ "select *,#{ky_mv} as ky from #{BD}.mv where nc=#{conta} and dl='#{rowfc[0].strftime(DF)}' and vl=#{rowfc[3]}"
51
+ end
52
+
53
+ # obtem movimento (values.mv) para inserir
54
+ #
55
+ # @return [String] ' NOVO'
56
+ def values_mv
57
+ @mvvls += ",('#{rowfc[0].strftime(DF)}','#{dvc.strftime(DF)}','#{rowfc[2]}',#{rowfc[3]}"\
58
+ ",#{conta},#{dvc.year},#{dvc.month},'#{tpc}',#{ctc})"
59
+ ' NOVO'
60
+ end
61
+
62
+ # @return [Date] data valor corrigida
63
+ def dvc
64
+ dvl = opcao[:v]
65
+ dvl.empty? ? rowfc[1] : Date.parse(dvl)
66
+ end
67
+
68
+ # @return [String] classificacao do movimento (null --> classificacao automatica)
69
+ def ctc
70
+ cmv = opcao[:g]
71
+ cmv.empty? ? 'null' : "'#{cmv}'"
72
+ end
73
+
74
+ # @return [String] tipo movimento c[redito] ou d[ebito]
75
+ def tpc
76
+ rowfc[3].positive? ? 'c' : 'd'
77
+ end
78
+ end
79
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Abank
4
- VERSION = '0.2.5'
4
+ VERSION = '0.3.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abank
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hernâni Rodrigues Vaz
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-06-10 00:00:00.000000000 Z
11
+ date: 2020-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -39,13 +39,13 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: google-cloud-bigquery
42
+ name: reek
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
- type: :runtime
48
+ type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
@@ -53,7 +53,49 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: roo
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: solargraph
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: yard
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: google-cloud-bigquery
57
99
  requirement: !ruby/object:Gem::Requirement
58
100
  requirements:
59
101
  - - ">="
@@ -67,7 +109,7 @@ dependencies:
67
109
  - !ruby/object:Gem::Version
68
110
  version: '0'
69
111
  - !ruby/object:Gem::Dependency
70
- name: thor
112
+ name: roo
71
113
  requirement: !ruby/object:Gem::Requirement
72
114
  requirements:
73
115
  - - ">="
@@ -81,7 +123,7 @@ dependencies:
81
123
  - !ruby/object:Gem::Version
82
124
  version: '0'
83
125
  - !ruby/object:Gem::Dependency
84
- name: yard
126
+ name: thor
85
127
  requirement: !ruby/object:Gem::Requirement
86
128
  requirements:
87
129
  - - ">="
@@ -117,10 +159,11 @@ files:
117
159
  - bin/setup
118
160
  - exe/abank
119
161
  - lib/abank.rb
120
- - lib/abank/big.rb
121
- - lib/abank/contrato.rb
122
- - lib/abank/folha.rb
123
- - lib/abank/rendas.rb
162
+ - lib/abank/big1.rb
163
+ - lib/abank/big2.rb
164
+ - lib/abank/big3.rb
165
+ - lib/abank/folha1.rb
166
+ - lib/abank/folha2.rb
124
167
  - lib/abank/version.rb
125
168
  homepage: https://github.com/hernanirvaz/abank
126
169
  licenses:
@@ -134,16 +177,16 @@ require_paths:
134
177
  - lib
135
178
  required_ruby_version: !ruby/object:Gem::Requirement
136
179
  requirements:
137
- - - ">="
180
+ - - "~>"
138
181
  - !ruby/object:Gem::Version
139
- version: 2.3.0
182
+ version: '2.7'
140
183
  required_rubygems_version: !ruby/object:Gem::Requirement
141
184
  requirements:
142
185
  - - ">="
143
186
  - !ruby/object:Gem::Version
144
187
  version: '0'
145
188
  requirements: []
146
- rubygems_version: 3.0.8
189
+ rubygems_version: 3.1.2
147
190
  signing_key:
148
191
  specification_version: 4
149
192
  summary: Arquiva movimentos conta-corrente, conta-cartao do activobank no bigquery.