# US-MGN-007-005-001: Crear Devolución de Cliente **RF Asociado:** [RF-MGN-007-004](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-004-entregas-de-ventas.md) **Módulo:** MGN-007 - Ventas Básico **Epic:** Devoluciones de Ventas **Prioridad:** P1 **Story Points:** 3 **Sprint:** Sprint 17 **Estado:** Ready for Development **Fecha:** 2025-11-24 --- ## User Story **Como** usuario de ventas, **Quiero** registrar devoluciones de productos por clientes, **Para** gestionar productos defectuosos o cambios solicitados por el cliente. --- ## Descripción Detallada Una Devolución (Return) es el proceso inverso a una delivery: productos regresan del cliente al almacén. Se puede crear desde: 1. Una delivery existente (reversa parcial o total) 2. Manualmente (sin delivery origen) Flujo: - Cliente solicita devolución - Se crea return order en draft - Especifica productos y cantidades a devolver - Motivo de devolución (defectuoso, cambio, error de envío) - Al validar: crea movimientos de stock (cliente → almacén) Estados: draft, confirmed, done, cancelled. --- ## Criterios de Aceptación ### Escenario 1: Crear devolución desde delivery (Camino Feliz) **Dado que** delivery DO/2024/0001 está done con product_id=1, qty=50, **Cuando** creo return desde delivery especificando qty_return=10, reason="Defectuoso", **Entonces** sistema crea return RET/2024/0001 en draft con línea: product_id=1, qty=10, vinculado a delivery. ### Escenario 2: Validar cantidades a devolver <= cantidades entregadas **Dado que** delivery tiene qty_delivered=50, **Cuando** intento crear return con qty_return=100, **Entonces** sistema retorna error 400 "No se pueden devolver más unidades de las entregadas". ### Escenario 3: Crear devolución manual (sin delivery origen) **Dado que** cliente devuelve producto sin referencia a delivery, **Cuando** creo return manual con customer_id=1, product_id=5, qty=3, **Entonces** sistema crea return sin delivery_id vinculado. ### Escenario 4: Motivo de devolución obligatorio **Dado que** intento crear return sin especificar reason, **Cuando** envío request, **Entonces** sistema retorna error 400 "El motivo de devolución es obligatorio". ### Escenario 5: Generar número secuencial **Dado que** última return fue RET/2024/0005, **Cuando** creo nueva return, **Entonces** sistema genera número RET/2024/0006. ### Escenario 6: Vincular return a SO si proviene de delivery **Dado que** return se crea desde delivery vinculada a SO id=1, **Cuando** se crea return, **Entonces** return.order_id=1. --- ## Reglas de Negocio - **RN-1:** Return se crea en estado draft. - **RN-2:** qty_return <= qty_delivered por producto. - **RN-3:** Motivo de devolución es obligatorio (enum: defective, wrong_item, customer_request, other). - **RN-4:** Número secuencial: RET/{year}/{seq:04d}. - **RN-5:** Ubicación origen: cliente, destino: almacén. - **RN-6:** Si proviene de delivery, se vincula delivery_id. - **RN-7:** Permisos: sales_user. --- ## Tareas Técnicas ### Backend - [ ] Endpoint: `POST /api/v1/sales/returns` - [ ] Endpoint: `POST /api/v1/inventory/deliveries/:id/create-return` - [ ] Service: `ReturnService.create(createReturnDto)` - [ ] Service: `DeliveryService.createReturn(deliveryId, returnDto)` - [ ] DTO: `CreateReturnDto` (customer_id, lines, reason, delivery_id?) - [ ] DTO: `ReturnLineDto` (product_id, quantity, reason) - [ ] Validar qty_return <= qty_delivered - [ ] Validar reason no vacío - [ ] Generar número secuencial RET - [ ] Vincular delivery_id y order_id si aplica - [ ] Crear mensaje en chatter - [ ] Unit tests (>80%) - [ ] Integration tests - [ ] Swagger docs ### Frontend - [ ] Botón: "Create Return" en vista de delivery done - [ ] Formulario: CreateReturnForm.tsx - [ ] Selector de productos/cantidades a devolver - [ ] Dropdown: Motivo de devolución - [ ] Validación: qty <= qty_delivered - [ ] API client: `returnApi.create(data)` - [ ] Notificación toast de éxito - [ ] Component tests - [ ] E2E test: "should create return from delivery" ### Database - [ ] Tabla: `sales.returns` (id, customer_id, delivery_id, order_id, number, state, reason, date) - [ ] Tabla: `sales.return_lines` (id, return_id, product_id, quantity) - [ ] FK: `sales.returns.delivery_id → inventory.deliveries.id` - [ ] Enum: return_reason (defective, wrong_item, customer_request, other) - [ ] Índices: idx_returns_delivery_id, idx_returns_customer_id - [ ] RLS policy: company_isolation_returns --- ## Mockups / Wireframes **Formulario Crear Devolución:** ``` ┌─────────────────────────────────────────────┐ │ Crear Devolución desde DO/2024/0001 │ ├─────────────────────────────────────────────┤ │ Cliente: ABC Corp │ │ Referencia: SO/2024/0001 │ │ │ │ Productos a devolver: │ │ ┌───────────────────────────────────────┐ │ │ │Producto │Entregado│A devolver│Motivo │ │ │ ├──────────┼─────────┼──────────┼───────┤ │ │ │Laptop HP │ 50 │[10] │[▼] │ │ │ └───────────────────────────────────────┘ │ │ │ │ Motivo general: [▼ Producto defectuoso] │ │ │ │ Notas: [Opcional] │ │ │ │ [Crear Devolución] [Cancelar] │ └─────────────────────────────────────────────┘ ``` --- ## Casos de Prueba ### Funcionales 1. **TC-001:** Crear return desde delivery exitosamente 2. **TC-002:** Crear return manual exitosamente 3. **TC-003:** Error si qty_return > qty_delivered 4. **TC-004:** Error si reason vacío 5. **TC-005:** Número secuencial generado correctamente 6. **TC-006:** delivery_id y order_id vinculados correctamente 7. **TC-007:** Mensaje creado en chatter ### No Funcionales 1. **Performance:** < 300ms para crear return 2. **Seguridad:** JWT + permiso sales_user --- ## Dependencias - **US bloqueantes:** - US-MGN-007-003-002 (Validar Entrega) - **Módulos requeridos:** MGN-005 (Inventario) --- ## Notas de Implementación - Frontend: Mostrar lista de deliveries done del cliente para facilitar selección - Validar que productos de la devolución coincidan con productos entregados - Considerar campo `expected_date` para cuando se espera la devolución - Stock se actualiza al validar return, no al crear --- ## Estimación Detallada | Tarea | Horas | |-------|-------| | Backend | 1.5 | | Frontend | 1.5 | | Testing | 1 | | Code Review | 0.5 | | **TOTAL** | **4.5 horas = 3 SP** | --- ## Definition of Done - [ ] Código implementado según ET - [ ] Tests pasando (>80%) - [ ] Code review aprobado - [ ] Return se crea correctamente - [ ] Validaciones aplicadas - [ ] Número secuencial generado - [ ] Vinculación a delivery/SO correcta - [ ] Mensaje en chatter creado - [ ] Swagger docs actualizado - [ ] QA validado - [ ] PO aprobado --- ## Referencias - [RF-MGN-007-004](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-004-entregas-de-ventas.md) - [ET Backend](../../02-modelado/especificaciones-tecnicas/backend/mgn-007/ET-BACKEND-MGN-007-004-entregas.md) - [ET Frontend](../../02-modelado/especificaciones-tecnicas/frontend/mgn-007/ET-FRONTEND-MGN-007-004-entregas.md) - [Traceability](../../02-modelado/trazabilidad/TRACEABILITY-MGN-007.yaml) - [Schema](../../02-modelado/database-design/schemas/sales-schema-ddl.sql)