Files
DeskcommCRM/docs/stories/epics
rafaelbatistazzandClaude Opus 5 ab59e0a7fd chore(settings): "Motivos de perda extras" sai da aba Organização
O campo gravava `organizations.settings.lost_reasons_extra` e NINGUÉM lia essa
chave. Quem decide se um motivo passa é `fn_validate_lost_reason_required`, e
ele aceita canônico ∪ `crm_pipelines.settings.lost_reasons`; quem monta a janela
de perder é `useMotivosDePerdaDoFunil`, que lê o settings do FUNIL. Medido no
upstream/main: o literal só aparece nas três telas de configuração, nos schemas,
nos testes e — no `baseline.sql` — dentro de um `comment on function`. Nenhuma
rota devolve a chave: a única que faz `select("settings")` de `organizations`
(`/api/v1/ai/providers`) lê `settings.llm` e escreve por merge.

O efeito era pior do que não ter o campo. Quem cadastrava ali não via os motivos
na hora de perder, digitava à mão em "Outro" e recebia `internal_error` — o
trigger recusando com 22023 um texto que a tela dissera aceitar, sem nada na
interface ligando uma coisa à outra.

`docs/testing/user-journey-map.md` (J4.40) já registrava o defeito e deixava a
saída em aberto: o trigger unir organização ∪ funil, ou o campo sair. Este
commit toma a segunda. Motivo de perda é vocabulário do FUNIL — é nele que o
relatório de perdas agrupa — e manter dois campos quase homônimos, um que vale
e um que não, custa mais do que o alcance por organização entrega. A outra
saída continua disponível: nada é apagado do banco.

- A action deixa de escrever `settings` por completo. Ela lia o jsonb inteiro,
  espalhava em memória e regravava o objeto — o padrão que a migration 0157
  documenta como perda silenciosa entre escritores concorrentes. Um escritor a
  menos nesse jsonb, de brinde.
- O dado já gravado FICA na linha, intocado. Sem migration, sem backfill.
- As três frases saem do dicionário e do catálogo zh-CN junto com a tela.

Teste: `lib/schemas/settings.test.ts` troca o caso que exigia o default pelo que
exige a AUSÊNCIA da chave no parse — é ele que impede a action de voltar a
gravá-la sem ninguém notar. Sabotagem medida: reinserindo o campo em
`tenantSchema`, 1 vermelho de 13, o previsto. (Na primeira tentativa a
reinserção caiu noutro schema do mesmo arquivo e o teste seguiu verde, o que é
o comportamento correto: ele guarda `tenantSchema`, não o arquivo.)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-18 19:44:50 +00:00
..