This commit is contained in:
Daniel Arantes Loverde
2026-03-05 10:10:27 -03:00
parent a8e3631177
commit 1407f0b9de
27 changed files with 1493 additions and 84 deletions

View File

@@ -565,3 +565,220 @@ Se o socket cair, o app deve continuar consultando o status até estado final.
- próximos 2min: a cada `5s`
- depois: a cada `10s`
- parar em status final (`COMPLETED`, `CANCELED`, `REFUNDED`) ou ao sair da tela.
### 8. Catálogo Oficial de Tags de Review
### 8.1 Matriz Completa de Endpoints (Reviews + Tags)
**Público/App (Customer):**
- `GET /api/public/reviews/tags` → catálogo oficial de tags e regras de validação.
- `POST /api/public/orders/:orderId/review` → cria/atualiza avaliação do pedido concluído.
- `GET /api/public/store/:storeId/reviews` → lista reviews públicos da loja.
**Store/Backoffice (analytics e operação):**
- `GET /api/store/:storeId/reviews` → listagem detalhada + métricas de reviews da loja.
- `POST /api/store/:storeId/reviews/:reviewId/reply` → resposta oficial da loja para avaliação.
- `POST /api/store/:storeId/reviews/:reviewId/dispute` → contestação da avaliação.
- `GET /api/store/reviews/app/nps` → NPS do app (geral/por filtros).
- `GET /api/store/reviews/app/nps/platform` → NPS por plataforma (`ios`, `android`, `web`).
- `GET /api/store/reviews/observability/overview` → funil técnico (sucesso/rejeição/erro).
- `GET /api/store/reviews/observability/alerts` → alertas operacionais (ex.: pico de reviews negativas).
**Observação de base URL:**
- No app, consumir sempre via domínio/API oficial do ecossistema (PediFoods/Atomenta), mantendo o Atomenta como orquestrador.
O app deve buscar este endpoint para renderizar as tags válidas e enviar somente os `id` retornados.
**Endpoint:**
- `GET /api/public/reviews/tags`
**Headers:**
- `Accept: application/json`
**Response (resumo):**
```json
{
"error": false,
"result": {
"version": "2026-03-01",
"order": {
"positive": [{ "id": "flavor", "label": "Sabor" }],
"improvement": [{ "id": "wrong_items", "label": "Itens errados" }],
"rules": {
"positiveAllowedWhenRateGte": 5,
"improvementAllowedWhenRateLte": 4
}
},
"delivery": {
"sentiments": [
{ "id": "positive", "allowedTags": ["politeness", "on_time"] },
{ "id": "negative", "allowedTags": ["delay", "rude"] }
],
"positive": [{ "id": "politeness", "label": "Educação" }],
"negative": [{ "id": "delay", "label": "Atraso" }]
},
"app": {
"nps": { "min": 0, "max": 10 },
"platforms": ["ios", "android", "web"]
}
}
}
```
**Regra de integração:**
- Não hardcodear tags no app; usar o catálogo do backend.
- Enviar no POST de review apenas os `id` retornados em cada bloco.
### 9. Enviar Avaliação do Pedido
Permite o customer enviar review da loja a partir de um pedido finalizado.
**Endpoint:**
- `POST /api/public/orders/:orderId/review`
**Headers:**
- `Authorization: Bearer <Users_JWT_Token>` (obrigatório)
- `Accept: application/json`
- `Content-Type: application/json`
**Body:**
```json
{
"orderRate": 5,
"orderComment": "Pedido chegou certinho e bem embalado.",
"orderPositiveTags": ["flavor", "temperature"],
"orderImprovementTags": [],
"deliverySentiment": "positive",
"deliveryPositiveTags": ["on_time", "politeness"],
"deliveryNegativeTags": [],
"appNps": 10,
"platform": "ios",
"rate": 5,
"message": "Pedido chegou certinho e bem embalado."
}
```
**Regras de negócio atuais:**
- Só aceita review para pedido com status `COMPLETED`.
- O `orderId` deve existir.
- `storeId`, `userId`, `clientName` e `orderId` do review são derivados do pedido no backend (não enviar no body).
- Campos obrigatórios para integração nova: `orderRate`, `deliverySentiment`, `appNps`, `platform`.
- Compatibilidade: `rate/message` ainda são aceitos como fallback.
- App deve manter o rascunho local do formulário em caso de erro HTTP para permitir reenvio sem redigitar.
**Response (sucesso):**
```json
{
"error": false,
"result": {
"id": "rev_abc123",
"storeId": "store_1772117366848_wmqw4",
"userId": "cust_uuid_001",
"clientName": "Customer 002",
"rate": 5,
"message": "Pedido chegou certinho e bem embalado.",
"orderRate": 5,
"orderComment": "Pedido chegou certinho e bem embalado.",
"deliveryFeedback": "positive",
"platform": "ios",
"editableUntil": "2026-03-06T17:15:00.000Z",
"storeReplyUntil": "2026-03-06T17:15:00.000Z",
"reviewWindowExpiresAt": "2026-03-06T16:10:00.000Z",
"orderId": "ffdc47b4-6a55-4713-aea9-45169e4cf0d7",
"date": "2026-03-01T17:15:00.000Z"
}
}
```
**Erros esperados:**
- `400` quando `orderId` não for enviado.
- `400` quando o pedido não existir ou ainda não estiver concluído (`Apenas pedidos concluídos podem ser avaliados`).
- `400` `REVIEW_WINDOW_EXPIRED` quando passou da janela inicial de 5 dias para criar review.
- `400` `REVIEW_EDIT_WINDOW_EXPIRED` quando tentar alterar review após 5 dias da criação.
- `400` `INVALID_REVIEW_PAYLOAD` / `INVALID_REVIEW_TAGS` / `INVALID_DELIVERY_SENTIMENT_TAGS` para payload inválido.
- `401` se o token JWT for inválido/ausente.
- `500` em falha interna (`Erro ao enviar avaliação`).
**Exemplos de validação (cenários):**
Exemplo válido (nota alta + entrega positiva):
```json
{
"orderRate": 5,
"orderComment": "Perfeito.",
"orderPositiveTags": ["flavor", "temperature"],
"orderImprovementTags": [],
"deliverySentiment": "positive",
"deliveryPositiveTags": ["on_time", "politeness"],
"deliveryNegativeTags": [],
"appNps": 10,
"platform": "android"
}
```
Exemplo inválido (nota 5 com `orderImprovementTags`):
```json
{
"orderRate": 5,
"orderImprovementTags": ["temperature"],
"deliverySentiment": "positive",
"appNps": 8,
"platform": "ios"
}
```
Retorno esperado: `400 INVALID_REVIEW_TAGS`.
Exemplo inválido (entrega positiva com tags negativas):
```json
{
"orderRate": 4,
"orderImprovementTags": ["temperature"],
"deliverySentiment": "positive",
"deliveryNegativeTags": ["delay"],
"appNps": 7,
"platform": "web"
}
```
Retorno esperado: `400 INVALID_DELIVERY_SENTIMENT_TAGS`.
### 10. Analytics de Reviews (Store/API)
Para dashboard da loja e análise de produto, usar:
- `GET /api/store/:storeId/reviews`
- filtros opcionais: `startDate`, `endDate`, `minRate`, `maxRate`, `deliverySentiment`, `platform`
- retorno inclui métricas de estrelas, blocos de pedido/entrega, janelas (`editableUntil`, `storeReplyUntil`) e `appNps` agregado.
- `POST /api/store/:storeId/reviews/:reviewId/reply`
- body obrigatório: `reply` (texto da resposta da loja).
- regra: respeita janela de resposta (`storeReplyUntil`).
- `POST /api/store/:storeId/reviews/:reviewId/dispute`
- body obrigatório: `reason` (motivo da contestação).
- `GET /api/store/reviews/app/nps`
- filtros opcionais: `startDate`, `endDate`, `storeId`, `platform`
- retorno: volume NPS, média e score.
- `GET /api/store/reviews/app/nps/platform`
- filtros opcionais: `startDate`, `endDate`, `storeId`
- retorno: NPS separado em `ios`, `android`, `web`.
- `GET /api/store/reviews/observability/overview`
- filtros opcionais: `startDate`, `endDate`, `storeId`
- retorno: tentativas, sucesso/rejeição/erro, taxa de sucesso e conversão por pedidos concluídos.
- `GET /api/store/reviews/observability/alerts`
- filtro opcional: `storeId`
- retorno: alertas de pico, ex.: `NEGATIVE_REVIEWS_SPIKE`.
**Compatibilidade Store:**
- O painel `/store/reviews` segue funcional com os campos legados (`rate`, `message`, `itemFeedback`, `improvementFeedback`, `deliveryFeedback`).
- Campos novos coexistem para evolução gradual sem quebrar o fluxo atual.