a
    0i!                     @   s"   d dl Z d dlZG dd dZdS )    Nc                   @   sJ   e Zd ZdZdd Zdd Zdd Zdd	d
Zdd Zdd Z	dd Z
dS )
CRMManageruv   
    Clase que gestiona la conexión y las operaciones con la API de
    Microsoft Dynamics 365 Business Central.
    c                 C   sz   | d| _| d| _| d| _| d| _| d| _d| j d| _d| j d	| j d
| _d| _d| _	d| _
dS )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config r   7/var/www/html/src/App/Utilities_module/CRMManagement.py__init__   s    zCRMManager.__init__c              
   C   s   | j rt | jd k rdS ddi}d| j| jdd}zJtj| j||d}|  |	 }|d	 | _ t |d
  | _t
d W n> tjjy } z"t
d|  d| _  W Y d}~n
d}~0 0 dS )u   
        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-urlencodedZclient_credentialsz1https://api.businesscentral.dynamics.com/.default)Z
grant_typer   r   scope)headersdatar   Z
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   er   r   r   
_get_token&   s&    
zCRMManager._get_tokenc              
   C   s   | j r
dS |   | j d}dd| j i}ztj||d}|  | dg }|D ]@}|d| jkrZ|d| _ t	d	| j d
| j    W dS qZt
d| j dW n8 tjjy } zt	d|   W Y d}~n
d}~0 0 dS )uT   
        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   r*   r   r   r    r
   r"   r#   r   r$   	Exceptionr%   r&   )r   urlr   r(   	companiescompanyr)   r   r   r   _get_company_guidD   s$    
zCRMManager._get_company_guidNc           	   
   C   s   |    |   d}d| j d| j d| d| j d| 
}d| j dd	}z:tj| |||d
}|	  |j
r|| n
d|jdW S  tjjy } z>td| d|  td|jr|jjnd   W Y d}~n
d}~0 0 dS )uU   
        Método genérico para realizar llamadas a los endpoints de la API.
        zIGSA/integration/v1.0r   r	   z/api/z/companies(z)/r,   zapplication/json)r+   r   )r   r#   success)statuscodeu   ❌ Error en la llamada API a 'z': zDetalle del error: zSin respuestaN)r*   r5   r   r   r   r   r    requestupperr"   contentr#   status_coder%   r&   r$   r(   text)	r   methodendpointr'   Zapi_group_pathr2   r   r(   r)   r   r   r   _make_api_request`   s*    
zCRMManager._make_api_requestc                 C   s   t d | ddS )zF
        Obtiene la lista de todas las oportunidades del CRM.
        u+   ℹ️ Obteniendo lista de oportunidades...GETZopportunitiesr$   r@   )r   r   r   r   get_opportunities~   s    zCRMManager.get_opportunitiesc                 C   s   t d | jdd|dS )uR   
        Envía los datos de una cotización al CRM para su importación.
        u%   ℹ️ Enviando cotización al CRM...POSTZquoteImports)r'   rB   )r   
quote_datar   r   r   
send_quote   s    zCRMManager.send_quotec                 C   s~  d| d}|  d|}|dg }|s8td| d|d }|d}i }|rd	| d}|  d|}	|	dg }
|
r|
d }qtd
| d ntd| d |d}i }|rd| d}|  d|}|dg }|r|d }ntd| d ntd| d |d|d|d|d|d|d|d|d|d|d|d|d|dd}|S )u   
        Obtiene y consolida el contexto completo (Oportunidad, Contacto y Vendedor) 
        para una cotización específica.
        zopportunities?$filter=No eq 'r0   rA   r-   zOportunidad 'z' no encontrada en el CRM.r   Z	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.Z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TypeZEMailStatusAddressColonyPhoneCityCountyPriorityPostCode)rH   ContactNameContactTypeSalespersonNameContactEMailrK   rL   rM   rN   rO   rP   rQ   rR   )r@   r
   
ValueErrorr$   )r   Zopportunity_noZopp_endpointZopportunities_dataZopportunity_listZopportunityZ
contact_noZcontactZcontact_endpointZcontacts_dataZcontact_listZsalesperson_codeZsalespersonZsales_endpointZ
sales_dataZ
sales_listZconsolidated_contextr   r   r   get_opportunity_context   sR    



z"CRMManager.get_opportunity_context)N)__name__
__module____qualname____doc__r   r*   r5   r@   rC   rF   rX   r   r   r   r   r   
   s   
r   )r    r   r   r   r   r   r   <module>   s   