Files
mercadodevida/project/specs-admin/050-orders/SPEC.md
2026-08-17 22:23:10 +02:00

296 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADM-013 / ADM-014 / ADM-015 — Orders Spec
## Goal
Gestión completa de pedidos: listado, detalle, y transiciones de estado.
---
## 1. Order List (`/admin/orders`)
### API Contract
```
GET /orders
Authorization: session_token (admin role)
Query params:
?offset=0&limit=20
?state=PENDING
?q=maria@ejemplo.com (búsqueda por email de cliente)
Response: OrderSummary[]
```
```typescript
interface OrderSummary {
id: string;
userId: string;
state: OrderState;
totalCents: number;
currency: 'EUR';
itemCount: number;
createdAt: string; // ISO
}
```
### Desktop UX
```
┌─────────────────────────────────────────────────────────────────┐
│ Pedidos [Estado ▼] [Búsqueda: ________] [🔍] │
├─────────────────────────────────────────────────────────────────┤
│ #ID Cliente Total Estado Fecha │
│ ──────────────────────────────────────────────────────────────── │
│ abc-123 maria@email.com €45.83 ● Paid 15 ago 2026 │
│ def-456 juan@email.com €23.10 ● Pending 14 ago 2026 │
│ ghi-789 ana@email.com €89.00 ● Shipped 10 ago 2026 │
├─────────────────────────────────────────────────────────────────┤
│ [← Anterior] Página 1 de 5 [Siguiente →] │
└─────────────────────────────────────────────────────────────────┘
```
### Filters
- **Estado**: PENDING, AWAITING_PAYMENT, PAID, PROCESSING, SHIPPED, DELIVERED, CANCELLED, REFUNDED, PARTIALLY_REFUNDED
- **Búsqueda**: por email de cliente (o ID)
- Estado por defecto: todos
### Responsive
Mobile: Cards en lugar de tabla
```
┌─────────────────────────┐
│ #abc-123 │
│ maria@email.com │
│ €45.83 · ● Paid │
│ 15 ago 2026 │
│ [Ver detalle →] │
└─────────────────────────┘
```
---
## 2. Order Detail (`/admin/orders/[id]`)
### API Contract
```
GET /orders/:id/admin
Authorization: session_token (admin role)
Response: Order (full)
```
```typescript
interface Order {
id: string;
userId: string;
state: OrderState;
subtotalCents: number;
discountCents: number;
taxCents: number;
totalCents: number;
currency: 'EUR';
idempotencyKey: string | null;
items: OrderItem[];
createdAt: string;
updatedAt: string;
}
interface OrderItem {
id: string;
productId: string;
variantId: string;
sku: string;
ean: string | null;
name: string;
unitPriceCents: number;
discountCents: number;
taxCents: number;
quantity: number;
}
```
### Desktop UX — Layout
```
┌─────────────────────────────────────────────────────────────────┐
│ ← Volver a pedidos │
├───────────────────────────────────┬─────────────────────────────┤
│ HEADER │ ACCIONES │
│ #abc-123-def │ [Cambiar estado ▼] │
│ ● Paid · 15 ago 2026 │ │
├───────────────────────────────────┴─────────────────────────────┤
│ │
│ ┌─────────────────────────┐ ┌─────────────────────────────┐ │
│ │ RESUMEN DEL PEDIDO │ │ CLIENTE │ │
│ │ │ │ maria@email.com │ │
│ │ Subtotal €37.88 │ │ │ │
│ │ Descuentos €0.00 │ │ ENVÍO │ │
│ │ IVA €7.95 │ │ Calle Gran Vía 42 │ │
│ │ ─────────────────── │ │ Madrid, 28013 │ │
│ │ TOTAL €45.83 │ │ │ │
│ └─────────────────────────┘ └─────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PRODUCTOS PEDIDOS │ │
│ │ ───────────────────────────────────────────────────── │ │
│ │ Almendras Crudas 2 × €8.95 = €17.90 │ │
│ │ Vitamina D3 + K2 2 × €9.99 = €19.98 │ │
│ │ ───────────────────────────────────────────────────── │ │
│ │ Envío estándar + €4.99 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ HISTORIAL │ │
│ │ ───────────────────────────────────────────────────── │ │
│ │ ● 15 ago 2026 14:32 Creado │ │
│ │ ● 15 ago 2026 14:35 Pagado │ │
│ └─────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
```
### Payment Transactions
```
GET /payments/orders/:orderId/transactions
Response: { transactions: PaymentTransaction[] }
```
Mostrar en sección separada: fecha, método, monto, estado.
---
## 3. Order State Transitions
### API Contract
```
POST /orders/:id/transitions/admin
Authorization: session_token (admin role)
Body: { state: OrderState }
Response: Order (updated)
```
### State Machine
```
PENDING ──────────→ AWAITING_PAYMENT (customer paid)
│ │
├─→ CANCELLED └─→ PAID ──→ PROCESSING ──→ SHIPPED ──→ DELIVERED
│ │ │
│ ├─→ CANCELLED│
│ │ ├─→ CANCELLED
│ │ │
│ ├─→ REFUNDED (full)
│ └─→ PARTIALLY_REFUNDED
│ │
└─→ CANCELLED ←──────────────────────────────┘
```
### Allowed transitions visible in UI
| Current State | Actions Available |
|-------------------|------------------------------------------------------------|
| PENDING | Marcar como Pagado · Cancelar pedido |
| AWAITING_PAYMENT | Marcar como Pagado · Cancelar pedido |
| PAID | Procesar pedido · Cancelar pedido · Reembolsar |
| PROCESSING | Marcar como enviado · Cancelar pedido · Reembolsar |
| SHIPPED | Marcar como entregado · Reembolso parcial |
| DELIVERED | Reembolso parcial |
| CANCELLED | (ninguna) |
| REFUNDED | (ninguna) |
| PARTIALLY_REFUNDED| (ninguna) |
### UX para transición
1. Dropdown o botones con las acciones válidas
2. Al hacer click en acción → Dialog de confirmación:
```
┌────────────────────────────────────────┐
│ Cambiar estado del pedido │
│ │
│ ¿Marcar este pedido como PAGADO? │
│ │
│ Estado actual: ● Pendiente │
│ Nuevo estado: ● Pagado │
│ │
│ [Cancelar] [Confirmar] │
└────────────────────────────────────────┘
```
3. Para Cancelar y Refund: campo obligatorio de "Motivo"
4. Submit → esperar respuesta → refresh del detalle
### Cancellation UX
```
┌────────────────────────────────────────┐
│ ⚠️ Cancelar pedido │
│ │
│ ¿Estás seguro de cancelar el pedido │
│ #abc-123-def? │
│ │
│ Motivo * │
│ ┌────────────────────────────────────┐│
│ │ Cliente solicitó cancelación ││
│ └────────────────────────────────────┘│
│ │
│ [Volver] [Cancelar pedido] │
└────────────────────────────────────────┘
```
---
## 4. Acceptance Criteria
### ADM-013 — Order List
- [ ] Órdenes listadas con paginación (20 por página)
- [ ] Filtro por estado funcional
- [ ] Búsqueda por email/ID funcional
- [ ] Link a detalle
- [ ] Empty state si no hay pedidos
- [ ] Loading skeleton
### ADM-014 — Order Detail
- [ ] Resumen con todos los totales
- [ ] Lista de productos con precios
- [ ] Información de cliente
- [ ] Línea de tiempo con historial de estados
- [ ] Transacciones de pago visibles
- [ ] Estado actual con badge de color + texto
### ADM-015 — State Transitions
- [ ] Solo acciones válidas visibles según estado actual
- [ ] Confirmación antes de ejecutar
- [ ] Campo "Motivo" obligatorio para Cancelar y Refund
- [ ] Refresh del detalle post-transición
- [ ] Timeline actualizada
- [ ] Toast de éxito/error
---
## 5. Tests
### Unit
- State machine: verify only valid transitions shown
- Transition formatter: state → label + color
### Component
- OrderStatusBadge renders correct color for each state
- TransitionDialog shows only valid actions
- OrderTimeline renders in correct order
### Integration
- Transition PENDING → PAID → PROCESSING → SHIPPED → DELIVERED
- Attempt invalid transition → backend error shown
### E2E
- Filter orders by status
- View order detail
- Transition order through valid states
- Cancel order with reason
- Error when backend rejects transition