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.
		
		
		
		
		
			
		
			
				
					
					
						
							109 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							109 lines
						
					
					
						
							5.2 KiB
						
					
					
				| # -*- coding: utf-8 -*- | |
| ################################################################################### | |
| #    A part of OpenHrms Project <https://www.openhrms.com> | |
| # | |
| #    Cybrosys Technologies Pvt. Ltd. | |
| #    Copyright (C) 2018-TODAY Cybrosys Technologies (<https://www.cybrosys.com>). | |
| #    Author: Saritha Sahadevan (<https://www.cybrosys.com>) | |
| # | |
| #    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 <https://www.gnu.org/licenses/>. | |
| # | |
| ################################################################################### | |
| 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 |