
    Xj6                     r    d dl m Z mZ d dlmZ d dlmZmZ d dlmZm	Z	m
Z
mZ  G d dej                        Zy)    )datetimetime)relativedelta)timezoneutc)_apifieldsmodelsc                   `    e Zd ZdZdgZ ej                  ddgdddd      Z ej                  d	d
      Z	 ej                  dddd      Z ej                  dd      Z ej                  d      d        Zd Zej$                   fd       Zd Zd Zd Zej.                  d        Z xZS )ResourceCalendarLeaveszresource.calendar.leaves)publicPublic)companyCompanyTyper   Tz4Mirrors XENHR's Holiday.type field (public/company).)stringdefaultindexhelpDescriptionzPMirrors XENHR's Holiday.description field (Thai annotation for public holidays).)r   r   Date_compute_xeno_date_inverse_xeno_datezSingle-day shortcut used by the Add Holiday quick-create dialog: writing it spans date_from/date_to over that whole day, matching the storage convention of the imported holiday rows (00:00:00 - 23:59:59).)r   computeinverser   z%Recurring yearly (same day each year)zMirrors XENHR's recurring-holiday flag. Next year's copy is created immediately on save, and a scheduled action keeps rolling each further year forward.	date_fromc                 l    | D ]/  }|j                   r|j                   j                         nd|_        1 y )NF)r   date	xeno_date)selfleaves     M/home/susu/odoo-hr-migration/xeno_holidays/models/resource_calendar_leaves.pyr   z)ResourceCalendarLeaves._compute_xeno_date&   s/     	SE8=eoo224UEO	S    c                 2   | D ]  }|j                   s| j                  j                  j                  d      xsh | j                  j                  j
                  xsF |j                  j
                  xs. | j                  j                  j                  j
                  xs d}t        |      }|j                  t        j                  |j                   t        j                              }|j                  t               j#                  d       |_         y )NtzUTC)tzinfo)r    envcontextgetuserr&   calendar_idr   resource_calendar_idr   localizer   combiner   min
astimezoner   replacer   )r!   r"   tz_namer&   
local_froms        r#   r   z)ResourceCalendarLeaves._inverse_xeno_date+   s      	RE((**..t4 a8H8H a((++a/3xx/?/?/T/T/W/Wa[` g&[[)9)9%//488)TU
","7"7"<"D"DD"D"Q	Rr$   c                     t         |   |      }| j                  j                  j	                  d      s |j                          |j                          |S )Nxeno_skip_recur)supercreater)   r*   r+   _xeno_ensure_next_year_copy!_xeno_auto_deduct_company_holiday)r!   	vals_listleaves	__class__s      r#   r9   zResourceCalendarLeaves.createD   sI    	* xx##$56..0446r$   c                    | j                   j                  j                  d      xsh | j                   j                  j                  xsF | j
                  j                  xs. | j                   j                  j                  j                  xs d}t        j                  |      j                  t        |            j                         S )zConvert a UTC-stored date_from/date_to datetime to the plain
        local calendar day it actually represents -- same tz resolution
        _inverse_xeno_date uses, just the reverse direction.r&   r'   )r)   r*   r+   r,   r&   r-   r   r.   r   r/   r2   r   r   )r!   dtr4   s      r#   _xeno_local_dayz&ResourceCalendarLeaves._xeno_local_dayN   s     ((""&&t, X0@0@ X""X&*hh&6&6&K&K&N&NXRW 	||B**8G+<=BBDDr$   c           
         | j                   d   j                         }| j                   d   j                         }| j                   d   j                         }|j                         j                  }| D ]  }|j                  dk7  s|j
                  s|j                  s+| j                  |j                        }|j                  r| j                  |j                        n|}|j                  dd|j                  dd|fdg      j                  d	      j                  fg      }|j                  |||t        d
|j                                y)aJ  Company holiday policy (per susu, not Odoo's stock assumption):
        a declared Company Holiday isn't automatically paid time off -- HR
        deducts a real leave day for every employee who already has leave
        allocated, cascading Annual -> Personal -> Unpaid (see hr.leave's
        _xeno_deduct_for_company_holiday, shared with the manual
        wizard/leave_holiday_deduct.py). Only for genuinely new, company-
        wide (no resource_id) "company"-type holidays -- a "public" holiday
        keeps Odoo's normal paid-non-working-day behavior, and auto-
        generated next-year recurring copies are skipped by the
        xeno_skip_recur guard in create() above (deducting against a year
        that doesn't have allocations yet would just fall through to
        Unpaid Leave for everyone, which isn't useful).
        zhr.leavezhr.employeezhr.leave.allocationr   idinholiday_status_id)state=validateemployee_idzCompany holiday deduction: %s)reasonN)r)   sudo"_xeno_holiday_deduct_cascade_typesidsxeno_holiday_typeresource_idr   rA   date_tosearchmapped _xeno_deduct_for_company_holidayr   name)	r!   LeaveEmployeeAlloccascade_type_idsr"   r   rP   	employeess	            r#   r;   z8ResourceCalendarLeaves._xeno_auto_deduct_company_holidayV   s7    $))+88M*//1./446 CCEII 	E&&)3u7H7HPUP_P_,,U__=I=B]]d**5==9PYG tU\\($0@A.+  6-(.) I 229g8%**E 3 	r$   c                    | j                  d       D ]3  }|j                  t        d      z   }|j                  xs |j                  t        d      z   }| j	                  d      j                  dd|j                  fdd|j                  j                  fd	d|j                  j                  fd
ddt        j                  |j                         t        j                        fddt        j                  |j                         t        j                        fg      }|r|j	                  d      j!                  ||d       6 y)zFor each recurring holiday, make sure the same holiday exists
        one year later (same day/month). Idempotent: matched by name +
        company + calendar within the target day.c                 T    | j                   xr | j                  xr | j                   S )N)xeno_recurring_yearlyr   rO   )ls    r#   <lambda>zDResourceCalendarLeaves._xeno_ensure_next_year_copy.<locals>.<lambda>}   s)    !11 &akk &% r$      yearsF)active_testrT   rG   
company_idr-   rO   rG   Fr   >=z<=T)r7   )r   rP   N)filteredr   r   rP   with_contextsearch_countrT   rc   rC   r-   r   r0   r   r   r1   maxcopy)r!   r"   nxt_fromnxt_toexistss        r#   r:   z2ResourceCalendarLeaves._xeno_ensure_next_year_copyx   s!    ]]&' 	E Q)??Hmm6u-a:PPF&&5&9FFejj)sE$4$4$7$78U%6%6%9%9:+dH$4$4X]]_dhh$OPdH$4$4X]]_dhh$OPH F ""4"8==!)%? 	r$   c                     t         j                  j                         t        d      z
  }| j	                  dddd|fg      j                          y)a
  Monthly, idempotent: every recurring holiday dated within the
        last year gets its next-year copy ensured, so the chain keeps
        rolling one year ahead even if a copy was deleted or the server
        was down when a create-time copy should have happened.r_   r`   )r\   rG   Trd   r   re   N)r
   Datetimenowr   rQ   r:   )r!   cutoffs     r#   _cron_xeno_recur_holidaysz0ResourceCalendarLeaves._cron_xeno_recur_holidays   sL     $$&Q)??0'$'
 	 '&(r$   )__name__
__module____qualname___name_inheritr
   	SelectionrN   Textxeno_remarkr   r    Booleanr\   r	   dependsr   r   model_create_multir9   rA   r;   r:   modelrr   __classcell__)r>   s   @r#   r   r   	   s    &E*+H(((	56xtC
 &++6K
 $.B3I +FNN62 S[[S SR2 	 E D. 	YY
) 
)r$   r   N)r   r   dateutil.relativedeltar   pytzr   r   odoor   r	   r
   r   Modelr    r$   r#   <module>r      s&    # 0  ' 'Q)V\\ Q)r$   