o
    %AhT                     @   s   d dl mZ d dlmZ d dlmZ d dlmZ d dlZd dl	m
Z
 d dlmZmZ d dlmZ e ZG d	d
 d
ejZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZG dd dejZdS )    )models)get_user_modelGroup)DecimalN)timezone)	timedeltadate)relativedeltac                   @   s   e Zd ZejdddZejddZejdej	ddddZ
ejeej	dddd	Zejdd
ZejddZejddZdd ZG dd dZdS )
Departmentd   T)
max_lengthuniqueblankEmployeemanaged_departments)	on_deletenullr   related_namez/User group with permissions for this department)r   r   r   	help_textdefaultauto_now_addauto_nowc                 C   s   | j S Nnameself r"   )/var/www/html/optinet_system/hr/models.py__str__   s   zDepartment.__str__c                   @      e Zd ZdgZdS )zDepartment.Metar   N__name__
__module____qualname__orderingr"   r"   r"   r#   Meta       
r+   N)r'   r(   r)   r   	CharFieldr   	TextFielddescription
ForeignKeySET_NULLmanagerr   
user_groupBooleanField	is_activeDateTimeField
created_at
updated_atr$   r+   r"   r"   r"   r#   r      s    r   c                       sr  e Zd Zg dZg dZg dZejeej	ddddZ
ejdddd	Zejd
dZejd
dZejddZej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ZejdddddZe ZejddZejeejdddZejddZejdeddZejdeddZe  Z!ej dddZ"ej dddZ#ej$ddddZ%ejded d!d"Z&ej$d#dddd$d%Z'ej$d#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*Z+ejd
dd*Z,ejddd*Z-ejddd*Z.ejddd*Z/ejd
dd*Z0ej1d+ddd,Z2ejddZ3ej4dd-Z5ej4dd.Z6 fd/d0Z7d=d3d4Z8e9d5d6 Z:e9d7d8 Z;d9d: Z<G d;d< d<Z=  Z>S )>r   ))	permanent	Permanent)contractContract)
internship
Internship)	temporary	Temporary)casualzCasual/Daily))monthlyMonthly)weeklyWeekly)dailyDaily)hourlyHourly))activeActive)on_leaveOn Leave)	suspended	Suspended)
terminated
Terminatedemployee_profileT)r   r   r   r      Fr   r   editable2   r   )r      zNational ID or Passport Number)r   r   r   zKRA PIN Number)r   r   r   r   zNSSF NumberzNHIF Numberr   	employeesr   r   r   r   r9   r   choicesr   rJ   r   r         zBasic salary amount)
max_digitsdecimal_placesr   rB   zHow often the employee is paid)r   r\   r   r   
   zDaily rate for casual workers)r`   ra   r   r   r   zHourly rate for hourly workerszContract start dater   r   r   z,Contract end date (for fixed-term contracts))r   r   zemployees/profiles/)	upload_tor   r   r   r   c           
         sL  | j s(tjjddd }|rt|j dd  }|d }nd}d|d| _ t j|i | | j	r| j
o<| j
jdk}|rQ| j	jsQd| j	_d	| j	_| j	  n|sj| j	jrj| j	jd	krjd
| j	_d| j	_| j	  | j
rddlm} |jjg dd}| j	jj|  z|jj| j
jd}	| j	j|	 W d S  |jy   Y d S w d S d S )NOGL)employee_id__startswithz-employee_id      03d
ManagementTadminF
technicianr   r   )rj   
Technician	MarketingzHR StaffzBilling StaffzCustomer Service)name__inr   )employee_idr   objectsfilterorder_byfirstintsupersaveuser
departmentr   is_superuserroledjango.contrib.auth.modelsr   groupsremovegetaddDoesNotExist)
r!   argskwargslast_employeelast_number
new_numberis_managementr   dept_groupsgroup	__class__r"   r#   rw   k   s<   

zEmployee.saveNrl   c              
      s   | j r| j S |s%ddlddl}|j|j  d fddtdD }| jo-| jjdk}t	j
j| j| j|| j| j|r>dnd	d
|d}| jrS| jjrS|j| jj || _ |   |S )z'Create a user account for this employeer   N c                 3   s    | ]}  V  qd S r   )choice).0_
characterssecretsr"   r#   	<genexpr>   s    z/Employee.create_user_account.<locals>.<genexpr>   rj   rk   rl   T)usernameemailpassword
first_name	last_namer{   is_staffrz   )rx   r   stringascii_lettersdigitsjoinrangery   r   Userrq   create_userrp   r   r   r   r3   r}   r   rw   )r!   r   r{   r   rz   rx   r"   r   r#   create_user_account   s.   
zEmployee.create_user_accountc                 C      | j  d| j S )N )r   r   r    r"   r"   r#   	full_name   s   zEmployee.full_namec                 C   s<   | j r
| j d  nd}| jr| jd  nd}| | S )z,Return employee initials for profile displayr   r   )r   upperr   )r!   first_initiallast_initialr"   r"   r#   initials   s   zEmployee.initialsc                 C   r   N - )rp   r   r    r"   r"   r#   r$      s   zEmployee.__str__c                   @   r%   )zEmployee.Metarp   Nr&   r"   r"   r"   r#   r+      r,   r+   )Nrl   )?r'   r(   r)   EMPLOYMENT_TYPE_CHOICESPAY_FREQUENCY_CHOICESEMPLOYMENT_STATUS_CHOICESr   OneToOneFieldr   CASCADErx   r-   rp   r   r   
EmailFieldr   phone	id_numberkra_pinnssf_numbernhif_numberr.   physical_addresspostal_addressr0   r   r1   ry   	job_titleemployment_typeemployment_status	DateField	hire_dateprobation_end_datetermination_dateDecimalFieldbasic_salarypay_frequency
daily_ratehourly_ratecontract_start_datecontract_end_date	bank_namebank_account_numberbank_branchemergency_contact_nameemergency_contact_phoneemergency_contact_relationship
ImageFieldprofile_picturenotesr6   r7   r8   rw   r   propertyr   r   r$   r+   __classcell__r"   r"   r   r#   r      s^    
+$

r   c                   @   s   e Zd Zg dZejeejddZej	dedZ
ej	ddZejdd	d
ZejdddZejejdZejddddZejddZejeejdddZejddZejddZdd ZG dd dZdS )	Deduction))taxTax)loanLoan)advancezSalary Advance)	insurance	Insurance)disciplinaryDisciplinaryotherOther
deductionsr   r   rS   r   r\      rW   rb   r_   r`   ra   Fz&Will this deduction apply every month?r   r   r   Tz"Leave blank for ongoing deductionsrc   created_deductionsrZ   r   r   c                 C      | j j d|   d| j S Nr   z: )employeer   get_deduction_type_displayamountr    r"   r"   r#   r$         zDeduction.__str__c                   @   r%   )zDeduction.Meta-created_atNr&   r"   r"   r"   r#   r+      r,   r+   N)r'   r(   r)   DEDUCTION_TYPE_CHOICESr   r0   r   r   r   r-   deduction_typereasonr   r   r4   is_recurringr   r	   today
start_dateend_dater5   r   r1   
created_byr6   r7   r8   r$   r+   r"   r"   r"   r#   r      s    	r   c                   @   s   e Zd Zg dZejeejddZej	dedZ
ej	ddZejdd	d
ZejdddZejejdZejddZejeejdddZejddZejddZdd ZG dd dZdS )Bonus))performancezPerformance Bonus)annualzAnnual Bonus)overtimeOvertime)
commission
Commission)holidayzHoliday Bonusr   bonusesr   rS   r   r   rW   rb   r_   r   Fz"Will this bonus apply every month?r   r   Tcreated_bonusesrZ   r   r   c                 C   r   r   )r   r   get_bonus_type_displayr   r    r"   r"   r#   r$      r   zBonus.__str__c                   @   r%   )z
Bonus.Metar   Nr&   r"   r"   r"   r#   r+      r,   r+   N)r'   r(   r)   BONUS_TYPE_CHOICESr   r0   r   r   r   r-   
bonus_typer   r   r   r4   r   r   r	   r   date_earnedr5   r   r1   r   r6   r7   r8   r$   r+   r"   r"   r"   r#   r      s    	r   c                       sf  e Zd ZejddddZejeejddZ	e
 Ze
 Ze
 Zejddd	Zejd
deddZejddddZejd
deddZejd
deddZejd
deddZejd
deddZejddddZejddZejddZejeejdddZejddZej ddZ!ej ddZ"dd Z#dd Z$dd Z% fddZ&dd Z'G dd dZ(  Z)S ) PaysliprV   TFrT   payslipsr   r^   r_   r   rb   0.00r`   ra   r   )r`   ra   rU   r   generated_payslipsrZ   r   r   r   c                 C   s   | j jj| j| jdddS )z9Get detailed breakdown of bonuses for this payslip periodT)date_earned__gtedate_earned__lter5   r  )r   r   rr   pay_period_startpay_period_endrs   r    r"   r"   r#   get_bonus_breakdown#  s   zPayslip.get_bonus_breakdownc                 C   s6   | j jj| jddtjddtj| jdB dS )z<Get detailed breakdown of deductions for this payslip periodT)start_date__lter5   )end_date__isnull)end_date__gter   )r   r   rr   r  r   Qr
  rs   r    r"   r"   r#   get_deduction_breakdown+  s   zPayslip.get_deduction_breakdownc           	      C   s"  | j jdkrf| j jj| j| jg dd}d}td}|D ]}|jdkr(|d7 }n|d7 }||jp3td7 }q| j j	p=td}|tt
| | _|dkrb| j jrd|| j j td	 }|  j|7  _dS dS dS | j jd
kr| j jj| j| jd}tdd |D }| j jptd}|| | _dS dS )z=Calculate salary based on attendance for casual/daily workersrF   )presentlatehalf_day)	date__gte	date__lte
status__inr   r  r  g      ?rh   z1.5rH   )r  r  c                 S   s   g | ]}|j qS r"   )total_hours)r   recordr"   r"   r#   
<listcomp>Y  s    z@Payslip.calculate_salary_based_on_attendance.<locals>.<listcomp>N)r   r   attendance_recordsrr   r
  r  r   statusovertime_hoursr   strr   r   sum)	r!   r  
total_daystotal_overtime_hoursr  r   overtime_payr  r   r"   r"   r#   $calculate_salary_based_on_attendance4  s8   

z,Payslip.calculate_salary_based_on_attendancec                    s   | j s3| jd}tjjd| dd }|r(t|j dd  }|d }nd}d| |d| _ | j	j
dv r=|   | j| j | _| j| j | j | j }| j| | _t j|i | d S )	Nz%Y%mPAY)payslip_number__startswithz-payslip_numberrh   04d)rF   rH   )payslip_numberr
  strftimer  rq   rr   rs   rt   ru   r   r   r#  r   total_bonusesgross_salarytotal_deductionspaye_taxnhif_deductionnssf_deduction
net_salaryrv   rw   )r!   r   r   
year_monthlast_payslipr   r   total_all_deductionsr   r"   r#   rw   ]  s2   

zPayslip.savec                 C   s   | j  d| jj S r   )r(  r   r   r    r"   r"   r#   r$     s   zPayslip.__str__c                   @   s   e Zd ZdgZg dZdS )zPayslip.Metaz-pay_period_start)r   r
  r  Nr'   r(   r)   r*   unique_togetherr"   r"   r"   r#   r+     s    r+   )*r'   r(   r)   r   r-   r(  r0   r   r   r   r   r
  r  pay_dater   r   r   r*  r+  r,  r-  r.  r/  r0  r4   is_generatedis_paidr   r1   generated_byr.   r   r6   r7   r8   r  r  r#  rw   r$   r+   r   r"   r"   r   r#   r    s4    	)"r  c                       s   e Zd ZejeejddZeje	j
ddZejddZe ZejddZejdddZ fd	d
Zedd Zedd Zdd Z  ZS )EmployeeInvitation
invitationr   T)r   r   r   Fr   r]   c                    s0   | j st tdd | _ t j|i | d S )N   days)
expires_atr   nowr   rv   rw   )r!   r   r   r   r"   r#   rw     s   zEmployeeInvitation.savec                 C   s   t  | jkS r   )r   r@  r?  r    r"   r"   r#   
is_expired  s   zEmployeeInvitation.is_expiredc                 C   s   | j  o| j S r   )is_usedrA  r    r"   r"   r#   is_valid  s   zEmployeeInvitation.is_validc                 C   s"   d| j j d| jrd S d S )NzInvitation for r   UsedPending)r   r   rB  r    r"   r"   r#   r$     s   "zEmployeeInvitation.__str__)r'   r(   r)   r   r   r   r   r   	UUIDFielduuiduuid4tokenr6   r7   r?  r4   rB  used_atrw   r   rA  rC  r$   r   r"   r"   r   r#   r:    s    

r:  c                   @   s   e Zd Zg dZejeejddZej	dedZ
ej	dddZejd	d
ZejeejdddZejddZejddZejddZdd Zedd ZG dd dZdS )EmployeeDocument))cvz	CV/Resume)applicationzJob Application)r;   zEmployment Contract)id_scanzNational ID Scan)passport_scanzPassport Scan)certificateCertificater   	documentsr   rS   r   r   zDocument title or description)r   r   zemployees/documents/)rd   Tuploaded_employee_docsrZ   r   r   r   c                 C   r   r   )r   r   get_document_type_displaytitler    r"   r"   r#   r$     r   zEmployeeDocument.__str__c                 C   sL   | j r$| j j}dD ]}|dk r|dd|   S |d }q	|ddS dS )z)Return file size in human readable format)BKBMBGBi   z.1fr   z TBUnknown)document_filesize)r!   r\  unitr"   r"   r#   	file_size  s   
zEmployeeDocument.file_sizec                   @   r%   )zEmployeeDocument.Metaz-uploaded_atNr&   r"   r"   r"   r#   r+     r,   r+   N)r'   r(   r)   DOCUMENT_TYPE_CHOICESr   r0   r   r   r   r-   document_typerU  	FileFieldr[  r   r1   uploaded_byr6   uploaded_atr.   r   r4   r5   r$   r   r^  r+   r"   r"   r"   r#   rK    s    

rK  c                       s   e Zd Zg dZejeejddZe	 Z
ejdeddZejdddZejdddZejd	d
dddZejd	d
eddZejddZejeejdddZejddZejddZedd Z fddZdd ZG dd dZ   Z!S )
Attendance))r  Present)absentAbsent)r  Late)r  zHalf Day)leaverM   )sickz
Sick Leaver  r   rS   r  r[   Tr]      r_   )r`   ra   r   r   r  r  r   recorded_attendancerZ   r   r   c                 C   s   | j r	| j | j S tdS )z(Calculate total hours including overtimer  )hours_workedr  r   r    r"   r"   r#   r    s   zAttendance.total_hoursc                    s   | j rR| jrRddlm}m} || j| j }|| j| j}||k r)||dd7 }|| }tt| d | _	| j	tdkrM| j	td | _
td| _	ntd| _
t j|i | d S )Nr   )datetimer   rh   r=  i  z8.00r  )check_in_timecheck_out_timern  r   combiner	   r   r  total_secondsrm  r  rv   rw   )r!   r   r   rn  r   check_in	check_out	time_diffr   r"   r#   rw     s   
zAttendance.savec                 C   s   | j j d| j d|   S r   )r   r   r	   get_status_displayr    r"   r"   r#   r$     r   zAttendance.__str__c                   @   s   e Zd ZddgZddgZdS )zAttendance.Metaz-dater   r	   Nr4  r"   r"   r"   r#   r+     s    r+   )"r'   r(   r)   STATUS_CHOICESr   r0   r   r   r   r   r	   r-   r  	TimeFieldro  rp  r   rm  r   r  r.   r   r   r1   recorded_byr6   r7   r8   r   r  rw   r$   r+   r   r"   r"   r   r#   rd    s$    	
rd  )	django.dbr   django.contrib.authr   r|   r   decimalr   rG  django.utilsr   rn  r   r	   dateutil.relativedeltar
   r   Modelr   r   r   r   r  r:  rK  rd  r"   r"   r"   r#   <module>   s&    0 &