You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							153 lines
						
					
					
						
							6.6 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							153 lines
						
					
					
						
							6.6 KiB
						
					
					
				
								# -*- coding: utf-8 -*-
							 | 
						|
								###############################################################################
							 | 
						|
								#
							 | 
						|
								#    Cybrosys Technologies Pvt. Ltd.
							 | 
						|
								#
							 | 
						|
								#    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
							 | 
						|
								#    Author: Noorjahan N A (odoo@cybrosys.com)
							 | 
						|
								#
							 | 
						|
								#    This program is under the terms of the Odoo Proprietary License v1.0
							 | 
						|
								#    (OPL-1) It is forbidden to publish, distribute, sublicense, or
							 | 
						|
								#    sell copies of the Software or modified copies of the Software.
							 | 
						|
								#
							 | 
						|
								#    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
							 | 
						|
								#    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
							 | 
						|
								#    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
							 | 
						|
								#    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
							 | 
						|
								#    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
							 | 
						|
								#    OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
							 | 
						|
								#    THE USE OR OTHER DEALINGS IN THE SOFTWARE.
							 | 
						|
								#
							 | 
						|
								###############################################################################
							 | 
						|
								import datetime
							 | 
						|
								from pandas import date_range
							 | 
						|
								from odoo import api, models
							 | 
						|
								from odoo.tools import date_utils
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								class HrPayslip(models.Model):
							 | 
						|
								    """ Extended model for HR Payslip"""
							 | 
						|
								    _inherit = 'hr.payslip'
							 | 
						|
								
							 | 
						|
								    def holiday(self, day):
							 | 
						|
								        """Get a list of dates for a given frequency.
							 | 
						|
								        Args:
							 | 
						|
								            day (str): Frequency of the dates (e.g., 'W-MON' for Mondays).
							 | 
						|
								        Returns:
							 | 
						|
								            list: List of dates in '%Y-%m-%d' format.
							 | 
						|
								        """
							 | 
						|
								        return date_range(
							 | 
						|
								            start=str(date_utils.start_of(
							 | 
						|
								                self.date_from.replace(month=self.date_from.month - 1),
							 | 
						|
								                'month')),
							 | 
						|
								            end=str(date_utils.end_of(
							 | 
						|
								                self.date_from.replace(month=self.date_from.month + 1),
							 | 
						|
								                'month')),
							 | 
						|
								            freq=day).strftime(
							 | 
						|
								            '%Y-%m-%d').tolist()
							 | 
						|
								
							 | 
						|
								    def get_all_holidays(self):
							 | 
						|
								        """Get all holidays based on the employee's working days.
							 | 
						|
								        Returns:
							 | 
						|
								            list: List of holiday dates in '%Y-%m-%d' format.
							 | 
						|
								        """
							 | 
						|
								        holidays = []
							 | 
						|
								        all_days = ['0', '1', '2', '3', '4', '5', '6']
							 | 
						|
								        for working_hours in \
							 | 
						|
								                self.employee_id.resource_calendar_id.attendance_ids:
							 | 
						|
								            if working_hours.dayofweek in all_days:
							 | 
						|
								                all_days.remove(working_hours.dayofweek)
							 | 
						|
								        for days in all_days:
							 | 
						|
								            if days == '0':
							 | 
						|
								                holidays += self.holiday('W-MON')
							 | 
						|
								            elif days == '1':
							 | 
						|
								                holidays += self.holiday('W-TUE')
							 | 
						|
								            elif days == '2':
							 | 
						|
								                holidays += self.holiday('W-WEN')
							 | 
						|
								            elif days == '3':
							 | 
						|
								                holidays += self.holiday('W-THU')
							 | 
						|
								            elif days == '4':
							 | 
						|
								                holidays += self.holiday('W-FRI')
							 | 
						|
								            elif days == '5':
							 | 
						|
								                holidays += self.holiday('W-SAT')
							 | 
						|
								            elif days == '6':
							 | 
						|
								                holidays += self.holiday('W-SUN')
							 | 
						|
								        return holidays
							 | 
						|
								
							 | 
						|
								    @api.model
							 | 
						|
								    def _get_payslip_lines(self):
							 | 
						|
								        """Compute payslip lines including Loss of Pay (LOP) deduction.
							 | 
						|
								        Returns:
							 | 
						|
								            list: List of payslip line dictionaries.
							 | 
						|
								        """
							 | 
						|
								        res = super(HrPayslip, self)._get_payslip_lines()
							 | 
						|
								        amount, lop_amount = 0, 0
							 | 
						|
								        daily_wage = self.contract_id.wage / 30
							 | 
						|
								        for leave in self.env['hr.leave'].search(
							 | 
						|
								                [('employee_id', '=', self.employee_id.id),
							 | 
						|
								                 ('state', '=', 'validate'),
							 | 
						|
								                 ('request_date_from', '>=', self.date_from),
							 | 
						|
								                 ('request_date_to', '<=', self.date_to)]):
							 | 
						|
								            no_of_days, no_of_days_before, no_of_days_after = 0, 0, 0
							 | 
						|
								            prev_flag, next_flag = 0, 0
							 | 
						|
								            leave_type = ''
							 | 
						|
								            previous_date = leave.request_date_from - datetime.timedelta(
							 | 
						|
								                days=1)
							 | 
						|
								            next_date = leave.request_date_to + datetime.timedelta(days=1)
							 | 
						|
								            holidays = self.get_all_holidays()
							 | 
						|
								            for public_holiday in self.env['resource.calendar.leaves'].search(
							 | 
						|
								                    [("resource_id", "=", False)]):
							 | 
						|
								                holiday_duration = len(date_range(
							 | 
						|
								                    start=public_holiday.date_from.strftime('%Y-%m-%d'),
							 | 
						|
								                    end=public_holiday.date_to.strftime('%Y-%m-%d'),
							 | 
						|
								                ).strftime('%Y-%m-%d').tolist())
							 | 
						|
								                if str(previous_date) == str(
							 | 
						|
								                        public_holiday.date_to.strftime('%Y-%m-%d')):
							 | 
						|
								                    no_of_days += holiday_duration
							 | 
						|
								                    no_of_days_before += holiday_duration
							 | 
						|
								                    prev_flag = 1
							 | 
						|
								                if str(next_date) == str(
							 | 
						|
								                        public_holiday.date_from.strftime('%Y-%m-%d')):
							 | 
						|
								                    no_of_days += holiday_duration
							 | 
						|
								                    no_of_days_after += holiday_duration
							 | 
						|
								                    next_flag = 1
							 | 
						|
								            while str(previous_date) in holidays:
							 | 
						|
								                no_of_days += 1
							 | 
						|
								                no_of_days_before += 1
							 | 
						|
								                prev_flag = 1
							 | 
						|
								                previous_date -= datetime.timedelta(days=1)
							 | 
						|
								            while str(next_date) in holidays:
							 | 
						|
								                no_of_days += 1
							 | 
						|
								                no_of_days_after += 1
							 | 
						|
								                next_flag = 1
							 | 
						|
								                next_date += datetime.timedelta(days=1)
							 | 
						|
								            if not next_flag and prev_flag:
							 | 
						|
								                leave_type = 'after_holiday'
							 | 
						|
								            if next_flag and not prev_flag:
							 | 
						|
								                leave_type = 'before_holiday'
							 | 
						|
								            if next_flag and prev_flag:
							 | 
						|
								                leave_type = 'between_holidays'
							 | 
						|
								                if no_of_days_before > no_of_days_after:
							 | 
						|
								                    no_of_days = no_of_days_before + no_of_days_after
							 | 
						|
								                else:
							 | 
						|
								                    no_of_days = no_of_days_after + no_of_days_before
							 | 
						|
								            lop_amount += daily_wage * (
							 | 
						|
								                    self.env['hr.leave.lop'].search([
							 | 
						|
								                        ('no_of_days', '=', no_of_days),
							 | 
						|
								                        ('leave_type', '=', leave_type)],
							 | 
						|
								                    ).deduction_amount / 100)
							 | 
						|
								            amount = lop_amount + (leave.number_of_days_display-1) * daily_wage
							 | 
						|
								        res.append({'sequence': 250,
							 | 
						|
								                    'code': 'LOP',
							 | 
						|
								                    'name': 'Loss of Pay',
							 | 
						|
								                    'salary_rule_id': self.env['hr.salary.rule'].search(
							 | 
						|
								                        [("name", "=", "Deduction"),
							 | 
						|
								                         ("id", "in", self.struct_id.rule_ids.ids)]).id,
							 | 
						|
								                    'contract_id': self.contract_id.id,
							 | 
						|
								                    'employee_id': self.employee_id.id,
							 | 
						|
								                    'amount': -amount,
							 | 
						|
								                    'quantity': 1.0,
							 | 
						|
								                    'rate': 100,
							 | 
						|
								                    'slip_id': self.id
							 | 
						|
								                    })
							 | 
						|
								        return res
							 | 
						|
								
							 |