7.9 KiB
US-MGN-007-001-002: Enviar Cotización por Email
RF Asociado: RF-MGN-007-001 Módulo: MGN-007 - Ventas Básico Epic: Cotizaciones Prioridad: P0 Story Points: 2 Sprint: Sprint 16 Estado: Ready for Development Fecha: 2025-11-24
User Story
Como vendedor, Quiero enviar cotizaciones por email con PDF adjunto, Para compartir la cotización con el cliente y cambiar su estado a "sent".
Descripción Detallada
Esta funcionalidad permite enviar la cotización al cliente por email con:
- Asunto y cuerpo personalizables
- PDF de la cotización adjunto
- Cambio automático de estado de draft → sent
- Registro de la fecha de envío (date_sent)
- Histórico de envíos en chatter/mensajes
El email se envía al contacto principal del partner (partner.email). El PDF se genera on-the-fly usando un template HTML.
Criterios de Aceptación
Escenario 1: Enviar cotización en draft (Camino Feliz)
Dado que tengo cotización id=1 en estado draft, Cuando ejecuto action "Send by Email" con to="cliente@example.com", subject="Cotización #QT/2024/0001", Entonces sistema envía email con PDF adjunto, cambia estado a sent, registra date_sent.
Escenario 2: Validar que cotización está en estado válido
Dado que cotización está en estado cancelled, Cuando intento enviar por email, Entonces sistema retorna error 400 "No se puede enviar cotización cancelada".
Escenario 3: Validar que partner tiene email
Dado que partner.email es nulo, Cuando intento enviar cotización, Entonces sistema retorna error 400 "El cliente no tiene email configurado".
Escenario 4: Generar PDF automáticamente
Dado que cotización tiene líneas con productos y totales, Cuando se envía por email, Entonces sistema genera PDF con logo empresa, datos cliente, líneas, totales.
Escenario 5: Template de email personalizable
Dado que existe template "quotation_email" configurado, Cuando se envía cotización, Entonces sistema usa el template con variables: {customer_name}, {quotation_number}, {total}.
Escenario 6: Registrar envío en chatter
Dado que cotización se envía exitosamente, Cuando se completa el envío, Entonces sistema crea mensaje en chatter: "Cotización enviada a cliente@example.com".
Reglas de Negocio
- RN-1: Solo cotizaciones en draft o sent pueden enviarse por email.
- RN-2: Al enviar, estado cambia automáticamente a sent.
- RN-3: date_sent se actualiza con timestamp del envío.
- RN-4: Partner debe tener email válido configurado.
- RN-5: PDF se genera dinámicamente, no se almacena.
- RN-6: Se registra mensaje en chatter con detalles del envío.
- RN-7: Permisos: sales_user o superior.
Tareas Técnicas
Backend
- Endpoint:
POST /api/v1/sales/quotations/:id/send-email - Service:
QuotationService.sendByEmail(id, emailDto) - Service:
PdfGeneratorService.generateQuotationPdf(quotation) - Service:
EmailService.sendWithAttachment(to, subject, body, pdfBuffer) - DTO:
SendQuotationEmailDto(to, cc?, subject, body) - Validar estado de cotización (draft o sent)
- Validar email de partner existe
- Generar PDF usando Puppeteer o similar
- Template HTML para PDF
- Actualizar estado a sent y date_sent
- Crear mensaje en chatter
- Unit tests (>80%)
- Integration tests
- Swagger docs
Frontend
- Componente:
SendQuotationEmailDialog.tsx - Modal con: destinatario, asunto, cuerpo editable
- Preview del email antes de enviar
- Botón "Send by Email" en vista de cotización
- API client:
quotationApi.sendEmail(id, data) - Notificación toast de éxito/error
- Component tests
- E2E test: "should send quotation by email"
Database
- Columna:
sales.quotations.date_sent(timestamp) - Columna:
sales.quotations.sent_count(int, contador de envíos) - Índice:
idx_quotations_date_sent
Mockups / Wireframes
Modal Enviar Email:
┌────────────────────────────────────────────┐
│ Enviar Cotización QT/2024/0001 │
├────────────────────────────────────────────┤
│ Para: [Input: cliente@example.com] * │
│ CC: [Input: opcional] │
│ │
│ Asunto: [Input: Cotización QT/2024/0001] │
│ │
│ Mensaje: │
│ ┌────────────────────────────────────────┐ │
│ │ Estimado cliente, │ │
│ │ │ │
│ │ Adjunto encontrará la cotización │ │
│ │ solicitada. │ │
│ │ │ │
│ │ Saludos, │ │
│ │ [Nombre Vendedor] │ │
│ └────────────────────────────────────────┘ │
│ │
│ Adjunto: quotation_QT_2024_0001.pdf │
│ │
│ [Vista Previa PDF] [Enviar] [Cancelar] │
└────────────────────────────────────────────┘
Casos de Prueba
Funcionales
- TC-001: Enviar cotización draft exitosamente
- TC-002: Error al enviar cotización cancelada
- TC-003: Error si partner no tiene email
- TC-004: PDF se genera correctamente con datos de cotización
- TC-005: Estado cambia a sent después de envío
- TC-006: date_sent se actualiza correctamente
- TC-007: Mensaje se registra en chatter
- TC-008: Template de email se aplica correctamente
No Funcionales
- Performance: < 3s para generar PDF y enviar email
- Seguridad: JWT + permiso sales_user
Dependencias
- US bloqueantes:
- US-MGN-007-001-001 (Crear Cotización)
- US-MGN-014-006-001 (Templates de Email) - Opcional
- Módulos requeridos: MGN-003, MGN-014
- Servicios externos: SMTP configurado
Notas de Implementación
- Usar Puppeteer o @react-pdf/renderer para generar PDF
- Template HTML debe incluir: logo, dirección empresa, datos cliente, tabla de líneas, totales
- Considerar usar cola (Bull/BullMQ) para envíos asíncronos si hay muchas cotizaciones
- Almacenar historial de envíos en tabla separada si se requiere auditoría completa
- Validar formato de email con regex RFC 5322
Estimación Detallada
| Tarea | Horas |
|---|---|
| Backend | 1.5 |
| Frontend | 1 |
| PDF Template | 1 |
| Testing | 0.5 |
| Code Review | 0.5 |
| TOTAL | 4.5 horas = 2 SP |
Definition of Done
- Código implementado según ET
- Tests pasando (>80%)
- Code review aprobado
- PDF se genera correctamente
- Email se envía con SMTP configurado
- Estado cambia a sent
- Mensaje en chatter creado
- Swagger docs actualizado
- QA validado
- PO aprobado