Fix
This commit is contained in:
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user