This commit is contained in:
Daniel Arantes Loverde
2026-04-16 14:50:07 -03:00
parent 7f7d414e6c
commit 0ebb854213
20 changed files with 871 additions and 216 deletions

View File

@@ -167,6 +167,106 @@ Used when interacting with a specific store (Catalog, Checkout).
- Se a distância entre `lat_long` enviado e o ponto do CEP for maior que `1.5 km`, a API substitui `lat_long` pelo ponto do CEP cacheado.
- Objetivo: evitar discrepâncias grandes entre endereço e coordenada salva no perfil.
### 5. List Favorite Stores
**GET** `/api/customer/favorites`
**Headers:**
- `Authorization: Bearer <JWT_Token>`
- `Atomenta-Token: 550e8400-e29b-41d4-a716-44665544000a`
**Notes:**
- Retorna as lojas favoritas do customer autenticado.
- Apenas lojas públicas/visíveis são retornadas.
- A ordem segue a ordem salva em `favorites`.
**Response:**
```json
{
"error": false,
"code": "CUSTOMER_FAVORITES_RETRIEVED",
"result": [
{
"id": "store_1775510226293_yn5ys",
"name": "CPS Drinks",
"logo": null,
"cover": null,
"category": "Doces & Bolos",
"rating": 4.8,
"totalReviews": 12,
"isOpen": true,
"statusLabel": "Aberto",
"nextOpenLabel": null
}
]
}
```
### 6. Add Store to Favorites
**POST** `/api/customer/favorites/:storeId`
**Headers:**
- `Authorization: Bearer <JWT_Token>`
- `Atomenta-Token: 550e8400-e29b-41d4-a716-44665544000a`
**Notes:**
- Salva a loja nos favoritos do customer autenticado.
- Se a loja já estiver favoritada, a operação continua idempotente.
- A loja precisa existir e estar publicamente visível.
**Response:**
```json
{
"error": false,
"code": "CUSTOMER_FAVORITE_SAVED",
"result": {
"favorites": ["store_1775510226293_yn5ys"],
"store": {
"id": "store_1775510226293_yn5ys",
"name": "CPS Drinks",
"logo": null,
"cover": null,
"category": "Doces & Bolos",
"rating": 4.8,
"totalReviews": 12,
"isOpen": true,
"statusLabel": "Aberto",
"nextOpenLabel": null
}
}
}
```
### 7. Remove Store from Favorites
**DELETE** `/api/customer/favorites/:storeId`
**Headers:**
- `Authorization: Bearer <JWT_Token>`
- `Atomenta-Token: 550e8400-e29b-41d4-a716-44665544000a`
**Notes:**
- Remove a loja dos favoritos do customer autenticado.
- A operação é idempotente: se a loja não estiver favoritada, o array volta sem ela.
**Response:**
```json
{
"error": false,
"code": "CUSTOMER_FAVORITE_REMOVED",
"result": {
"favorites": []
}
}
```
---
## 🏠 App Home Screen
@@ -538,19 +638,29 @@ Use este canal para acompanhar mudança de status do pedido em tempo real (sem d
```
**Eventos recebidos pelo app:**
- `order_update`: enviado quando o pedido muda (pagamento aprovado, aceito pela loja, saiu para entrega, concluído, cancelado).
- `order_update`: alteração geral de status do pedido.
- `order_cancelled`: cancelamento confirmado, com motivo e metadados de estorno.
- `delivery_order_cancelled`: evento dedicado para telas de OTP/entrega interromperem o fluxo imediatamente.
**Payload típico de `order_update`:**
**Payload típico de `order_cancelled`:**
```json
{
"id": "ord_987...",
"shortId": "1234",
"storeId": "store_123...",
"userId": "cust_uuid...",
"status": "CONFIRMED",
"paymentStatus": "CONFIRMED",
"updatedAt": "2026-02-15T20:10:00.000Z"
"event": "order_cancelled",
"emittedAt": "2026-03-05T18:00:00.000Z",
"orderId": "ffdc47b4-6a55-4713-aea9-45169e4cf0d7",
"shortId": "3778",
"storeId": "store_1772117366848_wmqw4",
"userId": "cust_uuid_001",
"status": "CANCELED",
"cancelledBy": "store",
"cancelledAt": "2026-03-05T18:00:00.000Z",
"cancelReasonCode": "STORE_UNAVAILABLE",
"cancelReasonDetail": "Falta de insumo crítico para finalizar o pedido",
"refundStatus": "failed",
"refundIdempotencyKey": "refund:ffdc47b4-...",
"refundProviderRef": null,
"refundError": "Falha ao solicitar estorno automático"
}
```
@@ -566,9 +676,45 @@ Se o socket cair, o app deve continuar consultando o status até estado final.
- 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. Cancelamento de Pedido (Loja/Customer)
### 8.1 Matriz Completa de Endpoints (Reviews + Tags)
**Cancelamento pela loja (Store API):**
- `POST /api/store/:storeId/orders/:orderId/cancel`
**Cancelamento pelo customer:**
- `POST /api/customer/orders/:orderId/cancel`
**Request body (ambos):**
```json
{
"reasonCode": "CUSTOMER_REQUEST",
"reasonDetail": "Cliente solicitou cancelamento antes da entrega"
}
```
**Motivos aceitos (`reasonCode`):**
- `STORE_UNAVAILABLE`
- `CUSTOMER_REQUEST`
- `DELIVERY_ISSUE`
**Regras atuais de cancelamento:**
- Permitido em: `PAYMENT_PENDING`, `PENDING`, `ACCEPTED`, `PREPARING`, `READY`, `DELIVERING`.
- Bloqueado em: `COMPLETED` e `CANCELED`.
- Motoboy não cancela pedido.
- Ao cancelar, o backend invalida `otp`, `confirmOtp` e `customerOtp`.
**Concorrência e idempotência (ponta a ponta):**
- Cancelamento é serializado por `orderId` (lock por pedido).
- Estorno automático usa lock + chave idempotente de estorno para evitar duplicidade.
- Em segunda tentativa após cancelamento efetivado, a API retorna `409 ORDER_ALREADY_CANCELED`.
**Campos relevantes no retorno:**
- `cancelledBy`, `cancelledAt`, `cancelReasonCode`, `cancelReasonDetail`
- `refundStatus`, `refundIdempotencyKey`, `refundProviderRef`
### 9. Catálogo Oficial de Tags de Review
### 9.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.
@@ -630,7 +776,7 @@ O app deve buscar este endpoint para renderizar as tags válidas e enviar soment
- 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
### 10. Enviar Avaliação do Pedido
Permite o customer enviar review da loja a partir de um pedido finalizado.
**Endpoint:**
@@ -749,7 +895,7 @@ Exemplo inválido (entrega positiva com tags negativas):
Retorno esperado: `400 INVALID_DELIVERY_SENTIMENT_TAGS`.
### 10. Analytics de Reviews (Store/API)
### 11. Analytics de Reviews (Store/API)
Para dashboard da loja e análise de produto, usar:
- `GET /api/store/:storeId/reviews`