Time off

The hr_holidays module (Time Off application) lets employees request time off, managers approve it, and HR grant the time that can be taken. It is built on:

  • the work entry types (hr.work.entry.type): in 20.0, hr.leave.type was merged into them, so a time off type is a work entry type, extended by hr_holidays with the time off configuration;

  • the time off requests (hr.leave): a period of absence (or of working time out of the office) of an employee, which goes through an approval flow;

  • the allocations (hr.leave.allocation): the time granted to an employee for a type, fixed or earned over time with accrual plans, see Time off allocations and accruals;

  • the resource leaves (resource.calendar.leaves): validated time off creates one, which removes the time from the working schedule, hence from the work entries and the payslips;

  • the mandatory days (hr.leave.mandatory.day): days on which employees cannot request time off.

This page covers the types, the requests and their effects; allocations, balances and accruals are covered in Time off allocations and accruals.

Veja também

Working schedules for the schedules and leaves the durations are computed from, Working time and calendars for the calendars of employees over time and Work entries for the work entries and the time rules.

Nota

The examples run in odoo-bin shell on a database with hr_holidays and its demo data. The shell runs as superuser, which bypasses the approval checks: the examples first switch to the administrator, a time off administrator, with env = env(user=env.ref('base.user_admin')).

Time off types

A time off type is a hr.work.entry.type with time_off_selectable set. Its work entry fields (code, country_id, count_as, amount_rate, see Work entry types) apply to the time off as to any work entry. hr_holidays adds:

requires_allocation

Whether the time must be granted by an allocation first (e.g. paid time off), or can be taken freely (e.g. sick leave, unpaid leave). It cannot be changed once requests of the type exist.

request_unit

The granularity of the requests: day, half_day or hour (Custom Hours). Requests of a type by hour can also be taken by day or half day.

unit_of_measure

The unit the type is allocated and counted in: hour (default) or day. Balances are expressed in this unit.

leave_validation_type and allocation_validation_type

Who approves the requests and the allocations: no_validation, hr (By HR Responsible, default), manager (By Time Off Approver) or both (time off approver, then HR). See States and approval.

count_days_as

working (default): the duration counts the working days of the schedule; calendar: every day counts. include_public_holidays_in_duration (Ignore Public Holidays) counts the public holidays as time off instead of deducting them. count_days_as cannot be changed once requests of the type exist, include_public_holidays_in_duration once requests of the current year overlap a public holiday.

allows_negative and max_allowed_negative

Let the balance go below zero, down to -max_allowed_negative.

employee_requests

Whether employees can request allocations of the type themselves.

allow_request_on_top

Allow other requests to overlap the requests of this type; only for working time types.

elligible_for_accrual_rate

Whether the time off counts as worked time for the accrual plans based on worked time. Always set for working time types.

create_calendar_meeting, support_document, color, hide_on_dashboard, …

User interface options: a calendar event per validated request, a supporting document notice, dashboard display.

The type also has non-stored fields computed for the employee of the context (employee_id or default_employee_id, else the user’s employee): max_leaves, leaves_taken, virtual_remaining_leaves and has_valid_allocation. With employee_id in the context, the display name also shows the balance.

Aviso

count_as defaults to working_time on hr.work.entry.type. An absence type must set count_as = 'absence', otherwise its time off counts as worked time in the schedules, the work entries and the payslips.

Example

from datetime import date

env = env(user=env.ref('base.user_admin'))
employee = env['hr.employee'].search([('name', '=', 'Ronnie Hart')])
pto, unpaid = env['hr.work.entry.type'].create([{
    'name': 'Paid Time Off',
    'code': 'DOCPTO',
    'count_as': 'absence',
    'requires_allocation': True,
    'request_unit': 'half_day',
    'unit_of_measure': 'day',
    'leave_validation_type': 'manager',
}, {
    'name': 'Unpaid Leave',
    'code': 'DOCUNPAID',
    'count_as': 'absence',
    'amount_rate': 0.0,
    'requires_allocation': False,
    'request_unit': 'hour',
    'leave_validation_type': 'no_validation',
}])
pto.country_id.code, pto.allocation_validation_type, pto.elligible_for_accrual_rate
# ('US', 'hr', False): the country of the company, defaults

env['hr.leave.allocation'].create({
    'employee_id': employee.id,
    'work_entry_type_id': pto.id,
    'number_of_days': 20,
    'date_from': date(2026, 1, 1),
}).action_approve()
pto.with_context(employee_id=employee.id).read(['max_leaves', 'virtual_remaining_leaves'])
# [{'id': ..., 'max_leaves': 20.0, 'virtual_remaining_leaves': 20.0}]
pto.with_context(employee_id=employee.id).display_name
# 'Paid Time Off (20 remaining out of 20 days)'

Time off requests

A request (hr.leave) belongs to an employee (employee_id) and has a type (work_entry_type_id). Its period is entered with the request fields, and computed into date_from and date_to:

request_date_from, request_date_to

The first and last days (date), in the employee’s timezone.

request_date_from_period, request_date_to_period

am or pm, for types by half day: a request from Monday afternoon to Wednesday morning is ('pm', 'am').

request_hour_from, request_hour_to

Float hours (13.5 is 13:30) in the employee’s timezone, for types by hour. When both are 0, the hours of the schedule are used.

date_from, date_to

Naive UTC datetimes, computed by _compute_date_from_to(). A day starts at the first working hour and ends at the last working hour of the schedule of the employee’s version on that day (a day off takes the hours of the nearest working day, see _get_hours_for_date()); a half day starts or ends at noon. Never write them: write the request fields.

resource_calendar_id

The working schedule of the version in contract during the request, computed. A request cannot span versions with different schedules (_check_contracts()).

number_of_days, number_of_hours

The duration, computed, see Durations.

request_duration (full, am, pm, specific) and request_date_hour_from / request_date_hour_to are form and calendar view helpers, converted from and to the request fields.

Example

Paid time off from Monday to Wednesday morning, created by the administrator for another employee, and an unpaid leave of two hours and a half:

leave = env['hr.leave'].create({
    'employee_id': employee.id,
    'work_entry_type_id': pto.id,
    'request_date_from': date(2026, 11, 16),
    'request_date_to': date(2026, 11, 18),
    'request_date_to_period': 'am',
})
leave.date_from, leave.date_to, leave.tz
# (datetime.datetime(2026, 11, 16, 7, 0), datetime.datetime(2026, 11, 18, 11, 0),
#  'Europe/Brussels'): 8:00 to 12:00 local time
leave.number_of_days, leave.number_of_hours, leave.state
# (2.5, 20.0, 'validate')
leave.display_name
# 'Ronnie Hart on Paid Time Off: 2.5 days (11/16/2026 to 11/18/2026)'

hourly = env['hr.leave'].create({
    'employee_id': employee.id,
    'work_entry_type_id': unpaid.id,
    'request_date_from': date(2026, 11, 20),
    'request_date_to': date(2026, 11, 20),
    'request_hour_from': 13.5,
    'request_hour_to': 16.0,
})
hourly.date_from, hourly.date_to, hourly.number_of_days, hourly.number_of_hours
# (datetime.datetime(2026, 11, 20, 12, 30), datetime.datetime(2026, 11, 20, 15, 0),
#  0.313, 2.5)

The paid time off is approved at once: see States and approval.

Durations

number_of_days and number_of_hours are computed by _get_durations(), which can also be called directly (it returns {leave.id: (days, hours)} without assigning the fields). The hours are the working hours of the request’s schedule between date_from and date_to, for the employee (see The resource mixin), minus the absence leaves: public holidays and other validated absences of the employee, but not the request itself. Then:

  • types by day round the days up to whole days, types by half day to half days; _get_durations() with check_work_entry_type=False gives the real number of working days;

  • with count_days_as = 'calendar', every day of the period counts (public holidays still deducted, unless include_public_holidays_in_duration), at the hours per day of the schedule;

  • with include_public_holidays_in_duration, public holidays are not deducted;

  • a single day request of an employee with a flexible schedule counts the real length of the request (minus public holidays), the hours of a flexible schedule having no position in the day;

  • working time types outside the schedule (e.g. a business trip on a Saturday) count their days, or their clock hours for types by hour.

The days of a request by hour are its hours divided by the hours of a day of the schedule.

Example

One week, Monday to Sunday, with a public holiday on Tuesday:

from datetime import datetime

day_type, half_type, hour_type = env['hr.work.entry.type'].create([{
    'name': f'Leave by {unit}',
    'code': f'DOC{unit.upper()}',
    'count_as': 'absence',
    'requires_allocation': False,
    'request_unit': unit,
    'leave_validation_type': 'no_validation',
} for unit in ('day', 'half_day', 'hour')])
env['resource.calendar.leaves'].create({
    'name': 'Founders Day',  # no resource: a public holiday
    'date_from': datetime(2026, 12, 8, 7, 0),
    'date_to': datetime(2026, 12, 8, 15, 0),
    'company_id': employee.company_id.id,
})

week = env['hr.leave'].create({
    'employee_id': employee.id,
    'work_entry_type_id': day_type.id,
    'request_date_from': date(2026, 12, 7),
    'request_date_to': date(2026, 12, 13),
})
week.number_of_days, week.number_of_hours  # (4.0, 32.0)

ph_counted, calendar_days = env['hr.work.entry.type'].create([{
    'name': 'PH counted', 'code': 'DOCPH', 'count_as': 'absence',
    'requires_allocation': False, 'include_public_holidays_in_duration': True,
}, {
    'name': 'Calendar days', 'code': 'DOCCAL', 'count_as': 'absence',
    'requires_allocation': False, 'count_days_as': 'calendar',
}])
for leave_type in (ph_counted, calendar_days):
    probe = env['hr.leave'].new({
        'employee_id': employee.id,
        'work_entry_type_id': leave_type.id,
        'request_date_from': date(2026, 12, 7),
        'request_date_to': date(2026, 12, 13),
    })
    print(leave_type.name, probe.number_of_days, probe.number_of_hours)
# PH counted 5.0 40.0
# Calendar days 6.0 48.0

The same afternoon requested with each unit (the hours are ignored by the types by day and half day, the periods by the type by hour):

for leave_type in (day_type, half_type, hour_type):
    probe = env['hr.leave'].new({
        'employee_id': employee.id,
        'work_entry_type_id': leave_type.id,
        'request_date_from': date(2026, 12, 15),
        'request_date_to': date(2026, 12, 15),
        'request_date_from_period': 'pm',
        'request_date_to_period': 'pm',
        'request_hour_from': 9.0,
        'request_hour_to': 11.0,
    })
    print(leave_type.request_unit, probe.date_from, probe.date_to,
          probe.number_of_days, probe.number_of_hours)
# day 2026-12-15 07:00:00 2026-12-15 15:00:00 1.0 8.0
# half_day 2026-12-15 11:00:00 2026-12-15 15:00:00 0.5 4.0
# hour 2026-12-15 08:00:00 2026-12-15 10:00:00 0.25 2.0

States and approval

digraph leave_states {
   rankdir=LR;
   node [shape=box, style=rounded, fontname="sans-serif", fontsize=10];
   edge [fontname="sans-serif", fontsize=9];
   confirm [label="confirm\n(To Approve)"];
   validate1 [label="validate1\n(Second Approval)"];
   validate [label="validate\n(Approved)"];
   refuse [label="refuse\n(Refused)"];
   cancel [label="cancel\n(Cancelled)"];
   confirm -> validate1 [label="first approval\n(type 'both')"];
   confirm -> validate [label="action_approve"];
   validate1 -> validate [label="action_approve"];
   confirm -> refuse [label="action_refuse"];
   validate1 -> refuse;
   validate -> refuse;
   validate -> confirm [label="action_back_to_approval"];
   validate -> cancel [label="_action_user_cancel"];
}

A request is created in confirm. The validation type of its type decides who approves it:

no_validation

The request is approved on creation.

hr

A time off officer (hr_holidays.group_hr_holidays_user) approves it.

manager

The employee’s time off approver (hr.employee.leave_manager_id, Time Off Approver, defaulting to the manager’s user) approves it, or an officer.

both

The time off approver gives a first approval (validate1), then an officer approves it.

On creation, _process_auto_approve_activities() approves the request right away when its type has no validation or when an officer creates it for another employee; otherwise, it schedules an approval activity for _get_responsible_for_approval(): the time off approver (or the manager’s user, or the HR responsible) for manager and the first step of both, the employee’s HR responsible (hr_responsible_id) for hr and the second step of both.

The actions are:

action_approve()

Validates the request if the user can (_action_validate()), else gives the first approval of a both type. Officers validate in one step, whatever the type. With check_state=False, rights are not checked.

action_refuse()

Refuses a request to approve or approved.

action_back_to_approval()

Resets approved requests to confirm.

_action_user_cancel() and _force_cancel()

Cancel a request, the first one checking that the user can (an employee can cancel their own requests unless they started). The Cancel button opens the hr.holidays.cancel.leave wizard, which calls the first one with a reason.

What the current user may do is given by _get_next_states_by_state() ({state: set(next_states)}) and checked by _check_approval_update(), which writing state also calls. The fields can_approve, can_validate, can_refuse, can_cancel and can_back_to_approve expose it to the views. The superuser bypasses these checks.

Example

Marc Demo (user base.user_demo) requests time off; his time off approver is the administrator:

demo = env.ref('base.user_demo')
marc = demo.employee_id
marc.leave_manager_id.name  # 'Mitchell Admin'

vacation = env['hr.work.entry.type'].create({
    'name': 'Vacation',
    'code': 'DOCVAC',
    'count_as': 'absence',
    'requires_allocation': False,
    'leave_validation_type': 'manager',
})
leave = env['hr.leave'].with_user(demo).create({
    'employee_id': marc.id,
    'work_entry_type_id': vacation.id,
    'request_date_from': date(2026, 12, 7),
    'request_date_to': date(2026, 12, 8),
})
leave.state  # 'confirm'
leave.activity_ids.mapped(lambda a: (a.activity_type_id.name, a.user_id.name))
# [('Time Off Approval', 'Mitchell Admin')]
leave._get_next_states_by_state()['confirm']  # set(): Marc cannot approve it

leave.with_user(env.user).action_approve()
leave.state, leave.first_approver_id.name  # ('validate', 'Mitchell Admin')

With a type validated twice, Marc approves the request of Randall Lewis, whose time off approver he is, then the administrator validates it:

vacation.leave_validation_type = 'both'
randall = env['hr.employee'].search([('name', '=', 'Randall Lewis')])
leave = env['hr.leave'].with_user(demo).create({
    'employee_id': randall.id,
    'work_entry_type_id': vacation.id,
    'request_date_from': date(2026, 12, 9),
    'request_date_to': date(2026, 12, 9),
})
leave.action_approve()
leave.state, leave.first_approver_id.name  # ('validate1', 'Marc Demo')
leave.with_user(env.user).action_approve()
leave.state, leave.second_approver_id.name  # ('validate', 'Mitchell Admin')

hr_holidays defines the groups Employee (group_hr_holidays_employee, every internal user), Time Off Responsible (group_hr_holidays_responsible, given automatically to the users set as time off approvers), Officer: Manage all requests (group_hr_holidays_user) and Administrator (group_hr_holidays_manager). Users who are not officers only access their own requests and the requests of the employees they approve; officers access all the requests of their companies. The description of a request (name, stored in private_name) is only readable by officers, the employee and their time off approver.

Checks

Creating or changing a request checks that:

  • it does not overlap another request of the employee with the same count_as, unless one of their types has allow_request_on_top (_check_date, skipped with the context key leave_skip_date_check);

  • it is covered by the allocations of the employee when the type requires one (_check_validity(), see Balances);

  • it is not on a mandatory day, for users who are not officers (same method);

  • an approved request is not moved without being reset first (_check_date_state);

  • an absence by hour does not exceed the planned hours of its days (_get_max_allowed_absence_hours());

  • it does not span versions with different schedules (_check_contracts()).

Validating an absence of zero hours, e.g. on a public holiday, raises a ValidationError (The following employees are not supposed to work during that period), except for a few sick and work accident types (_get_leaves_on_public_holiday()).

Resource leaves

Validation (_validate_leave_request()) creates a resource.calendar.leaves record per request (_create_resource_leave()), from _prepare_resource_leave_vals(): the employee’s resource, the request’s schedule, date_from and date_to, the type (work_entry_type_id, count_as, elligible_for_accrual_rate) and the request itself (holiday_id). This leave is what the rest of Odoo sees: the work intervals of the employee (see Working schedules), the planning and Gantt views, the work entries and the payslips.

It follows the request: leaving the validate state (refusal, reset, cancellation, deletion) removes it (_remove_resource_leave()), and changing the dates or the type of a validated request rewrites it (_amend_resource_leave_dates()). Validation also creates a calendar event (meeting_id) when the type has create_calendar_meeting.

Example

leave = env['hr.leave'].search([('employee_id', '=', marc.id), ('state', '=', 'validate'),
                                ('work_entry_type_id', '=', vacation.id)])
env['resource.calendar.leaves'].search([('holiday_id', '=', leave.id)]).read(
    ['resource_id', 'calendar_id', 'date_from', 'date_to', 'work_entry_type_id',
     'count_as'])
# [{'id': ..., 'resource_id': (3, 'Marc Demo'), 'calendar_id': (1, '40 hours/week'),
#   'date_from': datetime.datetime(2026, 12, 7, 7, 0),
#   'date_to': datetime.datetime(2026, 12, 8, 15, 0),
#   'work_entry_type_id': (..., 'Vacation'), 'count_as': 'absence'}]

leave.action_refuse()
leave.state  # 'refuse'
env['resource.calendar.leaves'].search_count([('holiday_id', '=', leave.id)])  # 0

Public holidays

Public holidays are global leaves: resource.calendar.leaves without resource_id, for a company and optionally a calendar (see Leaves). Two public holidays of the same company and calendar cannot overlap. hr_holidays:

  • deducts them from the duration of the requests, unless the type has include_public_holidays_in_duration;

  • recomputes the requests overlapping a public holiday when it is created, changed or deleted (_reevaluate_leaves()): their duration changes, the employee is notified, and a request no longer covered by its allocations is refused;

  • creates the public holidays of the next year from the CSV files of hr_holidays/data/public_holidays/, with a monthly cron (_cron_generate_public_holidays()) and the Load Public Holidays wizard (which gives them the type of code 006.00).

In the work entries, a public holiday wins over a time off on the same day, unless the type code of the time off is listed by _get_bypassing_work_entry_type_codes (see Computing the raw values).

Example

Continuing the previous examples, a request on the public holiday only, then a second public holiday during the week of time off of the durations example:

env['hr.leave'].create({
    'employee_id': marc.id,
    'work_entry_type_id': day_type.id,
    'request_date_from': date(2026, 12, 8),
    'request_date_to': date(2026, 12, 8),
})
# ValidationError: The following employees are not supposed to work during that period:
#  Marc Demo

env['resource.calendar.leaves'].create({
    'name': 'Extra day',
    'date_from': datetime(2026, 12, 10, 7, 0),
    'date_to': datetime(2026, 12, 10, 15, 0),
    'company_id': employee.company_id.id,
})
week.number_of_days, week.state  # (3.0, 'validate')

Mandatory days

A mandatory day (hr.leave.mandatory.day) is a period (start_date to end_date) during which employees must work, e.g. an inventory. It applies to the employees of its company_id, and can be restricted to a working schedule (resource_calendar_id), job positions (job_ids) and departments (department_ids, sub-departments included). _get_mandatory_days() returns the ones applying to an employee.

Users who are not time off officers cannot create requests overlapping a mandatory day; officers can, and the request’s has_mandatory_day is then set. The calendar views show them with get_special_days_data().

Example

env['hr.leave.mandatory.day'].create({
    'name': 'Year-end inventory',
    'start_date': date(2026, 12, 17),
    'end_date': date(2026, 12, 18),
    'color': 2,
})
marc._get_mandatory_days(date(2026, 12, 1), date(2026, 12, 31)).mapped('name')
# ['Year-end inventory']
marc.get_mandatory_days(date(2026, 12, 1), date(2026, 12, 31))
# {'2026-12-17': 2, '2026-12-18': 2}

vals = {
    'employee_id': marc.id,
    'work_entry_type_id': vacation.id,
    'request_date_from': date(2026, 12, 18),
    'request_date_to': date(2026, 12, 18),
}
env['hr.leave'].with_user(demo).create(vals)
# ValidationError: You are not allowed to request time off on a Mandatory Day.
env['hr.leave'].create(vals).has_mandatory_day  # True

Work entries and payroll

Validated time off reaches the work entries through its resource leave (see Computing the raw values). hr_holidays extends hr.version (HrVersion) so that:

The count_as and type used are the ones stored on the resource leave, copied at validation; the paid rate comes from amount_rate. Payroll then turns the work entries into worked days by type code.

Example

The week of the durations example (two public holidays):

vals_list = employee.version_id.generate_work_entries(date(2026, 12, 7), date(2026, 12, 11))
sorted((vals['date'].isoformat(), vals['work_entry_type_id'].code, vals['duration'],
        vals.get('leave_ids')) for vals in vals_list)
# [('2026-12-07', 'DOCDAY', 8.0, hr.leave(...)), ('2026-12-08', '006.00', 8.0, None),
#  ('2026-12-09', 'DOCDAY', 8.0, hr.leave(...)), ('2026-12-10', '006.00', 8.0, None),
#  ('2026-12-11', 'DOCDAY', 8.0, hr.leave(...))]

Time rules. hr.leave is a time rule source (hr.time.rule.source.mixin, see Time rule sources): when a validated request is created or changed, the rules whose condition_work_entry_type_ids include its type reclassify the time beyond (or missing from) their threshold. The outputs are validated requests linked to their source (source_leave_id, output_leave_ids, time_rule_id); a source cut by a rule is flagged is_time_rule_trimmed. Absences are clipped to the schedule before being measured (_get_pipeline_intervals_local()). Rules can also credit the excess to an allocation, see Allocations from time rules. _get_generated_leave_domain() matches the requests created by rules.

Versions, departures and splits

Requests follow the contract of the employee:

  • creating or changing a version (contract dates, date_version, resource_calendar_id) gives the requests the schedule of their version and recomputes them; a request now spanning versions with different schedules is split into one request per version, the last part being to approve again (_populate_all_new_leave_vals_from_split_leave()); approved requests starting before a new contract and overlapping it are refused;

  • registering a departure (hr.employee.departure.action_register) cuts the requests at the departure date, cancels the approved ones after it, deletes the others (or refuses them, see _check_refuse_future_leaves_condition()) and ends or deletes the allocations (_cleanup_employee_departure_leaves()).

Two helpers split requests:

_split_leaves()

Removes a period from the requests, keeping the parts before and after it; returns the created requests.

_create_leaves_from_split()

Splits a request into consecutive requests of other types, e.g. a sick leave paid by the employer for its first days then by the social security; localizations compute the split and _get_work_entry_type_change_warning() describes it.

Pitfalls

  • Write the request fields (request_date_from, request_hour_from, …), never date_from and date_to: they are recomputed from the request fields.

  • An officer creating a request for another employee approves it, with all its effects (resource leave, work entries, time rules); create it in confirm with another user, or reset it with action_back_to_approval().

  • Approved requests must be reset to confirm before their dates change.

  • The shell runs as superuser: rights and transitions are not checked. Test approval flows with with_user().

  • A failed create in a try block may leave partial data in the transaction (e.g. the first part of a batch): use env.cr.savepoint().

  • max_leaves and virtual_remaining_leaves on types depend on the employee in the context; without it, they are computed for the current user’s employee.

  • The resource leave keeps the count_as of the type at validation: changing the type’s count_as does not change approved requests.

Extending

Resource leave

_prepare_resource_leave_vals() to add values to the resource leave.

Approval

_get_next_states_by_state(), _check_approval_update() and _get_responsible_for_approval().

Durations

_get_durations() (called by the compute, and by the forms), _get_max_allowed_absence_hours() for the maximum hours of an absence.

Splits and departures

_get_extra_default_leave_values_for_split(), _check_refuse_future_leaves_condition().

Work entries

The hr.version hooks of Extending, e.g. _get_leave_work_entry_type_dates to change the type of a long absence after some days.

Reference

Original definition from hr_holidays

model odoo.addons.hr_holidays.models.hr_leave.HrLeave[código fonte]
_name = hr.leave

Time off request of an employee.

The request goes through the states confirm, validate1 (first approval of the types validated twice), validate, refuse and cancel; the transitions the current user may perform are given by _get_next_states_by_state() and checked by _check_approval_update(). The description (name, stored in private_name) is only readable by time off officers, the employee and their time off approver. Users who are not officers only access their own requests and the requests of the employees they approve, and a multi-company rule applies to everyone.

employee_id: int
Required

Name

Employee

Comodel

hr.employee

work_entry_type_id: int
Required

Name

Time Type

Comodel

hr.work.entry.type

state: str
Name

Status

Selection

confirm: To Approve refuse: Refused validate1: Second Approval validate: Approved cancel: Cancelled

Default

confirm

request_date_from: datetime.date
Name

Request Start Date

request_date_to: datetime.date
Name

Request End Date

request_date_from_period: str
Name

Date Period Start

Selection

am: Morning pm: Afternoon

Default

am

request_date_to_period: str
Name

Date Period End

Selection

am: Morning pm: Afternoon

Default

pm

request_hour_from: float
Name

Hour from

request_hour_to: float
Name

Hour to

date_from: datetime.datetime
Name

Start Date

Readonly

this field is not supposed to/cannot be set manually

date_to: datetime.datetime
Name

End Date

Readonly

this field is not supposed to/cannot be set manually

number_of_days: float
Name

Duration (Days)

Readonly

this field is not supposed to/cannot be set manually

Number of days of the time off request. Used in the calculation.

number_of_hours: float
Name

Duration (Hours)

Number of hours of the time off request. Used in the calculation.

resource_calendar_id: int
Name

Resource Calendar

Comodel

resource.calendar

validation_type: str
Name

None

first_approver_id: int
Name

First Approval

Readonly

this field is not supposed to/cannot be set manually

Comodel

hr.employee

This area is automatically filled by the user who validate the time off

second_approver_id: int
Name

Second Approval

Readonly

this field is not supposed to/cannot be set manually

Comodel

hr.employee

This area is automatically filled by the user who validate the time off with second level (If time type need second validation)

meeting_id: int
Name

Meeting

Comodel

calendar.event

has_mandatory_day: bool
Name

Has Mandatory Day

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

time_rule_id: int
Name

Time Rule

Comodel

hr.time.rule

source_leave_id: int
Name

Source Leave

Comodel

hr.leave

output_leave_ids: Sequence[odoo.orm.commands.Command]
Name

Output Leave

Comodel

hr.leave

is_time_rule_trimmed: bool
Name

Trimmed by Time Rule

Default

False

Set when a time rule trims this leave’s end to sub-day precision. Prevents _compute_date_from_to from snapping the end back to the schedule boundary.

create(vals_list)[código fonte]

Create time off requests, check them and start their approval.

Requests whose type is selectable are checked with _check_validity() (unless the context has skip_check_validity). Each request is then auto-approved or gets approval activities (_process_auto_approve_activities()) and the time rules run on it. With the context key leave_fast_create, the double validation rights, the approval and the time rules are skipped, and the validated requests directly get their resource leave.

write(vals)[código fonte]

Write on time off requests, keeping their resource leave in sync.

Changing the state checks _check_approval_update(). Leaving the 'validate' state removes the resource leave and reverses the time rule allocation credits; changing the dates or the type of a validated request amends its resource leave (_amend_resource_leave_dates()). Users who are not officers cannot modify started or cancelled requests.

Delete requests, after reversing their time rule credits and removing their leaves.

_compute_date_from_to()[código fonte]

Compute date_from and date_to (naive UTC) from the request fields.

The bounds are taken in the employee’s timezone: requests in hours use request_hour_from/request_hour_to (or the hours of the schedule when both are 0), half days the hours of the morning or afternoon, days the first and last working hours of the first and last days (see _get_hour_from_to()). Time rule outputs and trimmed sources keep the dates written by the time rules.

_get_hour_from_to(request_date_from, request_date_to, day_period=None, count_non_working_days=False)[código fonte]

Return the local hours a request starts and ends at.

The start is the first hour of the schedule of the employee on request_date_from, the end the last hour on request_date_to, see _get_hours_for_date(). Working time types in hours keep their explicit hours, or last the planned hours of the day from its start.

Parâmetros
  • request_date_from (datetime.date) – first day

  • request_date_to (datetime.date) – last day

  • day_period (str) – 'morning' or 'afternoon' for a half day

  • count_non_working_days (bool) – count the days off as working days, centered on noon

Retorna

(hour_from, hour_to) as float hours

Tipo de retorno

tuple

_to_utc(date, hour, resource)[código fonte]

Return the naive UTC datetime of hour on date in the resource’s timezone.

Parâmetros
  • date (datetime.date) – local day

  • hour (float) – local hour, capped at 24

  • resource – record with a tz field (employee); the user’s timezone without it

Tipo de retorno

datetime.datetime

_get_durations(check_work_entry_type=True, resource_calendar=None, additional_domain=None)[código fonte]

Compute the duration of the requests without assigning the fields.

Factored out of _compute_duration so it can be called or overridden without triggering the computes depending on number_of_days/number_of_hours. The hours are the working hours of the schedule within [date_from, date_to], minus the absence leaves: public holidays (unless the type has include_public_holidays_in_duration) and the other validated absences of the employee, but not the leave itself nor its time rule source. Then:

  • types counted in calendar days (count_days_as = 'calendar') count every day;

  • a flexible schedule counts the real length of a single-day request;

  • types requested by day are rounded up to whole days, half days to half days;

  • working time types outside the schedule count the days, or the clock hours.

Parâmetros
  • check_work_entry_type (bool) – False to skip the rounding to whole days of the types requested by day (gives the real number of working days)

  • resource_calendar – resource.calendar to use instead of resource_calendar_id

  • additional_domain – domain added to the one of the deducted leaves

Retorna

{leave.id: (number_of_days, number_of_hours)}, (0, 0) for requests without dates

Tipo de retorno

dict

_plans_hours_on_the_clock(worked_hours)[código fonte]

Tell whether the duration in hours of the request is clock time.

True for working time types requested in hours when the request is on a single day or covers no working time: the end is then date_from plus the duration, not planned on the schedule.

Parâmetros

worked_hours (float) – working hours of the schedule within the request days

Tipo de retorno

bool

_inverse_number_of_hours()[código fonte]

Move the end of the requests to give them the number_of_hours set.

Only for requests to approve: the end is planned on the version’s schedule from date_from (or on the clock, see _plans_hours_on_the_clock()) and written on request_date_to/request_hour_to.

Levanta

ValidationError – if the hours do not fit in the working time of the request days

_subtract_public_holidays(public_holidays)[código fonte]

Return the clock hours of the request minus the given public holidays.

Parâmetros

public_holidays – global resource.calendar.leaves

Tipo de retorno

float

_get_allowed_request_durations()[código fonte]

Return the values of request_duration the request can use.

['full'] for requests over several days and types requested by day, ['full', 'am', 'pm'] for half days, plus 'specific' for types requested in hours.

Tipo de retorno

list[str]

_get_request_duration(date_from, period_from, date_to, period_to)[código fonte]

Return the request_duration of a request given its bounds.

Retorna

period_from ('am' or 'pm') for a lone half day, 'full' otherwise

Tipo de retorno

str

_get_request_date_hours(reader_tz)[código fonte]

Return the bounds a calendar view draws the request on.

Requests in hours return their date_from/date_to with the wall clock of the request’s timezone restamped in reader_tz (8:00 in Tokyo is drawn at 8:00 in Brussels). Days and half days return midnight or noon of their first and last days in reader_tz, so that moving them by half a day is moving them by one period.

Parâmetros

reader_tz (zoneinfo.ZoneInfo) – timezone of the reader, see _reader_tz()

Retorna

(start, stop) naive UTC datetimes, (False, False) without request dates

Tipo de retorno

tuple

_get_request_vals_from_date_hours(date_hour_from, date_hour_to)[código fonte]

Return the request values matching bounds drawn by a calendar view.

Reverse of _get_request_date_hours(); the stop is exclusive, so 00:00 on D+1 ends the afternoon of D. An empty bound keeps its current value.

Parâmetros
  • date_hour_from (datetime) – new start, naive UTC

  • date_hour_to (datetime) – new end, naive UTC

Retorna

values to write (request dates, periods, hours, request_duration), {} when the bounds are invalid or unchanged

Tipo de retorno

dict

_reader_tz()[código fonte]

Return the timezone the request is read in, the one the web client draws it on.

Tipo de retorno

zoneinfo.ZoneInfo

reschedule_from_calendar(date_from, date_to)[código fonte]

Move a request to the bounds a calendar view displays.

Converts date_from/date_to with _get_request_vals_from_date_hours() and writes the request fields. An approved request needing validation goes back to 'confirm'.

Parâmetros
  • date_from – new start, as displayed (request_date_hour_from)

  • date_to – new end, as displayed (request_date_hour_to)

_check_validity()[código fonte]

Check that the requests are covered by allocations and avoid mandatory days.

For the types requiring an allocation (unless the context has skip_allocation_check), the balance of the employee on the first day of the request must cover it, within max_allowed_negative when the type allows a negative balance (see hr.work.entry.type.get_allocation_data()). Users who are not time off officers cannot request time off on a mandatory day.

With the context key multi_leave_request, the employees without enough allocation are returned instead of raising (used to create time off for several employees at once).

Retorna

(employees_without_allocation, zero_duration_employees), the second being the employees with an absence of zero hours (only with multi_leave_request)

Tipo de retorno

tuple

Levanta

ValidationError – when a request is not covered

_get_allocation_balance(target_date)[código fonte]

Return the balance of the allocations each request can use on target_date.

Counts the allocations not expired on target_date, based on _get_consumed_leaves().

Parâmetros

target_date (datetime.date) – date of the balance

Retorna

{leave: (virtual_remaining_leaves, max_leaves)}, in the unit of the type (unit_of_measure)

Tipo de retorno

dict

_check_contracts()[código fonte]

Forbid a time off over several versions with different working schedules.

A time off can still end up across such versions when the versions are changed after its creation (hr.version then splits it, see hr_holidays’s hr.version). Skipped with the context key skip_leave_version_check and for time rule outputs.

_get_overlapping_contracts()[código fonte]

Return the versions in contract of the employee overlapping the request dates.

Tipo de retorno

hr.version

_get_max_allowed_absence_hours(base_max_hours)[código fonte]

Hook returning the maximum number of hours of an absence requested in hours.

_check_max_absence_per_day passes the planned hours of the request days (24 per day for flexible schedules); localizations can raise or lower it.

Parâmetros

base_max_hours (float) – the default maximum

Tipo de retorno

float

_check_double_validation_rules(employees, state)[código fonte]

Check the rights to approve requests of a type validated twice ('both').

Time off administrators may do everything. Otherwise, a first approval ('validate1') requires being the time off approver of the employees or a time off officer, and the second one ('validate') being a time off officer.

Parâmetros
  • employees – hr.employee of the requests

  • state (str) – target state

Levanta

AccessError – when not allowed

_process_auto_approve_activities()[código fonte]

Approve a new request automatically, or notify its approvers.

The request is approved (as superuser) when its type needs no validation, or when it is created by a time off officer for another employee. Otherwise, approval activities are scheduled for _get_responsible_for_approval().

action_approve(check_state=True)[código fonte]

Approve the requests.

A request goes to 'validate' (see _action_validate()) when the user can validate it, otherwise to 'validate1' (first approval of a type validated twice) when the user can approve it. Time off officers can validate in one step.

Parâmetros

check_state (bool) – False to skip the rights check: types validated twice go to 'validate1', others are validated

Levanta

UserError – when the user can neither approve nor validate a request

_action_validate(check_state=True)[código fonte]

Validate the requests (state 'validate').

Sets the approvers, creates the resource leaves and meetings (_validate_leave_request()), closes the activities and runs the time rules.

Parâmetros

check_state (bool) – check that the user can validate the requests

Levanta
action_refuse()[código fonte]

Refuse requests to approve or approved: the resource leaves and meetings are removed.

Levanta

UserError – when a request is not 'confirm', 'validate1' or 'validate'

action_back_to_approval()[código fonte]

Reset to 'confirm' the requests the user may reset; others are ignored.

_move_validate_leave_to_confirm()[código fonte]

Reset the requests to 'confirm', removing their meetings and resource leaves.

_action_user_cancel(reason=None)[código fonte]

Cancel a request on behalf of its employee, see _force_cancel().

Parâmetros

reason (str) – reason posted on the request

Levanta

ValidationError – when the user cannot cancel the request (can_cancel)

_force_cancel(reason=None, msg_subtype='mail.mt_comment', notify_responsibles=True)[código fonte]

Cancel the requests without checking the rights.

The state becomes 'cancel', the meetings and resource leaves are removed. With a reason, it is posted on each request and the approvers who already approved it are notified.

Parâmetros
  • reason (str) – reason of the cancellation

  • msg_subtype (str) – xmlid of the subtype of the posted message

  • notify_responsibles (bool) – notify the approvers

_post_leave_cancel()[código fonte]

Archive the meetings and remove the resource leaves of the requests.

Undo the effects of the requests before their deletion.

Reverses the time rule allocation credits, archives the meetings and removes the resource leaves.

_get_next_states_by_state()[código fonte]

Return the states the current user can move the request to, from each state.

Officers can move between all states (and to 'validate1' for types validated twice), time off approvers of the employee can approve and refuse depending on the validation type, and employees can cancel their own requests, unless started.

Retorna

{state: set(next_states)}

Tipo de retorno

dict

_check_approval_update(state, raise_if_not_possible=True)[código fonte]

Check that the current user can move the requests to state.

Based on _get_next_states_by_state(); the superuser can do everything.

Parâmetros
  • state (str) – target state

  • raise_if_not_possible (bool) – raise instead of returning False

Tipo de retorno

bool

Levanta

UserError – when not possible and raise_if_not_possible

_get_responsible_for_approval()[código fonte]

Return the user who must approve the request in its current state.

For the approval by the time off approver ('manager', or 'both' in 'confirm'): the employee’s leave_manager_id, else the manager’s user, else the HR responsible. For the approval by HR ('hr', or 'both' in 'validate1'): the employee’s hr_responsible_id.

Tipo de retorno

res.users

activity_update()[código fonte]

Schedule or close the approval activities according to the state of the requests.

_notify_leave_request()[código fonte]

Notify the approvers (_get_responsible_for_approval()) of new requests.

_notify_manager()[código fonte]

Notify the time off approver of the employee when a request it approved is refused.

_notify_change(message, subtype_xmlid='mail.mt_note')[código fonte]

Post message on the requests and notify their employee.

Parâmetros
  • message (str) – message to post

  • subtype_xmlid (str) – subtype of the posted message

_get_leaves_on_public_holiday()[código fonte]

Return the absences of zero duration, which cannot be validated.

Such a request covers no working time (e.g. a public holiday). Some types (sick leave, maternity, work accident codes) are accepted anyway.

Tipo de retorno

hr.leave

_validate_leave_request()[código fonte]

Apply the effects of the validation of the requests.

Creates the resource leaves (_create_resource_leave()), the calendar events when the type has create_calendar_meeting, and posts a message to the employee.

_prepare_resource_leave_vals()[código fonte]

Return the values of the resource.calendar.leaves of a validated request.

Hook to add values. The leave copies the type (work_entry_type_id, count_as, elligible_for_accrual_rate), the dates and the calendar of the request, and is linked to the employee’s resource and to the request (holiday_id).

Tipo de retorno

dict

_create_resource_leave()[código fonte]

Create the resource.calendar.leaves of the requests, replacing existing ones.

Requests with an empty span get none. Called on validation.

Retorna

the created leaves

Tipo de retorno

resource.calendar.leaves

_remove_resource_leave()[código fonte]

Delete the resource.calendar.leaves of the requests (on refusal, cancellation, …).

_amend_resource_leave_dates()[código fonte]

Update the resource leaves of validated requests whose dates or type changed.

Rewrites them with _prepare_resource_leave_vals(); requests without resource leave are ignored.

_split_leaves(split_date_from, split_date_to=False)[código fonte]

Cut the requests out of a period, keeping the parts before and after it.

[request_date_from, request_date_to] becomes [request_date_from, split_date_from - 1 day] and [split_date_to, request_date_to]; parts without working time are dropped. The request keeps the first part (or the only one), a copy in the same state is created for the other one. Used when an employee leaves the company.

Parâmetros
  • split_date_from (datetime.date) – first day removed

  • split_date_to (datetime.date) – first day kept after the cut; defaults to split_date_from, which cuts the request in two without removing anything

Retorna

the created requests

Tipo de retorno

hr.leave

_get_split_hour_vals(date_from=None, date_to=None)[código fonte]

Return the hours of a part of a request in hours cut by _split_leaves().

The part whose first (or last) day changes takes the first (or last) hour of the schedule on that day.

Tipo de retorno

dict

_create_leaves_from_split(leave_split, use_worked_days=False)[código fonte]

Split the request into consecutive requests of the given types and durations.

Used by localizations to switch the type of a long absence (e.g. a sick leave paid by the employer, then by the social security). With a single entry, only the type of the request changes.

Parâmetros
  • leave_split (list) – (work_entry_type, number_of_days) tuples, in order

  • use_worked_days (bool) – count the working days of the schedule instead of the calendar days

Retorna

the request and the created ones

Tipo de retorno

hr.leave

_get_extra_default_leave_values_for_split()[código fonte]

Hook returning extra values for the requests created when splitting.

See _create_leaves_from_split().

Tipo de retorno

dict

_get_work_entry_type_change_warning(leave_split)[código fonte]

Return the message warning that the request will be split or change type.

Parâmetros

leave_split (list) – see _create_leaves_from_split()

Tipo de retorno

str

_get_request_date_to(number_of_days, days_data)[código fonte]

Return the day at which number_of_days working days are reached, from the start.

Parâmetros
  • number_of_days (float) – number of working days

  • days_data (list) – (date, duration) of the working days

Retorna

the day, False if not reached

_get_request_date_to_with_period(number_of_days, work_intervals)[código fonte]

Return the day and the period at which number_of_days working days are reached.

Parâmetros
  • number_of_days (float) – number of working days, possibly with a half day

  • work_intervals – work intervals of the request

Retorna

(date, 'am' or 'pm'), False if not reached

_get_calendar_days(date_min=datetime.date(1, 1, 1), date_max=datetime.date(9999, 12, 31))[código fonte]

Return the number of calendar days of the request within [date_min, date_max].

Half days are counted as 0.5.

Tipo de retorno

float

_get_calendar_days_between_leaves(leave_from, leave_to)[código fonte]

Return the number of calendar days between two requests.

The days strictly between the end of leave_from and the start of leave_to.

Half days are counted as 0.5.

Parâmetros
  • leave_from – the first hr.leave

  • leave_to – the second hr.leave

Tipo de retorno

float

_cancel_invalid_leaves()[código fonte]

Cron: cancel the requests of the next 31 days that accruals will not cover.

Only types with an accrual allocation are checked: a request whose balance on its start date exceeds the allowed negative amount is cancelled.

get_unusual_days(date_from, date_to=None)[código fonte]

Return the unusual days of the employee of the context (or of the user).

See _get_unusual_days().

Retorna

{'YYYY-MM-DD': bool}

Tipo de retorno

dict

_get_generated_leave_domain()[código fonte]

Return the domain of the leaves generated by time rules (outputs and remainders).

Tipo de retorno

odoo.fields.Domain

_get_search_request_date_hour_from_to_domain(date_field, hour_field, operator, value)[código fonte]

Search request_date_hour_from/request_date_hour_to on the stored request fields.

Mirrors _get_request_date_hours(): the day is compared on date_field, the hour on hour_field for requests in hours, on the period for half days.

Parâmetros
  • date_field (str) – 'request_date_from' or 'request_date_to'

  • hour_field (str) – 'request_hour_from' or 'request_hour_to'

Tipo de retorno

odoo.fields.Domain

_apply_record_output(rules, excess, deficit, active_iv=None)[código fonte]

Apply the result of the time rules on the requests.

See _apply_leave_output().

_get_pipeline_intervals_local(schedule)[código fonte]

Return the parts of the request that the time rules consider.

Absences are clipped to the schedule: nights, breaks and days off within the request do not count toward the thresholds. Other types keep their whole span.

Parâmetros

schedule (Intervals) – schedule of the employee, naive local datetimes

Retorna

list of (start, stop) naive datetimes in the employee’s timezone

Tipo de retorno

list

_get_source_extra_fields_domain()[código fonte]

Only validated requests are time rule sources.

Tipo de retorno

list

_get_write_source_extra_source_fields()[código fonte]

Run the time rules again when the type or the state of a request changes.

Tipo de retorno

set[str]

_get_time_rule_end_write_vals(end_utc, stop_local)[código fonte]

Return the values shortening a request to end_utc.

Writes date_to and the request fields; requests by day or half day are flagged is_time_rule_trimmed so that their end is not recomputed from the schedule.

Parâmetros
  • end_utc (datetime) – new end, naive UTC

  • stop_local (datetime) – the same instant in the employee’s timezone

Tipo de retorno

dict

_get_time_rule_deficit_occupied(employee_id, start_utc, period_end_utc)[código fonte]

Return the validated time off of the employee within a period.

Deficit outputs are only placed outside these intervals.

Parâmetros
  • employee_id (int) – employee id

  • start_utc (datetime) – naive UTC

  • period_end_utc (datetime) – naive UTC

Retorna

intervals of naive UTC datetimes

Tipo de retorno

Intervals

_get_time_rule_output_vals(rule, df, dt, pp)[código fonte]

Return the creation values of an output time off.

See _get_output_leave_vals().

Tipo de retorno

dict

_get_time_rule_remainder_vals(df, dt)[código fonte]

Return the creation values of a remainder: a validated time off linked to the source.

Parâmetros
  • df (datetime) – start, naive UTC

  • dt (datetime) – end, naive UTC

Tipo de retorno

dict

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.hr_work_entry_type.HrWorkEntryType[código fonte]
requires_allocation: bool
Required

Name

Requires Allocation

Default

True

request_unit: str
Required

Name

Duration Type

Selection

day: Full Day half_day: Half-Day hour: Custom Hours

Default

day

Define the minimum time off duration in which an employee can take when requesting a leave

unit_of_measure: str
Required

Name

Unit

Selection

hour: Hours day: Days

Default

hour

Define if the time type will be allocated/accrued in hours or days

leave_validation_type: str
Name

Time Off Validation

Selection

no_validation: None hr: By HR Responsible manager: By Time Off Approver both: By HR Responsible and Time Off Approver

Default

hr

allocation_validation_type: str
Name

Approval

Selection

no_validation: None hr: By HR Responsible manager: By Time Off Approver both: By HR Responsible and Time Off Approver

Default

hr

Select the level of approval needed in case of request by employee

# - No validation needed: The employee’s request is automatically approved. # - Approved by Time Off Officer: The employee’s request need to be manually approved # by the Time Off Officer, Employee’s Approver or both.

employee_requests: bool
Required

Name

Allow Employee Requests

Default

False

Extra Days Requests Allowed: User can request an allocation for himself.

Not Allowed: User cannot request an allocation.

count_days_as: str
Name

Count Days as

Selection

working: Working Days calendar: Calendar Days

Default

working

If you take a leave on the whole week, worked days will result in a various number based on the working hours of the employee, calendar days will result in 7 in every case.

include_public_holidays_in_duration: bool
Name

Ignore Public Holidays

Default

False

Public holidays should be counted in the leave duration when applying for leaves

allows_negative: bool
Name

Allow Negative

If checked, users request can exceed the allocated days and balance can go in negative.

max_allowed_negative: int
Name

Maximum Excess Amount

Define the maximum level of negative days this kind of time off can reach. Value must be at least 1.

allow_request_on_top: bool
Name

Allow Request on Top

Default

False

If checked, users can request another leave on top of the ones of this type.

elligible_for_accrual_rate: bool
Name

Eligible for Accrual Rate

If checked, this time type will be taken into account for accruals computation.

time_off_selectable: bool
Name

Selectable in Time Off

Default

True

create_calendar_meeting: bool
Name

Display Time Off in Calendar

Default

True

If this field is checked, every leave request of this type will have a corresponding entry in the calendar application. There will be no entry if this stays unchecked.

max_leaves: float
Name

Maximum Allowed

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

This value is given by the sum of all time off requests with a positive value.

leaves_taken: float
Name

Time off Already Taken

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

This value is given by the sum of all time off requests with a negative value.

virtual_remaining_leaves: float
Name

Virtual Remaining Time Off

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

Maximum Time Off Allowed - Time Off Already Taken - Time Off Waiting Approval

has_valid_allocation: bool
Name

Has Valid Allocation

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

This indicates if it is still possible to use this type of leave

get_allocation_data(employees, target_date=None, same_year_only=False)[código fonte]

Return the balance of the employees for each type of self on a date.

Sums the data of _get_consumed_leaves() over the allocations valid on target_date. Amounts are in the unit_of_measure of the type, rounded to 2 digits. Requests listed in the context key ignored_leave_ids are ignored.

Parâmetros
  • employees – hr.employee records

  • target_date – date, datetime or ISO string, today by default

  • same_year_only (bool) – only count the allocations starting in the year of target_date and the requests starting that year

Retorna

{employee: [(type name, data, requires_allocation, type id), ...]}, where data holds max_leaves, leaves_taken and remaining_leaves (approved), virtual_leaves_taken and virtual_remaining_leaves (also to approve), leaves_requested, leaves_approved, accrual_bonus, closest_allocation_expire (formatted date), closest_allocation_remaining, closest_allocation_duration, holds_changes, total_virtual_excess, virtual_excess_data, exceeding_duration and type information (request_unit, unit_of_measure, allows_negative, max_allowed_negative, color, …)

Tipo de retorno

dict

get_allocation_data_request(target_date=None, hidden_allocations=True, same_year_only=False)[código fonte]

Return the balances of the contextual employee for every type.

With the context key from_dashboard, types without allocated time are left out.

Parâmetros
  • target_date – date of the balances, today by default

  • hidden_allocations (bool) – include the types hidden on the dashboard

  • same_year_only (bool) – see get_allocation_data()

Retorna

list of tuples, see get_allocation_data()

Tipo de retorno

list

get_work_entry_types_with_valid_allocations(date_from, date_to, employee_id)[código fonte]

Return the types of self the employee can request time off of during a period.

Types without allocation always; types requiring an allocation when a validated one covers the whole period and is an accrual or has a positive balance (within the negative cap).

Parâmetros
  • date_from – first day

  • date_to – last day

  • employee_id (int) – employee id

Tipo de retorno

hr.work.entry.type

has_accrual_allocation()[código fonte]

Tell whether the contextual employee has a validated accrual allocation still running.

Tipo de retorno

bool

has_future_allocation()[código fonte]

Tell whether the contextual employee has a validated allocation starting in the future.

Tipo de retorno

bool

_get_closest_expiring_leaves_date_and_count(allocations, remaining_leaves, target_date, primary_unit)[código fonte]

Return the next date some remaining time expires, and how much.

Time expires at the end of an allocation, on a carry-over date when unused time is lost or limited, and at the end of the validity of carried over time.

Parâmetros
  • allocations – hr.leave.allocation with remaining time

  • remaining_leaves (dict) – {allocation: data} of _get_consumed_leaves()

  • target_date (datetime.date) – reference date

  • primary_unit (str) – 'days' or 'hours'

Retorna

(date, amount), (None, 0) when nothing expires

Tipo de retorno

tuple

_get_carried_over_days_expiration_data(allocations, target_date)[código fonte]

Return when the time carried over by accrual allocations expires, and how much.

Retorna

{allocation: {'expiration_date': date or None, 'no_expiring_days': float}}

Tipo de retorno

dict

_search_valid(operator, value)[código fonte]

Search has_valid_allocation: types with a validated allocation for an employee.

The employee is the context’s default_employee_id, employee_id or the user’s employee; the period is default_date_from/default_date_to (with tz) from the context, or the current year.

_search(domain, offset=0, limit=None, order=None, **kwargs)[código fonte]

Sort the types with _model_sorting_key() when an employee is in the context.

Only when the default order is requested; the sort is done in Python before offset and limit are applied.

_model_sorting_key(work_entry_type)[código fonte]

Return the sort key of the types in _search() (sequence).

_check_allow_request_on_top()[código fonte]

Forbid requests on top of absences.

_check_elligible_for_accrual_rate()[código fonte]

Working time types always count for the accruals.

_check_overlapping_public_holidays()[código fonte]

Forbid changing whether public holidays count when this year’s requests overlap one.

_check_leaves_for_count_days_as()[código fonte]

Forbid changing count_days_as once requests of the type exist.

check_allocation_requirement_edit_validity()[código fonte]

Forbid changing requires_allocation once requests of the type exist.

Original definition from hr_holidays

model odoo.addons.hr_holidays.models.hr_leave_mandatory_day.HrLeaveMandatoryDay[código fonte]
_name = hr.leave.mandatory.day
start_date: datetime.date
Required

Name

Start Date

end_date: datetime.date
Required

Name

End Date

company_id: int
Required

Name

Company

Comodel

res.company

resource_calendar_id: int
Name

Working Hours

Comodel

resource.calendar

department_ids: Sequence[odoo.orm.commands.Command]
Name

Departments

Comodel

hr.department

job_ids: Sequence[odoo.orm.commands.Command]
Name

Job Position

Comodel

hr.job

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.hr_employee.HrEmployee[código fonte]
leave_manager_id: int
Name

Time Off Approver

Comodel

res.users

Select the user responsible for approving “Time Off” of this employee. If empty, the approval is done by an Administrator or Approver (determined in settings/users).

current_leave_state: str
Name

Current Time Off Status

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

Selection

confirm: Waiting Approval refuse: Refused validate1: Waiting Second Approval validate: Approved cancel: Cancelled

leave_date_from: datetime.date
Name

From Date

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

leave_date_to: datetime.date
Name

To Date

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

is_absent: bool
Name

Absent Today

Readonly

this field is not supposed to/cannot be set manually

Store

this field is there only for technical reasons

create(vals_list)[código fonte]

Default the time off approver to the manager’s user and give it the approver group.

write(vals)[código fonte]

Keep the time off approver and the pending requests in sync with the employee.

The time off approver follows the manager when it was the previous manager’s user, the approver group is granted to new approvers and removed from former ones, and a new department is copied on the requests to approve or in the future.

_get_consumed_leaves(work_entry_types, target_date=False, ignore_future=False, precomputed_allocations={}, same_year_only=False)[código fonte]

Compute, per allocation, the time off taken and the balance of the employees.

The requests to approve or approved ('confirm', 'validate1', 'validate') of the given types are deducted from the validated allocations covering them, in this order: allocations with an end date (the earliest first), accrual allocations, then the others. Requests starting after target_date while an accrual allocation runs are not deducted but rechecked against the future accrual. The amounts are in the unit_of_measure of each type. Requests listed in the context key ignored_leave_ids are ignored.

Parâmetros
  • work_entry_types – hr.work.entry.type records to consider

  • target_date (datetime.date) – date of the balance, today by default; the accrual allocations include what they will have accrued by then

  • ignore_future (bool) – only consider requests starting by target_date and no future accrual

  • precomputed_allocations (dict) – {allocation: allocation_data} already computed for target_date (see hr.leave.allocation._process_accrual_plans()), used as is

  • same_year_only (bool) – only consider requests starting in the year of target_date

Retorna

(consumed, to_recheck):

  • consumed[employee][work_entry_type][allocation] is a dict with the keys <unit>_max_leaves, <unit>_accrual_bonus (accrual granted by target_date), <unit>_leaves_taken and <unit>_remaining_leaves (approved requests only), <unit>_virtual_leaves_taken and <unit>_virtual_remaining_leaves (all requests), where <unit> is days or hours after the type’s unit, plus <other unit>_taken and <other unit>_remaining in the other unit. Types without allocation use the key False instead of an allocation.

  • to_recheck[employee][work_entry_type] is a dict with excess_days ({date: {'amount', 'is_virtual', 'leave_id'}}, the time not covered by any allocation), to_recheck_leaves (the future requests not deducted) and exceeding_duration (negative or zero, what the future accrual will miss to cover them).

Tipo de retorno

tuple

_get_hours_per_day(date_from)[código fonte]

Return the hours per day of the employee’s calendar on date_from.

24 for a fully flexible calendar, 0 on an empty recordset. Single employee.

Tipo de retorno

float

_get_hours_for_date(target_date, day_period=None, count_non_working_days=False)[código fonte]

Return the local hours a working day of the employee starts and ends at.

From the schedule of the version on target_date (the company’s schedule on an empty recordset). A day off borrows the hours of the nearest working day, the day after first; a fully flexible schedule returns (0, 24). Duration-based attendances, flexible schedules and count_non_working_days give the hours per day centered on noon.

Parâmetros
  • target_date (datetime.date) – the day

  • day_period (str) – 'morning' or 'afternoon' to get the hours of a half day

  • count_non_working_days (bool) – treat days off as working days

Retorna

(hour_from, hour_to) as float hours

Tipo de retorno

tuple

_get_mandatory_days(start_date, end_date)[código fonte]

Return the mandatory days applying to the employee within a period.

A mandatory day applies when it is in the employee’s company and has no calendar or the employee’s calendar, no job or the employee’s job, and no department or the employee’s department or one of its parents.

Parâmetros
Tipo de retorno

hr.leave.mandatory.day

get_mandatory_days(start_date, end_date)[código fonte]

Return the colors of the mandatory days of the employee (or of the user’s employee).

Retorna

{'YYYY-MM-DD': color}

Tipo de retorno

dict

get_mandatory_days_data(date_start, date_end)[código fonte]

Return the mandatory days of the contextual employee as calendar events.

Retorna

list of dicts (id, title, start, end, colorIndex, …)

Tipo de retorno

list

_get_public_holidays(date_start, date_end)[código fonte]

Return the public holidays of the employee’s company and calendar within a period.

Parâmetros
  • date_start – start of the period

  • date_end – end of the period

Tipo de retorno

resource.calendar.leaves

get_public_holidays_data(date_start, date_end)[código fonte]

Return the public holidays of the contextual employee as calendar events.

Retorna

list of dicts (id, title, start, end, isAllDay, …)

Tipo de retorno

list

get_special_days_data(date_start, date_end)[código fonte]

Return the mandatory days and public holidays of the contextual employee.

Used by the calendar views.

Retorna

{'mandatoryDays': [...], 'bankHolidays': [...]}, see get_mandatory_days_data() and get_public_holidays_data()

Tipo de retorno

dict

get_time_off_dashboard_data(target_date=None)[código fonte]

Return the data of the time off dashboard of the contextual employee.

Parâmetros

target_date – date of the balances, today by default

Retorna

{'has_future_allocation', 'has_accrual_allocation', 'allocation_data', 'allocations_number'}, allocation_data being the result of hr.work.entry.type.get_allocation_data_request()

Tipo de retorno

dict

get_allocations_number()[código fonte]

Return the number of allocations of the contextual employee waiting for approval.

Tipo de retorno

int

_get_contextual_employee()[código fonte]

Return the employee of the context, or the user’s employee.

The context keys employee_id and default_employee_id are read in this order.

Tipo de retorno

hr.employee

_compute_leave_status()[código fonte]

Compute the time off status of the employees now.

leave_date_from, current_leave_state and is_absent come from the validated time off in progress; leave_date_to is the day the employee is back: the first working day after the end of that time off or of the public holiday in progress.

_get_first_working_interval_batch(min_dts)[código fonte]

Return the start of the first work interval of each employee after a datetime.

Looks up to two years ahead, in the calendars of the versions in contract, then in the current calendar.

Parâmetros

min_dts (dict) – {employee_id: naive UTC datetime}

Retorna

{employee_id: naive UTC datetime}, without the employees who never work

Tipo de retorno

dict

_adjust_leaves(leave_intervals)[código fonte]

Extend the leave intervals of time off by day or half day to whole days or halves.

A time off by day covers its days from midnight to midnight, a half day from midnight or noon to noon or midnight.

Parâmetros

leave_intervals (Intervals) – leave intervals of one employee

Tipo de retorno

Intervals

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.hr_version.HrVersion[código fonte]

Write and Create: Special case when setting a contract as running: If there is already a validated time off over another contract with a different schedule, split the time off, before the _check_contracts raises an issue. If there are existing leaves that are spanned by this new contract, update their resource calendar to the current one.

create(vals_list)[código fonte]

Create versions, moving the time off of the employees to the new working schedules.

See the class docstring; also creates the allocation of the working schedule’s accrual plan (_action_trigger_accrual_plan_working_schedule()).

write(vals)[código fonte]

Write on versions, moving the time off when the contract dates or the schedule change.

Time off spanning versions with different schedules is split, others get the new schedule. Changing the schedule also preserves the hours of allocations in hours and recreates the working schedule’s accrual allocation.

_check_contracts()[código fonte]

Check that the time off of the versions does not span different working schedules.

_get_leaves(extra_domain=None, min_date=None)[código fonte]

Return the time off of the versions’ employees ending after min_date.

Parâmetros
  • extra_domain – domain added to the search

  • min_date (datetime.date) – defaults to the earliest start of the versions

Tipo de retorno

hr.leave

_get_leaves_from_vals(vals)[código fonte]

Return the time off a version created with vals impacts.

The employee’s requests not refused or cancelled, on another schedule, within the contract.

Parâmetros

vals (dict) – creation values of a version

Tipo de retorno

hr.leave

_check_overlapping_contract(leave)[código fonte]

Return the versions in contract overlapping leave, sorted by start date.

Tipo de retorno

hr.version

_update_leave_calendar(leave, overlapping_contracts)[código fonte]

Give leave the schedule of the first overlapping version and recompute its dates.

Parâmetros
_update_leave_state(leave, leaves_state, refuse_leave=False)[código fonte]

Remember the state of leave, then refuse it or reset it to 'confirm'.

Parâmetros
  • leave – hr.leave

  • leaves_state (dict) – {leave_id: state}, updated

  • refuse_leave (bool) – refuse instead of resetting

Retorna

leaves_state

Tipo de retorno

dict

_populate_all_new_leave_vals_from_split_leave(all_new_leave_origin, all_new_leave_vals, overlapping_contracts, leave, leaves_state)[código fonte]

Prepare one request per overlapping version to replace leave.

The parts keep the original state, except the last one which is to approve again.

Retorna

(all_new_leave_origin, all_new_leave_vals), extended

Tipo de retorno

tuple

_create_all_new_leave(all_new_leave_origin, all_new_leave_vals)[código fonte]

Create the requests prepared by _populate_all_new_leave_vals_from_split_leave().

Validated ones get their resource leaves; each one gets a link to its origin.

_get_leave_work_entry_type(leave)[código fonte]

Return the type of the time off of the leave (holiday_id), else the leave’s type.

Parâmetros

leave – resource.calendar.leaves

Tipo de retorno

hr.work.entry.type

_get_more_vals_leave_interval(interval, leaves)[código fonte]

Add ('leave_ids', time off) for the leaves of time off containing interval.

Tipo de retorno

list

_get_interval_leave_work_entry_type(interval, leaves, bypassing_codes)[código fonte]

Return the type of a leave interval, arbitrating overlapping leaves.

Priority: time off whose type code is in bypassing_codes, then global leaves (public holidays), then other time off.

Parâmetros
  • interval (tuple) – (start, stop, payload)

  • leaves (list) – (start, stop, resource.calendar.leaves) tuples

  • bypassing_codes (list) – codes of the types winning over public holidays

Tipo de retorno

hr.work.entry.type

_get_sub_leave_domain()[código fonte]

Also accept the leaves of the time off of the employees, whatever their calendar.

Tipo de retorno

odoo.fields.Domain

_generate_work_entries_postprocess_adapt_to_calendar(vals)[código fonte]

Compute the duration of time off not requested in hours from the schedule.

Time rule outputs keep their real span.

Parâmetros

vals (dict) – raw work entry value

Tipo de retorno

bool

_get_work_entry_source_fields()[código fonte]

Add leave_ids to the keys merged when work entry values are combined.

Tipo de retorno

list[str]

_action_trigger_accrual_plan_working_schedule()[código fonte]

Recreate the allocation granted by the accrual plan of the working schedule.

Working schedules with a work time rate above 100% and a leave_accrual_plan_id give the employee an accrual allocation over the version’s period (allocation_from_working_schedule_id), replacing the previous one.

Levanta

ValidationError – when the previous allocation was already used

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.resource_calendar_leaves.ResourceCalendarLeaves[código fonte]
holiday_id: int
Name

Time Off Request

Comodel

hr.leave

elligible_for_accrual_rate: bool
Name

Eligible for Accrual Rate

Default

False

If checked, this time type will be taken into account for accruals computation.

_check_compare_dates()[código fonte]

Forbid overlapping public holidays in the same company and calendar.

_reevaluate_leaves(time_domain_dict)[código fonte]

Recompute the time off overlapping public holidays that were created, changed or deleted.

The durations are recomputed and the employees notified of the difference; a request whose allocation no longer covers it is refused.

Parâmetros

time_domain_dict (list) – see _get_time_domain_dict()

_get_domain(time_domain_dict)[código fonte]

Return the domain of the time off impacted by public holidays.

Requests of the company overlapping one of the periods, not refused or cancelled, and not generated by time rules.

Parâmetros

time_domain_dict (list) – see _get_time_domain_dict()

Tipo de retorno

odoo.fields.Domain

_get_time_domain_dict()[código fonte]

Return the company and the period of each global leave of self.

Retorna

list of {'company_id', 'date_from', 'date_to'}

Tipo de retorno

list

_prepare_public_holidays_data(start_date, end_date)[código fonte]

Prepare the public holidays of the user’s companies from the shipped CSV files.

Reads hr_holidays/data/public_holidays/public_holidays_<country>.csv and skips the holidays overlapping existing global leaves.

Parâmetros
Retorna

dict with prepared_public_holidays ({company_id: [values]}) and the companies companies_without_country, companies_without_public_holidays and companies_with_all_existing_holidays

Tipo de retorno

dict

_cron_generate_public_holidays()[código fonte]

Cron: create the public holidays of the next year from the shipped CSV files.

_ensure_datetime(datetime_representation, date_format=None)[código fonte]

Return datetime_representation as a datetime, parsing strings with date_format.

Retorna

the datetime, None when it cannot be parsed

Tipo de retorno

datetime.datetime or None

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.hr_employee_departure.HrEmployeeDeparture[código fonte]
_cleanup_employee_departure_leaves()[código fonte]

Clean up the employee’s leaves and allocations when processing their departure, optionally refusing future leaves instead of deleting them.

_check_refuse_future_leaves_condition()[código fonte]

Return whether future leaves should be refused. Can be overridden by localizations.

Additional fields with hr_holidays

model odoo.addons.hr_holidays.models.resource_resource.ResourceResource[código fonte]
leave_date_to: datetime.date
Name

None

_format_leave(leave, resource_hours_per_day, resource_hours_per_week, ranges_to_remove, start_day, end_day, locale)[código fonte]

Remove the time off by half day or in hours from the planning of the resource.

They only cover a half day or their hours of a single day; other leaves are handled by resource.

Original definition from hr_holidays

model odoo.addons.hr_holidays.models.hr_leave_display_name_mixin.HrLeaveDisplayNameMixin[código fonte]
_name = hr.leave.display.name.mixin
_get_leave_duration_display(request_unit, number_of_hours, number_of_days)[código fonte]

Format duration string based on request unit (hours or days)

_get_leave_display_date(date_from_utc, date_to_utc, number_of_days)[código fonte]

Format display date range string