Files
sar-android/_bmad-output/implementation-artifacts/3-2-ler-acrescimo-do-postgresql-no-sync-de-consulta.md
Julio Schlickmann dc61705c91 add project files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 22:33:42 -03:00

15 KiB
Raw Blame History

Story 3.2: Ler Acréscimo do PostgreSQL no Sync de Consulta

Status: done

Story

Como representante de vendas, quero que pedidos históricos sincronizados do ERP cheguem ao app com o acréscimo correto gravado, para que a consulta exiba os valores reais praticados mesmo em pedidos que não foram criados neste dispositivo.

Acceptance Criteria

  1. Dado que Global.sistema == SISTEMA_GERENTE e gerente.pedidos possui acrep = 3.0 e acrev = 105.00 para um pedido Quando PedidoPGSQL.selectAllPedConsulta ler o registro Então o VO Pedido retornado tem vlAcrescimo = 105.00

  2. Dado que Global.sistema == SISTEMA_SIG e sig.pedidos possui tx_acrescimo = 3.0 e total = 3500.00 para um pedido Quando PedidoPGSQL.selectAllPedConsulta ler o registro Então o VO Pedido retornado tem vlAcrescimo calculado como 3500.00 × 3.0 / 100 = 105.00

  3. Dado que a coluna de acréscimo não existe no PostgreSQL ou está NULL Quando selectAllPedConsulta for executado Então o VO recebe vlAcrescimo = 0.0, sem erro, sem crash

  4. Dado que PedidoConsultaDB.saveAll recebe os VOs retornados Quando gravar em pedido_consulta Então pedido_consulta.vl_acrescimo reflete o valor lido do PG

Escopo desta história

SIM:

  • Adicionar COALESCE(a.acrev, 0.0) as acrev ao SELECT Gerente em selectAllPedConsulta()
  • Reutilizar hasColunaAcrescimoSig() (já existe na classe) antes do SELECT SIG
  • Adicionar COALESCE(a.tx_acrescimo, 0.0) as tx_acrescimo condicionalmente ao SELECT SIG quando coluna existir
  • Ler e setar ped.setVlAcrescimo(...) no loop de ResultSet (acrev direto para Gerente; total × tx_acrescimo / 100 para SIG)

NÃO cobre:

  • PedidoConsultaDB — já grava e lê vl_acrescimo (Stories 2.3/2.4 já fizeram isso — não modificar)
  • MD5 de pedido_consulta incluindo vl_acrescimo — Story 3.3
  • DDL server-side — responsabilidade do DBA; app tolera ausência

Pré-condições verificadas

  • PedidoConsultaDB.insert() — já inclui vl_acrescimo na lista de colunas e lê ped.getVlAcrescimo() na linha 147. Nenhuma mudança necessária.
  • PedidoConsultaDB.updateErp() — já atualiza vl_acrescimo = ped.getVlAcrescimo() na linha 183. Nenhuma mudança necessária.
  • PedidoConsultaDB.selectFull() — já lê a.vl_acrescimo (índice 66) e chama pedido.setVlAcrescimo(c.getDouble(66)) na linha 296. Nenhuma mudança necessária.
  • hasColunaAcrescimoSig() — método privado já existe em PedidoPGSQL.java (linhas 11861203); pode ser reutilizado em selectAllPedConsulta() diretamente.
  • Gerente — acrep/acrev já existem: Confirmado em Story 3.1 — colunas estavam na lista do INSERT desde antes do Epic 3; safe para adicionar ao SELECT sem tolerância.
  • SIG — tx_acrescimo pode não existir: DDL pode estar pendente; mesma tolerância aplicada em Story 3.1.
  • Pedido.setVlAcrescimo(double) — getter/setter adicionados em Story 2.3; disponíveis no VO.
  • new Pedido()vlAcrescimo default é 0.0 (primitivo double); AC 3 satisfeito automaticamente quando não setado.
  • ResultSet em selectAllPedConsulta() usa acesso por nome (rs.getString("num_ped_sar"), etc.); adicionar colunas nomeadas ao SELECT é seguro e não desloca índices.
  • dbVersao permanece 43 — sem alteração de schema SQLite.

Tasks / Subtasks

  • Task 1: Declarar variável de controle SIG antes do if-else de queries (AC: 2, 3)

    • 1.1 — Em PedidoPGSQL.java, dentro de selectAllPedConsulta(), logo antes do bloco if (Global.sistema.equals(Global.SISTEMA_GERENTE)){ (linha 619), adicionar:
      boolean temAcrescSigConsulta = false;
      

      Variável acessível em ambos os branches e no loop de ResultSet. false como default garante AC 3 para SIG sem DDL.

  • Task 2: Adicionar acrev ao SELECT Gerente (AC: 1, 3)

    • 2.1 — No branch Gerente (linhas 624643), alterar a linha que termina com a.total:
      // ANTES:
      sql.append("       a.ped_flex, a.descv, a.descp, a.total"); //13-16
      
      // DEPOIS:
      sql.append("       a.ped_flex, a.descv, a.descp, a.total, COALESCE(a.acrev, 0.0) as acrev"); //13-17
      

      COALESCE garante que registros históricos com acrev = NULL retornem 0.0 — AC 3. acrep não é necessário para vlAcrescimo; apenas acrev (o valor calculado) é lido.

  • Task 3: Checar coluna e adicionar tx_acrescimo ao SELECT SIG condicionalmente (AC: 2, 3)

    • 3.1 — No branch SIG (linha ~645, início do else), ANTES de construir o sql, adicionar:
      temAcrescSigConsulta = hasColunaAcrescimoSig();
      

      Reutiliza o método privado existente (linhas 11861203). Executa UMA VEZ por chamada a selectAllPedConsulta, antes do loop de ResultSet.

    • 3.2 — No SELECT SIG, após a.total (linha ~658), adicionar condicionalmente:
      // ANTES:
      sql.append("       a.ped_flex, a.descv, a.descp, a.total"); //13-16
      
      // DEPOIS:
      sql.append("       a.ped_flex, a.descv, a.descp, a.total"); //13-16
      if (temAcrescSigConsulta) {
          sql.append(", COALESCE(a.tx_acrescimo, 0.0) as tx_acrescimo"); //17
      }
      
  • Task 4: Setar vlAcrescimo no VO no loop de ResultSet (AC: 1, 2, 3, 4)

    • 4.1 — Após ped.setTotal(rs.getDouble("total")) (linha 730), adicionar:
      if (Global.sistema.equals(Global.SISTEMA_GERENTE)) {
          ped.setVlAcrescimo(rs.getDouble("acrev"));
      } else if (temAcrescSigConsulta) {
          ped.setVlAcrescimo(rs.getDouble("total") * rs.getDouble("tx_acrescimo") / 100.0);
      }
      // else: vlAcrescimo = 0.0 (default de new Pedido() — AC 3 para SIG sem DDL)
      

      Para Gerente: acrev é o valor congelado no ERP (taxa aplicada na época do pedido). Para SIG: fórmula especificada no AC 2 — total × tx_acrescimo / 100. Se SIG sem DDL: temAcrescSigConsulta = false → nenhum setter chamado → vlAcrescimo = 0.0.

Dev Notes

Mapa de campos por sistema

Sistema Coluna PG para vlAcrescimo Existência garantida? Fórmula no app
Gerente (gerente.pedidos) acrev Sim — col já existia antes do Epic 3 vlAcrescimo = rs.getDouble("acrev")
SIG (sig.pedidos) tx_acrescimo Não — DDL pode estar pendente vlAcrescimo = total × tx_acrescimo / 100.0

Por que Gerente usa acrev (não acrep)

acrep é a taxa percentual (ex: 2.5). acrev é o valor calculado (ex: R$ 87,50). Pedido.vlAcrescimo armazena o valor monetário, não a taxa. Portanto apenas acrev é necessário no SELECT Gerente.

Por que SIG calcula o valor em vez de armazená-lo

SIG armazena só a taxa (tx_acrescimo). O valor é derivado server-side usando a fórmula total × tx_acrescimo / 100. Esta é a mesma assimetria documentada em Story 3.1 e nos pré-requisitos do Epic 3 — intencional, não é bug.

Reuso de hasColunaAcrescimoSig()

O método privado já existe em PedidoPGSQL.java (linhas 11861203). Foi criado em Story 3.1 para o INSERT; aqui é reutilizado no SELECT. Não duplicar lógica — chamar o mesmo método.

PedidoConsultaDB — NENHUMA MUDANÇA NECESSÁRIA

PedidoConsultaDB.insert() (linha 147): sql.append(ped.getVlAcrescimo() + ");") — já grava. PedidoConsultaDB.updateErp() (linha 183): sql.append(" vl_acrescimo = " + ped.getVlAcrescimo()) — já atualiza. PedidoConsultaDB.selectFull() (linha 296): pedido.setVlAcrescimo(c.getDouble(66)) — já lê.

A Story 2.4 já preparou tudo. Story 3.2 apenas popula o campo vlAcrescimo no VO antes de saveAll ser chamado.

Fluxo completo (para referência)

ComunicaActivity.onPostExecute()
  → PedidoPGSQL.selectAllPedConsulta()   ← MUDANÇA AQUI: ler acrev/tx_acrescimo
      → rs → Pedido VO com vlAcrescimo preenchido
  → PedidoConsultaDB.saveAll()           ← SEM MUDANÇA: já grava vl_acrescimo
      → insert() ou updateErp()
  → pedido_consulta.vl_acrescimo = valor lido do PG
  → BrowsePedidoConsulta / selectFull()  ← SEM MUDANÇA: já lê vl_acrescimo

Arquivo a modificar

Arquivo Caminho O que muda
PedidoPGSQL.java src/br/com/jcsinformatica/sarandroid/postgres/ selectAllPedConsulta(): SELECT Gerente + temAcrescSigConsulta + SELECT SIG condicional + setter no loop

NÃO modificar:

  • PedidoConsultaDB.java — já completo (Stories 2.3/2.4)
  • Pedido.java — VO completo (Story 2.3)
  • DatabaseHelper.java — schema SQLite não muda

Regras críticas do projeto (aplicáveis)

  • Sem Kotlin — somente Java puro
  • Sem Gradle — projeto Eclipse ADT
  • Sem JARs novos — nenhuma dependência adicional
  • Sem testes automatizados — validação manual via dispositivo/emulador
  • ConnectionManager.closeAll(st, rs) — já chamado ao final de selectAllPedConsulta() (linha 751); não alterar
  • ResultSet por nome — padrão em selectAllPedConsulta(); não usar índices posicionais

Inteligência de histórias anteriores

  • Story 3.1: hasColunaAcrescimoSig() criada aqui — reutilizar sem duplicar. insert() Gerente usa acrep/acrev (já existem); insertSig() usa tx_acrescimo com tolerância. Mesmos princípios aqui, mas para leitura.
  • Story 2.4: BrowsePedidoConsulta e selectFull() já usam vlAcrescimo do VO. Esta story fecha o ciclo: antes só os pedidos criados localmente tinham vlAcrescimo; agora também os históricos do PG.
  • Story 2.3: Pedido.vlAcrescimo (double, default 0.0) e PedidoConsultaDB totalmente preparados.
  • Story 1.2: Padrão de tolerância a coluna ausente — try-catch em FormaPagamentoPGSQL. Aqui usamos a abordagem mais robusta de hasColunaAcrescimoSig() (já criada em Story 3.1), que condiciona a construção do SQL em vez de tentar e falhar.

Verificação manual após implementação

  1. Gerente — pedido com acréscimo gravado no PG:

    • Garantir que um pedido em gerente.pedidos tenha acrev > 0 (enviar via Story 3.1 ou inserir diretamente)
    • Executar sync (ComunicaActivity); verificar em pedido_consulta via logcat que INSERT PEDIDO CONSULTA contém vl_acrescimo = <valor> correspondente ao acrev do PG
  2. Gerente — pedido histórico com acrev = NULL ou 0:

    • Verificar que vlAcrescimo = 0.0 no VO — sem crash
  3. SIG com DDL aplicado:

    • Pedido em sig.pedidos com tx_acrescimo = 3.0, total = 3500.00
    • Sync → vl_acrescimo = 105.00 em pedido_consulta
  4. SIG sem DDL (coluna ausente):

    • Com tx_acrescimo ausente em sig.pedidos
    • Sync deve concluir sem exceção; vl_acrescimo = 0.0 nos pedidos sincronizados
  5. Log para debug:

    • Log.d("INSERT PEDIDO CONSULTA", sql.toString()) — verificar vl_acrescimo no SQL de insert
    • Log.d("SQL PEDIDO CONSULTA = ", sql.toString()) — verificar se acrev ou tx_acrescimo está no SELECT

Git intelligence (commits recentes)

  • f2cf45d Story 2.4: pedido_consulta.vl_acrescimo + guard status >= STATUS_ENVIADO em consulta
  • 3ff26a7 Story 2.3: Pedido.vlAcrescimo + PedidoDB + PedidoConsultaDB preparados
  • Story 3.1 (não commitada): PedidoPGSQL.insert/insertSig/save/hasColunaAcrescimoSig — padrões a seguir

References

  • Epics: _bmad-output/planning-artifacts/epics.md#story-32-ler-acrescimo-do-postgresql-no-sync-de-consulta
  • FR15: Leitura inbound do acréscimo do PG na sync de consulta
  • FR16: Sync tolera ausência das colunas de acréscimo no PostgreSQL
  • PedidoPGSQL.java:603752 — método selectAllPedConsulta() completo
  • PedidoPGSQL.java:11861203hasColunaAcrescimoSig() a reutilizar
  • PedidoConsultaDB.java:98151insert() (linha 147: vl_acrescimo já gravado)
  • PedidoConsultaDB.java:153196updateErp() (linha 183: vl_acrescimo já atualizado)
  • PedidoConsultaDB.java:198305selectFull() (linha 296: vl_acrescimo já lido)
  • Memory: project_pg_sync_acrescimo_schema.md — assimetria Gerente vs SIG

Dev Agent Record

Agent Model Used

claude-sonnet-4-6 (create-story workflow)

Debug Log References

N/A — projeto sem infraestrutura de testes automatizados; validação manual via dispositivo/emulador conforme roteiro em "Verificação manual após implementação".

Completion Notes List

  • Story 3.2 implementada em 2026-04-16.
  • Task 1: boolean temAcrescSigConsulta = false declarada antes do if-else Gerente/SIG em selectAllPedConsulta() (linha 619). Acessível em ambos os branches e no loop de ResultSet.
  • Task 2 — Gerente SELECT: COALESCE(a.acrev, 0.0) as acrev adicionado ao SELECT (linha 630). COALESCE protege contra registros históricos com acrev = NULL. acrep não incluído — apenas o valor calculado (acrev) é necessário para vlAcrescimo.
  • Task 3 — SIG SELECT: temAcrescSigConsulta = hasColunaAcrescimoSig() chamado UMA VEZ antes de construir o SQL (linha 653). SELECT SIG inclui condicionalmente COALESCE(a.tx_acrescimo, 0.0) as tx_acrescimo quando coluna existe (linhas 661663). Reutiliza o método privado criado em Story 3.1 — sem duplicação de lógica.
  • Task 4 — vlAcrescimo no loop: Após ped.setTotal(...) (linhas 736740): Gerente → setVlAcrescimo(rs.getDouble("acrev")); SIG com DDL → setVlAcrescimo(total × tx_acrescimo / 100.0); SIG sem DDL → sem setter, vlAcrescimo = 0.0 (default primitivo). AC 1, 2, 3 e 4 satisfeitos.
  • PedidoConsultaDB não modificado — insert(), updateErp() e selectFull() já manipulam vl_acrescimo desde Stories 2.3/2.4.
  • dbVersao permanece 43 — sem alteração de schema SQLite.
  • Sem testes automatizados: projeto não possui infraestrutura (conforme CLAUDE.md). Validação manual necessária — roteiro em "Verificação manual após implementação".
  • Nenhum import adicionado — todas as classes já importadas.

File List

  • src/br/com/jcsinformatica/sarandroid/postgres/PedidoPGSQL.java

Review Findings

  • [Review][Defer] hasColunaAcrescimoSig() chamado duas vezes por sessão de sync — uma vez em save() (Story 3.1) e uma vez em selectAllPedConsulta() (Story 3.2). Durante uma janela de DDL migration, os dois resultados podem divergir, fazendo insert com tx_acrescimo mas read sem (ou vice-versa). Em produção, DDL deve ocorrer fora da janela de sync; risco é teórico. — deferred, pré-existente ao escopo de 3.2

Change Log

  • 2026-04-16: Story 3.2 criada pelo create-story workflow.
  • 2026-04-16: Story 3.2 implementada. PedidoPGSQL.selectAllPedConsulta(): SELECT Gerente agora inclui COALESCE(a.acrev, 0.0) as acrev; SELECT SIG inclui condicionalmente COALESCE(a.tx_acrescimo, 0.0) as tx_acrescimo (via hasColunaAcrescimoSig() reutilizado de Story 3.1); loop de ResultSet seta Pedido.vlAcrescimo com o valor lido do PG (acrev direto para Gerente; total × tx_acrescimo / 100 para SIG). Tolerância completa à ausência de DDL no SIG.