# US-MGN-007-001-002: Enviar Cotización por Email **RF Asociado:** [RF-MGN-007-001](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-001-gestión-de-cotizaciones.md) **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 1. **TC-001:** Enviar cotización draft exitosamente 2. **TC-002:** Error al enviar cotización cancelada 3. **TC-003:** Error si partner no tiene email 4. **TC-004:** PDF se genera correctamente con datos de cotización 5. **TC-005:** Estado cambia a sent después de envío 6. **TC-006:** date_sent se actualiza correctamente 7. **TC-007:** Mensaje se registra en chatter 8. **TC-008:** Template de email se aplica correctamente ### No Funcionales 1. **Performance:** < 3s para generar PDF y enviar email 2. **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 --- ## Referencias - [RF-MGN-007-001](../../02-modelado/requerimientos-funcionales/mgn-007/RF-MGN-007-001-gestión-de-cotizaciones.md) - [ET Backend](../../02-modelado/especificaciones-tecnicas/backend/mgn-007/ET-BACKEND-MGN-007-001-cotizaciones.md) - [ET Frontend](../../02-modelado/especificaciones-tecnicas/frontend/mgn-007/ET-FRONTEND-MGN-007-001-cotizaciones.md) - [Traceability](../../02-modelado/trazabilidad/TRACEABILITY-MGN-007.yaml) - [Schema](../../02-modelado/database-design/schemas/sales-schema-ddl.sql)