feat(crm): ampliar solicitud de servicio y encadenar el ciclo comercial #1

Closed
admin wants to merge 2 commits from feature/crm-solicitud-cotizacion-ciclo into feature/crm-workspace-altas-org-usuario
Owner

Objetivo

Ampliar la Solicitud de servicio con los campos del documento maestro de cotización y encadenar el ciclo comercial de punta a punta: Oportunidad → Solicitud → Cotización → Operación (embarque), de forma intuitiva y con pruebas unitarias.

Ejecutado bajo protocolo Sundown-Sunrise (autónomo). Actividad IA Kanban: DISEÑO DE PROMPTS IA → este PR es PRUEBAS SOBRE CAMBIOS IA (pendiente QA de ingeniería en Sunrise).

Qué incluye

Solicitud de servicio (documento maestro de cotización)

  • Campos nuevos: contacto, prioridad, moneda, ruta estructurada (país/ciudad/puerto de origen y destino, recolección/entrega), mercancía (HS, valor, seguro, IMO, refrigerada, estibable, país de origen), dimensiones/bultos (piezas/cajas/pallets, peso neto, medidas, unidad), FCL (contenedor/cantidad), LCL (embalaje, sobredimensión, peso/volumen por pallet), servicios adicionales, forma de pago y notas.
  • Origen/Destino seleccionables por catálogo de país (ISO), con respaldo de texto para ciudad/puerto.
  • Validación de contacto asociado (422 si no existe).

Ciclo comercial conectado

  • Dirección impo/expo se captura en la Oportunidad y se hereda a Solicitud → Cotización → Embarque.
  • Oportunidad → Solicitud: conversión idempotente con back-link (converted_service_request_id); modal de confirmación (reemplaza el window.prompt).
  • Solicitud → Cotización: endpoint POST /quotes/from-service-request; si la solicitud es "Ambas" genera 2 cotizaciones (FCL y LCL) para comparar; siembra los conceptos desde las tarifas de la solicitud. Botón "Cotizar" en la solicitud.
  • Cotización → Operación: al Liberar, modal que confirma IMPO/EXPO (prefijado desde la solicitud) y siembra automáticamente los hitos del proceso (Diagramas 2 y 3).
  • Fecha de la cotización (issue_date): por defecto hoy, editable y ya visible en el PDF.

Folios auto-generados — formato {LETRA}{AAAA}-{MM}-{NNN}-{DIR} (p. ej. O2025-08-001-E): O Oportunidad, S Solicitud, C Cotización, OP Operación. Consecutivo mensual por compañía y entidad (crm.folio_counters + helper next_folio con bloqueo de fila; el índice único evita duplicados). reference queda auto/read-only.

Catálogos — 9 nuevos globales: tipo_operacion, medio_transporte, tipo_servicio, prioridad, tipo_mercancia, unidad_medida, tipo_embalaje, servicio_adicional, tipo_documento. Reusa pais (201) para Origen/Destino.

Pruebas

  • 101 pruebas en verde (76 previas + 25 nuevas): test_folios, test_catalogs_seed, y casos añadidos en test_service_requests, test_quotes, test_shipments.
  • Migración b1c2d3e4f5a6 reversible verificada en PostgreSQL (upgrade → downgrade → upgrade).
  • svelte-check: sin errores nuevos en los archivos tocados.

Despliegue (Sunrise, en testing — NO prod)

  1. docker compose exec backend alembic upgrade head
  2. docker compose exec backend python -m api.v1.modules.crm.catalogs.seed
  3. Rebuild del frontend.

PENDIENTE DECISIÓN (no adivinado; a validar con negocio)

  • payment_method reusa el catálogo SAT forma_pago (códigos numéricos). ¿Lista comercial simplificada?
  • origin_city/destination_city y puertos/aeropuertos no tienen semilla global → se deja texto de respaldo. ¿Sembrar catálogo base de puertos/aeropuertos?
  • Convertir Oportunidad solo enlaza converted_service_request_id; ¿marcar además la oportunidad como won?
  • Solicitud→Cotización permite múltiples borradores por solicitud. ¿Bloquear si ya está cotizada?
  • unidad_medida es única (dimensión + peso). ¿Separar dimension_unit/weight_unit?
  • "Ambas": las 2 cotizaciones se siembran de las mismas tarifas (idénticas al inicio); el ejecutivo ajusta por variante. ¿Tarifas diferenciadas FCL/LCL en la solicitud?
  • Folio de Cotización/Embarque sin dirección (cotización manual sin solicitud): usa sufijo X. ¿Exigir solicitud?
  • Consecutivo mensual por compañía + entidad (la dirección I/E solo etiqueta). ¿Consecutivo separado por dirección?
  • reference pasa a auto/read-only; folios previos no se re-generan. ¿Backfill? Default: no.

🤖 Generated with Claude Code

## Objetivo Ampliar la **Solicitud de servicio** con los campos del documento maestro de cotización y **encadenar el ciclo comercial** de punta a punta: Oportunidad → Solicitud → Cotización → Operación (embarque), de forma intuitiva y con pruebas unitarias. Ejecutado bajo protocolo **Sundown-Sunrise** (autónomo). Actividad IA Kanban: **DISEÑO DE PROMPTS IA** → este PR es **PRUEBAS SOBRE CAMBIOS IA** (pendiente QA de ingeniería en Sunrise). ## Qué incluye **Solicitud de servicio (documento maestro de cotización)** - Campos nuevos: contacto, prioridad, moneda, ruta estructurada (país/ciudad/puerto de origen y destino, recolección/entrega), mercancía (HS, valor, seguro, IMO, refrigerada, estibable, país de origen), dimensiones/bultos (piezas/cajas/pallets, peso neto, medidas, unidad), FCL (contenedor/cantidad), LCL (embalaje, sobredimensión, peso/volumen por pallet), servicios adicionales, forma de pago y notas. - **Origen/Destino seleccionables** por catálogo de país (ISO), con respaldo de texto para ciudad/puerto. - Validación de contacto asociado (422 si no existe). **Ciclo comercial conectado** - **Dirección impo/expo** se captura en la **Oportunidad** y se hereda a Solicitud → Cotización → Embarque. - **Oportunidad → Solicitud**: conversión **idempotente** con back-link (`converted_service_request_id`); modal de confirmación (reemplaza el `window.prompt`). - **Solicitud → Cotización**: endpoint `POST /quotes/from-service-request`; si la solicitud es **"Ambas"** genera **2 cotizaciones** (FCL y LCL) para comparar; siembra los conceptos desde las tarifas de la solicitud. Botón **"Cotizar"** en la solicitud. - **Cotización → Operación**: al **Liberar**, modal que **confirma IMPO/EXPO** (prefijado desde la solicitud) y **siembra automáticamente los hitos** del proceso (Diagramas 2 y 3). - **Fecha de la cotización** (`issue_date`): por defecto hoy, editable y ya visible en el PDF. **Folios auto-generados** — formato `{LETRA}{AAAA}-{MM}-{NNN}-{DIR}` (p. ej. `O2025-08-001-E`): `O` Oportunidad, `S` Solicitud, `C` Cotización, `OP` Operación. Consecutivo **mensual** por compañía y entidad (`crm.folio_counters` + helper `next_folio` con bloqueo de fila; el índice único evita duplicados). `reference` queda auto/read-only. **Catálogos** — 9 nuevos globales: `tipo_operacion`, `medio_transporte`, `tipo_servicio`, `prioridad`, `tipo_mercancia`, `unidad_medida`, `tipo_embalaje`, `servicio_adicional`, `tipo_documento`. Reusa `pais` (201) para Origen/Destino. ## Pruebas - **101 pruebas** en verde (76 previas + **25 nuevas**): `test_folios`, `test_catalogs_seed`, y casos añadidos en `test_service_requests`, `test_quotes`, `test_shipments`. - Migración `b1c2d3e4f5a6` **reversible** verificada en PostgreSQL (`upgrade → downgrade → upgrade`). - `svelte-check`: sin errores nuevos en los archivos tocados. ## Despliegue (Sunrise, en testing — NO prod) 1. `docker compose exec backend alembic upgrade head` 2. `docker compose exec backend python -m api.v1.modules.crm.catalogs.seed` 3. Rebuild del frontend. ## PENDIENTE DECISIÓN (no adivinado; a validar con negocio) - `payment_method` reusa el catálogo SAT `forma_pago` (códigos numéricos). ¿Lista comercial simplificada? - `origin_city`/`destination_city` y puertos/aeropuertos no tienen semilla global → se deja texto de respaldo. ¿Sembrar catálogo base de puertos/aeropuertos? - Convertir Oportunidad solo enlaza `converted_service_request_id`; ¿marcar además la oportunidad como `won`? - Solicitud→Cotización permite múltiples borradores por solicitud. ¿Bloquear si ya está `cotizada`? - `unidad_medida` es única (dimensión + peso). ¿Separar `dimension_unit`/`weight_unit`? - "Ambas": las 2 cotizaciones se siembran de las mismas tarifas (idénticas al inicio); el ejecutivo ajusta por variante. ¿Tarifas diferenciadas FCL/LCL en la solicitud? - Folio de Cotización/Embarque **sin dirección** (cotización manual sin solicitud): usa sufijo `X`. ¿Exigir solicitud? - Consecutivo mensual por **compañía + entidad** (la dirección I/E solo etiqueta). ¿Consecutivo separado por dirección? - `reference` pasa a auto/read-only; folios previos no se re-generan. ¿Backfill? Default: no. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
admin added 1 commit 2026-08-03 23:53:02 +00:00
Solicitud de servicio:
- Campos del documento maestro de cotización (ruta estructurada por país,
  mercancía, dimensiones/bultos, FCL/LCL, servicios adicionales, notas).
- Origen/Destino seleccionables por catálogo de país (seed ya poblado).
- Validación de contacto asociado (422 si no existe).

Ciclo Oportunidad -> Solicitud -> Cotización -> Operación:
- Dirección impo/expo se captura en la Oportunidad y se hereda al ciclo.
- Conversión Oportunidad->Solicitud idempotente con back-link.
- Endpoint Solicitud->Cotización; "Ambas" genera 2 cotizaciones (FCL/LCL).
- Liberación a Operaciones confirma IMPO/EXPO (prefijado) y siembra los hitos.
- Fecha de la cotización (issue_date) por defecto hoy, editable y en el PDF.

Folios auto-generados {LETRA}{AAAA}-{MM}-{NNN}-{DIR} para Oportunidad (O),
Solicitud (S), Cotización (C) y Operación (OP); consecutivo mensual por
compañía y entidad (crm.folio_counters + helper next_folio con bloqueo de fila).

Catálogos: 9 nuevos (tipo_operacion, medio_transporte, tipo_servicio, prioridad,
tipo_mercancia, unidad_medida, tipo_embalaje, servicio_adicional, tipo_documento).

Migración b1c2d3e4f5a6 reversible (upgrade->downgrade->upgrade verificado en PG).
25 pruebas unitarias nuevas (folios, catálogos, solicitudes, cotizaciones,
embarques); suite completa en verde (101 pruebas).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
admin added 1 commit 2026-08-04 13:00:09 +00:00
- Solicitud: al marcar un servicio adicional se habilita su costo estimado
  (columna JSON additional_service_costs). Al cotizar, cada servicio marcado se
  siembra como concepto de la cotización con ese costo de partida (costo=venta).
- Folios visibles: se muestran en la tarjeta de Oportunidad del kanban y se aclara
  en el formulario que el folio se asigna al guardar (las listas ya lo mostraban).
- Sidebar CRM reordenado por flujo comercial (captación → embudo → solicitud →
  cotización → catálogos de apoyo).
- Migración c2d3e4f5a6b7 aditiva y reversible. Suite backend en verde (102).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
admin closed this pull request 2026-08-07 22:36:30 +00:00

Pull request closed

Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ADUANASOFT/CRM_AGENTES_CARGA#1
No description provided.