Search code examples
pythonapiodooodoo-15

Calculate leaves days in Odoo CE


using HR Payroll Community.

Trying to fix this Code.

The code of Calculating leaves in Payslip:

@api.model
def get_worked_day_lines(self, contracts, date_from, date_to):
    """
    @param contract: Browse record of contracts
    @return: returns a list of dict containing the input that should be applied for the given contract between date_from and date_to
    """
    res = []
    # fill only if the contract as a working schedule linked
    for contract in contracts.filtered(lambda contract: contract.resource_calendar_id):
        day_from = datetime.combine(fields.Date.from_string(date_from), datetime_time.min)
        day_to = datetime.combine(fields.Date.from_string(date_to), datetime_time.max)

        # compute leave days
        leaves = {}
        day_leave_intervals = contract.employee_id.list_leaves(day_from, day_to, calendar=contract.resource_calendar_id)
        for day_intervals in day_leave_intervals:
            for interval in day_intervals:
                holiday = interval[2]['leaves'].holiday_id
                current_leave_struct = leaves.setdefault(holiday.holiday_status_id, {
                    'name': holiday.holiday_status_id.name,
                    'sequence': 5,
                    'code': holiday.holiday_status_id.name,
                    'number_of_days': 0.0,
                    'number_of_hours': 0.0,
                    'contract_id': contract.id,
                })
                leave_time = (interval[1] - interval[0]).seconds / 3600
                current_leave_struct['number_of_hours'] += leave_time
                work_hours = contract.employee_id.get_day_work_hours_count(interval[0].date(), calendar=contract.resource_calendar_id)
                if work_hours:
                    current_leave_struct['number_of_days'] += leave_time / work_hours

        # compute worked days
        work_data = contract.employee_id.get_work_days_data(day_from, day_to, calendar=contract.resource_calendar_id)
        attendances = {
            'name': _("Normal Working Days paid at 100%"),
            'sequence': 1,
            'code': 'WORK100',
            'number_of_days': work_data['days'],
            'number_of_hours': work_data['hours'],
            'contract_id': contract.id,
        }
        res.append(attendances)
        attendance_lines = self.env['hr.attendance'].search([('employee_id', '=', contract.employee_id.id), ('check_in', '>=', date_from), ('check_out', '<=', date_to)])
        if attendance_lines:
            total_hours = sum(attendance_lines.mapped('worked_hours')) or 0.00
            attendance_hours = {
                'name': _("Attendence Hours"),
                'sequence': 1,
                'code': 'ATTNHOURS',
                'number_of_days': 0.00,
                'number_of_hours': total_hours,
                'contract_id': contract.id,
            }
            res.append(attendance_hours)

        res.extend(leaves.values())
    return res

The Error returning the Following:

    models/hr_payslip.py", line 50, in get_worked_day_lines
    holiday = interval[2]['leaves'].holiday_id
Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/opt/odoo15/odoo/odoo/http.py", line 644, in _handle_exception
    return super(JsonRequest, self)._handle_exception(exception)
  File "/opt/odoo15/odoo/odoo/http.py", line 302, in _handle_exception
    raise exception.with_traceback(None) from new_cause
TypeError: 'datetime.date' object is not subscriptable

I am trying to add the Attendance within the Payslip, but im getting this error once i import public holidays into the "Public Holidays" module. Any Advice ? Thanks.


Solution

  • The list_leaves is a list of tuples : [(start.date(), hours, leave), ...].

    In the first loop day_intervals will be set to a tuple value (start.date(), hours, leave), in the second loop interval will be one of the following values date, hours, or leave and the error happens when Odoo uses the [] notation with a date object.

    for day_intervals in day_leave_intervals:
        for interval in day_intervals:
            # In the first iteration `interval` is set to `start.date()`, a date object
            holiday = interval[2]['leaves'].holiday_id
        
    

    There should be a single loop, like in the original code:

    for day, hours, leave in day_leave_intervals:
        holiday = leave.holiday_id