+
    ·Ù¾jP�  ã                   óâ  € R t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	t^ RI
t
^ RIt
^ RIHtHt ^ RIHtHt ^ RIHtHtHtHtHt ]P.                  P1                  ]P.                  P3                  ]4      4      t]P.                  P9                  ]RR4      t]P<                  ! ]RR7       ]t]! 4       t ^t!R	t"R
R0t#]! 4       t$R R lt%R R lt&R R lt'R=R R llt(R t)R R lt*R R lt+R R lt,R R lt-R R lt.R R  lt/ ! R! R"]04      t1R# R$ lt2R% R& lt3R' R( lt4R>R) R* llt5R+ R, lt6R- R. lt7R/ R0 lt8R1 R2 lt9R3R40t:R5 R6 lt;R7 R8 lt<R?R9 R: llt=R; t>]?R<8X  d
   ]>! 4        R# R# )@u5  
cierre_mes.py â€” Cierre mensual automÃ¡tico Â· Dashboard Talento Humano Â· Faranda Hotels
â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�
Captura el snapshot del mes ANTERIOR desde la API de nÃ³mina e IR y lo guarda en
PostgreSQL para que el dashboard lo lea desde ahÃ­ en todas las consultas futuras.

Programado con LaunchAgent (macOS) para correr:
  Â· DÃ­a  1 de cada mes  a las 5:00 AM  â†’ primer cierre (datos iniciales)
  Â· DÃ­a  5 de cada mes  a las 5:00 AM  â†’ cierre definitivo (nÃ³mina liquidada)

Si falla: escribe log, reintenta 1 hora despuÃ©s y termina.

Uso manual:
  python3 cierre_mes.py                   â†’ cierra el mes anterior automÃ¡ticamente
  python3 cierre_mes.py --test            â†’ muestra quÃ© mes cerrarÃ­a (sin escribir)
  python3 cierre_mes.py --empleados-activos-detalle
  python3 cierre_mes.py --solo-empleados-si-vacio
N)ÚdateÚdatetime)ÚThreadPoolExecutorÚas_completed)ÚAPI_BASEÚNOMINA_API_KEYÚ	db_configÚrequire_secretsÚssl_contextÚlogsÚcierresT)Úexist_oké  ÚELMAÚFNSc                óP   € V ^8„  d   QhR\         R\         R\        P                  /# ©é   ÚanoÚmesÚreturn)ÚintÚloggingÚLogger)Úformats   "Új/Users/ricardomartinez/BIA CLAUDE PROYECTOS/Proyectos Claude IA/Talento Humano Api Dashboard/cierre_mes.pyÚ__annotate__r   9   s%   € ÷ ñ ”cð ¤ð ¬¯©ñ ó    c           
     ó®  € \         P                  ! 4       P                  R4      p\        P                  P                  \        RV  RVR RV R24      p\        P                  ! RV  RV 24      pVP                  \        P                  4       VP                  P                  4        \        P                  ! RRR7      p\        P                  ! \        P                   4      pVP#                  V4       VP%                  V4       \        P&                  ! VR	R
7      pVP#                  V4       VP%                  V4       VP)                  RV 24       V# )zGCrea logger que escribe en consola Y en archivo con fecha en el nombre.z%Y%m%d_%H%M%SÚcierre_Ú_Ú02dz.logz)%(asctime)s  %(levelname)-8s  %(message)sz%Y-%m-%d %H:%M:%S)Údatefmtzutf-8)Úencodingu   Log iniciado â†’ )r   ÚnowÚstrftimeÚosÚpathÚjoinÚLOGS_DIRr   Ú	getLoggerÚsetLevelÚDEBUGÚhandlersÚclearÚ	FormatterÚStreamHandlerÚsysÚstdoutÚsetFormatterÚ
addHandlerÚFileHandlerÚinfo)r   r   Ú	timestampÚlog_fileÚloggerÚfmtÚchÚfhs   &&      r   Úsetup_loggerr=   9   s  € ä—’“×'Ñ'¨Ó8€IÜ—‘—‘œX¨°°°Q°s¸3°i¸qÀÀÈ4Ð'PÓQ€Hä×Ò ¨¨¨Q¨s¨eÐ4Ó5€FØ
‡O�O”G—M‘MÔ"Ø
‡O�O×ÑÔä
×
Ò
ÐGØ%8ô:€Cô 
×	Ò	œsŸz™zÓ	*€BØ‡O�O�CÔØ
×Ñ�bÔô 
×	Ò	˜X°Ô	8€BØ‡O�O�CÔØ
×Ñ�bÔà
‡K�KÐ# H :Ð.Ô/Ø€Mr   c                óF   € V ^8„  d   QhR\         \        \        3,          /# ©r   r   )Útupler   )r   s   "r   r   r   U   s   € ÷ #ñ #œœc¤3˜h�ñ #r   c                 ó¶   € \         P                  ! 4       p V P                  ^8X  d   V P                  ^,
          ^3# V P                  V P                  ^,
          3# )u4   Devuelve (ano, mes) del mes anterior al dÃ­a de hoy.)r   ÚtodayÚmonthÚyear)Úhoys    r   Úget_prev_monthrF   U   sB   € ä
�*Š*‹,€CØ
‡y�y�A„~Ø�x‰x˜!�|˜RÐÐØ�8‰8�S—Y‘Y •]Ð"Ð"r   c                ó2   € V ^8„  d   QhR\         R,          /# )r   r   N)r   )r   s   "r   r   r   ]   s   € ÷ ñ ”t˜d•{ñ r   c                óš   € V '       g   R#  \         P                  ! \        V 4      P                  RR4      4      #   \         d     R# i ; i)zIParsea una fecha que puede venir como '2026-04-20' o '2026/06/03' o None.NÚ/Ú-)r   ÚfromisoformatÚstrÚreplaceÚ	Exception)Úvals   &r   Ú
parse_daterP   ]   sA   € çÙðÜ×!Ò!¤# c£(×"2Ñ"2°3¸Ó"<Ó=Ð=øÜô Úðús   Œ.; »A
Á	A
c                ó<   € V ^8„  d   QhR\         R\        R\        /# )r   r'   ÚbodyÚtimeout)rL   Údictr   )r   s   "r   r   r   g   s!   € ÷ 	'ñ 	'”3ð 	'œdð 	'¬Sñ 	'r   c                ó–  € \         P                  ! V4      P                  4       p\        P                  P                  \        V ,           VR\        RR/RR7      p\        P                  P                  WB\        R7      ;_uu_ 4       p\         P                  ! VP                  4       4      uuRRR4       #   + '       g   i     R# ; i)z7Hace POST a la API externa y devuelve el JSON parseado.ú	X-API-KeyzContent-Typezapplication/jsonÚPOST)ÚdataÚheadersÚmethod©rS   ÚcontextN)ÚjsonÚdumpsÚencodeÚurllibÚrequestÚRequestr   ÚAPI_KEYÚurlopenÚSSL_CTXÚloadsÚread)r'   rR   rS   rX   ÚreqÚresps   &&&   r   Úapi_postrj   g   s‹   € ä�:Š:�dÓ×"Ñ"Ó$€DÜ�>‰>×!Ñ!Ü�4�˜dØœg ~Ð7IÐJØð "ó €Cô
 
�‰×	Ñ	 ¼gÐ	×	FÔ	FÈ$Ü�zŠz˜$Ÿ)™)›+Ó&÷ 
G×	F×	FÓ	Fús   Â$B7Â7C	c                 óH   € \         P                  ! R/ \        B p RV n        V # )u   Abre conexiÃ³n PostgreSQL.F© )Úpsycopg2ÚconnectÚ	DB_CONFIGÚ
autocommit)Úconns    r   Ú
db_connectrr   s   s!   € ä×ÒÑ(œiÑ(€DØ€D„OØ€Kr   c                ó<   € V ^8„  d   QhR\         R\         R\         /# r   ©r   )r   s   "r   r   r   |   s!   € ÷ !ñ !¤Cð !¬cð !´cñ !r   c           
     óØ   € V P                  4       ;_uu_ 4       pVP                  R\        W^4      34       VP                  4       ^ ,          uuRRR4       #   + '       g   i     R# ; i)uH   Devuelve cuÃ¡ntos registros existen en historico_empleados para ese mes.z9SELECT COUNT(*) FROM historico_empleados WHERE fecha = %sN)ÚcursorÚexecuter   Úfetchone)rq   r   r   Úcurs   &&& r   Úya_cerrado_empleadosrz   |   sG   € à	�‰�Œ˜#Ø�‰ØGÜ�#˜AÓÐ ô	
ð �|‰|‹~˜aÕ ÷ 
��‹ús   ™4AÁA)	c                ó<   € V ^8„  d   QhR\         R\         R\         /# r   rt   )r   s   "r   r   r   †   s!   € ÷ !ñ !œSð !¤sð !¬sñ !r   c                óÔ   € V RVR 2pV P                  4       ;_uu_ 4       pVP                  RV34       VP                  4       ^ ,          uuRRR4       #   + '       g   i     R# ; i)uA   Devuelve cuÃ¡ntos registros existen en historico_ir para ese mes.rJ   r!   z4SELECT COUNT(*) FROM historico_ir WHERE periodo = %sN)rv   rw   rx   )rq   r   r   Úperiodory   s   &&&  r   Úya_cerrado_irr~   †   sL   € à��Q�s˜3�iÐ €GØ	�‰�Œ˜#Ø�‰ÐJÈWÈJÔWØ�|‰|‹~˜aÕ ÷ 
��‹ús   ¡*AÁA'	c                ó$   € V ^8„  d   QhR\         /# r?   ©rT   )r   s   "r   r   r   �   s   € ÷ +/ñ +/¤$ñ +/r   c                ó:  € V P                  \        P                  P                  R7      ;_uu_ 4       pVP	                  R\        \        4      34       VP                  4       pRRR4       RRRRRR	/p/ p/ p/ pX F†  pVP                  VR
,          VR,          4      pVR,          '       d   W„VR,          VR,          3&   VR
,          '       g   KW  W…VR
,          VR,          3&   VR
,          V9  g   K{  W†VR
,          &   Kˆ  	  WEV3#   + '       g   i     L®; i)u  
Devuelve tres mapas:
  hotel_bu_map : (hotel_name_api, bu_codigo_lower) â†’ razon_social
  nit_bu_map   : (nit, bu_codigo_lower)            â†’ razon_social  â†� clave para NITs compartidos
  nit_razon    : nit                               â†’ razon_social  â†� fallback sin bu
)Úcursor_factoryaj  
            SELECT e.codigo    AS razon_social,
                   e.nit,
                   u.hotel_name_api,
                   LOWER(COALESCE(u.bu_codigo, 'local')) AS bu_codigo
            FROM empresas e
            LEFT JOIN hotel_unificacion u ON u.razon_social = e.codigo
            WHERE e.nit IS NOT NULL
              AND e.codigo NOT IN %s
        NÚ	900657316ÚGHSÚ	901418135ÚSERVÚ	901936953ÚCCARÚnitÚrazon_socialÚhotel_name_apiÚ	bu_codigo)	rv   rm   ÚextrasÚRealDictCursorrw   r@   Ú	EXCLUIDOSÚfetchallÚget)	rq   ry   ÚrowsÚ	NIT_UNICOÚhotel_bu_mapÚ
nit_bu_mapÚ	nit_razonÚrÚrazons	   &        r   Úcargar_nit_razon_mapr™   �   s  € ð 
�‰¤H§O¡O×$BÑ$Bˆ×	CÔ	CÀsØ�‰ð 	ô ”IÓÐ ô		"ð �|‰|‹~ˆ÷ 
Dð  	�UØ�VØ�Vð€Ið €LØ€JØ€Iãˆà—‘˜a �h¨¨.Õ(9Ó:ˆàÐ×ÔØBG˜!Ð,Õ-¨q°­~Ð>Ñ?ØˆU�8Ž8Ø5:˜˜%� ! K¥.Ð1Ñ2Ø��x˜yÖ(Ø&+˜!˜E�(Ó#ñ ð  YÐ.Ð.÷I 
D×	Cús   ³1D
Ä
D	c                ó:   € V ^8„  d   QhR\         \        ,          /# r?   )ÚlistrL   )r   s   "r   r   r   ¾   s   € ÷ 
.ñ 
.¤¤c¥ñ 
.r   c                ó  € V P                  4       ;_uu_ 4       pVP                  R\        \        4      34       VP	                  4        Uu. uF  q"^ ,          NK  	  upuuRRR4       # u upi   + '       g   i     R# ; i)uE   Devuelve lista de NITs Ãºnicos activos (sin excluidos, sin nit nulo).z¡
            SELECT DISTINCT nit
            FROM empresas
            WHERE nit IS NOT NULL
              AND codigo NOT IN %s
            ORDER BY nit
        N)rv   rw   r@   r�   r�   ©rq   ry   r—   s   &  r   Úcargar_nits_activosrž   ¾   sa   € à	�‰�Œ˜#Ø�‰ð ô ”IÓÐ ô	"ð "Ÿl™lœnÓ-™n˜�!—�™nÑ-÷ 
Šùò .÷ 
�ˆús   ™3A/ÁA*ÁA/Á*A/Á/B 	c                ó$   € V ^8„  d   QhR\         /# r?   )Úset)r   s   "r   r   r   Ë   s   € ÷ .ñ .œsñ .r   c                óè   € V P                  4       ;_uu_ 4       pVP                  R4       VP                  4        Uu0 uF  q"^ ,          kK  	  upuuRRR4       # u upi   + '       g   i     R# ; i)z;Devuelve set de codigo_empleado marcados como SOCIO activo.z6SELECT codigo_empleado FROM socios WHERE activo = TRUEN)rv   rw   r�   r�   s   &  r   Úcargar_socios_setr¢   Ë   sL   € à	�‰�Œ˜#Ø�‰ÐLÔMØ!Ÿl™lœnÓ-™n˜�!—�™nÑ-÷ 
Šùâ-÷ 
�ˆús   ™$A ½AÁA ÁA Á A1	c                ó$   € V ^8„  d   QhR\         /# r?   r€   )r   s   "r   r   r   Ò   s   € ÷ 6ñ 6¤$ñ 6r   c                 ó†  € / p  \         P                  ! 4       p\        VP                  ^,
          VP                  ^4      P	                  4       pVP	                  4       pRVRVRRRRRRR	R
RRRRR/RRRRRR
RRRRR/RRRR.RRR.RRR.RRR.RRR.RRR.RRR.RRR./R. R,ORR/pR- FÒ  p\        R/ VCRV/C^<R7      pVP                  R. 4       F¥  pVP                  R. 4       FŒ  pVP                  R . 4       Fs  p	V	P                  R!4      R8X  g   K  V	P                  R4      '       g   K4  V	P                  R"4      '       g   KM  \        V	R,          4      p
\        V	R",          4      W
&   Ku  	  KŽ  	  K§  	  KÔ  	   \        P                  P                  \        R#,           R$\        /R%R&7      p\        P                  P                  V^\         R'7      ;_uu_ 4       p\"        P$                  ! VP'                  4       4      pR(R(R(4       XP                  R. 4       Ff  pVP                  R). 4       FM  p\        VP                  R*4      ;'       g    R4      p
V
'       g   K1  \        VP                  R+4      4      W
&   KO  	  Kh  	  V #   \         d     ELi ; i  + '       g   i     L ; i  \         d     T # i ; i).uû   
Construye mapa { identificacion â†’ fecha_vence_contrato } combinando:
  1. empleados-activos-detalle  (business date â€” cubre ~95% activos)
  2. IR ingresos Ãºltimos 24 meses (campo contrato=identificacion, vencimiento)
Devuelve el mapa unificado.
Úfecha_inicialÚfecha_finalÚestadoÚTÚagruparÚccoFÚbuTÚclaÚcausaÚcargoÚsaltosÚfiltrosÚcontratoÚ ÚzzzÚempleadoÚcentro_costoÚclasificacionÚnivelÚcausa_retiroÚordenÚIÚ
forma_pagoéç  ú/rrhh/ingresos-retirosÚtipo_nomina_id)rS   ÚhotelesÚunidades_negocior’   ÚtipoÚvencimientoú/rrhh/empleados-activos-detallerV   ÚGET©rY   rZ   r[   NÚ	empleadosÚidentificacionÚfecha_vence_contrato©ÚCÚNrº   ©é   é   )r   rB   rD   rC   Ú	isoformatrj   r‘   rL   rP   rN   r`   ra   rb   r   rc   rd   re   r]   rf   rg   )Ú	vence_maprE   ÚfiÚffÚ_ir_baseÚtipo_idrX   Úhotelr«   ÚrowÚidfrh   ri   Úemps                 r   Úfetch_vence_contrato_maprÙ   Ò   s®  € ð €IðÜ�jŠj‹lˆÜ�3—8‘8˜a•< §¡¨AÓ.×8Ñ8Ó:ˆØ�m‰m‹oˆà˜R °Ø�cØ˜  t¨T°E¸5À'È5ÐRYÐ[`ÐaØ˜  t¨U°E¸5À'È5ÐRYÐ[`ÐaØ˜ b¨ Z°¸bÀ¸ZØ'¨"¨U¨°T¸B¸u¸:Ø(¨2¨e¨*°gÀÀ5¸zØ  2 e *¨n¸rÀ%¸jðJð ’] L°#ð

ˆó ˆGÜÐ4Ð6]¸Ð6]ÐCSÐU\Ñ6]ÐgiÔjˆDØŸ™ )¨RÖ0�ØŸ)™)Ð$6¸Ö;�BØ!Ÿv™v f¨bÖ1˜ØŸ7™7 6›?¨cÖ1°c·g±g¸j×6IÔ6IÈcÏgÉgÐVc×NdÔNdÜ"% c¨*¥oÓ"6˜CÜ-7¸¸MÕ8JÓ-K˜I›Nó  2ó <ó 1ñ ðÜ�n‰n×$Ñ$ÜÐ8Õ8Ø ¤'Ð*Øð %ó 
ˆô
 �^‰^×#Ñ# C°¼WÐ#×EÔEÈÜ—:’:˜dŸi™i›kÓ*ˆD÷ Fà—X‘X˜i¨Ö,ˆEØ—y‘y ¨bÖ1�Ü˜#Ÿ'™'Ð"2Ó3×9Ð9°rÓ:�ß‘3Ü%/°·±Ð8NÓ0OÓ%P�I“Nó 2ñ -ð Ðøô) ô Úðú÷ F×Eûô ô ØàÐðús\   „DJ ÄJ Ä0J Å	6J Æ A!J1 Ç!%JÈAJ1 ÉJ1 É&$J1 ÊJÊJÊJ.	Ê)J1 Ê1K Ê?K c                   ó   € ] tR tRtRtRtR# )ÚNominaNoDisponiblei  u@   La nÃ³mina de ese NIT/mes aÃºn no ha sido cerrada en el sistema.rl   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__rl   r   r   rÛ   rÛ     s   † ÙJÛr   rÛ   c          
      ój   € V ^8„  d   QhR\         R\        R\        R\        \         \        3,          /# )r   r‰   r   r   r   )rL   r   r@   r›   )r   s   "r   r   r     s1   € ÷ ñ œSð ¤sð ´ð ¼¼sÄD¸yÕ9Iñ r   c                óÈ  €  \        RRV RVRVRRRR/4      pWP                  R	. 4      3#   \        P                  P                   d˜   p \
        P                  ! TP                  4       P                  4       4      pTP                  R
R4      P                  4       pM  \         d    Rp Mi ; iTP                  R8X  d   RT9   d   \        RT RTR 24      hh Rp?ii ; i)uŽ   
Llama la API de nÃ³mina para un NIT y devuelve (nit, [empleados]).
Lanza NominaNoDisponible si el perÃ­odo aÃºn no estÃ¡ cerrado (HTTP 400).
z/nomina/reporteÚ	hotel_nitr   r   Úincluir_empleadosTÚss_vistaÚambosrÆ   Údetailr²   i�  zperiodos cerradosu   nÃ³mina no cerrada para rJ   r!   N)rj   r‘   r`   ÚerrorÚ	HTTPErrorr]   rf   rg   ÚdecodeÚlowerrN   ÚcoderÛ   )r‰   r   r   rX   ÚerR   Údetalles   &&&    r   Úfetch_empleados_nitrð     sà   € ð
ÜÐ)Ø #Ø #Ø #Ø $Ø 'ð,
ó ˆð —H‘H˜[¨"Ó-Ð-Ð-øÜ�<‰<×!Ñ!ô 	ð	Ü—:’:˜aŸf™f›hŸo™oÓ/Ó0ˆDØ—h‘h˜x¨Ó,×2Ñ2Ó4‰GøÜô 	ØŠGð	úà�6‰6�SŒ=Ð0°GÔ;Ü$Ð'?À¸uÀAÀcÈ#ÀYÐ%OÓPÐPØûð	ús4   ‚(+ «C!ÁABÂCÂB.Â+CÂ-B.Â..CÃC!c                ó:   € V ^8„  d   QhR\         \        ,          /# r?   )r›   rT   )r   s   "r   r   r   ,  s   € ÷ #ñ #¬¬d­ñ #r   c                 óh  € \         P                  P                  \        R,           R\        /RR7      p \         P                  P                  V ^<\        R7      ;_uu_ 4       p\        P                  ! VP                  4       4      pRRR4       XP                  R. 4      #   + '       g   i     L"; i)u›   
Lee la foto viva de empleados activos.
Se usa en el cierre del dÃ­a 1: la foto tomada el dÃ­a 1 del mes siguiente
se guarda como cierre del mes anterior.
rÃ   rV   rÄ   rÅ   r[   Nr¿   )r`   ra   rb   r   rc   rd   re   r]   rf   rg   r‘   )rh   ri   rX   s      r   Úfetch_empleados_activos_detalleró   ,  s†   € ô �.‰.×
 Ñ
 ÜÐ4Õ4ØœgÐ&Øð !ó €Cô
 
�‰×	Ñ	 ¨R¼Ð	×	AÔ	AÀTÜ�zŠz˜$Ÿ)™)›+Ó&ˆ÷ 
Bà�8‰8�I˜rÓ"Ð"÷ 
B×	Aús   Á"%B!Â!B1	c                ól   € V ^8„  d   QhR\         \        ,          R\         \        ,          R\        RR/# )r   r¿   Únits_esperadosr–   r   N)r›   rT   rL   )r   s   "r   r   r   <  s8   € ÷ pñ p¤t¬D¥zð pÄ4ÌÅ9ð pÜ)-ðpØ:>ñpr   c                ó–  € V  Uu0 uF5  p\        VP                  R4      ;'       g    R4      P                  4       kK7  	  ppV Uu. uF  qf'       g   K  We9  g   K  VNK  	  ppV'       g   R# VP                  R\	        V4       R24       V F-  pVP                  VR4      pVP                  RV RV R	24       K/  	  R# u upi u upi )
u?  
Compara los NITs devueltos por empleados-activos-detalle contra los NITs
activos en la tabla `empresas`. Si la API omite un hotel completo (como
pasÃ³ con Belvedere/Faranda_Bogota en jul-2026, sin que la API devolviera
error alguno), lo deja como WARNING explÃ­cito en vez de fallar en
silencio con ese hotel en cero.
rä   r²   Nu8     âš ï¸�  La API empleados-activos-detalle NO devolviÃ³ z NIT(s) esperado(s):Ú?z      - NIT u    (razon_socialâ‰ˆu+   ) â€” quedarÃ¡ SIN empleados en este cierre)rL   r‘   ÚstripÚwarningÚlen)	r¿   rõ   r–   r9   ÚhÚnits_recibidosr‰   Ú	faltantesr˜   s	   &&&&     r   Úvalidar_hoteles_recibidosrþ   <  s»   € ñ FMÓMÁWÀ”c˜!Ÿ%™% Ó,×2Ð2°Ó3×9Ñ9Ö;ÁW€NÐMÙ .ÓT¡˜³#”¸#Ñ:S—�¡€IÐTßÙØ
‡N�NÐMÌcÐR[ËnÐM]Ð]qÐrÔsÛˆØ—‘˜c 3Ó'ˆØ�‰˜ c UÐ*;¸E¸7ÐBmÐnÖoó ùò NùÚTs   …!C§CÁ	CÁCÁCc                óœ   € V ^8„  d   QhR\         R\         R\        R\        R\        R\        R\        \        ,          R,          R	\         /# )
r   r   r   r”   r•   r–   Ú
socios_setrõ   Nr   )r   rT   r    r›   rL   )r   s   "r   r   r   O  se   € ÷ Fñ F´#ð F¼Cð FÜ59ðFÜGKðFä26ðFäDGðFô @DÄC½yÈ4Õ?OðFô \_ñFr   c	                óª  € \        W^4      p	\        4       p
V'       d   \        W¨WW4       . p^ pV
 EFY  pVP                  R4      ;'       g    Rp\	        VP                  R4      ;'       g    R4      P                  4       pVP                  R. 4       EFñ  pVP                  R4      ;'       g    RP                  4       pVP                  VV34      ;'       gH    VP                  VR34      ;'       g-    VP                  VV34      ;'       g    VP                  V4      pV'       g   V^,          pT;'       g    Rp\	        VP                  R4      ;'       g    R4      pVV9   d   R	MR
pVP                  R4      pVf   VP                  R4      pTP                  T	TT;'       g    RVP                  R4      ;'       g    R\        VP                  R4      4      VP                  R4      ;'       g    RP                  4       \        VP                  R4      4      \        VP                  R4      4      VP                  R4      VP                  R4      \        T;'       g    ^ 4      VVP                  R4      34       EKô  	  EK\  	  V'       d   VP                  RV 24       V'       g   VP                  R4       ^ # V P                  4       ;_uu_ 4       p\        P                  P                  VRVRR7       RRR4       V P!                  4        VP#                  R\%        V4       24       \%        V4      #   + '       g   i     LH; i)zDInserta empleados activos desde GET /rrhh/empleados-activos-detalle.Ú
hotel_namer²   rä   rÆ   rŒ   ÚlocalNrÇ   ÚSOCIOúEN OPERACIONÚsueldo_baseÚs_basicoÚnombreÚfecha_nacimientoÚsexoÚfecha_ingresorÈ   rµ   r®   Útipo_contratou/     Empleados activos sin razÃ³n social mapeada: z3  No se encontraron empleados activos para insertará4  
            INSERT INTO historico_empleados
                (fecha, razon_social, codigo_empleado, nombre_completo,
                 fecha_nacimiento, sexo, fecha_ingreso, fecha_vencimiento_contrato,
                 centro_costo, cargo, sueldo_base, operacion, tipo_contrato)
            VALUES %s
        éô  ©Ú	page_sizeu7     âœ… Empleados activos insertados desde detalle vivo: )r   ró   rþ   r‘   rL   rø   rì   ÚappendrP   Ú
capitalizer   rù   rv   rm   r�   Úexecute_valuesÚcommitr6   rú   )rq   r   r   r”   r•   r–   r   r9   rõ   Úfechar¿   r’   Ú	sin_razonrÕ   Ú	hotel_apir‰   rØ   r«   r˜   r×   Ú	operacionÚsueldory   s   &&&&&&&&&              r   Ú"insertar_empleados_activos_detaller  O  sÆ  € ô
 �˜1Ó€EÜ-Ó/€GßÜ! '¸9ÔMØ€DØ€IäˆØ—I‘I˜lÓ+×1Ð1¨rˆ	Ü�%—)‘)˜KÓ(×.Ð.¨BÓ/×5Ñ5Ó7ˆØ—9‘9˜[¨"×-ˆCØ—'‘'˜+Ó&×1Ð1¨'×8Ñ8Ó:ˆBà× Ñ  )¨R Ó1÷ &ð &Ø×#Ñ# Y°Ð$8Ó9÷&ð &à—>‘> 3¨ )Ó,÷&ð &ð —=‘= Ó%ð	 ÷ Ø˜Q•�	ØŸ˜˜t�ä�c—g‘gÐ.Ó/×5Ð5°2Ó6ˆCØ#&¨*Ô#4™¸.ˆIà—W‘W˜]Ó+ˆFØŠ~ØŸ™ Ó,�à�K‰KØØØ—��tØ—‘˜Ó!×'Ð' RÜ˜3Ÿ7™7Ð#5Ó6Ó7Ø—‘˜“×&Ð& B×2Ñ2Ó4Ü˜3Ÿ7™7 ?Ó3Ó4Ü˜3Ÿ7™7Ð#9Ó:Ó;Ø—‘˜Ó'Ø—‘˜Ó Ü�F—K�K˜aÓ Øð —‘˜Ó(ð!÷ ô' .ñ ÷R Ø�‰ÐHÈÈÐTÔUßØ�‰ÐLÔMÙà	�‰�Œ˜#Ü�‰×&Ñ& sð -ð ˜Sð 	'ô 	"÷ 
ð 	‡K�K„MØ
‡K�KÐIÌ#ÈdË)ÈÐUÔVÜˆt‹9Ð÷ 
�ús   Ë$MÍM	c                óš   € V ^8„  d   QhR\         R\         R\        R\        R\        R\        \        ,          R\        R\        R	\         /	# )
r   r   r   r”   r•   r–   Ú	nits_empsr   rÐ   r   )r   rT   r›   r@   r    )r   s   "r   r   r   ˜  se   € ÷ Oñ O¤#ð O¬Cð OÜ%)ðOÜ7;ðOÜHLðOä"&¤u¥+ðOä;>ðOô #'ðOô 47ñOr   c
                óú  € \         P                  ! W4      w  r«\        WV4      p\        W^4      p. p^ pV EF  w  ppV EFõ  p\        VP	                  R4      4      pVe   VV8:  d   V^,          pK4  VP	                  R4      ;'       g    RP                  4       pVP	                  VV34      ;'       g    VP	                  VV4      p\        VP	                  R4      ;'       g    R4      pVV9   d   RMRpVP	                  R	4      ;'       g    RP                  4       pVR
8X  d   RpM"VP	                  V4      pVf   Ve
   VV8”  d   TpTP                  TTT;'       g    RVP	                  R4      ;'       g    R\        VP	                  R4      4      VP	                  R4      ;'       g    RP                  4       \        VP	                  R4      4      TVP	                  R4      VP	                  R4      \        VP	                  R4      ;'       g    ^ 4      VVP	                  R	4      34       EKø  	  EK  	  V	P                  RV 24       V'       g   V	P                  R4       ^ # V P                  4       ;_uu_ 4       p\        P                  P                  VRVRR7       RRR4       V P!                  4        V	P                  R\#        V4       24       \#        V4      #   + '       g   i     LH; i)u¬  
Inserta empleados ACTIVOS del mes en historico_empleados.

Reglas:
- Solo empleados con fecha_retiro IS NULL o fecha_retiro > Ãºltimo dÃ­a del mes
- operacion: 'SOCIO' si identificacion in socios_set, 'EN OPERACION' si no
- fecha_vencimiento_contrato:
    1. vence_map[identificacion] (empleados-activos-detalle / IR)
    2. fecha_retiro de nÃ³mina si tipo_contrato='fijo' y fecha futura
    3. NULL para contratos indefinidos
Úfecha_retiroNrŒ   r  rÇ   r²   r  r  r  Ú
indefinidor  r	  r
  r  rµ   r®   r  z-  Empleados excluidos (retirados en el mes): z+  No se encontraron empleados para insertarr  r  r  u     âœ… Empleados insertados: )ÚcalendarÚ
monthranger   rP   r‘   rì   rL   r  r  r   r6   rù   rv   rm   r�   r  r  rú   )rq   r   r   r”   r•   r–   r  r   rÐ   r9   r    Ú
ultimo_diaÚultimor  r’   Ú	excluidosr‰   rÆ   rØ   r  r«   r˜   r×   r  r  Úvencery   s   &&&&&&&&&&                 r   Úinsertar_empleadosr&  ˜  s�  € ô ×'Ò'¨Ó1�M€AÜ˜ :Ó.€FÜ˜ 1Ó%€EØ€DØ€Iä#‰ˆˆYÜˆCä% c§g¡g¨nÓ&=Ó>ˆLØÒ'¨L¸FÔ,BØ˜Q•�	Ùà—W‘W˜[Ó)×4Ð4¨W×;Ñ;Ó=ˆBØ—N‘N C¨ 9Ó-×HÐH°·±¸sÀCÓ1HˆEÜ˜Ÿ™Ð 0Ó1×7Ð7°RÓ8ˆCð $'¨*Ô#4™¸.ˆIð !ŸW™W _Ó5×;Ð;¸×BÑBÓDˆMØ Ô,Ø‘ð "Ÿ™ cÓ*�à’= \Ò%=À,ÐQWÔBWØ(�Eà�K‰KØØØ—��tØ—‘˜Ó!×'Ð' RÜ˜3Ÿ7™7Ð#5Ó6Ó7Ø—‘˜“×&Ð& B×2Ñ2Ó4Ü˜3Ÿ7™7 ?Ó3Ó4ØØ—‘˜Ó'Ø—‘˜Ó Ü�C—G‘G˜JÓ'×,Ð,¨1Ó-ØØ—‘˜Ó(ð÷ ô3 ñ $ðT ‡K�KÐ?À	¸{ÐKÔLßØ�‰ÐDÔEÙà	�‰�Œ˜#Ü�‰×&Ñ& sð -ð ˜Sð 	'ô 	"÷ 
ð 	‡K�K„MØ
‡K�KÐ.¬s°4«y¨kÐ:Ô;Üˆt‹9Ð÷ 
�ús   Ê$K*Ë*K:	c                ó‚   € V ^8„  d   QhR\         R\         R\        R\        R\        R\        \        ,          R\         /# )r   r   r   r”   r•   r–   Únitsr   )r   rT   r›   rL   )r   s   "r   r   r   ê  sO   € ÷ ,Tñ ,T¤ð ,T¬#ð ,TÜ#'ð,TÜ59ð,TÜFJð,Tä¤�9ð,Tä14ñ,Tr   c                ó  € VP                  R4       \        ^R7      ;_uu_ 4       pVP                  \        V 4      p	VP                  \        4      p
V	P                  4       pV
P                  4       pRRR4       VP                  R\        X4       R\        X4       R24       VP                  R\        V4       R24       . p. p. p\        \        R7      ;_uu_ 4       pV Uu/ uF  pVP                  \        VW4      VbK  	  pp\        V4       FT  pVV,          p VP                  4       w  ppVP                  VV34       VP                  R	V R
\        V4       R24       KV  	  RRR4       V'       d2   VP                  R\        V4       RV 24       VP                  R4       V'       d!   VP                  R\        V4       RV 24       \!        WW#VW]W¼V4
      #   + '       g   i     EL{; iu upi   \         d,    TP                  T4       TP                  R	T R24        EK  \         d5   pTP                  T4       TP                  R	T RT 24        Rp?EKX  Rp?ii ; i  + '       g   i     EL; i)uE   Orquesta la captura paralela de empleados por NIT e inserciÃ³n en PG.u7     Cargando socios y mapa de vencimientos de contratoâ€¦)Úmax_workersNú  Socios activos cargados: z | Mapa vencimientos: z
 registrosu     Llamando API nÃ³mina para u    NITs en paraleloâ€¦z    NIT z: z
 empleadosu&   : nÃ³mina aÃºn no cerrada â€” se omiteu   : ERROR inesperado â€” u     âš ï¸�  Sin nÃ³mina cerrada (z NITs): uD        Se incluirÃ¡n en el cierre del dÃ­a 5 cuando estÃ©n disponiblesu     â�Œ Errores reales ()r6   r   Úsubmitr¢   rÙ   Úresultrú   ÚMAX_WORKERSrð   r   r  ÚdebugrÛ   rù   rN   ré   r&  )rq   r   r   r”   r•   r–   r(  r9   ÚpoolÚ
fut_sociosÚ	fut_vencer   rÐ   r  Ú
sin_cerrarÚerrores_realesr‰   ÚfuturosÚfutÚnit_resÚempsrî   s   &&&&&&&&              r   Úcierre_empleadosr9  ê  s_  € ð ‡K�KÐIÔJÜ	¨×	*Õ	*¨dØ—[‘[Ô!2°DÓ9ˆ
Ø—[‘[Ô!9Ó:ˆ	Ø×&Ñ&Ó(ˆ
Ø×%Ñ%Ó'ˆ	÷	 
+ð
 ‡K�KÐ-¬c°*«oÐ->ð ?&Ü&)¨)£nÐ%5°ZðAô Bð ‡K�KÐ.¬s°4«y¨kÐ9MÐNÔOØ€IØ€JØ€Nä	¬×	4Õ	4¸á"ó$Ù"�sð —;‘;Ô2°C¸ÓBÀCÒGÙ"ð 	ð $ä Ö(ˆCØ˜#•,ˆCð	IØ #§
¡
£‘�˜Ø× Ñ  '¨4 Ô1Ø—‘˜x¨ u¨B¬s°4«y¨k¸ÐDÖEñ )÷ 
5÷  Ø�‰Ð8¼¸Z»Ð8IÈÐR\ÐQ]Ð^Ô_Ø�‰Ð]Ô_ßØ�‰Ð-¬c°.Ó.AÐ-BÀ(È>ÐJZÐ[Ô\ä˜d¨¸JØ(°ZÈFóTð T÷I 
+×	*Ð	*üò$øô &ô WØ×!Ñ! #Ô&Ø—‘ ¨#¨Ð.TÐU×VÐVÜô IØ×%Ñ% cÔ*Ø—‘˜x¨ uÐ,CÀAÀ3ÐG×HÓHûðIú÷ 
5×	4Ð	4úsg   ¦AG$Ã I3Ã%!G8ÄI3Ä AG=Å'I3Ç$G5	Ç8I3Ç=1I0	È.I3È2I0	È;I0	È<(I+	É$I3É+I0	É0I3É3J	c                óR   € V ^8„  d   QhR\         R\         R\        \        ,          /# r   )r   r›   rT   )r   s   "r   r   r     s%   € ÷ =ñ =”#ð =œCð =¤D¬¥Jñ =r   c                 ó¨  € \         P                  ! W4      w  r#\        W^4      P                  4       p\        WV4      P                  4       pRVRVRRRRRRR	R
RRRRR/RRRRRR
RRRRR/RRRR.RRR.RRR.RRR.RRR.RRR.RRR.RRR./R. R4ORR/p. pR5 F6  p\	        R/ VCRV/C4      p	VP                  V	P                  R. 4      4       K8  	  . p
V EFö  pVP                  RR4      pVP                  R. 4       EFÉ  pVP                  R 4      ;'       g    VP                  RR4      ;'       g    R!P                  4       pVP                  R". 4       EFk  pVP                  R4      ;'       g    RP                  4       pV'       d   VP                  R#4      ^ ,          MR$pT
P                  R%TR TR&TR'VP                  R(4      ;'       g    VP                  R'R4      RVP                  RR4      R)VP                  R)R4      R*VP                  R+4      ;'       g    VP                  R,4      ;'       g    ^ R-\        VP                  R-4      4      R.\        VP                  R/4      ;'       g    VP                  R.4      4      RVP                  R4      R0VP                  R0R14      R2VP                  R3R4      /4       EKn  	  EKÌ  	  EKù  	  V
# )6zm
Llama la API de IR para el mes completo y aplana la respuesta.
Devuelve lista de rows listos para insertar.
r¥   r¦   r§   r¨   r©   rª   Fr«   Tr¬   r­   r®   r¯   r°   r±   r²   r³   r´   rµ   r¶   r·   r¸   r¹   rº   r»   r¼   r½   r¾   r¿   r  rÀ   rŒ   r  r’   rJ   Nr  Úcodigo_empleadoÚnombre_completoÚnombresr  r  r  r  ÚingresoÚterminorÂ   r  zEn OperacionÚtipo_movimientorÁ   rÉ   rÌ   )r   r!  r   rÏ   rj   Úextendr‘   Úupperrø   Úsplitr  rP   )r   r   r    r"  rÑ   rÒ   rÓ   Úhoteles_combinadosrÔ   rX   r’   rÕ   r  r«   rŒ   rÖ   Úcontrato_rawr<  s   &&                r   Úfetch_irrG    sæ  € ô
 ×'Ò'¨Ó1�M€AÜ
ˆs˜Ó
×
%Ñ
%Ó
'€BÜ
ˆs˜Ó
$×
.Ñ
.Ó
0€Bð 	˜"Ø˜"Ø˜#Ø�U˜E 4¨°°uØ˜e W¨eð5à�U˜E 4¨°°uØ˜e W¨eð5àØ˜b %˜[Ø˜b %˜[Ø˜b %˜[Ø˜b %˜[Ø˜b %˜[Ø˜b %˜[Ø˜b %˜[Ø˜b %˜[ð	
ð 	’oØ�cð'€Hð, &(ÐÛˆÜÐ0Ð2Y°XÐ2YÐ?OÐQXÑ2YÓZˆØ×!Ñ! $§(¡(¨9°bÓ"9Ö:ñ ð €DÜ#ˆØ—I‘I˜l¨BÓ/ˆ	Ø—)‘)Ð.°×3ˆBØŸ™ Ó,×KÐK°·±°t¸RÓ0@×KÐKÀG×RÑRÓTˆIØ—v‘v˜f b×)�ð !$§¡¨
Ó 3× 9Ð 9°r×@Ñ@ÓB�ß@L ,×"4Ñ"4°SÓ"9¸!Ö"<ÐRV�Ø—‘Ø iØ iØ% Ø% s§w¡w¨yÓ'9×'[Ð'[¸S¿W¹WÐEVÐXZÓ=[Ø c§g¡g¨g°rÓ&:Ø# c§g¡g¨o¸rÓ&BØ! c§g¡g¨hÓ&7×&SÐ&S¸3¿7¹7À:Ó;N×&SÐ&SÐRSØ¤j°·±¸Ó1CÓ&DØ¤j°·±¸Ó1G×1]Ð1]È3Ï7É7ÐS\ÓK]Ó&^Ø" c§g¡g¨nÓ&=Ø c§g¡g¨k¸>Ó&JØ% s§w¡w¨v°sÓ';ð÷ ô *ô 4ñ $ð0 €Kr   c                óv   € V ^8„  d   QhR\         \        ,          R\        R\        R\        R\        R\        /# )r   r’   r”   r–   r   r   r   )r›   rT   r   )r   s   "r   r   r   [  s>   € ÷ 'ñ 'œD¤�Jð '´dð 'Üð'Ü&)ð'Ü03ð'Ü@Cñ'r   c                óè  € V'       g   VP                  R4       ^ # V RVR 2p. pV F¹  p	V	R,          P                  4       p
VP                  V	R,          V
34      pTP                  TV	R,          V	R,          V	R,          V	R	,          V	R
,          '       d   \	        V	R
,          4      MRV	R,          V	R,          V	R,          V	R,          VV	P                  R4      34       K»  	  V P                  4       ;_uu_ 4       p\        P                  P                  VRVRR7       RRR4       V P                  4        VP                  R\        V4       24       \        V4      #   + '       g   i     LH; i)z+Inserta los movimientos IR en historico_ir.z%  No hay movimientos IR para insertarrJ   r!   rŒ   r  r=  r?  r®   rA  r  Nr  r@  r  r¸   r<  a  
            INSERT INTO historico_ir
                (razon_social, nombre_completo, ingreso, cargo,
                 tipo_movimiento, sueldo_base, tipo_contrato,
                 termino, operacion, causa_retiro, periodo, codigo_empleado)
            VALUES %s
        r  r  u!     âœ… Movimientos IR insertados: )rù   rì   r‘   r  Úfloatrv   rm   r�   r  r  r6   rú   )rq   r’   r”   r–   r   r   r9   r}   Úinsert_rowsr—   Úbu_lowr˜   ry   s   &&&&&&&      r   Úinsertar_irrM  [  sQ  € ÷ Ø�‰Ð>Ô?Ùà�%�q˜˜S˜	Ð"€GØ€KÛˆØ�;•×%Ñ%Ó'ˆØ×!Ñ! 1 [¥>°6Ð":Ó;ˆà×ÑØØÐÕ Øˆi�LØˆg�JØÐÕ Ø'(¨×'7Ô'7ŒE�!�MÕ"Ô#¸TØˆoÕØˆi�LØˆk�NØˆnÕØØ�E‰EÐ#Ó$ð
ö 	ñ	 ð& 
�‰�Œ˜#Ü�‰×&Ñ& sð -ð  Cð 	'ô 	)÷ 
ð 	‡K�K„MØ
‡K�KÐ3´C¸Ó4DÐ3EÐFÔGÜˆ{ÓÐ÷ 
�ús   Ã=$E!Å!E1	ÚCLUBÚFEBc                ó^   € V ^8„  d   QhR\         R\         R\        \         \         3,          /# r   )r   r@   )r   s   "r   r   r   �  s)   € ÷ 9ñ 9œ3ð 9¤Sð 9¬U´3¼°8­_ñ 9r   c                 ó:   € V^8X  d   V ^,
          ^3# W^,
          3# )é   rl   )r   r   s   &&r   Ú_periodo_anteriorrS  �  s!   € Ø 1œHˆC�!�G�Rˆ=Ð8¨3°aµ¨.Ð8r   c                ó<   € V ^8„  d   QhR\         R\         R\         /# r   rt   )r   s   "r   r   r   “  s&   € ÷ Vñ V¬3ð V´Sð VÌcñ Vr   c                ó´  € V RVR 2p\        W4      w  rg\        P                  ! W4      w  r‰\        W^4      p
\        WV	4      p^ pV P	                  4       ;_uu_ 4       pVP                  R4       \        V4       EF¡  pVP                  RW^34       VP                  4       ^ ,          ^ 8”  d   K5  VP                  RW®34       VP                  4        Uu/ uF  qÿ^ ,          VbK  	  ppVP                  R\        Wg^4      V34       VP                  4        Uu/ uF  qÿ^ ,          VbK  	  ppV'       g*   V'       d    VP                  RV RV RV RVR R	2	4       Kã  . pVP                  4        F¢  w  ppVV9   d   K  V^,          '       d"   W¯^,          u;8:  d   V8:  d   M M	V^,          MT
pTP                  Yï^,          TV^,          R
V^,          '       d   \        V^,          4      MRV^,          V^,          V^,          RVVR34       K¤  	  VP                  4        Fp  w  ppVV9   d   K  TP                  Yï^,          V^,          V^,          RV^,          '       d   \        V^,          4      MRV^,          VV^,          RVVR34       Kr  	  V'       g   EK*  \        P                  P                  VRVRR7       \!        R V 4       4      p\!        R V 4       4      pV\#        V4      ,          pVP                  RV RV RV RV R2	4       EK¤  	  RRR4       V P%                  4        V# u upi u upi   + '       g   i     L,; i)a+  
Sintetiza movimientos IR para las `razones` cuya API no entrega datos,
comparando el snapshot de historico_empleados del mes vs. el del mes anterior:
  - cedula en el mes y no en el anterior  -> ingreso ('I')
  - cedula en el anterior y no en el mes   -> retiro  ('R')
Solo actua si esa razon no tiene NINGUNA fila IR del periodo (si la API
empieza a devolverla, esos datos reales mandan). Filas marcadas origen='snapshot'.
Limitacion: una transferencia entre dos razones del mismo grupo se ve como
retiro en una + ingreso en la otra (no como traslado).
rJ   r!   zRALTER TABLE historico_ir ADD COLUMN IF NOT EXISTS origen VARCHAR(16) DEFAULT 'api'zFSELECT COUNT(*) FROM historico_ir WHERE periodo=%s AND razon_social=%sa  
                SELECT codigo_empleado, nombre_completo, cargo, tipo_contrato,
                       sueldo_base, operacion, fecha_ingreso, fecha_vencimiento_contrato
                FROM historico_empleados WHERE fecha=%s AND razon_social=%s
            z  IR fallback Ú z: sin snapshot de z, no se puede derivarrº   NÚsnapshotÚRa)  
                INSERT INTO historico_ir
                  (razon_social, nombre_completo, ingreso, cargo, tipo_movimiento,
                   sueldo_base, tipo_contrato, termino, operacion, causa_retiro,
                   periodo, codigo_empleado, origen)
                VALUES %s
            r  r  c              3   óD   "  € T F  q^,          R8X  g   K  ^x € K  	  R# 5i)rÍ   rº   Nrl   ©Ú.0Úfs   & r   Ú	<genexpr>Ú.completar_ir_desde_snapshot.<locals>.<genexpr>à  ó   é € Ð8¡5˜a¨a­D°C©KŸš£5ùó   ‚ –
 c              3   óD   "  € T F  q^,          R8X  g   K  ^x € K  	  R# 5i)rÍ   rX  Nrl   rZ  s   & r   r]  r^  á  r_  r`  u     âš ï¸�  IR de u(   : la API no la entrego â€” sintetizados z ingresos + z. retiros desde el snapshot (origen='snapshot'))rS  r   r!  r   rv   rw   Úsortedrx   r�   rù   Úitemsr  rJ  rm   r�   r  Úsumrú   r  )rq   r   r   Úrazonesr9   r}   ÚpaÚpmr    r"  Úini_mesÚfin_mesÚtotalry   Úrsr—   Úcur_snapÚ	prev_snapÚfilasÚcodÚingÚing_nÚret_ns   &&&&&                  r   Úcompletar_ir_desde_snapshotrs  “  s)  € ð ��Q�s˜3�iÐ €GÜ˜sÓ(�F€BÜ×'Ò'¨Ó1�M€AÜ�3˜QÓ€GÜ�3˜ZÓ(€GØ€Eà	�‰�Œ˜#Ø�‰Ø`ô	
ô ˜—/ˆBØ�K‰KØXØ�ôð �|‰|‹~˜aÕ  1Ô$Ùà�K‰Kð ð �ô	 ð
 *-¯©¬Ó8© A˜!�˜aš©ˆHÐ8à�K‰Kð ô �r˜q“/ 2Ð&ô	(ð
 +.¯,©,¬.Ó9©. Q˜1�˜qš©.ˆIÐ9çßØ—N‘NØ(¨¨¨A¨g¨YÐ6HÈÈÈAÈbÐQTÈXð V.ð /ôñ àˆEØ"Ÿ.™.Ö*‘��QØ˜)Ô#ÙØ  Ÿtœt¨°Qµ4Ö(B¸7×(B�a˜–dÈ�Ø—‘˜b A¥$¨¨Q¨q­T°3Ø-.¨q¯T¬Tœe A a¥Dœk°t¸Q¸q½TÀ1ÀQÅ4Ø �d D¨'°3¸
ðDö Eñ	 +ð $Ÿ/™/Ö+‘��QØ˜(”?ÙØ—‘˜b A¥$¨¨!­¨a°­d°CØ-.¨q¯T¬Tœe A a¥Dœk°t¸Q¸q½TÀ7Ø �d D¨'°3¸
ðDö Eñ ,÷ Úä�O‰O×*Ñ*¨3ð 1ð  #ð +ô 'ô Ñ8¡5Ó8Ó8ˆEÜÑ8¡5Ó8Ó8ˆEØ”S˜“ZÕˆEØ�N‰NØ" 2 $ a¨ yÐ0XØ�'˜ e WÐ,Zð\÷ñu "÷	 
ðF 	‡K�K„MØ€Lùòg 9ùò :÷1 
�ús@   Á A7MÃL=
Ã)2MÄM
Ä-MÄ?AMÆDMÊ$A?MÌ=
MÍM	c                ó`   € V ^8„  d   QhR\         R\         R\        R\        R\        R\        /# )r   r   r   Ú	modo_testÚempleados_activos_detalleÚsolo_empleados_si_vacior   )r   Úbool)r   s   "r   r   r   î  sA   € ÷ Bñ Bœð B¤3ð B´4ð BÜ/3ðBä-1ðBä>BñBr   c                óê  € . R*Op\        W4      pVP                  R+4       VP                  RWQ^,
          ,           RV  24       VP                  R\        P                  ! 4       P	                  R4       24       V'       d   VP                  R4       V'       d   VP                  R4       V'       d   VP                  R4       VP                  R+4        \        4       p\        V4      w  r‰p
\        V4      pVP                  R\        V4       24       VP                  R	4       VP                  R
4       \        WpV4      pV^ 8”  dÇ   VP                  RV RWQ^,
          ,           RV  24       V'       d   VP                  R4       MVP                  R4       V'       gl   V'       gd   VP                  4       ;_uu_ 4       pVP                  R\        W^4      34       RRR4       VP                  4        VP                  RV R24       MVP                  R4       V'       d   V^ 8”  d   TpM¦V'       gQ   V'       d:   \        V4      pVP                  R\        V4       24       \        WpWWšWöVR7	      pM]\!        WpWWšW¶4      pMNV'       d   VP                  R4       M2V'       d   V^ 8”  d   VP                  R4       MVP                  R4       ^ pVP                  R	4       VP                  R4       \#        WpV4      pV^ 8”  dº   VP                  RV RWQ^,
          ,           RV  24       VP                  R4       V'       gy   \$        P&                  ! W4      w  ppVP                  4       ;_uu_ 4       pVP                  RV  RVR 234       RRR4       VP                  4        VP                  RV R24       MVP                  R4       V'       gc   VP                  R4       \)        W4      pVP                  R \        V4       24       \+        VVWŠWV4      pV\-        WpV\.        V4      ,          pMVP                  R!4       ^ pVP                  R	4       VP                  R+4       V'       d'   VP                  R"WQ^,
          ,           RV  R#24       MLVP                  R$WQ^,
          ,           RV  24       VP                  R%V 24       VP                  R&V 24       VP                  R+4       VP1                  4        R'#   + '       g   i     EL;; i  + '       g   i     EL˜; i  \2         d©   p^ RIpTP7                  R	4       TP7                  R+4       TP7                  R(T 24       TP7                  TP9                  4       4       TP7                  R+4        XP;                  4        TP1                  4        M  \2         d     Mi ; i Rp?R)# Rp?ii ; i),zY
Ejecuta el cierre para (ano, mes).
Devuelve True si todo fue bien, False si hubo error.
u     CIERRE DE MES â€” rV  z  Ejecutado: ú%d/%m/%Y %H:%M:%Su6     MODO TEST â€” no se escribe nada en la base de datosu:     EMPLEADOS â€” usando GET /rrhh/empleados-activos-detalleu;     EMPLEADOS â€” solo se insertan si el periodo estÃ¡ vacÃ­oz  NITs activos encontrados: r²   z[ 1/2 ] EMPLEADOSu     âš ï¸�  Ya existen z registros para z;  Se conserva el cierre existente; no se recargan empleadosuC     Se sobreescribirÃ¡n (DELETE + INSERT para mantener datos frescos)z0DELETE FROM historico_empleados WHERE fecha = %sNz  Eliminados z registros anterioresu)     Sin datos previos â€” inserciÃ³n frescar+  )rõ   uK     [TEST] Se llamarÃ­a empleados-activos-detalle y se insertarÃ­an empleadosu2     [TEST] Se conservarÃ­an los empleados existentesu@     [TEST] Se llamarÃ­a la API nÃ³mina y se insertarÃ­an empleadosz[ 2/2 ] INGRESOS Y RETIROSz movimientos IR para z+DELETE FROM historico_ir WHERE periodo = %srJ   r!   z movimientos anterioresu     Llamando API de IRâ€¦z#  Movimientos recibidos de la API: u=     [TEST] Se llamarÃ­a la API IR y se insertarÃ­an movimientosu     âœ… TEST completado â€” z listo para cerraru     âœ… CIERRE COMPLETADO â€” z     Empleados:  z     IR:         Tu     â�Œ ERROR EN CIERRE â€” F©ÚEneroÚFebreroÚMarzoÚAbrilÚMayoÚJunioÚJulioÚAgostoÚ
SeptiembreÚOctubreÚ	NoviembreÚ	DiciembrezF======================================================================)r=   r6   r   r$   r%   rr   r™   rž   rú   rz   rv   rw   r   r  r¢   r  r9  r~   r   r!  rG  rM  rs  ÚIR_FALLBACK_SNAPSHOT_RAZONESÚcloserN   Ú	tracebackré   Ú
format_excÚrollback)r   r   ru  rv  rw  Úmeses_esr9   rq   r”   r•   r–   r(  Úexiste_empsry   Ú
total_empsr   Ú	existe_irr    r"  Úir_rowsÚtotal_irrî   rŠ  s   &&&&&                  r   Úejecutar_cierrer“  î  sú  € òQ€Hä˜#Ó#€Fà
‡K�K�ÔØ
‡K�KÐ& x°Aµ¥Ð&7°q¸¸Ð>Ô?Ø
‡K�K�-¤§¢£× 7Ñ 7Ð8KÓ LÐMÐNÔOßØ�‰ÐLÔMß Ø�‰ÐPÔQßØ�‰ÐQÔRØ
‡K�K�ÔðlÜ‹|ˆô /CÀ4Ó.HÑ+ˆ )Ü" 4Ó(ˆØ�‰Ð2´3°t³9°+Ð>Ô?ð 	�‰�BŒØ�‰Ð'Ô(Ü*¨4°cÓ:ˆØ˜Œ?Ø�K‰KÐ/°¨}Ð<LÈXÐZ[ÕV[Í_ÐL]Ð]^Ð_bÐ^cÐdÔeß&Ø—‘ÐYÕZà—‘ÐaÔbß×%<Ø—[‘[—]”] cØ—K‘KÐ RÜ!% c°Ó!2Ð 4ô6÷ #ð —‘”Ø—‘˜m¨K¨=Ð8MÐNÔOøà�K‰KÐCÔEç" {°Q¤Ø$‰Jßß(Ü.¨tÓ4�
Ø—‘Ð9¼#¸j»/Ð9JÐKÔLÜ?Ø˜s°*Ø°tô‘
ô
 .¨d¸Ø/9ÀdóT‘
÷ )Ø—‘ÐiÕjß(¨[¸1¬_Ø—‘ÐPÕQà—‘Ð^Ô_ØˆJð 	�‰�BŒØ�‰Ð0Ô1Ü! $¨SÓ1ˆ	Ø�qŒ=Ø�K‰KÐ/°	¨{Ð:OÐPXÐ]^ÕY^ÕP_ÐO`Ð`aÐbeÐafÐgÔhØ�K‰KÐ]Ô^ßÜ (× 3Ò 3°CÓ =‘��:Ø—[‘[—]”] cØ—K‘KØEØ˜5  # c Ð+Ð-ô÷ #ð
 —‘”Ø—‘˜m¨I¨;Ð6MÐNÔOøà�K‰KÐCÔEçØ�K‰KÐ1Ô2Ü  Ó*ˆGØ�K‰KÐ=¼cÀ'»l¸^ÐLÔMÜ# D¨'°<ÈCÐV\Ó]ˆHð Ô3Ø˜3Ô <¸fóõ ‰Hð �K‰KÐWÔXØˆHð 	�‰�BŒØ�‰�HÔßØ�K‰KÐ4°XÀ!½eµ_Ð4EÀQÀsÀeÐK]Ð^Õ_à�K‰KÐ6°xÀAÅµÐ6GÀqÈÈÐNÔOØ�K‰KÐ+¨J¨<Ð8Ô9Ø�K‰KÐ+¨H¨:Ð6Ô7Ø�‰�HÔà�
‰
ŒÙ÷W #—]�]ú÷N #—]�]ûôL ô ÛØ�‰�RÔØ�‰�XÔØ�‰Ð1°!°Ð5Ô6Ø�‰�Y×)Ñ)Ó+Ô,Ø�‰�XÔð	Ø�M‰MŒOØ�J‰J�LøÜô 	Ùð	úåûðús£   ÃCT? Æ'T? Æ/T? ÇTÇ%AT? È,T? È>T? ÉAT? ÊT? Ê0CT? ÎT+ÎAT? Ï#D2T? ÔT(	Ô"	T? Ô+T<	Ô6	T? Ô?W2Õ
A*W-Ö5 W×W-×W$×!W-×#W$×$W-×-W2c                  óV  € \        R 4       R\        P                  9   p R\        P                  9   pR\        P                  9   p\        4       w  r4\        P                  R,           Fw  pVP	                  R4      '       d$   \        VP                  R4      ^,          4      pK=  VP	                  R4      '       g   KV  \        VP                  R4      ^,          4      pKy  	  . ROp\        RWd^,
          ,           R	V 24       \        R
\        P                  ! 4       P                  R4       R24       \        W4WV4      pV'       d   \        P                  ! ^ 4       V '       gb   \        R,          p\        RV R24       \        P                  ! \        4       \        W4WV4      pV'       d   \        P                  ! ^ 4       \         P"                  ! RV RV 24      p	V	P%                  R\&        ,           4       V	P%                  R4       \        P                  ! ^4       R# )r   z--testz--empleados-activos-detallez--solo-empleados-si-vacio:rR  NNz--ano=Ú=z--mes=u   
ðŸ”„ cierre_mes.py â€” rV  z   rz  Ú
r   u   
â�³ Reintentando en u    hora(s)â€¦
r   r    u-   Ambos intentos fallaron â€” revisar logs en: z+Ejecutar manualmente: python3 cierre_mes.pyNr{  )r	   r1   ÚargvrF   Ú
startswithr   rD  Úprintr   r$   r%   r“  ÚexitÚRETRY_DELAY_SÚtimeÚsleepr   r*   ré   r)   )
ru  rv  rw  r   r   Úargr�  ÚokÚhorasÚlogger_alerts
             r   Úmainr¢  u  s¤  € ÜÐ$Ô%ØœCŸH™HÑ$€IØ =ÄÇÁÑ IÐØ9¼S¿X¹XÑEÐô Ó�H€CÜ�x‰x˜�|ˆ|ˆØ�>‰>˜(×#Ò#Ü�c—i‘i “n QÕ'Ó(ŠCØ�^‰^˜H×%Ô%Ü�c—i‘i “n QÕ'Ó(ŠCñ	 ò
R€Hô 
Ð% h°1­u¥oÐ%6°a¸°uÐ
=Ô>Ü	ˆC”—’“×'Ñ'Ð(;Ó<Ð=¸RÐ
@ÔAô 
˜ 9ÐI`Ó	a€Bß	Ü�Š�Œ÷ Ü Õ%ˆÜÐ& u g¨]Ð;Ô<Ü�
Š
”=Ô!ä˜S yÐMdÓeˆßÜ�HŠH�QŒKô ×$Ò$ w¨s¨e°1°S°EÐ%:Ó;€LØ×ÑÐFÌÕQÔRØ×ÑÐDÔEÜ‡H‚HˆQ†Kr   Ú__main__)é   )N)FFF)@rà   r]   r&   r1   rœ  r   r   Úurllib.requestr`   Úurllib.errorrm   Úpsycopg2.extrasr   r   Úconcurrent.futuresr   r   Ú
app_configr   r   r   r	   r
   r'   ÚdirnameÚabspathÚ__file__ÚBASE_DIRr(   r)   Úmakedirsrc   ro   r.  r›  r�   re   r=   rF   rP   rj   rr   rz   r~   r™   rž   r¢   rÙ   rN   rÛ   rð   ró   rþ   r  r&  r9  rG  rM  rˆ  rS  rs  r“  r¢  rÜ   rl   r   r   Ú<module>r¯     sX  ðñó& Û 	Û 
Û Û Û Û Û Û Û ß #ß ?ß XÕ Xð �7‰7�?‰?˜2Ÿ7™7Ÿ?™?¨8Ó4Ó5€Ø�7‰7�<‰<˜ &¨)Ó4€Ø ‡‚ˆH˜tÕ $ð €Ù‹K€	ð €Ø€ð �UˆO€	ñ ‹-€õõ8#õ÷	'òõ!õ!õ+/õ\
.õ.õ6ôv	˜ô 	õ
õ4#õ p÷&FõROõd,Tõb=õ@'ðb !'¨˜Ð õ9õV÷vBòN&ðR ˆzÔÙ†Fñ r   