# -*- coding: utf-8 -*- ################################################################################### # A part of OpenHrms Project # # Cybrosys Technologies Pvt. Ltd. # Copyright (C) 2018-TODAY Cybrosys Technologies (). # Author: Saritha Sahadevan () # # This program is free software: you can modify # it under the terms of the GNU Affero General Public License (AGPL) as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . # ################################################################################### from datetime import datetime, timedelta from odoo import models, fields, api, _, tools class HrPayroll(models.Model): _inherit = 'hr.payslip' @api.model def get_worked_day_lines(self, contract_ids, date_from, date_to): """ @param contract_ids: list of contract id @return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to """ def was_on_leave_interval(employee_id, date_from, date_to): date_from = fields.Datetime.to_string(date_from) date_to = fields.Datetime.to_string(date_to) return self.env['hr.holidays'].search([ ('state', '=', 'validate'), ('employee_id', '=', employee_id), ('type', '=', 'remove'), ('date_from', '<=', date_from), ('date_to', '>=', date_to) ], limit=1) res = [] # fill only if the contract as a working schedule linked uom_day = self.env.ref('product.product_uom_day', raise_if_not_found=False) for contract in self.env['hr.contract'].browse(contract_ids).filtered(lambda contract: contract): uom_hour = contract.employee_id.resource_id.calendar_id.uom_id or self.env.ref('product.product_uom_hour', raise_if_not_found=False) interval_data = [] holidays = self.env['hr.holidays'] attendances = { 'name': _("Normal Working Days paid at 100%"), 'sequence': 1, 'code': 'WORK100', 'number_of_days': 0.0, 'number_of_hours': 0.0, 'contract_id': contract.id, } leaves = {} # Gather all intervals and holidays for days in contract.shift_schedule: start_date = datetime.strptime(days.start_date, tools.DEFAULT_SERVER_DATE_FORMAT) end_date = datetime.strptime(days.end_date, tools.DEFAULT_SERVER_DATE_FORMAT) nb_of_days = (end_date - start_date).days + 1 for day in range(0, nb_of_days): working_intervals_on_day = days.hr_shift.get_working_intervals_of_day( start_dt=start_date + timedelta(days=day)) for interval in working_intervals_on_day: interval_data.append( (interval, was_on_leave_interval(contract.employee_id.id, interval[0], interval[1]))) # Extract information from previous data. A working interval is considered: # - as a leave if a hr.holiday completely covers the period # - as a working period instead for interval, holiday in interval_data: holidays |= holiday hours = (interval[1] - interval[0]).total_seconds() / 3600.0 if holiday: # if he was on leave, fill the leaves dict if holiday.holiday_status_id.name in leaves: leaves[holiday.holiday_status_id.name]['number_of_hours'] += hours else: leaves[holiday.holiday_status_id.name] = { 'name': holiday.holiday_status_id.name, 'sequence': 5, 'code': holiday.holiday_status_id.name, 'number_of_days': 0.0, 'number_of_hours': hours, 'contract_id': contract.id, } else: # add the input vals to tmp (increment if existing) attendances['number_of_hours'] += hours # Clean-up the results leaves = [value for key, value in leaves.items()] for data in [attendances] + leaves: data['number_of_days'] = uom_hour._compute_quantity(data['number_of_hours'], uom_day) \ if uom_day and uom_hour \ else data['number_of_hours'] / 8.0 res.append(data) return res