o
    B_i@.                     @  s  d dl mZ d dlmZ d dlmZ d dlmZmZm	Z	 d dl
mZmZ ddlmZ ddlmZmZ dd	lmZ ed
dG dd dZd<ddZd=ddZd=ddZd>ddZd?d!d"Zd@d%d&ZdAd'd(ZdBd+d,ZdCd-d.Zd=d/d0ZdDd2d3ZdCd4d5Z d6d7dEd:d;Z!d6S )F    )annotations)	dataclass)Path)ListOptionalTuple)PageLocator   )shot)log_steppause)$handle_terminate_sessions_if_presentT)frozenc                   @  sB   e Zd ZU ded< ded< dZded< dZded< d	Zded
< dS )
NewRowSpecstrhoursoverheadNzOptional[str]noteNTworktype_labelADMINtracking_label)__name__
__module____qualname____annotations__r   r   r    r   r   \/var/www/html/flask_server/apps/aroflo_connector_app/ui_automation/flows/timesheet_create.pyr      s   
 r   pager   run_dirr   returnNonec                 C  s6   zt | |r| d W d S W d S  ty   Y d S w )Ni  )r   wait_for_timeout	Exception)r   r    r   r   r   _close_session_limit_if_any   s   
r%   c                 C  s   | j ddd d S )Na  () => {
            const u = location.href.toLowerCase();
            if (!u.includes('timesheet')) return false;
            const t = document.body && (document.body.innerText || '');
            return t.includes('Daily Timesheet') || t.includes('Timesheet for');
        }iȯ  timeout)wait_for_functionr   r   r   r   _wait_timesheet_ready#   s   
r*   c              	   C  s|   | j ddd| d| d| d| dg}|D ]}z| dkr%W q|jjd	d
d W  d S  ty9   Y qw td)NbuttonSavenamezbutton:has-text('Save')z"input[type='button'][value='Save']z"input[type='submit'][value='Save']z-input.af-add-timesheet-form-btn[value='Save']r   X  Tr'   forcez Save button not found/clickable.)get_by_rolelocatorcountfirstclickr$   RuntimeError)r   
candidatescr   r   r   _click_save/   s    r:   nintr	   c                 C  s6   |  d| }| dkrtd| |j dS )Ninput#NTnewr   u,   No encuentro input de creación: input#NTnewz.xpath=ancestor::tr[contains(@class,'taskRow')])r3   r4   r7   r5   )r   r;   ntr   r   r   _get_new_rowC   s   r?   row)Tuple[Locator, Locator, Locator, Locator]c                 C  s   |  d| j}|  dj}|  d| dj}| dkr%|  dj}|  d| dj}| dkr;|  dj}||||fS )	Nr=   input.schOverheadztextarea[name="note"]r   ztextarea.descriptionzselect[name="newworktypezselect.worktyper3   r5   r4   )r@   r;   hrsoverhead_inpr   type_selr   r   r   _get_new_row_fieldsK   s   rH   overhead_textr   c                 C  s  | dj}| dkrtd| dj}| dkr"| dj}| dkr,td|jdd |  d	j}|jd
dd |jddd | dj}|jdd |  || |d | d | dj}|jdd | dj	|dj}| dkr| dj	|
dd dj}| dkrtd| d|  | d | dj}	|	 dkr| dj}	|	jdd |jddd z
|jddpd}
W n ty   d}
Y nw | |
 vrtd | d!|
 d"d#S )$ug  
    Overhead se asigna SIEMPRE vía el diálogo jqGrid (lupa):
    1) Click lupa (dentro del row).
    2) Espera dialog #dialog_search_overheads.
    3) Escribe en #gs_overhead.
    4) Click en la fila que matchee el overhead.
    5) Click "Select Overhead" (#btnSelect).
    6) Verifica que el input.schOverhead de la fila quedó con el valor esperado.
    rB   r   z*No encuentro input.schOverhead en la fila.zAdiv.imsSearchBox__wrapper:has(input.schOverhead) div#btnAdvSearchz$input.schOverhead + div#btnAdvSearchzMNo encuentro la lupa de Overhead (btnAdvSearch asociado a input.schOverhead).T)r1   z#dialog_search_overheadsattachedr/   )stater'   visiblezinput#gs_overheadi  r&   Enteri^  ztable[id^='tblSearchBox']i  z+tr.jqgrow td[aria-describedby$='_overhead'])has_text zNo encuentro overhead 'u   ' en el grid del diálogo.   z
#btnSelectztext=Select Overheadhidden   u'   Overhead no quedó aplicado. Esperaba 'u   ', quedó 'z'.N)r3   r5   r4   r7   r6   wait_forfillpressr#   filtersplitinput_valuer$   lower)r   r@   rI   inp
search_btndialogqgridcell
btn_select	final_valr   r   r   _set_overhead_new`   s\   



rc   c                 C  s0   |  d| dj}| dkr|  dj}|S )Nz#select[name="new_tracking_centre_idrC   r   zselect.tracking-centrerD   )r@   r;   selr   r   r   _get_tracking_select   s   re   r3   boolc                 C  sL   z|  d}|dv r| jdd}|pd dkW S W dS  ty%   Y dS w )Nzel => el.tagName.toLowerCase())inputtextarea  r&   rS   T)evaluaterY   stripr$   )r3   tagvr   r   r   	_is_empty   s   
rn   c                 C  s   t | |}t||\}}}}t|std| d| r*t|s*td| d| rPz|jddp6d }|rCtd| dW d S  tyO   Y d S w d S )NFila newu)    no está vacía: Hrs/Qty ya tiene valor.u*    no está vacía: Overhead ya tiene valor.ri   r&   rS   u&    no está vacía: Note ya tiene valor.)r?   rH   rn   r7   r4   rY   rk   r$   )r   r;   r@   rE   rF   r   	_type_selrm   r   r   r   _assert_new_row_empty   s    
rq   c                 C  s0   |  d | jd | jd |  d d S )N   	ArrowDownrM   )r#   keyboardrV   r)   r   r   r   _select_autocomplete_first   s   
ru   specc           	      C  s  t | |}t||\}}}}t||}|  |d |jt|jdd t| ||j	 |j
rH| dkr>td| d|  ||j
 | rdz|j|jd |d W n	 tyc   Y nw | rz|j|jd |d W d S  ty   Y d S w d S )	NrS      )delayr   ro   z : No encuentro textarea de note.)labelchange)r?   rH   re   r6   rU   typer   r   rc   r   r   r4   r7   select_optionr   dispatch_eventr$   r   )	r   r;   rv   r@   rE   rF   r   rG   tracking_selr   r   r   _fill_new_row   s6   


r   c              
     s   d fdd}||rdS  j dd	d
 j ddd
 d d d dg}tdD ]7}||r8 dS d}|D ]%}z| dkrGW q<|jjddd  d d}W  n	 tya   Y q<w |sf nq/||svtd| d| ddS )u   
    Asegura que existan inputs NTnew1..NTnewN.
    Si AroFlo sólo muestra 1 fila, normalmente hay un botón tipo "Add Row" / "Add".
    Ajusta los selectores de acuerdo al DOM real cuando lo veas en screenshots.
    ir<   r!   rf   c                   s     d|   dkS )Nr=   r   )r3   r4   )r   r)   r   r   exists  s   z&_ensure_new_rows_exist.<locals>.existsNr+   Addr-   zAdd Rowzbutton:has-text('Add')za:has-text('Add')z"input[type='button'][value*='Add']zbutton#afAddTimesheetRow
   Fr   i  Tr0      z!No pude asegurar filas new hasta z. No existe input#NTnew.)r   r<   r!   rf   )	r2   r3   ranger4   r5   r6   r#   r$   r7   )r   r;   r   add_candidates_clickedr9   r   r)   r   _ensure_new_rows_exist  s>   	
r   N)rowsr   Optional[List[NewRowSpec]]c                C  s  t | | t|  t| t| |du r+tdddddtddd	ddtd
ddddg}t| |d td|  t|d t|ddD ]\}}t	| | t
| || qAt| |d td|  t|d t|  | d t | | t| |d td|  t|d dS )u   
    SOLO CREATE:
    - Solo escribe en filas newX (NTnew1, NTnew2, ...)
    - Requiere que la fila esté vacía
    - No toca filas existentes (IDs numéricos)
    N5zAdmin Dutiesr   r   )r   r   r   r   z0.5zLunch Break - UnpaidzLunch Break2zts-create-01-readyz$Timesheet ready (before create fill)   )startzts-create-02-filledzFilled new rows (before save)rR   zts-create-03-after-savez
After save)r%   r*   r   lenr   r   r   r   	enumeraterq   r   r:   r#   )r   cfgr    r   idxrv   r   r   r   run7  s.   








r   )r   r   r    r   r!   r"   )r   r   r!   r"   )r   r   r;   r<   r!   r	   )r@   r	   r;   r<   r!   rA   )r   r   r@   r	   rI   r   r!   r"   )r@   r	   r;   r<   r!   r	   )r3   r	   r!   rf   )r   r   r;   r<   r!   r"   )r   r   r;   r<   rv   r   r!   r"   )r   r   r    r   r   r   r!   r"   )"
__future__r   dataclassesr   pathlibr   typingr   r   r   playwright.sync_apir   r	   core.artifactsr   core.logr   r   auth.post_loginr   r   r%   r*   r:   r?   rH   rc   re   rn   rq   ru   r   r   r   r   r   r   r   <module>   s.   






U




',