+
    :maiF                     j   R t ^ RIt^ RIt^ RIHtHtHt ]P                  P                  ]P                  P                  ]P                  P                  ]P                  P                  ]P                  P                  ]
4      4      4      4      4       ^ RIHt  ! R R4      tR	R ltR
R ltRR ltR# )u  
Módulo de Validación de Reglas Globales.

Este módulo proporciona un validador genérico que evalúa datos contra
reglas definidas en la tabla RulesGlobal de la base de datos.

Características:
- Validación por módulo completo
- Validación de reglas específicas
- Soporte para operadores: >, <, >=, <=, =, !=, BETWEEN
- Soporte para tipos de datos: Number, Date
- Mensajes de error configurables desde BD
N)datetimedate	timedelta)RulesGlobalSQLc                   N   a  ] tR t^t o RtR tR tR tR tR t	R t
R tR	tV tR
# )RulesValidatoru  
Validador genérico de reglas de negocio.

Esta clase permite validar datos contra reglas definidas en la tabla RulesGlobal.
Soporta validación por módulo completo o por regla específica.

Ejemplo de uso:
    validator = RulesValidator()
    
    # Validar todo un módulo
    resultado = validator.validar_reglas('FR_FlightRequest', {
        'kilometraje': 350,
        'fecha_salida': '2025-01-20'
    })
    
    # Validar regla específica
    resultado = validator.validar_regla_especifica('KM_MIN', 350)
c                $    \        4       V n        R# )z"Inicializa el validador de reglas.N)r   sqlselfs   &Nc:\Users\victor.cervantes\Desktop\Elep\src\App\Utilities_module\RulesGlobal.py__init__RulesValidator.__init__2   s    !#    c           	        \        RR( 24       \        RV 24       \        R( 4       . p^ p^ pV P                  P                  V4      pVR,          '       g+   \        RVR,           24       RRRR	VR,           2.R
^ R^ /# VR,          pV'       g   \        RV 24       RRR. R
^ R^ /# \        R\        V4       24       V EF  pV^,          pVR,          p	\        RR) 24       \        RV	 RVR,           24       W9  d   \        RV	 R24       KS  W),          p
\        RV
 24       \        RVR,           24       \        RVR,           24       V P	                  VR,          V
VR,          VR,          VR,          R7      pVR,          '       g5   V^,          pVR,          pVP                  V4       \        RV 24       EK  \        R 4       EK  	  \        RR( 24       \        R!4       \        R( 4       \        R"V 24       \        R#WE,
           24       \        R$V 24       \        R%V^ 8X  d   R&MR' 24       \        R( R24       R\        V4      ^ 8H  RVR
VRV/# )*u  
Valida todas las reglas activas de un módulo específico.

Este método obtiene todas las reglas del módulo desde la BD y
valida los datos proporcionados contra cada regla.

Args:
    module_id (str): ID del módulo (ej: 'FR_FlightRequest')
    datos (dict): Diccionario con los datos a validar
                 Las keys deben coincidir con los RuleCode
                 
Returns:
    dict: {
        'valido': bool,           # True si todas las reglas pasan
        'errores': list,          # Lista de mensajes de error
        'reglas_evaluadas': int,  # Cantidad de reglas evaluadas
        'reglas_fallidas': int    # Cantidad de reglas que fallaron
    }
    
Ejemplo:
    datos = {
        'KM_MIN': 350,              # Para regla de kilometraje mínimo
        'ANTICIP_DIAS': '2025-01-20' # Para regla de anticipación
    }
    resultado = validator.validar_reglas('FR_FlightRequest', datos)

u#   🔍 VALIDANDO REGLAS DEL MÓDULO: successu   ❌ Error al obtener reglas: errorvalidoFerroreszError al cargar reglas: reglas_evaluadasreglas_fallidasreglasu3   ℹ️  No hay reglas configuradas para el módulo Tu   📋 Reglas encontradas: RuleCodezEvaluando regla: z - RuleNameu   ⚠️  Dato 'u5   ' no proporcionado en los datos, saltando validaciónz   Valor a validar: z   Operador: ComparisonOperatorz   Valor esperado: 	RuleValue
RuleValue2	ValueTypeoperatorvalor_actualvalor_esperadovalor_esperado2
value_typeMessageIfViolatedu      ❌ FALLA: u      ✅ PASAu   📊 RESUMEN DE VALIDACIÓNz   Reglas evaluadas: z   Reglas que pasaron: z   Reglas que fallaron: z   Resultado: u   ✅ VÁLIDOu   ❌ INVÁLIDOzP================================================================================u   ────────────────────────────────────────────────────────────────────────────────)printr	   obtener_reglas_por_modulolen_validar_comparacionappend)r   	module_iddatosr   r   r   resultado_sqlr   regla	rule_coder!   resultado_validacionmensaje_errors   &&&          r   validar_reglasRulesValidator.validar_reglas:   s   6 	6(m3I;?@ ::9EY''1-2H1IJK%6}W7M6NOP"A!1	  x(G	{ST$2"A!1	  	)#f+78 E!j)IBxj/"%i[E*4E3FGH %yk1fgh +L(78M%(<"=!>?@'k(:';<= $(#<#<34)$[1 %l 3 - $= $  (111$ %&9 :}-}o67%A F 	6(m+-%&6%789'(8(J'KLM((9:;10D}/Z[\m c'la'w 0	
 	
r   c                   \        RV 24       \        RV 24       V P                  P                  V4      pVR,          '       g#   \        RVR,           24       RRRVR,          /# VR	,          pV P                  VR
,          VVR,          VR,          VR,          R7      pVR,          '       g   VR,          p\        RV 24       RRRV/# \        R4       RRRR/# )u  
Valida una regla específica por su código.

Args:
    rule_code (str): Código de la regla (ej: 'KM_MIN')
    valor: Valor a validar (puede ser int, float, str, date)
    
Returns:
    dict: {
        'valido': bool,
        'mensaje': str (solo si no es válido)
    }
u#   
🔍 Validando regla específica: z
   Valor: r   u   ❌ Error: r   r   Fmensajer.   r   r   r   r   r   r%   u   ❌ FALLA: u   ✅ PASATN)r&   r	   obtener_regla_por_codigor)   )r   r/   valorr-   r.   r0   r5   s   &&&    r   validar_regla_especifica'RulesValidator.validar_regla_especifica   s    	4YK@A
5'"# 99)DY''Kg 6789%=1 
 g&  $88/0 -!,/[)  9  
 $H--/0GKy)*%7 
 	dt
 	
r   c                    V P                  W%4      pV P                  W54      pVR8X  d   V'       d   V P                  WE4      pVR8X  d   Wg8  p	MpVR8X  d   Wg8  p	MdVR8X  d   Wg8  p	MXVR8X  d   Wg8*  p	MLVR8X  d   Wg8H  p	M@VR8X  d   Wg8g  p	M4VR8X  d%   V'       g   RR	R
R/# Yvu;8*  ;'       d    X8*  Mu p	M	RR	R
RV 2/# RV	R
R/#   \         d   p
RR	R
R\        T
4       2/u Rp
?
# Rp
?
ii ; i)u  
Valida una comparación según el operador y tipo de dato.

Args:
    operator (str): Operador (>, <, >=, <=, =, !=, BETWEEN)
    valor_actual: Valor actual a validar
    valor_esperado: Valor esperado de la regla
    valor_esperado2: Segundo valor esperado (para BETWEEN)
    value_type (str): Tipo de dato (Number, Date)
    
Returns:
    dict: {
        'valido': bool,
        'detalle': str (opcional)
    }
BETWEEN><z>=z<==z!=r   Fdetallez$Operador BETWEEN requiere RuleValue2zOperador no soportado: Nu   Error en validación: )_convertir_tipo	Exceptionstr)r   r    r!   r"   r#   r$   valor_actual_convertidovalor_esperado_convertidovalor_esperado2_convertidor   es   &&&&&&     r   r)   #RulesValidator._validar_comparacion   s>   "3	&*&:&:<&T#(,(<(<^(X% 9$-1-A-A/-^* 30LS0LT!0MT!0MS0MT!0MY&& %!#I  3kkQkk e!8
C  &4 
  	%3CF8< 	s5   0C A'C C !C  C C-C("C-(C-c                   Vf   R#  VR8X  d   \        V\        \        34      '       d   \        V4      # \        V\        4      '       d~   VP	                  4       P                  4       pVP                  RR4      P                  RR4      pVP                  RR4      P                  RR4      pVP	                  4       p\        V4      # \        V4      # VR8X  d   \        V\        \        34      '       d)   \        V\        4      '       d   V# VP                  4       # \        V\        4      '       dA   . ROpV F(  p \        P                  ! W4      P                  4       u # 	  \        R	V 24      hV# \        V4      #   \         d     KU  i ; i  \         d#   p\        R
T RT R\        T4       24      hRp?ii ; i)z
Convierte un valor al tipo de dato correcto.

Args:
    valor: Valor a convertir
    value_type (str): Tipo de dato ('Number', 'Date')
    
Returns:
    Valor convertido (int, float, date, o str)
    
Raises:
    ValueError: Si no se puede convertir
NNumberkm kgu   díasdiasDatezNo se pudo parsear fecha: zError al convertir 'z
' a tipo 'z': )%Y-%m-%dz%d/%m/%Yz%d-%m-%Yz%Y/%m/%d)
isinstanceintfloatrB   striplowerreplacer   r   strptime
ValueErrorrA   )r   r7   r$   valor_limpioformatosformatorF   s   &&&    r   r@   RulesValidator._convertir_tipo,  s    =/	^X%ec5\22 <' eS))#(;;=#6#6#8L#/#7#7b#A#I#I$PR#SL#/#7#7#D#L#LVUW#XL#/#5#5#7L ..U|#v%edH%566$.ud$;$;5MM eS)) H $,%#+#4#4U#D#I#I#KK $, %'A%%IJJ 5z!  * %$%  	^3E7*ZLPSTWXYTZS[\]]	^se   -F BF 	
F :F F F ?#F"F %F 7
F FF FF GF<<Gc                6    V P                   P                  4       # )u   
Obtiene todas las reglas activas del sistema.
Útil para debugging o administración.

Returns:
    dict: Resultado de la consulta SQL
)r	   obtener_todas_reglas_activasr
   s   &r   obtener_todas_reglas#RulesValidator.obtener_todas_reglasr  s     xx4466r   c                l    V P                   P                  V4      pVR,          ;'       d
    VR,          # )u   
Verifica si una regla existe y está activa.

Args:
    rule_code (str): Código de la regla
    
Returns:
    bool: True si existe y está activa
r   existe)r	   verificar_existencia_regla)r   r/   	resultados   && r   verificar_regla_existe%RulesValidator.verificar_regla_existe|  s0     HH77	B	#;;	((;;r   )r	   N)__name__
__module____qualname____firstlineno____doc__r   r2   r8   r)   r@   r^   rd   __static_attributes____classdictcell__)__classdict__s   @r   r   r      s:     &$n
h2
pDL@^L7< <r   r   c                f     \        V 4      pW!8  d   RRRR/# RRRRV RV R2/#    RRRR	/u # ; i)
u   
Valida que el kilometraje sea mayor o igual al mínimo establecido.

Args:
    kilometraje (float): Kilometraje del viaje
    km_minimo (float): Kilometraje mínimo requerido (default: 300)
    
Returns:
    dict: {'valido': bool, 'mensaje': str}
r   Tr5   NFz$El kilometraje debe ser de al menos z km. Actual: z kmu   Kilometraje inválido)rR   )kilometraje	km_minimorJ   s   && r   validar_kilometraje_minimorq     so    
;?$4  %A)MZ\Y]]`a 
e.
 	
s   & & 0c                    \        V \        4      '       d'   \        P                  ! V R4      P	                  4       pM)\        V \        4      '       d   V P	                  4       pMT p\        P
                  ! 4       \        VR7      ,           pW#8  d   RRRR/# W2,
          P                  pRRRRV R	V R
2/#    RRRR/u # ; i)u  
Valida que la fecha de salida tenga la anticipación requerida.

Args:
    fecha_salida (str o date): Fecha de salida del viaje
    dias_anticipacion (int): Días de anticipación requeridos (default: 7)
    
Returns:
    dict: {'valido': bool, 'mensaje': str}
rO   )daysr   Tr5   NFz%Debe solicitar el vuelo con al menos u     días de anticipación. Faltan u    díasu   Fecha de salida inválida)rP   rB   r   rV   r   todayr   rs   )fecha_salidadias_anticipacionfechafecha_minimadias_faltantess   &&   r   validar_anticipacion_diasrz     s    
lC((%%lJ?DDFEh// %%'E Ezz|i5F&GG $4 
 +288N%BCTBUUu  wE  vF  FL  M 
e2
 	
s   BB8 B8 8Cc                     . pV ^8  d   VP                  R4       Ve   V^8  d   VP                  RV R24       V'       d   RRRRP                  V4      /# RR	RR/#    RRRR
/u # ; i)uY  
Valida que el equipaje cumpla con los límites establecidos.

Reglas:
- Máximo 1 maleta documentada
- Peso máximo por maleta: 23 kg
- Equipaje de mano: 10 kg

Args:
    cantidad_maletas (int): Cantidad de maletas documentadas
    exceso_kg (float): Exceso de equipaje en kg (opcional)
    
Returns:
    dict: {'valido': bool, 'mensaje': str}
u&   Máximo 1 maleta documentada permitidaNu-   El peso máximo por maleta es 23 kg. Actual: z kgr   Fr5   z; Tu   Datos de equipaje inválidos)r*   join)cantidad_maletas	exceso_kgr   s   && r   validar_equipaje_pasajeror     s     
 aNNCD  Y^NNJ9+UXYZ%499W-  dt
 	

e5
 	
s   AA A A A))i,  )   )N)rj   sysosr   r   r   pathr*   dirnameabspath__file__&Consultas_SQL.Utilities.RulesGlobalSQLr   r   rq   rz   r    r   r   <module>r      s     	 . . PX@Y0Z [\ ] Ai< i<`
<%
P)
r   