Files
sar-android/_bmad-output/implementation-artifacts/2-4-exibir-acrescimo-na-consulta-de-pedidos.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

30 KiB
Raw Blame History

Story 2.4: Exibir Acréscimo na Consulta de Pedidos

Status: done

Story

Como representante de vendas, quero ver o total correto (com acréscimo) na consulta de pedidos já fechados, para que o histórico reflita os valores reais praticados, preservados no momento do fechamento.

Acceptance Criteria

  1. Dado que consulto um pedido fechado (status >= STATUS_ENVIADO) que possui vl_acrescimo > 0 gravado no registro Quando a tela de detalhe do pedido (UpdatePedidoActivity via MainPedidoFragment + TotalPedidoFragment) for exibida Então o campo "Acréscimo" exibe o valor persistido (Global.pedido.getVlAcrescimo()) — não recalculado a partir da tx_acrescimo atual da forma de pagamento E o total geral exibido inclui esse acréscimo persistido (subtotal + vl_acrescimo_persistido)

  2. Dado que consulto um pedido fechado criado antes desta funcionalidade (sem vl_acrescimo ou com vl_acrescimo = 0) Quando a tela de detalhe do pedido for exibida Então o pedido é exibido normalmente, campo "Acréscimo" mostra R$ 0,00, total geral = subtotal E nenhum NullPointerException ou crash ocorre

  3. Dado que a migração SQLite v42→v43 é executada em um dispositivo com pedido_consulta sem vl_acrescimo Quando DatabaseHelper.onUpgrade() rodar Então a coluna vl_acrescimo REAL DEFAULT 0 é adicionada à tabela pedido_consulta E todos os registros existentes são preservados com vl_acrescimo = 0 E dbVersao = 43

  4. Dado que um novo pedido chega via sync PostgreSQL (AtualizaDados.atualizaPedidosConsulta) Quando PedidoConsultaDB.saveAll() inserir/atualizar o registro em pedido_consulta Então o valor de ped.getVlAcrescimo() (0.0 por enquanto — sync PG do acréscimo é deferred) é gravado em pedido_consulta.vl_acrescimo sem erro E a sync segue sem interrupção mesmo que o VO chegue com vlAcrescimo = 0.0

  5. Dado que PedidoConsultaDB.selectFull() carrega um pedido Quando o cursor percorrer as colunas adicionais Então a.vl_acrescimo é lida e pedido.setVlAcrescimo() é populado com o valor do banco (ou 0.0 quando a coluna é NULL)

Escopo desta história

Esta história cobre exclusivamente:

  • SIM migração SQLite v42 → v43 adicionando vl_acrescimo na tabela pedido_consulta
  • SIM persistência em PedidoConsultaDB.insert() e updateErp()
  • SIM leitura em PedidoConsultaDB.selectFull() — cursor index 66 (novo, adicionado ao fim)
  • SIM exibição correta do acréscimo persistido em MainPedidoFragment.fillFields() e atualizarResumoPedido() quando status >= STATUS_ENVIADO
  • SIM exibição correta em TotalPedidoFragment.FillFields() quando status >= STATUS_ENVIADO

NÃO cobre (deferred):

  • Sync do acréscimo via PG (PedidoPGSQL.selectAllPedConsulta / PedidoPGSQL.insert) — PG ainda não possui a coluna; reavaliar em story futura (ver deferred-work.md)
  • Alteração do layout list_browse_pedido.xml ou do VO PedidoList — o total exibido na lista usa pedido_consulta.total (já persistido no save) e permanece inalterado
  • Atualização de PedidoConsultaDB.selectListResumo()total da lista permanece como está (deferred até sync PG carregar acréscimo)
  • Atualização de PedidoConsultaDB.selectTotais() (agregação de vendas em ConsultaVendasActivity) — soma peditem_consulta.vl_totliq, independente de acréscimo (deferred)
  • MD5 do pedido não inclui vl_acrescimo (deferred per review da Story 2.3)

Pré-condições verificadas

Inspeção do código confirma:

  • Tabela pedido_consulta NÃO possui coluna vl_acrescimo (DatabaseHelper.java:261-285) — nunca foi migrada; Story 2.3 migrou apenas a tabela pedido
  • dbVersao atual = 42 (DatabaseHelper.java:10)
  • PedidoConsultaDB.insert() e updateErp() não tocam em vl_acrescimo (PedidoConsultaDB.java:98-194)
  • PedidoConsultaDB.selectFull() percorre índices 0..65; nãovl_acrescimo (PedidoConsultaDB.java:196-302)
  • ThreadAbrirPedidoConsulta força status = STATUS_ENVIADO antes de abrir UpdatePedidoActivity (ThreadAbrirPedidoConsulta.java:22-24) — ou seja: todo pedido aberto via consulta chega em MainPedidoFragment com status >= STATUS_ENVIADO
  • MainPedidoFragment.fillFields() (linha ~439-446) e atualizarResumoPedido() (linha ~979-986) recalculam vlAcrescimo = totalGeral × (txAcrescimo/100) e sobrescrevem Global.pedido.setVlAcrescimo(vlAcrescimo) — comportamento correto para edição, mas destrói o valor histórico em consulta
  • TotalPedidoFragment.FillFields() (linha ~97-103) faz o mesmo recálculo — também precisa ser corrigido
  • Pedido.vlAcrescimo já existe como campo + getter/setter (Pedido.java:41,759-764) — Story 2.3

Tasks / Subtasks

  • Task 1: Migração SQLite v42 → v43 em DatabaseHelper.java (AC: 3)

    • 1.1 — Incrementar dbVersao de 42 para 43 (DatabaseHelper.java:10):
      final static int dbVersao = 43; // era 42
      
    • 1.2 — Adicionar bloco em onUpgrade() ao final, após o bloco if (oldVersion < 42) (linha ~708):
      if (oldVersion < 43) {
          db.execSQL("ALTER TABLE pedido_consulta ADD COLUMN vl_acrescimo REAL DEFAULT 0;");
      }
      
    • 1.3 — Atualizar também onCreate() para incluir vl_acrescimo REAL na definição de CREATE TABLE pedido_consulta (linha ~261-285). Adicionar ao final da lista de colunas (antes das FOREIGN KEY):
      + "    total              REAL,"
      + "    vl_acrescimo       REAL    DEFAULT 0,"
      + "    FOREIGN KEY ( id_empresa ) REFERENCES empresa ( id_empresa ),"
      

      ⚠️ Essencial: onCreate + onUpgrade devem permanecer em sincronia para instalações novas vs. atualizadas.

  • Task 2: Persistir vl_acrescimo em PedidoConsultaDB.insert() (AC: 4)

    • 2.1 — Em PedidoConsultaDB.java:119-123, adicionar vl_acrescimo à lista de colunas:
      sql.append(" id_pedido_consulta, id_empresa, numero, id_erp, numero_erp, status, data,");
      sql.append(" id_cliente, data_emissao, id_formapag, observacao, id_pauta, md5, tipo, permite_flex,");
      sql.append(" desconto_p, desconto_v, total, vl_acrescimo");
      sql.append(") VALUES(");
      
    • 2.2 — Em PedidoConsultaDB.java:146, ajustar o último append para não fechar ainda e adicionar o valor:
      sql.append(ped.getTotalPedidoConsulta() + ", "); //total
      sql.append(ped.getVlAcrescimo() + ");");         //vl_acrescimo
      

      O valor virá 0.0 da sync PG (getter default) enquanto a sync não carregar o campo — comportamento aceitável (AC 4).

  • Task 3: Persistir vl_acrescimo em PedidoConsultaDB.updateErp() (AC: 4)

    • 3.1 — Em PedidoConsultaDB.java:181-182, adicionar vl_acrescimo ao SET (antes do WHERE):
      sql.append(" total        = "  +ped.getTotalPedidoConsulta()+", ");
      sql.append(" vl_acrescimo = "  +ped.getVlAcrescimo());
      sql.append(" WHERE id_empresa = " + Global.getEmpresa().getId() + " AND id_erp = " + ped.getIdErp());
      

      ⚠️ Atenção: o total atual não termina com vírgula; mudar para + ", " ao inserir o novo campo.

  • Task 4: Ler vl_acrescimo em PedidoConsultaDB.selectFull() (AC: 5)

    • 4.1 — No SELECT (PedidoConsultaDB.java:211), acrescentar a.vl_acrescimo ao final da lista:
      sql.append(" a.permite_flex, a.desconto_p, a.desconto_v, a.total, a.vl_acrescimo");
      
      a.vl_acrescimo é o índice 66 do cursor (após 65 = a.total).
    • 4.2 — No loop de leitura (PedidoConsultaDB.java:293), após pedido.setTotal(c.getDouble(65));, adicionar:
      pedido.setTotal(c.getDouble(65));
      pedido.setVlAcrescimo(c.getDouble(66));
      
  • Task 5: Preservar vl_acrescimo histórico em MainPedidoFragment.fillFields() (AC: 1, 2)

    • 5.1 — Em MainPedidoFragment.java:439-446, envolver o recálculo em um guard por status:
      // Estado atual:
      double txAcrescimo = 0.0;
      if (Global.pedido.getFormapag() != null) {
          txAcrescimo = Global.pedido.getFormapag().getTxAcrescimo();
      }
      double vlAcrescimo = totalGeral * (txAcrescimo / 100.0);
      tvAcrescimoPedido.setText(Util.formataValorMonetario(vlAcrescimo));
      tvTotalGeral.setText(Util.formataValorMonetario(totalGeral + vlAcrescimo));
      Global.pedido.setVlAcrescimo(vlAcrescimo);
      
      Substituir por:
      double vlAcrescimo;
      if (Global.pedido.getStatus() >= Pedido.STATUS_ENVIADO) {
          // Pedido fechado (consulta) — usa valor persistido, NÃO recalcula
          vlAcrescimo = Global.pedido.getVlAcrescimo();
      } else {
          // Pedido em edição — recalcula a partir da taxa vigente
          double txAcrescimo = 0.0;
          if (Global.pedido.getFormapag() != null) {
              txAcrescimo = Global.pedido.getFormapag().getTxAcrescimo();
          }
          vlAcrescimo = totalGeral * (txAcrescimo / 100.0);
          Global.pedido.setVlAcrescimo(vlAcrescimo);
      }
      tvAcrescimoPedido.setText(Util.formataValorMonetario(vlAcrescimo));
      tvTotalGeral.setText(Util.formataValorMonetario(totalGeral + vlAcrescimo));
      
  • Task 6: Preservar vl_acrescimo histórico em MainPedidoFragment.atualizarResumoPedido() (AC: 1, 2)

    • 6.1 — Em MainPedidoFragment.java:979-986, aplicar o mesmo padrão da Task 5:
      double vlAcrescimo;
      if (Global.pedido.getStatus() >= Pedido.STATUS_ENVIADO) {
          vlAcrescimo = Global.pedido.getVlAcrescimo();
      } else {
          double txAcrescimo = 0.0;
          if (Global.pedido.getFormapag() != null) {
              txAcrescimo = Global.pedido.getFormapag().getTxAcrescimo();
          }
          vlAcrescimo = totalGeral * (txAcrescimo / 100.0);
          Global.pedido.setVlAcrescimo(vlAcrescimo);
      }
      tvAcrescimoPedido.setText(Util.formataValorMonetario(vlAcrescimo));
      tvTotalGeral.setText(Util.formataValorMonetario(totalGeral + vlAcrescimo));
      

      Não duplicar em helper — manter paralelo à Task 5 segue o padrão pré-existente do projeto (cálculo duplicado em fillFields e atualizarResumoPedido já deferred per review da Story 2.2).

  • Task 7: Preservar vl_acrescimo histórico em TotalPedidoFragment.FillFields() (AC: 1, 2)

    • 7.1 — Em TotalPedidoFragment.java:97-103, aplicar o mesmo padrão:
      double vlAcrescimo;
      if (Global.pedido.getStatus() >= Pedido.STATUS_ENVIADO) {
          vlAcrescimo = Global.pedido.getVlAcrescimo();
      } else {
          double txAcrescimo = 0.0;
          if (Global.pedido.getFormapag() != null) {
              txAcrescimo = Global.pedido.getFormapag().getTxAcrescimo();
          }
          vlAcrescimo = vlTotalGeral * (txAcrescimo / 100.0);
      }
      tvAcrescimo.setText(Util.formataValorMonetario(vlAcrescimo));
      tvTotalGeral.setText(Util.formataValorMonetario(vlTotalGeral + vlAcrescimo));
      

      TotalPedidoFragment não chama setVlAcrescimo — o save é gerenciado por MainPedidoFragment, então não é necessário replicar essa gravação aqui mesmo no branch de edição (manter paralelo ao comportamento pré-existente).

Dev Notes

Fluxo de abertura de pedido via consulta — verificado

BrowsePedidoConsulta.onItemClick(pos)
  → ThreadAbrirPedidoConsulta.run()
     → PedidoConsultaDB.selectFull(id)       [carrega Pedido VO do pedido_consulta]
     → pedido.setStatus(STATUS_ENVIADO)      [força status, se < 2]   ← LINHA 22-24
     → Global.pedido = pedido
     → brwPedido.abrirUpdate()
        → startActivity(UpdatePedidoActivity)
           → MainPedidoFragment.fillFields() [recalcula vlAcrescimo — BUG]
           → TotalPedidoFragment.FillFields() [idem]

Conclusão: todo pedido aberto via consulta tem status >= STATUS_ENVIADO garantido. O guard status >= STATUS_ENVIADO é suficiente.

Pedidos via BrowsePedidoThreadAbrirPedidoPedidoDB.selectFull() (editáveis) preservam o status original; a mesma correção funciona em ambos os fluxos.

Por que NÃO usar isEditable() / flag custom

O projeto já tem Pedido.STATUS_* constantes. status >= STATUS_ENVIADO (valor 2) cobre ENVIADO, CANCELADO, EMITIDO — exatamente os status "fechados" (não-editáveis). Inventar uma nova flag seria reinvenção.

Mapeamento de índices em PedidoConsultaDB.selectFull() — cuidado com offset

Índices atuais do cursor (PedidoConsultaDB.java:200-211):

  • 0..1: A.id_pedido_consulta, A.id_empresa
  • 2..12: dados do pedido
  • 13..35: dados do cliente
  • 36..42: dados do município
  • 43..50: dados da forma de pagamento
  • 51..61: dados da pauta
  • 62: a.permite_flex
  • 63: a.desconto_p
  • 64: a.desconto_v
  • 65: a.totalpedido.setTotal(c.getDouble(65))
  • 66: a.vl_acrescimo ← ADICIONAR → pedido.setVlAcrescimo(c.getDouble(66))

Não alterar os índices existentes — apenas acrescentar ao final.

⚠️ Precedente: PedidoDB.selectAllFull() usa índice 68 para a.vl_acrescimo (Story 2.3). Em PedidoConsultaDB.selectFull() o índice é 66 — SQL e estrutura de join diferem; validar contando colunas do SELECT antes de alterar.

vl_acrescimo da sync PG estará em 0.0 (por enquanto)

  • PedidoPGSQL.selectAllPedConsulta() não lê vl_acrescimo do PostgreSQL — deferred per review da Story 2.3 (PG ainda não tem a coluna)
  • Portanto, pedidos novos que chegam via sync PG terão vlAcrescimo = 0.0 no VO
  • Tarefa 2 e 3 gravam esse 0.0 sem problema — garante forward-compat quando o sync PG começar a carregar o valor real
  • AC 2 cobre explicitamente esse caso: pedidos com vl_acrescimo = 0 exibem R$ 0,00 e funcionam normalmente

Quando a história futura "sync PG do acréscimo" for implementada, PedidoPGSQL.selectAllPedConsulta() popula ped.setVlAcrescimo(rs.getDouble("vl_acrescimo")) e tudo funcionará sem outras mudanças neste caminho.

Pedidos locais (antes do sync PG) — fluxo paralelo

Quando o usuário cria e salva um pedido localmente (antes de enviar ao ERP), ele fica em pedido (não em pedido_consulta) com vl_acrescimo gravado por Story 2.3.

Ao enviar/sincronizar, o pedido pode transitar de pedido para pedido_consulta (via sync PG de retorno). Durante essa transição, pedido_consulta.vl_acrescimo ficará 0.0 (até o sync PG carregar o valor). Para o usuário, isso pode significar:

  • Abrir o pedido via BrowsePedido (local) → PedidoDB.selectFull()vlAcrescimo lido de pedido → exibido corretamente
  • Abrir o mesmo pedido via BrowsePedidoConsultaPedidoConsultaDB.selectFull()vlAcrescimo = 0.0 → exibido R$ 0,00

Essa dualidade é esperada e documentada como deferred. Escopo desta história é garantir que quando o valor ESTÁ persistido, ele é exibido corretamente (AC 1), e que a ausência não quebra nada (AC 2).

Null-safety do getter getVlAcrescimo()

Pedido.vlAcrescimo inicializa em 0.0 (primitive double, Pedido.java:41). getVlAcrescimo() não pode retornar null. c.getDouble(66) em SQLite retorna 0.0 quando a coluna é NULL. Zero risco de NPE em toda a cadeia de AC 2.

Por que atualizar onCreate e onUpgrade em Task 1

Dispositivos novos nunca rodam onUpgrade — apenas onCreate. Se só adicionarmos em onUpgrade, instalações limpas terão pedido_consulta sem vl_acrescimo, fazendo PedidoConsultaDB.selectFull() estourar SQLiteException: no such column. Padrão já estabelecido em stories 1.1 e 2.3 (sempre atualizar ambos).

Arquivos a modificar

Arquivo Caminho O que muda
DatabaseHelper.java src/br/com/jcsinformatica/sarandroid/database/ dbVersao = 43; bloco v43 em onUpgrade(); coluna em onCreate()
PedidoConsultaDB.java src/br/com/jcsinformatica/sarandroid/database/ INSERT, UPDATE (updateErp), SELECT (selectFull)
MainPedidoFragment.java src/br/com/jcsinformatica/sarandroid/pedido/ Guard status >= STATUS_ENVIADO em fillFields() e atualizarResumoPedido()
TotalPedidoFragment.java src/br/com/jcsinformatica/sarandroid/pedido/ Guard status >= STATUS_ENVIADO em FillFields()

NÃO modificar nesta história:

  • list_browse_pedido.xml — layout permanece
  • PedidoList.java (VO do adapter) — permanece com só total
  • SimpleArrayAdapterPedidoBrowser.java — exibe total como antes
  • PedidoConsultaDB.selectListResumo() — deferred (ver seção Escopo)
  • PedidoConsultaDB.selectTotais() — deferred
  • PedidoPGSQL.java — deferred
  • Pedido.java VO — vlAcrescimo já existe (Story 2.3)
  • Pedido.getTotalPedidoConsulta() — retorna this.total diretamente; não altera

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
  • dbVersao incrementado para 43 (nunca pular versões; padrão linear estabelecido)
  • Thread background para SQLiteselectFull em consulta já é chamado em ThreadAbrirPedidoConsulta, padrão preservado
  • Strings sem acento em Java — este story não adiciona strings hardcoded (apenas lógica)
  • SQL por StringBuilder — padrão projeto-wide (deferred)
  • Aritmética double para monetário — padrão projeto-wide (deferred)

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

  1. Pedido com acréscimo — caminho quente (local, antes do sync)

    • Criar pedido com subtotal R$ 100,00; selecionar forma de pagamento com tx_acrescimo = 5.0
    • Salvar — verificar pedido.vl_acrescimo = 5.0 via SQLite Browser
    • Reabrir o pedido via BrowsePedido: campo "Acréscimo" = R$ 5,00; total = R$ 105,00
  2. Pedido em consulta com acréscimo — simulação de pedido histórico

    • Via ADB/SQLite Browser, UPDATE pedido_consulta SET vl_acrescimo = 10.0 WHERE id_pedido_consulta = X para um pedido conhecido
    • Abrir o pedido via BrowsePedidoConsulta
    • Verificar: status é forçado a ENVIADO; campo "Acréscimo" exibe R$ 10,00 (valor persistido, NÃO recalculado)
    • Alterar tx_acrescimo da forma de pagamento no banco para valor diferente; reabrir — "Acréscimo" continua R$ 10,00 ✓ AC 1
  3. Pedido legado em consulta — sem acréscimo

    • UPDATE pedido_consulta SET vl_acrescimo = 0 WHERE id_pedido_consulta = Y (ou deixar NULL pré-migração)
    • Abrir via BrowsePedidoConsulta: "Acréscimo" = R$ 0,00; total = subtotal; sem crash ✓ AC 2
  4. Migração v43

    • Instalar em dispositivo com app v42; verificar via adb shell pm dump ou via lint de schema que pedido_consulta.vl_acrescimo existe após primeira execução ✓ AC 3
    • Registros pré-existentes em pedido_consulta apresentam vl_acrescimo = 0 ✓ AC 3
  5. Sync PG tolerante

    • Executar comunicação — verificar que PedidoConsultaDB.saveAll() insere/atualiza com vl_acrescimo = 0 sem erro (pedidos vindos do PG têm ped.getVlAcrescimo() = 0.0 default) ✓ AC 4
  6. Instalação nova (onCreate)

    • Limpar dados do app e relançar — pedido_consulta criado com vl_acrescimo direto em onCreate() ✓ (evita regressão posterior ao mesclar onCreate/onUpgrade)

Inteligência de histórias anteriores

  • Story 1.1: padrão de migração if (oldVersion < N) em onUpgrade() + atualização de onCreate — replicado aqui
  • Story 1.2: padrão de tolerância a coluna ausente no PG — PedidoPGSQL mantém comportamento atual (não lê vl_acrescimo), sync continua sem erro
  • Story 2.1: tvAcrescimoPedido / tvAcrescimo já existem nos layouts — nenhum layout muda aqui
  • Story 2.2: cálculo vlAcrescimo = subtotal × (tx_acrescimo/100) estabelecido em MainPedidoFragment e TotalPedidoFragment; esta história envelopa esse cálculo em um guard de status
  • Story 2.3: migração v41→v42 + Pedido.vlAcrescimo + PedidoDB.insert/update/selectAllFull/selectFull — esta história segue exatamente o mesmo padrão para pedido_consulta
  • Review da Story 2.3 — deferred identificado: "fillFields() recalcula vlAcrescimo com taxa atual ao abrir pedido existente" → esta história resolve para pedidos com status >= STATUS_ENVIADO (consulta); para status < ENVIADO continua recalculando (correto para edição)

Git intelligence (commits recentes)

  • 3ff26a7 Story 2.3: vl_acrescimo em pedido + Pedido.setVlAcrescimo() + persistência em PedidoDB
  • 9b70ee3 Story 2.2: cálculo em MainPedidoFragment e TotalPedidoFragment
  • 474d98f Story 2.1: layout com tvAcrescimoPedido
  • 168b9db Story 1.2: sync formapag.acresc → tx_acrescimo
  • 4bfccc7 Story 1.1: migração v40→v41

References

  • PRD: _bmad-output/planning-artifacts/prd.md#user-journeys — Jornada 3
  • Epics: _bmad-output/planning-artifacts/epics.md#story-24-exibir-acrescimo-na-consulta-de-pedidos
  • FR12: exibir total com acréscimo em pedidos fechados que possuem o campo gravado
  • FR13: exibir pedidos sem campo de acréscimo sem alteração ou erro
  • NFR3: vl_acrescimo = NULL nunca causa NPE
  • NFR4: Migração idempotente (guard if (oldVersion < 43))
  • Deferred work: _bmad-output/implementation-artifacts/deferred-work.md

Dev Agent Record

Agent Model Used

claude-opus-4-7 (dev-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 2.4 implementada em 2026-04-16.
  • DatabaseHelper.java: dbVersao incrementado de 42 para 43. onCreate() atualizado adicionando vl_acrescimo REAL DEFAULT 0 à definição da tabela pedido_consulta (sincronia com onUpgrade). Bloco if (oldVersion < 43) adicionado em onUpgrade() executando ALTER TABLE pedido_consulta ADD COLUMN vl_acrescimo REAL DEFAULT 0;. Migração idempotente via guard. AC 3 satisfeito.
  • PedidoConsultaDB.java INSERT: coluna vl_acrescimo adicionada ao INSERT INTO pedido_consulta(...) e valor ped.getVlAcrescimo() adicionado no final da lista de valores. AC 4 satisfeito (tolerante a vlAcrescimo = 0.0 default vindo do sync PG).
  • PedidoConsultaDB.java UPDATE (updateErp): vl_acrescimo = ped.getVlAcrescimo() adicionado ao SET. Vírgula anterior ajustada em total para acomodar novo campo.
  • PedidoConsultaDB.java SELECT (selectFull): a.vl_acrescimo adicionado ao final da lista do SELECT (cursor index 66, após a.total em 65). pedido.setVlAcrescimo(c.getDouble(66)) adicionado após pedido.setTotal(c.getDouble(65)). AC 5 satisfeito.
  • MainPedidoFragment.java (fillFields linha ~439-451): guard if (Global.pedido.getStatus() >= Pedido.STATUS_ENVIADO) envolvendo o cálculo do acréscimo. Para pedidos em consulta (status >= ENVIADO), usa Global.pedido.getVlAcrescimo() persistido; para pedidos em edição, recalcula a partir de tx_acrescimo e atualiza o VO via setVlAcrescimo(). AC 1 e AC 2 satisfeitos.
  • MainPedidoFragment.java (atualizarResumoPedido linha ~984-996): mesmo guard aplicado; mesma lógica.
  • TotalPedidoFragment.java (FillFields linha ~97-108): mesmo guard aplicado. Fragment não grava no VO em branch de edição (paralelo ao comportamento pré-existente — save é gerenciado por MainPedidoFragment).
  • AC 1 satisfeito: pedidos consultados com vl_acrescimo > 0 gravado exibem o valor persistido, preservando o histórico mesmo se a tx_acrescimo for alterada futuramente no ERP.
  • AC 2 satisfeito: pedidos antigos com vl_acrescimo = 0 ou NULL exibem R$ 0,00 sem NPE (c.getDouble(66) retorna 0.0 para NULL; primitive double sem risco de NPE).
  • AC 3 satisfeito: migração v42→v43 adiciona coluna com DEFAULT 0, preservando registros existentes.
  • AC 4 satisfeito: sync PG atual entrega ped.getVlAcrescimo() = 0.0 (default do VO) — persistência aceita sem erro.
  • AC 5 satisfeito: leitura no cursor funciona com valores persistidos ou 0/NULL.
  • Sem testes automatizados: projeto não possui infraestrutura (conforme CLAUDE.md e padrão das stories anteriores). Validação manual necessária — roteiro completo em "Verificação manual após implementação".
  • Itens deferred permanecem deferred conforme escopo: PedidoPGSQL.selectAllPedConsulta (sync do acréscimo), list_browse_pedido.xml (layout da lista), PedidoConsultaDB.selectListResumo (total da lista), PedidoConsultaDB.selectTotais (agregação de vendas), MD5 change detection.

File List

  • src/br/com/jcsinformatica/sarandroid/database/DatabaseHelper.java
  • src/br/com/jcsinformatica/sarandroid/database/PedidoConsultaDB.java
  • src/br/com/jcsinformatica/sarandroid/pedido/MainPedidoFragment.java
  • src/br/com/jcsinformatica/sarandroid/pedido/TotalPedidoFragment.java

Change Log

  • 2026-04-16: Implementação da Story 2.4. Migração SQLite v42→v43 adicionando vl_acrescimo em pedido_consulta; PedidoConsultaDB lendo/escrevendo o campo; MainPedidoFragment e TotalPedidoFragment exibindo o valor persistido quando status >= STATUS_ENVIADO (preserva histórico em consulta) e recalculando quando editável.
  • 2026-04-16: Code review executado (Blind Hunter + Edge Case Hunter + Acceptance Auditor). Auditor aprovou todos os 5 ACs sem violações. 7 itens pré-existentes deferred; 8 findings dismissados como falsos positivos ou by-design.

Review Findings

  • [Review][Defer] PedidoPGSQL não inclui vl_acrescimo na sync para/de PostgreSQL [PedidoPGSQL.java] — deferred, explicitamente fora de escopo per spec; pedidos recém-sincronizados via PG terão vl_acrescimo = 0 até history future do sync PG do acréscimo
  • [Review][Defer] MD5 do pedido não inclui vl_acrescimo na hash de change-detection — deferred, explicitamente fora de escopo per spec; reavaliar junto com sync PG
  • [Review][Defer] total recalculado de itens em tempo real enquanto vl_acrescimo é congelado (status >= ENVIADO) — pré-existente; mesmo padrão que descontoV estabelecido em Story 2.3; risco de inconsistência se itens forem reprecificados após envio, mas cenário improvável em prática
  • [Review][Defer] Índice 66 do cursor hard-coded em PedidoConsultaDB.selectFull() [PedidoConsultaDB.java:296] — deferred, padrão projeto-wide pré-existente; lista de índices posicionais já é longa (4366); migrar para getColumnIndexOrThrow() em refatoração futura
  • [Review][Defer] SQL building via StringBuilder e concatenação de strings em PedidoConsultaDB.insert/updateErp [PedidoConsultaDB.java:119-147,179-184] — deferred, padrão projeto-wide pré-existente; usar PreparedStatement ou binds em refatoração maior
  • [Review][Defer] Lógica duplicada de cálculo+guard de acréscimo em MainPedidoFragment.fillFields, MainPedidoFragment.atualizarResumoPedido e TotalPedidoFragment.FillFields — deferred, padrão DRY pré-existente (já flagged em review da Story 2.2); extrair para helper em refatoração futura
  • [Review][Defer] Global.pedido sem null-check em fillFields, atualizarResumoPedido e FillFields — deferred, pré-existente em múltiplos pontos (já flagged em reviews das Stories 2.1, 2.2, 2.3); risco de NPE se fragment recriado após process kill com Global.pedido = null
  • [Review][Defer] new UpdatePedItemActivity().precoComIpi() instancia Activity fora do lifecycle Android em MainPedidoFragment.fillFields e atualizarResumoPedido — deferred, anti-padrão pré-existente (já flagged em Story 2.1)
  • [Review][Defer] Ausência de onDowngrade() em DatabaseHelper — deferred, padrão projeto-wide pré-existente; instalação de APK antigo após v43 crashará com SQLiteException; não introduzido por este diff

Review findings — dismissed (para referência, sem ação)

  • Formatação decimal dependente de locale em concatenação SQL — falso positivo: Double.toString() e + com double em Java sempre usam . como separador decimal (garantia do JLS), independente de Locale.getDefault()
  • status >= STATUS_ENVIADO incluir CANCELADO (3) e EMITIDO (4) — by-design per spec: todos os status "fechados" (não-editáveis) devem congelar o valor histórico; documentado em Dev Notes da story
  • TotalPedidoFragment não chama setVlAcrescimo no branch de edição — by-design per spec: save é gerenciado por MainPedidoFragment; duplicar persistência causaria write duplo
  • Pedidos legados sem vl_acrescimo (valor 0) exibidos como R$ 0,00 em consulta — coberto por AC 2; comportamento correto per spec
  • c.getDouble(66) com NULL — seguro: Cursor.getDouble() retorna 0.0 para NULL; ALTER TABLE ... DEFAULT 0 garante não-NULL em linhas pré-migração
  • NaN/Infinity concatenado em SQL — teórico: totalGeral × (txAcrescimo/100.0) com double bounded nunca produz NaN/Infinity em entradas válidas
  • getVlAcrescimo()/setVlAcrescimo() existência — verificado: Pedido.java:41,759-764 declara campo primitive double vlAcrescimo = 0.0 com getter/setter (Story 2.3)
  • Migração não idempotente sem IF NOT EXISTSguard if (oldVersion < 43) já garante idempotência; SQLite Android não suporta IF NOT EXISTS em ADD COLUMN de qualquer forma