30 KiB
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
-
Dado que consulto um pedido fechado (
status >= STATUS_ENVIADO) que possuivl_acrescimo > 0gravado no registro Quando a tela de detalhe do pedido (UpdatePedidoActivityviaMainPedidoFragment+TotalPedidoFragment) for exibida Então o campo "Acréscimo" exibe o valor persistido (Global.pedido.getVlAcrescimo()) — não recalculado a partir datx_acrescimoatual da forma de pagamento E o total geral exibido inclui esse acréscimo persistido (subtotal + vl_acrescimo_persistido) -
Dado que consulto um pedido fechado criado antes desta funcionalidade (sem
vl_acrescimoou comvl_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 nenhumNullPointerExceptionou crash ocorre -
Dado que a migração SQLite v42→v43 é executada em um dispositivo com
pedido_consultasemvl_acrescimoQuandoDatabaseHelper.onUpgrade()rodar Então a colunavl_acrescimo REAL DEFAULT 0é adicionada à tabelapedido_consultaE todos os registros existentes são preservados comvl_acrescimo = 0EdbVersao = 43 -
Dado que um novo pedido chega via sync PostgreSQL (
AtualizaDados.atualizaPedidosConsulta) QuandoPedidoConsultaDB.saveAll()inserir/atualizar o registro empedido_consultaEntão o valor deped.getVlAcrescimo()(0.0 por enquanto — sync PG do acréscimo é deferred) é gravado empedido_consulta.vl_acrescimosem erro E a sync segue sem interrupção mesmo que o VO chegue comvlAcrescimo = 0.0 -
Dado que
PedidoConsultaDB.selectFull()carrega um pedido Quando o cursor percorrer as colunas adicionais Entãoa.vl_acrescimoé lida epedido.setVlAcrescimo()é populado com o valor do banco (ou0.0quando a coluna é NULL)
Escopo desta história
Esta história cobre exclusivamente:
- SIM migração SQLite v42 → v43 adicionando
vl_acrescimona tabelapedido_consulta - SIM persistência em
PedidoConsultaDB.insert()eupdateErp() - SIM leitura em
PedidoConsultaDB.selectFull()— cursor index 66 (novo, adicionado ao fim) - SIM exibição correta do acréscimo persistido em
MainPedidoFragment.fillFields()eatualizarResumoPedido()quandostatus >= STATUS_ENVIADO - SIM exibição correta em
TotalPedidoFragment.FillFields()quandostatus >= 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 (verdeferred-work.md) - Alteração do layout
list_browse_pedido.xmlou do VOPedidoList— o total exibido na lista usapedido_consulta.total(já persistido no save) e permanece inalterado - Atualização de
PedidoConsultaDB.selectListResumo()—totalda lista permanece como está (deferred até sync PG carregar acréscimo) - Atualização de
PedidoConsultaDB.selectTotais()(agregação de vendas emConsultaVendasActivity) — somapeditem_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_consultaNÃO possui colunavl_acrescimo(DatabaseHelper.java:261-285) — nunca foi migrada; Story 2.3 migrou apenas a tabelapedido dbVersaoatual = 42 (DatabaseHelper.java:10)PedidoConsultaDB.insert()eupdateErp()não tocam emvl_acrescimo(PedidoConsultaDB.java:98-194)PedidoConsultaDB.selectFull()percorre índices 0..65; não lêvl_acrescimo(PedidoConsultaDB.java:196-302)ThreadAbrirPedidoConsultaforçastatus = STATUS_ENVIADOantes de abrirUpdatePedidoActivity(ThreadAbrirPedidoConsulta.java:22-24) — ou seja: todo pedido aberto via consulta chega emMainPedidoFragmentcomstatus >= STATUS_ENVIADOMainPedidoFragment.fillFields()(linha ~439-446) eatualizarResumoPedido()(linha ~979-986) recalculamvlAcrescimo = totalGeral × (txAcrescimo/100)e sobrescrevemGlobal.pedido.setVlAcrescimo(vlAcrescimo)— comportamento correto para edição, mas destrói o valor histórico em consultaTotalPedidoFragment.FillFields()(linha ~97-103) faz o mesmo recálculo — também precisa ser corrigidoPedido.vlAcrescimojá 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
dbVersaode 42 para 43 (DatabaseHelper.java:10):final static int dbVersao = 43; // era 42 - 1.2 — Adicionar bloco em
onUpgrade()ao final, após o blocoif (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 incluirvl_acrescimo REALna definição deCREATE TABLE pedido_consulta(linha ~261-285). Adicionar ao final da lista de colunas (antes dasFOREIGN KEY):+ " total REAL," + " vl_acrescimo REAL DEFAULT 0," + " FOREIGN KEY ( id_empresa ) REFERENCES empresa ( id_empresa ),"⚠️ Essencial:
onCreate+onUpgradedevem permanecer em sincronia para instalações novas vs. atualizadas.
- 1.1 — Incrementar
-
Task 2: Persistir
vl_acrescimoemPedidoConsultaDB.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
appendpara não fechar ainda e adicionar o valor:sql.append(ped.getTotalPedidoConsulta() + ", "); //total sql.append(ped.getVlAcrescimo() + ");"); //vl_acrescimoO valor virá
0.0da sync PG (getter default) enquanto a sync não carregar o campo — comportamento aceitável (AC 4).
- 2.1 — Em PedidoConsultaDB.java:119-123, adicionar
-
Task 3: Persistir
vl_acrescimoemPedidoConsultaDB.updateErp()(AC: 4)- 3.1 — Em PedidoConsultaDB.java:181-182, adicionar
vl_acrescimoao SET (antes doWHERE):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
totalatual não termina com vírgula; mudar para+ ", "ao inserir o novo campo.
- 3.1 — Em PedidoConsultaDB.java:181-182, adicionar
-
Task 4: Ler
vl_acrescimoemPedidoConsultaDB.selectFull()(AC: 5)- 4.1 — No SELECT (PedidoConsultaDB.java:211), acrescentar
a.vl_acrescimoao 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));
- 4.1 — No SELECT (PedidoConsultaDB.java:211), acrescentar
-
Task 5: Preservar
vl_acrescimohistórico emMainPedidoFragment.fillFields()(AC: 1, 2)- 5.1 — Em MainPedidoFragment.java:439-446, envolver o recálculo em um guard por status:
Substituir por:
// 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);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));
- 5.1 — Em MainPedidoFragment.java:439-446, envolver o recálculo em um guard por status:
-
Task 6: Preservar
vl_acrescimohistórico emMainPedidoFragment.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
fillFieldseatualizarResumoPedidojá deferred per review da Story 2.2).
- 6.1 — Em MainPedidoFragment.java:979-986, aplicar o mesmo padrão da Task 5:
-
Task 7: Preservar
vl_acrescimohistórico emTotalPedidoFragment.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));TotalPedidoFragmentnão chamasetVlAcrescimo— o save é gerenciado porMainPedidoFragment, então não é necessário replicar essa gravação aqui mesmo no branch de edição (manter paralelo ao comportamento pré-existente).
- 7.1 — Em TotalPedidoFragment.java:97-103, aplicar o mesmo padrão:
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 BrowsePedido → ThreadAbrirPedido → PedidoDB.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.total→pedido.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 paraa.vl_acrescimo(Story 2.3). EmPedidoConsultaDB.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_acrescimodo 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.0no VO - Tarefa 2 e 3 gravam esse
0.0sem 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 = 0exibem 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()→vlAcrescimolido depedido→ exibido corretamente - Abrir o mesmo pedido via
BrowsePedidoConsulta→PedidoConsultaDB.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 permanecePedidoList.java(VO do adapter) — permanece com sótotalSimpleArrayAdapterPedidoBrowser.java— exibetotalcomo antesPedidoConsultaDB.selectListResumo()— deferred (ver seção Escopo)PedidoConsultaDB.selectTotais()— deferredPedidoPGSQL.java— deferredPedido.javaVO —vlAcrescimojá existe (Story 2.3)Pedido.getTotalPedidoConsulta()— retornathis.totaldiretamente; 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
dbVersaoincrementado para 43 (nunca pular versões; padrão linear estabelecido)- Thread background para SQLite —
selectFullem consulta já é chamado emThreadAbrirPedidoConsulta, 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
doublepara monetário — padrão projeto-wide (deferred)
Verificação manual após implementação
-
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.0via SQLite Browser - Reabrir o pedido via
BrowsePedido: campo "Acréscimo" = R$ 5,00; total = R$ 105,00
- Criar pedido com subtotal R$ 100,00; selecionar forma de pagamento com
-
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 = Xpara 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_acrescimoda forma de pagamento no banco para valor diferente; reabrir — "Acréscimo" continua R$ 10,00 ✓ AC 1
- Via ADB/SQLite Browser,
-
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
-
Migração v43
- Instalar em dispositivo com app v42; verificar via
adb shell pm dumpou via lint de schema quepedido_consulta.vl_acrescimoexiste após primeira execução ✓ AC 3 - Registros pré-existentes em
pedido_consultaapresentamvl_acrescimo = 0✓ AC 3
- Instalar em dispositivo com app v42; verificar via
-
Sync PG tolerante
- Executar comunicação — verificar que
PedidoConsultaDB.saveAll()insere/atualiza comvl_acrescimo = 0sem erro (pedidos vindos do PG têmped.getVlAcrescimo() = 0.0default) ✓ AC 4
- Executar comunicação — verificar que
-
Instalação nova (onCreate)
- Limpar dados do app e relançar —
pedido_consultacriado comvl_acrescimodireto emonCreate()✓ (evita regressão posterior ao mesclar onCreate/onUpgrade)
- Limpar dados do app e relançar —
Inteligência de histórias anteriores
- Story 1.1: padrão de migração
if (oldVersion < N)emonUpgrade()+ atualização deonCreate— replicado aqui - Story 1.2: padrão de tolerância a coluna ausente no PG —
PedidoPGSQLmantém comportamento atual (não lêvl_acrescimo), sync continua sem erro - Story 2.1:
tvAcrescimoPedido/tvAcrescimojá existem nos layouts — nenhum layout muda aqui - Story 2.2: cálculo
vlAcrescimo = subtotal × (tx_acrescimo/100)estabelecido emMainPedidoFragmenteTotalPedidoFragment; 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 parapedido_consulta - Review da Story 2.3 — deferred identificado: "
fillFields()recalculavlAcrescimocom taxa atual ao abrir pedido existente" → esta história resolve para pedidos comstatus >= STATUS_ENVIADO(consulta); para status < ENVIADO continua recalculando (correto para edição)
Git intelligence (commits recentes)
3ff26a7Story 2.3:vl_acrescimoempedido+Pedido.setVlAcrescimo()+ persistência emPedidoDB9b70ee3Story 2.2: cálculo emMainPedidoFragmenteTotalPedidoFragment474d98fStory 2.1: layout comtvAcrescimoPedido168b9dbStory 1.2: sync formapag.acresc → tx_acrescimo4bfccc7Story 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 = NULLnunca 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:dbVersaoincrementado de 42 para 43.onCreate()atualizado adicionandovl_acrescimo REAL DEFAULT 0à definição da tabelapedido_consulta(sincronia comonUpgrade). Blocoif (oldVersion < 43)adicionado emonUpgrade()executandoALTER TABLE pedido_consulta ADD COLUMN vl_acrescimo REAL DEFAULT 0;. Migração idempotente via guard. AC 3 satisfeito.PedidoConsultaDB.javaINSERT: colunavl_acrescimoadicionada aoINSERT INTO pedido_consulta(...)e valorped.getVlAcrescimo()adicionado no final da lista de valores. AC 4 satisfeito (tolerante avlAcrescimo = 0.0default vindo do sync PG).PedidoConsultaDB.javaUPDATE (updateErp):vl_acrescimo = ped.getVlAcrescimo()adicionado ao SET. Vírgula anterior ajustada emtotalpara acomodar novo campo.PedidoConsultaDB.javaSELECT (selectFull):a.vl_acrescimoadicionado ao final da lista do SELECT (cursor index 66, apósa.totalem 65).pedido.setVlAcrescimo(c.getDouble(66))adicionado apóspedido.setTotal(c.getDouble(65)). AC 5 satisfeito.MainPedidoFragment.java(fillFieldslinha ~439-451): guardif (Global.pedido.getStatus() >= Pedido.STATUS_ENVIADO)envolvendo o cálculo do acréscimo. Para pedidos em consulta (status >= ENVIADO), usaGlobal.pedido.getVlAcrescimo()persistido; para pedidos em edição, recalcula a partir detx_acrescimoe atualiza o VO viasetVlAcrescimo(). AC 1 e AC 2 satisfeitos.MainPedidoFragment.java(atualizarResumoPedidolinha ~984-996): mesmo guard aplicado; mesma lógica.TotalPedidoFragment.java(FillFieldslinha ~97-108): mesmo guard aplicado. Fragment não grava no VO em branch de edição (paralelo ao comportamento pré-existente — save é gerenciado porMainPedidoFragment).- AC 1 satisfeito: pedidos consultados com
vl_acrescimo > 0gravado exibem o valor persistido, preservando o histórico mesmo se atx_acrescimofor alterada futuramente no ERP. - AC 2 satisfeito: pedidos antigos com
vl_acrescimo = 0ou 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.javasrc/br/com/jcsinformatica/sarandroid/database/PedidoConsultaDB.javasrc/br/com/jcsinformatica/sarandroid/pedido/MainPedidoFragment.javasrc/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_acrescimoempedido_consulta;PedidoConsultaDBlendo/escrevendo o campo;MainPedidoFragmenteTotalPedidoFragmentexibindo o valor persistido quandostatus >= 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_acrescimona sync para/de PostgreSQL [PedidoPGSQL.java] — deferred, explicitamente fora de escopo per spec; pedidos recém-sincronizados via PG terãovl_acrescimo = 0até history future do sync PG do acréscimo - [Review][Defer] MD5 do pedido não inclui
vl_acrescimona hash de change-detection — deferred, explicitamente fora de escopo per spec; reavaliar junto com sync PG - [Review][Defer]
totalrecalculado de itens em tempo real enquantovl_acrescimoé congelado (status >= ENVIADO) — pré-existente; mesmo padrão quedescontoVestabelecido 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 (43–66); migrar paragetColumnIndexOrThrow()em refatoração futura - [Review][Defer] SQL building via
StringBuildere concatenação de strings emPedidoConsultaDB.insert/updateErp[PedidoConsultaDB.java:119-147,179-184] — deferred, padrão projeto-wide pré-existente; usarPreparedStatementou binds em refatoração maior - [Review][Defer] Lógica duplicada de cálculo+guard de acréscimo em
MainPedidoFragment.fillFields,MainPedidoFragment.atualizarResumoPedidoeTotalPedidoFragment.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.pedidosem null-check emfillFields,atualizarResumoPedidoeFillFields— 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 comGlobal.pedido = null - [Review][Defer]
new UpdatePedItemActivity().precoComIpi()instancia Activity fora do lifecycle Android emMainPedidoFragment.fillFieldseatualizarResumoPedido— deferred, anti-padrão pré-existente (já flagged em Story 2.1) - [Review][Defer] Ausência de
onDowngrade()emDatabaseHelper— deferred, padrão projeto-wide pré-existente; instalação de APK antigo após v43 crashará comSQLiteException; 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+comdoubleem Java sempre usam.como separador decimal (garantia do JLS), independente deLocale.getDefault() status >= STATUS_ENVIADOincluir 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 storyTotalPedidoFragmentnão chamasetVlAcrescimono branch de edição — by-design per spec: save é gerenciado porMainPedidoFragment; 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()retorna0.0para NULL;ALTER TABLE ... DEFAULT 0garante não-NULL em linhas pré-migraçãoNaN/Infinityconcatenado em SQL — teórico:totalGeral × (txAcrescimo/100.0)comdoublebounded nunca produz NaN/Infinity em entradas válidasgetVlAcrescimo()/setVlAcrescimo()existência — verificado:Pedido.java:41,759-764declara campo primitivedouble vlAcrescimo = 0.0com getter/setter (Story 2.3)- Migração não idempotente sem
IF NOT EXISTS— guardif (oldVersion < 43)já garante idempotência; SQLite Android não suportaIF NOT EXISTSemADD COLUMNde qualquer forma