Ë
    éƒtjý*  ã                  ó&  — U d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	m
Z
mZ ddlmZmZmZ ddlmZmZ  ej&                  «       Zi Zd	ed
<   i Zded<   e
dz  dz  Zdd„Zdd„Zdd„Zd d„Zd!d„Zd"d„Zd#d„Zd$d„Z d%d„Z!d&d„Z"d'd„Z#ddœd(d„Z$y))zÂIn-memory PDF calculation jobs (confirm-before-calc).

By default user PDFs and extracted content are kept in process memory only
and are never written to disk (see Settings.persist_user_data).
é    )ÚannotationsN)ÚPath)ÚAny)ÚBASE_DIRÚget_settings)Ú	calculateÚformat_job_contextÚvalidate_rows)ÚExtractionResultÚextract_pdfzdict[str, dict[str, Any]]Ú_JOBSzdict[str, str]Ú_SESSION_JOBSÚdataÚpdf_uploadsc                 ó<   — t        t        «       j                  «      S ©N)Úboolr   Úpersist_user_data© ó    ú)/var/www/html/CA-Chatbot/app/pdf/store.pyÚ_persist_enabledr      s   € Ü”“×0Ñ0Ó1Ð1r   c                 ó<   — t         j                  dd¬«       t         S )NT)ÚparentsÚexist_ok)Ú_UPLOAD_DIRÚmkdirr   r   r   Ú_ensure_upload_dirr      s   € Ü×Ñ˜d¨TÐÔ2ÜÐr   c                óD  — g }| D ]˜  }t        |d«      rpt        |t        «      s`|j                  |j                  |j
                  |j                  |j                  |j                  |j                  |j                  dœ«       Œ|j                  t        |«      «       Œš |S )NÚ__dict__©ÚdescriptionÚdebitÚcreditÚamountÚdateÚaccountÚraw)ÚhasattrÚ
isinstanceÚdictÚappendr"   r#   r$   r%   r&   r'   r(   )ÚrowsÚoutÚrs      r   Ú_serialize_rowsr0   !   s   € Ø
€CÛˆÜ�1�jÔ!¬*°Q¼Ô*=Ø�J‰Jà#$§=¡=ØŸW™WØŸh™hØŸh™hØŸF™FØ Ÿy™yØŸ5™5ñõ
ð �J‰J”t˜A“wÕð ð €Jr   c           
     óô   — t        «       syt        «        t        | d   › d�z  }|j                  t	        j
                  | j                  «       D ��ci c]  \  }}|dk7  sŒ||“Œ c}}d¬«      «       yc c}}w )u5   Optional durable copy â€” off by default for privacy.NÚjob_idú.jsonÚ	file_pathé   )Úindent)r   r   r   Ú
write_textÚjsonÚdumpsÚitems)ÚjobÚ	meta_pathÚkÚvs       r   Ú_save_job_diskr?   5   si   € äÔØÜÔÜ  X¡ ¨uÐ5Ñ5€IØ×ÑÜ�
‰
 S§Y¡Y¤[ÔE¡[™T˜Q °A¸Ó4D�A�q‘D [ÒEÈaÔPõùÛEs   ÁA4Á A4c                óò  — t        | |¬«      }t        |dd «      xs d}t        t        |j                  «      |¬«      }||_        |j                  r|j                  d«      rd}d}d}nd}d}d	}d|_        d|_        i d
|j                  “d|j                  “d|j                  “d|“d|“d	|“dd“d|“dt        |j                  «      “d|j                  “d|j                  xs |j                  “d|j                  “d|“d|j                  “dt!        «       rt#        | «      nd “dd “dt        |dd «      xs i “}t$        5  |t&        |j                  <   d d d «       t)        |«       |S # 1 sw Y   ŒxY w)N)ÚfilenameÚdocument_kindÚunknown©rB   ÚokFTÚreadyÚneeds_confirmr2   rA   Úsource_typeÚtrustedÚ	confirmedÚstatusr-   Útext_previewÚdocument_textÚwarningsÚ
validationÚocr_usedr4   ÚcalculationÚstatement_totals)r   Úgetattrr
   r0   r-   rO   rI   ÚgetrG   r2   rA   rH   rL   rM   rN   rP   r   ÚstrÚ_LOCKr   r?   )	Ú
saved_pathrA   ÚresultÚkindrO   rG   rI   rK   r;   s	            r   Úcreate_job_from_uploadrZ   @   sÎ  € Ü*¨:ÀÔI€FÜ�6˜?¨DÓ1Ò>°Y€DÜœ¨v¯{©{Ó;È4ÔP€JØ"€FÔð ‡~‚~˜*Ÿ.™.¨Ô.ØˆØˆØ‰àˆØˆØ ˆØˆŒØ#ˆÔðØ�&—-‘-ðà�F—O‘Oðð 	�v×)Ñ)ðð 	˜ð	ð
 	�7ðð 	˜ðð 	�Uðð 	�&ðð 	” §¡Ó,ðð 	˜×+Ñ+ðð 	˜×-Ñ-ÒD°×1DÑ1Dðð 	�F—O‘Oðð 	�jðð 	�F—O‘Oðð 	Ô(8Ô(:”S˜”_Àðð  	�tð!ð" 	œG FÐ,>ÀÓEÒKÈð#€Cö( 
Ø"Œˆf�m‰mÑ÷ 
ô �3ÔØ€J÷	 
ˆús   ÅE-Å-E6c                óN  — t         5  t        j                  | «      }d d d «       r|S t        «       sy t        | › d�z  }|j                  «       r=t        j                  |j                  «       «      }t         5  |t        | <   d d d «       |S y # 1 sw Y   ŒrxY w# 1 sw Y   |S xY w)Nr3   )	rV   r   rT   r   r   Úexistsr8   ÚloadsÚ	read_text)r2   r;   r<   r   s       r   Úget_jobr_   m   s‰   € Þ	Ü�i‰i˜Óˆ÷ 
á
Øˆ
ÜÔØÜ  ¨Ð.Ñ.€IØ×ÑÔÜ�z‰z˜)×-Ñ-Ó/Ó0ˆÞØ ŒE�&‰M÷ àˆØ÷ 
ˆú÷ àˆús   ‡BÁ9
BÂBÂB$c                óT  — t        | «      }|st        d«      ‚g }|D ]£  }|j                  t        |j	                  d«      xs d«      j                  «       |j	                  d«      |j	                  d«      |j	                  d«      |j	                  d«      |j	                  d«      |j	                  d	«      xs dd
œ«       Œ¥ t        ||j	                  d«      xs d¬«      }||d<   ||d<   d|d<   d|d<   t        |j	                  d«      «      |d<   |j	                  d«      rdnd|d<   t        |j	                  d«      xs g «      |d<   |j	                  d«      s|d   |j	                  dg «      z   |d<   t        5  |t        | <   d d d «       t        |«       |S # 1 sw Y   ŒxY w)NúJob not foundr"   Ú r#   r$   r%   r&   r'   r(   r!   rB   rC   rD   r-   rO   TrJ   FrG   rE   rI   ÚinvalidrK   rN   Úissues)r_   ÚKeyErrorr,   rU   rT   Ústripr
   r   ÚlistrV   r   r?   )r2   r-   r;   Úcleanedr/   rO   s         r   Úconfirm_jobri   }   s|  € Ü
�&‹/€CÙÜ�Ó'Ð'à€GÛˆØ�‰ä" 1§5¡5¨Ó#7Ò#=¸2Ó>×DÑDÓFØŸ™˜w›ØŸ%™% ›/ØŸ%™% ›/ØŸ™˜f›ØŸ5™5 Ó+Ø—u‘u˜U“|Ò) rñõ
	
ð ô ˜w°c·g±g¸oÓ6NÒ6[ÐR[Ô\€JØ€Cˆ�KØ"€CˆÑØ€CˆÑØ €CˆÑÜ˜*Ÿ.™.¨Ó.Ó/€Cˆ	�NØ#-§>¡>°$Ô#7‘K¸Y€Cˆ�MÜ˜3Ÿ7™7 :Ó.Ò4°"Ó5€Cˆ
�OØ�>‰>˜$ÔØ˜j™/¨J¯N©N¸8ÀRÓ,HÑHˆˆJ‰æ	ØŒˆf‰÷ 
ä�3ÔØ€J÷ 
ˆús   Å?
FÆF'c                ó¶   — | sy t         5  t        j                  | «      }|t        | <   |r||k7  rt        j	                  |d «       d d d «       y # 1 sw Y   y xY wr   )rV   r   rT   r   Úpop)Ú
session_idr2   Úprevs      r   Úattach_job_to_sessionrn   ¡   sF   € ÙØÞ	ä× Ñ  Ó,ˆØ$*Œ�jÑ!Ù�D˜F’NÜ�I‰I�d˜DÔ!÷ 
�‰ús   Š<AÁAc                ó„   — | sy t         5  t        j                  | «      }d d d «       sy t        |«      S # 1 sw Y   ŒxY wr   )rV   r   rT   r_   )rl   r2   s     r   Úget_session_jobrp   ¬   s8   € ÙØÞ	Ü×"Ñ" :Ó.ˆ÷ 
áØÜ�6‹?Ð÷	 
ˆús   Š6¶?c                óØ   — | sy t         5  t        j                  | d «      }|rt        j                  |d «       d d d «       	 ddlm}  || «       y # 1 sw Y   ŒxY w# t        $ r Y y w xY w)Nr   )Úclear_session_history)rV   r   rk   r   Úapp.rag.chainrr   Ú	Exception)rl   r2   rr   s      r   Úclear_session_jobru   ¶   s^   € ÙØÞ	Ü×"Ñ" :¨tÓ4ˆÙÜ�I‰I�f˜dÔ#÷ 
ð
Ý7á˜jÕ)÷ 
ˆûô ò Ùðús   Š/AÁA ÁAÁ	A)Á(A)c           
     óî  — t        | |«      }|j                  d«      xs g }|s>|j                  d«      s-|j                  d«      sd|› d�|d<   |rt        ||d   «       |S |j                  d«      xs i }|j                  d	«      €|j                  d«      �°|j                  d«      xs d}|dk(  rd}||d<   	 |rt        |d   |«      }t	        |d   «      }nMd|d<   d|d<   d|d<   ddlm}  ||g ¬«      |d<   d|d<   t        5  |t        |d   <   d
d
d
«       t        |«       |rt        ||d   «       t        |«      |d<   |S |rt        |d   |«      }	 t	        |d   «      }|rt        ||d   «       t        |«      |d<   |S # 1 sw Y   ŒvxY w# t        $ rT}t        t        j                  t        |j                  d«      xs g «      t        |«      gz   «      «      |d<   Y d
}~ŒÆd
}~ww xY w# t        $ ru}t        t        j                  t        |j                  d«      xs g «      t        |«      gz   «      «      |d<   |rt        ||d   «       t        |«      |d<   |cY d
}~S d
}~ww xY w)uN   Extract â†’ auto-confirm â†’ calculate â†’ bind to chat session (memory only).r-   rM   rL   u&   Could not read usable content from â€œu   â€�.Úerrorr2   rR   Ú	money_outNÚmoney_inrB   Úbank_statementrC   TrJ   FrG   rI   r   )Úcalculate_from_statement_totals)r-   rQ   Ú
calculatedrK   rN   Úcontext_block)rZ   rT   rn   ri   Úcalculate_jobÚapp.pdf.calcr{   rV   r   r?   rt   rg   r+   ÚfromkeysrU   r	   )	rW   rA   rl   r;   r-   ÚheaderrY   r{   Úexcs	            r   Úingest_pdf_for_chatrƒ   Æ   sv  € ä
  ¨XÓ
6€CØ�7‰7�6‹?Ò ˜b€DÙ˜Ÿ™ Ô1°S·W±W¸^Ô5LØ?À¸zÈÐNˆˆG‰ÙÜ! *¨c°(©mÔ<Øˆ
ð �W‰WÐ'Ó(Ò.¨B€FØ‡z�z�+ÓÐ*¨f¯j©j¸Ó.DÐ.PØ�w‰w�Ó'Ò;Ð+;ˆØ�9ÒØ#ˆDØ#'ˆC�Ñ ð	`ÙÜ! # h¡-°Ó6�Ü# C¨¡MÓ2‘à#'��KÑ Ø',��OÑ$Ø!%��I‘ÝHá%DÀVÐRTÔ%U��MÑ"Ø ,��H‘ÞØ+.”E˜#˜h™-Ñ(÷ ä˜sÔ#ñ Ü! *¨c°(©mÔ<Ü1°#Ó6ˆˆOÑØˆ
áÜ˜#˜h™-¨Ó.ˆð	Ü  H¡Ó.ˆCñ Ü˜j¨#¨h©-Ô8ä-¨cÓ2€CˆÑØ€J÷3 �Uûô ò 	`Ü"¤4§=¡=´°c·g±g¸jÓ6IÒ6OÈRÓ1PÔTWÐX[ÓT\ÐS]Ñ1]Ó#^Ó_ˆC�
ŽOûð	`ûô ò 	Ü"¤4§=¡=´°c·g±g¸jÓ6IÒ6OÈRÓ1PÔTWÐX[ÓT\ÐS]Ñ1]Ó#^Ó_ˆC�
‰OÙÜ% j°#°h±-Ô@Ü#5°cÓ#:ˆC�Ñ Ø�Jûð	úsQ   Â;AF ÄF
ÄF ÅG6 Æ
FÆF Æ	G3ÆA
G.Ç.G3Ç6	I4Ç?A*I/É)I4É/I4T)Úallow_unbalancedc          	     ó  — t        | «      }|st        d«      ‚|j                  d«      s"|j                  d«      s|j                  d«      s|j                  d«      st        d«      ‚|j                  d«      xs g }|j                  d«      xs d	}|j                  d
«      xs i }|s-|j                  d«      €|j                  d«      €t	        d«      ‚|rt        ||¬«      n	dg dddd |dœ}||d<   |j                  d«      xs g D �cg c]  }d|j                  «       v sŒ|‘Œ }}|rt	        ddj                  |«      z   «      ‚|j                  d
«      xs i j                  d«      s\ddlm	}	  |	|j                  d«      xs |j                  d«      xs d«      }
|
r&|
|d
<   |
}|j                  d«      xs d	d	k(  rd|d<   d}t        |||xs d ¬«      }|dk7  r |j                  d«      du r�d|d<   d|d <   |j                  d«      xs g }|j                  d!d«      d"z   dj                  |«      z   d#z   |d!<   t        t        j                  t        |j                  d$«      xs g «      |z   «      «      |d$<   nH|dk7  rC|j                  d«      s2|s0t	        ddj                  |j                  d«      xs g «      z   «      ‚||d%<   ||d<   d&|d'<   t        5  |t        | <   d d d «       t!        |«       |S c c}w # 1 sw Y   ŒxY w)(Nra   rP   rG   rI   rJ   uZ   Confirm extracted amounts before calculating. Click â€œConfirm amountsâ€�, then Calculate.r-   rB   rC   rR   rx   ry   z6No line items to calculate. Add or confirm rows first.rD   Tr   )rE   rd   Ú	row_countÚdebit_totalÚcredit_totalÚbalancedrB   rO   rd   zno numeric amountzValidation failed: z; )Úparse_statement_header_totalsrM   rL   rb   rz   )rB   rR   r‰   FrE   Ú
imbalancedÚsummaryz/ | WARNING: debits and credits do not balance (Ú)rN   rQ   r|   rK   )r_   re   rT   ÚPermissionErrorÚ
ValueErrorr
   ÚlowerÚjoinÚapp.pdf.extractrŠ   r   rg   r+   r€   rV   r   r?   )r2   r„   r;   r-   rY   r�   rO   ÚiÚhard_issuesrŠ   ÚparsedrX   rd   s                r   r~   r~   ÿ   s  € Ü
�&‹/€CÙÜ�Ó'Ð'à
‡w�wˆzÔ˜cŸg™g oÔ6¸c¿g¹gÀiÔ>PØ�w‰w�{Ô#Ü!ð?óð ð
 �7‰7�6‹?Ò ˜b€DØ�7‰7�?Ó#Ò0 y€DØ�W‰WÐ'Ó(Ò.¨B€FÙØ�
‰
�;ÓÐ+¨v¯z©z¸*Ó/EÐ/QäÐQÓRÐRá<@”˜t°4Õ8ØØØØØØØñG€Jð #€CˆÑà)Ÿ~™~¨hÓ7Ò=¸2Ð=ÓcÑ=˜ÐBUÐYZ×Y`ÑY`ÓYbÒBb’1Ð=€KÐcÙÜÐ.°·±¸;Ó1GÑGÓHÐHð �G‰GÐ&Ó'Ò-¨2×2Ñ2°;Ô?ÝAá.Ø�G‰G�OÓ$ÒE¨¯©°Ó(?ÒEÀ2ó
ˆñ Ø&,ˆCÐ"Ñ#ØˆFØ—‘˜Ó(Ò5¨I¸)ÒCØ'7��OÑ$Ø'�ä�t¨4À&Â.ÈDÔQ€FØÐÒ J§N¡N°:Ó$>À%Ñ$GØˆˆt‰Ø#ˆˆ|ÑØ—‘ Ó)Ò/¨Rˆà�J‰J�y "Ó%Ø?ñ@à�i‰i˜Óñ ð ñð 	ˆyÑô œtŸ}™}¬T°#·'±'¸*Ó2EÒ2KÈÓ-LÈvÑ-UÓVÓWˆˆJŠØ	Ð!Ò	!¨*¯.©.¸Ô*>ÑGWÜÐ.°·±¸:¿>¹>È(Ó;SÒ;YÐWYÓ1ZÑZÓ[Ð[à€CˆÑØ€CˆÑØ €Cˆ�MÞ	ØŒˆf‰÷ 
ä�3ÔØ€JùòO d÷H 
ˆús   ÄK;Ä#K;Ë
L Ì L	)Úreturnr   )r–   r   )r-   z	list[Any]r–   úlist[dict[str, Any]])r;   údict[str, Any]r–   ÚNone)rW   r   rA   rU   r–   r˜   )r2   rU   r–   údict[str, Any] | None)r2   rU   r-   r—   r–   r˜   )rl   rU   r2   rU   r–   r™   )rl   ú
str | Noner–   rš   )rl   r›   r–   r™   )rW   r   rA   rU   rl   r›   r–   r˜   )r2   rU   r„   r   r–   r˜   )%Ú__doc__Ú
__future__r   r8   Ú	threadingÚpathlibr   Útypingr   Ú
app.configr   r   r   r   r	   r
   r’   r   r   ÚLockrV   r   Ú__annotations__r   r   r   r   r0   r?   rZ   r_   ri   rn   rp   ru   rƒ   r~   r   r   r   Ú<module>r¤      sŸ   ðòõ #ã Û Ý Ý ç -ß EÑ Eß 9àˆ	�‰Ó€Ø#%€Ð Ó %Ø "€ˆ~Ó "Ø˜Ñ -Ñ/€ó2óó
ó(ó*óZó !óH"óóó 6ðr <@ö Fr   