abank 0.2.9 → 0.3.4

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