abank 0.2.5 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,134 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'google/cloud/bigquery'
4
-
5
- # @see Abank::Big
6
- class Abank::Big
7
- DF = '%Y-%m-%d'
8
-
9
- # @return [Hash] opcoes trabalho
10
- attr_reader :opcao
11
-
12
- # @return [Google::Cloud::Bigquery] API bigquery
13
- attr_reader :bqapi
14
-
15
- # @return [Google::Cloud::Bigquery::QueryJob] job bigquery
16
- attr_reader :bqjob
17
-
18
- # @return [Google::Cloud::Bigquery::Data] resultado do select
19
- attr_reader :bqres
20
-
21
- # @return [Integer] numero linhas afetadas pela Data Manipulation Language (DML)
22
- attr_reader :bqnrs
23
-
24
- # @return [String] movimentos a inserir (values.mv)
25
- attr_reader :mvvls
26
-
27
- # @return [String] movimentos a apagar (keysin.mv)
28
- attr_reader :mvkys
29
-
30
- # acesso a base dados abank no bigquery
31
- #
32
- # @param [Hash] opc opcoes trabalho
33
- # @option opc [String] :k ('') movimentos a apagar (keysin.mv)
34
- # @option opc [String] :c ('') id contrato arrendamento (re)
35
- # @option opc [String] :d ('') data inicio contrato arrendamento (re)
36
- # @option opc [Boolean] :t (false) trabalha todas as rendas? (re)
37
- # @return [Hash] opcoes trabalho
38
- def initialize(opc = {})
39
- @opcao = opc
40
- @bqapi = Google::Cloud::Bigquery.new
41
- @mvvls = ''
42
- @mvkys = opc.fetch(:k, '')
43
- @ctide = opc.fetch(:c, '')
44
- # p ['B', opcao]
45
- opcao
46
- end
47
-
48
- # (see CLI#tag)
49
- def mv_classifica
50
- dml('update hernanilr.ab.mv set mv.ct=tt.nct ' \
51
- 'from (select * from hernanilr.ab.cl) as tt ' \
52
- "where #{ky_mv}=tt.ky")
53
- puts 'MOVIMENTOS CLASSIFICADOS ' + bqnrs.to_s
54
- end
55
-
56
- # apaga movimentos & suas rendas associadas no bigquery
57
- #
58
- # @return [Big] acesso a base dados abank no bigquery
59
- def mv_delete
60
- vars_mv_work
61
- if mvkys.size.positive?
62
- # obtem lista contratos arrendamento associados aos movimentos a apagar
63
- @ctlct = sel("select ct from hernanilr.ab.mv where #{ky_mv} in(#{mvkys}) and substr(ct,1,1)='r' group by 1")
64
-
65
- # apaga rendas associadas e depois movimentos
66
- @opcao[:t] = true
67
- lr_apaga.mv_delete_dml
68
-
69
- # para obrigar re_work a trabalhar com lista contratos (ctlct)
70
- @bqnrs = 0
71
- end
72
- self
73
- end
74
-
75
- # insere & classifica movimentos no bigquery
76
- #
77
- # @return [Big] acesso a base dados abank no bigquery
78
- def mv_insert
79
- if mvvls.size.positive?
80
- dml('insert hernanilr.ab.mv VALUES' + mvvls)
81
- puts 'MOVIMENTOS INSERIDOS ' + bqnrs.to_s
82
- mv_classifica if bqnrs.positive?
83
- end
84
- self
85
- end
86
-
87
- # inicializa variaveis para delete/insert movimentos
88
- def vars_mv_work
89
- @bqnrs = 0
90
- @ctlct = []
91
- @mvkys = mvkys[1..] if mvkys[0] == ','
92
- @mvvls = mvvls[1..] if mvvls[0] == ','
93
- end
94
-
95
- # apaga movimentos no bigquery
96
- def mv_delete_dml
97
- dml("delete from hernanilr.ab.mv where #{ky_mv} in(#{mvkys})")
98
- puts 'MOVIMENTOS APAGADOS ' + bqnrs.to_s
99
- end
100
-
101
- # @return [String] expressao sql da chave de movimentos
102
- def ky_mv
103
- 'FARM_FINGERPRINT(CONCAT(CAST(mv.nc as STRING),mv.ds,CAST(mv.dl as STRING),CAST(mv.vl as STRING)))'
104
- end
105
-
106
- # cria job bigquery & verifica execucao
107
- #
108
- # @param [String] sql comando a executar
109
- # @return [Boolean] job ok?
110
- def job?(sql)
111
- # p sql
112
- @bqjob = bqapi.query_job(sql)
113
- @bqjob.wait_until_done!
114
- puts @bqjob.error['message'] if @bqjob.failed?
115
- @bqjob.failed?
116
- end
117
-
118
- # executa sql & devolve resultado do bigquery
119
- #
120
- # @param (see job?)
121
- # @param [Array] erro quando da erro no bigquery
122
- # @return [Google::Cloud::Bigquery::Data] resultado do sql
123
- def sel(sql, erro = [])
124
- @bqres = job?(sql) ? erro : bqjob.data
125
- end
126
-
127
- # executa Data Manipulation Language (DML) no bigquery
128
- #
129
- # @param (see job?)
130
- # @return [Integer] numero rows afetadas pelo dml
131
- def dml(sql)
132
- @bqnrs = job?(sql) ? 0 : bqjob.num_dml_affected_rows
133
- end
134
- end
@@ -1,107 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # acesso a base dados abank no bigquery
4
- class Abank::Big
5
- # @return [String] id contrato arrendamento
6
- attr_reader :ctide
7
-
8
- # @return [Array<Hash>] lista ids contratos arrendamento
9
- # @example
10
- # [{ ct: 'r03000' }, ...]
11
- attr_reader :ctlct
12
-
13
- # @return [Array<Hash>] lista dados contrato arrendamento (inclui lista movimentos novos)
14
- # @example
15
- # [{ct: 'r03000', dc: '2020-03-01', ano: 2020, cnt: 0, dl: '2020-03-01', mv: [{dl: '2020-03-02', vl: 30}, ...] }]
16
- attr_reader :ctlcm
17
-
18
- # (see CLI#criact)
19
- def ct_cria
20
- if existe_contrato?
21
- @bqnrs = 1
22
- puts 'CONTRATO JA EXISTE'
23
- else
24
- dml('insert into hernanilr.ab.re ' + sql_contrato_mv)
25
- puts "CONTRATO #{ctide} " + (bqnrs.zero? ? 'NAO EXISTE' : 'INSERIDO')
26
- end
27
- return unless existem_rendas?
28
-
29
- # processa rendas associadas ao contrato arrendamento
30
- cm_cria.vr_cria.re_insert
31
- end
32
-
33
- # (see CLI#apagact)
34
- def ct_apaga
35
- @ctlct = [{ ct: ctide }]
36
- lc_apaga
37
- end
38
-
39
- # apaga rendas da lista de contrato arrendamento
40
- #
41
- # @return [Big] acesso a base dados abank no bigquery
42
- def lr_apaga
43
- return self unless opcao[:t] && ctlct.count.positive?
44
-
45
- # para nao apagar contrato arrendamento - somente as rendas
46
- @opcao[:t] = false
47
-
48
- lc_apaga
49
- self
50
- end
51
-
52
- # apaga rendas da lista de contratos arrendamento
53
- def lc_apaga
54
- dml("delete from hernanilr.ab.re where ct in(#{str_lc})#{opcao[:t] ? '' : ' and cnt>0'}")
55
- puts "RENDAS #{str_lc('')} APAGADAS " + bqnrs.to_s
56
- end
57
-
58
- # @return [String] texto formatado que representa lista de contratos arrendamento
59
- def str_lc(sep = "'")
60
- ctlct.map { |c| sep + c[:ct] + sep }.join(',')
61
- end
62
-
63
- # optem lista dados contrato arrendamento (inclui lista movimentos novos)
64
- #
65
- # @return [Big] acesso a base dados abank no bigquery
66
- def cm_cria
67
- @ctlcm = []
68
- ctlct.each do |c|
69
- @ctide = c[:ct]
70
- sel(sql_last_re)
71
- @ctlcm << bqres[0].merge({ mv: sel(sql_novo_mv(bqres[0][:dl])) })
72
- end
73
- self
74
- end
75
-
76
- # @return [Boolean] existem rendas para processar sim/nao?
77
- def existem_rendas?
78
- @ctlct = [{ ct: ctide }]
79
- bqnrs.positive? && opcao[:t]
80
- end
81
-
82
- # @return [Boolean] contrato arrendamento ja existe sim/nao?
83
- def existe_contrato?
84
- sel("select ct from hernanilr.ab.re where ct='#{ctide}' and cnt=0").count.positive?
85
- end
86
-
87
- # @return [String] sql para obter ultima renda do contrato arrendamento
88
- def sql_last_re
89
- 'select ct,DATE_SUB(DATE_SUB(dl,INTERVAL dias DAY),INTERVAL IF(cnt=0,0,cnt-1) MONTH) as dc,ano,cnt,dl ' \
90
- "from hernanilr.ab.re where ct='#{ctide}' order by ano desc,cnt desc limit 1"
91
- end
92
-
93
- # @return [String] sql para obter movimentos novos (depois da ultima renda do contrato arrendamento)
94
- def sql_novo_mv(mdl)
95
- "select dl,vl from hernanilr.ab.mv where ct='#{ctide}' and dl>='#{(mdl + 1).strftime(DF)}' order by dl,dv"
96
- end
97
-
98
- # @return [String] sql para obter dados do inicio contrato arrendamento
99
- def sql_contrato_mv
100
- if opcao[:d].size.zero?
101
- 'select ct,EXTRACT(YEAR FROM DATE_TRUNC(dl,MONTH)) as ano,0 as cnt,DATE_TRUNC(dl,MONTH) as dl,0 dias ' \
102
- "from hernanilr.ab.mv where ct='#{ctide}' order by dl limit 1"
103
- else
104
- "select '#{ctide}' as ct,EXTRACT(YEAR FROM DATE '#{opcao[:d]}') as ano,0 as cnt,DATE '#{opcao[:d]}' as dl,0 dias"
105
- end
106
- end
107
- end
@@ -1,154 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'roo'
4
-
5
- # acesso a folha calculo & base dados abank no bigquery
6
- class Abank::Big::Folha < Abank::Big
7
- # @return [Roo::Excelx] folha calculo a processar
8
- attr_reader :folha
9
-
10
- # @return [Integer] numero conta associado a folha calculo
11
- # @example
12
- # mov*.xlsx --> 1 --> conta-corrente
13
- # movCard*.xlsx --> 2 --> conta-cartao
14
- attr_reader :conta
15
-
16
- # @return [Array] row folha calculo em processamento
17
- attr_reader :rowfc
18
-
19
- # acesso a folha calculo & base dados abank no bigquery
20
- #
21
- # @param [Hash] opc opcoes trabalho
22
- # @option opc [String] :f ('') folha calculo a processar
23
- # @option opc [Boolean] :s (false) apaga movimento similar? (mv)
24
- # @option opc [Boolean] :e (false) apaga movimento igual? (mv)
25
- # @option opc [Boolean] :i (false) insere movimento novo? (mv)
26
- # @option opc [String] :v ('') data valor movimentos (mv)
27
- # @option opc [String] :g ('') classificacao movimentos (mv)
28
- def initialize(opc = {})
29
- @opcao = super
30
- @folha = Roo::Spreadsheet.open(opc.fetch(:f))
31
- @conta = opc.fetch(:f).match?(/card/i) ? 2 : 1
32
- @opcao[:s] = opc.fetch(:s, false)
33
- @opcao[:e] = opc.fetch(:e, false)
34
- @opcao[:i] = opc.fetch(:i, false)
35
- @opcao[:v] = opc.fetch(:v, '')
36
- @opcao[:g] = opc.fetch(:g, '')
37
- end
38
-
39
- # carrega/mostra folha calculo
40
- def processa_xls
41
- n = 0
42
- folha.sheet(0).parse(header_search: ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor']) do |r|
43
- n += 1
44
- puts n == 1 ? "\n" + folha.info : processa_linha(r)
45
- end
46
- return unless opcao[:i]
47
-
48
- # processa movimentos & atualiza rendas
49
- mv_delete.mv_insert.re_work
50
- end
51
-
52
- # processa linha folha calculo
53
- #
54
- # @param [Hash] linha da folha calculo em processamento
55
- # @return [String] texto informativo formatado da linha em processamento
56
- def processa_linha(linha)
57
- vars_xls(linha)
58
- # pesquisa existencia linha folha calculo no bigquery
59
- # array.count = 0 ==> pode carregar esta linha
60
- # array.count = 1 ==> mais testes necessarios
61
- # array.count > 1 ==> nao pode carregar esta linha
62
- sel(sql_existe_mv, [{}, {}])
63
- if linha_naoexiste? then linha_base + values_mv
64
- elsif linha_existe? then linha_existe
65
- elsif linha_simila? then linha_similar
66
- else linha_multiplas
67
- end
68
- end
69
-
70
- # inicializa variavel para processar linha folha calculo
71
- #
72
- # @param (see processa_linha)
73
- def vars_xls(linha)
74
- @rowfc = linha.values
75
- @rowfc[2] = rowfc[2].strip
76
- @rowfc[3] = -1 * rowfc[3] if conta > 1
77
- end
78
-
79
- # @return [String] texto base formatado para display
80
- def linha_base
81
- "#{rowfc[0].strftime(DF)} #{format('%<v3>-34.34s %<v4>8.2f', v3: rowfc[2], v4: rowfc[3])}"
82
- end
83
-
84
- # @return [String] texto linha existente formatada para display
85
- def linha_existe
86
- add_kys if opcao[:e]
87
- linha_base + ' EXIS ' + format('%<v1>20d', v1: bqres.first[:ky])
88
- end
89
-
90
- # @return [String] texto linha similar formatada para display
91
- def linha_similar
92
- add_kys if opcao[:s]
93
- linha_base + ' SIMI ' + format('%<v1>-20.20s', v1: bqres.first[:ds].strip)
94
- end
95
-
96
- # @return [String] texto linha existencia multipla formatada para display
97
- def linha_multiplas
98
- linha_base + ' MULT(' + bqres.count.to_s + ')'
99
- end
100
-
101
- # obtem chaves movimento (keysin.mv) para apagar
102
- def add_kys
103
- bqres.each { |r| @mvkys += ",#{r[:ky]}" }
104
- end
105
-
106
- # @return [Boolean] linha folha calculo nao existe no bigquery?
107
- def linha_naoexiste?
108
- bqres.count.zero?
109
- end
110
-
111
- # @return [Boolean] linha folha calculo existe no bigquery?
112
- def linha_existe?
113
- bqres.count == 1 && bqres.first[:ds].strip == rowfc[2]
114
- end
115
-
116
- # @return [Boolean] linha folha calculo existe parecida no bigquery?
117
- def linha_simila?
118
- bqres.count == 1 && bqres.first[:ds].strip != rowfc[2]
119
- end
120
-
121
- # @return [String] sql para movimentos no bigquery
122
- def sql_existe_mv
123
- "select *,#{ky_mv} as ky from hernanilr.ab.mv " \
124
- "where nc=#{conta} and dl='#{rowfc[0].strftime(DF)}' and vl=#{rowfc[3]}"
125
- end
126
-
127
- # obtem movimento (values.mv) para inserir
128
- #
129
- # @return [String] ' NOVO'
130
- def values_mv
131
- @mvvls += ",('#{rowfc[0].strftime(DF)}','#{dvc.strftime(DF)}','#{rowfc[2]}',#{rowfc[3]}" + values_mv_extra
132
- ' NOVO'
133
- end
134
-
135
- # @return [String] campos extra do movimento (values.mv) para inserir
136
- def values_mv_extra
137
- ",#{conta},#{dvc.year},#{dvc.month},'#{tpc}',#{ctc})"
138
- end
139
-
140
- # @return [Date] data valor corrigida
141
- def dvc
142
- opcao[:v].size.zero? ? rowfc[1] : Date.parse(opcao[:v])
143
- end
144
-
145
- # @return [String] classificacao do movimento (null --> classificacao automatica)
146
- def ctc
147
- opcao[:g].size.zero? ? 'null' : ("'" + opcao[:g] + "'")
148
- end
149
-
150
- # @return [String] tipo movimento c[redito] ou d[ebito]
151
- def tpc
152
- rowfc[3].positive? ? 'c' : 'd'
153
- end
154
- end
@@ -1,121 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # @see Abank::Big
4
- class Abank::Big
5
- # @return [Integer] ano renda em tratamento
6
- attr_reader :reano
7
-
8
- # @return [Integer] mes renda em tratamento
9
- attr_reader :repos
10
-
11
- # @return [Float] valor renda mensal
12
- attr_reader :revre
13
-
14
- # @return [String] rendas a inserir (values.re)
15
- attr_reader :revls
16
-
17
- # @return [Integer] movimento em tratamento
18
- attr_reader :mvpos
19
-
20
- # @return [Date] data lancamento movimento em tratamento
21
- attr_reader :mvdlm
22
-
23
- # @return [Float] valor movimento em tratamento
24
- attr_reader :mvvlm
25
-
26
- # (see CLI#recriare)
27
- def re_atualiza
28
- # obtem contratos ativos
29
- @ctlct = sel('SELECT ct from hernanilr.ab.re group by 1')
30
-
31
- # [re]cria rendas [novas|todas]
32
- lr_apaga.cm_cria.vr_cria.re_insert
33
- end
34
-
35
- # cria rendas associadas a lista ids contratos arrendamento
36
- def re_work
37
- bqnrs.zero? || ctlct.count.positive? ? cm_cria.vr_cria.re_insert : re_atualiza
38
- end
39
-
40
- # obtem rendas a inserir (values.re)
41
- #
42
- # @return [Big] acesso a base dados abank no bigquery
43
- def vr_cria
44
- @revls = ctlcm.map { |c| rendas_novas(c) }.flatten(1).join(',')
45
- self
46
- end
47
-
48
- # insere rendas no bigquery
49
- def re_insert
50
- if revls.size.zero?
51
- puts 'NAO EXISTEM RENDAS NOVAS'
52
- else
53
- dml('insert hernanilr.ab.re VALUES' + revls)
54
- puts "RENDAS #{str_lc('')} CRIADAS " + bqnrs.to_s
55
- end
56
- end
57
-
58
- # @param [Hash] cmv dados contrato arrendamento (inclui lista movimentos novos)
59
- # @return [Array<String>] lista rendas novas dum contrato arrendamento (values.re)
60
- def rendas_novas(cmv)
61
- return [] unless cmv[:mv].count.positive?
62
-
63
- vars_re(cmv)
64
- r = []
65
- while mvvlm >= revre && mvpos < cmv[:mv].count
66
- r << nova_re(cmv)
67
- proximo_mv(cmv)
68
- end
69
- r
70
- end
71
-
72
- # inicializa variaveis para processar rendas do contrato arrendamento
73
- # @param (see rendas_novas)
74
- def vars_re(cmv)
75
- @reano = cmv[:ano]
76
- @repos = cmv[:cnt]
77
- @revre = Float(cmv[:ct][/\d+/]) / 100
78
- @mvpos = 0
79
- vars_re_mv(cmv)
80
- end
81
-
82
- # inicializa variaveis para processar movimentos associados ao contrato arrendamento
83
- # @param (see rendas_novas)
84
- def vars_re_mv(cmv)
85
- @mvdlm = cmv[:mv][mvpos][:dl]
86
- @mvvlm = cmv[:mv][mvpos][:vl]
87
- end
88
-
89
- # @param (see rendas_novas)
90
- # @return [String] renda formatada (values.re)
91
- def nova_re(cmv)
92
- # inicializa proxima renda
93
- if repos == 12
94
- @repos = 1
95
- @reano += 1
96
- else
97
- @repos += 1
98
- end
99
- "('#{cmv[:ct]}',#{reano},#{repos},'#{mvdlm.strftime(DF)}',#{dias(cmv)})"
100
- end
101
-
102
- # @param (see rendas_novas)
103
- # @return [Integer] dias atraso no pagamento da renda
104
- def dias(cmv)
105
- mvdlm.mjd - (Date.new(reano, repos, 1) >> (cmv[:dc].month - 1)).mjd
106
- end
107
-
108
- # inicializa variaveis para processar proximo movimento
109
- # @param (see rendas_novas)
110
- def proximo_mv(cmv)
111
- # valor renda paga retirado do valor do movimento
112
- @mvvlm -= revre
113
- return unless mvvlm < revre
114
-
115
- # avanca na lista de movimentos
116
- @mvpos += 1
117
- return unless mvpos < cmv[:mv].count
118
-
119
- vars_re_mv(cmv)
120
- end
121
- end