From 8576ec7e37b6d8af5277b69df63c34061f0dbfb7 Mon Sep 17 00:00:00 2001 From: Ernesto Herrera Date: Mon, 27 Jul 2026 09:10:19 -0600 Subject: [PATCH] =?UTF-8?q?feat(crm):=20cat=C3=A1logo=20Tipos=20de=20equip?= =?UTF-8?q?o/contenedor=20con=20medidas=20(Medidas=20de=20Equipos)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agrega el catálogo global 'tipo_equipo' (27 opciones: contenedores marítimos, ULD aéreos y remolques terrestres) con dimensiones en el campo extra (modo, largo/ancho/alto, capacidad m³, tara, carga máx., pallets). Base para la sección FCL del módulo de Cotización (T2026-07-183). Expone extra en el API de catálogos. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/api/v1/modules/crm/catalogs/dto.py | 1 + backend/api/v1/modules/crm/catalogs/seed.py | 1 + .../api/v1/modules/crm/catalogs/seed_data.py | 278 +++++++++++++++--- frontend/src/lib/api/crm/catalogs.ts | 1 + 4 files changed, 233 insertions(+), 48 deletions(-) diff --git a/backend/api/v1/modules/crm/catalogs/dto.py b/backend/api/v1/modules/crm/catalogs/dto.py index 38d7df1..c4def27 100644 --- a/backend/api/v1/modules/crm/catalogs/dto.py +++ b/backend/api/v1/modules/crm/catalogs/dto.py @@ -33,6 +33,7 @@ class CatalogItemResponse(CatalogItemBase): catalog: str tenant_id: int | None is_system: bool + extra: dict | None = None # metadata (ej. dimensiones de un tipo de equipo) class CatalogMeta(BaseModel): diff --git a/backend/api/v1/modules/crm/catalogs/seed.py b/backend/api/v1/modules/crm/catalogs/seed.py index 0827522..a44adb9 100644 --- a/backend/api/v1/modules/crm/catalogs/seed.py +++ b/backend/api/v1/modules/crm/catalogs/seed.py @@ -38,6 +38,7 @@ def seed_global_catalogs(db: Session) -> dict: label=item["label"], parent_catalog=item.get("parent_catalog"), parent_code=item.get("parent_code"), + extra=item.get("extra"), tenant_id=None, sort_order=order, is_active=True, diff --git a/backend/api/v1/modules/crm/catalogs/seed_data.py b/backend/api/v1/modules/crm/catalogs/seed_data.py index 05615b9..b0cce3c 100644 --- a/backend/api/v1/modules/crm/catalogs/seed_data.py +++ b/backend/api/v1/modules/crm/catalogs/seed_data.py @@ -1,14 +1,13 @@ """Datos semilla de los catálogos de referencia del CRM (T2026-07-081/082). -Generado de CATALOGOS CRM.xlsx (SAT/ISO) + catálogos estándar. Globales -(Aduanasoft) se siembran con tenant_id NULL; los catálogos "cliente" los llena -cada tenant desde la administración (aquí solo su metadata). +Generado de CATALOGOS CRM.xlsx (SAT/ISO) + catálogos estándar + Medidas de +Equipos (tipo_equipo con dimensiones en extra). Globales (Aduanasoft) se siembran +con tenant_id NULL; los catálogos "cliente" los llena cada tenant. """ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', 'is_system': True, - 'items': [{'code': 'cliente', 'label': 'Cliente'}, - {'code': 'prospecto', 'label': 'Prospecto'}]}, + 'items': [{'code': 'cliente', 'label': 'Cliente'}, {'code': 'prospecto', 'label': 'Prospecto'}]}, 'tipo_persona': {'label': 'Tipo de persona', 'is_system': True, 'items': [{'code': 'fisica', 'label': 'Persona física'}, @@ -236,14 +235,10 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'XAF', 'label': 'Franco CFA BEAC'}, {'code': 'XAG', 'label': 'Plata'}, {'code': 'XAU', 'label': 'Oro'}, - {'code': 'XBA', - 'label': 'Unidad de Mercados de Bonos Unidad Europea Composite (EURCO)'}, - {'code': 'XBB', - 'label': 'Unidad Monetaria de Bonos de Mercados Unidad Europea (UEM-6)'}, - {'code': 'XBC', - 'label': 'Mercados de Bonos Unidad Europea unidad de cuenta a 9 (UCE-9)'}, - {'code': 'XBD', - 'label': 'Mercados de Bonos Unidad Europea unidad de cuenta a 17 (UCE-17)'}, + {'code': 'XBA', 'label': 'Unidad de Mercados de Bonos Unidad Europea Composite (EURCO)'}, + {'code': 'XBB', 'label': 'Unidad Monetaria de Bonos de Mercados Unidad Europea (UEM-6)'}, + {'code': 'XBC', 'label': 'Mercados de Bonos Unidad Europea unidad de cuenta a 9 (UCE-9)'}, + {'code': 'XBD', 'label': 'Mercados de Bonos Unidad Europea unidad de cuenta a 17 (UCE-17)'}, {'code': 'XCD', 'label': 'Dólar del Caribe Oriental'}, {'code': 'XDR', 'label': 'DEG (Derechos Especiales de Giro)'}, {'code': 'XOF', 'label': 'Franco CFA BCEAO'}, @@ -251,12 +246,10 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'XPF', 'label': 'Franco CFP'}, {'code': 'XPT', 'label': 'Platino'}, {'code': 'XSU', 'label': 'Sucre'}, - {'code': 'XTS', - 'label': 'Códigos reservados específicamente para propósitos de prueba'}, + {'code': 'XTS', 'label': 'Códigos reservados específicamente para propósitos de prueba'}, {'code': 'XUA', 'label': 'Unidad ADB de Cuenta'}, {'code': 'XXX', - 'label': 'Los códigos asignados para las transacciones en que intervenga ninguna ' - 'moneda'}, + 'label': 'Los códigos asignados para las transacciones en que intervenga ninguna moneda'}, {'code': 'YER', 'label': 'Rial yemení'}, {'code': 'ZAR', 'label': 'Rand'}, {'code': 'ZMW', 'label': 'Kwacha zambiano'}, @@ -467,25 +460,13 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'NULL', 'label': 'NULL'}]}, 'estado': {'label': 'Estado / Provincia', 'is_system': True, - 'items': [{'code': 'AGU', - 'label': 'Aguascalientes', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, - {'code': 'BCN', - 'label': 'Baja California', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, - {'code': 'BCS', - 'label': 'Baja California Sur', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, + 'items': [{'code': 'AGU', 'label': 'Aguascalientes', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, + {'code': 'BCN', 'label': 'Baja California', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, + {'code': 'BCS', 'label': 'Baja California Sur', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'CAM', 'label': 'Campeche', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'CHP', 'label': 'Chiapas', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'CHH', 'label': 'Chihuahua', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, - {'code': 'CMX', - 'label': 'Ciudad de México', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, + {'code': 'CMX', 'label': 'Ciudad de México', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'COA', 'label': 'Coahuila', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'COL', 'label': 'Colima', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'DUR', 'label': 'Durango', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, @@ -493,10 +474,7 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'GRO', 'label': 'Guerrero', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'HID', 'label': 'Hidalgo', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'JAL', 'label': 'Jalisco', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, - {'code': 'MEX', - 'label': 'Estado de México', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, + {'code': 'MEX', 'label': 'Estado de México', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'MIC', 'label': 'Michoacán', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'MOR', 'label': 'Morelos', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'NAY', 'label': 'Nayarit', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, @@ -504,14 +482,8 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'OAX', 'label': 'Oaxaca', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'PUE', 'label': 'Puebla', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'QUE', 'label': 'Querétaro', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, - {'code': 'ROO', - 'label': 'Quintana Roo', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, - {'code': 'SLP', - 'label': 'San Luis Potosí', - 'parent_catalog': 'pais', - 'parent_code': 'MEX'}, + {'code': 'ROO', 'label': 'Quintana Roo', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, + {'code': 'SLP', 'label': 'San Luis Potosí', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'SIN', 'label': 'Sinaloa', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'SON', 'label': 'Sonora', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, {'code': 'TAB', 'label': 'Tabasco', 'parent_catalog': 'pais', 'parent_code': 'MEX'}, @@ -544,8 +516,7 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', 'is_system': False, 'items': [{'code': 'naviera', 'label': 'Naviera'}, {'code': 'aerolinea', 'label': 'Aerolínea'}, - {'code': 'transportista_terrestre', - 'label': 'Transportista Terrestre'}, + {'code': 'transportista_terrestre', 'label': 'Transportista Terrestre'}, {'code': 'ferrocarril', 'label': 'Ferrocarril'}, {'code': 'agente_aduanal', 'label': 'Agente Aduanal'}, {'code': 'agente_carga', 'label': 'Agente de Carga'}, @@ -553,7 +524,218 @@ GLOBAL_CATALOGS = {'tipo_registro': {'label': 'Tipo de registro', {'code': 'almacen', 'label': 'Almacén'}, {'code': 'aseguradora', 'label': 'Aseguradora'}, {'code': 'paqueteria', 'label': 'Paquetería'}, - {'code': 'otro', 'label': 'Otro'}]}} + {'code': 'otro', 'label': 'Otro'}]}, + 'tipo_equipo': {'label': 'Tipo de equipo / contenedor', + 'is_system': True, + 'items': [{'code': '40DC', + 'label': "40' Standard", + 'extra': {'modo': 'maritimo', + 'largo_m': 12.035, + 'ancho_m': 2.35, + 'alto_m': 2.392, + 'capacidad_m3': 67.7, + 'tara_kg': 3700, + 'carga_max_kg': 26790}}, + {'code': '20DC', + 'label': "20' Standard", + 'extra': {'modo': 'maritimo', + 'largo_m': 5.9, + 'ancho_m': 2.35, + 'alto_m': 2.392, + 'capacidad_m3': 33.2, + 'tara_kg': 2230, + 'carga_max_kg': 21770}}, + {'code': '20OT', + 'label': "20' Open Top", + 'extra': {'modo': 'maritimo', + 'largo_m': 5.894, + 'ancho_m': 2.311, + 'alto_m': 2.354, + 'capacidad_m3': 32.23, + 'tara_kg': 2400, + 'carga_max_kg': 30490}}, + {'code': '20FR', + 'label': "20' Flat Rack", + 'extra': {'modo': 'maritimo', + 'largo_m': 5.62, + 'ancho_m': 2.23, + 'alto_m': 2.233, + 'tara_kg': 2530, + 'carga_max_kg': 21470}}, + {'code': '40HC', + 'label': "40' High Cube", + 'extra': {'modo': 'maritimo', + 'largo_m': 12.036, + 'ancho_m': 2.35, + 'alto_m': 2.697, + 'capacidad_m3': 76.3, + 'tara_kg': 3970, + 'carga_max_kg': 26510}}, + {'code': '20PL', + 'label': "20' Platform", + 'extra': {'modo': 'maritimo', + 'largo_m': 6.058, + 'ancho_m': 2.438, + 'alto_m': 0.37, + 'tara_kg': 2520, + 'carga_max_kg': 27960}}, + {'code': '20FRC', + 'label': "20' Flat Rack Collapsible", + 'extra': {'modo': 'maritimo', + 'largo_m': 5.618, + 'ancho_m': 2.206, + 'alto_m': 2.233, + 'tara_kg': 2750, + 'carga_max_kg': 27730}}, + {'code': '20BK', + 'label': "20' Bulk", + 'extra': {'modo': 'maritimo', + 'largo_m': 5.93, + 'ancho_m': 2.35, + 'alto_m': 2.34, + 'capacidad_m3': 32.0, + 'tara_kg': 2450, + 'carga_max_kg': 21350}}, + {'code': '20TK', + 'label': "20' Tank", + 'extra': {'modo': 'maritimo', + 'largo_m': 6.058, + 'ancho_m': 2.438, + 'alto_m': 2.438, + 'tara_kg': 4100, + 'carga_max_kg': 26200}}, + {'code': 'LD2', + 'label': 'LD2', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 3.5, + 'tara_kg': 30, + 'carga_max_kg': 1225, + 'nota': 'Aviones 767'}}, + {'code': 'LD3', + 'label': 'LD3', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 4.2, + 'tara_kg': 80, + 'carga_max_kg': 1587, + 'nota': 'B747/B777/DC10/MD-11/A310/A330/A340'}}, + {'code': 'LBD', + 'label': 'LBD (Flex Door)', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 7.0, + 'tara_kg': 123, + 'carga_max_kg': 2449, + 'nota': 'Aviones 767'}}, + {'code': 'LD6', + 'label': 'LD6', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 8.9, + 'tara_kg': 175, + 'carga_max_kg': 3175, + 'nota': 'B747/B777/DC10/MD-11/A310/A330/A340'}}, + {'code': 'PAG', + 'label': 'PAP / PIP / PAG', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 10.0, + 'tara_kg': 120, + 'carga_max_kg': 6033, + 'nota': 'Boeing 747/767/777/DC10'}}, + {'code': 'LD9', + 'label': 'LD9 AAP', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 10.0, + 'tara_kg': 85, + 'carga_max_kg': 1588, + 'nota': 'Boeing 747/777/DC10'}}, + {'code': 'XAW', + 'label': 'XAW', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 14.0, + 'tara_kg': 170, + 'carga_max_kg': 5000, + 'nota': 'Boeing 747/777/DC10'}}, + {'code': 'PMC', + 'label': 'PMC', + 'extra': {'modo': 'aereo', + 'capacidad_m3': 12.7, + 'tara_kg': 130, + 'carga_max_kg': 6804, + 'nota': 'Boeing 747/767/777'}}, + {'code': 'LD8', + 'label': 'LD8', + 'extra': {'modo': 'aereo', 'capacidad_m3': 7.2, 'tara_kg': 120, 'carga_max_kg': 2450}}, + {'code': 'DV48', + 'label': "Dry Van 48'", + 'extra': {'modo': 'terrestre', + 'largo_m': 14.63, + 'ancho_m': 2.59, + 'alto_m': 2.3, + 'capacidad_m3': 98.0, + 'carga_max_kg': 20412, + 'pallets': 22}}, + {'code': 'SD', + 'label': 'Legal Step Deck (Single Drop)', + 'extra': {'modo': 'terrestre', + 'largo_m': 11.58, + 'ancho_m': 2.59, + 'alto_m': 3.05, + 'carga_max_kg': 20865}}, + {'code': 'TANK', + 'label': 'Tanker', + 'extra': {'modo': 'terrestre', + 'largo_m': 16.15, + 'ancho_m': 2.59, + 'alto_m': 2.3, + 'capacidad_l': 22712}}, + {'code': 'DV53', + 'label': "Dry Van 53'", + 'extra': {'modo': 'terrestre', + 'largo_m': 16.15, + 'ancho_m': 2.59, + 'alto_m': 2.3, + 'capacidad_m3': 99.11, + 'carga_max_kg': 20412, + 'pallets': 26}}, + {'code': 'DD', + 'label': 'Double Drop (Low Boy)', + 'extra': {'modo': 'terrestre', + 'largo_m': 8.53, + 'ancho_m': 2.59, + 'alto_m': 3.51, + 'carga_max_kg': 18144}}, + {'code': 'RF48', + 'label': "48' Reefer Trailer", + 'extra': {'modo': 'terrestre', + 'largo_m': 14.63, + 'ancho_m': 2.4, + 'alto_m': 2.3, + 'capacidad_m3': 90.0, + 'carga_max_kg': 19958, + 'pallets': 20}}, + {'code': 'FB48', + 'label': "48' Legal Flatbed", + 'extra': {'modo': 'terrestre', + 'largo_m': 14.63, + 'ancho_m': 2.59, + 'alto_m': 2.59, + 'carga_max_kg': 21772}}, + {'code': 'PUP28', + 'label': "Pup Trailer 28'", + 'extra': {'modo': 'terrestre', + 'largo_m': 8.53, + 'ancho_m': 2.59, + 'alto_m': 2.3, + 'capacidad_m3': 57.45, + 'carga_max_kg': 9979, + 'pallets': 14}}, + {'code': 'IM53', + 'label': "Intermodal 53' Container", + 'extra': {'modo': 'terrestre', + 'largo_m': 16.15, + 'ancho_m': 2.59, + 'alto_m': 2.3, + 'capacidad_m3': 99.11, + 'carga_max_kg': 19958, + 'pallets': 24}}]}} TENANT_CATALOG_LABELS = {'servicio': 'Servicios que ofrece', 'puerto': 'Puertos donde opera', diff --git a/frontend/src/lib/api/crm/catalogs.ts b/frontend/src/lib/api/crm/catalogs.ts index 3d66d8a..0901d6f 100644 --- a/frontend/src/lib/api/crm/catalogs.ts +++ b/frontend/src/lib/api/crm/catalogs.ts @@ -15,6 +15,7 @@ export interface CatalogItem { sort_order: number; is_active: boolean; is_system: boolean; + extra?: Record | null; } export interface CatalogMeta {