Skip to main content

Resultado inicial — Spike 198299

Título SP: zzapp — Avaliar a possibilidade de a data de expiração ser opcional nas vitrines
Workitem: 198299
Data: 2026-07-09
Tipo de entrega: Plano de implementação (sem alteração de código de produto)

Índice de contexto

DocConteúdo
context/sp.mdSP e critérios de aceite
context/CONTEXT.mdGlossário de domínio
context/AS-IS.mdCRUD AS-IS completo
context/grill-decisions.mdDecisões D1–D8
context/impacto-repos.mdMatriz de impacto detalhada
context/research-showcase-api.mdAPI showcase
context/research-zzapp.mdApp vendedor
context/research-portal.mdPortal marca (referência)
context/research-showcase-web.mdFront público
context/research-jobs.mdJobs

1. Resposta da Spike: é possível?

Sim — viável com baixo risco estrutural.

Motivos:

  1. O serviço de vitrines já implementa “sem data de expiração” para vitrine da marca (DateTime.MaxValue no Elasticsearch; UI portal com placeholder “Sem data de expiração”).
  2. Vitrines de vendedor (Store e Recommendation) usam o mesmo campo DateExpiration e os mesmos filtros de “ativa”.
  3. Não há job que force expiração de Store/Recommend; mudar o valor de DateExpiration basta para o comportamento de listagem e link público.
  4. O zzapp já tem suporte parcial de UI (nullExpirationLabel em listas de recommend/marca).

Principal cuidado: hoje null na Store significa “aplicar default +31”, não “sem prazo”. A US precisa inverter essa semântica (null → never) e colocar o default na UI, alinhado ao CA-2.


2. Interpretação dos critérios de aceite (TO-BE)

CAInterpretação operacional
CA-1Campo data de expiração não obrigatório em create/edit de Minhas e Histórico (não marca).
CA-2Ao criar, UI preenche prazo padrão atual (~+31 no código / “+30” na SP). Usuário pode limpar. Limpar não reaplica default no backend. Se preencher data, respeitar teto (~30/31 dias).
CA-3Em edit: adicionar, alterar ou remover data (remover = sem expiração).
CA-4Listagem e detalhe: se sem data → texto "Sem data de expiração" no lugar da data.
CA-5Estoque, preço, disponibilidade (jobs de produto), compartilhamento de links e demais regras inalterados.

Escopo de menu (SP): Minhas vitrines + Vitrine por histórico. Fora: Vitrine da marca (zzportal).


3. AS-IS em uma página

  • 4 tipos de vitrine no ES; SP mexe em 2 (Store, Recommendation).
  • Persistência: Elasticsearch; soft-delete DateDeleted; expiração por data no documento.
  • Store: create aceita DateTime? mas null → +31d.
  • Recommend: data obrigatória (FluentValidation + UI).
  • Brand: null → MaxValue (precedente).
  • Jobs: status só de marca; product sync não expira vitrine.
  • showcase-web: sem conceito de expiração; sumiu do API = “não encontrada”.

Detalhe: context/AS-IS.md.


4. Decisões de desenho (resumo)

#Decisão
D1“Sem expiração” = DateTime.MaxValue no ES; null na API/UI
D2Escopo Store + Recommend
D3Manter +31 numérico AS-IS; alinhar texto “+30” com PO
D4Default na UI; clear → never (sem re-default no server)
D5Reativar expiradas: fora do MVP
D6Unicidade Recommend inclui never-expire como ativa
D7Portal / web / jobs sem mudança de CA
D8Plano de US inclui cap no backend se data informada

Detalhe: context/grill-decisions.md.


5. Serviços, módulos e repos impactados

RepoPrecisa alterar?Módulos
coezzion-service-showcaseSimDomain (ElasticBaseIndex / ShowCaseModel), Commands Store + Recommend, Validators Recommend, mapeamento DTO MaxValue→null, unit tests
coezzion_vendas_appSimlib/screens/show_case/** (minhas + recommend), models create/update/list, date field clearable
coezzion-portalNãoReferência UX apenas
coezzion-showcase-webNão
coezzion-service-jobsNãoProduct jobs permanecem (CA-5)

Arquivos e PRs: context/impacto-repos.md.


6. Plano de implementação (US futura)

Fase 0 — Produto (curto)

  • Confirmar com PO: 30 vs 31 dias (default e máximo).
  • Confirmar copy exata: "Sem data de expiração" (já usada no app/portal).
  • Confirmar D1 MaxValue (recomendado; padrão marca).

Fase 1 — API (coezzion-service-showcase) — PR1

  1. Definir helper de normalização (idealmente compartilhado com Brand):
    • nullDateTime.MaxValue (sem expiração)
    • data → validar futura + opcional max N dias
  2. Store: alterar SetDateExpiration / create-update para não converter null em +31.
  3. Recommend: DateTime? nos commands; validators opcionais; handler grava MaxValue se null.
  4. Em todos DTOs Store/Recommend de leitura: MaxValuenull.
  5. Testes unitários: null=never; data válida; data passada falha; max falha; unicidade com MaxValue.
  6. Garantir que filtros ES existentes continuam incluindo MaxValue como ativo.

Contrato a publicar para o app:

Request dateExpiration:
- <iso-date> = expira nessa data
- null / omitido com semântica never = sem expiração (preferir null explícito)
Response dateExpiration:
- null = sem data de expiração
- <iso-date> = data

Default +N não deve ser responsabilidade silenciosa do server se null = never. UI envia a data default quando o usuário não limpa.

Fase 2 — zzapp (coezzion_vendas_app) — PR2

  1. Minhas: picker clearable; default +N; create/update enviam null se limpo.
  2. Models: update e list item com dateExpiration nullable.
  3. List/detail: label CA-4.
  4. Histórico: remover bloqueio obrigatório; clearable; max no edit; default create.
  5. Testes de serialização null.
  6. Smoke manual create/edit/share.

Fase 3 — Não-código de outros repos

  • Portal / web / jobs: sem PR, só checklist de não-regressão.

Fase 4 — QA

Ver seção 8.

Ordem

Fase 0 (PO) → PR1 API → PR2 App (ou paralelo com contrato fixo) → QA

7. Riscos e mitigações

RiscoMitigação
Null no ES some da listagemNunca persistir null; usar MaxValue
Server ainda aplica +31 em nullRemover essa coerção; testes de regressão
MaxValue aparece como ano 9999 na UIMapear sempre MaxValue→null nos DTOs
30 vs 31 gera bug de “máximo”Constante única documentada; alinhar PO
Recommend “prende” cliente para sempreDocumentar unicidade; vendedor pode editar/excluir
Mudança quebra BrandNão alterar paths Brand; helper compartilhado com cuidado
App antigo envia null esperando +31Coordenar deploy API+app; se necessário feature flag ou aceitar mudança de contrato (avaliar clientes da API)

Clientes da API Store create: principal é zzapp. Validar se há outros consumers (BFF, scripts) antes do merge.


8. Critérios de verificação (pós-implementação)

Funcional

  • Criar Minhas sem limpar data → tem dateExpiration ~+N; some da lista após N dias (ou data forçada em QA).
  • Criar Minhas limpando data → lista/detalhe “Sem data de expiração”; GET público ok após N dias.
  • Editar: alterar data; remover data; recolocar data.
  • Mesmos cenários em Histórico.
  • Segunda Recommend ativa mesmo CPF bloqueada se a primeira é never-expire.
  • Vitrine da marca no portal inalterada.
  • Link público de never-expire abre produtos; estoque/preço coerentes após job de produto (CA-5).
  • Share/copy de link continua funcionando.

Técnico

  • Unit tests API verdes.
  • Documento ES de never-expire contém dateExpiration = MaxValue (inspecionar em QA).
  • Response JSON nunca devolve data “9999…” para o app.

9. Fora de escopo (explícito)

  • Alterar regras de vitrine da marca / portal.
  • UX de expiração no showcase-web (“expirou em…”).
  • Job de notificação “vai expirar”.
  • Listar/reativar vitrines já expiradas no app.
  • Migração em massa de vitrines existentes para never-expire.
  • Hard-delete de documentos expirados no ES.

10. Estimativa relativa (ordem de grandeza)

FatiaEsforço relativo
API Store + Recommend + testsM
zzapp Minhas + Recommend UIM
QA manual / alinhamento POS
Jobs / portal / web

Não é refactor amplo: reaproveita padrão Brand e widgets existentes.


11. Conclusão

PerguntaResposta
É possível?Sim
Onde mudar?showcase API + zzapp (Store + Recommend)
Padrão técnico?MaxValue + null na borda (como marca)
Jobs?Não para expiração de vendedor; product jobs só não regredir
Próximo passo?Abrir US(s) de implementação com este plano; fechar 30 vs 31 com PO

12. Histórico da Spike

QuandoO quê
2026-07-09Pesquisa multi-repo; AS-IS; decisões D1–D8; este relatório