
    {jG                         d dl Z d dlZd dlZd dlmZmZ d dlmZmZ d dl	m
Z
  ej                  e      Z ej                  d      Z G d dej                         Zy)    N)_http)AccessError	UserError)requestz^([01]\d|2[0-3]):[0-5]\d$c                   8   e Zd Zd Zd Zd Zd Zd Z ej                  dddd	d	d	
      	 	 d+d       Z
 ej                  dddd	d	d	
      	 	 d+d       Z ej                  ddd      d,d       Zd Zd Z ej                  dddd	d	d	
      d-d       Z ej                  dddd	d	d	
      d-d       Zd Z ej                  ddd      d        Z ej                  ddd      d-d       Z ej                  ddd      d        Z ej                  d dd      d!        Z ej                  d"dd      d#        Z ej                  d$d%d      d-d&       Z ej                  d'ddd	d	d	
      d.d(       Z ej                  d)ddd	d	d	
      d.d*       Zy)/XenoAttendanceControllerc                 ~    t         j                  j                  }|j                  d      xs |j                  d      S )N)hr_attendance.group_hr_attendance_officerzhr.group_hr_userr   envuser	has_group)selfr   s     #xeno_attendance/controllers/main.py_has_accessz$XenoAttendanceController._has_access   s7    {{ JK 6>>"45	7    c                 T    t         j                  j                  j                  d      S )Nr   r   r   s    r   	_can_editz"XenoAttendanceController._can_edit   s      {{))*UVVr   c                     t         j                  d   j                         j                  t         j                  j                        S )Nzxeno.attendance.viewer)r   r   sudoget_team_codesr   r   s    r   _team_codesz$XenoAttendanceController._team_codes   s5    {{3499;JJKK 	r   c                 L    t        j                  dt        d      z  dgd      S )Nu?   <h3 style='font-family:sans-serif;padding:2rem'>403 — %s</h3>z&HR access required to view attendance.Content-Typeztext/html; charset=utf-8i  )headersstatus)r   make_responser   r   s    r   
_forbiddenz#XenoAttendanceController._forbidden"   s/    $$M89:AB	
 	
r   c                 Z   t         j                  j                         }	 |rt        |      n|j                  }	 |rt        |      n|j                  }|t        t        |d      d      fS # t
        t        f$ r |j                  }Y Ow xY w# t
        t        f$ r |j                  }Y Vw xY w)N      )
datetimedatetodayintyear	TypeError
ValueErrormonthminmax)r   r)   r,   r'   s       r   _parse_year_monthz*XenoAttendanceController._parse_year_month*   s    ##%	 $3t9%**D	 "'CJU[[E SUA+++ :& 	::D	 :& 	 KKE	 s"   A+ B +B	B	B*)B*z/odoo/attendances/bymonthr   r   F)typeauthwebsitesitemapcsrfNc                 X   | j                         s| j                         S | j                  ||      \  }}t        j                  d   j                         }|j                  |||      }		 |j                  |||xs d |	| j                         |xs d |xs d |xs d       }
t        j                  |
d
g      S # t        $ rf}t        j                  d       dt        d      dt        d      dt        j                  d   j                  t        |            d	}
Y d }~d }~ww xY w)Nxeno.attendance.report)restrict_codescan_editdepartment_idcategory_idjob_idz attendance bymonth render failedzC<div style='font-family:sans-serif;padding:2rem;color:#b21f22'><h3>zAttendance report unavailablez</h3><p>z)Could not build the report from HRSystem.z1</p><pre style='white-space:pre-wrap;color:#555'>z</pre></div>r   r   )r   r!   r/   r   r   r   xeno_codes_for_filtersrender_htmlr   	Exception_logger	exceptionr   _escstrr    )r   r)   r,   employee
departmentgrouppositionkwReportfilter_codeshtmlexcs               r   bymonthz XenoAttendanceController.bymonth6   s     !??$$,,T59e56;;=44ZQ	%%eX-l)(0Demt'4	 & D& $$GH
 	
  	@A 56ABKK 89>>s3xH 	s   +7B: :	D)AD$$D)z /odoo/attendances/bymonth/exportc                    | j                         s| j                         S | j                  ||      \  }}t        j                  d   j                         }|j                  |||      }		 |j                  |||xs d |	      }
d||fz  }t        j                  |
dd	d
|z  fg      S # t        $ r8 t        j                  d       t        j                  t        d      d      cY S w xY w)Nr6   r7   z attendance bymonth export failed$   Export failed — check server logs.  r   zattendance_%04d_%02d.xlsxr   zAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetContent-Dispositionattachment; filename="%s"r<   )r   r!   r/   r   r   r   r=   export_xlsxr?   r@   rA   r    r   )r   r)   r,   rD   rE   rF   rG   rH   rI   rJ   xlsxfilenames               r   bymonth_exportz'XenoAttendanceController.bymonth_exportZ   s	    !??$$,,T59e56;;=44ZQ	G%%eX-l & D /$>$$V&(Ch(NO
 	
  	G@A((89#G G	Gs   +B) )>C*)C*z/odoo/attendances/bymonth/editjson)r0   r1   c                    | j                         st        t        d            |dvrt        t        d            |xs dj	                         }|r)t
        j                  |      st        t        d            	 t        j                  j                  |d      j                         }t        j                  d   j                         }|d	k(  rd
nd}|d	k(  rdnd
}	|j                  ddt!        |      fdd|fgd      }
|
r5|
j#                  ||xs di       |
|   s|
|	   s|
j%                          ddiS |r |j'                  dt!        |      d|||i       ddiS # t        t        f$ r t        t        d            w xY w)Nz6Attendance Officer access required to edit attendance.inoutzInvalid field. z%Time must be in HH:MM 24-hour format.z%Y-%m-%dzInvalid date.zxeno.attendance.overrider]   time_intime_outemployee_code=r&   r#   limitFokT)r   r   r   r   stripTIME_REmatchr%   strptimer&   r*   r+   r   r   r   searchrC   writeunlinkcreate)r   rb   r&   fieldvaluerH   date_objOverride
vals_fieldother_fieldrecs              r   bymonth_editz%XenoAttendanceController.bymonth_edity   s   
 ~~a XYZZ%A./00"##%u-AEFGG	0((11$
CHHJH ;;9:??A"'4-YZ
$)TMjyooc3}#56S(#
    IIz5>E23z?3{+;

 d| OO]!3E 
 d|) :& 	0Ao.//	0s   =.E $Fc                 B   t         j                  j                  j                  }|sXt         j                  d   j	                         j                  ddt         j                  j                  j                  fgd      }|xr |j	                         j                  xs dS )Nhr.employeeuser_idrc   r#   rd   F)r   r   r   employee_idr   rk   idxeno_employee_code)r   emps     r   _my_codez!XenoAttendanceController._my_code   s     kk**++m,113::S'++"2"2"5"567q ; BC4sxxz44==r   c                 2    t        j                  ddg      S )Nz<div style='font-family:sans-serif;padding:2rem'><h3>My Attendance is not available yet</h3><p>Your login is not linked to an employee record with an HRSystem employee code. Please contact HR.</p></div>r   r<   )r   r    r   s    r   _not_linkedz$XenoAttendanceController._not_linked   s$    $$C BB
 	
r   /odoo/attendances/myc                    | j                         }|s| j                         S | j                  ||      \  }}	 t        j                  d   j                         j                  ||d |gdd      }t        j                  |dg      S # t        $ rM}t        j                  d       dt        j                  d   j                  t        |            z  }Y d }~id }~ww xY w)	Nr6   r   T)r7   base_urlmy_modezattendance my render failedz<div style='font-family:sans-serif;padding:2rem;color:#b21f22'><h3>My Attendance unavailable</h3><p>Could not build the report from HRSystem.</p><pre style='white-space:pre-wrap;color:#555'>%s</pre></div>r   r<   )r~   r   r/   r   r   r   r>   r?   r@   rA   rB   rC   r    )r   r)   r,   rH   coderK   rL   s          r   my_attendancez&XenoAttendanceController.my_attendance   s    
 }}##%%,,T59e	;;78==?KKeT4&/ L D $$GH
 	
  	;<N ++67<<SXF	G 	s   7B 	CACCz/odoo/attendances/my/exportc                    | j                         }|s| j                         S | j                  ||      \  }}	 t        j                  d   j                         j                  ||d |g      }d||fz  }t        j                  |dd	d
|z  fg      S # t        $ r8 t        j                  d       t        j                  t        d      d      cY S w xY w)Nr6   rO   zattendance my export failedrP   rQ   rR   zmy_attendance_%04d_%02d.xlsxrS   rT   rU   r<   )r~   r   r/   r   r   r   rV   r?   r@   rA   r    r   )r   r)   r,   rH   r   rW   rX   s          r   my_attendance_exportz-XenoAttendanceController.my_attendance_export   s    
 }}##%%,,T59e	G;;78==?KKeT4& L D 2T5MA$$V&(Ch(NO
 	
  	G;<((89#G G	Gs   5B >CCc                    t         j                  j                  j                  }|sXt         j                  d   j	                         j                  ddt         j                  j                  j                  fgd      }|S )Nrx   ry   rc   r#   rd   )r   r   r   rz   r   rk   r{   )r   rD   s     r   _my_employeez%XenoAttendanceController._my_employee   sg    ;;##//{{=1668??S'++"2"2"5"567q @ BHr   z!/odoo/attendances/my/today_statusc                     | j                         }|sdddS t        j                  d   j                         j	                  |      S )zToday's merged first-in/last-out for the calling user's own
        employee -- lets the My Attendance widget notice a fingerprint
        check-in that Odoo's own hr_attendance module doesn't know about,
        without pulling the whole month.
        Nr\   r6   )r~   r   r   r   get_today_status)r   rH   r   s      r   my_today_statusz(XenoAttendanceController.my_today_status   sA     }}t,,{{3499;LLTRRr   z(/odoo/attendances/my/month_present_countc                 :   | j                         }|sddiS t        j                  j                         }|rt        |      n|j                  }|rt        |      n|j
                  }t        j                  d   j                         j                  |||      }d|iS )a  This calendar month's distinct present-days for the calling
        user's own employee, from the same merged biometric+native source
        as the My Attendance report -- used by Odoo Mobile's home page
        "This Month / Days Present" card, which used to count raw
        hr.attendance rows only and silently showed 0 for anyone who
        exclusively uses the physical biometric scanner.
        presentr   r6   )
r~   r%   nowr(   r)   r,   r   r   r   get_month_present_count)	r   r)   r,   rH   r   r'   ymcounts	            r   my_month_present_countz/XenoAttendanceController.my_month_present_count   s     }}q>!!!%%'CI5::CJU[[45::<TTUY[\^_`5!!r   z*/odoo/attendances/my/close_fingerprint_dayc                     | j                         }|st        t        d            t        j                  d   j                         j                  |j                        S )a  Explicit "Check Out" for a day that started with a
        fingerprint-only check-in: writes a real hr.attendance record
        (check_in = the fingerprint's scan time, check_out = now) so Odoo's
        own attendance state becomes consistent going forward.
         No linked employee record found.r6   )r   r   r   r   r   r   close_fingerprint_dayr{   r   rH   rD   s      r   my_close_fingerprint_dayz1XenoAttendanceController.my_close_fingerprint_day  sQ     $$&A@ABB{{3499;QQRZR]R]^^r   z"/odoo/attendances/my/native_statusc                     | j                         }|sdddS t        j                  d   j                         j	                  |j
                        S )a9  Whether the calling user has a currently open native
        hr.attendance check-in, and whether it's stale (open from a
        previous day/shift, effectively a forgotten checkout) -- lets the
        My Attendance widget show Absent/Check In for today instead of an
        indefinitely-stale Present.
        F)openstaler6   )r   r   r   r   get_native_checkin_statusr{   r   s      r   my_native_statusz)XenoAttendanceController.my_native_status#  sK     $$&!E22{{3499;UUV^VaVabbr   z(/odoo/attendances/my/close_stale_checkinc                     | j                         }|st        t        d            t        j                  d   j                         j                  |j                        S )a"  Auto-close a forgotten open check-in (see my_native_status) so
        the employee can check in fresh today. Closes at 23:59:59 on the
        stale check-in's own day -- the actual fresh check-in is then done
        by the normal core check-in flow right after, from the client.
        r   r6   )r   r   r   r   r   r   close_stale_checkinr{   r   s      r   my_close_stale_checkinz/XenoAttendanceController.my_close_stale_checkin3  sQ     $$&A@ABB{{3499;OOPXP[P[\\r   z/odoo/attendances/my/calendarjsonrpcc                 *   | j                         }|sddiS | j                  ||      \  }}t        j                  d   j	                         }|j                  ||d|g      }|d   r|d   d   ndt        j                  j                         j                         }|t        j                  d   j	                         j                         v }i }	t        d	|d
   d	z         D ]'  }
d|||
fz  t        j                  |||
      j                         dk\  }|d   v }t        fd|d   D        d      }|f|j                  di       v }|f|j                  di       v }r#|j                  j                  dz              nd}r#|j                  j                  dz              nd}rj                  d      xs ddd nd}|rd}n/|rd}n*|rd}n%|rd}n |rd}n|r
||kD  rdnd}n|rd}n
|k  rd}nd}||||d|	<   * d |	d!S )"aS  Slim per-day attendance summary for the My Profile dashboard
        widget's mini-calendar -- same HRSystem source as /odoo/attendances/my
        (biometric + app/GPS punches), just shaped for a calendar cell
        instead of a full grid. {"linked": False} if this login isn't
        bridged to an HRSystem employee_code yet.
        linkedFr6   NrO   rowsr   zxeno.attendance.auto.ruler#   daysz%04d-%02d-%02d   holidaysc              3      K   | ]6  }|d    cxk  r|d   k  r#n n r|d   j                  d      k(  r|d    8 yw)startendrz   r   N)get).0lvdatestrrows     r   	<genexpr>zBXenoAttendanceController.my_attendance_calendar.<locals>.<genexpr>^  sK      OwK77bi7M!2cggm6L!L F Os   <?leavesdayoffsbusiness_tripsz%s.Inz%s.Outshift_startz09:00btoffholidayweekendleavelater   absentupcoming)r   r]   r^   
leave_codeT)r   r   )r~   r/   r   r   r   get_month_reportr%   r&   r'   	isoformatget_auto_fill_codesrangeweekdaynextr   _fmt)r   r)   r,   rH   r   rI   data	today_str	auto_fillr   d
is_weekend
is_holidayon_leave	on_dayoffon_bttintoutsstartr   r   r   s                       @@r   my_attendance_calendarz/XenoAttendanceController.my_attendance_calendarB  sK    }}e$$,,T59e56;;=&&tUD$&P!%fd6l1o4MM'')335	GKK(CDIIK__aa	q$v,*+ #	_A&$q)99G!tUA6>>@AEJ D$44JOd8n O 	H w488Ir+BBI7Otxx0@"'EEE=@&++cggg&789dC?B6;;swwx''9:;DBEsww}-8"1=7F"" #&<Y"9$!#'-SU]^DMG#	_J --r   /odoo/attendances/myteamc                    | j                         }| j                         s|s| j                         S | j                  ||      \  }}	 t        j
                  d   j                         j                  |||xs d |dd      }t	        j                  |dg      S # t        $ rM}t        j                  d       dt        j
                  d   j                  t        |            z  }Y d }~id }~ww xY w)	Nr6   r   T)r7   r   	team_modezattendance myteam render failedz<div style='font-family:sans-serif;padding:2rem;color:#b21f22'><h3>My Team Attendance unavailable</h3><p>Could not build the report from HRSystem.</p><pre style='white-space:pre-wrap;color:#555'>%s</pre></div>r   r<   )r   r   r!   r/   r   r   r   r>   r?   r@   rA   rB   rC   r    )r   r)   r,   rD   rH   
team_codesrK   rL   s           r   myteamzXenoAttendanceController.myteam  s    
 %%'
!*??$$,,T59e	;;78==?KKeX-j3t L D $$GH
 	
  	?@N ++67<<SXF	G 	s   	:B 	C1$AC,,C1z/odoo/attendances/myteam/exportc                    | j                         }| j                         s|s| j                         S | j                  ||      \  }}	 t        j
                  d   j                         j                  |||xs d |      }d||fz  }t	        j                  |dd	d
|z  fg      S # t        $ r8 t        j                  d       t	        j                  t        d      d      cY S w xY w)Nr6   rO   zattendance myteam export failedrP   rQ   rR   z!my_team_attendance_%04d_%02d.xlsxrS   rT   rU   r<   )r   r   r!   r/   r   r   r   rV   r?   r@   rA   r    r   )r   r)   r,   rD   rH   r   rW   rX   s           r   myteam_exportz&XenoAttendanceController.myteam_export  s   
 %%'
!*??$$,,T59e	G;;78==?KKeX-j L D 7$F$$V&(Ch(NO
 	
  	G?@((89#G G	Gs   	8B& &>C'&C')NNNNNN)NNNN)NN)NNN)__name__
__module____qualname__r   r   r   r!   r/   r   routerM   rY   rv   r~   r   r   r   r   r   r   r   r   r   r   r   r    r   r   r	   r	      sf   7W

, TZZ#&%U 7;6:
	
@ TZZ*&%U >B=A
	
6 TZZ(&	@>
 TZZ&%U
	
0 TZZ%&%U
	
2 TZZ+&	S		S TZZ2&"	"" TZZ4&	_		_ TZZ,&
c	
c TZZ2&	]		] TZZ'V8.	8.t TZZ"&%U
	
0 TZZ)&%U
	
r   r	   )r%   loggingreodoor   r   odoo.exceptionsr   r   	odoo.httpr   	getLoggerr   r@   compilerh   
Controllerr	   r   r   r   <module>r      sL      	  2 
'

H
%
"**1
2i
t i
r   