§
    Âðin  ã                   ól  — d dl Z d dlZd dlmZmZmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dl m!Z!m"Z"m#Z#m$Z$ de%de%de%de&dede&fd„Z'd„ Z(d„ Z)d„ Z*d„ Z+d„ Z,d„ Z-de%de.fd „Z/de%d!e&de.fd"„Z0de%ddfd#„Z1de2fd$„Z3d%„ Z4dS )&é    N)ÚdateÚ	timedeltaÚdatetime)ÚMIMEMultipart)ÚMIMEText)ÚAsyncSession)ÚselectÚfunc)ÚAsyncSessionLocal)ÚContract)ÚRecurringTask)ÚTask)ÚLeaveRequest)ÚNotification)ÚUser)Úsettings)Úget_next_due_date)Únotify_user_by_idÚnotify_adminsÚnotify_user_groupÚnotify_admin_groupÚto_emailÚusernameÚcontract_titleÚ	days_leftÚ
expires_onÚcontract_idc              ƒ   ó’  K  — 	 t          d¦  «        }d|› d|› �|d<   t          j        |d<   | |d<   d|› d|› d	|› d
|› d|› d�}|                     t	          |d¦  «        ¦  «         t          j        |t          j        t          j        dd¬¦  «        ƒ d{V —† dS # t          $ r }t          d| › d|› �¦  «         Y d}~dS d}~ww xY w)z5Send contract expiry warning email via local Postfix.Úalternativez[Jarvis] Contract expiring in z days: ÚSubjectÚFromÚToz
        <p>Hi a  ,</p>
        <p>This is a reminder that the following contract is expiring soon:</p>
        <table style="border-collapse:collapse;margin:12px 0">
          <tr><td style="padding:4px 12px 4px 0;color:#555">Contract</td>
              <td style="padding:4px 0"><strong>z�</strong></td></tr>
          <tr><td style="padding:4px 12px 4px 0;color:#555">Expires on</td>
              <td style="padding:4px 0"><strong>z¥</strong></td></tr>
          <tr><td style="padding:4px 12px 4px 0;color:#555">Days left</td>
              <td style="padding:4px 0"><strong style="color:#e63946">zm days</strong></td></tr>
        </table>
        <p>
          <a href="https://jarvis.goteku.com/contracts/u-  "
             style="background:#206bc4;color:#fff;padding:8px 18px;border-radius:4px;text-decoration:none">
            View Contract
          </a>
        </p>
        <p style="color:#9ca3af;font-size:12px;margin-top:24px">
          â€” Jarvis Â· no-reply@jarvis.goteku.com
        </p>
        ÚhtmlF©ÚhostnameÚportÚuse_tlsÚ	start_tlsNz[scheduler] email error to ú: )r   r   Ú	SMTP_FROMÚattachr   Ú
aiosmtplibÚsendÚ	SMTP_HOSTÚ	SMTP_PORTÚ	ExceptionÚprint)	r   r   r   r   r   r   Úmsgr#   Úes	            ú>/var/www/html/jarvis.com/web/backend/app/services/scheduler.pyÚsend_expiry_emailr5      sg  è è € ð'=Ý˜MÑ*Ô*ˆØ\¸)Ð\Ð\ÈNÐ\Ð\ˆˆI‰ÝÔ(ˆˆF‰ØˆˆD‰	ðØðð ð
 2@ðð ð 2<ðð ð HQðð ð 9Dðð ð ˆð, 	�
Š
•8˜D &Ñ)Ô)Ñ*Ô*Ð*õ ŒoØÝÔ'ÝÔ#ØØð
ñ 
ô 
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
ð 	
øõ ð =ð =ð =ÝÐ;¨HÐ;Ð;¸Ð;Ð;Ñ<Ô<Ð<Ð<Ð<Ð<Ð<Ð<Ð<øøøøð=øøøs   „BB Â
CÂ&CÃCc               ƒ   óØ  K  — t          j        ¦   «         } | t          d¬¦  «        z   }| t          d¬¦  «        z   }t          ¦   «         4 ƒd{V —†}	 |                     t          t          ¦  «                             t          j        |k    t          j        |k    ¦  «        ¦  «        ƒ d{V —†}| 	                    ¦   «          
                    ¦   «         }|D �]�}|j        | z
  j        }t          ¦   «         }|j        r|                     |j        ¦  «         |                     t          t          ¦  «                             t          j        dk    t          j        dk    ¦  «        ¦  «        ƒ d{V —†}	|	 	                    ¦   «          
                    ¦   «         D ]}
|                     |
j        ¦  «         Œ|                     t          t          ¦  «                             t          j                             |¦  «        ¦  «        ¦  «        ƒ d{V —†}d„ | 	                    ¦   «          
                    ¦   «         D ¦   «         }|D �]}|                     t          t*          ¦  «                             t*          j        |k    t*          j        d|j        › �k    t*          j                             d	¦  «        ¦  «        ¦  «        ƒ d{V —†}|rŒ‰|                     t+          |d
|j        › �d|› d|j        › d�d|j        › �¬¦  «        ¦  «         |                     |¦  «        }|r;|j        r4t9          |j        |j        |j        ||j        |j        ¬¦  «        ƒ d{V —† �Œ�Œ‘|                     ¦   «         ƒ d{V —† nC# t>          $ r6}|                      ¦   «         ƒ d{V —† tC          d|› �¦  «         Y d}~nd}~ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )zKCheck contracts expiring in ~90 days and send in-app + email notifications.éU   ©Údaysé_   NÚadminTc                 ó   — i | ]
}|j         |“ŒS © )Úid©Ú.0Úus     r4   ú
<dictcomp>z)check_contract_expiry.<locals>.<dictcomp>_   s   € ÐGÐGÐG Q˜œ˜qÐGÐGÐGó    ú/contracts/zContract expiring%zKontrak hampir berakhir: zBerakhir dalam z hari (ú))Úuser_idÚtitleÚbodyÚlink)r   r   r   r   r   r   z [scheduler] expiry check error: )"r   Útodayr   r   Úexecuter	   r   ÚwhereÚ
period_endÚscalarsÚallr9   ÚsetÚ
created_byÚaddr   ÚroleÚ	is_activer>   Úin_Úscalarr   rF   rI   rG   ÚlikeÚgetÚemailr5   r   Úcommitr0   Úrollbackr1   )rJ   Únotify_fromÚ	notify_toÚdbÚresultÚ	contractsÚcontractr   Úuser_idsÚadminsr;   Úusers_resultÚusersrF   ÚexistingÚuserr3   s                    r4   Úcheck_contract_expiryrh   A   sÍ  è è € åŒJ‰LŒL€EØ�)¨Ð,Ñ,Ô,Ñ,€KØ�)¨Ð,Ñ,Ô,Ñ,€Iå Ñ"Ô"ð =:ð =:ð =:ð =:ð =:ð =:ð =: bð<	:ØŸ:š:Ý•xÑ Ô ×&Ò&ÝÔ'¨;Ò6ÝÔ'¨9Ò4ñô ñô ð ð ð ð ð ð ˆFð ŸšÑ(Ô(×,Ò,Ñ.Ô.ˆIà%ð .ñ .�Ø%Ô0°5Ñ8Ô>�	õ ™5œ5�ØÔ&ð 6Ø—L’L Ô!4Ñ5Ô5Ð5à!Ÿzšz­&µ©,¬,×*<Ò*<½T¼YÈ'Ò=QÕSWÔSaÐeiÒSiÑ*jÔ*jÑkÔkÐkÐkÐkÐkÐkÐk�Ø#Ÿ^š^Ñ-Ô-×1Ò1Ñ3Ô3ð +ð +�EØ—L’L ¤Ñ*Ô*Ð*Ð*ð &(§Z¢Zµµt±´×0BÒ0BÅ4Ä7Ç;Â;ÈxÑCXÔCXÑ0YÔ0YÑ%ZÔ%ZÐZÐZÐZÐZÐZÐZ�ØGÐG¨,×*>Ò*>Ñ*@Ô*@×*DÒ*DÑ*FÔ*FÐGÑGÔG�à'ð ñ �Gà%'§Y¢YÝ�|Ñ,Ô,×2Ò2Ý(Ô0°GÒ;Ý(Ô-Ð1L¸x¼{Ð1LÐ1LÒLÝ(Ô.×3Ò3Ð4HÑIÔIñô ñ&ô &ð  ð  ð  ð  ð  ð  �Hð  ð !Ø ð —F’F�<Ø 'ØJ¸(¼.ÐJÐJØW¨yÐWÐWÀÔATÐWÐWÐWØ8¨8¬;Ð8Ð8ð	ñ ô ñ ô ð ð !Ÿ9š9 WÑ-Ô-�DØð  ¤
ð Ý/Ø%)¤ZØ%)¤]Ø+3¬>Ø&/Ø'/Ô':Ø(0¬ðñ ô ð ð ð ð ð ð ð ùñ/ð@ —)’)‘+”+ÐÐÐÐÐÐÐÐøÝð 	:ð 	:ð 	:Ø—+’+‘-”-ÐÐÐÐÐÐÐÝÐ8°QÐ8Ð8Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9øøøøð	:øøøðw=:ð =:ð =:ñ =:ô =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:ð =:øøøð =:ð =:ð =:ð =:ð =:ð =:s=   ÁOÁL0NÎOÎ
OÎ,N>Î9OÎ>OÏOÏ
O#Ï&O#c            
   ƒ   ó&  K  — t          j        ¦   «         } t          ¦   «         4 ƒd{V —†}	 |                     t	          t
          ¦  «                             t
          j        dk    t
          j         	                    ddg¦  «        ¦  «        ¦  «        ƒ d{V —†}| 
                    ¦   «                              ¦   «         }|D �]Ë}	 |j        p| t          d¬¦  «        z
  }t          |j        |j        |¦  «        }|t          |j        ¬¦  «        z
  }| |k    �rA|                     t	          t&          ¦  «                             t&          j        |j        k    t&          j        |k    ¦  «        ¦  «        ƒ d{V —†}|sÝt'          |j        |j        |j        ||j        ¬¦  «        }	|                     |	¦  «         |                     ¦   «         ƒ d{V —† ||_        t9          d|j        › d	|› �¦  «         |j        r1t;          ||j        d
|j        › �d|› �d|	j        › �¦  «        ƒ d{V —† t=          |d
|j        › �d|› �d|	j        › �d¬¦  «        ƒ d{V —† �Œ›# t>          $ r%}
t9          d|j        › d|
› �¦  «         Y d}
~
�ŒÅd}
~
ww xY w|                      ¦   «         ƒ d{V —† nC# t>          $ r6}
| !                    ¦   «         ƒ d{V —† t9          d|
› �¦  «         Y d}
~
nd}
~
ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )zDCheck all active recurring tasks and create task instances when due.NTÚon_scheduleÚbothé   r8   )rG   Úassigned_torQ   Údue_dateÚrecurring_task_idz&[scheduler] generated recurring task 'z' due zTask recurring baru: ú
Due date: ú/tasks/Útelegram_thread_task©Ú
thread_keyz[scheduler] recurring task z error: z,[scheduler] generate_recurring_tasks error: )"r   rJ   r   rK   r	   r   rL   rT   Útrigger_moderU   rN   rO   Úlast_generated_duer   r   Úrecurrence_typeÚrecurrence_configÚadvance_daysrV   r   ro   r>   rn   rG   rm   rQ   rR   Úflushr1   r   r   r0   rZ   r[   )rJ   r^   r_   Úrecurring_listÚrtÚafterÚnext_dueÚtrigger_daterf   Únew_taskr3   s              r4   Úgenerate_recurring_tasksr�   ‡   sŸ  è è € åŒJ‰LŒL€EÝ Ñ"Ô"ð :Fð :Fð :Fð :Fð :Fð :Fð :F bð9	FØŸ:š:Ý•}Ñ%Ô%×+Ò+Ý!Ô+¨tÒ3Ý!Ô.×2Ò2°MÀ6Ð3JÑKÔKñô ñô ð ð ð ð ð ð ˆFð $Ÿ^š^Ñ-Ô-×1Ò1Ñ3Ô3ˆNà$ð +Lñ +L�ð*LØÔ1ÐP°e½iÈQÐ>OÑ>OÔ>OÑ6O�EÝ0°Ô1CÀRÔEYÐ[`ÑaÔa�HØ#+­i¸R¼_Ð.MÑ.MÔ.MÑ#M�Là Ò,Ñ,à)+¯ªÝ"¥4™LœL×.Ò.Ý $Ô 6¸"¼%Ò ?Ý $¤°Ò 9ñô ñ*ô *ð $ð $ð $ð $ð $ð $˜ð  (ð Ý'+Ø&(¤hØ,.¬NØ+-¬=Ø)1Ø24´%ð(ñ (ô (˜Hð ŸFšF 8Ñ,Ô,Ð,Ø"$§(¢(¡*¤*Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø4<˜BÔ1Ý!Ð"eÈ2Ì8Ð"eÐ"eÐ[cÐ"eÐ"eÑfÔfÐfà!œ~ð "Ý&7Ø$&¨¬Ø$F¸B¼HÐ$FÐ$FØ$;°Ð$;Ð$;Ø$;¨h¬kÐ$;Ð$;ñ	'"ô '"ð !"ð !"ð !"ð !"ð !"ð !"ð !"õ #4Ø "Ø B¸¼Ð BÐ BØ 7¨XÐ 7Ð 7Ø 7¨(¬+Ð 7Ð 7Ø+Að#ñ #ô #ð ð ð ð ð ð ð ùøõ !ð Lð Lð LÝÐJ¸¼ÐJÐJÀqÐJÐJÑKÔKÐKÐKÐKÐKÐKÑKøøøøðLøøøð —)’)‘+”+ÐÐÐÐÐÐÐÐøÝð 	Fð 	Fð 	FØ—+’+‘-”-ÐÐÐÐÐÐÐÝÐDÀÐDÐDÑEÔEÐEÐEÐEÐEÐEÐEøøøøð	Føøøðq:Fð :Fð :Fñ :Fô :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Fð :Føøøð :Fð :Fð :Fð :Fð :Fð :Fsf   ªL ¬BJ*ÃFIÉJ*É
JÉ'JÊJ*ÊJÊJ*Ê)L Ê*
K*Ê4,K%Ë L Ë%K*Ë*L Ì 
L
ÌL
c            
   ƒ   ó„  K  — t          j        ¦   «         } t          ¦   «         4 ƒd{V —†}	 |                     t	          t
          ¦  «                             t
          j        | t          d¬¦  «        z
  k    t
          j	        dk    t
          j
        dk    ¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         }|D ]l}t          ||j
        d|j        › �d|j        › d�d|j        › �¦  «        ƒ d{V —† t!          |d|j        › �d	|j        › d
�d|j        › �d¬¦  «        ƒ d{V —† Œm|                     ¦   «         ƒ d{V —† nC# t$          $ r6}|                     ¦   «         ƒ d{V —† t)          d|› �¦  «         Y d}~nd}~ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )z7Notify assignees about tasks that became overdue today.Nrl   r8   ÚdonezTask overdue: zTask ini melewati due date (z).rq   z	Due date z
 terlewat.rr   rs   ú![scheduler] overdue tasks error: )r   rJ   r   rK   r	   r   rL   rn   r   Ústatusrm   rN   rO   r   rG   r>   r   rZ   r0   r[   r1   )rJ   r^   r_   ÚtasksÚtaskr3   s         r4   Úcheck_overdue_tasksrˆ   Ç   sÚ  è è € åŒJ‰LŒL€EÝ Ñ"Ô"ð ;ð ;ð ;ð ;ð ;ð ;ð ; bð	;ØŸ:š:Ý•t‘”×"Ò"Ý”M U­Y¸AÐ->Ñ->Ô->Ñ%>Ò>Ý”K 6Ò)ÝÔ$¨Ò,ñô ñô ð ð ð ð ð ð ˆFð —N’NÑ$Ô$×(Ò(Ñ*Ô*ˆEØð ð �Ý'Ø˜Ô(Ø1 T¤ZÐ1Ð1ØD°4´=ÐDÐDÐDØ'˜dœgÐ'Ð'ñ	ô ð ð ð ð ð ð ð õ (ØØ1 T¤ZÐ1Ð1Ø9 ¤Ð9Ð9Ð9Ø'˜dœgÐ'Ð'Ø5ðñ ô ð ð ð ð ð ð ð ð ð —)’)‘+”+ÐÐÐÐÐÐÐÐøÝð 	;ð 	;ð 	;Ø—+’+‘-”-ÐÐÐÐÐÐÐÝÐ9°aÐ9Ð9Ñ:Ô:Ð:Ð:Ð:Ð:Ð:Ð:øøøøð	;øøøð3;ð ;ð ;ñ ;ô ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;ð ;øøøð ;ð ;ð ;ð ;ð ;ð ;s;   ªF/¬D,EÅF/Å
FÅ#,FÆF/ÆFÆF/Æ/
F9Æ<F9c            
   ƒ   ól  K  — t          j        ¦   «         t          d¬¦  «        z   } t          ¦   «         4 ƒd{V —†}	 |                     t          t          ¦  «                             t          j        | k    t          j	        dk    t          j
        dk    ¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         }|D ]`}t          ||j
        d|j        › �d| › �d|j        › �¦  «        ƒ d{V —† t!          |d|j        › �d| › �d|j        › �d¬	¦  «        ƒ d{V —† Œa|                     ¦   «         ƒ d{V —† nC# t$          $ r6}|                     ¦   «         ƒ d{V —† t)          d
|› �¦  «         Y d}~nd}~ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )z9Notify assignees about tasks due tomorrow (H-1 reminder).rl   r8   Nrƒ   zTask due besok: rp   rq   rr   rs   ú [scheduler] due tomorrow error: )r   rJ   r   r   rK   r	   r   rL   rn   r…   rm   rN   rO   r   rG   r>   r   rZ   r0   r[   r1   )Útomorrowr^   r_   r†   r‡   r3   s         r4   Úcheck_due_tomorrowrŒ   è   sÐ  è è € åŒz‰|Œ|�i¨QÐ/Ñ/Ô/Ñ/€HÝ Ñ"Ô"ð :ð :ð :ð :ð :ð :ð : bð	:ØŸ:š:Ý•t‘”×"Ò"Ý”M XÒ-Ý”K 6Ò)ÝÔ$¨Ò,ñô ñô ð ð ð ð ð ð ˆFð —N’NÑ$Ô$×(Ò(Ñ*Ô*ˆEØð ð �Ý'Ø˜Ô(Ø3 t¤zÐ3Ð3Ø+ Ð+Ð+Ø'˜dœgÐ'Ð'ñ	ô ð ð ð ð ð ð ð õ (ØØ3 t¤zÐ3Ð3Ø+ Ð+Ð+Ø'˜dœgÐ'Ð'Ø5ðñ ô ð ð ð ð ð ð ð ð ð —)’)‘+”+ÐÐÐÐÐÐÐÐøÝð 	:ð 	:ð 	:Ø—+’+‘-”-ÐÐÐÐÐÐÐÝÐ8°QÐ8Ð8Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9øøøøð	:øøøð3:ð :ð :ñ :ô :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :ð :øøøð :ð :ð :ð :ð :ð :s;   »F#½DEÅF#Å
FÅ,FÆF#ÆFÆF#Æ#
F-Æ0F-c            
   ƒ   ó`  K  — t          j        ¦   «         } t          ¦   «         4 ƒd{V —†}	 |                     t	          t
          ¦  «                             t
          j        | t          d¬¦  «        z
  k    ¦  «        ¦  «        ƒ d{V —†}| 	                    ¦   «          
                    ¦   «         }|D ]x}d|j        › �}d|j        › d�}d|j        › �}|j        rt          ||j        |||¦  «        ƒ d{V —† t          ||||¦  «        ƒ d{V —† t!          ||||d¬	¦  «        ƒ d{V —† Œy|                     ¦   «         ƒ d{V —† nC# t$          $ r6}|                     ¦   «         ƒ d{V —† t)          d
|› �¦  «         Y d}~nd}~ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )z6Notify creator + admins when a contract expires today.Nrl   r8   zKontrak telah berakhir: zKontrak berakhir pada ú.rD   Útelegram_thread_contractrs   ú%[scheduler] contracts expired error: )r   rJ   r   rK   r	   r   rL   rM   r   rN   rO   rG   r>   rQ   r   r   r   rZ   r0   r[   r1   )	rJ   r^   r_   r`   ra   rG   rH   rI   r3   s	            r4   Úcheck_contracts_expired_todayr‘   	  s´  è è € åŒJ‰LŒL€EÝ Ñ"Ô"ð ?ð ?ð ?ð ?ð ?ð ?ð ? bð	?ØŸ:š:Ý•xÑ Ô ×&Ò&¥xÔ':¸eÅiÐUVÐFWÑFWÔFWÑ>WÒ'WÑXÔXñô ð ð ð ð ð ð ˆFð ŸšÑ(Ô(×,Ò,Ñ.Ô.ˆIØ%ð 	fð 	f�ØC°8´>ÐCÐC�ØG°Ô1DÐGÐGÐG�Ø3 h¤kÐ3Ð3�àÔ&ð XÝ+¨B°Ô0CÀUÈDÐRVÑWÔWÐWÐWÐWÐWÐWÐWÐWÝ# B¨¨t°TÑ:Ô:Ð:Ð:Ð:Ð:Ð:Ð:Ð:å'¨¨E°4¸ÐJdÐeÑeÔeÐeÐeÐeÐeÐeÐeÐeÐeØ—)’)‘+”+ÐÐÐÐÐÐÐÐøÝð 	?ð 	?ð 	?Ø—+’+‘-”-ÐÐÐÐÐÐÐÝÐ=¸!Ð=Ð=Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>øøøøð	?øøøð#?ð ?ð ?ñ ?ô ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?ð ?øøøð ?ð ?ð ?ð ?ð ?ð ?s;   ªF¬DEÅFÅ
FÅ,FÅ=FÆFÆFÆ
F'Æ*F'c               ƒ   óŽ  ‡‡‡‡‡K  — t          j        ¦   «         Št          ¦   «         4 ƒd{V —†} 	 |                      t	          t          j        ¦   «         ¦  «                             t          ¦  «         	                    t          j
                             ddg¦  «        ¦  «        ¦  «        ƒ d{V —†pd}|                      t	          t          j        ¦   «         ¦  «                             t          ¦  «         	                    t          j
        dk    ¦  «        ¦  «        ƒ d{V —†pd}|                      t	          t          j        ¦   «         ¦  «                             t          ¦  «         	                    t          j        ‰k    t          j        ‰t          d¬¦  «        z   k    ¦  «        ¦  «        ƒ d{V —†pd}|                      t	          t          ¦  «         	                    t          j        ‰k     t          j
        dk    ¦  «                             t          j        ¦  «                             d	¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         Št-          ‰¦  «        }|                      t	          t          ¦  «         	                    t          j
        dk    ¦  «                             t          j        ¦  «                             d	¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         Š|                      t	          t          ¦  «         	                    t          j        ‰k    t          j        ‰t          d¬¦  «        z   k    ¦  «                             t          j        ¦  «                             d	¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         Št1          ¦   «         }‰D ]#}	|	j        r|                     |	j        ¦  «         Œ$‰D ]}
|                     |
j        ¦  «         Œi Š|r�|                      t	          t8          ¦  «         	                    t8          j                             |¦  «        ¦  «        ¦  «        ƒ d{V —†}d
„ |                     ¦   «                              ¦   «         D ¦   «         Šdt<          fˆˆfd„}dt<          fˆˆfd„}dt<          fˆˆfd„}d}d}‰r)d|› d|                     ddd¬¦  «        ›  |¦   «         › d�}d}‰r)d|› d|                     ddd¬¦  «        ›  |¦   «         › d�}d}‰r)d|› d|                     ddd¬¦  «        ›  |¦   «         › d�}d ‰› d!|› d"|› d#|› d$|› d%|› d&|› d&|› d'�}|                      t	          t8          ¦  «         	                    t8          j         d(k    t8          j!        d)k    ¦  «        ¦  «        ƒ d{V —†}|                     ¦   «                              ¦   «         D ]Ù}|j"        sŒ
	 tG          d*¦  «        }d+‰› �|d,<   tH          j%        |d-<   |j"        |d.<   | &                    tO          |d/¦  «        ¦  «         tQ          j)        |tH          j*        tH          j+        d0d0¬1¦  «        ƒ d{V —† tY          d2|j"        › �¦  «         Œ©# tZ          $ r$}tY          d3|j"        › d4|› �¦  «         Y d}~ŒÒd}~ww xY wn)# tZ          $ r}tY          d5|› �¦  «         Y d}~nd}~ww xY wddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )6z+Send daily digest HTML email to all admins.NÚtodoÚin_progressr   Úpendingé   r8   rƒ   é
   c                 ó(   — i | ]}|j         |j        “ŒS r=   )r>   r   r?   s     r4   rB   z%send_daily_digest.<locals>.<dictcomp>\  s   € ÐMÐMÐM°!˜QœT 1¤:ÐMÐMÐMrC   Úreturnc                  óÈ   •— d} t          ‰¦  «        D ]N\  }}|dz  rdnd}|j        r‰                     |j        d¦  «        nd}| d|› d|j        › d|› d|j        › d	�	z  } ŒO| S )
NÚ é   úbackground:#fafafa;ú-ú<tr style="z?"><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6">úM</td><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6;color:#555">z`</td><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6;color:#dc2626;font-weight:600">ú
</td></tr>)Ú	enumeraterm   rX   rG   rn   )ÚrowsÚiÚtÚbgÚassigneeÚoverdue_tasksÚ	users_maps        €€r4   Ú_overdue_rowsz(send_daily_digest.<locals>._overdue_rows_  s·   ø€ Ø�Ý% mÑ4Ô4ð 	ð 	‘D�A�qØ23°a±%Ð?Ð.Ð.¸R�BØDEÄMÐZ˜yŸ}š}¨Q¬]¸CÑ@Ô@Ð@ÐWZ�HØð! bð !ð !ØXYÔX_ð!ð !àckð!ð !ð wxô  wAð!ð !ð !ñ�D�Dð �rC   c                  óþ   •— d} t          ‰¦  «        D ]i\  }}|dz  rdnd}‰                     |j        d¦  «        }|j        |j        z
  j        dz   }| d|› d|› d|j        › d	|j        › d
|› d|j        pd› d�z  } Œj| S )Nr›   rœ   r�   rž   rl   rŸ   úO"><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6;font-weight:500">r    u    â†’ zg &nbsp;<span style="background:#fef3c7;color:#92400e;padding:1px 6px;border-radius:3px;font-size:11px">zY hari</span></td><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6;color:#555">r¡   )r¢   rX   rF   Úend_dateÚ
start_dater9   Úreason)r£   r¤   Úlrr¦   Úunamer9   Ú
leave_listr©   s         €€r4   Ú_leave_rowsz&send_daily_digest.<locals>._leave_rowsm  så   ø€ Ø�Ý& zÑ2Ô2ð ð ‘E�A�rØ23°a±%Ð?Ð.Ð.¸R�BØ%ŸMšM¨"¬*°cÑ:Ô:�EØœK¨"¬-Ñ7Ô=ÀÑA�DØð! bð !ð !Øhmð!ð !ð œ=ð!ð !ð 02¬{ð!ð !ð |@ð	!ð !ð dfÔclÐcsÐpsð!ð !ð !ñ	�D�Dð �rC   c                  óž   •— d} t          ‰¦  «        D ]9\  }}|dz  rdnd}|j        ‰z
  j        }| d|› d|j        › d|j        › d|› d�	z  } Œ:| S )	Nr›   rœ   r�   rŸ   r¬   r    z²</td><td style="padding:8px 10px;border-bottom:1px solid #f3f4f6"><span style="background:#fef2f2;color:#dc2626;padding:2px 8px;border-radius:4px;font-size:12px;font-weight:700">z hari</span></td></tr>)r¢   rM   r9   rG   )r£   r¤   Úcr¦   r   Úcontracts_listrJ   s        €€r4   Ú_contract_rowsz)send_daily_digest.<locals>._contract_rows  s    ø€ Ø�Ý% nÑ5Ô5ð ð ‘D�A�qØ23°a±%Ð?Ð.Ð.¸R�BØ!"¤°Ñ!5Ô ;�IØð! bð !ð !ØhiÔhoð!ð !àcdÔcoð!ð !ð LUð	!ð !ð !ñ�D�Dð �rC   aà  <tr style="background:#f9fafb"><th style="text-align:left;padding:8px 10px;font-size:11px;color:#666;font-weight:600;border-bottom:1px solid #e5e7eb;letter-spacing:.3px">{h1}</th><th style="text-align:left;padding:8px 10px;font-size:11px;color:#666;font-weight:600;border-bottom:1px solid #e5e7eb;letter-spacing:.3px">{h2}</th><th style="text-align:left;padding:8px 10px;font-size:11px;color:#666;font-weight:600;border-bottom:1px solid #e5e7eb;letter-spacing:.3px">{h3}</th></tr>r›   u´   <tr><td style="padding:24px 32px 0"><div style="font-size:13px;font-weight:700;color:#dc2626;margin-bottom:10px;border-left:3px solid #dc2626;padding-left:10px">ðŸ”´ Task Overdue (zk)</div><table width="100%" cellpadding="0" cellspacing="0" style="border-collapse:collapse;font-size:13px">ÚTASKÚASSIGNEEzDUE DATE)Úh1Úh2Úh3z</table></td></tr>u´   <tr><td style="padding:20px 32px 0"><div style="font-size:13px;font-weight:700;color:#d97706;margin-bottom:10px;border-left:3px solid #d97706;padding-left:10px">ðŸ�– Cuti Pending (ÚEMPLOYEEÚPERIODEÚALASANuÅ   <tr><td style="padding:20px 32px 0"><div style="font-size:13px;font-weight:700;color:#16a34a;margin-bottom:10px;border-left:3px solid #16a34a;padding-left:10px">âš ï¸� Kontrak Berakhir â‰¤30 Hari (ÚKONTRAKÚBERAKHIRÚSISAuß  <!DOCTYPE html>
<html lang="id"><head><meta charset="utf-8"></head>
<body style="margin:0;padding:32px 16px;background:#f3f4f6;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif">
<table width="100%" cellpadding="0" cellspacing="0"><tr><td align="center">
<table width="600" cellpadding="0" cellspacing="0" style="background:#fff;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,.10);overflow:hidden">
  <tr><td style="background:#1D9E75;padding:26px 32px">
    <table width="100%" cellpadding="0" cellspacing="0"><tr>
      <td><div style="color:#fff;font-size:22px;font-weight:700;letter-spacing:-0.3px">ðŸ“Š Daily Digest</div>
          <div style="color:rgba(255,255,255,.75);font-size:13px;margin-top:5px">u%   &nbsp;Â·&nbsp; Jarvis Internal</div></td>
      <td align="right"><div style="background:rgba(255,255,255,.15);border-radius:6px;padding:8px 14px;color:#fff;font-size:12px;font-weight:600">08:00 WIB</div></td>
    </tr></table>
  </td></tr>
  <tr><td style="padding:24px 32px 0">
    <table width="100%" cellpadding="0" cellspacing="0"><tr>
      <td style="width:22%;background:#fff1f0;border-radius:8px;padding:16px 10px;text-align:center;border:1px solid #fecaca">
        <div style="font-size:32px;font-weight:800;color:#dc2626;line-height:1">as  </div>
        <div style="font-size:10px;color:#888;margin-top:5px;font-weight:600;letter-spacing:.5px">OVERDUE</div>
      </td>
      <td style="width:4%"></td>
      <td style="width:22%;background:#eff6ff;border-radius:8px;padding:16px 10px;text-align:center;border:1px solid #bfdbfe">
        <div style="font-size:32px;font-weight:800;color:#2563eb;line-height:1">av  </div>
        <div style="font-size:10px;color:#888;margin-top:5px;font-weight:600;letter-spacing:.5px">TASK AKTIF</div>
      </td>
      <td style="width:4%"></td>
      <td style="width:22%;background:#fefce8;border-radius:8px;padding:16px 10px;text-align:center;border:1px solid #fde68a">
        <div style="font-size:32px;font-weight:800;color:#d97706;line-height:1">ax  </div>
        <div style="font-size:10px;color:#888;margin-top:5px;font-weight:600;letter-spacing:.5px">CUTI PENDING</div>
      </td>
      <td style="width:4%"></td>
      <td style="width:22%;background:#f0fdf4;border-radius:8px;padding:16px 10px;text-align:center;border:1px solid #bbf7d0">
        <div style="font-size:32px;font-weight:800;color:#16a34a;line-height:1">u«   </div>
        <div style="font-size:10px;color:#888;margin-top:5px;font-weight:600;letter-spacing:.5px">KONTRAK â‰¤30H</div>
      </td>
    </tr></table>
  </td></tr>
  z
  a}  
  <tr><td style="padding:28px 32px 32px;text-align:center;border-top:1px solid #f0f0f0">
    <div style="margin-top:20px">
      <a href="https://jarvis.goteku.com"
         style="display:inline-block;background:#1D9E75;color:#fff;padding:12px 32px;border-radius:6px;text-decoration:none;font-size:14px;font-weight:600;letter-spacing:.2px">
        Buka Jarvis &rarr;
      </a>
    </div>
    <div style="color:#9ca3af;font-size:11px;margin-top:16px;line-height:1.6">
      Anda menerima email ini karena Anda adalah admin Jarvis.<br>
      no-reply@jarvis.goteku.com
    </div>
  </td></tr>
</table>
</td></tr></table>
</body></html>r;   Tr   u   [Jarvis] Daily Digest â€” r    r!   r"   r#   Fr$   z![scheduler] daily digest sent to z"[scheduler] digest email error to r)   ú [scheduler] daily digest error: ).r   rJ   r   rV   r	   r
   ÚcountÚselect_fromr   rL   r…   rU   r   r   rM   r   rK   rn   Úorder_byÚlimitrN   rO   ÚlenÚ
created_atrP   rm   rR   rF   r   r>   ÚstrÚformatrS   rT   rY   r   r   r*   r+   r   r,   r-   r.   r/   r1   r0   )r^   Úactive_countÚpending_leave_countÚexpiring_countÚoverdue_resÚoverdue_countÚ	leave_resÚcontracts_resrb   r¥   r°   Úu_resrª   r³   r·   ÚthÚoverdue_sectionÚleave_sectionÚcontracts_sectionr#   Ú
admins_resr;   Ú	email_msgr3   r¶   r²   r¨   rJ   r©   s                           @@@@@r4   Úsend_daily_digestrÚ   "  s’	  øøøøøè è € åŒJ‰LŒL€EÝ Ñ"Ô"ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]: bð\	:à!#§¢Ý•t”z‘|”|Ñ$Ô$×0Ò0µÑ6Ô6×<Ò<Ý”K—O’O V¨]Ð$;Ñ<Ô<ñô ñ"ô "ð ð ð ð ð ð ð ð ð	 ð
 )+¯	ª	Ý•t”z‘|”|Ñ$Ô$×0Ò0µÑ>Ô>×DÒDÝ Ô'¨9Ò4ñô ñ)ô )ð #ð #ð #ð #ð #ð #ð #ð ð	  ð
 $&§9¢9Ý•t”z‘|”|Ñ$Ô$×0Ò0µÑ:Ô:×@Ò@ÝÔ'¨5Ò0ÝÔ'¨5µ9À"Ð3EÑ3EÔ3EÑ+EÒEñô ñ$ô $ð ð ð ð ð ð ð ð
 ð ð !#§
¢
Ý•t‘”×"Ò"Ý”M EÒ)Ý”K 6Ò)ñô ÷ ’(�4œ=Ñ)Ô)¯%ª%°©)¬)ñ	!ô !ð ð ð ð ð ð ˆKð (×/Ò/Ñ1Ô1×5Ò5Ñ7Ô7ˆMÝ Ñ.Ô.ˆMà ŸjšjÝ•|Ñ$Ô$×*Ò*Ý Ô'¨9Ò4ñô ç’(�<Ô2Ñ3Ô3·E²E¸"±I´Iñô ð ð ð ð ð ð ˆIð
 #×*Ò*Ñ,Ô,×0Ò0Ñ2Ô2ˆJà"$§*¢*Ý•xÑ Ô ×&Ò&ÝÔ'¨5Ò0ÝÔ'¨5µ9À"Ð3EÑ3EÔ3EÑ+EÒEñô ÷ ’(�8Ô.Ñ/Ô/·²°b±	´	ñ	#ô #ð ð ð ð ð ð ˆMð +×2Ò2Ñ4Ô4×8Ò8Ñ:Ô:ˆNõ ‘u”uˆHØ"ð 0ð 0�Ø”=ð 0Ø—L’L ¤Ñ/Ô/Ð/øØ ð )ð )�Ø—’˜RœZÑ(Ô(Ð(Ð(Ø ˆIØð NØ Ÿjšj­µ©¬×);Ò);½D¼G¿KºKÈÑ<QÔ<QÑ)RÔ)RÑSÔSÐSÐSÐSÐSÐSÐS�ØMÐM°u·}²}±´×7JÒ7JÑ7LÔ7LÐMÑMÔM�	ð¥3ð ð ð ð ð ð ð ð¥ð ð ð ð ð ð ð ð$¥Cð ð ð ð ð ð ð ð ˆBð !ˆOØð ð*ð huð*ð *ð —y’y F¨z¸j�yÑIÔIð*ð LYÈ=É?Ì?ð*ð *ð *ð  ð ˆMØð ð*ð h{ð*ð *ð —y’y J°9À�yÑJÔJð*ð MXÈKÉMÌMð*ð *ð *ð ð !#ÐØð ð*ð yGð*ð *ð —y’y I°*À�yÑHÔHð*ð KYÈ.ÑJZÔJZð*ð *ð *ð "ð4ð SXð4ð 4ð R_ð4ð 4ð( R^ð)4ð 4ð2 Reð34ð 4ð< R`ð=4ð 4ðF ðG4ð 4ðH ðI4ð 4ðJ ðK4ð 4ð 4ˆDðn  "ŸzšzÝ•t‘”×"Ò"¥4¤9°Ò#7½¼È4Ò9OÑPÔPñ ô  ð ð ð ð ð ð ˆJð $×+Ò+Ñ-Ô-×1Ò1Ñ3Ô3ð Sð S�Ø”{ð ØðSÝ -¨mÑ <Ô <�IØ+OÈÐ+OÐ+O�I˜iÑ(Ý(0Ô(:�I˜fÑ%Ø&+¤k�I˜d‘OØ×$Ò$¥X¨d°FÑ%;Ô%;Ñ<Ô<Ð<Ý$œ/Ø!Ý!)Ô!3Ý%Ô/Ø %Ø"'ðñ ô ð ð ð ð ð ð ð õ ÐK¸e¼kÐKÐKÑLÔLÐLÐLøÝ ð Sð Sð SÝÐQ¸u¼{ÐQÐQÈaÐQÐQÑRÔRÐRÐRÐRÐRÐRÐRøøøøðSøøøð#Søõ( ð 	:ð 	:ð 	:ÝÐ8°QÐ8Ð8Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9øøøøð	:øøøðy]:ð ]:ð ]:ñ ]:ô ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:ð ]:øøøð ]:ð ]:ð ]:ð ]:ð ]:ð ]:sf   ¯\4±W6[8Ø(B[Û[8Û
[4Û[/Û*[8Û/[4Û4[8Û7\4Û8
\Ü\Ü\4Ü\Ü\4Ü4
\>Ý\>Úkeyr™   c              ƒ   ó&  K  — ddl m} t          j        ¦   «                              ¦   «         }t          ¦   «         4 ƒd{V —†}|                     || ¦  «        ƒ d{V —†}|duo
|j        |k    cddd¦  «        ƒd{V —† S # 1 ƒd{V —†swxY w Y   dS )zEReturn True if this check already ran today (dedup via app_settings).r   ©Ú
AppSettingN)Úapp.models.app_settingrÞ   r   rJ   Ú	isoformatr   rX   Úvalue©rÛ   rÞ   Ú	today_strr^   Úsettings        r4   Ú_already_ran_todayrå     sT  è è € à1Ð1Ð1Ð1Ð1Ð1Ý”
‘”×&Ò&Ñ(Ô(€IÝ Ñ"Ô"ð Bð Bð Bð Bð Bð Bð B bØŸš˜z¨3Ñ/Ô/Ð/Ð/Ð/Ð/Ð/Ð/ˆØ˜dÐ"ÐA w¤}¸	Ò'AðBð Bð Bð Bñ Bô Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bð Bøøøð Bð Bð Bð Bð Bð Bs   Á+B Â 
B
ÂB
r9   c              ƒ   ó²  K  — ddl m} t          j        ¦   «         }t	          ¦   «         4 ƒd{V —†}|                     || ¦  «        ƒ d{V —†}|r|j        s	 ddd¦  «        ƒd{V —† dS 	 t          j        |j        ¦  «        }||z
  j        |k     cddd¦  «        ƒd{V —† S # t          $ r Y ddd¦  «        ƒd{V —† dS w xY w# 1 ƒd{V —†swxY w Y   dS )zBReturn True if this check already ran within the last `days` days.r   rÝ   NF)
rß   rÞ   r   rJ   r   rX   rá   Úfromisoformatr9   Ú
ValueError)rÛ   r9   rÞ   rJ   r^   rä   Úlast_runs          r4   Ú_already_ran_within_daysrê     sö  è è € à1Ð1Ð1Ð1Ð1Ð1ÝŒJ‰LŒL€EÝ Ñ"Ô"ð ð ð ð ð ð ð  bØŸš˜z¨3Ñ/Ô/Ð/Ð/Ð/Ð/Ð/Ð/ˆØð 	˜gœmð 	Øðð ð ñ ô ð ð ð ð ð ð ð ð ð ð	ÝÔ)¨'¬-Ñ8Ô8ˆHØ˜HÑ$Ô*¨TÒ1ðð ð ð ñ ô ð ð ð ð ð ð ð ð øõ ð 	ð 	ð 	Øðð ð ñ ô ð ð ð ð ð ð ð ð ð ð	øøøðð ð ð ð ð ð ð ð ð øøøð ð ð ð ð ð s/   °'CÁ+&B$Â$
CÂ.CÃCÃCÃ
CÃCc              ƒ   ó’  K  — ddl m} t          j        ¦   «                              ¦   «         }t          ¦   «         4 ƒd{V —†}|                     || ¦  «        ƒ d{V —†}|r||_        n |                      || |¬¦  «        ¦  «         | 	                    ¦   «         ƒ d{V —† ddd¦  «        ƒd{V —† dS # 1 ƒd{V —†swxY w Y   dS )z!Record that this check ran today.r   rÝ   N)rÛ   rá   )
rß   rÞ   r   rJ   rà   r   rX   rá   rR   rZ   râ   s        r4   Ú_mark_ran_todayrì     sm  è è € à1Ð1Ð1Ð1Ð1Ð1Ý”
‘”×&Ò&Ñ(Ô(€IÝ Ñ"Ô"ð ð ð ð ð ð ð  bØŸš˜z¨3Ñ/Ô/Ð/Ð/Ð/Ð/Ð/Ð/ˆØð 	9Ø%ˆGŒMˆMà�FŠF�:�: #¨YÐ7Ñ7Ô7Ñ8Ô8Ð8Ø�iŠi‰kŒkÐÐÐÐÐÐÐðð ð ñ ô ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð øøøð ð ð ð ð ð s   ÁA!B6Â6
C ÃC c               ƒ   óà   K  — t          j        ¦   «         t          d¬¦  «        z   } |                      dddd¬¦  «        }| |k    r|t          d¬¦  «        z  }|| z
                       ¦   «         S )z4Return seconds to wait until next 08:00 WIB (UTC+7).é   )Úhoursé   r   )ÚhourÚminuteÚsecondÚmicrosecondrl   r8   )r   Úutcnowr   ÚreplaceÚtotal_seconds)Únow_wibÚtargets     r4   Ú_seconds_until_8am_wibrú   *  ss   è è € åŒoÑÔ¥)°!Ð"4Ñ"4Ô"4Ñ4€GØ�_Š_ !¨A°aÀQˆ_ÑGÔG€FØ�&ÒÐØ•) Ð#Ñ#Ô#Ñ#ˆØ�WÑ×+Ò+Ñ-Ô-Ð-rC   c               ƒ   ó„  K  — 	 t          ¦   «         ƒ d{V —†} t          d| dz  d›d�¦  «         t          j        | ¦  «        ƒ d{V —† t	          dd¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d¦  «        ƒ d{V —† n)# t          $ r}t          d	|› �¦  «         Y d}~nd}~ww xY wt          d
¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d
¦  «        ƒ d{V —† n)# t          $ r}t          d|› �¦  «         Y d}~nd}~ww xY wt          d¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d¦  «        ƒ d{V —† n)# t          $ r}t          d|› �¦  «         Y d}~nd}~ww xY wt          d¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d¦  «        ƒ d{V —† n)# t          $ r}t          d|› �¦  «         Y d}~nd}~ww xY wt          d¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d¦  «        ƒ d{V —† n)# t          $ r}t          d|› �¦  «         Y d}~nd}~ww xY wt          d¦  «        ƒ d{V —†sT	 t          ¦   «         ƒ d{V —† t          d¦  «        ƒ d{V —† n)# t          $ r}t          d|› �¦  «         Y d}~nd}~ww xY w�Œ¾)zDRun daily checks at 08:00 WIB. Dedup prevents double-run on restart.TNz[scheduler] sleeping i  z.1fzh until 08:00 WIBÚsched_contract_expiryé   z#[scheduler] contract expiry error: Úsched_recurringz#[scheduler] recurring tasks error: Úsched_overduer„   Úsched_due_tomorrowrŠ   Úsched_contracts_expiredr�   Úsched_daily_digestrÃ   )rú   r1   ÚasyncioÚsleeprê   rh   rì   r0   rå   r�   rˆ   rŒ   r‘   rÚ   )Úwaitr3   s     r4   Úrun_schedulerr  3  s©  è è € ð.>Ý+Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-ˆÝÐF d¨4¡iÐFÐFÐFÐFÑGÔGÐGÝŒm˜DÑ!Ô!Ð!Ð!Ð!Ð!Ð!Ð!Ð!õ .Ð.EÀqÑIÔIÐIÐIÐIÐIÐIÐIð 	AðAÝ+Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-Ý%Ð&=Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>øÝð Að Að AÝÐ?¸AÐ?Ð?Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@øøøøðAøøøõ (Ð(9Ñ:Ô:Ð:Ð:Ð:Ð:Ð:Ð:ð 	AðAÝ.Ñ0Ô0Ð0Ð0Ð0Ð0Ð0Ð0Ð0Ý%Ð&7Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8øÝð Að Að AÝÐ?¸AÐ?Ð?Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@øøøøðAøøøõ (¨Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8ð 	?ð?Ý)Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ý% oÑ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ð6øÝð ?ð ?ð ?ÝÐ=¸!Ð=Ð=Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>øøøøð?øøøõ (Ð(<Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=ð 	>ð>Ý(Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ý%Ð&:Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øÝð >ð >ð >ÝÐ<¸Ð<Ð<Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=øøøøð>øøøõ (Ð(AÑBÔBÐBÐBÐBÐBÐBÐBð 	CðCÝ3Ñ5Ô5Ð5Ð5Ð5Ð5Ð5Ð5Ð5Ý%Ð&?Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ð@øÝð Cð Cð CÝÐA¸aÐAÐAÑBÔBÐBÐBÐBÐBÐBÐBøøøøðCøøøõ (Ð(<Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=ð 	>ð>Ý'Ñ)Ô)Ð)Ð)Ð)Ð)Ð)Ð)Ð)Ý%Ð&:Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;Ð;Ð;øÝð >ð >ð >ÝÐ<¸Ð<Ð<Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=øøøøð>øøøñ[.>s�   Á )B
 Â

B0ÂB+Â+B0Ã	)C3 Ã3
DÃ=DÄDÄ2)E Å
FÅ&E=Å=FÆ)G Ç
G+ÇG&Ç&G+È)H. È.
IÈ8IÉIÉ-)J Ê
J=Ê!J8Ê8J=)5r  r,   r   r   r   Úemail.mime.multipartr   Úemail.mime.textr   Úsqlalchemy.ext.asyncior   Ú
sqlalchemyr	   r
   Úapp.databaser   Úapp.models.contractr   Úapp.models.recurring_taskr   Úapp.models.taskr   Úapp.models.leave_requestr   Úapp.models.notificationr   Úapp.models.userr   Ú
app.configr   Úapp.services.recurrencer   Úapp.services.notifierr   r   r   r   rÊ   Úintr5   rh   r�   rˆ   rŒ   r‘   rÚ   Úboolrå   rê   rì   Úfloatrú   r  r=   rC   r4   ú<module>r     s�  ðØ €€€Ø Ð Ð Ð Ø .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ð .Ø .Ð .Ð .Ð .Ð .Ð .Ø $Ð $Ð $Ð $Ð $Ð $Ø /Ð /Ð /Ð /Ð /Ð /Ø #Ð #Ð #Ð #Ð #Ð #Ð #Ð #Ø *Ð *Ð *Ð *Ð *Ð *Ø (Ð (Ð (Ð (Ð (Ð (Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ø  Ð  Ð  Ð  Ð  Ð  Ø 1Ð 1Ð 1Ð 1Ð 1Ð 1Ø 0Ð 0Ð 0Ð 0Ð 0Ð 0Ø  Ð  Ð  Ð  Ð  Ð  Ø Ð Ð Ð Ð Ð Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5Ø iÐ iÐ iÐ iÐ iÐ iÐ iÐ iÐ iÐ iÐ iÐ ið*= cð *=°Sð *=È#ð *=Ø(+ð*=Ø9=ð*=ØLOð*=ð *=ð *=ð *=ðZC:ð C:ð C:ðL=Fð =Fð =Fð@;ð ;ð ;ðB:ð :ð :ðB?ð ?ð ?ð2`:ð `:ð `:ðFB #ð B¨$ð Bð Bð Bð Bð¨ð °3ð ¸4ð ð ð ð ð
˜sð 
 tð 
ð 
ð 
ð 
ð. eð .ð .ð .ð .ð0>ð 0>ð 0>ð 0>ð 0>rC   