Files
sar-android/_bmad-output/implementation-artifacts/2-3-persistir-acrescimo-ao-fechar-o-pedido.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

17 KiB
Raw Blame History

Story 2.3: Persistir Acréscimo ao Fechar o Pedido

Status: done

Story

Como sistema, quero gravar o valor do acréscimo calculado no registro do pedido ao fechar, para que o valor histórico seja preservado independente de alterações futuras na taxa.

Acceptance Criteria

  1. Dado que um pedido foi editado com acréscimo R$ 87,50 e total R$ 3.587,50 Quando o pedido for salvo/fechado Então o valor do acréscimo (87,50) está gravado no registro do pedido no SQLite (vl_acrescimo = 87.50)

  2. Dado que um pedido foi salvo com acréscimo Quando a taxa de acréscimo da forma de pagamento for alterada no ERP e sincronizada Então o valor gravado no pedido antigo permanece inalterado (somente um novo salvar() atualizaria)

  3. Dado que um pedido é criado com forma de pagamento sem acréscimo Quando o pedido for salvo Então o acréscimo gravado é 0,00 (vl_acrescimo = 0.0)

Escopo desta história

Esta história cobre exclusivamente a persistência do vl_acrescimo calculado no banco SQLite.

  • NÃO modifica a lógica de cálculo exibido na UI — cálculo já foi implementado na Story 2.2
  • NÃO implementa exibição do acréscimo em consultas — esse é escopo da Story 2.4
  • SIM adiciona migração de schema SQLite v41 → v42 (nova coluna vl_acrescimo em pedido)
  • SIM atualiza o VO Pedido, o PedidoDB (insert/update/select) e o MainPedidoFragment (salvar)

Pré-condição verificada

A tabela pedido NÃO possui colunas para acréscimo. Constatado via inspeção de:

  • DatabaseHelper.onCreate() — schema original sem vl_acrescimo
  • PedidoDB.insert() e update() — sem vl_acrescimo nas queries
  • Pedido.java — sem campo vlAcrescimo
  • dbVersao atual = 41 (última migração adicionou tx_acrescimo à tabela formapag)

Esta história inclui a adição da coluna via migração v42.

Tasks / Subtasks

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

    • 1.1 — Incrementar dbVersao de 41 para 42:
      // Linha ~10 de DatabaseHelper.java
      private static final int dbVersao = 42; // era 41
      
    • 1.2 — Adicionar bloco de migração em onUpgrade() (após o bloco if (oldVersion < 41)):
      if (oldVersion < 42) {
          db.execSQL("ALTER TABLE pedido ADD COLUMN vl_acrescimo REAL DEFAULT 0;");
      }
      
  • Task 2: Adicionar campo vlAcrescimo ao VO Pedido.java (AC: 1, 2, 3)

    • 2.1 — Adicionar campo privado após a declaração de total (linha ~40):
      private double vlAcrescimo = 0.0;
      
    • 2.2 — Adicionar getter e setter (junto aos demais getters/setters do VO):
      public double getVlAcrescimo() {
          return vlAcrescimo;
      }
      
      public void setVlAcrescimo(double vlAcrescimo) {
          this.vlAcrescimo = vlAcrescimo;
      }
      
  • Task 3: Popular vlAcrescimo em Global.pedido durante cálculo em MainPedidoFragment.java (AC: 1, 2, 3)

    • 3.1 — Em atualizarResumoPedido() (linha ~974), após a linha tvAcrescimoPedido.setText(...), adicionar:
      Global.pedido.setVlAcrescimo(vlAcrescimo);
      
      O bloco completo resultante ficará:
      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); // ← ADICIONADO
      
    • 3.2 — Em fillFields() (linha ~439), mesmo padrão — após tvAcrescimoPedido.setText(...), adicionar:
      Global.pedido.setVlAcrescimo(vlAcrescimo);
      
  • Task 4: Persistir vl_acrescimo em PedidoDB.java — INSERT (AC: 1, 3)

    • 4.1 — Em insert(), na lista de colunas (linha ~89), acrescentar , vl_acrescimo após total:
      sql.append(" desconto_v, total, vl_acrescimo");
      
    • 4.2 — Na lista de valores (linha ~110), acrescentar , ped.getVlAcrescimo() após ped.getTotal():
      sql.append(ped.getTotal() + ", ");
      sql.append(ped.getVlAcrescimo() + ");");
      
  • Task 5: Persistir vl_acrescimo em PedidoDB.java — UPDATE (AC: 1, 2, 3)

    • 5.1 — Em update(), após a linha de total (linha ~150), adicionar:
      sql.append(",");
      sql.append("        vl_acrescimo  = ").append(ped.getVlAcrescimo());
      
      O final do UPDATE ficará:
      sql.append("        total         = ").append(ped.getTotal());
      sql.append(",");
      sql.append("        vl_acrescimo  = ").append(ped.getVlAcrescimo());
      sql.append("  WHERE id_pedido     = " + ped.getId() + ";");
      
  • Task 6: Ler vl_acrescimo em PedidoDB.selectAllFull() (necessário para Story 2.4) (AC: 1, 2)

    • 6.1 — Na construção do SELECT (linha ~204), adicionar a.vl_acrescimo ao final:
      sql.append(" a.cod_liberacao, a.desconto_v, b.st_especifica, a.total, c.desco_perc, b.desc_cliente_rede, a.vl_acrescimo");
      
      Resultado: a.vl_acrescimo é o índice 68 do cursor. Atualizado em ambos os métodos selectAllFull() (lista e por id).
    • 6.2 — No loop de leitura do cursor (após cli.setDesc_cliente_rede(c.getInt(67))), adicionado:
      pedido.setVlAcrescimo(c.getDouble(68));
      
      Atualizado em ambos os métodos selectAllFull().

Dev Notes

Estrutura atual do pedido — schema SQLite (sem vl_acrescimo)

CREATE TABLE pedido (
    id_pedido INTEGER PRIMARY KEY AUTOINCREMENT,
    ...
    desconto_v REAL,
    total      REAL
    -- vl_acrescimo ainda NÃO existe (será adicionada pela migração v42)
)

Pedido.getTotal() é COMPUTADO, não armazenado

Atenção crítica: getTotal() em Pedido.java (linha ~750) é um método computado:

public double getTotal() {
    return (getTotalProduto() - getTotalDesconto()) + getTotalIcmsST();
}

O setTotal(double total) existe mas NÃO afeta getTotal() — o getter sempre recomputa a partir dos itens. Por isso, PedidoDB.insert() usa ped.getTotal() que é o subtotal dos produtos sem acréscimo. O vl_acrescimo é um valor independente que precisa de campo próprio no VO e na tabela.

A abordagem adotada é: Global.pedido.vlAcrescimo é atualizado toda vez que o cálculo da UI é executado, mantendo-o sempre sincronizado com o valor exibido. No momento do pedDB.salvar(), o valor já está pronto em Global.pedido.getVlAcrescimo().

Isso evita recalcular vlAcrescimo no onClick() do botão salvar — que seria:

  • Duplicação de lógica
  • Risco de divergência com o valor exibido (e.g., diferença no tratamento de IPI via !precoComIpi)

O totalGeral local em atualizarResumoPedido() inclui IPI condicionalmente, enquanto Global.pedido.getTotal() não inclui IPI. Calcular no onClick() exigiria replicar toda a lógica com IPI. Usar o valor já calculado e armazenado no VO é mais seguro.

Fluxo de salvar — ponto exato de chamada

MainPedidoFragment.java, método onClick(), seção de sucesso da validação (linha ~549554):

// Estado ATUAL após Story 2.2:
if (erro == null) {
    PedidoDB pedDB = new PedidoDB();
    try {
        Global.pedido.setObservacao(etObservacao.getText().toString());
        Global.pedido.setDescontoV(Global.pedido.getTotalDesconto()); // linha 553
        pedDB.salvar(getActivity().getApplicationContext(), Global.pedido); // linha 554
        Global.pedido = null;
        getActivity().finish();
    } catch (Exception e) {
        Util.sendError(getActivity(), e);
    }
}

Global.pedido.vlAcrescimo será populado ANTES de pedDB.salvar() via Task 3 (chamado em atualizarResumoPedido() / fillFields() durante a edição). Nenhuma alteração é necessária no onClick().

Mapeamento de índices em selectAllFull() — cuidado com offset

Índices atuais do cursor em selectAllFull() (linha ~204 até ~291):

  • 0..1: A.id_pedido, A.id_empresa
  • ...
  • 62: a.cod_liberacao
  • 63: a.desconto_v
  • 64: b.st_especifica
  • 65: a.totalpedido.setTotal(c.getDouble(65))
  • 66: c.desco_percpedido.getFormapag().setDescontoPerc(c.getDouble(66))
  • 67: b.desc_cliente_redecli.setDesc_cliente_rede(c.getInt(67))
  • 68: a.vl_acrescimo ← ADICIONAR com pedido.setVlAcrescimo(c.getDouble(68))

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

Null-safety e pedidos legados

A coluna vl_acrescimo REAL DEFAULT 0 garante que pedidos já existentes no dispositivo (criados antes desta migração) terão vl_acrescimo = 0.0 automaticamente — sem necessidade de backfill manual.

Quando lidos pelo selectAllFull(), pedido.setVlAcrescimo(c.getDouble(68)) retornará 0.0 para pedidos antigos — comportamento correto para AC3.

Migração idempotente

O guard if (oldVersion < 42) em onUpgrade() garante que a migração não seja executada mais de uma vez, mesmo em atualizações encadeadas (e.g., v40→v42 executa os blocos v41 e v42 na sequência correta).

Arquivos a modificar

Arquivo Caminho O que muda
DatabaseHelper.java src/br/com/jcsinformatica/sarandroid/database/ dbVersao = 42, migration block v42
Pedido.java src/br/com/jcsinformatica/sarandroid/vo/ Campo vlAcrescimo, getter/setter
MainPedidoFragment.java src/br/com/jcsinformatica/sarandroid/pedido/ setVlAcrescimo() em atualizarResumoPedido() e fillFields()
PedidoDB.java src/br/com/jcsinformatica/sarandroid/database/ INSERT, UPDATE e selectAllFull()

NÃO modificar nesta história:

  • TotalPedidoFragment.java — sem persistência aqui; save só ocorre via MainPedidoFragment
  • FormaPagamento.java / FormaPagamentoDB.java — inalterados
  • UpdatePedidoActivity.java — apenas container de ViewPager, sem lógica de save
  • Layouts XML — sem mudança de UI nesta história
  • PedidoPGSQL.java (se existir) — sync com PostgreSQL é escopo separado

Regras críticas do projeto (aplicáveis a esta história)

  • Sem Kotlin — somente Java puro
  • Sem Gradle — projeto Eclipse ADT, sem build.gradle
  • Sem JARs novos — sem dependências adicionais
  • Sem testes automatizados — o projeto não possui infraestrutura de testes; validação manual via dispositivo/emulador
  • dbVersao deve ser incrementado para 42 — nunca pular versões
  • Thread background para SQLitesalvar() em MainPedidoFragment já é chamado na UI thread (dentro de onClick()), mas o padrão do projeto aceita isso para writes pontuais; a leitura em selectAllFull() é gerenciada pelo chamador
  • Strings com acentos — NÃO usar em código Java (sem "Acréscimo" em strings hard-coded em Java)

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

  1. Criar pedido com itens, selecionar forma de pagamento com tx_acrescimo > 0, salvar
  2. Via SQLite Browser (ou adb shell), verificar na tabela pedido que vl_acrescimo contém o valor correto
  3. Alterar tx_acrescimo da forma de pagamento diretamente no banco SQLite (simulando sync do ERP)
  4. Reabrir o pedido salvo — verificar que vl_acrescimo no registro do pedido NÃO mudou (AC2)
  5. Criar pedido com forma de pagamento sem acréscimo, salvar — verificar vl_acrescimo = 0 (AC3)
  6. Verificar que dbVersao no DatabaseHelper é 42 e que a migração foi aplicada sem erro

Inteligência de histórias anteriores

  • Story 1.1 migrou formapag v40→v41; o padrão de migração if (oldVersion < N) em onUpgrade() deve ser replicado aqui para v42
  • Story 1.2 adicionou tx_acrescimo a FormaPagamento VO com getter getTxAcrescimo() — campo utilizado aqui para calcular vlAcrescimo antes de persistir
  • Story 2.1 adicionou campos de UI (tvAcrescimoPedido, tvAcrescimo) — nenhuma alteração de UI nesta história
  • Story 2.2 implementou o cálculo de vlAcrescimo em atualizarResumoPedido() e fillFields() — esta história apenas adiciona Global.pedido.setVlAcrescimo(vlAcrescimo) nesses dois pontos já existentes
  • Review da Story 2.2 identificou: codigoLiberacao2() computa hash sobre totalGeral sem acréscimo — esse comportamento permanece inalterado nesta história (deferred)
  • Review da Story 2.2 identificou: validaCampos() usa getTotalProduto() para limite de crédito e pedido mínimo, excluindo acréscimo — permanece deferred

Git intelligence (commits recentes)

  • 9b70ee3 Story 2.2: cálculo em MainPedidoFragment.atualizarResumoPedido(), fillFields(), TotalPedidoFragment.FillFields()
  • 474d98f Story 2.1: campos tvAcrescimoPedido e tvAcrescimo adicionados ao layout e vinculados
  • 168b9db Story 1.2: FormaPagamentoDB lendo tx_acrescimo; FormaPagamento com getter
  • 4bfccc7 Story 1.1: migração v40→v41 em DatabaseHelper.onUpgrade()

Review Findings

  • [Review][Defer] PedidoPGSQL não inclui vl_acrescimo na sync para PostgreSQL [PedidoPGSQL.java] — deferred, out of scope per spec; escopo de story futura de sincronização PG
  • [Review][Defer] fillFields() recalcula vlAcrescimo com tx_acrescimo atual, sobrescrevendo valor carregado do BD ao abrir pedido existente [MainPedidoFragment.java:443-446] — deferred, by-design; AC2 cobre sync automático, não re-salvamento explícito pelo usuário; consistente com comportamento de descontoV
  • [Review][Defer] MD5 do pedido não inclui vl_acrescimo na hash de change-detection — deferred, impacto futuro; PG ainda não tem a coluna; reavaliar quando PedidoPGSQL for atualizado
  • [Review][Defer] Índice 59 do cursor lê DATE(D.data_inicio) em vez de C.md5 para FormaPagamento.setMd5() [PedidoDB.java:269,392] — deferred, pré-existente não introduzido por este diff
  • [Review][Defer] Concatenação de string para SQL em vez de PreparedStatement [PedidoDB.java:85-153] — deferred, padrão projeto-wide pré-existente
  • [Review][Defer] Global.pedido sem null-check antes de setVlAcrescimo() [MainPedidoFragment.java:446,986] — deferred, pré-existente; mesmo padrão já deferred na Story 2.2
  • [Review][Defer] Aritmética de ponto flutuante (double) para valor monetário vl_acrescimo — deferred, padrão projeto-wide pré-existente; Util.formataValorMonetario() já trata formatação

Dev Agent Record

Agent Model Used

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

Debug Log References

Completion Notes List

  • Story 2.3 implementada em 2026-04-16.
  • DatabaseHelper.java: dbVersao incrementado de 41 para 42. Bloco de migração if (oldVersion < 42) adicionado em onUpgrade(), adicionando vl_acrescimo REAL DEFAULT 0 à tabela pedido. Migração idempotente via guard.
  • Pedido.java: campo private double vlAcrescimo = 0.0 adicionado após total. Getter getVlAcrescimo() e setter setVlAcrescimo(double) adicionados.
  • MainPedidoFragment.java: Global.pedido.setVlAcrescimo(vlAcrescimo) adicionado em dois pontos — após cálculo em fillFields() (linha ~446) e em atualizarResumoPedido() (linha ~986). O valor gravado no VO é exatamente o valor exibido na UI (sem recalcular no onClick()), evitando divergência de IPI.
  • PedidoDB.java INSERT: coluna vl_acrescimo adicionada ao INSERT INTO pedido(...) e valor ped.getVlAcrescimo() adicionado na lista de valores.
  • PedidoDB.java UPDATE: vl_acrescimo = ped.getVlAcrescimo() adicionado ao SET do UPDATE.
  • PedidoDB.java SELECT: a.vl_acrescimo adicionado ao SELECT em ambos os métodos selectAllFull() (lista e por id); pedido.setVlAcrescimo(c.getDouble(68)) adicionado após leitura do índice 67 em ambos.
  • AC1 satisfeito: vl_acrescimo é gravado na tabela pedido ao salvar (via INSERT ou UPDATE).
  • AC2 satisfeito: vl_acrescimo só é atualizado no banco quando pedDB.salvar() é chamado explicitamente — mudanças de tx_acrescimo na forma de pagamento não afetam pedidos já salvos.
  • AC3 satisfeito: vlAcrescimo inicializa em 0.0; forma de pagamento sem acréscimo resulta em vlAcrescimo = 0.0 * 0 = 0.0 gravado.
  • Sem testes automatizados (projeto não possui infraestrutura de testes). Validação manual via dispositivo/emulador.

File List

  • src/br/com/jcsinformatica/sarandroid/database/DatabaseHelper.java
  • src/br/com/jcsinformatica/sarandroid/vo/Pedido.java
  • src/br/com/jcsinformatica/sarandroid/pedido/MainPedidoFragment.java
  • src/br/com/jcsinformatica/sarandroid/database/PedidoDB.java