
    i!                     (    S SK r S SKr " S S5      rg)    Nc                   F    \ rS rSrSrS rS rS rSS jrS r	S	 r
S
 rSrg)
CRMManager
   uj   
Clase que gestiona la conexión y las operaciones con la API de
Microsoft Dynamics 365 Business Central.
c                 x   UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        UR                  S5      U l        SU R                   S3U l        SU R                   S	U R                   S
3U l        SU l        SU l	        SU l
        g)u   
Inicializa el gestor del CRM con un objeto de configuración de Flask.

Args:
    config: El objeto app.config (que se accede como diccionario).
BC_TENANT_IDBC_CLIENT_IDBC_CLIENT_SECRETBC_ENV_NAMEBC_COMPANY_NAMEz"https://login.microsoftonline.com/z/oauth2/v2.0/token.https://api.businesscentral.dynamics.com/v2.0//z	/api/v2.0Nr   )get	tenant_id	client_idclient_secretenv_namecompany_name	token_urlapi_base_urlaccess_tokentoken_expires_atcompany_guid)selfconfigs     aC:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\Utilities_module\CRMManagement.py__init__CRMManager.__init__   s     $ZZ7DN#ZZ7DN!',>!?D"JJ}5DM &

+< =D  B$..AQQcdDN"PQUQ_Q_P``abfboboappy zD !%D$%D! $D    c                    U R                   (       a'  [        R                  " 5       U R                  S-
  :  a  gSS0nSU R                  U R                  SS.n [
        R                  " U R                  XS9nUR                  5         UR                  5       nUS	   U l         [        R                  " 5       US
   -   U l        [        S5        g! [
        R                  R                   a  n[        SU 35        SU l         e SnAff = f)ur   
Obtiene un token de acceso. Si el token existente es válido, lo reutiliza.
De lo contrario, solicita uno nuevo.
<   NContent-Typez!application/x-www-form-urlencodedclient_credentialsz1https://api.businesscentral.dynamics.com/.default)
grant_typer   r   scope)headersdatar   
expires_inu3   ✅ Token de acceso obtenido/renovado exitosamente.u   ❌ Error al obtener el token: )r   timer   r   r   requestspostr   raise_for_statusjsonprint
exceptionsRequestException)r   r%   payloadresponser&   es         r   
_get_tokenCRMManager._get_token&   s    
 t/D/Dr/I!I!#FG.!//H	
	}}T^^WSH%%'==?D $^ 4D$(IIK$|2D$DD!GH""33 	3A378 $D	s   A4C D,DDc                 v   U R                   (       a  gU R                  5         U R                   S3nSSU R                   30n [        R
                  " XS9nUR                  5         UR                  5       R                  S/ 5      nU H_  nUR                  S5      U R                  :X  d  M$  UR                  S5      U l         [        S	U R                   S
U R                    35          g   [        SU R                   S35      e! [        R                  R                   a  n[        SU 35        e SnAff = f)uD   
Obtiene y almacena en caché el GUID de la compañía configurada.
Nz
/companiesAuthorizationBearer )r%   valuenameidu   ✅ GUID para 'z' encontrado: u-   No se encontró la compañía con el nombre ''u/   ❌ Error al obtener el GUID de la compañía: )r   r3   r   r   r)   r   r+   r,   r   r-   	Exceptionr.   r/   )r   urlr%   r1   	companiescompanyr2   s          r   _get_company_guidCRMManager._get_company_guidD   s"    ""#:."gd.?.?-@$AB	||C9H%%' ++GR8I$;;v&$*;*;;(/D(9D%OD,=,=+>nTM^M^L_`a	 % KDL]L]K^^_`aa""33 	CA3GH	s%   A&D .<D +D D8$D33D8Nc           
      l   U R                  5         U R                  5         SnSU R                   SU R                   SU SU R                   SU 3
nSU R
                   3SS	.n [        R                  " UR                  5       XVUS
9nUR                  5         UR                  (       a  UR                  5       $ SUR                  S.$ ! [        R                  R                   aL  n[        SU SU 35        [        SUR                   (       a  UR                   R"                  OS 35        e SnAff = f)uE   
Método genérico para realizar llamadas a los endpoints de la API.
zIGSA/integration/v1.0r   r   z/api/z/companies(z)/r7   zapplication/json)r6   r!   )r%   r,   success)statuscodeu   ❌ Error en la llamada API a 'z': zDetalle del error: zSin respuestaN)r3   r@   r   r   r   r   r)   requestupperr+   contentr,   status_coder.   r/   r-   r1   text)	r   methodendpointr0   api_group_pathr=   r%   r1   r2   s	            r   _make_api_requestCRMManager._make_api_request`   s"    	  1??OqQUQ^Q^P_N#;t/@/@.AH:O  't'8'8&9:.

	''SZ[H%%'&.&6&68==?oyZbZnZn<oo""33 	3H:SDE'1::

?'[\]	s    %AC	 :C	 	D3'AD..D3c                 <    [        S5        U R                  SS5      $ )z6
Obtiene la lista de todas las oportunidades del CRM.
u+   ℹ️ Obteniendo lista de oportunidades...GETopportunitiesr-   rN   )r   s    r   get_opportunitiesCRMManager.get_opportunities~   s      	;<%%e_==r   c                 :    [        S5        U R                  SSUS9$ )uB   
Envía los datos de una cotización al CRM para su importación.
u%   ℹ️ Enviando cotización al CRM...POSTquoteImports)r0   rS   )r   
quote_datas     r   
send_quoteCRMManager.send_quote   s%     	56%%fnj%QQr   c                    SU S3nU R                  SU5      nUR                  S/ 5      nU(       d  [        SU S35      eUS   nUR                  S5      n0 nU(       aG  S	U S3nU R                  SU5      n	U	R                  S/ 5      n
U
(       a  U
S   nO[        S
U S35        O[        SU S35        UR                  S5      n0 nU(       aG  SU S3nU R                  SU5      nUR                  S/ 5      nU(       a  US   nO[        SU S35        O[        SU S35        UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      S.nU$ )up   
Obtiene y consolida el contexto completo (Oportunidad, Contacto y Vendedor) 
para una cotización específica.
zopportunities?$filter=No eq 'r;   rQ   r8   zOportunidad 'z' no encontrada en el CRM.r   	ContactNozcontactsImports?$filter=No eq 'uI   ⚠️ Aviso: No se encontró la información detallada del Contacto No. .u   ⚠️ Aviso: La oportunidad z  no tiene un ContactNo asignado.SalespersonCodez/salespersonImports?$filter=SalespersonCode eq 'uA   ⚠️ Aviso: No se encontró la información del Vendedor Cód. z& no tiene un SalespersonCode asignado.NoNameTypeEMailStatusAddressColonyPhoneCityCountyPriorityPostCode)r`   ContactNameContactTypeSalespersonNameContactEMailrd   re   rf   rg   rh   ri   rj   rk   )rN   r   
ValueErrorr-   )r   opportunity_noopp_endpointopportunities_dataopportunity_listopportunity
contact_nocontactcontact_endpointcontacts_datacontact_listsalesperson_codesalespersonsales_endpoint
sales_data
sales_listconsolidated_contexts                    r   get_opportunity_context"CRMManager.get_opportunity_context   s    7~6FaH!33E<H-11'2>}^,<<VWXX&q) !__[1
!@AN 225:JKM(,,Wb9L&q/ablammnop1.1AAabc '??+<=NO_N``abN//~FJ#4J(mYZjYkklmn1.1AAghi
 //$'";;v.";;v.*v6#KK0!ooh/{{9-kk(+[[)KK'kk(+#
3J/ 
  $#r   )
r   r   r   r   r   r   r   r   r   r   )N)__name__
__module____qualname____firstlineno____doc__r   r3   r@   rN   rT   rZ   r   __static_attributes__ r   r   r   r   
   s,    %.<8<>R@$r   r   )r)   r(   r   r   r   r   <module>r      s     B$ B$r   