o
    GY)j h  ã                   @   s`   d Z ddlZddlmZ ddlZddlZddlZddlZddlm	Z	 e 
e¡ZG dd„ dƒZdS )z]
Quality Parameters Handler
Manages CRUD operations for business-specific quality parameters
é    N)Ú
DictCursor)Úcontextmanagerc                   @   sÖ   e Zd ZdZdd„ Zedd„ ƒZdd„ Zedd	„ ƒZ	ed
d„ ƒZ
edd„ ƒZed0dd„ƒZdd„ Zddœdd„Zdd„ Zdd„ Zdd„ Zd1dd„Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Zd,d-„ Zd.d/„ ZdS )2ÚQualityParametersHandlerz'Handle all quality parameter operationsc              	   C   sJ   || _ | dd¡| dd¡| dd¡| dd¡| d	d
¡dtddœ| _d S )NÚDB_HOSTz	127.0.0.1ÚDB_PORTiê  ÚDB_USERÚadminÚDB_PASSWORDzmcube@admin123ÚDB_NAMEÚvoicebot_clusterÚutf8mb4T)ÚhostÚportÚuserÚpasswordÚdatabaseÚcharsetÚcursorclassÚ
autocommit)ÚconfigÚgetr   Ú	db_config)Úselfr   © r   úE/home/aiteam/pcaa-dev/dashboard-backend/quality_parameters_handler.pyÚ__init__   s   




øz!QualityParametersHandler.__init__c              
   c   sx    d}z0zt jdi | j¤Ž}|V  W n t jy( } z	t d|› ¡ ‚ d}~ww W |r2| ¡  dS dS |r;| ¡  w w )z(Context manager for database connectionsNzDatabase connection error: r   )ÚpymysqlÚconnectr   ÚErrorÚloggerÚerrorÚclose)r   ÚconnÚer   r   r   Úget_connection    s    €
€þÿÿ
ÿz'QualityParametersHandler.get_connectionc                 C   sR   |   ¡ }| ¡ }d}| ||f¡ | ¡ }|W  d  ƒ S 1 s"w   Y  dS )z2Get all quality parameters for a specific businessz¦
                SELECT *
                FROM quality_parameters
                WHERE bid = %s
                ORDER BY parameter_group, parameter_name
            N©r$   ÚcursorÚexecuteÚfetchall©r   Úbidr"   r&   ÚqueryÚresultsr   r   r   Úget_parameters.   s   
$óz'QualityParametersHandler.get_parametersc                 C   s$   d  dd„ t| p	dƒ ¡  ¡ D ƒ¡S )NÚ c                 s   s    | ]	}|  ¡ r|V  qd S ©N)Úisalnum)Ú.0Úchr   r   r   Ú	<genexpr>A   s   € z=QualityParametersHandler._normalize_header.<locals>.<genexpr>)ÚjoinÚstrÚstripÚlower©Úvaluer   r   r   Ú_normalize_header?   s   $z*QualityParametersHandler._normalize_headerc                 C   s   | d u rdS t | ƒ ¡ S ©Nr.   )r5   r6   r8   r   r   r   Ú_clean_cellC   s   z$QualityParametersHandler._clean_cellc                 C   s*   t | tƒr| S t| pdƒ ¡  ¡ }|dv S )Nr.   >   Ú1ÚyÚyesÚtrueÚenabledÚ
applicable)Ú
isinstanceÚboolr5   r6   r7   )r9   Útextr   r   r   Ú_parse_boolI   s   
z$QualityParametersHandler._parse_boolNc              	   C   sB   t | pdƒ ¡ }|s|S ztt|ƒƒW S  ttfy    | Y S w r;   )r5   r6   ÚintÚfloatÚ	TypeErrorÚ
ValueError)r9   ÚdefaultrE   r   r   r   Ú
_parse_intP   s   ÿz#QualityParametersHandler._parse_intc              
      sô  t j t|pdƒ ¡ ¡d }|dkr{zddlm} W n ty+ } ztdƒ|‚d }~ww |t	 
|¡dd}|j}t|jdd	ƒ}|sDg S ‡fd
d„|d D ƒ‰ g }	|dd … D ]!‰ˆrft‡fdd„ˆD ƒƒsgqW|	 ‡ ‡fdd„ttˆ ƒƒD ƒ¡ qW|	S |dvrƒtdƒ‚z| d¡}
W n ty˜   | d¡}
Y nw d}|
d d… }zt ¡ j|dd}|j}W n7 tjyæ   |
 ¡ p½dgd }| d¡}| d¡}| d¡}||krÚ|dkrÚd}n
||krä|dkräd}Y nw tjt	 |
¡|d}‡fdd„|D ƒS )Nr.   é   z.xlsxr   )Úload_workbookz)openpyxl is required to upload XLSX filesT)Ú	data_only)Úvalues_onlyc                    s   g | ]}ˆ   |¡‘qS r   ©r<   ©r1   Úcell©r   r   r   Ú
<listcomp>f   s    z>QualityParametersHandler._read_upload_rows.<locals>.<listcomp>c                 3   ó    | ]}ˆ   |¡V  qd S r/   rQ   rR   rT   r   r   r3   i   ó   € z=QualityParametersHandler._read_upload_rows.<locals>.<genexpr>c                    s*   i | ]}ˆ | |t ˆƒk rˆ| nd “qS )r.   )Úlen)r1   Úidx)ÚheadersÚrowr   r   Ú
<dictcomp>k   s   * z>QualityParametersHandler._read_upload_rows.<locals>.<dictcomp>>   ú.csvr.   z%Only CSV and XLSX files are supportedz	utf-8-sigzlatin-1ú,i    z,;	|)Ú
delimitersú;ú	)Ú	delimiterc                    s.   g | ]}|rt ‡ fd d„| ¡ D ƒƒr|‘qS )c                 3   rV   r/   rQ   )r1   r9   rT   r   r   r3   „   rW   zHQualityParametersHandler._read_upload_rows.<locals>.<listcomp>.<genexpr>)ÚanyÚvalues©r1   r[   rT   r   r   rU   „   s   . )ÚosÚpathÚsplitextr5   r7   ÚopenpyxlrN   ÚImportErrorrJ   ÚioÚBytesIOÚactiveÚlistÚ	iter_rowsrc   ÚappendÚrangerX   ÚdecodeÚUnicodeDecodeErrorÚcsvÚSnifferÚsniffrb   r   Ú
splitlinesÚcountÚ
DictReaderÚStringIO)r   ÚfilenameÚcontentÚextrN   ÚexcÚworkbookÚsheetrd   ÚrowsrE   rb   ÚsampleÚdialectÚ
first_lineÚ
semicolonsÚcommasÚtabsÚreaderr   )rZ   r[   r   r   Ú_read_upload_rowsZ   sZ   
€ÿ$ÿ



€ø	z*QualityParametersHandler._read_upload_rowsr.   ©rK   c                G   s,   |D ]}|   |¡}||v r||   S q|S r/   )r:   )r   Únormalized_rowrK   ÚnamesÚnameÚkeyr   r   r   Ú_row_get†   s   
ÿz!QualityParametersHandler._row_getc                    sN  ‡ fdd„|  ¡ D ƒ}ˆ  |ddd¡}ˆ  |ddd¡}ˆ jˆ  |d	d
d¡d d}|r,|s.dS |d u s6|dk r8dS ˆ  |ddd¡}||ˆ j|ddddpLdˆ  |ddd¡ˆ  |ddd¡|ˆ  |dd¡|ˆ  ˆ  |dd¡¡ˆ  ˆ  |d d!¡¡ˆ  ˆ  |d"d#¡¡ˆ  ˆ  |d$d%¡¡ˆ  ˆ  |d&d'¡¡ˆ  ˆ  |d(d)¡¡ˆ j|d*d+d,dp¢d,d-œd fS ).Nc                    s"   i | ]\}}ˆ   |¡ˆ  |¡“qS r   )r:   r<   )r1   rŽ   r9   rT   r   r   r\   Ž   s   " z>QualityParametersHandler._row_to_parameter.<locals>.<dictcomp>zParameter GroupÚparameter_groupÚGroupzParameter NameÚparameter_nameÚNameÚScorez	Max ScoreÚ	max_scorerŠ   )Nz/Parameter Group and Parameter Name are requiredrM   )Nz%Score must be a number greater than 0z"When is this check not applicable?zNot Applicable ConditionÚapplicability_conditionzParameter TypeÚparameter_typeÚRequiredzWhat do you want to check on?zCheck DescriptionÚcheck_descriptionÚDescriptionzDetailed DescriptionÚdetailed_descriptionzSample UtterancesÚsample_utteranceszAuto Detect N/AÚauto_detect_nazDefault N/AÚ
default_nazApplicable Once Per CustomerÚapplicable_once_per_customerzApplicable ThresholdÚapplicable_thresholdÚFatalÚis_fatalzSubjective MarkingÚenable_subjective_markingÚStatusÚstatusÚ
Applicable)r   r’   r—   r™   r›   r•   rœ   r–   r   rž   rŸ   r    r¢   r£   r¥   )Úitemsr   rL   rF   )r   r[   Ú
normalizedr   r’   ÚscoreÚna_conditionr   rT   r   Ú_row_to_parameter   sJ   üüìëz*QualityParametersHandler._row_to_parameterc                 C   s²  t |ƒ ¡ }|stdƒ‚|  ||¡}|stdƒ‚d}d}d}g }|  ¡ ä}	|	 ¡ }
t|ddD ]Í\}}|  |¡\}}|rI|d7 }| ||dœ¡ q/|
 	d||d	 |d
 f¡ |
 
¡ }|r­|d |d< d}|
 	|| d¡| d¡| d¡| d¡| d¡| d¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡|d |f¡ |d7 }q/d}|
 	||| d	¡| d
¡| d¡| d¡| d¡| d¡| d¡| d¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡f¡ |d7 }q/|	 ¡  W d  ƒ n	1 sw   Y  ||||dd… dœ}|dkrW|dkrWd }|r3|d!|› d"7 }|rL|d#|d d$ › d%|d d& › 7 }t|ƒ‚|rS|d'7 }t|ƒ‚|S )(zJImport quality parameters from a CSV/XLSX upload and upsert by group/name.zUploaded file is emptyz(No parameter rows found in uploaded filer   é   )ÚstartrM   )r[   r    zÏ
                    SELECT id
                    FROM quality_parameters
                    WHERE bid = %s AND parameter_group = %s AND parameter_name = %s
                    LIMIT 1
                    r   r’   Úida_  
                        UPDATE quality_parameters
                        SET
                            parameter_type = %s,
                            check_description = %s,
                            detailed_description = %s,
                            max_score = %s,
                            sample_utterances = %s,
                            applicability_condition = %s,
                            auto_detect_na = %s,
                            default_na = %s,
                            applicable_once_per_customer = %s,
                            applicable_threshold = %s,
                            is_fatal = %s,
                            enable_subjective_marking = %s,
                            status = %s,
                            updated_at = NOW()
                        WHERE id = %s AND bid = %s
                    r—   r™   r›   r•   rœ   r–   r   Frž   rŸ   r    r¢   r£   r¥   r¦   á  
                    INSERT INTO quality_parameters
                    (bid, parameter_group, parameter_name, parameter_type, check_description,
                     detailed_description, max_score, sample_utterances, applicability_condition,
                     auto_detect_na, default_na, applicable_once_per_customer, applicable_threshold,
                     is_fatal, enable_subjective_marking, status)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
                Né   )ÚinsertedÚupdatedÚskippedÚerrorszNo rows were imported.ú z row(s) had errors.z Row r[   z: r    zx Check that the file uses comma or semicolon separators and includes Parameter Group, Parameter Name, and Score columns.)r5   r6   rJ   r‰   r$   r&   Ú	enumerater«   rp   r'   Úfetchoner   Úcommit)r   r*   r{   r|   r   r±   r²   r³   r´   r"   r&   Úindexr[   Úparameter_datar    Úexistingr+   ÚresultÚdetailr   r   r   Úimport_parameters_file¶   s¦   
ù	





ñ





ð

§\
ü$þz/QualityParametersHandler.import_parameters_filec                 C   s@   |   ¡ }| ¡ }| d¡ W d  ƒ dS 1 sw   Y  dS )z7Create storage for reusable system parameter templates.as  
                CREATE TABLE IF NOT EXISTS quality_parameter_templates (
                  id INT AUTO_INCREMENT PRIMARY KEY,
                  template_key VARCHAR(100) NOT NULL DEFAULT 'default',
                  parameter_group VARCHAR(255) NOT NULL,
                  parameter_name VARCHAR(255) NOT NULL,
                  parameter_type VARCHAR(100),
                  check_description TEXT,
                  detailed_description TEXT,
                  max_score INT NOT NULL,
                  sample_utterances TEXT,
                  applicability_condition VARCHAR(255),
                  auto_detect_na BOOLEAN DEFAULT FALSE,
                  default_na BOOLEAN DEFAULT FALSE,
                  applicable_once_per_customer BOOLEAN DEFAULT FALSE,
                  applicable_threshold INT,
                  is_fatal BOOLEAN DEFAULT FALSE,
                  enable_subjective_marking BOOLEAN DEFAULT FALSE,
                  status VARCHAR(50) DEFAULT 'Applicable',
                  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
                  updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                  INDEX idx_template_key (template_key),
                  UNIQUE KEY unique_template_param (template_key, parameter_group, parameter_name)
                ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
            N)r$   r&   r'   )r   r"   r&   r   r   r   Úensure_template_table1  s   
"þz.QualityParametersHandler.ensure_template_tablerK   c           	      C   sÐ   |   ¡  t|pdƒ}|  ¡ }| ¡ }| d|f¡ | ¡ }W d  ƒ n1 s(w   Y  |sf|rf|  t|ƒ¡}|rf|D ]$}t|ƒ}| dd¡ | dd¡ | dd¡ | dd¡ |  	||¡ q<|  
|¡S |S )zOGet reusable template parameters, optionally seeding from an existing BID once.rK   z¼
                SELECT *
                FROM quality_parameter_templates
                WHERE template_key = %s
                ORDER BY parameter_group, parameter_name
                Nr®   r*   Ú
created_atÚ
updated_at)r¿   r5   r$   r&   r'   r(   r-   ÚdictÚpopÚsave_template_parameterÚget_template_parameters)	r   Útemplate_keyÚseed_from_bidr"   r&   r,   ÚsourceÚparamÚitemr   r   r   rÅ   O  s,   
ù
	õ
z0QualityParametersHandler.get_template_parametersc                 C   s¦  |   ¡  t|pdƒ}|  ¡ »}| ¡ }d|v rt|d rtd}| || d¡| d¡| d¡| d¡| d¡| d	¡| d
¡| d¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡|d |f¡ |d W  d  ƒ S d}| ||| d¡| d¡| d¡| d¡| d¡| d	¡| d
¡| d¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡f¡ |jW  d  ƒ S 1 sÌw   Y  dS )z-Save or update a reusable template parameter.rK   r®   a„  
                    UPDATE quality_parameter_templates
                    SET
                        parameter_group = %s,
                        parameter_name = %s,
                        parameter_type = %s,
                        check_description = %s,
                        detailed_description = %s,
                        max_score = %s,
                        sample_utterances = %s,
                        applicability_condition = %s,
                        auto_detect_na = %s,
                        default_na = %s,
                        applicable_once_per_customer = %s,
                        applicable_threshold = %s,
                        is_fatal = %s,
                        enable_subjective_marking = %s,
                        status = %s,
                        updated_at = NOW()
                    WHERE id = %s AND template_key = %s
                r   r’   r—   r™   r›   r•   rœ   r–   r   Frž   rŸ   r    r¢   r£   r¥   r¦   Naý  
                INSERT INTO quality_parameter_templates
                (template_key, parameter_group, parameter_name, parameter_type, check_description,
                 detailed_description, max_score, sample_utterances, applicability_condition,
                 auto_detect_na, default_na, applicable_once_per_customer, applicable_threshold,
                 is_fatal, enable_subjective_marking, status)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            )r¿   r5   r$   r&   r'   r   Ú	lastrowid)r   rÆ   rº   r"   r&   r+   r   r   r   rÄ   n  s`   






ïÔ.





ð$¸z0QualityParametersHandler.save_template_parameterc                 C   s^   |   ¡  |  ¡ }| ¡ }| dt|pdƒ|f¡ |jdkW  d  ƒ S 1 s(w   Y  dS )z%Delete a reusable template parameter.z}
                DELETE FROM quality_parameter_templates
                WHERE template_key = %s AND id = %s
                rK   r   N)r¿   r$   r&   r'   r5   Úrowcount)r   rÆ   Úparameter_idr"   r&   r   r   r   Údelete_template_parameter¼  s   
û$÷z2QualityParametersHandler.delete_template_parameterc                 C   óT   |   ¡ }| ¡ }d}| |||f¡ | ¡ }|W  d  ƒ S 1 s#w   Y  dS )z&Get a specific quality parameter by IDzy
                SELECT *
                FROM quality_parameters
                WHERE bid = %s AND id = %s
            N©r$   r&   r'   r·   )r   r*   rÍ   r"   r&   r+   r¼   r   r   r   Úget_parameter_by_idÊ  s   
$ôz,QualityParametersHandler.get_parameter_by_idc                 C   s’  |   ¡ »}| ¡ }d|v rj|d rjd}| || d¡| d¡| d¡| d¡| d¡| d¡| d	¡| d
¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡|d |f¡ |d W  d  ƒ S d}| ||| d¡| d¡| d¡| d¡| d¡| d¡| d	¡| d
¡| dd¡| dd¡| dd¡| d¡| dd¡| dd¡| dd¡f¡ |jW  d  ƒ S 1 sÂw   Y  dS )z"Save or update a quality parameterr®   ar  
                    UPDATE quality_parameters
                    SET
                        parameter_group = %s,
                        parameter_name = %s,
                        parameter_type = %s,
                        check_description = %s,
                        detailed_description = %s,
                        max_score = %s,
                        sample_utterances = %s,
                        applicability_condition = %s,
                        auto_detect_na = %s,
                        default_na = %s,
                        applicable_once_per_customer = %s,
                        applicable_threshold = %s,
                        is_fatal = %s,
                        enable_subjective_marking = %s,
                        status = %s,
                        updated_at = NOW()
                    WHERE id = %s AND bid = %s
                r   r’   r—   r™   r›   r•   rœ   r–   r   Frž   rŸ   r    r¢   r£   r¥   r¦   Nr¯   )r$   r&   r'   r   rË   )r   r*   rº   r"   r&   r+   r   r   r   Úsave_parameterÚ  s\   






ïÐ4	





ð$°z'QualityParametersHandler.save_parameterc                 C   sR   |   ¡ }| ¡ }d}| |||f¡ |jdkW  d  ƒ S 1 s"w   Y  dS )zDelete a quality parameterzg
                DELETE FROM quality_parameters
                WHERE bid = %s AND id = %s
            r   N)r$   r&   r'   rÌ   )r   r*   rÍ   r"   r&   r+   r   r   r   Údelete_parameter.  s   
$öz)QualityParametersHandler.delete_parameterc                 C   sf   |   ¡ %}| ¡ }d}| ||f¡ | ¡ }|r |d r |d ndW  d  ƒ S 1 s,w   Y  dS )z1Calculate total possible score for all parametersz 
                SELECT SUM(max_score) as total_score
                FROM quality_parameters
                WHERE bid = %s AND default_na = FALSE
            Útotal_scorer   NrÐ   )r   r*   r"   r&   r+   r¼   r   r   r   Úcalculate_total_possible_score<  s   
$ôz7QualityParametersHandler.calculate_total_possible_scorec                 C   rÏ   )z'Get all parameters for a specific groupz®
                SELECT *
                FROM quality_parameters
                WHERE bid = %s AND parameter_group = %s
                ORDER BY parameter_name
            Nr%   )r   r*   r   r"   r&   r+   r,   r   r   r   Úget_parameters_by_groupL  s   
$óz0QualityParametersHandler.get_parameters_by_groupc                 C   s\   |   ¡  }| ¡ }d}| ||f¡ | ¡ }dd„ |D ƒW  d  ƒ S 1 s'w   Y  dS )z/Get list of all parameter groups for a businessz­
                SELECT DISTINCT parameter_group
                FROM quality_parameters
                WHERE bid = %s
                ORDER BY parameter_group
            c                 S   s   g | ]}|d  ‘qS )r   r   re   r   r   r   rU   l  s    zAQualityParametersHandler.get_parameter_groups.<locals>.<listcomp>Nr%   r)   r   r   r   Úget_parameter_groups]  s   
$óz-QualityParametersHandler.get_parameter_groupsr/   )rK   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r$   r-   Ústaticmethodr:   r<   rF   rL   r‰   r   r«   r¾   r¿   rÅ   rÄ   rÎ   rÑ   rÒ   rÓ   rÕ   rÖ   r×   r   r   r   r   r      s8    



	,){
NTr   )rÛ   r   Úpymysql.cursorsr   Úloggingrt   rk   rf   Ú
contextlibr   Ú	getLoggerrØ   r   r   r   r   r   r   Ú<module>   s    
