
    .5j~T                    ,   % S r SSKJr  SSKrSSKrSSKrSSKJr  SSKJ	r	  SSK
Jr  \R                  " \5      r\" 1 Sk5      rS\S	'   \R$                  " S
5      r0 SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_S S!_S"S#_S$S%_S&S_S'S_S(S_S!S#S)S*S+.ErS,\S-'   SJS. jrSKS/ jrSLS0 jrSMS1 jrSNS2 jrSOS3 jrSPS4 jrSQS5 jrSRS6 jrSSS7 jr          STS8 jrSUS9 jr           SVS: jr!SS;.         SWS< jjr"SXS= jr#SYS> jr$SZS? jr%          S[S@ jr& S\       S]SA jjr' S\       S]SB jjr(      S^SC jr)SS;.       S_SD jjr* S\       S`SE jjr+        SaSF jr,        SbSG jr-        SbSH jr.ScSI jr/g)dub   Relleno de identificación en informe familia vía placeholders {{clave}} sin romper la plantilla.    )annotationsN)deepcopy)Path)Any>   student_ageperson_emailperson_phonestudent_coursestudent_schoolperson_presenceperson_full_namestudent_born_datestudent_full_nameprofessional_emailprofessional_phonestudent_birth_datestudent_social_namereceiver_social_nameprofessional_full_nameperson_relation_studentprofessional_phone_emailprofessional_social_nameprofessional_job_positionperson_identification_numberstudent_identification_number"professional_delivered_date_inform"professional_identification_numberzfrozenset[str]FAMILIA_IDENTIFICATION_KEYSzQ\{\{\s*([a-zA-Z0-9_]+)\s*\}\}|\{\s*([a-zA-Z0-9_]+)\s*\}|\[\s*([a-zA-Z0-9_]+)\s*\]r   )nombre de identidadnombres y apellidosznombre completor   )runrutidentificacionr   )nombre socialr   )fecha nacimientofecha de nacimientor   )edadr
   )zcurso / nivelzcurso nivelr   )establecimientor   )r   r    r   )r!   r"   r   r   )rolcargofuncionr   )telefonou	   teléfonofonor   )correoe mailemailr   )fecha entregazfecha de entregar   r   r   )vinculou   vínculo
parentescorelacion)	presencia)r	   r   r   r   zdict[str, tuple[str, ...]]_IDENTIFICATION_LABEL_HINTSc                    [         R                  " SU =(       d    S5      nSR                  S U 5       5      n[        R                  " SSUR                  5       5      R                  5       $ )NNFKD c              3  `   #    U  H$  n[         R                  " U5      (       a  M   Uv   M&     g 7fN)unicodedata	combining).0chs     bC:\Users\jesus\Desktop\proyecto_pie360\backend\app\backend\utils\agent_familia_placeholder_fill.py	<genexpr>#_normalize_label.<locals>.<genexpr>K   s     LFb+2G2G2KrrFs   .	.z
[^a-z0-9]+ )r<   	normalizejoinresublowerstrip)textfoldedasciiishs      r@   _normalize_labelrM   I   sO    ""64:26FwwLFLLH66-hnn&67==??    c                    [        U 5      nU(       a  [        U5      S:  a  g[        R                  US5       H%  nX#:X  d  UR	                  U5      (       d  X2;   d  M%    g   g)NP   F T)rM   lenr6   getendswith)rJ   keynormhints       r@   _paragraph_matches_labelrX   O   sR    D!D3t9r>+//R8<4==..$, 9 rN   c                $    SU  S3SU  S3SU  S34$ )N{{z}}{}[]rQ   )tags    r@   _formats_for_tagr`   Y   s(    3%t3%rlauAJ77rN   c                    [        5       n[        R                  U =(       d    S5       Ha  nUR                  S5      =(       d)    UR                  S5      =(       d    UR                  S5      nU[        ;   d  MP  UR                  U5        Mc     U$ )Nr9            )set_PLACEHOLDER_REfinditergroupr   add)rJ   foundmrU   s       r@   _keys_in_textrl   ]   sd    eE%%djb1ggaj4AGGAJ4!''!*--IIcN 2 LrN   c                \    SR                  S U R                  U" S5      5       5       5      $ )Nr9   c              3  J   #    U  H  oR                   =(       d    S v   M     g7f)r9   NrJ   )r>   ts     r@   rA   *_paragraph_visible_text.<locals>.<genexpr>g   s     >)=A66<R<)=s   !#w:t)rE   iter)p_elqns     r@   _paragraph_visible_textrv   f   s$    77>2e9)=>>>rN   c              #    #    U R                   R                  R                  U" S5      5       H  nUv   M	     U R                   Hv  nUR                  UR
                  UR                  UR                  4 HA  nUb  UR                  c  M  UR                  R                  U" S5      5       H  nUv   M	     MC     Mx     g 7fNw:p)	elementbodyrs   sectionsheaderfooterfirst_page_headerfirst_page_footer_element)docru   rt   sectionhfs        r@   _iter_body_paragraphsr   j   s       %%bi0
 1<<NNNN%%%%	
B zR[[0((E3
 4
  s   B>C c                x    SSK Jn  [        5       n[        X5       H  nU[	        [        X15      5      -  nM     U$ )uR   Claves {{...}} presentes (aunque Word las parta en varios w:t del mismo párrafo).r   ru   )docx.oxml.nsru   re   r   rl   rv   )r   ru   keysrt   s       r@   $list_familia_placeholder_keys_in_docr   z   s5    UD%c.5d?@@ /KrN   c                |     SSK Jn  U" [        U 5      5      n[        U5      $ ! [         a    [        5       s $ f = f)Nr   Document)docxr   strr   	Exceptionre   )pathr   r   s      r@   %list_familia_placeholder_keys_in_pathr      s9    !s4y!3C88 us   !$ ;;c                *    [        [        U 5      5      $ r;   )boolr   )r   s    r@   docx_has_familia_placeholdersr      s    5d;<<rN   c                    U nUR                  5        H8  u  p4Ub  [        U5      OSn[        U5       H  nUR                  Xe5      nM     M:     U$ )Nr9   )itemsr   r`   replace)rJ   replacementsresultr_   valuevalfmts          r@   _replace_text_placeholdersr      sP    F"((*
!-c%j2#C(C^^C-F ) + MrN   c                   [        X5      nU(       a  SU;  a  SU;  a  SU;  a  / $ [        U5      nU(       d  / $ U Vs0 s H  ofU;   d  M
  XcU   _M     nnU(       d  / $ [        XG5      nX:X  a  / $ Sn	U R                  U" S5      5       H*  n
U
R	                  U" S5      5      nUc  M  [        U5      n	  O   [        U 5       H,  nUR                  U" S5      :X  d  M  U R                  U5        M.     U" S5      n
U	b  U
R                  [        U	5      5        U" S5      nXl
        UR                  S5      (       d  UR                  S5      (       a  UR                  U" S	5      S
5        U
R                  U5        U R                  U
5        / nU H/  n[        U5       H  nUU;   d  M  UR                  U5          M-     M1     U$ s  snf )uG   Reemplaza placeholders en un w:p aunque estén partidos en varios runs.rZ   r[   r]   Nw:rw:rPrrr   rC   	xml:spacepreserve)rv   rl   r   findallfindr   listr_   removeappendrJ   
startswithrT   re   r`   )rt   ru   OxmlElementr   full	keys_herek
applicablenew_fullref_r_prrrprchildwtfilledr_   r   s                    r@   "_replace_placeholders_in_paragraphr      s    #4,D4t#4CtO	d#I	.7Mi;L$!!_$iJM	)$;H	H\\"U)$ffR[!?}H	 % d995	!KK  	EA	(#$	U	BG38#4#4S#9#9
r+
+HHRLKKNF#C(Cd{c" ) 
 MG Ns   	G	Gc              #    #    U H}  nU[        U R                  5      :  a  M  U R                  U   R                   HB  nUR                   H/  nUR                  R                  U" S5      5       H  nUv   M	     M1     MD     M     g 7frx   )rR   tablesrowscellsr   r   )r   table_indicesru   	table_idxrowcellrt   s          r@   _iter_table_paragraphsr      sk     "	CJJ'::i(--C		 MM11"U)<DJ = " . #s   BBc                :   S nU R                  U" S5      5       H*  nUR                  U" S5      5      nUc  M  [        U5      n  O   [        U 5       H,  nUR                  U" S5      :X  d  M  U R                  U5        M.     U" S5      nUb  UR                  [        U5      5        U" S5      nXl        UR                  S5      (       d  UR                  S5      (       a  UR                  U" S5      S5        UR                  U5        U R                  U5        g )Nr   r   rr   rC   r   r   )r   r   r   r   r_   r   r   rJ   r   rT   re   )	rt   r   ru   r   r   r   r   r   r   s	            r@   _set_paragraph_plain_textr      s     H\\"U)$ffR[!?}H	 %
 d995	!KK  	EA	(#$	U	BGs 3 3
r+
+HHRLKKNrN   keys_filterc          	        SSK Jn  SSKJn  UnUb+  UR	                  5        VVs0 s H  u  pxXs;   d  M  Xx_M     nnn/ n	[        XU5       H  n
U	R                  [        XXF5      5        M      [        [        U	5      5      $ s  snnf )u?   Sustituye {{clave}} solo en tablas indicadas (identificación).r   r   r   )
	docx.oxmlr   r   ru   r   r   extendr   sortedre   )r   r   r   r   r   ru   filteredr   vr   rt   s              r@   "replace_placeholders_in_doc_tablesr      s     &H%1%7%7%9N%9TQQ=MDAD%9NF&s2>.tO	
 ? #f+ Os
   BBc                >   U S:X  aZ  SU;   a  gSU;   d  SU;   a  gSU;   a  gS	U;   d  S
U;   a  gUS:X  d  UR                  S5      (       a  gSU;   a  SU;   a  gSU;   a  ggU S:X  a  US:  nSU;   a  U(       a  S$ S$ SU;   d  SU;   d  SU;   a  U(       a  S$ S$ SU;   a  U(       a  S$ S$ SU;   d  SU;   a  g S!U;   d  UR                  S"5      (       a  U(       a  S#$ S$$ S%U;   d  S&U;   d  S'U;   a  U(       a  US(:  a  g)U(       d  S*$ S)$ S+U;   a  g,S-U;   d  S.U;   a  g/g)0u2   Mapea etiqueta ministerial → clave de reemplazo.rb   r   r   r"   iper   r$   r   r%   r&   r   r'   zedad r   cursonivelr
   r(   r   Nrc      r   r   	pasaporter   r   r   r   r)   r*   r   r,   telr	   r   r/   r0   r.      r   r   r1   r   r4   relacir   )r   )r   label_row_idx
label_normreceivers       r@   _key_for_ministerial_labelr     sx   A~ J.&J%:"52j((+/D
/R':#8#8#A#A j W
%:#
*#A~ A% J.)1%O7OOJ+";u
?R  / :
 j(-5)U;UUJ'Z"7.#z'<'<U'C'C%->G3GGz!W
%:h*>TMR/%/7'K^Kj(7#x:'=,rN   c                    U S:X  a  USSSSSSSS.R                  X5      :H  $ U S:X  a"  USSSSSSSSSSSSSS.R                  X5      :H  $ US:H  $ )zOSolo la columna izquierda de cada bloque (evita duplicar en celdas fusionadas).rb   r   rd   rc   )r   r   r   r   r   r
   r      )r   r   r   r   r   r   r   r   r   r   r	   r   r   )rS   )r   rU   col_idxs      r@   _primary_col_for_labelr   9  s    A~!"-.#$"#
 #c
 	 A~&'23())*"#"#23 !,-$%'(
 #c
 	 a<rN   c                X    [        SR                  S U R                   5       5      5      $ )NrC   c              3  8   #    U  H  oR                   v   M     g 7fr;   ro   )r>   ps     r@   rA   #_cell_label_text.<locals>.<genexpr>Y  s     $E_VV_s   )rM   rE   
paragraphs)r   s    r@   _cell_label_textr   X  s     CHH$ET__$EEFFrN   c                *   U R                   nUR                  U" S5      5      nU(       d  U" S5      nUR                  U5        U/n[        US   XU5        USS  H4  n[	        Xr5      R                  5       (       a  M#  UR                  U5        M6     g)uL   Escribe el valor en la fila superior (primer párrafo), sin tocar etiquetas.ry   r   rb   N)r   r   r   r   rv   rI   r   )r   r   ru   r   tc_elr   rt   extras           r@   _set_value_cellr   \  s     MMEr%y)J5!TV
jmUDAB&u17799LL  rN   c           	     (   SSK Jn  SSKJn  / nU GHj  nU[	        U R
                  5      :  a  M  U R
                  U   R                  n[        S[	        U5      5       GH  nXx   n	XxS-
     n
[        5       n[        U	R                  5       H  u  p[        U5      nU(       a  [	        U5      S:  a  M(  [        XhU5      nU(       a  X;   a  MB  [        XoU5      (       d  MU  [        UR                  U5      =(       d    S5      R!                  5       nU(       d  M  U[	        U
R                  5      :  a  M  [#        U
R                  U   UXC5        UR%                  U5        UR'                  U5        M     GM     GMm     [)        [        U5      5      $ )zK
Formato ministerial: fila N = etiqueta, fila N-1 = valor (misma columna).
r   r   r   rb   x   r9   )r   r   r   ru   rR   r   r   rangere   	enumerater   r   r   r   r   rS   rI   r   ri   r   r   )r   r   r   r   ru   r   r   r   ri	label_row	value_rowkeys_this_rowci
label_cellr   rU   r   s                    r@   *fill_identification_ministerial_label_rowsr   o  sB    &F"	CJJ'zz)$))3t9%BI!VI&)eM"+IOO"<-j9
!S_s%:0
Kc2-ibAAL,,S17R8>>@Y__--	 3UBL!!#&c"! #=	 &	 #2 #f+rN   c           
     X   SSK Jn  SSKJn  / nU GH}  nU[	        U R
                  5      :  a  M  U R
                  U   R                   GH@  nUR                   GH+  nUR                  n	U	R                  U" S5      5      n
U
(       d  M0  U
 Vs/ s H  n[        X5      PM     nn[         H  n[        UR                  U5      =(       d    S5      R                  5       nU(       d  M=  Sn[        U5       H  u  nn[!        UU5      (       d  M  Un  O   Ub  US:X  a  Mt  US:  a  US-
  OSnU
U   nUU   R                  5       nSU;   d  U(       a  [#        U5      (       d  M  [%        UXU5        UR'                  U5        M     GM.     GMC     GM     [)        [+        U5      5      $ s  snf )	uS   
Rellena celdas con layout «valor arriba / etiqueta abajo» sin usar coordenadas.
r   r   r   ry   r9   Nrb   rZ   )r   r   r   ru   rR   r   r   r   r   r   rv   r   r   rS   rI   r   rX   rl   r   r   r   re   )r   r   r   r   ru   r   r   r   r   r   r   r   textsrU   r   	label_idxirJ   	value_idxtargetcurrents                        r@   'fill_identification_by_labels_in_tablesr     so    &F"	CJJ'::i(--C		"]]2e95
!AKLA07L6C 0 0 5 ;<BBDE  ,0I#,U#343D#>>()I! $4 !(IN 1:Q	AAI'	2F#I.446Gwgw9O9O1&%[Qc*# 7 " . #8 #f+' Ms   F'
c                "   UR                  5        VVs0 s H  u  p#U[        ;   d  M  X#_M     nnn[        U SU[        S9nUR                  [	        XS5      5        UR                  [        XS5      5        [        [        U5      5      $ s  snnf )z>Placeholders + filas ministeriales + etiquetas en misma celda.rb   rc   r   )r   r   r   r   r   r   r   re   )r   r   r   r   id_replacementsr   s         r@   "fill_familia_identification_tablesr     s    
 )5(:(:(<a(<E`@`tqt(<Oa/V_2MF MM23P MM9#PVWX#f+ bs
   BBc          	        SSK Jn  SSKJn  UnUb+  UR	                  5        VVs0 s H  u  pgXb;   d  M  Xg_M     nnnU(       d  / $ / n[        X5       H  n	UR                  [        XX55      5        M      [        [        U5      5      $ s  snnf )u   
Sustituye {{clave}} por párrafo (no por run suelto).
Word suele partir {{student_full_name}} en varios w:t; por eso fallaba el reemplazo.
r   r   r   )
r   r   r   ru   r   r   r   r   r   re   )
r   r   r   r   ru   r   r   r   r   rt   s
             r@   #replace_familia_placeholders_in_docr     s     &H%1%7%7%9N%9TQQ=MDAD%9N	F%c..tO	
 /
 #f+ Os
   B	B	c                   SSK Jn  SSKJn  U" [	        U 5      5      nU" [	        U5      5      nUR
                  R                  R                  U" S5      5      nUR
                  R                  R                  U" S5      5      nU HY  n	U	[        U5      :  d  U	[        U5      :  a  M#  X   R                  5       n
U
c  M:  U
R                  X   [        Xy   5      5        M[     UR                  [	        U5      5        g)uM   Copia tablas de identificación (1 y 2) de source a dest sin tocar narrativa.r   r   r   zw:tblN)r   r   r   ru   r   rz   r{   r   rR   	getparentr   r   save)source_path	dest_pathr   r   ru   src_docdst_docsrc_tblsdst_tblsidxparents              r@    copy_familia_tables_between_docsr    s     s;'(Gs9~&G##++BwK8H##++BwK8H#h-3#h-#7((*>x}hx}&=>  LLY rN   c                   SSK nSSKn[        U5      n[        U 5      n UR                  5       (       a  U R                  5       (       d  / $ [	        U5      (       d  / $ U R
                  SUR                  5       R                  SS  S3-  n [        XU5      n[        XPS5        UR                  S5      =(       d    / n[        R                  S[        U5      U R                  5        UUR                  S	S
9  $ ! UR                  S	S
9  f = f)z
Tras GPT, el .docx ya no tiene {{...}}. Regenera tablas 1-2 desde la plantilla
con datos de BD y las pega en el informe final (conserva tabla 3 del modelo).
r   N_familia_id_   z.docxr   filled_keysu<   Identificación restaurada desde plantilla (%d claves) en %sT)
missing_ok)shutiluuidr   is_filer   r
  uuid4hex(fill_familia_identification_placeholdersr  rS   loggerinforR   nameunlink)output_pathtemplate_pathr   r  r  tempr   r   s           r@   ,restore_familia_identification_from_templater    s     'M{#K  ""+*=*=*?*?	(77	,tzz|/?/?/C.DE JJD%9
 	)FCM*0bJK	

 t$t$s   AC9 9D
c                   SSK nSSKJn  [        U 5      n [        U5      nU R	                  5       UR	                  5       :w  a  UR                  X5        U" [        U5      5      nUR                  5        VVs0 s H  u  pgU[        ;   d  M  Xg_M     nnn[        XX5      n	UR                  [        U5      5        [        R                  S[        U	5      UR                  5        SU	SS.$ s  snnf )u<   Copia plantilla y reemplaza placeholders de identificación.r   Nr   u-   Placeholders identificación: %d claves en %ssuccessplaceholdersstatusr  mode)r  r   r   r   resolvecopy2r   r   r   r   r  r  r  rR   r  )
r  r   r  r  r   r   r   r   r   r   s
             r@   r  r  -  s     'M{#K+"5"5"77]0
3{#
$C(4(:(:(<a(<E`@`tqt(<Oa/EFHHS
KK7F
  OO bs   8C*C*c                   SSK Jn  [        U 5      nU" U5      (       d  [        XU5      $ SSKn[        U5      nUR                  XB5        SSKJn  U" [        U5      5      nSSK	J
n  UR                  5        V	V
s0 s H  u  pU	[        ;   d  M  X_M     nn	n
U" X{5      nUR                  [        U5      5        [        U5      (       a  SOSnSXS	.$ s  sn
n	f )
uO   Solo identificación (tablas 1-2). Sin narrativa ni coordenadas si hay {{...}}.r   )!docx_is_familia_ministerial_tablaNr   )r   r!  zministerial-label-rowsr   r"  )*app.backend.utils.agent_familia_tabla_fillr(  r   r  r  r&  r   r   r   0app.backend.utils.agent_familia_placeholder_fillr   r   r   r  r   )r  r   r  r(  r   r  r   r   r   r   r   r   r   r$  s                 r@   %fill_familia_identification_only_docxr+  H  s     ]D,T227U`aa{#K
LL#
3{#
$C )5(:(:(<a(<E`@`tqt(<Oa/EFHHS:4@@>F^DEE	 bs   ;CCc                <    SSK Jn  SSKJn  U" U5      nU" X5        g)uM   Reaplica identificación desde BD (placeholders + coordenadas para el resto).r   ))build_familia_identification_replacements)"refill_familia_identification_onlyN)'app.backend.utils.agent_familia_prefillr-  r)  r.  )	docx_pathstudent_contextr-  r.  r   s        r@   #restore_identification_from_contextr2  f  s    a]<_ML&y?rN   )rJ   r   returnr   )rJ   r   rU   r   r3  r   )r_   r   r3  ztuple[str, ...])rJ   r   r3  set[str])rt   r   ru   r   r3  r   )r   r   ru   r   )r   r   r3  r4  )r   r   r3  r4  )r   r   r3  r   )rJ   r   r   dict[str, str]r3  r   )
rt   r   ru   r   r   r   r   r5  r3  	list[str])r   r   r   tuple[int, ...]ru   r   )
rt   r   r   r   ru   r   r   r   r3  None)
r   r   r   r7  r   r5  r   frozenset[str] | Noner3  r6  )r   intr   r:  r   r   r3  z
str | None)r   r:  rU   r   r   r:  r3  r   )r   r   r3  r   )
r   r   r   r   ru   r   r   r   r3  r8  )r   )r   r   r   r5  r   r7  r3  r6  )r   r   r   r5  r3  r6  )r   r   r   r5  r   r9  r3  r6  )r  r   r  r   r   r7  r3  r8  )r  r   r  r   r   r5  r3  r6  )r  
str | Pathr   r5  r  r;  r3  dict[str, Any])r0  r   r1  r<  r3  r8  )0__doc__
__future__r   loggingrF   r<   copyr   pathlibr   typingr   	getLogger__name__r  	frozensetr   __annotations__compilerf   r6   rM   rX   r`   rl   rv   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r+  r2  rQ   rN   r@   <module>rH     s   h "  	    			8	$ /8/ ^ 8 **X
;Z;#%E; -; E	;
 9; 6; *; L; ).;  2;  !<; ;; 7; )*O; F;  .!;" #N#;$ 61P%+; 7 2@8? =2
22 2 !	2
 2j
 	 	
 
> *.	" !
 ' .+\>G 
   	  	 
 
 , &,%	% % #% 	%V &,(	( ( #( 	(V	  ( *.		  '	
 @ &,!!! #! 
	!2"%"%"% !"% 	"%JPP P P 	P6FF F F 	F<@rN   