
    sz0i                     v   S SK r S SKrS SKrS SKJr  S SKJr  S SKJr  S SK	J
r
Jr  S SKJrJrJr  S SKJrJr  \ R&                  " SS	5      r\S
:X  a  \O\
rSrSrSr\R2                  " SS5        \R2                  " SS5        \R2                  " SS5        \R2                  " SS5         " S S5      rSS jrS rg)    N)BytesIO)datetime)jsonify)DevelopmentConfigProductionConfig)obtener_catalogo_validacionguardar_log_validacionobtener_cantidades_componentes)ValidadorTiposDatoslimpiar_dataframe	FLASK_ENVdevelopment
productionzhttps://igsa1-my.sharepoint.com/personal/alexis_moreno_igsa_com_mx/_layouts/15/download.aspx?share=EStyzV5jqTRGqhyxo4jfzmIBYCfPhbrU4xMICcpWqMSqiwScoreV2zdisplay.max_columnszdisplay.max_rowszdisplay.widthzdisplay.max_colwidth2   c                   f    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rSrg)ValidadorScore!   u7   
Clase principal para manejar la validación del Score
c                     [         U l        [        U l        [        U l        U R                  5       U l        S U l        S U l	        / U l
        [        R                  " 5       R                  S5      U l        g )Nz%Y%m%d_%H%M%S)url_sharepoint_globalurl_sharepointnombre_hoja_globalnombre_hojanombre_tabla_excel_globalnombre_tabla_excel_obtener_ruta_descargaruta_descargacatalogo_validaciondf_scoreerrores_validacionr   nowstrftime	timestamp)selfs    qC:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\SupyCtrol_Module\IngenieroControl\ValidarScore.py__init__ValidadorScore.__init__&   sZ    3-";!88:#' "$!00A    c                     [         S:X  a  SnO4[        R                  R                  [        R                  " 5       SS5      n[        R
                  " USS9  U$ )ul   
1.2 Configura la ruta de descarga según el ambiente

Returns:
    str: Ruta donde se guardará el archivo
r   z)/var/www/elephant/temp/score_validacionestempscore_validacionesT)exist_ok)r   ospathjoingetcwdmakedirs)r$   rutas     r%   r   %ValidadorScore._obtener_ruta_descarga0   sE     $>D 77<<		V5IJD 	D4(r(   c                      [        5       U l        U R                  (       d  [        S5        g[        S[        U R                  5       S35        g! [         a!  n[        S[        U5       35         SnAgSnAff = f)u   
1.3 Consulta la tabla CM_DataTypeValidator y crea el diccionario

Returns:
    bool: True si se inicializó correctamente, False en caso contrario
u5   Error: No se pudo obtener el catálogo de validaciónFu"   Catálogo de validación cargado: 	 columnasTu    Error al inicializar catálogo: N)r   r   printlen	Exceptionstr)r$   es     r%   inicializar_catalogo#ValidadorScore.inicializar_catalogoC   sp    	'B'DD$++MN6s4;S;S7T6UU^_` 	4SVH=>	s   +A "A 
A<A77A<c                 P    [        S5        [        R                  " U R                  SS9nUR                  S:w  a  [        SUR                   35        gSU R
                   S3n[        R                  R                  U R                  U5      n[        US	5       nUR                  UR                  5        SSS5        [        S
U 35        [        S:X  a  U R                  5         U$ ! , (       d  f       N8= f! [         a!  n[        S[!        U5       35         SnAgSnAff = f)zs
2. Descarga el archivo Excel desde SharePoint

Returns:
    str: Ruta del archivo descargado o None si hubo error
z'Descargando archivo desde SharePoint...   )timeout   u   Error al descargar: código NScore_.xlsxwbzArchivo descargado: r   zError al descargar Excel: )r6   requestsgetr   status_coder#   r-   r.   r/   r   openwritecontentr   _limpiar_archivos_antiguosr8   r9   )r$   responsenombre_archivoruta_completafr:   s         r%   descargar_excelValidadorScore.descargar_excelX   s    	;<||D$7$7DH##s*4X5I5I4JKL  &dnn%5U;NGGLL););^LMmT*a(() + (89 L(//1   +*  	.s1vh78	s7   AC: AC: C)71C: )
C73C: :
D%D  D%c                     [         R                  " 5       nUR                  nUR                  nUS::  a  SSU-
  -
  nUS-
  nOUS-
  nUnU US 3n[        R
                  " U R                  5      nU H  nUR                  S5      (       d  M  UR                  S5      (       d  M3   UR                  S5      S   SS	 n	X:  aP  [        R                  R                  U R                  U5      n
[        R                  " U
5        [        S
U 35        M  M     g!    M  = f! [         a!  n[        S[        U5       35         SnAgSnAff = f)z+
2.4 Elimina archivos anteriores a 3 meses
         02drA   rB   _N   zArchivo antiguo eliminado: z$Error al limpiar archivos antiguos: )r   r!   monthyearr-   listdirr   
startswithendswithsplitr.   r/   remover6   r8   r9   )r$   fecha_limite
mes_actual   año_actual
mes_limite   año_limitefecha_limite_strarchivosarchivofecha_archivoruta_archivor:   s               r%   rJ   )ValidadorScore._limpiar_archivos_antiguosz   s8   	C#<<>L%++J&++KQ1z>2
)Ao'!^
)"-z#.>?zz$"4"45H#%%h//G4D4DW4M4M!(/c(:1(=bq(A(;+-77<<8J8JG+TLIIl3!$?y"IJ < $!  	C8QABB	Cs7   BD  D  'A*DD  DD   
E*EEc                 H   SSK Jn  SSKJn  / n [	        S5        [	        S5        [	        S5        [	        S5        [	        SU 35        [	        S	5        U" US
S9n[	        S5        [	        SUR
                   35        [	        SU R                   S35        U R                  UR
                  ;  aC  [	        SU R                   S35        [	        SUR
                   35        UR                  5         U$ XPR                     n[	        S5        [	        SUR                   35        [	        SUR                   35        [	        SUR                   35        [	        S5        0 n[        US   SS9 H=  u  pU	R                  (       d  M  [        U	R                  5      R                  5       Xx'   M?     [	        S[        U5       S35        [	        S5        [!        UR#                  5       5      SS  H  u  p[	        SU
S  S!U 35        M     [        U5      S":  a  [	        S#[        U5      S"-
   S$35        [	        S%5        [	        S&5        [	        S5        SnSnS'n[        UR%                  S(S)9S(S9 GHr  u  nnUS-  nX::  GaE  [	        S*S+ 35        [	        S,U S-U 35        [	        S+ 5        SnSnSn[	        S.5        [        USS/ SS9 H  u  pUR'                  US0U 35      nU	R                  nU	R(                  nU	R*                  nUb  US1:X  a  S2nUS-  nO[        U5      SS3 nUS-  nUU:H  nU(       a  US-  nS4nOS5n[	        S6U S7U S8US9 S:US; S<U S=35        M     [        U5      n[	        S>U S?35        [	        S@U 35        [	        SAU 35        [	        SBU 35        [	        SCU 35        US:  a  [	        SD5        [        USS9 H  u  pU	R(                  U:X  d  M  US-  nUR'                  USEU 35      nU	R                  (       a  [        U	R                  5      OSFnU	R*                  nUR-                  UUUSGSHU 3SI.5        X::  aI  [	        SJU SK35        [	        SLU 35        [	        SMU 35        [	        SNU 35        [	        SOU 35        M  [	        SPU SQU SRU SSU STU 3
5        M     X:  d  GMT  USU-  S:X  d  GM`  [	        SVU SWU SX35        GMu     [	        S*S 35        [	        SY5        UR                  5         [	        SZ5        [	        S*S 35        [	        S[5        [	        S 5        [	        S\UR/                  S]5      S^    35        [	        S_U R                   35        [	        S`U 35        [	        Sa[        U5       35        [	        SbU[        U5      -  Sc 35        US:  a  [	        SdU 35        [	        Se5        0 nU H   nUSf   nUR'                  US5      S-   UU'   M"     [1        UR#                  5       5       H  u  nn [	        SgU S!U  Sh35        M     [	        Si5        [        US5       H)  u  n!n[	        S6U!Sj SkUSl   Sm SnUSo   S9 SnUSf    35        M+     O[	        Sp5        [	        Sq5        [	        S S*35        U$ ! [2         au  n"[	        S*S 35        [	        Sr5        [	        S 5        [	        Ss[        U"5       35        [	        St5        SSKn#U#R7                  5         [	        S S*35        Us Sn"A"$ Sn"A"ff = f)uu  
Detecta errores nativos de Excel usando OpenPyXL
(como #VALOR!, #REF!, #DIV/0!, #N/A, #NAME?, #NULL!, #NUM!)
CON PRINTS DETALLADOS PARA DEBUG

Args:
    ruta_archivo (str): Ruta del archivo Excel
    
Returns:
    list: Lista de errores encontrados en formato estándar
r   )load_workbook)
TYPE_ERRORe
====================================================================================================uB   🔍 INICIANDO DETECCIÓN DE ERRORES NATIVOS DE EXCEL CON OPENPYXLd====================================================================================================u!   
📂 PASO 1: Abriendo archivo...z	   Ruta: u?      Modo: data_only=False (mantiene fórmulas y detecta errores)T)	data_onlyu$      ✅ Archivo abierto correctamenteu      📊 Hojas disponibles: u"   
📄 PASO 2: Seleccionando hoja 'z'...u      ❌ ERROR: Hoja 'z' no encontradaz   Hojas disponibles: u&      ✅ Hoja seleccionada correctamenteu      📏 Dimensiones: u      📊 Filas máximas: u      📊 Columnas máximas: u5   
📋 PASO 3: Leyendo nombres de columnas (fila 1)...rT   )startu      ✅ z columnas detectadasz
   Primeras 10 columnas:N{   z
      Col 2d: 
   z      ... y u    columnas másu>   
🔎 PASO 4: Iniciando búsqueda de errores (desde fila 2)...u9      Se mostrarán las primeras 5 filas de datos en detalle      )min_row
,  ────────────────────────────────────────────────────────────────────────────────────────────────────u
   📍 FILA u    (Fila Excel) - Índice z"   Mostrando primeras 10 columnas:#   Col_    [VACÍO]r   u	   ❌ ERRORu   ✓       [z] z<30 = <40z (tipo: )u   
   📊 Resumen fila :u         • Total celdas: u         • Con valor: u         • Vacías: u         • Con ERROR: u,         ⚠️  ¡FILA CON ERRORES DETECTADOS!Columna_z#ERROR!ERROR_EXCELu&   🚫 Error nativo de Excel detectado: filacolumnavalortipo_esperadoerroru   
      🚨 ERROR #z ENCONTRADO:z         Celda: z         Fila Excel: z         Columna: z         Valor: u      ❌ Error #z: Fila z, Columna 'z' [z]: d   z   ... Procesadas z filas (z errores hasta ahora)...u5   🔒 PASO 5: Cerrando workbook y liberando memoria...u%      ✅ Workbook cerrado correctamenteu;   📊 RESUMEN FINAL - DETECCIÓN DE ERRORES NATIVOS DE EXCELu      📄 Archivo: /u      📋 Hoja: u      📏 Filas procesadas: u      📊 Columnas analizadas: u       🔍 Total celdas revisadas: ,u    
   ⚠️  ERRORES DETECTADOS: z#
   Detalle de errores encontrados:r   u
         • z ocurrencia(s)u#   
   📋 Lista completa de errores:3dz. Fila r   4d | r   u1   
   ✅ NO SE DETECTARON ERRORES NATIVOS DE EXCELu>      🎉 Todas las celdas están libres de errores de fórmulasu4   ❌ ERROR CRÍTICO EN DETECCIÓN DE ERRORES DE EXCEL
   Error: 
   Stack trace completo:)openpyxlrk   openpyxl.cell.cellrl   r6   
sheetnamesr   close
dimensionsmax_row
max_column	enumeratevaluer9   stripr7   listitems	iter_rowsrE   	data_type
coordinateappendr]   sortedr8   	traceback	print_exc)$r$   rh   rk   rl   errores_excelrC   wscolumnascol_idxcellidxnombrecontador_erroresfilas_procesadasMOSTRAR_PRIMERAS_N_FILASrow_idxrowceldas_con_valorceldas_vaciasceldas_con_errornombre_columnar   	tipo_dato
coordenadavalor_mostrares_errormarcadortotal_celdas_filavalor_errortipos_errorr   tipocantidadir:   r   s$                                       r%   _detectar_errores_excel_nativos.ValidadorScore._detectar_errores_excel_nativos   s    	+1O	!.!VW'N
 68Il^,-SU|t<B8:/?@
 78H8H7INOr}}4,T-=-=,>oNO.r}}o>?
$$$$%B:<)"--9:,RZZL9:/?@
 JLH!*2a5!::::(+DJJ(=(=(?H% "; GCM?*>?@.0#HNN$45ds;
3r("VH56  < 8}r!S]R%7$8GH
 SUMO'N  '($ )",,q,*A K A% 
 $?Byk*+Jwi/GHXGYZ[YK)'($$%M'($ >@)23s81)E)1ggY?O)P !%

$(NN	%)__
 !=ERK,6M)Q.M,/JsOM,1, $-
#:#,1,'2H',H xj:,bPS@TTWXefiWjjrs|r}}~  A3 *F8 ),C%3G9A>?45F4GHI12B1CDE/?@12B1CDE'!+ LN
 &/s!%<MG~~3(A-()1g'?S)T9=c$**o%)__
 &,,$+'5%0-:'Mk]%[.  ,G!$89I8J,"WX!$4ZL"AB!$9'"CD!$6~6F"GH!$4[M"BC "N3C2DGG9T_`n_oors}r~  B  CN  BO  #P  Q7 &=< $>CSVYCY]^C^./?.@IYHZZrstu !L~ Bwi.!IKHHJ9;
 Bwi.!OQWI%l&8&8&=b&A%BCDN4#3#3"456./?.@AB1#h-AB45EH5UVW4XYZ!#9:J9KLM<> !*E >D(3a(@1(DK% + '-[->->-@&AND(JtfBxjGH 'B <> )- ;HAuF1R&fb/AU9EUVYDZZ]^cdk^l]mno !< JLVXWIR.!   		!Bwi.!HJWIJs1vh'(.0!WIR.!  		!sA   C$Z" 5BZ" IZ" +CZ" Z" GZ" "
\!,A*\\!\!c                     [        S5        [        R                  " U5      nU R                  UR                  ;  a2  [        SU R                   S35        [        SUR                   35        g[        R
                  " XR                  [        S9U l        U R                  R                   Vs/ s H  o3R                  5       PM     snU R                  l        [        S[        U R                  5       S[        U R                  R                  5       S	35        [        S
5        [        S5        [        S5        [        S[        U R                  5      5      n[        U5       H  nUS-   n[        SS 35        [        SU SU S35        [        S 5        U R                  R                  U/   R                  nS/Ul        U R                  R                  U   R                  5        Hf  u  p[        R                   " U	5      (       a  Sn
OU	S:X  a  Sn
O[        U	5      SS n
[#        U	5      R$                  n[        SUS SU
S SU S35        Mh     M     [        S
5        [        S5        [        S5        [        S 5        [        U R                  R&                  R)                  5       5        [        S!5        U R                  R+                  5       R-                  5       nXS":     n[        U5      S":  a  [        UR)                  5       5        O[        S#5        [        S$5        g%s  snf ! [.         a5  n[        S&[        U5       35        S"SKnUR3                  5          SnAgSnAff = f)'u   
3. Lee el archivo Excel y carga los datos en un DataFrame

Args:
    ruta_archivo (str): Ruta del archivo a leer
    
Returns:
    bool: True si se leyó correctamente, False en caso contrario
zLeyendo archivo Excel...zError: La hoja 'z' no existe en el archivozHojas disponibles: F)
sheet_namedtypeu   Archivo leído correctamente: z filas, r5   z
======================================================================================================================================================u#   📊 PRIMERAS 5 FILAS DEL DATAFRAMEz======================================================================================================================================================rR   rv   rx   u   FILA NÚMERO u    (índice DataFrame: r   Valorz[NULL]r|   r}   Nr     z<45r   z<55r   ]zFIN DE PRIMERAS 5 FILASu    
📋 RESUMEN DE TIPOS DE DATOS:u"   
⚠️  RESUMEN DE VALORES NULOS:r   u   ✓ No hay valores nulosz
======================================================================================================================================================
TzError al leer Excel: )r6   pd	ExcelFiler   sheet_names
read_excelr9   r   columnsr   r7   minrangeilocTr   isnatype__name__dtypes	to_stringisnullsumr8   r   r   )r$   rh   
excel_filecolnum_filas_mostrarr   
fila_excelfila_dfcolumna_nombrer   valor_formateador   nulosnulos_con_datosr:   r   s                   r%   
leer_excelValidadorScore.leer_excel  s   N	,-l3Jz'='==()9)9(::STU+J,B,B+CDE MM,CSCS[^_DM =AMM<Q<Q$R<QSYY[<Q$RDMM!23t}}3E2FhsSWS`S`ShShOiNjjstu .!78'N !$As4=='9 :./ 1W
7)n%j\1Fse1MN	# --,,cU355#*) .2]]-?-?-D-J-J-L)Nwwu~~+3("+5(+.u:ds+;(  ;//DB~c2#6Fs5K2dVSTUV .M 04 .!+,'N 56$--&&0023 78MM((*..0E#AI.O?#a'o//1201'(s %Sv  	)#a&23!		s2   A,L4 /A L4 /L/I&L4 /L4 4
M3>+M..M3c           
         / n U R                   R                  R                  5       n[        U R                  R                  5       5      n[        U5      [        U5      -  n[        U5      S:X  a  UR                  SSS.5        SU4$ [        [        U5      [        U5      -
  5      n[        [        U5      [        U5      -
  5      n[        S5        [        S5        [        S5        [        S	[        U5       35        [        S
5        [        S5        [        [        U5      S5       H  u  px[        SUS SU 35        M     U(       aT  [        S[        U5       35        [        S5        [        S5        [        US5       H  u  px[        SUS SU 35        M     U(       at  [        S[        U5       35        [        S5        [        S5        [        US5       H7  u  pxU R                  R                  US5      n	[        SU SUS SU	 S35        M9     [        S5        [        S5        [        S5        S/ 4$ ! [         a.  n
UR                  SS[        U
5       3S.5        SU4s Sn
A
$ Sn
A
ff = f)u   
4.1 y 4.2 Valida que al menos existan columnas en común
YA NO valida orden ni que sean exactamente las mismas
Solo valida las columnas con Origin = 'Manual'

Returns:
    tuple: (es_valido: bool, errores: list)
r   
ESTRUCTURAu^   No hay columnas en común entre el Excel y el catálogo (Origin=Manual). Verifica los nombres.)r   mensajeFzQ
================================================================================u   ANÁLISIS DE COLUMNASzP================================================================================u:   
✓ Columnas con Origin='Manual' en común para validar: u'   
Listado de columnas que se validarán:zP--------------------------------------------------------------------------------rT   r   rr   . u>   
ℹ️  Columnas en Excel que NO están en catálogo Manual: u1       (Estas columnas se IGNORAN en la validación)u>   
⚠️  Columnas en catálogo Manual que NO están en Excel: u4       (Estas columnas deberían desactivarse en la BD)zN/Ar   z (r   u%   ✓ Validación de estructura exitosazQ================================================================================
TzError al validar estructura: N)r   r   tolistr   r   keyssetr7   r   r   r6   r   rE   r8   r9   )r$   errorescolumnas_excelcolumnas_catalogocolumnas_comunescolumnas_solo_excelcolumnas_solo_catalogor   r   r   r:   s              r%   validar_estructura!ValidadorScore.validar_estructura  sh    7	"!]]2299;N $T%=%=%B%B%D E  #>2S9J5KK#$)(   g~% #)^)<sCT?U)U"V%+C0A,BSEX,X%Y" - )*&MOPSTdPeOfgh<=(O#F+;$<a@1R&3%() A #WX[\oXpWqrsIJh'(;Q?FABqfBse,- @ &WX[\rXsWtuvLMh'(>BFA3377UCDBqcC9BtfA67 C - 9:- 8O 	"NN$:3q6(C  '>!	"s%   BI 	F8I 
I:#I5/I:5I:c                 .    [        U R                  5      n[        U R                  5      u  U l        n[        U R                  5      nX-
  n[        SU S35        UUUS.nXR4$ ! [         a%  n[        S[        U5       35        S/ 4s SnA$ SnAff = f)ut   
4.3 Aplica limpieza y tratamiento al DataFrame

Returns:
    tuple: (dict estadísticas, list errores_eliminacion)
u   ✓ Tratamiento aplicado: z filas eliminadas)filas_originalesfilas_finalesfilas_eliminadaszError al aplicar tratamiento: N)r7   r   r   r6   r8   r9   )r$   r   filas_eliminadas_detaller   r   estadisticasr:   s          r%   aplicar_tratamiento_datos(ValidadorScore.aplicar_tratamiento_datos   s    	"4==1 7H6V3DM3.M/?./?.@@QRS %5!.$4L  99 	23q6(;<8O	s   A"A% %
B/B	BBc           
      j   / n [        S5        [        U R                  R                  R	                  5       5      n[        U R
                  R                  5       5      nX#-  n[        S[        U5       35        [        R                   Vs/ s H  nXT;   d  M
  UPM     nnU(       a  [        SU 35        U H  nU R
                  U   n[        U R                  U   5       Hi  u  p[        R                  " U
UUS9u  pU(       a  M&  UR                  U	S-   U[        R                  " U
5      (       a  [        U
5      SS OSUUS	.5        Mk     M     [        S
[        U5       S35        U$ s  snf ! [          a6  n[        S[        U5       35        SSSSS[        U5       3S	./s SnA$ SnAff = f)u  
5. Valida los tipos de datos SOLO de las columnas que:
- Existen en el Excel
- Existen en el catálogo
- Tienen Origin = 'Manual' (ya filtrado en la consulta SQL)
- INCLUYE validación de campos obligatorios (NOT NULL)

Returns:
    list: Lista de errores encontrados
zValidando tipos de datos...z9Columnas a validar (Origin='Manual' y existen en Excel): u*   ⚠️  Columnas obligatorias (NOT NULL): )r   rv   Nr   r}   r   u   ✓ Validación completada: z errores encontradosz!Error al validar tipos de datos: r   SISTEMAr|      Error crítico: )r6   r   r   r   r   r   r   r7   r   COLUMNAS_OBLIGATORIASr   validar_por_tipo_sqlr   r   notnar9   r8   )r$   r   r   r   columnas_a_validarr   #columnas_obligatorias_en_validacionr   tipo_sqlr   r   	es_validomensaje_errorr:   s                 r%   validar_tipos_datos"ValidadorScore.validar_tipos_datos>  s    4	/0 !6!6!=!=!?@N #D$<$<$A$A$C D "0!CMcRdNeMfgh  3HH3H, H 0 3 3BCfBghi-33G< #,DMM',B"CJC/B/W/W '.0,I %9$'!G'.8:SZ_Z-5%2(  #D	 .* 0W>RSTN=3@  	5c!fX>?$!#+CF84  	s>   BE2 	E-E-A%E2 A$E2 -E2 2
F2<+F-'F2-F2c                     [        U5      [        U5      -   n[        U R                  R                  R	                  5       5      n[        U R
                  R                  5       5      nXV-  n0 nU H,  n	U	R                  SS5      n
UR                  U
S5      S-   X'   M.     U H,  n	U	R                  SS5      n
UR                  U
S5      S-   X'   M.     U R                  [        R                  " 5       R                  S5      US:X  a  SOS	U(       a  UR                  S
S5      OSU(       a  UR                  SS5      OSU(       a  UR                  SS5      OS[        U5      [        U5      [        U5      U[        U5      [        U5      S.	UUUS.S.n[        U(       a  UR                  SS5      OSUU[        R                  " 5       US   S9  U$ ! [         a!  n[        S[        U5       35         SnAgSnAff = f)u5   
5.3 Genera el reporte consolidado de la validación
r   r   r   rT   r   	TIPO_DATO%Y-%m-%d %H:%M:%SEXITOSOCON_ERRORESr   r   r   )	r   r   r   r   columnas_catalogo_manualcolumnas_validadastotal_erroreserrores_estructuraerrores_datos)
estructuradatos)r#   fecha_validacionestador   errores_por_tipor   r  )total_filasr  r  r#   r  zError al generar reporte: N)r7   r   r   r   r   r   r   rE   r#   r   r!   r"   r	   r8   r6   r9   )r$   r  r  stats_tratamientor  r   r   r  r  r   r   reporter:   s                r%   generar_reporte_consolidado*ValidadorScore.generar_reporte_consolidado  s   4	 23c-6HHM !!6!6!=!=!?@N #D$<$<$A$A$C D!/!C!+yy6)9)=)=dA)F)J & , 'yy+>)9)=)=dA)F)J & '
 "^^$,LLN$;$;<O$P'4'9)}Xi(9(=(=>PRS(TopUf(9(=(=oq(QlmXi(9(=(=>PRS(Top&).&9034E0F*-.@*A%2*-.@*A%(%7
! %5"4*!G, #IZ-11/1E`a+!1",,.x( N 	.s1vh78	s   GG 
G>G99G>c                 j   / n [        S5        [        S5        [        S5        [        S5        [        5       nUR                  (       a  [        S5        U$ [        S[        U5       S35        [        S5        [        S	[	        UR
                  5       35        [        S
5        UR
                   H   n[        SU SX#   R                   35        M"     [        SS 35        [        S5        [        S5        [        S[        U5      5      n[        U5       H  n[        SS 35        [        SUS-    35        [        S 5        UR                  U   n[        SUS    35        [        SUS    35        [        SUS    35        [        SUS    35        [        SUS    35        [        SUS    35        [        SUS     35        US   S!:  =(       d    US   S!:  =(       d    US    S!:  nU(       d  M  [        S"5        M     [        SS S35        [        S#5        [        S$5        [        S S35        S%nUR                  5        GH  u  pVUS   n	US   n
[        R                  " US   5      (       a  US   OS&nUS   n[        R                  " U5      (       ag  US!:  aa  US-  nS'U
 3S[        [        U5      5      S(S)U S[        U5       S*3S+.nUR                  U5        [        S,U S-U	 S.[        U5       S/35        US   n[        R                  " U5      (       ag  US!:  aa  US-  nS'U
 3S[        [        U5      5      S(S)U S[        U5       S03S+.nUR                  U5        [        S,U S-U	 S.[        U5       S135        US    n[        R                  " U5      (       d  GMf  US!:  d  GMo  US-  nS'U
 3S [        [        U5      5      S(S)U S[        U5       S23S+.nUR                  U5        [        S,U S-U	 S.[        U5       S335        GM     [        SS 35        [        S45        [        S5        [        S5[        U5       35        [        S6[        U5      [        [!        U Vs/ s H  nUS7   PM
     sn5      5      -
   35        [        S8[        U5       35        [        U5      S%:  a  [        S95        [#        S: U 5       5      n[#        S; U 5       5      n[#        S< U 5       5      nUS%:  a  [        S=U 35        US%:  a  [        S>U 35        US%:  a  [        S?U 35        [        S@5        [%        US5       H'  u  nn[        SAUSB SCUS7    SDUSE    SFUSG    35        M)     O[        SH5        [        SI5        [        S S35        U$ s  snf ! [&         au  n[        SS 35        [        SJ5        [        S 5        [        SK[        U5       35        [        SL5        S%SMKnUR+                  5         [        S S35        Us SMnA$ SMnAff = f)Nu   
Valida que las cantidades de motores, generadores y radiadores no excedan el máximo (1)
mediante consulta SQL INDEPENDIENTE del Excel

Returns:
    list: Lista de errores encontrados donde cantidad >= 2
rm   u=   🔍 INICIANDO VALIDACIÓN DE CANTIDADES DE COMPONENTES (SQL)rn   u(   
📊 PASO 1: Ejecutando consulta SQL...u/   ⚠️  La consulta SQL no devolvió resultadosu   ✅ Consulta ejecutada: z registros obtenidosu$   
📋 Resumen de columnas obtenidas:z   Columnas: z   Tipos de datos:z      - rs   rx   u'   📊 PRIMERAS 5 FILAS DEL RESULTADO SQLru   ry   u   📍 REGISTRO rT   z   OrderNum: OrderNumz   OrderLine: 	OrderLinez   OrderNum&Line: zOrderNum&Linez   JobNum2: JobNum2u      🔧 CantidadDeMotores: CantidadDeMotoresu      ⚡ CantidadDeGeneradores: CantidadDeGeneradoresu"      🌡️  CantidadDeRadiadores: CantidadDeRadiadoresrv   u)      ⚠️  ¡CANTIDAD EXCEDIDA DETECTADA!u$   🔎 PASO 2: Validando cantidades...u'      Criterio: Si cantidad >= 2 → ERRORr   z
Sin JobNumzOrderNum&Line: CANTIDAD_MAXIMAu   ⚠️ JobNum u*    motores detectados (máximo permitido: 1)r   u   ❌ Error #z: OrderNum z - z motoresu.    generadores detectados (máximo permitido: 1)z generadoresu-    radiadores detectados (máximo permitido: 1)z radiadoresu2   📊 RESUMEN FINAL - VALIDACIÓN DE CANTIDADES SQLu      📋 Registros analizados: u      ✅ Registros sin errores: r   u!      ❌ Total errores detectados: u%   
   📋 Detalle de errores por tipo:c              3   :   #    U  H  oS    S:X  d  M  Sv   M     g7f)r   r"  rT   N .0r:   s     r%   	<genexpr>DValidadorScore.validar_cantidades_componentes_sql.<locals>.<genexpr>M  s     %`AiLL_<_aa   	c              3   :   #    U  H  oS    S:X  d  M  Sv   M     g7f)r   r#  rT   Nr'  r(  s     r%   r*  r+  N  s     )hW)Pg@g!!Wr,  c              3   :   #    U  H  oS    S:X  d  M  Sv   M     g7f)r   r$  rT   Nr'  r(  s     r%   r*  r+  O  s     (fGq|Oe?eGr,  u         • Motores excedidos: u!         • Generadores excedidos: u          • Radiadores excedidos: u   
   📋 Lista de errores:r~   r   r   r   r   r   r   u-   
   ✅ NO SE DETECTARON CANTIDADES EXCEDIDASu=      🎉 Todas las órdenes tienen cantidades válidas (0 o 1)u3   ❌ ERROR CRÍTICO EN VALIDACIÓN DE CANTIDADES SQLr   r   N)r6   r
   emptyr7   r   r   r   r   r   r   iterrowsr   r  r9   intr   r   r   r   r8   r   r   )r$   r   df_cantidadesr   r   r   r   tiene_errorr   	order_numorder_line_fulljob_numcantidad_motoresr   cantidad_generadorescantidad_radiadoresr:   errores_motoreserrores_generadoreserrores_radiadoresr   r   s                         r%   "validar_cantidades_componentes_sql1ValidadorScore.validar_cantidades_componentes_sql  s    e	.!QR'N
 =>:<M""GH,S-?,@@TUV 9;M$}'<'<"=!>?@&($,,R(:(@(@'ABC - Bwi.!;<'N #As='9 :./9+&'sQwi01%#((-c*o%678s;'7&89:*3+?*@ABS^$4563C8K4L3MNO6s;R7S6TUV:3?U;V:WXY +,1 5/0A55./14  ;EG/ 02 Bwir"#
 89;=WIR.! )224
O	"%o"6,.HHS^,D,D#i.,
 $'':#; 88,--2Ba2G$)$"1/1B C#6!$S)9%:!;):#1'"SAQ=R<SS}!~E NN5)K(8'9YKsSVWgShRiiqrs
 (++B'C$880116Ja6O$)$"1/1B C#:!$S)=%>!?):#1'"SAU=V<W  XF  "GE NN5)K(8'9YKsSVWkSlRmmyz{
 '**@&A#88/005HA5M$)$"1/1B C#9!$S)<%=!>):#1'"SAT=U<V  WD  "EE NN5)K(8'9YKsSVWjSkRllwxyg 5p Bwi.!FG'N23}3E2FGH23}3ECdkPldk_`QRSYQZdkPlLmHn3n2opq5c'l^DE7|a>@"%%`%`"`&))hW)h&h#%((fG(f%f""Q&9/9JKL&*=>Q=RST%)<=O<PQR35 )'1 5HAuF1R&5=/U9=M<NcRWX_R`Qabc !6 FHUWWIR.!N3 Qm6  		Bwi.!GIWIJs1vh'(.0!WIR.!N		sM   AV3 F"V3 >F5V3 8V3 B?V3  V.DV3 .V3 3
X2=A*X-'X2-X2c                      U R                  5       (       d  SSS.$ U R                  5       nU(       d  SSS.$ U R                  U5      (       d  SSS.$ U R                  U5      nU R	                  5       u  p4U(       d  U R                  U/ S5      $ U R                  5       u  pVU R                  5       nU R                  5       nX&-   U-   U-   n	[        S[        U	5       35        [        S[        U5       35        [        S	[        U5       35        [        S
[        U5       35        U R                  UU	U5      n
U
$ ! [         aF  n[        S[        U5       35        SSKnUR                  5         SS[        U5       3S.s SnA$ SnAff = f)u   
Ejecuta el flujo completo de validación
INCLUYE detección de errores nativos de Excel

Returns:
    dict: Reporte completo de la validación
ERROR-   No se pudo cargar el catálogo de validaciónr  r   z-No se pudo descargar el archivo de SharePointz No se pudo leer el archivo ExcelNu    ✓ Total errores consolidados: z  - Errores Excel: z  - Filas eliminadas: z  - Errores de tipos: u   Error en validación completa: r   r   )r;   rO   r   r   r   r  r   r  r=  r6   r7   r8   r9   r   r   )r$   rh   errores_excel_nativosestructura_validar  r  errores_filas_eliminadasr  errores_cantidades_sqltodos_los_errores_datosr  r:   r   s                r%   ejecutar_validacion_completa+ValidadorScore.ejecutar_validacion_completao  s   <	,,..%N 
  //1L%N 
 ??<00%A  %)$H$H$V!484K4K4M1$77&  ;?:X:X:Z7 446M%)%L%L%N" '<&VYf&fi&#4S9P5Q4RST',A(B'CDE*3/G+H*IJK*3}+=*>?@66"'!G N 	3CF8<=!!-c!fX6 		s4   D= D= D= <D= B,D= =
F;FFF)r   r   r    r   r   r   r#   r   N)r   
__module____qualname____firstlineno____doc__r&   r   r;   rO   rJ   r   r   r   r   r  r  r=  rH  __static_attributes__r'  r(   r%   r   r   !   sX    B&* D!CH`!HXtB"H<AF8xodDr(   r   c                 .    [        5       nU c9  UR                  5       (       d  SSSS.$ UR                  5       n U (       d  SSSS.$ OHUR                  5       (       d  SSSS.$ SSKnUR                  R                  U 5      (       d	  SS	S
U  3S.$ UR                  5       nUR                  S5      S:X  a  SSUR                  SS5      US.$ UR                  S0 5      R                  SS5      nUS:  aa  SSSU S3UR                  S0 5      UUUR                  S0 5      R                  SS5      UR                  S0 5      R                  SS5      S.S.$ SSSU UUR                  S0 5      S.$ ! [         a  nSSS[        U5       3S.s SnA$ SnAff = f)uk  
Función auxiliar para ser llamada desde ActualizarScore.py

Esta función ejecuta la validación del Score y retorna un formato
compatible con el módulo de actualización.

Args:
    ruta_archivo (str, optional): Ruta del archivo Excel a validar.
                                  Si no se proporciona, descarga desde SharePoint.

Returns:
    dict: {
        'success': bool,              # True si validación exitosa, False si hay errores
        'status': int,                # 200 si éxito, 400 si error
        'mensaje': str,               # Mensaje descriptivo
        'ruta_archivo': str,          # Ruta del archivo validado (si éxito)
        'reporte': dict,              # Reporte completo de validación (opcional)
        'errores': dict               # Errores encontrados (si falla)
    }

Ejemplo de uso:
    from App.SupyCtrol_Module.IngenieroControl.ValidarScore import validar_score_para_actualizacion
    
    resultado = validar_score_para_actualizacion()
    if resultado['success']:
        ruta = resultado['ruta_archivo']
        # Continuar con el proceso...
    else:
        # Manejar errores...
NFi  uH   No se pudo cargar el catálogo de validación desde CM_DataTypeValidator)successstatusr   z6No se pudo descargar el archivo Excel desde SharePointrA  r   i  zEl archivo no existe: r  r@  r   u   Error en validación)rP  rQ  r   r  r   r  zSe encontraron u    errores de validaciónr   r  r  )r  r  r  )rP  rQ  r   r   r  detallesTr@   u%   Validación exitosa. Datos correctos.)rP  rQ  r   rh   r  r     u   Error crítico en validación: )
r   r;   rO   r-   r.   existsrH  rE   r8   r9   )rh   	validadorr-   r  r  r:   s         r%    validar_score_para_actualizacionrV    s   >T
"$	 1133$!i  %446L$!W    1133$!N  77>>,//$!!7~F  88: ;;x G+ ";;y2HI"	   NB7;;OQO1 ,]O;RS";;y"5"%2*1++nb*I*M*MNbde*f%,[[%D%H%HZ[%\  >(#KK;
 	
  
8QA
 	

sA   'E. E. E. #,E. ;E. BE. E. .
F8F	FFc                 `    U R                  SS/S9S 5       nU R                  SS/S9S 5       ng)	u}   
Registra la ruta de ejecución de validación en Flask

Args:
    app: Instancia de Flask
    mail: Instancia de Flask-Mail
z0/SyC/IngenieroControl/ModuloValidacionScore/testGET)methodsc                  d    [        SS[        R                  " 5       R                  S5      S.5      $ )z5Ruta de prueba para verificar que el backend funcionaTu$   ¡Backend funcionando correctamente!r  )rP  r   r#   )r   r   r!   r"   r'  r(   r%   test_validacion2ejecutar_validacion_score.<locals>.test_validacion;  s1     =!001DE
  	r(   z4/SyC/IngenieroControl/ModuloValidacionScore/ejecutarPOSTc                       [        S5        [        5       n U R                  5       n[        U5      $ ! [         a#  n[        S[        U5      S.5      S4s SnA$ SnAff = f)u/   Ejecuta la validación del Score y retorna JSONu"   Iniciando validación del Score...r@  rB  rS  N)r6   r   rH  r   r8   r9   )rU  r  r:   s      r%   ejecutar_validacion6ejecutar_validacion_score.<locals>.ejecutar_validacionD  sg    		67&(I<<>G7## 	!q6   	s   /2 
AAAAN)route)appmailr[  r_  s       r%   ejecutar_validacion_scorerd  1  sM     	YYAE7YS T 	YYEPVxYX Yr(   )N)r-   rD   pandasr   ior   r   flaskr   configr   r   4Consultas_SQL.SupYCtrol.IngDeControl.ValidarScoreSQLr   r	   r
   9App.SupyCtrol_Module.IngenieroControl.ValidarScoreHelpersr   r   getenvr   Configr   r   r   
set_optionr   rV  rd  r'  r(   r%   <module>rn     s    
      6 W  W l IIk=1	&,6	<M l  %  #T *  $ ' ot $ $b )R Rts
lr(   