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.
121 lines
5.6 KiB
121 lines
5.6 KiB
# -*- coding: utf-8 -*-
|
|
|
|
from datetime import timedelta, datetime
|
|
from odoo import models, fields, api, _
|
|
|
|
|
|
class WorkedDayOvertime(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 = []
|
|
normal_hours = 0
|
|
total_hours = 0
|
|
number_of_days = 0
|
|
contract_id = []
|
|
# fill only if the contract as a working schedule linked
|
|
uom_day = self.env.ref('product.product_uom_day', raise_if_not_found=False)
|
|
contract_id = []
|
|
for contract in self.env['hr.contract'].browse(contract_ids).filtered(lambda contract: contract.working_hours):
|
|
contract_val = 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 = {}
|
|
day_from = fields.Datetime.from_string(date_from)
|
|
day_to = fields.Datetime.from_string(date_to)
|
|
nb_of_days = (day_to - day_from).days + 1
|
|
|
|
# Gather all intervals and holidays
|
|
for day in range(0, nb_of_days):
|
|
working_intervals_on_day = contract.working_hours.get_working_intervals_of_day(
|
|
start_dt=day_from + 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
|
|
if data['name'] == 'Normal Working Days paid at 100%':
|
|
number_of_days = data['number_of_days']
|
|
normal_hours = data['number_of_hours']
|
|
contract_id = data['contract_id']
|
|
res.append(data)
|
|
|
|
date_from = fields.Datetime.from_string(date_from)
|
|
date_from += timedelta(days=-1)
|
|
date_from = str(date_from)
|
|
date_to = fields.Datetime.from_string(date_to)
|
|
date_to += timedelta(days=1)
|
|
date_to = str(date_to)
|
|
for attn_lines in self.env['hr.attendance'].search([('check_in', '>=', date_from),
|
|
('check_out', '<=', date_to),
|
|
('employee_id', '=', contract_val.employee_id.id)]):
|
|
check_in = datetime.strptime(attn_lines.check_in, '%Y-%m-%d %H:%M:%S')
|
|
check_out = datetime.strptime(attn_lines.check_out, '%Y-%m-%d %H:%M:%S')
|
|
time_diff = check_out - check_in
|
|
total_hours += ((time_diff.seconds / 60) / 60)
|
|
ovt_hours = total_hours - normal_hours
|
|
|
|
if ovt_hours > 0:
|
|
res.append({
|
|
'code': 'OVT',
|
|
'contract_id': contract_id,
|
|
'number_of_days': number_of_days,
|
|
'number_of_hours': ovt_hours,
|
|
'name': 'Overtime Hours',
|
|
})
|
|
return res
|
|
|