abank 0.6.8 → 0.7.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12bf681641a433a069f8657160ccb947e021b06ab94261f07a38da6001b4d970
4
- data.tar.gz: f807d26c094e3c6c2def749ef6c85e2aeeab848d07394b3f7c05c7f0e07b3757
3
+ metadata.gz: b52d3129983933c52306acea70fdfc2c1104038080b554456a4d8ac1e89406f5
4
+ data.tar.gz: 73ebaaa2457f7166cdb4f455534a6d8ff3554c78b7106bbb140efdfb145a96a6
5
5
  SHA512:
6
- metadata.gz: c643369008fc54e42f41ef77395c425d5dcf935ad3611bc83e2aba5120d604a9fc439d6aedeae7095426cb86a18d7e655270bdf74b9c4cc9d47be8ffa96b5e06
7
- data.tar.gz: 18bb5910ed4c3a40d57bb313eac62c5295d86d04c10f7b5fa1ba505af3e18e38100ec808302cd32d13467b032e637d42298b9bf48951b2c095df9cc16429ceff
6
+ metadata.gz: ecd45604e88d0cf0aed881117b8865f5cb73baf7bafda6b4f33f35000b1807f106d3ebcd2f949f86009e89adca82fc53147e42e56b20b02361871385338df6ab
7
+ data.tar.gz: 44903880f6ebb27932ba21eaa1baebcd6df49af6fa0bddfb2e45a36cc646b6b996bd8fb06c2cf598a42956a3f734b14f075b1b817df05cfeafbc22a3814e8cbc
data/.rubocop.yml CHANGED
@@ -18,7 +18,7 @@ Metrics/AbcSize:
18
18
 
19
19
  # Formatting Rules
20
20
  Layout/LineLength:
21
- Max: 160
21
+ Max: 185
22
22
  AllowHeredoc: true
23
23
  AllowURI: true
24
24
 
@@ -26,7 +26,7 @@ Layout/IndentationWidth:
26
26
  Width: 2
27
27
 
28
28
  Layout/SpaceInsideHashLiteralBraces:
29
- EnforcedStyle: space
29
+ EnforcedStyle: no_space
30
30
 
31
31
  Layout/SingleLineBlockChain:
32
32
  Enabled: false
@@ -65,3 +65,6 @@ Lint/AmbiguousOperatorPrecedence:
65
65
 
66
66
  Lint/ConstantResolution:
67
67
  Enabled: false
68
+
69
+ Lint/UnifiedInteger:
70
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- abank (0.6.8)
4
+ abank (0.7.0)
5
5
  google-cloud-bigquery
6
6
  roo
7
7
  thor
@@ -54,7 +54,7 @@ GEM
54
54
  logger
55
55
  faraday-net_http (3.4.0)
56
56
  net-http (>= 0.5.0)
57
- google-apis-bigquery_v2 (0.83.0)
57
+ google-apis-bigquery_v2 (0.84.0)
58
58
  google-apis-core (>= 0.15.0, < 2.a)
59
59
  google-apis-core (0.16.0)
60
60
  addressable (~> 2.5, >= 2.5.1)
@@ -64,7 +64,7 @@ GEM
64
64
  mutex_m
65
65
  representable (~> 3.0)
66
66
  retriable (>= 2.0, < 4.a)
67
- google-cloud-bigquery (1.51.1)
67
+ google-cloud-bigquery (1.52.0)
68
68
  bigdecimal (~> 3.0)
69
69
  concurrent-ruby (~> 1.0)
70
70
  google-apis-bigquery_v2 (~> 0.71)
@@ -72,12 +72,12 @@ GEM
72
72
  google-cloud-core (~> 1.6)
73
73
  googleauth (~> 1.9)
74
74
  mini_mime (~> 1.0)
75
- google-cloud-core (1.7.1)
75
+ google-cloud-core (1.8.0)
76
76
  google-cloud-env (>= 1.0, < 3.a)
77
77
  google-cloud-errors (~> 1.0)
78
78
  google-cloud-env (2.2.1)
79
79
  faraday (>= 1.0, < 3.a)
80
- google-cloud-errors (1.4.0)
80
+ google-cloud-errors (1.5.0)
81
81
  google-logging-utils (0.1.0)
82
82
  googleauth (1.13.1)
83
83
  faraday (>= 1.0, < 3.a)
@@ -87,9 +87,10 @@ GEM
87
87
  multi_json (~> 1.11)
88
88
  os (>= 0.9, < 2.0)
89
89
  signet (>= 0.16, < 2.a)
90
- httpclient (2.8.3)
90
+ httpclient (2.9.0)
91
+ mutex_m
91
92
  jaro_winkler (1.6.0)
92
- json (2.10.1)
93
+ json (2.10.2)
93
94
  jwt (2.10.1)
94
95
  base64
95
96
  kramdown (2.5.1)
@@ -105,10 +106,10 @@ GEM
105
106
  mutex_m (0.3.0)
106
107
  net-http (0.6.0)
107
108
  uri
108
- nokogiri (1.18.2)
109
+ nokogiri (1.18.3)
109
110
  mini_portile2 (~> 2.8.2)
110
111
  racc (~> 1.4)
111
- nokogiri (1.18.2-x86_64-linux-gnu)
112
+ nokogiri (1.18.3-x86_64-linux-gnu)
112
113
  racc (~> 1.4)
113
114
  observer (0.1.2)
114
115
  os (1.1.4)
@@ -141,7 +142,7 @@ GEM
141
142
  roo (2.10.1)
142
143
  nokogiri (~> 1)
143
144
  rubyzip (>= 1.3.0, < 3.0.0)
144
- rubocop (1.72.1)
145
+ rubocop (1.73.2)
145
146
  json (~> 2.3)
146
147
  language_server-protocol (~> 3.17.0.2)
147
148
  lint_roller (~> 1.1.0)
@@ -152,7 +153,7 @@ GEM
152
153
  rubocop-ast (>= 1.38.0, < 2.0)
153
154
  ruby-progressbar (~> 1.7)
154
155
  unicode-display_width (>= 2.4.0, < 4.0)
155
- rubocop-ast (1.38.0)
156
+ rubocop-ast (1.38.1)
156
157
  parser (>= 3.3.1.0)
157
158
  rubocop-rake (0.7.1)
158
159
  lint_roller (~> 1.1)
@@ -164,7 +165,7 @@ GEM
164
165
  faraday (>= 0.17.5, < 3.a)
165
166
  jwt (>= 1.5, < 3.0)
166
167
  multi_json (~> 1.10)
167
- solargraph (0.51.2)
168
+ solargraph (0.52.0)
168
169
  backport (~> 1.2)
169
170
  benchmark
170
171
  bundler (~> 2.0)
@@ -182,6 +183,7 @@ GEM
182
183
  thor (~> 1.0)
183
184
  tilt (~> 2.0)
184
185
  yard (~> 0.9, >= 0.9.24)
186
+ yard-solargraph (~> 0.1)
185
187
  thor (1.3.2)
186
188
  tilt (2.6.0)
187
189
  trailblazer-option (0.1.2)
@@ -189,8 +191,10 @@ GEM
189
191
  unicode-display_width (3.1.4)
190
192
  unicode-emoji (~> 4.0, >= 4.0.4)
191
193
  unicode-emoji (4.0.4)
192
- uri (1.0.2)
194
+ uri (1.0.3)
193
195
  yard (0.9.37)
196
+ yard-solargraph (0.1.0)
197
+ yard (~> 0.9)
194
198
  zeitwerk (2.6.18)
195
199
 
196
200
  PLATFORMS
data/lib/abank/big.rb CHANGED
@@ -3,29 +3,18 @@
3
3
  require('google/cloud/bigquery')
4
4
 
5
5
  module Abank
6
- BD = 'hernanilr.ab'
7
-
8
- # @see Big
9
6
  class Big
10
7
  DF = '%Y-%m-%d'
11
8
 
9
+ # @return [Google::Cloud::Bigquery::QueryJob] job bigquery
12
10
  # @return [Hash] opcoes trabalho
13
- attr_reader :opcao
14
-
15
11
  # @return [Google::Cloud::Bigquery::Data] resultado do Structured Query Language (SQL) no bigquery
16
- attr_reader :bqres
17
-
18
12
  # @return [Integer] numero linhas afetadas pelo Data Manipulation Language (DML) no bigquery
19
- attr_reader :bqnrs
20
-
21
13
  # @return [Integer] contrato arrendamento em tratamento
22
- attr_reader :ctpos
23
-
24
14
  # @return [Integer] movimento do contrato arrendamento em tratamento
25
- attr_reader :mvpos
15
+ attr_reader :job, :opcao, :bqres, :bqnrs, :ctpos, :mvpos
26
16
 
27
17
  # acesso a base dados abank no bigquery
28
- #
29
18
  # @param [Thor::CoreExt::HashWithIndifferentAccess] opcoes trabalho
30
19
  # @option opcoes [String] :k ('') movimentos a apagar (keysin.mv)
31
20
  # @option opcoes [String] :c ('') id contrato arrendamento (re)
@@ -34,138 +23,93 @@ module Abank
34
23
  # @return [Hash] opcoes trabalho
35
24
  def initialize(opcoes = {})
36
25
  @opcao = opcoes
37
- opcao
38
26
  end
39
27
 
40
- # @return [Google::Cloud::Bigquery] API bigquery
41
- def bqapi
42
- @bqapi ||= Google::Cloud::Bigquery.new
43
- end
28
+ # insere & classifica movimentos no bigquery
29
+ # @return [Big] acesso a base dados abank no bigquery
30
+ def mv_insert
31
+ return self if mvvls.empty?
44
32
 
45
- # @return [String] movimentos a apagar (keysin.mv)
46
- def mvkys
47
- opcao[:k].to_s.scan(/[-+]?\d+/).join(',')
33
+ dml("insert #{BD}.mv VALUES#{mvvls.join(',')}")
34
+ puts("MOVIMENTOS INSERIDOS #{bqnrs}")
35
+ mv_classifica if bqnrs.positive?
36
+ self
48
37
  end
49
38
 
50
39
  # apaga movimentos & suas rendas associadas no bigquery
51
- #
52
40
  # @return [Big] acesso a base dados abank no bigquery
53
41
  def mv_delete
54
42
  @ctlct = []
55
- unless mvkys.empty?
56
- # obtem lista contratos arrendamento associados aos movimentos a apagar
57
- @ctlct = sql("select distinct ct from #{BD}.gmr where ky in(#{mvkys})")
43
+ return self if mvkys.empty?
58
44
 
59
- re_apaga.mv_delete_dml
60
- end
45
+ # obtem lista contratos arrendamento associados aos movimentos a apagar
46
+ @ctlct = sql("select distinct ct from #{BD}.gmr where ky IN UNNEST(@kys)", kys: mvkys)
47
+ re_apaga
48
+ mv_delete_dml
61
49
  self
62
50
  end
63
51
 
64
- # apaga movimentos no bigquery
65
- def mv_delete_dml
66
- dml("delete from #{BD}.mv where #{BD}.ky(dl,dv,ds,vl,nc,ex) in(#{mvkys})")
67
- puts("MOVIMENTOS APAGADOS #{bqnrs}")
68
- end
69
-
70
- # (see CLI#tag)
52
+ # classifica movimentos no bigquery
53
+ # @return [Big] acesso a base dados abank no bigquery
71
54
  def mv_classifica
72
- @ctlct = []
55
+ @ctlct = sql("select * from #{BD}.gnr")
73
56
  stp("call #{BD}.uct()")
74
57
  puts("MOVIMENTOS CLASSIFICADOS #{bqnrs}")
75
- @ctlct = sql("select ct from #{BD}.ca") if bqnrs.positive?
76
58
  self
77
59
  end
78
60
 
79
- # (see CLI#criact)
61
+ # cria contrato arrendamento no bigquery
62
+ # @return [Big] acesso a base dados abank no bigquery
80
63
  def ct_cria
81
- unless ct_existe?
82
- dml("insert into #{BD}.re #{sql_contrato_mv}")
64
+ if sql("SELECT ct FROM #{BD}.ca WHERE ct=@ct", ct: opcao[:c]).empty?
65
+ if valid_dc?
66
+ dml("insert #{BD}.re select @ct,EXTRACT(YEAR FROM DATE(@dc)),0,DATE(@dc),0", ct: opcao[:c], dc: opcao[:d])
67
+ else
68
+ dml("insert #{BD}.re select ct,EXTRACT(YEAR FROM DATE_TRUNC(dl,MONTH)),0,DATE_TRUNC(dl,MONTH),0 from #{BD}.mv where ct=@ct order by dl limit 1", ct: opcao[:c])
69
+ end
83
70
  puts("CONTRATO #{opcao[:c]} #{bqnrs.zero? ? 'NAO ' : ''}INSERIDO")
71
+ else
72
+ @bqnrs = 1
73
+ puts('CONTRATO JA EXISTE')
84
74
  end
85
- # processar rendas sim/nao?
75
+ @ctlct = [{ct: opcao[:c]}]
86
76
  return unless bqnrs.positive? && opcao[:t]
87
77
 
88
78
  # processa rendas associadas ao contrato arrendamento
89
79
  ct_dados.re_insert
90
80
  end
91
81
 
92
- # @return [Boolean] contrato arrendamento ja existe sim/nao?
93
- def ct_existe?
94
- @ctlct = [{ ct: opcao[:c] }]
95
- vaz = sql("select ct from #{BD}.ca where ct in(#{str_lc})").empty?
96
- unless vaz
97
- @bqnrs = 1
98
- puts('CONTRATO JA EXISTE')
99
- end
100
- !vaz
101
- end
102
-
103
82
  # (see CLI#apagact)
104
83
  def ct_apaga
105
- @ctlct = [{ ct: opcao[:c] }]
84
+ @ctlct = [{ct: opcao[:c]}]
106
85
  re_delete_dml
107
86
  end
108
87
 
109
88
  # optem lista dados contrato arrendamento (inclui lista movimentos novos)
110
- #
111
89
  # @return [Big] acesso a base dados abank no bigquery
112
90
  def ct_dados
113
91
  ctlct.map! do |ctr|
114
92
  opcao[:c] = ctr[:ct]
115
- lre = sql(sql_last_re).first
116
- lre[:dl] += -1 if lre[:cnt].zero?
117
- ctr.merge(lre, mv: sql(sql_novo_mv(lre[:dl])))
93
+ lre = sql("select * from #{BD}.glr where ct=@ct order by ano desc,cnt desc limit 1", ct: opcao[:c]).first
94
+ lre[:dl] -= 1 if lre[:cnt].zero?
95
+ ctr.merge(lre, mv: sql("select * from #{BD}.gmn where ct=@ct and dl>=@ud order by 1,2", ct: opcao[:c], ud: lre[:dl] + 1))
118
96
  end
119
97
  self
120
98
  end
121
99
 
122
- # @param [Array] are lista rendas novas atual
123
- # @return [Array<String>] lista rendas novas duma lista contratos arrendamento
124
- def ct_rendas(lre = [])
125
- while ctpos < ctlct.size
126
- @mvpos = 0
127
- lre += re_rendas
128
- @ctpos += 1
129
- end
130
- lre
131
- end
132
-
133
- # @example sem dados movimentos
134
- # [{ ct: 'r03000' }, ...]
135
- # @example com dados movimentos
136
- # [{ct: 'r03000', dc: '2020-03-01', ano: 2020, cnt: 0, dl: '2020-03-01', mv: [{dl: '2020-03-02', vl: 30}, ...] }]
137
- # @return [Array<Hash>] lista dados contrato arrendamento (inclui lista movimentos novos)
138
- def ctlct
139
- @ctlct ||= []
140
- end
141
-
142
- # @return [String] texto formatado que representa lista de contratos arrendamento
143
- def str_lc(sep = "'")
144
- ctlct.map { |cid| sep + cid[:ct] + sep }.join(',')
145
- end
146
-
147
- # @return [String] sql para obter ultima renda do contrato arrendamento
148
- def sql_last_re
149
- "select * from #{BD}.glr where ct='#{opcao[:c]}' order by ano desc,cnt desc limit 1"
150
- end
151
-
152
- # @return [String] sql para obter movimentos novos (depois da ultima renda do contrato arrendamento)
153
- def sql_novo_mv(mdl)
154
- "select * from #{BD}.gmn where ct='#{opcao[:c]}' and dl>='#{(mdl + 1).strftime(DF)}' order by 1,2"
155
- end
156
-
157
- # @return [String] sql para obter dados do inicio contrato arrendamento
158
- def sql_contrato_mv
159
- cti = opcao[:c]
160
- dat = opcao[:d]
161
- if dat.empty?
162
- 'select ct,EXTRACT(YEAR FROM DATE_TRUNC(dl,MONTH)) ano,0 cnt,DATE_TRUNC(dl,MONTH) dl,0 dias ' \
163
- "from #{BD}.mv where ct='#{cti}' order by dl limit 1"
100
+ # insere rendas associadas a lista contratos arrendamento no bigquery
101
+ def re_insert
102
+ @ctpos = 0
103
+ vls = ct_rendas.join(',')
104
+ if vls.empty?
105
+ puts('NAO EXISTEM RENDAS NOVAS')
164
106
  else
165
- "select '#{cti}' ct,EXTRACT(YEAR FROM DATE '#{dat}') ano,0 cnt,DATE '#{dat}' dl,0 dias"
107
+ dml("insert #{BD}.re VALUES#{vls}")
108
+ puts("RENDAS #{cta.join(',')} CRIADAS #{bqnrs}")
166
109
  end
167
110
  end
168
111
 
112
+ # @return [String] sql inicio contrato arrendamento sem movimentos
169
113
  # (see CLI#recriare)
170
114
  def re_atualiza
171
115
  # [re]cria rendas novas/todas dos contratos ativos
@@ -173,31 +117,67 @@ module Abank
173
117
  re_apaga.ct_dados.re_insert
174
118
  end
175
119
 
176
- # insere rendas associadas a lista contratos arrendamento no bigquery
177
- def re_insert
178
- @ctpos = 0
179
- vls = ct_rendas.join(',')
180
- if vls.empty?
181
- puts('NAO EXISTEM RENDAS NOVAS')
182
- else
183
- dml("insert #{BD}.re VALUES#{vls}")
184
- puts("RENDAS #{str_lc('')} CRIADAS #{bqnrs}")
185
- end
120
+ private
121
+
122
+ # @return [Google::Cloud::Bigquery] API bigquery
123
+ def bqapi
124
+ @bqapi ||= Google::Cloud::Bigquery.new
125
+ end
126
+
127
+ # @return [String] movimentos a apagar (keysin.mv)
128
+ def mvkys
129
+ @mvkys ||= opcao[:k].to_s.scan(/[-+]?\d+/).map(&:to_i)
130
+ end
131
+
132
+ # @return [Boolean] data contrato arrendamento valida?
133
+ def valid_dc?
134
+ s = opcao[:d].to_s.strip
135
+ return false unless s.length.positive?
136
+
137
+ d = Date.parse(s)
138
+ opcao[:d] = d.iso8601
139
+ Date.valid_date?(d.year, d.month, d.day)
140
+ rescue StandardError
141
+ false
186
142
  end
187
143
 
188
144
  # apaga rendas da lista de contrato arrendamento
189
- #
190
145
  # @return [Big] acesso a base dados abank no bigquery
191
146
  def re_apaga
192
147
  return self if ctlct.empty?
193
148
 
194
149
  # para nao apagar contrato arrendamento - somente as rendas
195
150
  opcao[:t] = false
196
-
197
151
  re_delete_dml
198
152
  self
199
153
  end
200
154
 
155
+ # @example sem dados movimentos
156
+ # [{ ct: 'r03000' }, ...]
157
+ # @example com dados movimentos
158
+ # [{ct: 'r03000', dc: '2020-03-01', ano: 2020, cnt: 0, dl: '2020-03-01', mv: [{dl: '2020-03-02', vl: 30}, ...] }]
159
+ # @return [Array<Hash>] lista dados contrato arrendamento (inclui lista movimentos novos)
160
+ def ctlct
161
+ @ctlct ||= []
162
+ end
163
+
164
+ # @return [Array<String>] lista de contratos arrendamento
165
+ def cta
166
+ ctlct.map { |c| c[:ct] }
167
+ end
168
+
169
+ # @param [Array] are lista rendas novas atual
170
+ # @return [Array<String>] lista rendas novas duma lista contratos arrendamento
171
+ def ct_rendas
172
+ lre = []
173
+ ctlct.each do
174
+ @mvpos = 0
175
+ lre += re_rendas
176
+ @ctpos += 1
177
+ end
178
+ lre
179
+ end
180
+
201
181
  # @return [Array<String>] lista rendas novas dum contrato arrendamento
202
182
  def re_rendas
203
183
  lre = []
@@ -211,21 +191,27 @@ module Abank
211
191
  # @return [String] renda formatada (values.re)
212
192
  def re_nova_renda
213
193
  re_proximos_dados
214
- "('#{re_atual[:ct]}',#{ano},#{cnt},'#{re_atual_mv[:dl].strftime(DF)}',#{dias})"
194
+ "('#{re_atual[:ct]}',#{ano},#{cnt},'#{re_atual_mv[:dl].iso8601}',#{dias})"
215
195
  end
216
196
 
217
197
  # @return [Hash] dados contrato arrendamento (inclui lista movimentos novos)
218
198
  def re_proximos_dados
219
199
  # valor renda paga retirada do movimento
220
200
  re_atual_mv[:vl] -= re_atual[:vr]
221
- dre = cnt.zero? ? Date.new(re_atual[:dc].year, re_atual[:dc].month, 1) : Date.new(ano, cnt, 1) >> 1
201
+ dre = cnt.zero? ? Date.new(re_atual[:dc].year, re_atual[:dc].month, 1) : Date.new(ano, cnt, 1).next_month
222
202
  re_atual.merge!(ano: dre.year, cnt: dre.month)
223
203
  end
224
204
 
205
+ # apaga movimentos no bigquery
206
+ def mv_delete_dml
207
+ dml("delete from #{BD}.mv where #{BD}.ky(dl,dv,ds,vl,nc,ex) IN UNNEST(@kys)", kys: mvkys)
208
+ puts("MOVIMENTOS APAGADOS #{bqnrs}")
209
+ end
210
+
225
211
  # apaga rendas da lista de contratos arrendamento
226
212
  def re_delete_dml
227
- dml("delete from #{BD}.re where ct in(#{str_lc})#{opcao[:t] ? '' : ' and cnt>0'}")
228
- puts("RENDAS #{str_lc('')} APAGADAS #{bqnrs}")
213
+ dml("delete from #{BD}.re where ct IN UNNEST(@cts)#{' and cnt>0' unless opcao[:t]}", cts: cta)
214
+ puts("RENDAS #{cta.join(',')} APAGADAS #{bqnrs}")
229
215
  end
230
216
 
231
217
  # @return [Boolean] movimento com saldo suficiente?
@@ -258,48 +244,41 @@ module Abank
258
244
  re_atual_mv[:dl].mjd - Date.new(ano, cnt, 1).mjd
259
245
  end
260
246
 
247
+ # cria job bigquery & verifica execucao
261
248
  # @param [String] cmd comando a executar
262
- # @return [Google::Cloud::Bigquery::QueryJob] tarefa SQL/DML no bigquery
263
- def job(cmd)
264
- bqjob = bqapi.query_job(cmd)
265
- bqjob.wait_until_done!
266
- puts(bqjob.error['message']) if bqjob.failed?
267
- bqjob
249
+ # @param [Hash] prm parâmetros para a query
250
+ # @return [Boolean] job ok?
251
+ def job?(cmd, prm = {})
252
+ @job = bqapi.query_job(cmd, params: prm, priority: 'BATCH')
253
+ job.wait_until_done!
254
+ return true unless job.failed?
255
+
256
+ puts("BigQuery: #{job.error['message']}\n#{cmd}")
257
+ false
268
258
  end
269
259
 
270
260
  # executa Structured Query Language (SQL) no bigquery
271
- #
272
- # @param (see job)
273
- # @param [Array] erro resultado quando falha execucao
261
+ # @param [String] cmd comando SQL a executar
262
+ # @param [Hash] prm parâmetros para a query
274
263
  # @return [Google::Cloud::Bigquery::Data] resultado do SQL
275
- def sql(cmd, erro = [])
276
- # se job.failed? executa job(cmd).data => StandardError
277
- @bqres = job(cmd).data
278
- rescue StandardError
279
- @bqres = erro
264
+ def sql(cmd, prm = {})
265
+ @bqres = job?(cmd, prm) ? job.data : []
280
266
  end
281
267
 
282
268
  # executa Data Manipulation Language (DML) no bigquery
283
- #
284
- # @param (see job)
285
- # @return [Integer] numero rows afetadas pelo DML
286
- def dml(cmd)
287
- # se job.failed? executa Integer(nil) => StandardError
288
- @bqnrs = Integer(job(cmd).num_dml_affected_rows)
289
- rescue StandardError
290
- @bqnrs = 0
269
+ # @param [String] cmd comando DML a executar
270
+ # @param [Hash] prm parâmetros para a query
271
+ # @return [Integer] numero linhas afetadas
272
+ def dml(cmd, prm = {})
273
+ @bqnrs = job?(cmd, prm) ? job.num_dml_affected_rows.to_i : 0
291
274
  end
292
275
 
293
- # executa Stored Procedure (STP) with DML operations no bigquery
294
- #
295
- # @param (see job)
276
+ # executa Stored Procedure (STP) no bigquery
277
+ # @param [String] cmd comando STP a executar
296
278
  # @return [Integer] numero rows afetadas pelo STP
297
279
  def stp(cmd)
298
280
  # last command STP=SELECT @@row_count AS rows_affected;
299
- # se job.failed? executa Integer(nil) => StandardError
300
- @bqnrs = Integer(job(cmd).data.first[:rows_affected])
301
- rescue StandardError
302
- @bqnrs = 0
281
+ @bqnrs = job?(cmd) ? job.data.first[:rows_affected].to_i : 0
303
282
  end
304
283
  end
305
284
  end
data/lib/abank/folha.rb CHANGED
@@ -3,16 +3,10 @@
3
3
  require('roo')
4
4
 
5
5
  module Abank
6
- # @see Folha
7
6
  class Folha < Big
8
- # @return [Roo::Excelx] folha calculo a processar
9
- # attr_reader :folha
10
-
11
7
  # @return [Array] row folha calculo em processamento
12
- attr_reader :rowfc
13
-
14
8
  # @return [String] movimentos a inserir (values.mv)
15
- attr_reader :mvvls
9
+ attr_reader :rowfc, :mvvls
16
10
 
17
11
  # acesso a folha calculo & base dados abank no bigquery
18
12
  #
@@ -24,147 +18,109 @@ module Abank
24
18
  # @option opcoes [String] :v ('') data valor movimentos (mv)
25
19
  # @option opcoes [String] :g ('') classificacao movimentos (mv)
26
20
  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
- rescue StandardError => e
42
- raise("Erro ao abrir a folha de cálculo: #{e.message}")
21
+ super
22
+ @opcao = opcao.merge(s: opcoes.fetch(:s, false), e: opcoes.fetch(:e, false), i: opcoes.fetch(:i, false), v: opcoes.fetch(:v, ''), g: opcoes.fetch(:g, ''), k: +'', f: opcoes[:f])
23
+ @mvvls = []
43
24
  end
44
25
 
45
26
  # carrega/mostra folha calculo
46
27
  def processa_xls
47
28
  puts("\n#{folha.info}")
48
- folha.sheet(0).parse(header_search: ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor']) do |row|
49
- puts(processa_linha) if ok?(row)
29
+ mvs = sql("select * from #{BD}.gmv where nc=@nc", nc: conta).group_by { |m| [m[:dl], m[:vl].to_f] }
30
+ folha.sheet(0).parse(header_search: ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor']) do |r|
31
+ next unless valid?(r.values)
32
+
33
+ @bqres = mvs[[rowfc[0], rowfc[3]]] || []
34
+ if bqres.empty?
35
+ puts(lnexi)
36
+ elsif bqres.one? && bqres.first[:ds].strip == rowfc[2]
37
+ puts(lexis)
38
+ elsif bqres.one?
39
+ puts(lsiml)
40
+ else
41
+ puts(lmult)
42
+ end
50
43
  end
51
44
  return unless opcao[:i]
52
45
 
53
- # processa movimentos & atualiza rendas
54
46
  mv_delete.mv_insert.ct_dados.re_insert
55
47
  end
56
48
 
57
- # @return [Integer] numero conta associado a folha calculo
49
+ private
50
+
51
+ # @return [Roo::Excelx] folha calculo a processar
52
+ def folha
53
+ @folha ||= Roo::Spreadsheet.open(opcao[:f])
54
+ rescue StandardError
55
+ raise("Erro ao abrir a folha de cálculo: #{opcao[:f]}")
56
+ end
57
+
58
58
  # @example
59
59
  # mov*.xlsx --> 1 --> conta-corrente
60
60
  # movCard*.xlsx --> 2 --> conta-cartao
61
+ # @return [Integer] numero conta associado a folha calculo
61
62
  def conta
62
- opcao[:f].match?(/card/i) ? 2 : 1
63
+ @conta ||= opcao[:f].match?(/card/i) ? 2 : 1
63
64
  end
64
65
 
65
- # @param [Hash] linha da folha calculo em processamento
66
- # @return [Boolean] linha com valores para processar?
67
- def ok?(linha)
68
- @rowfc = linha.values
69
- return false if rowfc.first.is_a?(String)
66
+ # @param [Array] row folha calculo em processamento
67
+ # @return [Boolean] linha com valores correctos para processar?
68
+ def valid?(row)
69
+ return false unless row[0].is_a?(Date) && row[1].is_a?(Date)
70
70
 
71
- rowfc[2] = rowfc[2].strip
72
- rowfc[3] = rowfc[3] * -1 if conta > 1
71
+ row[2] = row[2].to_s.strip.gsub("'", '').gsub('\\', '') # Descrição
72
+ row[3] = row[3].to_f * (conta == 1 ? 1 : -1) # Valor
73
+ @rowfc = row
73
74
  true
75
+ rescue StandardError => e
76
+ puts("Error processing row values: #{e.message}\nRow: #{row.inspect}")
77
+ false
74
78
  end
75
79
 
76
- # @return [String] texto informativo formatado da linha processada
77
- def processa_linha
78
- # pesquisa existencia linha folha calculo no bigquery
79
- # array.count = 0 ==> pode carregar esta linha
80
- # array.count = 1 ==> mais testes necessarios
81
- # array.count > 1 ==> nao pode carregar esta linha
82
- sql(sql_existe_mv, [{}, {}])
83
-
84
- return linha_base + values_mv if linha_naoexiste?
85
- return linha_existe if linha_existe?
86
- return linha_similar if linha_simila?
87
-
88
- linha_multiplas
89
- end
90
-
91
- # insere & classifica movimentos no bigquery
92
- #
93
- # @return [Big] acesso a base dados abank no bigquery
94
- def mv_insert
95
- unless mvvls.empty?
96
- @mvvls = mvvls[1..] if mvvls.first == ','
97
- dml("insert #{BD}.mv VALUES#{mvvls}")
98
- puts("MOVIMENTOS INSERIDOS #{bqnrs}")
99
- mv_classifica if bqnrs.positive?
100
- end
101
- self
102
- end
103
-
104
- # @return [Boolean] linha folha calculo nao existe no bigquery?
105
- def linha_naoexiste?
106
- bqres.empty?
107
- end
108
-
109
- # @return [Boolean] linha folha calculo existe no bigquery?
110
- def linha_existe?
111
- bqres.count == 1 && bqres.first[:ds].strip == rowfc[2]
112
- end
113
-
114
- # @return [Boolean] linha folha calculo existe parecida no bigquery?
115
- def linha_simila?
116
- bqres.count == 1 && bqres.first[:ds].strip != rowfc[2]
80
+ # @return [String] texto base formatado para display
81
+ def lbase
82
+ format('%<dt>10s %<v3>-34.34s %<v4>8.2f', dt: rowfc[0].strftime(DF), v3: rowfc[2], v4: rowfc[3])
117
83
  end
118
84
 
119
- # @return [String] texto base formatado para display
120
- def linha_base
121
- "#{rowfc.first.strftime(DF)} #{format('%<v3>-34.34s %<v4>8.2f', v3: rowfc[2], v4: rowfc[3])}"
85
+ # @return [String] novo texto base formatado para display
86
+ def lnexi
87
+ @mvvls << "('#{rowfc[0].iso8601}','#{dvc.iso8601}','#{rowfc[2]}',#{rowfc[3]},#{conta},#{dvc.year},#{dvc.month},'#{tpc}',#{ctc},null,null)"
88
+ "#{lbase} NOVO"
122
89
  end
123
90
 
124
91
  # @return [String] texto linha existente formatada para display
125
- def linha_existe
92
+ def lexis
126
93
  add_kys if opcao[:e]
127
- "#{linha_base} EXIS #{format('%<v1>20d', v1: bqres.first[:ky])}"
94
+ "#{lbase} EXIS #{format('%<v1>20d', v1: bqres.first[:ky])}"
128
95
  end
129
96
 
130
97
  # @return [String] texto linha similar formatada para display
131
- def linha_similar
98
+ def lsiml
132
99
  add_kys if opcao[:s]
133
- "#{linha_base} SIMI #{format('%<v1>20d %<v2>-34.34s', v1: bqres.first[:ky], v2: bqres.first[:ds].strip)}"
100
+ "#{lbase} SIMI #{format('%<v1>20d %<v2>-34.34s', v1: bqres.first[:ky], v2: bqres.first[:ds].strip)}"
134
101
  end
135
102
 
136
103
  # @return [String] texto linha existencia multipla formatada para display
137
- def linha_multiplas
138
- "#{linha_base} ML#{format('%<v0>2d %<v1>20d', v0: bqres.count, v1: bqres.first[:ky])}"
104
+ def lmult
105
+ "#{lbase} ML#{format('%<v0>2d %<v1>20d', v0: bqres.count, v1: bqres.first[:ky])}"
139
106
  end
140
107
 
141
- # obtem chaves movimento (keysin.mv) para apagar
142
108
  def add_kys
143
- bqres.each { |row| opcao[:k] += ",#{row[:ky]}" }
144
- end
145
-
146
- # @return [String] sql para movimentos no bigquery
147
- def sql_existe_mv
148
- "select * from #{BD}.gmv where nc=#{conta} and dl='#{rowfc.first.strftime(DF)}' and vl=#{rowfc[3]}"
149
- end
150
-
151
- # obtem movimento (values.mv) para inserir
152
- #
153
- # @return [String] ' NOVO'
154
- def values_mv
155
- @mvvls += ",('#{rowfc.first.strftime(DF)}','#{dvc.strftime(DF)}','#{rowfc[2]}',#{rowfc[3]},#{conta},#{dvc.year},#{dvc.month},'#{tpc}',#{ctc},null,null)"
156
- ' NOVO'
109
+ opcao[:k] << bqres.each_with_object(+'') { |r, s| s << ",#{r[:ky]}" }
157
110
  end
158
111
 
159
112
  # @return [Date] data valor corrigida
160
113
  def dvc
161
- dvl = opcao[:v]
114
+ dvl = opcao[:v].to_s
162
115
  dvl.empty? ? rowfc[1] : Date.parse(dvl)
116
+ rescue ArgumentError
117
+ puts("Invalid date format in #{opcao[:v].inspect}")
118
+ rowfc[1]
163
119
  end
164
120
 
165
121
  # @return [String] classificacao do movimento (null --> classificacao automatica)
166
122
  def ctc
167
- cmv = opcao[:g]
123
+ cmv = opcao[:g].to_s
168
124
  cmv.empty? ? 'null' : "'#{cmv}'"
169
125
  end
170
126
 
data/lib/abank/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Abank
4
- VERSION = "0.6.8"
4
+ VERSION = '0.7.0'
5
5
  end
data/lib/abank.rb CHANGED
@@ -8,6 +8,7 @@ require('abank/version')
8
8
  # @author Hernani Rodrigues Vaz
9
9
  module Abank
10
10
  DR = "/home/#{`whoami`.chomp}/Downloads".freeze
11
+ BD = 'hernanilr.ab'
11
12
 
12
13
  # CLI para carregar folhas calculo comuns no bigquery
13
14
  class CLI < Thor
@@ -43,13 +44,11 @@ module Abank
43
44
 
44
45
  desc 'recriact', 'atualiza rendas de contrato arrendamento'
45
46
  option :c, banner: 'CONTRATO', required: true, desc: 'Identificador contrato arrendamento'
46
- option :d, banner: 'DATA', default: '', desc: 'data contrato arrendamento'
47
- option :t, type: :boolean, default: false, desc: 'apaga todas as rendas?'
48
47
  # atualiza rendas de contrato arrendamento
49
48
  def recriact
50
49
  opc = options[:c]
51
- Big.new(c: opc, t: options[:t]).ct_apaga
52
- Big.new(c: opc, t: true, d: options[:d]).ct_cria
50
+ Big.new(c: opc, t: false).ct_apaga
51
+ Big.new(c: opc, t: true).ct_cria
53
52
  end
54
53
 
55
54
  desc 'recriare', 'atualiza rendas dos contratos ativos'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abank
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.8
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hernâni Rodrigues Vaz
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-02-16 00:00:00.000000000 Z
10
+ date: 2025-03-12 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bundler