+
    ej!                     b   R t ^ RIt^ RIt^ RIHt ]P
                  ! ]4      t]P                  ! R4      t	]P                  ! R4      t
R R ltR R ltR	 R
 ltR R lt]P                  ! R]P                  4      t]P                  ! R]P                  4      tR R ltR R ltRtRtR R ltR# )u  Preencher a ficha da empresa a partir das publicações do registo comercial.

Três níveis de informação, e é importante não prometer o nível errado:

1. **Qualquer publicação**, mesmo uma simples "PRESTAÇÃO DE CONTAS", traz um
   cabeçalho com NIPC, firma oficial, natureza jurídica e sede. Serve para
   enriquecer empresas de qualquer idade — a SECURITAS, constituída há décadas,
   dá o nome legal actual e a sede a partir de uma prestação de contas de 2026.
2. **Ficha completa** (objecto, capital, sócios com quotas, gerência) só vem na
   publicação de **Constituição**, que existe para empresas constituídas depois
   de ~2006. A SEGUNOR tem (2018, ainda como IGPSPROTEK); a SECURITAS não.
3. Os actos posteriores trazem só o delta (`Artigo(s) alterado(s): 2.º`), que a
   `mj_people_parser` já usa para acompanhar a gerência.

Onde não houver constituição publicada, capital e objecto ficam por preencher —
e isso fica visível na UI, em vez de se inventar um valor.
N)Anyz<[^>]+>z[ \t]+c                >    V ^8  d   QhR\         R,          R\         /#    htmlNreturnstr)formats   "M/Volumes/www/segunor-intel-grid/backend/app/services/mj_company_enrichment.py__annotate__r      s     ) )sTz )c )    c                    V '       g   R # ^ RI p\        P                  RV 4      pVP                  V4      pVP	                  RR4      P	                  RR4      p\
        P                  RV4      p\        P                  ! RRV4      # ) N
z
 z\n{2,})r   _TAG_REsubunescapereplace_WS_LINE_REre)r   _htmltexts   &  r   html_to_textr      sk    ;;tT"D>>$D <<%--dD9D??3%D66)T4((r   c                J    V ^8  d   QhR\         R\         R\         R,          /# )r   r   labelr   Nr   )r
   s   "r   r   r   *   s%     5 5C 5 5d
 5r   c                    \         P                  ! V R2V \         P                  4      pV'       d*   VP                  ^4      P	                  4       ;'       g    R# R# )uQ   Valor de um campo do cabeçalho: a etiqueta fica numa linha, o valor na
seguinte.z\s*:\s*\n\s*(.+)N)r   search
IGNORECASEgroupstrip)r   r   ms   && r   	_labelledr$   *   sH     			eW,-tR]]CA)*1771:%%44r   c                L    V ^8  d   QhR\         R,          R\         R,          /# )r   valueNr   r   )r
   s   "r   r   r   1   s"      t d
 r   c                   V '       g   R# V  Uu. uF  qP                  4       '       g   K  VNK  	  ppV'       g   V # \        R V 4       4      \        V4      ,          pVR8  d   V # 0 Rmp. pV P                  4       P	                  4        F2  pTP                  Wd9   d   V'       d   TMVP                  4       4       K4  	  RP                  V4      # u upi )u)  A fonte escreve em maiúsculas e com acentos partidos: "SOCIEDADE ANóNIMA"
tem mesmo um "ó" minúsculo no meio de tudo em caixa alta. Testar
`any(islower())` deixaria passar exactamente esse caso, por isso decidimos
pela maioria — só normalizamos quando o valor é esmagadoramente maiúsculo.Nc              3   T   "   T F  qP                  4       '       g   K  ^x  K   	  R# 5i)   N)isupper).0cs   & r   	<genexpr> _titlecase_pt.<locals>.<genexpr>;   s     8AIIKaas   (
(g?r   >   edadedoemdasdospor)isalphasumlenlowersplitappend
capitalizejoin)r&   r,   lettersupper_ratiominorwordsws   &      r   _titlecase_ptrD   1   s    
 /%Q99;qq%G/8883w<GKS>EE[[]  "!*QALLNC #88E? 0s
   CCc                `    V ^8  d   QhR\         R,          R\        \         \        3,          /# r   )r	   dictr   )r
   s   "r   r   r   E   s&     8 8C$J 84S> 8r   c                   \        V 4      pRRRRRRRRRRRRRRR	RR
RRRRRRR/pV'       g   V# \        VR4      VR&   \        VR4      VR&   \        \        VR4      4      VR&   \        VR4      VR&   \        P                  ! RV\        P
                  4      pV'       d   VP                  ^4      P                  4       ;'       g    RVR&   VP                  ^4      P                  4       ;'       g    RVR&   VP                  ^4      P                  4       ;'       g    RVR&   VP                  ^4      '       d&   VP                  ^4       RVP                  ^4       2MVP                  ^4      VR	&   VP                  ^4      P                  4       VR
&   M\        P                  ! RV\        P
                  \        P                  ,          4      pV'       d   VP                  ^4      P                  4       ;'       g    RVR&   VP                  ^4      P                  4       ;'       g    RVR&   VP                  ^4      P                  4       ;'       g    RVR&   \        P                  ! RV\        P                  \        P                  ,          4      pV'       d@   \        P                  ! RRVP                  ^4      4      P                  4       R,          VR&   \        P                  ! RV\        P                  \        P
                  ,          4      pV'       d_   VP                  ^4      P                  4       P                  RR4      P                  RR4      P                  RR4      p \        V4      VR&   \        \        P                  ! RV\        P
                  4      4      VR&   V#   \         d     LAi ; i)u>   Campos da empresa contidos numa publicação. Todos opcionais.nipcNfirmanatureza_juridicasededistritoconcelho	freguesiacodigo_postal
localidadeobjeto_socialcapital_socialis_constitutionFu(   N[º°o]\s*de\s*Matr[íi]cula\s*/\s*NIPCFirmau   Natureza\s*Jur[íi]dicaSedezyDistrito\s*:\s*(.*?)\s*Concelho\s*:\s*(.*?)\s*Freguesia\s*:\s*(.*?)[ \t]*\n[ \t]*(\d{4})(?:\s*-\s*(\d{3}))?[ \t]+([^\n]+)-zJDistrito\s*:\s*(.*?)\s*Concelho\s*:\s*(.*?)\s*Freguesia\s*:\s*(.*?)[ \t]*$u?   ^OBJECTO\s*:\s*(.+?)(?=\n[A-ZÇÃÕÉ][A-ZÇÃÕÉ \t]{2,}\s*:)z\s+r   :Ni  Nz!^CAPITAL\s*:\s*([\d .,]+)\s*Eurosr   .,u%   CONSTITUI[ÇC][ÃA]O\s+DE\s+SOCIEDADE)r   r$   rD   r   r   r    r!   r"   	MULTILINEDOTALLr   r   float
ValueErrorbool)r   r   outr#   raws   &    r   parse_publicationr`   E   s   Dgt%8$D*dKPTdOT3CT5	C 
D"MNCKT7+CL,Yt=W-XYCD&)CK 				:bmm	A
 	''!***,44J''!***,44J771:++-55K?@wwqzz!''!*Qqwwqzl;qwwWXzOGGAJ,,.LIIY"--",,.
 ggaj..088DC
Oggaj..088DC
O wwqz//199TC 			TVZ\^\h\hkmktkt\tuA!vvfc1771:>DDFuMO
		6bllR]]>Z[Aggaj ((b199#rBJJ3PST	$)#JC ! "")),TVZ\^\i\i"jkCJ	  		s   6N8 8OOu%   constitui[çc][ãa]o\s+de\s+sociedadeu+   (aumento|redu[çc][ãa]o)\s+d[oe]\s+capitalc                h    V ^8  d   QhR\         \        \        \        3,          ,          R\        /# r   pubsr   )listrF   r	   r   r]   )r
   s   "r   r   r      s+     
T 
TT$sCx.1 
Td 
Tr   c                    \         ;QJ d&    R V  4       F  '       g   K   R'       * # 	  R'       * # ! R V  4       4      '       * # )u  True quando o capital da constituição ainda é o capital actual.

A constituição diz o capital **inicial**. A SEGUNOR foi constituída com
1.000 EUR em 2018 e aumentou depois — as quotas dos sócios já são de
125.000 EUR cada. Publicar 1.000 como capital actual seria simplesmente
errado, e não temos o valor novo (os actos de aumento não repetem o total).
Nesse caso preferimos não preencher: um campo vazio é honesto, um número
desactualizado não é.
c              3   ~   "   T F3  p\         P                  VP                  R 4      ;'       g    R4      x  K5  	  R# 5iAct_Factr   N)CAPITAL_CHANGE_REr   getr+   ps   & r   r-   %capital_is_current.<locals>.<genexpr>   s0     Sd$++AEE*,=,C,CDDds   +==TF)any)rc   s   &r   capital_is_currentro      s6     sSdSssSSsSSsSdSSSSr   c                    V ^8  d   QhR\         \        \        \        3,          ,          R\         \        \        \        3,          ,          /# rb   rd   rF   r	   r   )r
   s   "r   r   r      s5      d38n)= $tCQTH~BV r   c                    V '       g   . # V ^ ,          .p\        R V  4       R4      pVe   W ^ ,          Jd   VP                  V4       V# )ub  Escolhe as publicações que vale a pena abrir para enriquecer a ficha.

Puxar o conteúdo de todas seria caro sem ganho: são 2105 publicações nas 94
empresas monitorizadas e a esmagadora maioria são prestações de contas, que
repetem o mesmo cabeçalho. Bastam duas:

  * a **mais recente**, para firma, natureza jurídica e sede actuais — o
    cabeçalho vem em qualquer publicação, mesmo numa prestação de contas;
  * a **constituição**, quando existe, que é a única que traz objecto,
    capital, sócios e gerência inicial.

`pubs` vem do IRN ordenada da mais recente para a mais antiga.
c              3      "   T F=  p\         P                  VP                  R 4      ;'       g    R4      '       g   K9  Vx  K?  	  R# 5irg   )CONSTITUTION_REr   rj   rk   s   & r   r-   1select_enrichment_publications.<locals>.<genexpr>   s0     LDqO221553D3J3JKDs   +A
A
AN)nextr<   )rc   chosenconstitutions   &  r   select_enrichment_publicationsry      sM     	1gYFLDLdL LQ$?l#Mr   c                    V ^8  d   QhR\         \        \        \        3,          ,          R\        \        \        3,          /# )r   publicationsr   rq   )r
   s   "r   r   r      s/      tDcN'; S#X r   c                   V '       g   RR/# \          Uu/ uF  qV ^ ,          P                  V4      bK  	  ppV  FD  p\         F7  pVP                  V4      e   K  VP                  V4      f   K-  W1,          W!&   K9  	  KF  	  \        ;QJ d    R V  4       F  '       g   K   RM	  RM! R V  4       4      VR&   V# u upi )uC  Combina as publicações abertas numa ficha só.

**A identidade e a morada vêm exclusivamente da publicação mais recente**,
em bloco. Preencher campo a campo a partir de várias publicações produz
fichas incoerentes: a SEGUNOR ficava com a rua actual e o código postal da
constituição de 2018, e a firma seria "IGPSPROTEK, LDA", o nome anterior à
mudança. Um campo em falta é preferível a um campo de outra época.

Objecto e capital só existem na constituição, e esses sim aceitam-se de lá.

`publications` deve vir ordenada da mais recente para a mais antiga.
has_constitutionFc              3   B   "   T F  qP                  R 4      x  K  	  R# 5i)rS   N)rj   rk   s   & r   r-   'merge_company_fields.<locals>.<genexpr>   s     $T|!UU+<%=%=|s   T)CURRENT_STATErj   FROM_CONSTITUTIONrn   )r{   kmergedpubs   &   r   merge_company_fieldsr      s     "E**ANOAa!4!4Q!77FO"Azz!}$)?F	 #  "%$T|$T$T|$T!TFM Ps   !B;)rI   rJ   rK   rL   rM   rN   rO   rP   )rQ   rR   )__doc__loggingr   typingr   	getLogger__name__loggercompiler   r   r   r$   rD   r`   r    rt   ri   ro   ry   r   r   r    r   r   <module>r      s   "  	 			8	$
**Z
 jj#)5(8v **Er}}UJJ2BMM 

T2 8 r   