+
    -^ej*                         R t ^ RIt^ RIHt ^ RIHt ^ RIHt ^ RIH	t	 ^ RI
HtHt ^ RIHtHt ]P                   ! ]4      tRtR	tRR
 R lltR R ltR R ltRR R lltR# )u  Envio dos avisos de insolvência.

Separado do sweep de propósito: o sweep grava os hits e segue; o envio corre
depois, sobre os hits por notificar. Assim um SMTP em baixo nunca faz perder
anúncios, e um reenvio é só voltar a correr isto.

Destinatários vêm de `alerts_config` com `kind='insolvency'` — configuráveis nas
Definições, com `geral@segunor.pt` semeado por defeito.
N)date)Any)text)AsyncSession)send_email_rawsend_webhook_alert)mark_notifiedpending_notificationsuE   [Intel Grid] Insolvência: {nome} — reclamar créditos até {prazo}uT  {nome} (NIF {nif}) foi declarada insolvente.

O prazo para reclamar créditos termina a {prazo}{estimado}.
Faltam {dias} dias.

Processo:      {processo}
Tribunal:      {tribunal}
{sentenca}
Administrador de insolvência (é a quem se reclama o crédito):
  {admin}
  {admin_email}

{publicacoes}
Detalhe em http://10.0.30.108/insolvencies
c          	      t    V ^8  d   QhR\         R\        R\        \        \        \        3,          ,          /# )   sessionkindreturn)r   strlistdictr   )formats   "!app/services/insolvency_alerts.py__annotate__r   )   s1     # #| #3 #$tTWY\T\~J^ #    c                    "   V P                  \        R 4      RV/4      G Rj  xL
 P                  4       P                  4       pV Uu. uF  p\	        V4      NK  	  up#  L;u upi 5i)z
                SELECT id::text, type, target FROM alerts_config
                WHERE enabled = TRUE AND kind = :kind
                r   N)executer   mappingsallr   )r   r   rowsrs   &&  r   _recipientsr   )   se     oo TN
 	
 hj 	 ""TDGT""	
 #s!   !A&A$A&A!A&!A&c                t    V ^8  d   QhR\         \        \        3,          R\        \        \        3,          /# )r   hitr   )r   r   r   tuple)r   s   "r   r   r   8   s.     R RDcN RuS#X Rr   c                 |    V P                  R 4      ;'       g    RV P                  R4      ;'       g
    V R,          3# )matched_nif process_numberidget)r   s   &r   
_group_keyr'   8   s4    GGM"((b#''2B*C*P*Ps4yQQr   c                    V ^8  d   QhR\         \        \        \        3,          ,          R\        \        \        3,          /# )r   groupr   )r   r   r   r   r   )r   s   "r   r   r   <   s/     6= 6=4S#X' 6=E#s(O 6=r   c                v   V  Uu. uF  qP                  R4      '       g   K  VNK  	  ppV'       d   \        VR R7      MV ^ ,          pVP                  R4      pV'       d'   V\        P                  ! 4       ,
          P                  MRpVP                  R4      '       d   RMRpVP                  R4      '       d   R	VR,           R
2MRp\        R V  4       R4      p\        R V  4       R4      p	R.p
\        V R R7       F  pVP                  R4      '       d   VR,          P                  4       MRpV
P                  RVP                  R4       RVP                  R4       RV 24       VP                  R4      '       g   K  V
P                  RVR,           R24       K  	  \        V 4      ^8  d   V
P                  R4       RVP                  R4      ;'       g    VP                  R4      RVP                  R4      RV'       d   VP                  4       MRR TR!TR"VP                  R#4      ;'       g    R$R%VP                  R%4      ;'       g    R$R&TR'T;'       g    R(R)T	;'       g    R*R+R
P                  V
4      R
,           /p\        P                  ! R,/ VB \        P                  ! R,/ VB 3# u upi )-u  Um email por (entidade, processo), não por publicação.

A mesma insolvência costuma render duas publicações — a sentença e o anúncio
— e os prazos calculados diferem, porque só uma delas menciona os éditos.
Mandar dois emails com datas diferentes sobre o mesmo processo é pior do que
não mandar nenhum: quem lê fica sem saber qual vale. Mostramos **a data mais
curta** como a que conta, e listamos as publicações por trás para a decisão
poder ser confirmada na fonte.
claim_deadlinec                     V R ,          # r+    )hs   &r   <lambda>_format.<locals>.<lambda>G   s
    A.>,?r   )key?claim_deadline_estimatedud    (estimado — o documento não indicava o prazo, usou-se o supletivo de 30 dias do art. 128º CIRE)r"   insolvency_dateu   Sentença:      
c              3   d   "   T F&  qP                  R 4      '       g   K  VR ,          x  K(  	  R# 5i)
admin_nameNr%   .0r/   s   & r   	<genexpr>_format.<locals>.<genexpr>V   s!     H5aEE,4G/!L//5   00Nc              3   d   "   T F&  qP                  R 4      '       g   K  VR ,          x  K(  	  R# 5i)admin_emailNr%   r9   s   & r   r;   r<   W   s$     P%Q55;O(-((%r=   u)   Publicações que fundamentam este prazo:c                 T    V P                  R 4      ;'       g    \        P                  # r-   )r&   r   max)xs   &r   r0   r1   Z   s    !%%0@*A*M*MTXX*Mr   z	sem prazoz  - pub_dateu    · atoz -> claim_days_sourcez      ""u_     (datas diferentes porque só uma das publicações refere os éditos; assume-se a mais curta)nomematched_namer!   nifprazozpor determinarestimadodiasprocessor#   u   —tribunalsentencaadminu%   (não identificado nas publicações)r?   u%   (as publicações não indicam email)publicacoesr.   )r&   minr   todaydaysnextsorted	isoformatappendlenjoinSUBJECTr   BODY)r)   r/   with_deadlineleaddeadlinerL   rK   rO   rP   r?   linhasprazo_hpayloads   &            r   _formatrc   <   sv    !&A1/?)@QQMADQ3}"?@W\]^W_Dxx()H-5Htzz|#))3D 88.//	' 	  ;?((CT:U:U
4 12326[] 
 H5H$OEP%PRVWK9:FENO56UU;K5L5L!$%//1R]QUU:./tAEE%L>gYOP55$%%MMHQ':%;$<B?@	 P
 5zA~'	
 	(CCDHH],Ctxx&##%7GHDHH-.77%DHHZ(11EHAAA{MM&Mtyy(4/G >>$G$dkk&<G&<<<Y Bs
   J6J6c                <    V ^8  d   QhR\         R\        R\        /# )r   r   limitr   )r   int)r   s   "r   r   r   u   s!     9 9L 9 9s 9r   c                  "   \        V 4      G Rj  xL
 p\        WR7      G Rj  xL
 pV'       g   ^ # V'       g"   \        P                  R\	        V4      4       ^ # / pV F-  pVP                  \        V4      . 4      P                  V4       K/  	  ^ pVP                  4        EF+  p\        V4      w  rRp
V F  pVR,          R8X  d   \        VR,          W4      G Rj  xL
 w  rM;VR,          R8X  d!   \        VR,          R	V/4      G Rj  xL
 w  rMRR
VR,           2rT
;'       g    Tp
 T P                  \        R4      RV^ ,          R,          RVR,          RV'       d   RMRRT;'       g    RR,          ;'       g    R/4      G Rj  xL
  K  	  V
'       g   K  V F  p\        WR,          4      G Rj  xL
  K  	  V^,          pEK.  	  V P!                  4       G Rj  xL
  \        P#                  RV\	        V4      4       V#  EL EL EL4 EL	 L  \         d#   p\        P                  RT4        Rp?EK  Rp?ii ; i L Lf5i)zCEnvia os avisos por enviar. Devolve quantos hits foram notificados.N)re   uI   %d hits de insolvência por notificar mas não há destinatários activosFtypeemailtargetwebhookhitsztipo desconhecido z
                        INSERT INTO alerts_log (announcement_id, alert_config_id, status, response)
                        VALUES (CAST(:aid AS UUID), CAST(:cid AS UUID), :st, :resp)
                        aidannouncement_idcidr$   stsentfailedrespr"   :Ni  Nzalerts_log insert falhou: %su?   avisos de insolvência: %d avisos entregues (%d hits agrupados))r   r	   loggerwarningrY   
setdefaultr'   rX   valuesrc   r   r   r   r   	Exceptionr   commitinfo)r   re   configsrl   groupsr   rq   r)   subjectbody	deliveredcfgokrs   es   &&             r   dispatch_pendingr   u   s    ((G&w<<DWY\]aYb	
 :<F*S/2.55c:  D	C6{g%!/Hw!MMDV	)!3CMFE?!SSD $6s6{m"DD!RIBoo uQx(9:s4yfU 3 ; ;t	   8 9#GY777 AIDE !H ..

KKI4QTUYQZ Ko )<& NS
  B=qAAB 8 s   IHIHI	IB$I H!-IHI,I0AH4HHHH	I#I=I>)I'I('IIIIHI	'I=II		II)
insolvency)d   )__doc__loggingdatetimer   typingr   
sqlalchemyr   sqlalchemy.ext.asyncior   app.services.alertsr   r    app.services.insolvency_matchingr   r	   	getLogger__name__rt   r[   r\   r   r'   rc   r   r.   r   r   <module>r      sX        / B Q			8	$
Q"#R6=r9 9r   