3.3 KiB
3.3 KiB
F-125 — Transiciones hacia atrás en pedidos + reenviar email
Cambios
src/modules/orders/domain/order.ts
State machine ampliado con transiciones hacia atrás (un paso):
export const ALLOWED_TRANSITIONS = {
PENDING: ['AWAITING_PAYMENT', 'CANCELLED'],
AWAITING_PAYMENT: ['PAID', 'CANCELLED'],
- PAID: ['PROCESSING', 'SHIPPED', 'CANCELLED', 'REFUNDED'],
+ PAID: ['PROCESSING', 'SHIPPED', 'CANCELLED', 'REFUNDED'], // unchanged
- PROCESSING: ['SHIPPED', 'CANCELLED', 'REFUNDED'],
+ PROCESSING: ['PAID', 'SHIPPED', 'CANCELLED', 'REFUNDED'], // + PAID (backward)
- SHIPPED: ['DELIVERED', 'PARTIALLY_REFUNDED'],
+ SHIPPED: ['PROCESSING', 'DELIVERED', 'PARTIALLY_REFUNDED'], // + PROCESSING (backward)
- DELIVERED: ['PARTIALLY_REFUNDED'],
+ DELIVERED: ['SHIPPED', 'PARTIALLY_REFUNDED'], // + SHIPPED (backward)
CANCELLED: [],
REFUNDED: [],
PARTIALLY_REFUNDED: [],
};
Terminales (CANCELLED, REFUNDED, PARTIALLY_REFUNDED) siguen terminales — un reembolso no se puede deshacer.
src/modules/orders/tests/order-state-machine.test.ts
- Test renombrado: "rejects SHIPPED back to PENDING (too far)" — el comportamiento de rechazo sigue siendo correcto (PENDING está demasiado lejos).
- Test nuevo: "allows one-step backward transitions (F-125)" — verifica
PROCESSING→PAID,SHIPPED→PROCESSING,DELIVERED→SHIPPED.
apps/admin/src/app/(dashboard)/orders/[id]/page.tsx
- Mismo
ALLOWED_TRANSITIONSduplicado (frontend) actualizado con las nuevas transiciones. ACTION_LABELSreemplazado porACTION_LABELS_BY_TRANSITIONkeyed por"<from>><to>". Esto permite que el mismo target (p. ej.PROCESSING) tenga label distinto según origen:PAID > PROCESSING: "Procesar pedido"SHIPPED > PROCESSING: "Revertir a En preparación"
- Función helper
actionLabel(from, to)que devuelve el label del par o fallback"Pasar a {to}". - Dos usos actualizados:
{actionLabel(currentState, next)}(botón) y{actionLabel(currentState, showConfirm)}(modal de confirmación).
Sin cambios en backend de email. El handler POST /orders/:id/transitions/admin ya envía email en cada transición con courier y trackingNumber actuales del pedido (ver orders.routes.ts:271 y buildOrderStatusEmail en order-status-mailer.ts).
Cuando SHIPPED → PROCESSING:
- El email se reenvía con
state='PROCESSING' - El bloque "Transportista: X / Número de seguimiento: Y" sigue apareciendo porque
courierytrackingNumbersiguen guardados en DB y se incluyen en el body si están presentes (independiente del estado).
Verificación
Tests
npx vitest run src/modules/orders/tests/order-state-machine.test.ts→ 5/5 pass (incluye el nuevo test de transiciones hacia atrás).
Build
cd apps/admin && npx tsc --noEmit→ exit 0.cd apps/admin && npm run build→ exit 0.
Evidencia manual
Con pedidos existentes:
- PROCESSING → botón "Marcar como Enviado" + botón nuevo "Revertir a Pagado"
- SHIPPED → botón "Marcar como Entregado" + botón nuevo "Revertir a En preparación"
- DELIVERED → botón "Reembolso parcial" + botón nuevo "Revertir a Enviado"
Notas
- El reenvío de email ya estaba implementado (F-113) — solo había que permitir las transiciones.
- El operador debe reiniciar admin (
./scripts/monolith.sh prod restart) para desplegar la nueva UI.