13 KiB
13 KiB
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[]
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)
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
- Dropdown o botones con las acciones válidas
- 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] │ └────────────────────────────────────────┘ - Para Cancelar y Refund: campo obligatorio de "Motivo"
- 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