Documento de Requisitos — Passar a receber o RecommendationsId (App)
Tarefa: #196024 Contexto: Sequência de implementação #6 Refinamento: Grill session 12/06/2026
Visão Geral
Ajustar o UpsellRecommendationController (App zzapp) para consumir o novo formato de resposta do BFF (POST bff/customer-product-recommendation/{codeStore}/{cpf}), extrair o recommendationsId retornado pelo servidor e repassá-lo ao criar o carrinho via POST api/cart.
Mudança na resposta consumida:
| Antes | Depois |
|---|---|
[ { id, name, sku, ... } ] | { recommendationsId: "...", items: [ { id, name, sku, ... } ] } |
Escopo restrito: apenas o fluxo de upsell (FLOW B) — UpsellRecommendationController. O fluxo de recomendação de produtos (ProductRecommendationProductsController, endpoint /bff/recommend-customer) não é alterado.
Papéis Envolvidos
| Papel | Responsabilidade |
|---|---|
| Desenvolvedor Front-end | Alterar deserialização da resposta e extração do recommendationsId no UpsellRecommendationController |
Requisitos Funcionais
RF-01 — Detecção do formato da resposta
História de Usuário: Como App, quero interpretar corretamente ambos os formatos de resposta do BFF, para não quebrar durante a transição entre versões do backend.
Critérios de Aceitação:
- WHEN a resposta do BFF for um
Mapcontendo a chaveitemsTHEN o sistema SHALL tratá-la como o novo formato ({ recommendationsId, items }) - WHEN a resposta do BFF for um
List(formato legado) THEN o sistema SHALL tratá-la como o formato antigo (array de itens, semrecommendationsId) - WHEN o formato for detectado como legado THEN o sistema SHALL logar um warning e gerar
recommendationsIdlocal (UUID v4) como fallback
Casos de Borda:
- Resposta
nullou string vazia"": comportamento atual mantido — limparrecommendedItems
RF-02 — Extração do recommendationsId do novo formato
História de Usuário: Como App, quero capturar o recommendationsId gerado pelo BFF, para rastrear o fluxo de upsell ponta a ponta com o identificador do servidor.
Critérios de Aceitação:
- WHEN a resposta estiver no novo formato (
Mapcom chaveitems) THEN o sistema SHALL extrairrecommendationsIddo mapa da resposta - WHEN
recommendationsIdestiver presente e não-vazio THEN o sistema SHALL armazená-lo emUpsellRecommendationController.recommendationsIde emCartDTO.recommendationsIdviaaddRecommendedItemsCached - WHEN
recommendationsIdestiver ausente ounullno mapa da resposta THEN o sistema SHALL gerarrecommendationsIdlocal (UUID v4) como fallback e logar warning - WHEN a lista
itemsestiver vazia ([]) masrecommendationsIdestiver presente THEN o sistema SHALL armazenar orecommendationsIdmesmo sem itens recomendados
Casos de Borda:
recommendationsIdcom string vazia"": tratar como ausente (fallback UUID local)
RF-03 — Deserialização dos itens no novo formato
História de Usuário: Como App, quero extrair os itens recomendados do novo wrapper, mantendo o mesmo contrato de cada item individual.
Critérios de Aceitação:
- WHEN a resposta estiver no novo formato THEN o sistema SHALL extrair a lista da chave
itemse deserializar cada elemento comUpsellRecommendationItem.fromJson - WHEN a resposta estiver no formato legado THEN o sistema SHALL manter a deserialização atual (
(response as List).map(...)) - WHEN deserializando itens THEN o sistema SHALL manter o limite de 3 itens (
take(3)— definição de produto) - WHEN deserializando itens THEN o sistema SHALL manter a validação de
cartIdLocalpara evitar race condition (o carrinho ativo pode ter mudado durante a chamada HTTP)
Casos de Borda:
- Nenhum — o contrato de cada
UpsellRecommendationItemnão muda
RF-04 — Comportamento em erros HTTP
História de Usuário: Como App, quero lidar com erros do BFF sem quebrar o fluxo de venda, mantendo comportamento retrocompatível.
Critérios de Aceitação:
- WHEN o BFF retornar erro HTTP (400, 404, 500, etc.) THEN o sistema SHALL manter o comportamento atual do bloco
catch— setarhasError = truesem tentar extrairrecommendationsId - WHEN ocorrer erro THEN o
recommendationsIdno controller SHALL permanecernull - WHEN o carrinho for enviado sem
recommendationsId(camponullnoCartDTO) THEN otoJson()SHALL omitir o campo do payload (comportamento atual mantido)
Casos de Borda:
- O BFF, conforme Task #196023 RF-06, não retorna o wrapper
{ recommendationsId, items }em erros — retorna o erro AS IS
RF-05 — Preservação do recommendationsId no CartDTO
História de Usuário: Como App, quero que o recommendationsId trafegue junto ao carrinho até o POST api/cart, sem alterações no contrato do payload.
Critérios de Aceitação:
- WHEN
CartDTO.recommendationsIdfor não-nulo THEN otoJson()SHALL incluir o campo"recommendationsId"com o valor - WHEN
CartDTO.recommendationsIdfornullTHEN otoJson()SHALL omitir o campo (retrocompatível) - WHEN o cart for persistido localmente THEN
toJsonLocal()SHALL incluir o campo (se não-nulo) — comportamento atual mantido - WHEN o cart for restaurado de persistência local THEN
fromJson()SHALL ler o camporecommendationsId— comportamento atual mantido
Casos de Borda:
- Nenhuma alteração necessária —
CartDTOjá suporta o campo
RF-06 — Comportamento do retry
História de Usuário: Como App, quero que o retry de recomendação obtenha um novo recommendationsId do BFF.
Critérios de Aceitação:
- WHEN o usuário acionar retry THEN o sistema SHALL resetar
recommendationsIdparanullehasLoadedRecommendationsparafalse(comportamento atual) - WHEN o novo fetch retornar sucesso THEN o sistema SHALL capturar o novo
recommendationsIddo BFF (aplicando RF-01 e RF-02)
Casos de Borda:
- Comportamento atual mantido, sem alterações no método
retry()
Fora de Escopo
- Alterações no fluxo de recomendação de produtos (
ProductRecommendationProductsController, endpoint/bff/recommend-customer) - Reset de
hasLoadedRecommendationsao alterar itens do carrinho (mantido comportamento atual — recomendações não são re-buscadas após mudanças no carrinho) - Alterações no Portal (tratado na Task #196025)
- Alterações no
POST api/cart(tratado na Task #196022) - Alterações no
UpsellRecommendationItem.fromJson(contrato de item individual não muda)
Dependências
| Dependência | Descrição | Status |
|---|---|---|
| Task #196023 | BFF deve retornar RecommendationsResponse { recommendationsId, items } | Pendente |
| Task #196022 | POST api/cart deve aceitar recommendationsId | Pendente |
Questões em Aberto
(nenhuma — todas resolvidas durante grill session 12/06/2026)
Decisões da Grill Session
| Decisão | Resolução |
|---|---|
| Formato da resposta | Detecção automática (Map com items = novo; List = legado) |
Fallback recommendationsId | UUID local quando ausente, com log de warning |
| Armazenar com items vazios | Sim, se recommendationsId estiver presente |
| Escopo | Apenas FLOW B (upsell), não FLOW A |
| Erro HTTP | Não extrair recommendationsId, manter comportamento atual |
| Re-busca ao mudar carrinho | Não — manter comportamento atual |
| Nome do campo no cart | recommendationsId (camelCase), omitido quando null |