
    ,}Pjt                     ~    d Z ddlZddlmZmZ ddlmZmZ  ej                  e	      Z
 G d dej                        Zy)aI  Log approved Odoo leave into SAP B1 as an employee absence record.

B1 has no leave-request/approval workflow (no such entities in the Service
Layer) and only a flat absence log (EmployeeAbsenceInfoLines: FromDate, ToDate,
Reason, ApprovedBy). So Odoo owns the workflow (request + approval + per-type
balances) and, on approval, writes the result into B1 so B1 holds the
authoritative absence log for whoever uses it (payroll/accounting).

Push is best-effort: a B1 outage never blocks the Odoo approval. Unsynced
approved leaves are retried by a cron.

Note: write() fires this on ANY code path that sets state='validate' --
normal approval, HR force-approve, a bulk edit, a future feature, an
import. There's no separate opt-in per caller, which is exactly why the
production-write guard below has to live here rather than in each caller.
    N)fieldsmodels   )SAPB1Clientcheck_production_write_allowedc                   ^     e Zd ZdZ ej
                  ddd      Z fdZd Zd Z	d	 Z
 xZS )
HrLeavezhr.leavezLogged to SAP B1TF)stringreadonlycopyc                     t         |   |      }|j                  d      dk(  r | j                  d       j	                          |S )Nstatevalidatec                     | j                    S )N)b1_absence_syncedls    u/tmp/claude-1003/-home-susu/da238cdb-39ed-486c-99e2-9f5ca01dda37/scratchpad/xeno_sapb1_sync_deploy/models/hr_leave.py<lambda>zHrLeave.write.<locals>.<lambda>"   s    (;(;$;     )superwritegetfiltered_push_absence_to_b1)selfvalsres	__class__s      r   r   zHrLeave.write   s=    gmD!88G
*MM;<PPR
r   c                 f   | j                  d       }|syt        | j                  d      sy	 t        j                  | j                        }	 |5 }|D ]7  }	 |j                  |       t        j                  j                         |_        9 	 ddd       y# t
        $ r }t        j                  d|       Y d}~yd}~ww xY w# t
        $ r+}t        j                  d|j                  |       Y d}~d}~ww xY w# 1 sw Y   yxY w# t
        $ r }t        j                  d|       Y d}~yd}~ww xY w)zAAppend an absence line to each employee's B1 record. Best-effort.c                 n    | j                   dk(  xr% | j                  j                  xr | j                   S )Nr   )r   employee_idb1_employee_idr   r   s    r   r   z-HrLeave._push_absence_to_b1.<locals>.<lambda>(   s5    agg+ (,,(''' r   NT)softzB1 absence push skipped: %sz'B1 absence push failed for leave %s: %sz%B1 absence push connection failed: %s)r   r   envr   from_env	Exception_loggerwarning_push_one_absencer   Datetimenowr   	exceptionid)r   pushableclientexcb1leaves         r   r   zHrLeave._push_absence_to_b1%   s   ==(

 -dhhTB	 ))$((3F	J 2% E//328//2E2E2G/ 	  	OO93?	 % ))EuxxQT    	JOOCSII	Jsw   B D C;4CC;D 	C!B<<C	C8!C3.C;3C88C;;D D D 	D0D++D0c                    | j                          | j                  j                  }| j                  j                  xs  | j
                  j                  j                  }| j                  j                  xs d}| j                  r| d| j                   }| j                   d| j                   d|d d |xs dd d d}|j                  d| dd	d
i      }|xs i j                  d
g       xs g }|D 	cg c]"  }dD 	ci c]  }	|	|j                  |	       c}	$ }
}}	|j                  d| dd
|
|gz   i       y c c}	w c c}	}w )NLeavez: z
T00:00:00Zd    )FromDateToDateReason
ApprovedByzEmployeesInfo()z$selectEmployeeAbsenceInfoLines)params)json)
ensure_oner"   r#   first_approver_idnamer%   userholiday_status_idrequest_date_fromrequest_date_tor   patch)r   r2   bidapproverreasonlinecurexistinglnkcleans              r   r*   zHrLeave._push_one_absenceB   sf   --))..D$((--2D2D'',,799xr$))-F112*=--.j9Tcl#>r4C0	
 ffSE#Y8R,S  
 I2??#=rBHb 
 $RRaQq	\R
 
 	SE#,etfn= 	 	
 S
s   9	EEEEc                 P    | j                  g d      }|r|j                          yy)z+Retry approved leaves not yet logged to B1.))r   =r   )r   rR   F)zemployee_id.b1_employee_idz!=FN)searchr   )r   pendings     r   _cron_push_absenceszHrLeave._cron_push_absences]   s+    ++ 
 
 '') r   )__name__
__module____qualname___inheritr   r+   r   r   r   r*   rU   __classcell__)r   s   @r   r	   r	      s4    H'/ADW\]J:
6*r   r	   )__doc__loggingodoor   r   sapb1_clientr   r   	getLoggerrV   r(   Modelr	    r   r   <module>rb      s9       E
'

H
%K*fll K*r   