lib/abank/folha.rb in abank-0.2.4 vs lib/abank/folha.rb in abank-0.2.5

- old
+ new

@@ -1,159 +1,154 @@ # frozen_string_literal: true require 'roo' -# class Big::Contrato +# acesso a folha calculo & base dados abank no bigquery class Abank::Big::Folha < Abank::Big - HT = ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor'].freeze - RF = '%<v3>-34.34s %<v4>8.2f' - EN = ' %<v1>20d' - ES = ' %<v1>-20.20s' - # @return [Roo::Excelx] folha calculo a processar attr_reader :folha - # @return [Integer] numero conta + + # @return [Integer] numero conta associado a folha calculo + # @example + # mov*.xlsx --> 1 --> conta-corrente + # movCard*.xlsx --> 2 --> conta-cartao attr_reader :conta # @return [Array] row folha calculo em processamento - attr_reader :row + attr_reader :rowfc - def initialize(xls, ops = { s: false, e: false, m: false, i: false, - v: '', g: '' }) - p ['Folha', xls, ops] - @folha = Roo::Spreadsheet.open(xls) if xls.size.positive? - @conta = xls.match?(/card/i) ? 2 : 1 - super(ops) + # acesso a folha calculo & base dados abank no bigquery + # + # @param [Hash] opc opcoes trabalho + # @option opc [String] :f ('') folha calculo a processar + # @option opc [Boolean] :s (false) apaga movimento similar? (mv) + # @option opc [Boolean] :e (false) apaga movimento igual? (mv) + # @option opc [Boolean] :i (false) insere movimento novo? (mv) + # @option opc [String] :v ('') data valor movimentos (mv) + # @option opc [String] :g ('') classificacao movimentos (mv) + def initialize(opc = {}) + @opcao = super + @folha = Roo::Spreadsheet.open(opc.fetch(:f)) + @conta = opc.fetch(:f).match?(/card/i) ? 2 : 1 + @opcao[:s] = opc.fetch(:s, false) + @opcao[:e] = opc.fetch(:e, false) + @opcao[:i] = opc.fetch(:i, false) + @opcao[:v] = opc.fetch(:v, '') + @opcao[:g] = opc.fetch(:g, '') end - # processa linhas folha calculo & classifica bigquery - def processa_folha + # carrega/mostra folha calculo + def processa_xls n = 0 - folha.sheet(0).parse(header_search: HT) do |r| + folha.sheet(0).parse(header_search: ['Data Lanc.', 'Data Valor', 'Descrição', 'Valor']) do |r| n += 1 - puts n == 1 ? "\n" + folha.info : processa_row(r) + puts n == 1 ? "\n" + folha.info : processa_linha(r) end - mv_classifica + return unless opcao[:i] + + # processa movimentos & atualiza rendas + mv_delete.mv_insert.re_work end - # processa linha folha calculo para arquivo + # processa linha folha calculo # - # @param (see corrige_hash) - # @return [String] texto informativo do processamento - def processa_row(has) - corrige_hash(has) + # @param [Hash] linha da folha calculo em processamento + # @return [String] texto informativo formatado da linha em processamento + def processa_linha(linha) + vars_xls(linha) # pesquisa existencia linha folha calculo no bigquery # array.count = 0 ==> pode carregar esta linha # array.count = 1 ==> mais testes necessarios # array.count > 1 ==> nao pode carregar esta linha - sel(sql_sel_mv, [{}, {}]) - if row_naoexiste? then row_str + (insert_mv == 1 ? ' NOVA' : ' ERRO') - elsif row_simila? then row_similar - elsif row_existe? then row_existente - else row_multiplas + sel(sql_existe_mv, [{}, {}]) + if linha_naoexiste? then linha_base + values_mv + elsif linha_existe? then linha_existe + elsif linha_simila? then linha_similar + else linha_multiplas end end - # corrige linha folha calculo para processamento + # inicializa variavel para processar linha folha calculo # - # @param [Hash] has da linha em processamento - def corrige_hash(has) - @row = has.values - @row[2] = row[2].strip - @row[3] = -1 * row[3] if conta > 1 + # @param (see processa_linha) + def vars_xls(linha) + @rowfc = linha.values + @rowfc[2] = rowfc[2].strip + @rowfc[3] = -1 * rowfc[3] if conta > 1 end - # @return [String] linha folha calculo formatada - def row_str - "#{row[0].strftime(DF)} #{format(RF, v3: row[2], v4: row[3])}" + # @return [String] texto base formatado para display + def linha_base + "#{rowfc[0].strftime(DF)} #{format('%<v3>-34.34s %<v4>8.2f', v3: rowfc[2], v4: rowfc[3])}" end - # @return [String] linha folha calculo similar - def row_similar - d = opl[:s] ? delete_mv : 0 - row_str + ' SIMI' + str_apagadas(d) + str_extra_s(resultados.first[:ds]) + # @return [String] texto linha existente formatada para display + def linha_existe + add_kys if opcao[:e] + linha_base + ' EXIS ' + format('%<v1>20d', v1: bqres.first[:ky]) end - # @return [String] linha folha calculo existente - def row_existente - d = opl[:e] ? delete_mv : 0 - row_str + ' EXIS' + str_apagadas(d) + str_extra_n(resultados.first[:ky]) + # @return [String] texto linha similar formatada para display + def linha_similar + add_kys if opcao[:s] + linha_base + ' SIMI ' + format('%<v1>-20.20s', v1: bqres.first[:ds].strip) end - def str_extra_s(ext) - format(ES, v1: ext.strip) + # @return [String] texto linha existencia multipla formatada para display + def linha_multiplas + linha_base + ' MULT(' + bqres.count.to_s + ')' end - def str_extra_n(ext) - format(EN, v1: ext) + # obtem chaves movimento (keysin.mv) para apagar + def add_kys + bqres.each { |r| @mvkys += ",#{r[:ky]}" } end - # @return [String] linha folha calculo existencia multipla - def row_multiplas - d = opl[:m] ? delete_mv : 0 - row_str + ' M(' + resultados.count.to_s + ')' + str_apagadas(d) - end - - # @param [Integer] numero linhas apagadas - # @return [String] texto formatado linhas apagadas - def str_apagadas(num) - num.positive? ? ' A(' + num.to_s + ')' : '' - end - # @return [Boolean] linha folha calculo nao existe no bigquery? - def row_naoexiste? - resultados.count.zero? + def linha_naoexiste? + bqres.count.zero? end # @return [Boolean] linha folha calculo existe no bigquery? - def row_existe? - resultados.count == 1 && resultados.first[:ds].strip == row[2] + def linha_existe? + bqres.count == 1 && bqres.first[:ds].strip == rowfc[2] end # @return [Boolean] linha folha calculo existe parecida no bigquery? - def row_simila? - resultados.count == 1 && resultados.first[:ds].strip != row[2] + def linha_simila? + bqres.count == 1 && bqres.first[:ds].strip != rowfc[2] end - def sql_sel_mv - "select *,#{sql_digest_mv} as ky " + sql_where_mv + # @return [String] sql para movimentos no bigquery + def sql_existe_mv + "select *,#{ky_mv} as ky from hernanilr.ab.mv " \ + "where nc=#{conta} and dl='#{rowfc[0].strftime(DF)}' and vl=#{rowfc[3]}" end - # @return [String] parte sql para processamento movimentos - def sql_where_mv - "from hernanilr.ab.mv where nc=#{conta} " \ - "and dl='#{row[0].strftime(DF)}' " \ - "and vl=#{row[3]}" + # obtem movimento (values.mv) para inserir + # + # @return [String] ' NOVO' + def values_mv + @mvvls += ",('#{rowfc[0].strftime(DF)}','#{dvc.strftime(DF)}','#{rowfc[2]}',#{rowfc[3]}" + values_mv_extra + ' NOVO' end - # @return [Integer] numero linhas inseridas - def insert_mv - return 1 unless opl[:i] - - dml('insert hernanilr.ab.mv(dl,dv,ds,vl,nc,ano,mes,ct,tp) VALUES(' \ - "'#{row[0].strftime(DF)}','#{dvc.strftime(DF)}','#{row[2]}',#{row[3]}" + - str_ins_pc) + # @return [String] campos extra do movimento (values.mv) para inserir + def values_mv_extra + ",#{conta},#{dvc.year},#{dvc.month},'#{tpc}',#{ctc})" end # @return [Date] data valor corrigida def dvc - opl[:v].size.zero? ? row[1] : Date.parse(opl[:v]) + opcao[:v].size.zero? ? rowfc[1] : Date.parse(opcao[:v]) end - # @return [String] campos extra da linha bigquery - def str_ins_pc - ",#{conta},#{dvc.year},#{dvc.month},#{ctc},'#{tpc}')" - end - + # @return [String] classificacao do movimento (null --> classificacao automatica) def ctc - opl[:g].size.zero? ? 'null' : ("'" + opl[:g] + "'") + opcao[:g].size.zero? ? 'null' : ("'" + opcao[:g] + "'") end + # @return [String] tipo movimento c[redito] ou d[ebito] def tpc - row[3].positive? ? 'c' : 'd' - end - - # @return [Integer] numero linhas apagadas - def delete_mv - dml('delete ' + sql_where_mv + " and ds='#{resultados.first[:ds]}'") + rowfc[3].positive? ? 'c' : 'd' end end