a
    Veir                     @   s   d Z ddlmZmZmZ ddlmZmZ ddlZddlZej	
ej	ej	ej	ej	ej	e ddlmZ ddlmZ G dd dZd	d
 ZdS )uz  
Módulo de Solicitud de Vuelos.

Este módulo gestiona todo el flujo de creación de solicitudes de vuelo:
1. Obtención de catálogos (centros de costos)
2. Validación de datos básicos
3. Validación de centro de costos
4. Validación de proyecto (si existe)
5. Validación de reglas de negocio
6. Generación de folio
7. Inserción en base de datos
8. Respuesta al cliente
    )jsonifyrender_templaterequest)datetimedateN)SolicitudVueloSQL)RulesValidatorc                   @   sH   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dS )SolicitudVueloControlleru   
    Controlador principal para el módulo de Solicitud de Vuelos.
    
    Esta clase maneja toda la lógica de negocio para crear solicitudes de vuelo,
    incluyendo validaciones, generación de folios e inserción en base de datos.
    c                 C   s   t  | _t | _dS )zInicializa el controlador.N)r   sqlr   Zrules_validator)self r   M/var/www/html/src/App/Global_Module/AdminSolicitudes/Vuelos/SolicitudVuelo.py__init__*   s    z!SolicitudVueloController.__init__c              
   C   s  z|t d t d t d t d | |}|d sZt d|d   dd	|d d
W S t d t d |d}| j|}|d st d|d   d|d dW S t d|d d   |d}d}|rd| rdt d| d | j|}|d s&t d|d   d|d dW S |d sLt d dd| ddW S t d|d d   nt d  t d! | |}|d st d"|d   dd#|d d
W S t d$ t d% | |}	t d& t d' | j	|	}
|
d( st d)|
d   dd*|
d d+W S |
d, }|
d- }t d.| d/|  t d0 |d1g }|r| 
|}| j||}|d( st d2|d   dd3|d d+W S t d4|d5   nt d6 t d7 |d8g }|r$| |}| j||}|d( st d9|d   dd:|d d+W S t d;|d5   nt d< t d t d= t d>|  t d?|  t d@ dAdB||t|t|dCdDW S  ty } z>t dEt|  dFdl}|  ddGt|d+W  Y d}~S d}~0 0 dS )HuD  
        🎯 FUNCIÓN ORQUESTADORA PRINCIPAL
        
        Esta función coordina todo el flujo de creación de una solicitud de vuelo.
        
        FLUJO DE EJECUCIÓN:
        1. Creación estructura de datos recibidos
        2. Validar centro de costos (existe y está activo)
        3. Validar proyecto en ERP (si se proporcionó)
        4. Validar reglas de negocio (kilometraje, anticipación, etc.)
        5. Generar folio único
        6. Insertar solicitud principal
        7. Insertar pasajeros
        8. Insertar opciones de vuelo
        9. Retornar respuesta exitosa con folio
        
        Args:
            datos_json (dict): Diccionario con todos los datos de la solicitud (camelCase)
            
        Returns:
            dict: Respuesta estructurada con success, mensaje, datos o errores
        Q
================================================================================u.   🎯 INICIANDO CREACIÓN DE SOLICITUD DE VUELOP================================================================================u.   
📋 PASO 1: Validando estructura de datos...validou   ❌ Estructura inválida: erroresFu   Datos incompletos o inválidos)successmensajer   u   ✅ Estructura válidau+   
💰 PASO 2: Validando centro de costos...centroCostosexisteu    ❌ Centro de costos inválido: errorr   r   u   ✅ Centro de costos válido: datosZ
NombreCeCoproyectoNu"   
📁 PASO 3: Validando proyecto 'z' en ERP...u   ❌ Proyecto inválido: Zvigenteu   ❌ Proyecto no vigentezEl proyecto "u   " no está vigente en el ERPu   ✅ Proyecto válido: ZNombreProyectou5   
ℹ️  PASO 3: Sin proyecto especificado (opcional)u,   
📏 PASO 4: Validando reglas de negocio...u$   ❌ Reglas de negocio no cumplidas: z#No se cumplen las reglas de negociou)   ✅ Todas las reglas de negocio cumplidasu1   
📦 PASO 5: Preparando datos para inserción...u   ✅ Datos preparadosu/   
💾 PASO 6: Insertando solicitud principal...r   u!   ❌ Error al insertar solicitud: zError al guardar la solicitudr   r   r   flight_request_idfoliou   ✅ Solicitud insertada - ID: z	, Folio: u%   
👥 PASO 7: Insertando pasajeros...	pasajerosu!   ❌ Error al insertar pasajeros: zError al guardar pasajerosu   ✅ Pasajeros insertados: Z
insertadosu#   ℹ️  Sin pasajeros para insertaru0   
✈️  PASO 8: Insertando opciones de vuelo...vuelosu   ❌ Error al insertar vuelos: z"Error al guardar opciones de vuelou   ✅ Vuelos insertados: u+   ℹ️  Sin opciones de vuelo para insertaru+   🎉 SOLICITUD DE VUELO CREADA EXITOSAMENTEu   📄 Folio: u	   🆔 ID: zQ================================================================================
Tz&Solicitud de vuelo creada exitosamente)ZpasajerosInsertadosZvuelosInsertados)r   r   r   ZflightRequestIdr   u   
❌ ERROR CRÍTICO: r   Error al procesar la solicitud)print_validar_estructura_datosgetr
   Zvalidar_centro_costosstripZvalidar_proyecto_erp_validar_reglas_negocio_preparar_datos_solicitudZinsertar_solicitud_preparar_pasajerosZinsertar_pasajeros_preparar_vuelosZinsertar_vueloslen	Exceptionstr	traceback	print_exc)r   
datos_jsonZvalidacion_estructuraZcentro_costosZresultado_ccr   Zvigencia_proyectoZresultado_proyectoZvalidacion_reglasZdatos_solicitudZresultado_insertr   r   r   pasajeros_preparadosZresultado_pasajerosr   vuelos_preparadosZresultado_vueloser,   r   r   r   crear_solicitud_vuelo3   s    













z.SolicitudVueloController.crear_solicitud_vueloc                 C   s  g }g d}|D ]$}||vs$|| s| d|  qd|v rx|d }ddg}|D ]$}||vsf|| sR| d|  qRd|v rt|d trt|d dkr| d	 d
|v rt|d
 ts| d n*t|d
 dk r| dt|d
  d n
| d t|dk|dS )u   
        Valida que los datos recibidos tengan la estructura mínima requerida.
        
        Args:
            datos (dict): Datos del frontend en camelCase
            
        Returns:
            dict: {'valido': bool, 'errores': list}
        )r   descripcionorigendestinofechasr   zCampo obligatorio faltante: r6   salida
horaSalidaz%Campo de fecha obligatorio faltante: r   r   Debe haber al menos un pasajeror   z"El campo vuelos debe ser una lista   u5   Se requieren mínimo 3 opciones de vuelo (recibidas: )zEl campo vuelos es obligatorior   r   )append
isinstancelistr)   )r   r   r   campos_obligatorioscampor6   Zcampos_fecha_obligatoriosr   r   r   r"      s.    
	


z2SolicitudVueloController._validar_estructura_datosc              
   C   s(  g }z| di }| d}|s6|d d|dW S t|d }| d}d}|rzt|d }||k rz|d	 t }||k r|d
 || j}	|	dk rtd|	 d W np ty }
 z |dt	|
  W Y d}
~
nBd}
~
0  t
y( }
 z |dt	|
  W Y d}
~
n
d}
~
0 0 | di }|rzL| dd}d|v rt|dddd}|dk rtd| d W n8 t
y }
 ztdt	|
  W Y d}
~
n
d}
~
0 0 | dg }t|dkr|d | dg }t|dk r|d t| d! t|dk|dS )"u  
        Valida las reglas de negocio específicas para solicitudes de vuelo.
        
        Por ejemplo:
        - Kilometraje mínimo para requerir vuelo
        - Anticipación mínima
        - Equipaje máximo
        
        Args:
            datos (dict): Datos de la solicitud en camelCase
            
        Returns:
            dict: {'valido': bool, 'errores': list}
        r6   r7   z!La fecha de salida es obligatoriaFr<   z%Y-%m-%dregresoNz>La fecha de regreso no puede ser anterior a la fecha de salidaz,La fecha de salida no puede ser en el pasado   u+   ⚠️  ADVERTENCIA: Anticipación de solo u    días (recomendado: 7+ días)zError en formato de fecha: zError al validar fechas: 
distancias	carretera0 kmkm km ,d   u+   ⚠️  ADVERTENCIA: Kilometraje muy bajo (z km)u(   ⚠️  No se pudo validar kilometraje: r   r   r9   r   r:   u2   Se requieren mínimo 3 opciones de vuelo (actual: r;   )r#   r=   r   strptimer   todaydaysr!   
ValueErrorr+   r*   floatreplacer)   )r   r   r   r6   Zfecha_salida_strZfecha_salidaZfecha_regreso_strZfecha_regresoZhoyZdias_anticipacionr1   rD   kilometraje_strkilometrajer   r   r   r   r   r%   9  sV    





(*

(

z0SolicitudVueloController._validar_reglas_negocioc           
      C   s   | di }| di }t|tr.| ddnt|}| di }t|trX| ddnt|}| di }| dd}d	|v rt|d
dddnd}	| d| dd| d||	| d| d| d| dddS )u(  
        Prepara los datos de la solicitud principal para inserción en BD.
        Convierte de camelCase (frontend) a formato SQL.
        
        Args:
            datos (dict): Datos del frontend en camelCase
            
        Returns:
            dict: Datos preparados para SQL
        r6   r4   namerI   r5   rD   rE   rF   rG   rH   rJ   g        r   r   Nr3   r7   rB   r8   ZhoraRegresoSYSTEM)ZCentroCostosZProyectoZVigenciaProyectoZDescripcionMotivoZDestinoZKilometrajeViajeZFechaSalidaZFechaRegresoZHoraAproxSalidaZHoraAproxRegreso	CreatedBy)r#   r>   dictr+   rP   rQ   )
r   r   r6   Z
origen_objZ
origen_strZdestino_objZdestino_strrD   rR   rS   r   r   r   r&     s(    $z2SolicitudVueloController._preparar_datos_solicitudc                 C   s   g }t |ddD ]\}}|d|d|d|d|dd|dd	|d
|d|dd	d	dd	d	d	|dd|d|d|d}|| q|S )u?  
        Prepara los datos de pasajeros para inserción en BD.
        Convierte de camelCase (frontend) a formato SQL.
        
        Args:
            lista_pasajeros (list): Lista de pasajeros del frontend en camelCase
            
        Returns:
            list: Lista de pasajeros preparados para SQL
           startZnombreCompletoZnumeroEmpleadoempresaZfechaNacimientoZidentificacionOficialZINENZnacionalidademailtelefonoFZrequiereEquipajeZcantidadMaletasZexcesoEquipaje)ZNombrePasajeroZNumeroEmpleadoZEmpresaZFechaNacimientoZTipoIdentificacionZNumeroIdentificacionZVigenciaIdentificacionZNacionalidadZCorreoElectronicoTelefonoZNumeroPasaporteZVigenciaPasaporteZTieneVisaVigenteZTipoVisaZVigenciaVisaZPaisVisaZRequiereEquipajeExtraZCantidadMaletasZExcesoEquipajeKgZOrdenPasajero)	enumerater#   r=   )r   Zlista_pasajerosr/   idxZpasajeroZpasajero_preparador   r   r   r'     s2    

z,SolicitudVueloController._preparar_pasajerosc              	   C   sP   g }t |ddD ]:\}}|d|ddt|dd|d}|| q|S )	u>  
        Prepara los datos de opciones de vuelo para inserción en BD.
        Convierte de camelCase (frontend) a formato SQL.
        
        Args:
            lista_vuelos (list): Lista de vuelos del frontend en camelCase
            
        Returns:
            list: Lista de vuelos preparados para SQL
        rX   rY   Z	aerolineaZnumeroVueloNZ
costoTotalr   )Z	AerolineaZNumeroVueloZ
FechaVueloZ
CostoTotalZOrdenPreferencia)r_   r#   rP   r=   )r   Zlista_vuelosr0   r`   ZvueloZvuelo_preparador   r   r   r(     s    z)SolicitudVueloController._preparar_vuelosN)__name__
__module____qualname____doc__r   r2   r"   r%   r&   r'   r(   r   r   r   r   r	   "   s   	 J=f((r	   c                    sz   t   | jddgddd }| jddgd fdd}| jd	dgdd
d }| jddgd fdd}td dS )u   
    Registra las rutas de Flask para el módulo de Solicitud de Vuelos.
    
    Args:
        app: Instancia de Flask
        mail: Instancia de Flask-Mail (para envío de correos si es necesario)
    z./Global/AdminSolicitudes/Vuelos/SolicitudVueloGET)methodsc                   S   s   t dS )u   
        Renderiza la página HTML del módulo de Solicitud de Vuelos.
        
        Returns:
            HTML renderizado
        z2Global/AdminSolicitudes/Vuelos/SolicitudVuelo.html)r   r   r   r   r   solicitud_vuelo_page  s    z6ejecutar_solicitud_vuelo.<locals>.solicitud_vuelo_pagez=/Global/AdminSolicitudes/Vuelos/SolicitudVuelo/centros-costosc               
      s   zxt d  j } | d rJt dt| d   td| d ddfW S t d| d	   td
d| d	 ddfW S W n^ ty } zFt dt|  ddl}|  td
dt|ddfW  Y d}~S d}~0 0 dS )z
        Endpoint para obtener todos los centros de costos activos.
        
        Returns:
            JSON con lista de centros de costos
        u;   
📥 GET /centros-costos - Obteniendo centros de costos...r   u!   ✅ Centros de costos obtenidos: centrosT)r   rh      u   ❌ Error: r   Fz"Error al obtener centros de costosr     u   ❌ ERROR EN ENDPOINT: r   N)	r!   r
   obtener_centros_costosr)   r   r*   r+   r,   r-   )	resultador1   r,   
controllerr   r   rk   +  s<    

z8ejecutar_solicitud_vuelo.<locals>.obtener_centros_costosz3/Global/AdminSolicitudes/Vuelos/SolicitudVuelo/testc                   S   s    t ddt dddddS )u   
        Ruta de prueba para verificar que el backend funciona correctamente.
        
        Returns:
            JSON con mensaje de éxito
        Tu;   ¡Backend de Solicitud de Vuelos funcionando correctamente!z%Y-%m-%d %H:%M:%SzSolicitud de Vuelosz1.0)r   r   	timestampmoduloversionaxios_ready)r   r   nowstrftimer   r   r   r   test_solicitud_vueloU  s    z6ejecutar_solicitud_vuelo.<locals>.test_solicitud_vueloz4/Global/AdminSolicitudes/Vuelos/SolicitudVuelo/crearPOSTc               
      s4  zt d t d t d t } | sBt d tddddfW S t d	 t d
| d  t d| dd  t dt| dg   t dt| dg    | }|d rdnd}t||fW S  ty. } zFt dt|  ddl	}|
  tddt|ddfW  Y d}~S d}~0 0 dS )u!  
        Endpoint para crear una nueva solicitud de vuelo.
        
        Recibe JSON con toda la información de la solicitud en camelCase y ejecuta
        el flujo completo de validación e inserción.
        
        Returns:
            JSON con resultado de la operación
        r   u%   📥 RECIBIENDO PETICIÓN POST /crearr   u(   ❌ No se recibieron datos en el requestFzNo se recibieron datosr   i  u!   ✅ Datos recibidos correctamenteu   📊 Centro de Costos: r   u   📊 Proyecto: r   zN/Au   📊 Pasajeros: r   u   📊 Vuelos: r   r   ri   u   
❌ ERROR EN ENDPOINT: r   Nr    r   rj   )r!   r   get_jsonr   r#   r)   r2   r*   r+   r,   r-   )r.   rl   status_coder1   r,   rm   r   r   crear_solicitud_vuelo_endpointj  s@    
z@ejecutar_solicitud_vuelo.<locals>.crear_solicitud_vuelo_endpointu9   ✅ Rutas de Solicitud de Vuelo registradas correctamenteN)r	   router!   )appmailrg   rk   ru   ry   r   rm   r   ejecutar_solicitud_vuelo  s    

)
2r}   )rd   flaskr   r   r   r   r   sysospathr=   dirnameabspath__file__Z>Consultas_SQL.Global.AdminSolicitudes.Vuelos.SolicitudVueloSQLr   Z App.Utilities_module.RulesGlobalr   r	   r}   r   r   r   r   <module>   s   4   n