o
    Nº:j–U  ã                   @   s‚  d dl Z d dlZd dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	 d dl
mZ d dlmZ e e¡Ze ¡ Zh d£Zh d£Zdd	d
dddœZh d£ZddddddddddddddddœZdd d!d"d#d$d%d&d'd(d)d*d+d,d-dœZi d.d/“d/d/“d0d/“d1d2“d3d2“d4d2“d5d2“d6d7“d7d7“d8d9“d:d9“d9d9“d;d9“d<d=“d=d=“d>d=“Z	?	dˆd@edAedBedCedDeeef dB dEeeef dB fdFdG„ZdBedEedB fdHdI„ZG dJdK„ dKƒZdLedAedMedNeeef dOeeef dPedEeeef fdQdR„Zd‰dSedTedUedB dEeeef fdVdW„Z dLedAedSedOeeef dXe!dEeeef fdYdZ„Z"dSedOeeef d[e#e dXe!dEeeef f
d\d]„Z$dSedOeeef dEedB fd^d_„Z%dSedOeeef dEe#e fd`da„Z&dSedbedOeeef dEedB fdcdd„Z'dOeeef dTedEefdedf„Z(dOeeef dTedgedEdfdhdi„Z)dSedEeeef fdjdk„Z*dOeeef dEdfdldm„Z+dOeeef dEeeef fdndo„Z,dOeeef dEeeef fdpdq„Z-dOeeef dEeeef fdrds„Z.dPedEedB fdtdu„Z/dgedve0e dEe1fdwdx„Z2dAedyedEeeef fdzd{„Z3dgedEedB fd|d}„Z4dgedEeeef fd~d„Z5dgedEe!fd€d�„Z6dgedEefd‚dƒ„Z7dgedEefd„d…„Z8dEefd†d‡„Z9dS )Šé    N)Úclosing)ÚdatetimeÚtimezone)ÚPath)ÚAny>   ú	pos touchúpunto de ventaúventas mostradorÚposÚcajaÚticketÚfacturaÚticketsÚfacturarÚfacturasÚpostouchÚfacturacion>   úmb invúback officeúmb inventarioÚboÚbackÚmbinvÚstockÚbodegaÚ	backoficeÚ
backofficeÚ
inventarioÚexistenciasÚinventarioszEmergencia de CobroÚSoporteÚImplementacionÚVentasÚAdministracion)Úemergencia_cobroÚsoporteÚimplementacionÚventasÚadministracion>   ÚnitÚcorreoÚnombreÚanydeskÚempresaÚtelefonoÚ	industriaÚnombre_empresazNombre y empresaÚEmpresaÚSistemaÚTiendaÚCajazDescripcion del inconvenientezDescripcion de la solicitudzDescripcion de la dudazDescripcion de la consultaÚAnyDeskÚNombreÚTelefonozCorreo electronicoÚ	IndustriaÚNIT)r0   r-   ÚsistemaÚtiendar   Údescripcion_inconvenienteÚdescripcion_solicitudÚdescripcion_dudaÚdescripcion_consultar,   r+   r.   r*   r/   r)   z.Indicanos tu nombre y el nombre de tu empresa.z"Indicanos el nombre de tu empresa.z,Selecciona el sistema donde necesitas apoyo.z-Indicanos la tienda donde ocurre el problema.z6Indicanos la caja o terminal donde ocurre el problema.zÈPor favor describenos el inconveniente que se esta presentando. Si cuentas con una imagen o video, puedes enviarlo en este momento; nos ayudara a comprender mejor el caso y apoyarte de forma mas agil.z¯Por favor cuentanos que ocurre o que necesitas que revisemos. Si tienes una imagen o video del problema, puedes enviarlo en este momento; eso nos ayuda a darte un mejor apoyo.zDescribe la duda que tienes.z$Describe tu consulta administrativa.zIIndicanos el numero de AnyDesk. Si no tienes, responde: No tengo AnyDesk.zIndicanos tu nombre.z Indicanos tu numero de telefono.z Indicanos tu correo electronico.zIndicanos tu tipo de industria.zIndicanos el NIT de tu empresa.Ú1r%   ÚsupportÚ2r$   Ú
emergenciazemergencia cobrozemergencia de cobroÚ3r&   Ú4r'   ÚventaÚsalesÚ5r(   ÚadminÚsqliteÚ
store_pathÚcustomer_keyÚmessage_textÚbackendÚmysql_configÚreturnc                 C   s  |sdS t || |d�}|pd ¡ }t|ƒ}| |¡}tt| d¡ƒƒ}	|dv rE| d¡rCt|	ƒ | |dd|	¡ ddd	| d¡dd
œS dS t	| d¡ƒ}
|
rWt
|||
||	|ƒS t|ƒ}|s_dS t|ƒ|	d< t||	ƒ}|r�| ||||	¡ t||dt| › d�d�S t||||	d	d�S )zHBuild a stateful intake reply or return None to use the normal bot flow.N)rN   Úsqlite_pathrO   Ú Údata>   ÚsalirÚcancelarÚactive_flowÚtextzCHe cancelado la captura de datos. Si necesitas apoyo, escribe menu.T©ÚtyperW   ÚintakeÚflowÚfieldÚactive_requestzPara z* voy a pedirte algunos datos, uno por uno.©Úintro©Úalready_available)ÚCustomerStateServiceÚstripÚ
_normalizeÚloadÚ_normalize_data_shapeÚ_ensure_data_dictÚgetÚ_clear_active_requestÚsaveÚ_valid_flowÚ_continue_active_flowÚdetect_selected_flowÚ_new_requestÚ_first_missing_fieldÚ_ask_field_payloadÚFLOW_TITLESÚ_finish_flow)rK   rL   rM   rN   rO   ÚserviceÚmessageÚ
normalizedÚstaterS   rV   Úselected_flowÚmissing_field© ry   úL/var/www/html/macrobase-freshchat-api/app/services/customer_state_service.pyÚbuild_customer_intake_reply‚   sL   ý

û
ýr{   c                 C   sX   t | ƒ}|tv rt| S d|v rdS d|v rdS d|v rdS d|v r$dS d|v r*dS d S )Nr%   rC   r$   r&   r'   r(   )rd   ÚOPTION_TO_FLOW)rM   ru   ry   ry   rz   rm   ¹   s   rm   c                
   @   sN  e Zd Z			d$dededeeef dB ddfdd	„Zd
edeeef fdd„Zd
ededB dedB deeef ddf
dd„Zd
edeeef fdd„Z	d
ededB dedB deeef ddf
dd„Z
d
edeeef fdd„Zd
ededB dedB deeef ddf
dd„Zd%dd„Zd%dd„Zd%dd„Zdejfd d!„Zdefd"d#„ZdS )&rb   rJ   údata/customer_state.dbNrN   rQ   rO   rP   c                 C   sh   |dkrdnd| _ t|ƒ| _|pi | _tt| j d¡pdƒƒ| _| j dkr.| jjj	ddd� |  
¡  d S )NÚmysqlrJ   ÚtableÚcustomer_statesT)ÚparentsÚexist_ok)rN   r   rQ   rO   Ú_safe_table_nameÚstrrh   Ú
table_nameÚparentÚmkdirÚ_ensure_schema)ÚselfrN   rQ   rO   ry   ry   rz   Ú__init__Ë   s   


zCustomerStateService.__init__rL   c                 C   s   | j dkr
|  |¡S |  |¡S ©Nr~   )rN   Ú_load_mysqlÚ_load_sqlite)r‰   rL   ry   ry   rz   re   Û   s   


zCustomerStateService.loadrV   Úcurrent_fieldrS   c                 C   s2   | j dkr|  ||||¡ d S |  ||||¡ d S r‹   )rN   Ú_save_mysqlÚ_save_sqlite)r‰   rL   rV   rŽ   rS   ry   ry   rz   rj   à   s   
zCustomerStateService.savec              	   C   sl   t �' t|  ¡ ƒ�}| d|f¡ ¡ }W d   ƒ n1 sw   Y  W d   ƒ n1 s,w   Y  t||ƒS )NzXSELECT active_flow, current_field, data_json FROM customer_states WHERE customer_key = ?)Ú_LOCKr   Ú_connect_sqliteÚexecuteÚfetchoneÚ_row_to_state)r‰   rL   ÚconnÚrowry   ry   rz   r�   ì   s   ûúÿ€ 
z!CustomerStateService._load_sqlitec              
   C   sš   t ƒ }tj|ddd�}t�6 t|  ¡ ƒ�}| d|||||f¡ | ¡  W d   ƒ n1 s.w   Y  W d   ƒ d S W d   ƒ d S 1 sFw   Y  d S )NFT©Úensure_asciiÚ	sort_keysa)  INSERT INTO customer_states (customer_key, active_flow, current_field, data_json, updated_at) VALUES (?, ?, ?, ?, ?) ON CONFLICT(customer_key) DO UPDATE SET active_flow = excluded.active_flow, current_field = excluded.current_field, data_json = excluded.data_json, updated_at = excluded.updated_at)Ú_utc_now_for_dbÚjsonÚdumpsr‘   r   r’   r“   Úcommit)r‰   rL   rV   rŽ   rS   Ú
updated_atÚ	data_jsonr–   ry   ry   rz   r�   ÷   s   	õ
Pòz!CustomerStateService._save_sqlitec              
   C   s¢   t �B t|  ¡ ƒ�,}| ¡ �}| d| j› d�|f¡ | ¡ }W d   ƒ n1 s)w   Y  W d   ƒ n1 s8w   Y  W d   ƒ n1 sGw   Y  t||ƒS )Nz3SELECT active_flow, current_field, data_json FROM `z` WHERE customer_key = %s)r‘   r   Ú_connect_mysqlÚcursorr“   r…   r”   r•   )r‰   rL   r–   r¢   r—   ry   ry   rz   rŒ     s   
ÿû
ø€ÿ€ 

z CustomerStateService._load_mysqlc           	      C   sÌ   t ƒ }tj|ddd�}t�O t|  ¡ ƒ�0}| ¡ �}| d| j› d�|||||f¡ W d   ƒ n1 s4w   Y  | 	¡  W d   ƒ n1 sGw   Y  W d   ƒ d S W d   ƒ d S 1 s_w   Y  d S )NFTr˜   zINSERT INTO `a   ` (customer_key, active_flow, current_field, data_json, updated_at) VALUES (%s, %s, %s, %s, %s) ON DUPLICATE KEY UPDATE active_flow = VALUES(active_flow), current_field = VALUES(current_field), data_json = VALUES(data_json), updated_at = VALUES(updated_at))
r›   rœ   r�   r‘   r   r¡   r¢   r“   r…   rž   )	r‰   rL   rV   rŽ   rS   rŸ   r    r–   r¢   ry   ry   rz   r�     s   
	õÿ
Pñz CustomerStateService._save_mysqlc                 C   s"   | j dkr|  ¡  d S |  ¡  d S r‹   )rN   Ú_ensure_mysql_schemaÚ_ensure_sqlite_schema©r‰   ry   ry   rz   rˆ   7  s   
z#CustomerStateService._ensure_schemac              	   C   sx   t �0 t|  ¡ ƒ�}| d¡ | ¡  W d   ƒ n1 sw   Y  W d   ƒ d S W d   ƒ d S 1 s5w   Y  d S )Nz¬CREATE TABLE IF NOT EXISTS customer_states (customer_key TEXT PRIMARY KEY,active_flow TEXT,current_field TEXT,data_json TEXT NOT NULL DEFAULT '{}',updated_at TEXT NOT NULL))r‘   r   r’   r“   rž   )r‰   r–   ry   ry   rz   r¤   =  s   þ
Pôz*CustomerStateService._ensure_sqlite_schemac              
   C   sª   t �I t|  ¡ ƒ�*}| ¡ �}| d| j› d�¡ W d   ƒ n1 s#w   Y  | ¡  W d   ƒ n1 s6w   Y  W d   ƒ d S W d   ƒ d S 1 sNw   Y  d S )NzCREATE TABLE IF NOT EXISTS `zý` (customer_key VARCHAR(191) PRIMARY KEY,active_flow VARCHAR(64) NULL,current_field VARCHAR(64) NULL,data_json JSON NOT NULL,updated_at DATETIME NOT NULL,INDEX idx_updated_at (updated_at)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci)r‘   r   r¡   r¢   r“   r…   rž   )r‰   r–   r¢   ry   ry   rz   r£   L  s   
þÿ
Pòz)CustomerStateService._ensure_mysql_schemac                 C   s   t  | j¡S ©N)Úsqlite3ÚconnectrQ   r¥   ry   ry   rz   r’   ]  ó   z$CustomerStateService._connect_sqlitec              
   C   s˜   zdd l }W n ty } ztdƒ|‚d }~ww |jt| j d¡p"dƒt| j d¡p+dƒt| j d¡p4dƒt| j d	¡p=dƒt| j d
¡pFdƒddd�S )Nr   zCPyMySQL no esta instalado. Ejecuta: pip install -r requirements.txtÚhostz	127.0.0.1Úportiê  ÚuserrR   ÚpasswordÚdatabaseÚutf8mb4F)rª   r«   r¬   r­   r®   ÚcharsetÚ
autocommit)ÚpymysqlÚImportErrorÚRuntimeErrorr¨   r„   rO   rh   Úint)r‰   r²   Úexcry   ry   rz   r¡   `  s&   ÿþ€ÿùz#CustomerStateService._connect_mysql)rJ   r}   N)rP   N)Ú__name__Ú
__module__Ú__qualname__r„   Údictr   rŠ   re   rj   r�   r�   rŒ   r�   rˆ   r¤   r£   r§   Ú
Connectionr’   r¡   ry   ry   ry   rz   rb   Ê   sl    üþýü
ûþýü
û
úþýü
û
úþýü
û
ú


rb   rs   rV   rv   rS   rt   c           	      C   sØ   t || d¡|ƒ}|st| |||dd�S t|ƒs'|  ||||¡ t||dd�S |dkrGt|ƒ}|s@|  ||||¡ t||dd�S t|||ƒ nt||| ¡ ƒ t	||ƒ}|rc|  ||||¡ t||ƒS t| |||dd�S )	NrŽ   Tr`   z"Necesito este dato para continuar.r^   r:   zyNo logre identificar el sistema. Puedes tocar una opcion o responder con palabras como POS, facturas, inventario o MBINV.F)
Ú_current_or_first_missingrh   rr   Ú_has_answerrj   rp   Ú_parse_system_valueÚ_set_field_valuerc   ro   )	rs   rL   rV   rv   rS   rt   rŽ   Úsystem_valueÚ
next_fieldry   ry   rz   rl   s  s4   ýü

rl   r[   r\   r_   c                 C   sX   t | }|r|› d|› �n|}d|d| |dœ}|dkr*| dddd	g|› d
�dœ¡ |S )Nz

rW   TrX   r:   Úquick_replieszSelecciona el sistemaÚPOSTouchÚ
BackOfficezI

Opciones: POSTouch (facturacion/cajas) o BackOffice (inventario/MBINV).)rY   Ú	help_textÚbuttonsÚfallback_text)ÚFIELD_PROMPTSÚupdate)r[   r\   r_   ÚpromptrW   Úpayloadry   ry   rz   rp   Ÿ  s"   ûûÿrp   ra   c           	      C   sˆ   t ||ƒ}t|ƒ ¡ }||d< tƒ |d< |s.| dg ¡}t|tƒr.| |¡ |dd … |d< t||||d�}t	|ƒ |  
|d d |¡ |S )Nr[   Úcompleted_atÚrequestsiìÿÿÿr`   )Ú_fields_for_flowÚ_request_fieldsÚcopyr›   Ú
setdefaultÚ
isinstanceÚlistÚappendÚ_summary_payloadri   rj   )	rs   rL   r[   rS   ra   ÚfieldsÚrequest_snapshotrÍ   rË   ry   ry   rz   rr   º  s   



rr   rÖ   c           	      C   s‚   t |  }|rdnd}|› d|› d�g}|D ]}t||ƒ}| dt| › d|› �¡ q| d¡ | d¡ d	d
 |¡d| d d|dœS )Nz#Ya tengo los datos registrados parazDatos recibidos paraú ú:z- z: rR   z+En breve un asesor continuara con el apoyo.rW   Ú
T)rY   rW   rZ   r[   r\   Úcompletera   )rq   Ú_get_field_valuerÔ   ÚFIELD_LABELSÚjoin)	r[   rS   rÖ   ra   ÚtitleÚprefixÚlinesr\   Úvaluery   ry   rz   rÕ   Ò  s    


ùrÕ   c                 C   s*   t | |ƒD ]}tt||ƒƒs|  S qd S r¦   )rÎ   r½   rÜ   )r[   rS   r\   ry   ry   rz   ro   ë  s
   ÿro   c                 C   s†   | dkr!ddg}t t|dƒƒdkr| ddg¡ | ddg¡ |S | d	kr)g d
¢S | dkr1ddgS | dkr9g d¢S | dkrAg d¢S g S )Nr%   r-   r:   r   r;   r   r=   r,   r$   )r0   r;   r   r<   r,   r&   r0   r>   r'   )r+   r.   r*   r-   r/   r(   )r0   r)   r?   )rd   rÜ   Úextend)r[   rS   rÖ   ry   ry   rz   rÎ   ò  s   rÎ   rŽ   c                 C   s8   t | |ƒ}t|tƒr||v rtt||ƒƒs|S t| |ƒS r¦   )rÎ   rÒ   r„   r½   rÜ   ro   )r[   rŽ   rS   rÖ   ry   ry   rz   r¼     s
   

r¼   c                 C   s<   |t v rtt| ƒ |¡pdƒ ¡ S tt| ƒ |¡pdƒ ¡ S ©NrR   )ÚPROFILE_FIELDSr„   Ú_profilerh   rc   rÏ   )rS   r\   ry   ry   rz   rÜ     s   rÜ   râ   c                 C   s(   |t v r|t| ƒ|< d S |t| ƒ|< d S r¦   )rå   ræ   rÏ   )rS   r\   râ   ry   ry   rz   r¿     s   r¿   c                 C   s   | i t ƒ dœS )N)r[   rÖ   Ú
started_at)r›   )r[   ry   ry   rz   rn   $  s   ýrn   c                 C   s   i | d< d S )Nr]   ry   )rS   ry   ry   rz   ri   ,  r©   ri   c                 C   s&   |   di ¡}t|tƒsi }|| d< |S )NÚprofile©rÑ   rÒ   rº   )rS   rè   ry   ry   rz   ræ   0  s
   
ræ   c                 C   sH   |   di ¡}t|tƒsi }|| d< |  di ¡}t|tƒs"i }||d< |S )Nr]   rÖ   ré   )rS   ÚrequestrÖ   ry   ry   rz   rÏ   8  s   

rÏ   c                 C   sr   t | ƒ}tD ]}| |¡s|  |¡r| | ||< q|  di ¡}t|tƒs(i | d< |  dg ¡}t|tƒs7g | d< | S )Nr]   rÍ   )ræ   rå   rh   rÑ   rÒ   rº   rÓ   )rS   rè   r\   r]   rÍ   ry   ry   rz   rf   D  s   €

rf   c                 C   s8   t | ƒ}t|tƒ}t|tƒ}||krdS ||krdS d S )NrÃ   rÄ   )rd   Ú_keyword_scoreÚPOSTOUCH_KEYWORDSÚBACKOFFICE_KEYWORDS)rt   ru   Úpostouch_scoreÚbackoffice_scorery   ry   rz   r¾   U  s   

r¾   Úkeywordsc                 C   sn   d}d| › d�}|D ]*}t |ƒ}|sq
|| krt|dƒ}q
d|› d�|v r+t|dƒ}q
|| v r4t|dƒ}q
|S )Nr   rØ   é   é   é   )rd   Úmax)râ   rð   ÚscoreÚpaddedÚkeywordÚnormalized_keywordry   ry   rz   rë   a  s    


€rë   r—   c                 C   s˜   |sd d i dœS |d |d |d }}}t |tƒr"|jddd�}z	t |p(d¡}W n ty<   t d	| ¡ i }Y nw ||t |tƒrH|dœS i dœS )
N)rV   rŽ   rS   r   ró   rò   zutf-8Úreplace)Úerrorsz{}z/Invalid customer state JSON for customer_key=%s)	rÒ   ÚbytesÚdecoderœ   ÚloadsÚ
ValueErrorÚloggerÚwarningrº   )rL   r—   rV   rŽ   r    rS   ry   ry   rz   r•   s  s"   
þýýr•   c                 C   s   t | tƒr| tv r| S d S r¦   )rÒ   r„   rq   ©râ   ry   ry   rz   rk   ˆ  s   rk   c                 C   s   t | tƒr| S i S r¦   )rÒ   rº   r  ry   ry   rz   rg   Œ  ó   rg   c                 C   s   t | pd ¡ ƒS rä   )Úboolrc   r  ry   ry   rz   r½   �  s   r½   c                 C   s:   t  d| pd¡}d dd„ |D ƒ¡}d | ¡  ¡  ¡ ¡S )NÚNFKDrR   c                 s   s   � | ]
}t  |¡s|V  qd S r¦   )ÚunicodedataÚ	combining)Ú.0Úcharry   ry   rz   Ú	<genexpr>–  s   € z_normalize.<locals>.<genexpr>rØ   )r  Ú	normalizerÞ   Úlowerrc   Úsplit)râ   ru   ry   ry   rz   rd   ”  s   rd   c                 C   s   t  d| pd¡stdƒ‚| S )Nz[A-Za-z0-9_]+rR   zLCUSTOMER_STATE_MYSQL_TABLE solo puede contener letras, numeros y guion bajo.)ÚreÚ	fullmatchrþ   r  ry   ry   rz   rƒ   š  s   rƒ   c                   C   s   t  tj¡ d¡S )Nz%Y-%m-%d %H:%M:%S)r   Únowr   ÚutcÚstrftimery   ry   ry   rz   r›      r  r›   )rJ   Nr¦   ):rœ   Úloggingr  r§   Ú	threadingr  Ú
contextlibr   r   r   Úpathlibr   Útypingr   Ú	getLoggerr·   rÿ   ÚLockr‘   rì   rí   rq   rå   rÝ   rÈ   r|   r„   rº   r{   rm   rb   rl   rp   r  rr   rÓ   rÕ   ro   rÎ   r¼   rÜ   r¿   rn   ri   ræ   rÏ   rf   r¾   Úsetrµ   rë   r•   rk   rg   r½   rd   rƒ   r›   ry   ry   ry   rz   Ú<module>   sF   
ûñéÿþýüûúùø	÷
öõôóòñðûÿþýüû
ú7 *ÿþý
ü
ûú

ù(,ÿþý
üû

úÿ
þýü

û""&""""