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

13 KiB
Raw Blame History

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

  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