/** * Utilidades de formato y catálogos de etiquetas para el CRM. */ export interface Option { value: string; label: string; } export function formatMoney(value: number | null | undefined, currency = 'MXN'): string { if (value === null || value === undefined) return '—'; return new Intl.NumberFormat('es-MX', { style: 'currency', currency }).format(Number(value)); } export function formatDate(value: string | null | undefined): string { if (!value) return '—'; const d = new Date(value); if (Number.isNaN(d.getTime())) return '—'; return d.toLocaleDateString('es-MX', { year: 'numeric', month: 'short', day: 'numeric' }); } export function labelOf(list: Option[], value: string | null | undefined): string { if (!value) return '—'; return list.find((x) => x.value === value)?.label ?? value; } // ----- Clientes / Prospectos ----- export const RECORD_TYPES: Option[] = [ { value: 'cliente', label: 'Cliente' }, { value: 'prospecto', label: 'Prospecto' } ]; export const PERSON_TYPES: Option[] = [ { value: 'fisica', label: 'Física' }, { value: 'moral', label: 'Moral' } ]; export const ACCOUNT_STATUS: Option[] = [ { value: 'active', label: 'Activo' }, { value: 'inactive', label: 'Inactivo' } ]; export const COMMERCIAL_CLASSIFICATION: Option[] = [ { value: 'importador', label: 'Importador' }, { value: 'exportador', label: 'Exportador' }, { value: 'importador_exportador', label: 'Importador / Exportador' } ]; export const ACCOUNT_TYPES: Option[] = [ { value: 'importador', label: 'Importador' }, { value: 'exportador', label: 'Exportador' }, { value: 'immex', label: 'IMMEX / Maquila' }, { value: 'agencia_aduanal', label: 'Agencia aduanal' }, { value: 'transportista', label: 'Transportista' }, { value: 'otro', label: 'Otro' } ]; export const CONTACT_METHODS: Option[] = [ { value: 'llamada', label: 'Llamada telefónica' }, { value: 'correo', label: 'Correo electrónico' }, { value: 'videoconferencia', label: 'Videoconferencia' }, { value: 'whatsapp', label: 'WhatsApp' }, { value: 'otro', label: 'Otro' } ]; // ----- Proveedores ----- export const SUPPLIER_CLASSIFICATIONS: Option[] = [ { value: 'naviera', label: 'Naviera' }, { value: 'aerolinea', label: 'Aerolínea' }, { value: 'transportista_terrestre', label: 'Transportista terrestre' }, { value: 'ferrocarril', label: 'Ferrocarril' }, { value: 'agente_aduanal', label: 'Agente aduanal' }, { value: 'agente_carga', label: 'Agente de carga' }, { value: 'agente_corresponsal', label: 'Agente corresponsal' }, { value: 'almacen', label: 'Almacén' }, { value: 'aseguradora', label: 'Aseguradora' }, { value: 'paqueteria', label: 'Paquetería' }, { value: 'otro', label: 'Otro' } ]; export const COVERAGE: Option[] = [ { value: 'nacional', label: 'Nacional' }, { value: 'internacional', label: 'Internacional' }, { value: 'ambos', label: 'Nacional e internacional' } ]; // ----- Direcciones ----- export const ADDRESS_TYPES: Option[] = [ { value: 'fiscal', label: 'Fiscal' }, { value: 'oficina', label: 'Oficina' }, { value: 'sucursal', label: 'Sucursal' }, { value: 'bodega', label: 'Bodega' }, { value: 'patio', label: 'Patio' }, { value: 'terminal', label: 'Terminal' }, { value: 'almacen', label: 'Almacén' } ]; // ----- Documentos ----- export const DOC_TYPES: Option[] = [ { value: 'constancia_fiscal', label: 'Constancia de Situación Fiscal' }, { value: 'acta_constitutiva', label: 'Acta Constitutiva' }, { value: 'identificacion', label: 'Identificación Oficial' }, { value: 'comprobante_domicilio', label: 'Comprobante de Domicilio' }, { value: 'contrato', label: 'Contrato' }, { value: 'presentacion', label: 'Presentación Comercial' }, { value: 'certificacion', label: 'Certificación' }, { value: 'licencia', label: 'Licencia' }, { value: 'convenio', label: 'Convenio' }, { value: 'tarifario', label: 'Tarifario' }, { value: 'otro', label: 'Otro' } ]; // ----- Contactos ----- export const CONTACT_AREAS: Option[] = [ { value: 'ventas', label: 'Ventas' }, { value: 'operaciones', label: 'Operaciones' }, { value: 'facturacion', label: 'Facturación' }, { value: 'cobranza', label: 'Cobranza' }, { value: 'servicio_cliente', label: 'Servicio al Cliente' }, { value: 'otro', label: 'Otro' } ]; export const CONTACT_STATUS: Option[] = [ { value: 'active', label: 'Activo' }, { value: 'inactive', label: 'Inactivo' } ]; // ----- Prospectos (leads / funnel) ----- export const LEAD_SOURCES: Option[] = [ { value: 'web', label: 'Web' }, { value: 'referido', label: 'Referido' }, { value: 'evento', label: 'Evento' }, { value: 'llamada', label: 'Llamada' }, { value: 'email', label: 'Email' }, { value: 'otro', label: 'Otro' } ]; export const LEAD_STATUS: Option[] = [ { value: 'new', label: 'Nuevo' }, { value: 'contacted', label: 'Contactado' }, { value: 'qualified', label: 'Calificado' }, { value: 'unqualified', label: 'No calificado' }, { value: 'converted', label: 'Convertido' } ]; // ----- Actividades ----- export const ACTIVITY_TYPES: Option[] = [ { value: 'call', label: 'Llamada' }, { value: 'meeting', label: 'Reunión' }, { value: 'task', label: 'Tarea' }, { value: 'email', label: 'Correo' }, { value: 'note', label: 'Nota' } ]; export const ACTIVITY_STATUS: Option[] = [ { value: 'pending', label: 'Pendiente' }, { value: 'completed', label: 'Completada' }, { value: 'canceled', label: 'Cancelada' } ]; // ----- Comercial: Solicitudes / Cotizaciones ----- export const OPERATION_TYPES: Option[] = [ { value: 'importacion', label: 'Importación' }, { value: 'exportacion', label: 'Exportación' } ]; export const TRANSPORT_MODES: Option[] = [ { value: 'maritimo', label: 'Marítimo' }, { value: 'aereo', label: 'Aéreo' }, { value: 'terrestre', label: 'Terrestre' }, { value: 'ferroviario', label: 'Ferroviario' }, { value: 'multimodal', label: 'Multimodal' } ]; export const SERVICE_TYPES: Option[] = [ { value: 'puerto_puerto', label: 'Puerto – Puerto' }, { value: 'puerto_puerta', label: 'Puerto – Puerta' }, { value: 'puerta_puerto', label: 'Puerta – Puerto' }, { value: 'puerta_puerta', label: 'Puerta – Puerta (Door to Door)' } ]; export const LOAD_TYPES: Option[] = [ { value: 'FCL', label: 'FCL (contenedor completo)' }, { value: 'LCL', label: 'LCL (carga consolidada)' }, { value: 'AMBAS', label: 'Ambas (comparar FCL y LCL)' }, { value: 'AEREO', label: 'Aéreo (carga aérea)' } ]; export const PRIORITIES: Option[] = [ { value: 'baja', label: 'Baja' }, { value: 'normal', label: 'Normal' }, { value: 'alta', label: 'Alta' }, { value: 'urgente', label: 'Urgente' } ]; // Pestañas del formulario de solicitud de servicio (documento maestro de cotización) export const SR_FORM_TABS: Option[] = [ { value: 'datos', label: 'Datos' }, { value: 'ruta', label: 'Servicio y ruta' }, { value: 'mercancia', label: 'Mercancía' }, { value: 'dimensiones', label: 'Dimensiones' }, { value: 'servicios', label: 'Servicios' }, { value: 'notas', label: 'Notas' } ]; export const SR_STATUS: Option[] = [ { value: 'nueva', label: 'Nueva' }, { value: 'contacto', label: 'Contacto realizado' }, { value: 'en_analisis', label: 'En análisis' }, { value: 'cotizada', label: 'Cotizada' }, { value: 'aceptada', label: 'Aceptada' }, { value: 'rechazada', label: 'Rechazada' }, { value: 'liberada', label: 'Liberada a operaciones' } ]; export const QUOTE_STATUS: Option[] = [ { value: 'borrador', label: 'Borrador' }, { value: 'enviada', label: 'Enviada' }, { value: 'aceptada', label: 'Aceptada' }, { value: 'rechazada', label: 'Rechazada' } ]; export const QUOTE_CONCEPTS: Option[] = [ { value: 'flete_internacional', label: 'Flete internacional' }, { value: 'transporte_terrestre', label: 'Transporte terrestre' }, { value: 'despacho_aduanal', label: 'Despacho aduanal' }, { value: 'gastos_destino', label: 'Gastos en destino' }, { value: 'otros', label: 'Otros cargos' } ]; export const RATE_STATUS: Option[] = [ { value: 'solicitada', label: 'Solicitada' }, { value: 'recibida', label: 'Recibida' }, { value: 'declinada', label: 'Declinada' } ]; // ----- Operaciones: Embarques ----- export const SHIPMENT_STATUS: Option[] = [ { value: 'abierta', label: 'Abierta' }, { value: 'booking', label: 'Booking' }, { value: 'en_transito', label: 'En tránsito' }, { value: 'arribado', label: 'Arribado' }, { value: 'entregada', label: 'Entregada' }, { value: 'cerrada', label: 'Cerrada' }, { value: 'cancelada', label: 'Cancelada' } ]; export const DOC_KINDS: Option[] = [ { value: 'master', label: 'Master' }, { value: 'house', label: 'House' }, { value: 'otro', label: 'Otro' } ]; // ----- Bitácora del embarque: hitos y decisiones ----- export const EVENT_STATUS: Option[] = [ { value: 'pendiente', label: 'Pendiente' }, { value: 'completado', label: 'Completado' }, { value: 'omitido', label: 'Omitido' }, { value: 'rechazado', label: 'Rechazado' }, { value: 'en_correccion', label: 'En corrección' } ]; export const EVENT_OUTCOME: Option[] = [ { value: 'autorizado', label: 'Autorizado' }, { value: 'rechazado', label: 'Rechazado' } ]; // ----- Facturación ----- export const INVOICE_STATUS: Option[] = [ { value: 'borrador', label: 'Borrador' }, { value: 'emitida', label: 'Emitida' }, { value: 'enviada', label: 'Enviada' }, { value: 'en_revision_cliente', label: 'En revisión del cliente' }, { value: 'pagada', label: 'Pagada' }, { value: 'cancelada', label: 'Cancelada' } ]; export const PAYMENT_METHODS: Option[] = [ { value: 'transferencia', label: 'Transferencia' }, { value: 'efectivo', label: 'Efectivo' }, { value: 'cheque', label: 'Cheque' }, { value: 'tarjeta', label: 'Tarjeta' }, { value: 'otro', label: 'Otro' } ]; export const SHIPMENT_DOC_TYPES: Option[] = [ { value: 'MBL', label: 'MBL (Master Bill of Lading)' }, { value: 'HBL', label: 'HBL (House Bill of Lading)' }, { value: 'MAWB', label: 'MAWB (Master Air Waybill)' }, { value: 'HAWB', label: 'HAWB (House Air Waybill)' }, { value: 'CMR', label: 'CMR (Carta Porte Internacional)' }, { value: 'factura_comercial', label: 'Factura Comercial' }, { value: 'packing_list', label: 'Packing List' }, { value: 'carta_encomienda', label: 'Carta Encomienda' }, { value: 'carta_garantia', label: 'Carta Garantía' }, { value: 'certificado_permiso', label: 'Certificado / Permiso' }, { value: 'otro', label: 'Otro' } ];