# app/services/romaneios/normalizador.rb # # Parsing compartilhado entre as duas fontes de plano (API e .xlsx). Existe para os # dois caminhos entregarem EXATAMENTE a mesma forma de linha ao Romaneios::Importador # — se cada um normalizasse do seu jeito, o mesmo plano importado por caminhos # diferentes geraria linhas com chave_origem diferente e a reconciliação duplicaria # tudo na primeira reimportação. # # Namespace no plural (Romaneios::) para não colidir com a constante do model # Romaneio. module Romaneios module Normalizador # "NF 90507 - CICERA BESERRA DOS ANJOS" -> ['90507', 'CICERA BESERRA DOS ANJOS'] NF_TITULO = /\ANF\s+(\d+)\s*-\s*(.+)\z/i # "TEL: (11) 99262-0594 / (11) 99824-8099" — o plano guarda o telefone dentro # das Anotações, em texto livre. Pegamos TODOS os que casarem: uma parada com # dois números precisa dos dois no papel (o motorista liga do portão). TEL_ANOTACAO = /\(?\d{2}\)?\s*\d{4,5}-?\d{4}/ module_function # Devolve [nf, nome]. Título fora do padrão vira [nil, título] — não é erro: # plano avulso e de inclusão às vezes chegam sem o prefixo "NF n - ". def nf_e_nome(titulo) texto = titulo.to_s.strip m = NF_TITULO.match(texto) return [m[1], m[2].strip] if m [nil, texto] end # O SimpliRoute devolve o endereço com sufixo ", Brazil"; o documento impresso # nunca teve isso. Caixa alta porque é como o romaneio sai desde sempre. def endereco(valor) valor.to_s .gsub(/,\s*Brazil\s*\z/i, '') .strip .gsub(/\s+/, ' ') .upcase end # Telefones a partir das anotações do plano. Só é usado quando a operação não # tem o número — a coluna `telefones` da gade_entregas_* é a fonte preferida # (ver Romaneios::EnriquecimentoGade). def telefones_de_anotacao(anotacoes) texto = anotacoes.to_s return '' unless texto.match?(/TEL/i) texto.scan(TEL_ANOTACAO).map(&:strip).uniq.join(' / ') end def nome(valor) valor.to_s.strip.gsub(/\s+/, ' ').upcase end # 'SIM' quando o paciente é NOVO na operação; vazio caso contrário. # É o que a segunda planilha do programa Python fazia à mão. def aparelho_por_status(status_gade) status_gade.to_s.strip.casecmp('NOVO').zero? ? 'SIM' : '' end # Uma linha crua do plano (de qualquer fonte) vira a forma canônica que o # Importador consome. def linha(veiculo:, ordem:, titulo:, endereco:, anotacoes: nil, nota_fiscal: nil, tracking_id: nil, motorista: nil) # `endereco` aqui é a variável local do kwarg — o método homônimo continua # acessível com parênteses, mas renomeamos para ninguém tropeçar. endereco_cru = endereco nf_titulo, nome_titulo = nf_e_nome(titulo) nf = nota_fiscal.to_s.strip nf = nf_titulo.to_s if nf.empty? { veiculo: veiculo.to_s.strip, ordem: ordem.to_i, motorista: motorista.to_s.strip, nota_fiscal: nf.to_s, nome: nome(nome_titulo), endereco: endereco(endereco_cru), telefones: telefones_de_anotacao(anotacoes), tracking_id: tracking_id.to_s, titulo: titulo.to_s } end end end