-- =============================================================================
-- ERP TRANSPORTISTAS - Schema Compliance DDL
-- =============================================================================
-- Archivo: 08-compliance-schema-ddl.sql
-- Version: 1.0.0
-- Fecha: 2026-01-25
-- Descripcion: Carta Porte CFDI 3.1, HOS, inspecciones, NOM-087/068
-- =============================================================================

-- =============================================================================
-- TIPOS ENUMERADOS
-- =============================================================================

CREATE TYPE compliance.estado_carta_porte AS ENUM (
  'BORRADOR',
  'VALIDADA',
  'TIMBRADA',
  'CANCELADA'
);

CREATE TYPE compliance.tipo_cfdi_carta_porte AS ENUM (
  'INGRESO',  -- Servicio de transporte
  'TRASLADO'  -- Traslado propio
);

CREATE TYPE compliance.estado_hos AS ENUM (
  'DRIVING',       -- Conduciendo
  'ON_DUTY',       -- En servicio (no conduciendo)
  'SLEEPER',       -- En litera
  'OFF_DUTY'       -- Fuera de servicio
);

-- =============================================================================
-- TABLA: cartas_porte
-- =============================================================================

CREATE TABLE compliance.cartas_porte (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),

  -- Viaje relacionado
  viaje_id UUID NOT NULL,

  -- CFDI
  tipo_cfdi compliance.tipo_cfdi_carta_porte NOT NULL,
  version_carta_porte VARCHAR(10) DEFAULT '3.1',

  -- Identificación CFDI
  serie VARCHAR(10),
  folio VARCHAR(20),
  uuid_cfdi UUID,
  fecha_timbrado TIMESTAMPTZ,

  -- Emisor
  emisor_rfc VARCHAR(13) NOT NULL,
  emisor_nombre VARCHAR(200) NOT NULL,
  emisor_regimen_fiscal VARCHAR(10),

  -- Receptor (para Ingreso) / Propietario (para Traslado)
  receptor_rfc VARCHAR(13) NOT NULL,
  receptor_nombre VARCHAR(200) NOT NULL,
  receptor_uso_cfdi VARCHAR(10),
  receptor_domicilio_fiscal_cp VARCHAR(10),

  -- Totales CFDI
  subtotal DECIMAL(15, 2),
  total DECIMAL(15, 2),
  moneda VARCHAR(3) DEFAULT 'MXN',

  -- Datos transporte federal
  transporte_internacional BOOLEAN DEFAULT FALSE,
  entrada_salida_merc VARCHAR(10), -- 'Entrada' o 'Salida'
  pais_origen_destino VARCHAR(3),

  -- Datos específicos autotransporte
  permiso_sct VARCHAR(50),
  num_permiso_sct VARCHAR(50),
  config_vehicular VARCHAR(10), -- C2, C3, T3S2, etc.
  peso_bruto_total DECIMAL(12, 3),
  unidad_peso VARCHAR(10) DEFAULT 'KGM',
  num_total_mercancias INT,

  -- Seguro
  asegura_resp_civil VARCHAR(100),
  poliza_resp_civil VARCHAR(50),
  asegura_med_ambiente VARCHAR(100),
  poliza_med_ambiente VARCHAR(50),
  asegura_carga VARCHAR(100),
  poliza_carga VARCHAR(50),
  prima_seguro DECIMAL(15, 2),

  -- Estado
  estado compliance.estado_carta_porte DEFAULT 'BORRADOR',

  -- XML y PDF
  xml_cfdi TEXT,
  xml_carta_porte TEXT,
  pdf_url TEXT,
  qr_url TEXT,

  -- Cancelación
  fecha_cancelacion TIMESTAMPTZ,
  motivo_cancelacion TEXT,
  uuid_sustitucion UUID,

  -- Auditoría
  created_at TIMESTAMPTZ DEFAULT NOW(),
  created_by_id UUID NOT NULL,
  updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_carta_porte_tenant ON compliance.cartas_porte(tenant_id);
CREATE INDEX idx_carta_porte_viaje ON compliance.cartas_porte(viaje_id);
CREATE INDEX idx_carta_porte_uuid ON compliance.cartas_porte(uuid_cfdi);
CREATE INDEX idx_carta_porte_estado ON compliance.cartas_porte(tenant_id, estado);

-- =============================================================================
-- TABLA: ubicaciones_carta_porte
-- =============================================================================

CREATE TABLE compliance.ubicaciones_carta_porte (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),
  carta_porte_id UUID NOT NULL REFERENCES compliance.cartas_porte(id),

  -- Tipo
  tipo_ubicacion VARCHAR(10) NOT NULL, -- 'Origen' o 'Destino'

  -- ID Ubicación (catálogo SAT)
  id_ubicacion VARCHAR(10),

  -- RFC
  rfc_remitente_destinatario VARCHAR(13),
  nombre_remitente_destinatario VARCHAR(200),

  -- Domicilio
  pais VARCHAR(3) DEFAULT 'MEX',
  estado VARCHAR(10), -- Clave SAT
  municipio VARCHAR(10), -- Clave SAT
  localidad VARCHAR(10),
  codigo_postal VARCHAR(10) NOT NULL,
  colonia VARCHAR(10),
  calle VARCHAR(200),
  numero_exterior VARCHAR(50),
  numero_interior VARCHAR(50),
  referencia VARCHAR(500),

  -- Fechas
  fecha_hora_salida_llegada TIMESTAMPTZ,

  -- Distancia
  distancia_recorrida DECIMAL(10, 2), -- Solo para destinos

  -- Secuencia (orden en la ruta)
  secuencia INT NOT NULL
);

CREATE INDEX idx_ubicacion_carta ON compliance.ubicaciones_carta_porte(carta_porte_id);

-- =============================================================================
-- TABLA: mercancias_carta_porte
-- =============================================================================

CREATE TABLE compliance.mercancias_carta_porte (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),
  carta_porte_id UUID NOT NULL REFERENCES compliance.cartas_porte(id),

  -- Bienes transportados
  bienes_transp VARCHAR(10) NOT NULL, -- Clave SAT
  descripcion VARCHAR(1000) NOT NULL,
  cantidad DECIMAL(14, 3) NOT NULL,
  clave_unidad VARCHAR(10) NOT NULL, -- Clave SAT
  unidad VARCHAR(50),

  -- Dimensiones
  peso_en_kg DECIMAL(14, 3) NOT NULL,
  largo_cm DECIMAL(10, 2),
  ancho_cm DECIMAL(10, 2),
  alto_cm DECIMAL(10, 2),

  -- Valor
  valor_mercancia DECIMAL(15, 2),
  moneda VARCHAR(3) DEFAULT 'MXN',

  -- Material peligroso
  material_peligroso BOOLEAN DEFAULT FALSE,
  cve_material_peligroso VARCHAR(10),
  tipo_embalaje VARCHAR(10),
  descripcion_embalaje VARCHAR(200),

  -- Fracción arancelaria (comercio exterior)
  fraccion_arancelaria VARCHAR(10),
  uuid_comercio_ext UUID,

  -- Pedimentos (comercio exterior)
  pedimentos TEXT[], -- Array de números de pedimento

  -- Guías (paquetería)
  guias TEXT[], -- Array de números de guía

  -- Secuencia
  secuencia INT NOT NULL
);

CREATE INDEX idx_mercancia_carta ON compliance.mercancias_carta_porte(carta_porte_id);

-- =============================================================================
-- TABLA: figuras_transporte (Operador, propietario, arrendatario)
-- =============================================================================

CREATE TABLE compliance.figuras_transporte (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),
  carta_porte_id UUID NOT NULL REFERENCES compliance.cartas_porte(id),

  -- Tipo de figura
  tipo_figura VARCHAR(10) NOT NULL, -- '01'=Operador, '02'=Propietario, '03'=Arrendador

  -- Datos
  rfc_figura VARCHAR(13),
  nombre_figura VARCHAR(200),
  num_licencia VARCHAR(50), -- Solo para operadores

  -- Domicilio (opcional)
  pais VARCHAR(3),
  estado VARCHAR(10),
  codigo_postal VARCHAR(10),
  calle VARCHAR(200),

  -- Partes transporte (solo para Propietario/Arrendador)
  partes_transporte JSONB -- Array de {parte_transporte: string}
);

CREATE INDEX idx_figura_carta ON compliance.figuras_transporte(carta_porte_id);

-- =============================================================================
-- TABLA: autotransporte_carta_porte
-- =============================================================================

CREATE TABLE compliance.autotransporte_carta_porte (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),
  carta_porte_id UUID NOT NULL REFERENCES compliance.cartas_porte(id),

  -- Permiso
  perm_sct VARCHAR(10) NOT NULL, -- Tipo permiso SAT
  num_permiso_sct VARCHAR(50) NOT NULL,

  -- Identificación vehicular tractora
  config_vehicular VARCHAR(10) NOT NULL, -- C2, C3, T3S2, etc.
  placa_vm VARCHAR(15) NOT NULL,
  anio_modelo_vm INT,

  -- Remolques (puede haber hasta 2)
  remolques JSONB -- Array de {sub_tipo_rem, placa}
);

CREATE INDEX idx_autotransporte_carta ON compliance.autotransporte_carta_porte(carta_porte_id);

-- =============================================================================
-- TABLA: hos_logs (Hours of Service - NOM-087)
-- =============================================================================

CREATE TABLE compliance.hos_logs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),

  -- Operador y viaje
  operador_id UUID NOT NULL,
  viaje_id UUID,

  -- Log
  fecha DATE NOT NULL,
  hora_inicio TIME NOT NULL,
  hora_fin TIME,
  duracion_minutos INT,

  -- Estado
  estado compliance.estado_hos NOT NULL,

  -- Ubicación
  latitud DECIMAL(10, 7),
  longitud DECIMAL(10, 7),
  ubicacion_descripcion VARCHAR(200),

  -- Odómetro
  odometro_inicio INT,
  odometro_fin INT,

  -- Observaciones
  observaciones TEXT,

  -- Certificado
  certificado_por_operador BOOLEAN DEFAULT FALSE,
  certificado_fecha TIMESTAMPTZ,

  -- Auditoría
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_hos_operador ON compliance.hos_logs(operador_id);
CREATE INDEX idx_hos_fecha ON compliance.hos_logs(tenant_id, fecha);
CREATE INDEX idx_hos_viaje ON compliance.hos_logs(viaje_id);

-- =============================================================================
-- TABLA: hos_resumen_diario
-- =============================================================================

CREATE TABLE compliance.hos_resumen_diario (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),

  operador_id UUID NOT NULL,
  fecha DATE NOT NULL,

  -- Horas por estado
  horas_driving DECIMAL(4, 2) DEFAULT 0,
  horas_on_duty DECIMAL(4, 2) DEFAULT 0,
  horas_sleeper DECIMAL(4, 2) DEFAULT 0,
  horas_off_duty DECIMAL(4, 2) DEFAULT 0,
  horas_totales DECIMAL(4, 2) DEFAULT 0,

  -- Cumplimiento NOM-087
  horas_conduccion_disponibles DECIMAL(4, 2),
  horas_servicio_disponibles DECIMAL(4, 2),
  en_cumplimiento BOOLEAN DEFAULT TRUE,
  violaciones TEXT[],

  -- Acumulados (ciclo de 7 días)
  horas_conduccion_ciclo DECIMAL(5, 2),
  horas_servicio_ciclo DECIMAL(5, 2),

  -- Certificación
  certificado BOOLEAN DEFAULT FALSE,
  certificado_fecha TIMESTAMPTZ,

  CONSTRAINT uq_hos_resumen UNIQUE (operador_id, fecha)
);

CREATE INDEX idx_hos_resumen_operador ON compliance.hos_resumen_diario(operador_id);
CREATE INDEX idx_hos_resumen_fecha ON compliance.hos_resumen_diario(tenant_id, fecha);

-- =============================================================================
-- TABLA: inspecciones_pre_viaje
-- =============================================================================

CREATE TABLE compliance.inspecciones_pre_viaje (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES public.tenants(id),

  -- Viaje y unidad
  viaje_id UUID NOT NULL,
  unidad_id UUID NOT NULL,
  remolque_id UUID,
  operador_id UUID NOT NULL,

  -- Fecha
  fecha_inspeccion TIMESTAMPTZ NOT NULL,

  -- Resultado general
  aprobada BOOLEAN DEFAULT FALSE,

  -- Items checklist (JSON con resultados)
  checklist_items JSONB NOT NULL,
  -- Ejemplo: [{ "item": "Frenos", "estado": "OK", "observacion": null }, ...]

  -- Defectos encontrados
  defectos_encontrados TEXT[],
  defectos_criticos INT DEFAULT 0,
  defectos_menores INT DEFAULT 0,

  -- Firma
  firma_operador TEXT, -- Base64
  firma_fecha TIMESTAMPTZ,

  -- Evidencias
  fotos JSONB, -- URLs de fotos

  -- Auditoría
  created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_inspeccion_viaje ON compliance.inspecciones_pre_viaje(viaje_id);
CREATE INDEX idx_inspeccion_unidad ON compliance.inspecciones_pre_viaje(unidad_id);
CREATE INDEX idx_inspeccion_fecha ON compliance.inspecciones_pre_viaje(tenant_id, fecha_inspeccion);

-- =============================================================================
-- RLS POLICIES
-- =============================================================================

ALTER TABLE compliance.cartas_porte ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.ubicaciones_carta_porte ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.mercancias_carta_porte ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.figuras_transporte ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.autotransporte_carta_porte ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.hos_logs ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.hos_resumen_diario ENABLE ROW LEVEL SECURITY;
ALTER TABLE compliance.inspecciones_pre_viaje ENABLE ROW LEVEL SECURITY;

CREATE POLICY tenant_isolation_cartas ON compliance.cartas_porte
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_ubicaciones ON compliance.ubicaciones_carta_porte
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_mercancias ON compliance.mercancias_carta_porte
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_figuras ON compliance.figuras_transporte
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_autotransporte ON compliance.autotransporte_carta_porte
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_hos ON compliance.hos_logs
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_hos_resumen ON compliance.hos_resumen_diario
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

CREATE POLICY tenant_isolation_inspecciones ON compliance.inspecciones_pre_viaje
  USING (tenant_id = current_setting('app.tenant_id')::uuid);

-- =============================================================================
-- COMENTARIOS
-- =============================================================================

COMMENT ON TABLE compliance.cartas_porte IS 'CFDI con complemento Carta Porte 3.1';
COMMENT ON TABLE compliance.ubicaciones_carta_porte IS 'Ubicaciones origen/destino de la carta porte';
COMMENT ON TABLE compliance.mercancias_carta_porte IS 'Mercancías transportadas en la carta porte';
COMMENT ON TABLE compliance.figuras_transporte IS 'Figuras de transporte (operador, propietario, arrendador)';
COMMENT ON TABLE compliance.autotransporte_carta_porte IS 'Datos del autotransporte federal';
COMMENT ON TABLE compliance.hos_logs IS 'Registros de horas de servicio (NOM-087)';
COMMENT ON TABLE compliance.hos_resumen_diario IS 'Resumen diario de HOS por operador';
COMMENT ON TABLE compliance.inspecciones_pre_viaje IS 'Inspecciones pre-viaje de unidades';

-- =============================================================================
-- FIN DDL COMPLIANCE
-- =============================================================================
