
    vg}J                        d Z ddlZddlmZmZmZ ddlZddlmZ ddl	m
Z
 ddlmZ ddlmZmZ 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 ddlmZmZ dddddddddddddZ d Z!d Z"d9dZ#d9dZ$d Z%d  Z&d! Z'd" Z(d# Z)d$ Z*d% Z+d& Z,d' Z-d( Z.d) Z/d* Z0d+ Z1d, Z2d- Z3d. Z4d/ Z5 G d0 d1      Z6 G d2 d3      Z7d4 Z8d5 Z9d6 Z:d7 Z;d8 Z<y):z4
utils.py

This module is used write custom methods
    N)datetimetime	timedelta)ValidationError)	Paginator)models)QSum)HttpResponse)gettext_lazy)get_pagination)	WEEK_DAYSCompanyLeavesHolidays)Employee)HORILLA_DATE_FORMATSHORILLA_TIME_FORMATS                        	   
         )januaryfebruarymarchaprilmayjunejulyaugust	septemberoctobernovemberdecemberc                 t    t        | dz        }t        | dz  dz        }t        | dz  dz        } |dd|dS )zi
    this method is used to formate seconds to H:M and return it
    args:
        seconds : seconds
      <   02d:)int)secondshourminutess      ,/var/www/horilla/attendance/methods/utils.pyformat_timer6   '   sM     w$D7T>b()G7T>R'(G3Zq&&    c                 ~    g d}t        d t        |t        t         | j                  d                  D              S )z
    this method is used reconvert time in H:M formate string back to seconds and return it
    args:
        time : time in H:M format
    )r-   r.   r   c              3   ,   K   | ]  \  }}||z    y wN ).0abs      r5   	<genexpr>z"strtime_seconds.<locals>.<genexpr><   s     EAq1uEs   r0   )sumzipmapr1   split)r   ftrs     r5   strtime_secondsrE   4   s2     CES#c:4::c?*C!DEEEr7   c                    i }| j                   j                  }|r|D cg c]  }|j                  |vs| }}|D ]E  }t        | |j                        }t        ||j                        }||k7  s5||f||j                  <   G |S c c}w )aj  
    Compare the fields of two instances and identify the changes.

    Args:
        first_instance: The first instance to compare.
        other_instance: The second instance to compare.
        exclude_fields: A list of field names to exclude from comparison (optional).

    Returns:
        A dictionary of changed fields with their old and new values.
    )_metafieldsnamegetattr)first_instanceother_instanceexclude_fields
differencefields_to_comparefield	old_value	new_values           r5   get_diff_objrS   ?   s     J&,,330
EJJn4TE
 
 # <NEJJ7	NEJJ7		!&/%;Juzz"< 
s
   BBc                 f   i }| j                         D ]  \  }}|j                  |      }||k(  r|s||f||<   (|j                  j                  |      }|j                  }t        |t        j                        r]|r*|dk7  r%t        j                  |d      j                  d      n|}|r*|dk7  r%t        j                  |d      j                  d      n|}nt        |t        j                        rd }	 |	|      } |	|      }nt        |t        j                        r|r?t        |      j                         r&|j                  j                   j                  |      n|}|r?t        |      j                         r&|j                  j                   j                  |      n|}||f||<    |S )an  
    Compare two dictionaries and identify differing key-value pairs.

    Args:
        first_dict: The first dictionary to compare.
        other_dict: The second dictionary to compare.
        model: The model class (optional, for verbose names and type-specific formatting)

    Returns:
        A dictionary of differing keys with their old and new values.
    None%Y-%m-%dz%d %b %Yc                     | rN| dk7  rI| t        | j                  d            dk(  rdndz  } t        j                  | d      j	                  d      S | S )NrU   r0   r   z:00 %H:%M:%Sz%I:%M %p)lenrC   r   strptimestrftime)vals    r5   r6   z"get_diff_dict.<locals>.format_time   sN    3&=C		#$71$<5"DC#,,S*=FFzRR
r7   )id)itemsgetrG   	get_fieldverbose_name
isinstancer   	DateFieldr   r[   r\   	TimeField
ForeignKeystrisdigitrelated_modelobjects)

first_dict
other_dictmodelrN   keyvalueother_valuerP   verbose_keyr6   s
             r5   get_diff_dictrr   ^   s    J &&( 07
U nnS)K$k2JsO %%c*(( eV--. Uf_ !!%4==jI  ;&#8 !!+z:CCJO  
 v//0  &E%k2Kv001 SZ//1 ##++//5/9  3{#3#;#;#= ##++//;/?   $)+"6
;a07d r7   c                 r    d\  }}	 | j                   j                  }|j                  }||fS # ||fc cY S xY w)zb
    This method return the employee instance and work info if not exists return None instead
    )NN)useremployee_getemployee_work_info)requestemployeerv   s      r5   employee_existsry      sH     $. H .<<,,%88,--,--s   "- 6c                 "   | j                   j                  |      }d\  }}}|j                         rY|d   }|j                  }t	        |j
                  j                  d            }t	        |j                  j                  d            }|||fS )z
    This function is used to find shift schedules for the day,
    it will returns min hour,start time seconds  end time seconds
    args:
        shift   : shift instance
        day     : shift day object
    )shift_id)r   r   00:00r   z%H:%M)day_schedulefilterexistsminimum_working_hourrE   
start_timer\   end_time)dayshiftschedule_todaystart_time_secend_time_secminimum_hours         r5   shift_schedule_todayr      s     %%,,e,<N1>.NL,'*%::()B)B)K)KG)TU&~'>'>'G'G'PQ.,77r7   c                     | j                   }| j                  }t        |      }t        |      }||kD  rt        ||z
        S y)a  
    This method is used to calculate overtime of the attendance, it will
    return difference between attendance worked hour and minimum hour if
    and only worked hour greater than minimum hour, else return 00:00
    args:
        attendance : attendance instance
    r|   )r   attendance_worked_hourrE   r6   )
attendancer   at_workat_work_secminimum_hour_secs        r5   overtime_calculationr      sL     **L//G!'*K&|4%%K*::<<r7   c                     | j                   j                  }	 |j                  j                  j                  }||k(  S # t
        $ r t        d      cY S w xY w)a  
    if the instance have employee id field then you can use this method to know the
    request user employee is the reporting manager of the instance
    args :
        request : request
        instance : an object or instance of any model contain employee_id foreign key field
    z,This Employee Dont Have any work information)rt   ru   employee_idrv   reporting_manager_id	Exceptionr   )rw   instancemanageremployee_workinfo_managers       r5   is_reportingmangerr      s`     ll''GL  33HH 	"
 ///  LJKKLs    = AAc                     d}	 t        j                  | |      }|j                         S # t        $ r}t	        t        d            d }~ww xY w)NrY   z,Invalid format, it should be HH:MM:SS format)r   r[   r   
ValueErrorr   _)ro   
timeformat	validtimees       r5   validate_hh_mm_ss_formatr      sO    JQ%%eZ8	~~ Qa NOPPQs   %* 	AAAc                 V   | j                  d      dk(  r#dj                  | j                  d      dd       } t        |       dkD  rt	        t        d            	 | j                  d      \  }}t        |      dkD  st        |      dkD  rt	        t        d            t        |      }t        |      }t        t        |            dkD  s$t        t        |            dkD  s|t        d      vrt	        t        d	            y# t        $ r}t	        t        d
            |d}~ww xY w)M
    this method is used to validate the format of duration like fields.
    r0   r   Nr   z)Invalid format, it should be HH:MM formatr   zInvalid timer.   Invalid time, excepted MM:SSzInvalid format)
countjoinrC   rZ   r   r   r1   rg   ranger   )ro   r3   minuteerrors       r5   validate_time_formatr      s    {{31 S)"1-.
5zA~a KLMM	>{{3'ft9q=CK!O!!N"3444yVs4y>AS[!1A!5uRy9P!!$B"CDD :Q >a 012=>s   B)D 	D(D##D(c                     t        j                         j                         }| st        t	        d            | |kD  rt        t	        d            y)z
    Validates if the provided date is not a future date.

    :param date: The date to validate.
    :raises ValidationError: If the provided date is in the future.
    zCheck date format.z You cannot choose a future date.N)r   todaydater   r   )r   r   s     r5   attendance_date_validater     sJ     NN!!#Ea 4566	a BCDD 
r7   c                    | j                   j                  }| j                   j                  }| j                   j                  }| j                  j
                  }| j                  j                  }| j                  j                  }| j                  j                  }| j                  j                  }| j                  j
                  }	| j                  j                  }
t        |||||      t        ||||	|
      fS )z
    This method is used to convert clock-in and clock-out of activity as datetime object
    args:
        attendance_activity : attendance activity instance
    )
clock_in_dateyearmonthr   clock_inr3   r   clock_out_date	clock_outr   )attendance_activityin_yearin_monthin_dayin_hour	in_minuteout_year	out_monthout_dayout_hour
out_minutes              r5   activity_datetimer     s     "//44G"0066H ..22F!**//G#,,33I"1166H#2288I!0044G",,11H$..55JGXvw	BH)Wh
E  r7   c                     t        t        | j                  d            \  }}t        j                  | d| dd      j                         }|t        d      z   }||fS )zI
    This method is use to return the start and end date of the week
    z-Wz-1z	%Y-W%W-%wr   days)rB   r1   rC   r   r[   r   r   )weekr   week_number
start_dateend_dates        r5   get_week_start_end_datesr   *  sd    
 CD!12D+ ""dV2k]"#={KPPRJ I1--Hxr7   c                     t        t        | j                  d            \  }}t        ||d      j	                         }t        j                  ||      \  }}t        |||      j	                         }||fS )zJ
    This method is use to return the start and end date of the month
    -r   )rB   r1   rC   r   r   calendar
monthrange)
year_monthr   r   r   r   last_dayr   s          r5   get_month_start_end_datesr   :  sp    
 c:++C01KD%$q)..0J %%dE2KAxeX.335Hxr7   c                     ddd}g }| D ]H  }|j                  |      j                  t        d            d   }|j                  |r|dz  nd	       J ||d
<   |S )z&
    To find all the worked hours
    zWorked Hourszrgba(75, 192, 192, 0.6)labelbackgroundColor:employee_id__employee_work_info__department_id__departmenthour_account_second	total_sumr   r-   r   datar~   	aggregater
   appendlabelsrecordsr   dept_recordsdeptr   s         r5   worked_hour_datar   J  s    
  4D L BNNGK # 

)c"78)
9+G	 		I,qA	B
  DLKr7   c                     ddd}g }| D ]H  }|j                  |      j                  t        d            d   }|j                  |r|dz  nd	       J ||d
<   |S )z'
    To find all the pending hours
    zPending Hourszrgba(255, 99, 132, 0.6)r   r   hour_pending_secondr   r   r-   r   r   r   r   s         r5   pending_hour_datar   \  s    
 !4D L BNNGK # 

)c"78)
9+G	 		I,qA	B
  DLKr7   c                 \    | j                   j                  r| j                   j                  S y)z5
    This method is used to return the last name
    rX   )r   employee_last_name)r   s    r5   get_employee_last_namer   n  s(     00%%888r7   c                    t        j                  | d      }|j                  d      }g }t        j                  j                         }|D ]  }|j                  }|j                  }t        j                  t        |      d      }t        j                  t        |      d      }|}	|	|k  sa|j                  |	j                  d             |	t        d      z  }	|	|k  r5 |D ]  }
t        |
      t        |       k(  sd} n i }t        j                  j                         }|D ];  }t        t              j                  |j                        }|j                   }|||<   = t        |j"                  dz
  dz  dz   dz
        }|j%                         D ]c  }t        |d         dk(  rt        |d         t        |      k(  rd} |S t        |d         |k(  sEt        |d         t        |      k(  s`d} |S  |S )	NrV   z%Ar   r   r|   r   r   rU   )r   r[   r\   r   rj   allr   r   rg   r   r   r   dictr   r`   based_on_week_daybased_on_weekr   r_   )attendance_dater   attendance_datetimeattendance_dayleavesholidaysholir   r   current_dateleavecompany_leavescompany_leave	com_leaver=   r>   week_in_monthpairss                     r5   attendance_day_checkingr   w  s   "++OZH )11$7N F##%H .__
== &&s:
C
$$S]J? "h&MM,//
;<I1--L h&.  u:_--"L N!))--/M" 	O	 ; ;<##q -11A5!;a?1DEM  %%' 
uQx=F"58}N 33& 	 uQx=M)58}N 33&
 r7   c                 P    t        | t                     }|j                  |      } | S )z2
    This method is used to paginate queryset
    )r   r   get_page)qrysetpage_number	paginators      r5   paginator_qryr     s(     &."23I,FMr7   c                    g }t         j                  j                  | |      }|t        |j	                  dd            z  }t
        j                  j                         }|D ]o  }|}| } |j                  }|j                  }|d k7  rt        j                  d       t        j                  ||       }|t        |         }	|	D 
cg c]
  }
|
dk7  s	|
 }}
|D ]c  }
t        j                  | d| dd|
dd	      j                         }|j!                         t        |      k(  sN||vsS|j#                  |       e t        j                  d       t        j                  ||       }|D ]d  }|t        |         dk7  st        j                  | d| dd|t        |         dd	      j                         }||vsT|j#                  |       f r |S c c}
w )
N)start_date__monthstart_date__yearr   T)flatr   r   r   02rV   )r   rj   r~   listvalues_listr   r   r   r   r   setfirstweekdaymonthcalendarr1   r   r[   r   weekdayr   )r   r   leave_datesr   r   r   r   r   month_calendarweeksr   weekdays_in_weeks	date_namer   s                 r5   monthly_leave_daysr    s   K&&QU&VH4,,\,EFFK"**..0N' 6%33);;D $$Q'%33D%@N"3}#56E05 B B B( 2$--fAeBZqR1:$&  %%'3/@+AA!4&&y12 $$Q'%33D%@N& 6-./14 ( 1 1&%1T#6G2H-I",MN"! df  !3#**956-6< + !Cs   
GGc                    t        |       dkD  rt        t        d            	 | j                  d      \  }}t        |      dkD  st        |      dkD  rt        t        d            t	        |      }t	        |      }|t        d      vs|t        d      vrt        t        d            y# t        $ r}t        t        d            |d}~ww xY w)	r   r   z)Invalid format, it should be MM:SS formatr0   r   r   r.   zInvalid format,  excepted MM:SSN)rZ   r   r   rC   r1   r   r   )ro   r4   secr   s       r5   validate_time_in_minutesr    s     5zA~a KLMM	K{{3'w<!s3x!|!!$B"CDDg,#h%)#s%)';!!$B"CDD (< Ka ABCJKs   BB- -	C6CCc                       e Zd ZdZ	 	 ddZy)Requesta_  
    Represents a request for clock-in or clock-out.

    Attributes:
    - user: The user associated with the request.
    - date: The date of the request.
    - time: The time of the request.
    - path: The path associated with the request (default: "/").
    - session: The session data associated with the request (default: {"title": None}).
    Nc                 z    || _         d| _        dd i| _        || _        || _        || _        t               | _        y )N/title)rt   pathsessionr   r   r   META)selfrt   r   r   r   s        r5   __init__zRequest.__init__  s;     				 F	r7   )returnN)__name__
__module____qualname____doc__r  r;   r7   r5   r  r    s    	 
r7   r  c                        e Zd ZdZed        Zy)r  z0
    Provides access to HTTP metadata keys.
    c                     dgS )z
        Retrieve the list of available HTTP metadata keys.

        Returns:
            list: A list of HTTP metadata keys.
        HTTP_HX_REQUESTr;   )clss    r5   keysz	META.keys  s     """r7   N)r  r   r!  r"  classmethodr'  r;   r7   r5   r  r    s     # #r7   r  c                     t        | t              r| S t        | t              r?t        j                         D ](  }	 t        j                  | |      j                         c S  y # t        $ r Y 7w xY wr:   )rc   r   rg   r   valuesr   r[   r   )time_str
format_strs     r5   
parse_timer-    sm    (D!(C .557 	J((:>CCEE	
   s   #A##	A/.A/c                     	 t        j                  |       j                         S # t         j                  j                  t
        f$ r d|j                         d    ||<   Y y w xY w)NzInvalid date format for )pdto_datetimer   errorsParserErrorr   rC   )date_str	error_keyactivitys      r5   
parse_dater7  *  s^    ~~h',,..II!!:.  89J29N8OPs   "% <A$#A$c                 J    | r |rt        j                  |  d|d d  d      S d S )N r   z%Y-%m-%d %H:%M)r   r[   )r4  r+  s     r5   parse_datetimer:  2  s<      	XJa!~68HI r7   c                     t        | t              r| S t        | t              r4t        j                         D ]  \  }}	 t        j
                  | |      c S  y # t        $ r Y ,w xY wr:   )rc   r   rg   r   r_   r[   r   )r   format_namer,  s      r5   get_dater=  :  si    $!	D#	';'A'A'C 	#K((z::	
   s   A	A$#A$c                     | D ]  }t        |d         |d<    | D cg c]	  }|d   | } }t        | d       }|S c c}w )NAttendance Datec                     | d   S )Nr?  r;   )xs    r5   <lambda>z%sort_activity_dicts.<locals>.<lambda>Q  s    CTAU r7   )rn   )r=  sorted)activity_dictsr6  sorted_activity_dictss      r5   sort_activity_dictsrF  F  so    " L&.x8I/J&K"#L '%&2 	N 
 #>7UV  s   =r:   )=r"  r   r   r   r   pandasr0  django.core.exceptionsr   django.core.paginatorr   	django.dbr   django.db.modelsr	   r
   django.httpr   django.utils.translationr   r   base.methodsr   base.modelsr   r   r   employee.modelsr   horilla.horilla_settingsr   r   MONTH_MAPPINGr6   rE   rS   rr   ry   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r-  r7  r:  r=  rF  r;   r7   r5   <module>rS     s    . .  2 +  # $ 6 ' : : $ O  
'F>@F	.8$$0&Q>.E0    $$5p$NK$ 8# # 
	!r7   