Time off allocations and accruals¶
An allocation (hr.leave.allocation) grants an employee an amount of time off of a type
that requires it (requires_allocation, see Time off types). The amount is
either fixed, or earned over time by an accrual plan (hr.leave.accrual.plan) and its
levels (hr.leave.accrual.level). The time off requests of the employee are deducted from
the allocations to compute the balance, which is checked when requesting time off.
Allocations are also created by hr_holidays itself: from the accrual plan of a working
schedule, and from the time rules crediting overtime as compensatory time off.
其他資料
Time off for the time off types and requests.
備註
As in Time off, the examples run in odoo-bin shell with the demo data,
as the administrator: env = env(user=env.ref('base.user_admin')).
Allocations¶
An allocation belongs to an employee (employee_id) and a type (work_entry_type_id), and is
valid from date_from to date_to (both date; no date_to means no end). Time off is only
deducted from an allocation for its part within the validity of the allocation.
number_of_daysThe amount granted, always in days, also for types allocated in hours.
number_of_hoursis computed from it with the hours per day of the employee’s schedule atdate_from(24 for a fully flexible schedule) and can be written, which setsnumber_of_days(for an accrual allocation, the schedule at its next accrual is used).type_request_unitis the unit the allocation is displayed and accrued in: theadded_value_typeof the accrual plan, else the type’sunit_of_measure(_get_request_unit()).stateconfirm(To Approve, the only state allowed at creation),validate1(Second Approval),validate(Approved) orrefuse. Only approved allocations count.accrual_plan_idSet for accrual allocations, see Accrual plans; the plan’s type must be the allocation’s type.
The approval works as for time off requests, with the type’s allocation_validation_type:
types without validation are approved on creation, the others with
action_approve() (to validate, or to validate1
for the first approval of a type validated twice) and
action_refuse(). Only time off administrators
approve their own allocations. Employees can request allocations of the types with
employee_requests.
An approved allocation cannot be reduced below the time already taken from it; only
allocations to approve or refused, without time off taken, can be deleted. A negative
allocation is only allowed for types allowing a negative balance, within their
max_allowed_negative.
Balances¶
_get_consumed_leaves() is the core of every balance. For a set of
employees and types, it deducts the requests to approve and approved (confirm, validate1,
validate) from the approved allocations, request by request in chronological order, and
allocation by allocation in this order:
the allocations with an end date, the one ending first first;
the accrual allocations without end date;
the other allocations without end date.
A request is only deducted from the allocations valid on its dates; the part of a request that no allocation covers is an excess. The result distinguishes:
the approved amounts:
leaves_takenandremaining_leaves, counting approved requests only;the virtual amounts:
virtual_leaves_takenandvirtual_remaining_leaves, also counting the requests to approve. The virtual remaining amount is what can still be requested.
Amounts are in the unit_of_measure of the type: keys are prefixed with days_ or hours_
(e.g. days_virtual_remaining_leaves), and the other unit is also given as <unit>_taken and
<unit>_remaining. Types without allocation use the key False instead of an allocation.
On top of it:
get_allocation_data()The balance per employee and type on a date, summed over the allocations valid on that date:
{employee: [(type name, data, requires_allocation, type id), ...]}. It feeds the time off dashboard (throughget_allocation_data_request) and the checks of the requests.- The computed fields
max_leaves,leaves_takenandvirtual_remaining_leaves On
hr.leave.allocation(per allocation, today), onhr.work.entry.type(for the employee of the context) and onhr.leave(max_leaves,virtual_remaining_leaves, for the request’s employee and type). They are for display: code should call the methods above.
Creating or changing a request of a type requiring an allocation checks that the virtual balance
on its first day covers it (_check_validity()), down to
-max_allowed_negative when the type allows a negative balance.
Example
Marc Demo has an allocation of 3 days valid in 2026 and an open-ended one of 10 days, an approved request of 4 days and a request of half a day to approve:
from datetime import date
env = env(user=env.ref('base.user_admin'))
demo = env.ref('base.user_demo')
marc = demo.employee_id
pto = 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',
'allocation_validation_type': 'hr',
})
yearly, open_ended = env['hr.leave.allocation'].create([{
'employee_id': marc.id,
'work_entry_type_id': pto.id,
'number_of_days': 3,
'date_from': date(2026, 1, 1),
'date_to': date(2026, 12, 31),
}, {
'employee_id': marc.id,
'work_entry_type_id': pto.id,
'number_of_days': 10,
'date_from': date(2026, 1, 1),
}])
yearly.state, yearly.name # ('confirm', 'Paid Time Off (3.0 day(s))')
(yearly | open_ended).action_approve()
yearly.state, yearly.approver_id.name # ('validate', 'Mitchell Admin')
approved = env['hr.leave'].create({
'employee_id': marc.id,
'work_entry_type_id': pto.id,
'request_date_from': date(2026, 12, 1),
'request_date_to': date(2026, 12, 4),
})
pending = env['hr.leave'].with_user(demo).create({
'employee_id': marc.id,
'work_entry_type_id': pto.id,
'request_date_from': date(2026, 12, 14),
'request_date_to': date(2026, 12, 14),
'request_date_to_period': 'am',
})
(approved.state, approved.number_of_days), (pending.state, pending.number_of_days)
# (('validate', 4.0), ('confirm', 0.5))
consumed, to_recheck = marc._get_consumed_leaves(pto)
dict(consumed[marc][pto][yearly]) # a defaultdict
# {'days_max_leaves': 3.0, 'days_accrual_bonus': 0, 'days_leaves_taken': 3.0,
# 'days_virtual_leaves_taken': 3.0, 'days_remaining_leaves': 0.0,
# 'days_virtual_remaining_leaves': 0.0, 'hours_taken': 24.0, 'hours_remaining': 0.0}
dict(consumed[marc][pto][open_ended])
# {'days_max_leaves': 10.0, 'days_accrual_bonus': 0, 'days_leaves_taken': 1.0,
# 'days_virtual_leaves_taken': 1.5, 'days_remaining_leaves': 9.0,
# 'days_virtual_remaining_leaves': 8.5, 'hours_taken': 8.0, 'hours_remaining': 68.0}
name, data, requires_allocation, type_id = pto.get_allocation_data(marc)[marc][0]
{key: data[key] for key in ('max_leaves', 'leaves_taken', 'remaining_leaves',
'virtual_leaves_taken', 'virtual_remaining_leaves',
'leaves_requested')}
# {'max_leaves': 13.0, 'leaves_taken': 4.0, 'remaining_leaves': 9.0,
# 'virtual_leaves_taken': 4.5, 'virtual_remaining_leaves': 8.5, 'leaves_requested': 0.5}
env['hr.leave'].create({
'employee_id': marc.id,
'work_entry_type_id': pto.id,
'request_date_from': date(2026, 12, 15),
'request_date_to': date(2026, 12, 31),
})
# ValidationError: Marc Demo does not have a valid allocation for the leave type
# Paid Time Off to cover that request.
Accrual plans¶
An accrual plan (hr.leave.accrual.plan) earns time for its type (work_entry_type_id) over
time. Its levels (level_ids, Milestones), ordered by start, each define a rate:
start_count,start_type,milestone_dateWhen the level starts, after the start of the allocation (
milestone_date = 'creation': immediately). The first level may start later than the allocation.added_value,added_value_typeThe amount earned per period, in days or hours. The first level’s unit is the unit of the plan (
added_value_typeof the plan) and of its allocations (type_request_unit).frequencyhourly(per worked hour, see below),daily,weekly(week_day),bimonthly(first_day,second_day),monthly(first_day),biyearly(first_month,first_month_day,second_month,second_month_day) oryearly(yearly_month,yearly_day): the accrual dates, computed by_get_next_date()and_get_previous_date().cap_accrued_time,maximum_leaveA cap on the balance (earned minus taken): accrual stops while the balance is at the cap.
cap_accrued_time_yearly,maximum_leave_yearlyA cap on the amount earned per year (between two carry-over dates).
action_with_unused_accruals,carryover_options,max_carriedover_durationWhat happens to the balance on the carry-over date:
lost(reset), or carried over, without limit or up tomax_carriedover_duration.accrual_validity,accrual_validity_count,accrual_validity_typeThe time carried over expires after this period.
On the plan:
accrued_gain_timeend(default): the time of a period is earned at its end (on the next accrual date);start: at its start.transition_modeimmediately: a level starts on its start date;end_of_accrual: on its first accrual date from its start date, so that a period is never split between two levels (_get_lvls_boundaries()).is_based_on_worked_timeProrate the earned time on the worked time of the period: absences whose type is not
elligible_for_accrual_ratereduce it (_get_accrual_plan_level_work_entry_prorata()). Withhourlylevels, the amount is earned per hour of the period (worked hours with this option, all planned hours without).can_be_carryover,carryover_date,carryover_day,carryover_monthWhether unused time is carried over at all (otherwise it is lost on the carry-over date), and when: the start of the year, the anniversary of the allocation, or a custom day.
The first period of an allocation starting between two accrual dates is prorated on its number of days, unless the plan is based on worked time.
Running the accruals¶
An accrual allocation stores its progress: number_of_days (earned so far), lastcall and
nextcall (the last and next accrual events: accrual dates, level transitions, carry-over
dates, expirations), last_accrual, yearly_accrued_days,
previous_carryover_number_of_days and carried_over_days_expiration_date.
The daily cron (Accrual Time Off: Updates the number of time off) runs
model._get_to_update_accrual_allocations()._update_accrual():
_get_to_update_accrual_allocations() selects the
approved accrual allocations valid today whose nextcall is due, and
_update_accrual() processes every event up to today
and writes the result. A new allocation starting in the past catches up at its first run.
_process_accrual_plans() does the computation
without writing: it starts from the stored values (or the precomputed_allocations given),
processes the events up to a date and returns {allocation: allocation_data}. The Accrual
inconsistent helper methods (see the class docstring of
HrLeaveAllocation) only read and update allocation_data, so that
the same code serves:
the cron, which writes the result;
the future balance: the balance on a future date includes what the accrual will have earned by then (
accrual_bonus,_get_additionnal_future_leaves_on()), and future requests are checked against it (to_recheck_leaves,exceeding_durationin the second result of_get_consumed_leaves());the allocation form, which simulates the plan from
date_fromuntil today.
A second daily cron (_cancel_invalid_leaves()) cancels the requests of
the next 31 days that the accruals will not cover.
Example
A plan earning 1.5 days per month at the end of the month, carrying over at most 5 days at the start of the year, and 2 days per month after two years:
from odoo.fields import Command
plan = env['hr.leave.accrual.plan'].create({
'name': 'Monthly 1.5 days',
'work_entry_type_id': pto.id,
'accrued_gain_time': 'end',
'can_be_carryover': True,
'carryover_date': 'year_start',
'level_ids': [Command.create({
'added_value': 1.5,
'added_value_type': 'day',
'frequency': 'monthly',
'first_day': '1',
'action_with_unused_accruals': 'all',
'carryover_options': 'limited',
'max_carriedover_duration': 5,
}), Command.create({
'milestone_date': 'after',
'start_count': 2,
'start_type': 'year',
'added_value': 2,
'added_value_type': 'day',
'frequency': 'monthly',
'first_day': '1',
'action_with_unused_accruals': 'all',
})],
})
employee = env['hr.employee'].search([('name', '=', 'Ronnie Hart')])
allocation = env['hr.leave.allocation'].create({
'employee_id': employee.id,
'work_entry_type_id': pto.id,
'accrual_plan_id': plan.id,
'date_from': date(2026, 1, 1),
'number_of_days': 0,
})
allocation.action_approve()
allocation.number_of_days, allocation.nextcall # (0.0, False): not run yet
allocation._update_accrual() # what the cron does (today is 2026-10-23)
allocation.number_of_days, allocation.lastcall, allocation.nextcall
# (13.5, datetime.date(2026, 10, 1), datetime.date(2026, 11, 1)): 9 months
allocation._get_lvls_boundaries()
# [datetime.date(2026, 1, 1), datetime.date(2028, 1, 1)]
allocation._process_accrual_plans(date(2027, 1, 1))[allocation]
# {'last_accrual': datetime.date(2027, 1, 1), 'lastcall': datetime.date(2027, 1, 1),
# 'nextcall': datetime.date(2027, 2, 1), 'allocated_duration': 6.5,
# 'yearly_accrued_duration': 0, 'carried_over_days_expiration_date': False,
# 'previous_carryover_allocated_duration': 5, 'leaves_taken': 0}
allocation.number_of_days # 13.5: nothing written
data = pto.get_allocation_data(employee, date(2026, 12, 31))[employee][0][1]
data['max_leaves'], data['accrual_bonus'] # (16.5, 3.0)
On January 1, 2027, the 16.5 days earned in 2026 are capped to 5 by the carry-over, then December’s 1.5 days are earned (at the end of the period): 6.5 days.
Allocations from working schedules¶
A working schedule can have an accrual plan (resource.calendar.leave_accrual_plan_id). When an
employee’s version uses a schedule with a work time rate above 100% and such a plan, the version
gets an accrual allocation of the plan over its period
(hr.version.allocation_from_working_schedule_id), recreated when the version’s schedule
changes (_action_trigger_accrual_plan_working_schedule()). It
compensates schedules longer than the legal working time with time off.
Allocations from time rules¶
hr_holidays adds two fields to the time rules (hr.time.rule, see
Time rules): allocation_type_id (Allocate to, a type
requiring an allocation) and leave_compensation_rate (Allocate %). The excess hours of such a
rule, times the rate, divided by the employee’s hours per day, are credited to the employee’s
approved allocation without end date of that type, created and approved if needed
(_apply_allocation_credits()); the missing hours of an undertime
rule are deducted from it, unless the allocation cannot cover them all
(_filter_deficit_exceeding_allocation()).
Each credit is logged in a hr.time.rule.allocation.log record (the source record res_model
and res_id, the allocation and the days). When the source is evaluated again, changed,
refused or deleted, its logged credits are reversed first
(_reverse_allocation_credits()); a reversal that would bring the
allocation below what was already taken raises a ValidationError.
The sources are the time off requests (validated working time requests exceeding the schedule,
e.g. a long business trip) and, with hr_holidays_attendance, the attendances: see
Overtime and time off: hr_holidays_attendance.
Example
A business trip of 12 hours on a day of 8 planned hours, with a rule crediting the excess as compensatory days:
trip, compensatory = env['hr.work.entry.type'].create([{
'name': 'Business Trip',
'code': 'DOCTRIP',
'count_as': 'working_time',
'requires_allocation': False,
'request_unit': 'hour',
'leave_validation_type': 'no_validation',
}, {
'name': 'Compensatory Days',
'code': 'DOCCOMP',
'count_as': 'absence',
'requires_allocation': True,
'request_unit': 'half_day',
'unit_of_measure': 'day',
}])
env['hr.time.rule'].create({
'name': 'Trip overtime to compensatory days',
'company_id': employee.company_id.id,
'threshold_operator': 'exceed',
'working_hours_mode': 'schedule_day',
'condition_work_entry_type_ids': [Command.set(trip.ids)],
'leave_compensation_rate': 1.0,
'allocation_type_id': compensatory.id,
})
leave = env['hr.leave'].create({
'employee_id': employee.id,
'work_entry_type_id': trip.id,
'request_date_from': date(2026, 12, 2),
'request_date_to': date(2026, 12, 2),
'request_hour_from': 7.0,
'request_hour_to': 19.0,
})
leave.state, leave.number_of_hours # ('validate', 12.0)
credit = env['hr.leave.allocation'].search([
('employee_id', '=', employee.id), ('work_entry_type_id', '=', compensatory.id),
])
credit.state, credit.number_of_days, credit.date_to # ('validate', 0.5, False)
env['hr.time.rule.allocation.log'].search([]).read(['res_model', 'res_id', 'days'])
# [{'id': ..., 'res_model': 'hr.leave', 'res_id': leave.id, 'days': 0.5}]
leave.action_refuse()
credit.number_of_days # 0.0: the credit is reversed
Pitfalls¶
number_of_daysis in days even for types allocated in hours; the hours are converted with the employee’s hours per day, so an allocation in hours keeps its hours when the schedule changes only becausehr.versionrewritesnumber_of_days.The computed balance fields (
max_leaves,virtual_remaining_leaves, …) are computed for today, or for the employee of the context on types: useget_allocation_data()with a date in code.Approving an accrual allocation does not run its plan:
number_of_daysstays at its initial value until the cron or a call to_update_accrual().A request is deducted from the allocations valid on its dates only: an allocation starting after the request, or ending before it, does not cover it, and an allocation ending during a request only covers its first part.
The accrual helpers flagged Accrual inconsistent must not read the allocation fields nor write: override them consistently with
allocation_data.Time rule credits go to the allocation without end date of the type: a fixed allocation of the same type without end date receives them too.
Extending¶
- Accrual frequencies
_get_hourly_frequencies()(frequencies accruing per hour), with_get_next_date()and_get_previous_date()for new frequencies;hr_holidays_attendanceadds a frequency on attendances this way.- Accrual amounts
_get_accrual_plan_level_work_entry_prorata()and_get_period_added_duration().- Balances
_set_leaves_from_consumption_data()to reuse an already computed_get_consumed_leaves().- Time rule credits
_get_output_leave_merge_key()(when consecutive outputs make one request) and the source hooks of Time rule sources.
Reference¶
Original definition from hr_holidays¶
- model odoo.addons.hr_holidays.models.hr_leave_allocation.HrLeaveAllocation[原始碼]¶
- _name = hr.leave.allocation¶
Allocation of time off: credits an employee with days or hours of a time type.
A regular allocation grants
number_of_days(number_of_hoursfor types allocated in hours); an accrual allocation (accrual_plan_idset) earns it over time, see_update_accrual().Some accrual methods are tagged Accrual inconsistent: they must not read the allocation fields loaded by
_get_accrual_allocation_data()nor write any field, but read and update theirallocation_datadict instead, so that the accrual can be simulated (e.g. a future balance) without writing anything. Methods tagged Possibly accrual inconsistent takeallocation_data={}and read the fields when it is empty.- state: str¶
- Name
Status
- Readonly
this field is not supposed to/cannot be set manually
- Selection
confirm: To Approverefuse: Refusedvalidate1: Second Approvalvalidate: Approved- Default
confirm
The status is 『To Approve』, when an allocation request is created. The status is 『Refused』, when an allocation request is refused by manager. The status is 『Approved』, when an allocation request is approved by manager.
- date_from: datetime.date¶
- Required
- Name
Start Date
- date_to: datetime.date¶
- Name
End Date
- number_of_days: float¶
- Name
Number of Days
- Default
1
Duration in days. Reference field to use when necessary.
- number_of_hours: float¶
- Name
Duration (hours)
For an Accrual Allocation, this field contains the theorical amount of time given to the employee, due to a previous start date, on the first run of the plan. This can be manually edited.
- type_request_unit: str¶
- Name
Type Request Unit
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- Selection
hour: Hourshalf_day: Half-Dayday: Day
- max_leaves: float¶
- Name
Max Leaves
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- leaves_taken: float¶
- Name
Time off Taken
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- virtual_remaining_leaves: float¶
- Name
Available Time Off
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- last_accrual: datetime.date¶
- Name
Date of the last accrual allocation
- lastcall: datetime.date¶
- Name
Date of the last executed accrual event (accrual, carryover date, expiring carriedover days, …)
- nextcall: datetime.date¶
- Name
Date of the closest next accrual event (accrual, carryover date, expiring carriedover days, …)
- carried_over_days_expiration_date: datetime.date¶
- Name
Carried over days expiration date
- create(vals_list)[原始碼]¶
Create allocations in
'confirm'and start their approval.Types without validation are approved at once.
- 引發
UserError – when another state is given
- write(vals)[原始碼]¶
Write on allocations, checking the state transitions.
- 引發
ValidationError – when the change reduces the balance below the time already taken (beyond the negative cap of the type)
- action_approve()[原始碼]¶
Approve the allocations: validate them, or give the first approval (
'validate1').- 引發
UserError – when the user can neither validate nor approve an allocation
- action_refuse()[原始碼]¶
Refuse the allocations.
- 引發
UserError – when an allocation is not
'confirm','validate1'or'validate'
- _check_approval_update(state, raise_if_not_possible=True)[原始碼]¶
Check that the current user can move the allocations to
state.Only time off administrators can approve their own allocations (unless the type needs no validation). The superuser can do everything.
- _get_next_states_by_state()[原始碼]¶
Return the states the current user can move the allocation to, from each state.
Same rules as for time off; types without validation can always be approved.
- 回傳
{state: set(next_states)}- 回傳型別
- _get_responsible_for_approval()[原始碼]¶
Return the user who must approve the allocation in its current state.
Same rules as
_get_responsible_for_approval().- 回傳型別
res.users
- _check_negative_allocation()[原始碼]¶
Allow negative allocations only for types allowing a negative balance, within their cap.
The negative allocations of the employee and type overlapping the validity period may not exceed
max_allowed_negativein total.
- _set_leaves_from_consumption_data(employee_days_per_allocation)[原始碼]¶
Set
max_leaves,leaves_takenandvirtual_remaining_leaves.Lets extensions reuse an already fetched result (e.g.
l10n_be_hr_payroll).- 參數
employee_days_per_allocation (dict) – first element of the result of
_get_consumed_leaves()
- _get_request_unit()[原始碼]¶
Return the unit the allocation is computed in (
type_request_unit).The
added_value_typeof the accrual plan, else theunit_of_measureof the type.- 回傳
'day'or'hour'- 回傳型別
- _get_employee_hours_per_day(allocation_data={})[原始碼]¶
Return the hours per day of the employee, to convert days into hours.
Possibly accrual inconsistent. The schedule is the one at the accrual’s
nextcall(accrual allocations) or atdate_from; 24 for fully flexible employees.- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()- 回傳型別
- _convert_duration(duration, src_unit, dst_unit, allocation_data={})[原始碼]¶
Convert a duration between days and hours with the employee’s hours per day.
Possibly accrual inconsistent, see
_get_employee_hours_per_day().
- _convert_to_type_request_unit(duration, duration_unit, allocation_data={})[原始碼]¶
Convert a duration into the allocation’s unit (
type_request_unit).Possibly accrual inconsistent, see
_convert_duration().
- _convert_from_type_request_unit(duration, duration_unit, allocation_data={})[原始碼]¶
Convert a duration expressed in the allocation’s unit into
duration_unit.Possibly accrual inconsistent, see
_convert_duration().
- _get_to_update_accrual_allocations()[原始碼]¶
Return the allocations the accrual cron must update.
Validated accrual allocations valid today, whose
nextcallis not set or is due.- 回傳型別
hr.leave.allocation
- _update_accrual(date_to=None)[原始碼]¶
Run the accrual plans of the allocations up to
date_toand write the result.Writes
number_of_days(the credit of the allocation) and the accrual fields (last_accrual,lastcall,nextcall,yearly_accrued_days,previous_carryover_number_of_days,carried_over_days_expiration_date) computed by_process_accrual_plans(). Called daily by the cron on_get_to_update_accrual_allocations().- 參數
date_to (datetime.date) – last day to process, today by default
- _process_accrual_plans(date_to=None, precomputed_allocations={})[原始碼]¶
Compute the accrual of the allocations up to
date_to, without writing.Runs every accrual event (accrual dates, level transitions, carry-over dates, expiration of the carried over time) from
nextcallup todate_to(today by default), from the values stored on the allocation or fromprecomputed_allocations. Allocations without accrual plan are left out.- 參數
date_to (datetime.date) – last day to process
precomputed_allocations (dict) –
{allocation: allocation_data}to start from, instead of the stored values
- 回傳
{allocation: allocation_data}whereallocation_dataholdslast_accrual,lastcall,nextcall,carried_over_days_expiration_date(dates),allocated_duration,yearly_accrued_duration,previous_carryover_allocated_durationandleaves_taken(floats intype_request_unit)- 回傳型別
- _get_accrual_allocation_data()[原始碼]¶
Return the accrual data of the allocations, read from their fields.
- 回傳
{allocation: allocation_data}, see_process_accrual_plans();leaves_takenisNone- 回傳型別
- _init_accrual_calls(allocation_data)[原始碼]¶
Initialize
last_accrual,lastcallandnextcallfor a first accrual run.Accrual inconsistent.
lastcallis the start of the first level;nextcallis the same date when accruing at the start of the period, else the first accrual, carry-over or level transition date.- 參數
allocation_data (dict) – accrual data, updated in place
- _process_accrual_start(allocation_data, current_level, next_accrual)[原始碼]¶
Accrue the period starting on
allocation_data['nextcall'], if it is an accrual date.Accrual inconsistent. For plans accruing at the start of the period (
accrued_gain_time = 'start').- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()current_level –
hr.leave.accrual.levelaccruingnext_accrual (datetime.date) – next accrual date
- _process_accrual_end(allocation_data, current_level, current_level_idx, first_level_start_date)[原始碼]¶
Accrue the period ending on
allocation_data['nextcall'], if it is an accrual date.Accrual inconsistent. For plans accruing at the end of the period (
accrued_gain_time = 'end').- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()current_level –
hr.leave.accrual.levelaccruingcurrent_level_idx (int) – index of the level
first_level_start_date (datetime.date) – start of the first level
- _add_days_to_allocation(allocation_data, current_level, period_start, period_end, start_date, end_date)[原始碼]¶
Add the gain of an accrual period to
allocation_data.Accrual inconsistent. The gain (
_get_period_added_duration()) is capped by the yearly cap of the level and by its balance cap (maximum_leave, on the balanceallocated_duration - leaves_taken). Updatesallocated_duration,yearly_accrued_durationandlast_accrual.- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()current_level –
hr.leave.accrual.levelaccruingperiod_start (datetime.date) – start of the full accrual period
period_end (datetime.date) – end of the full accrual period
start_date (datetime.date) – start of the accrued part of the period
end_date (datetime.date) – end of the accrued part of the period
- _get_period_added_duration(allocation_data, level, period_start, start_date, period_end, end_date)[原始碼]¶
Return the duration earned over an accrual period, in
type_request_unit.Accrual inconsistent.
added_valuetimes the prorata of_get_accrual_plan_level_work_entry_prorata(); a partial period (e.g. the first one) is prorated on its number of days, unless the plan is based on worked time.- 回傳型別
- _get_accrual_plan_level_work_entry_prorata(level, start_period, start_date, end_period, end_date)[原始碼]¶
Return the factor applied to the
added_valueof the level for a period.Possibly accrual inconsistent.
1unless the plan is based on worked time or the frequency is hourly. For hourly frequencies, the number of hours of the period: worked hours plus absences eligible for accrual (plus the other absences when the plan is not based on worked time). Otherwise the ratio of those hours to all the planned hours.- 參數
level –
hr.leave.accrual.levelstart_period (datetime.date) – start of the full period
start_date (datetime.date) – start of the accrued part
end_period (datetime.date) – end of the full period
end_date (datetime.date) – end of the accrued part
- 回傳型別
- _process_carryover_date(allocation_data, current_level, carryover_date)[原始碼]¶
Apply the carry-over policy of the level on its carry-over date.
Accrual inconsistent. Unused time is lost (
action_with_unused_accruals = 'lost'), kept, or kept up tomax_carriedover_duration; withaccrual_validity, the time carried over expires after the validity period (carried_over_days_expiration_date).- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()current_level –
hr.leave.accrual.levelin effectcarryover_date (datetime.date) – the carry-over date
- _get_next_carryover_date(date_from, date_from_included=True)[原始碼]¶
Return the next carry-over date of the accrual plan from
date_from.- 參數
date_from (datetime.date) – reference date
date_from_included (bool) – return
date_fromif it is a carry-over date
- 回傳型別
- _has_expiring_days(allocation_data)[原始碼]¶
Tell whether carried over time is still to expire after
nextcall.Accrual inconsistent.
- 回傳型別
- _get_days_after_expiration(allocation_data)[原始碼]¶
Return
allocated_durationonce the carried over time not taken has expired.Accrual inconsistent.
- 參數
allocation_data (dict) – accrual data, see
_process_accrual_plans()- 回傳型別
- _get_lvls_boundaries() list[datetime.date] | None[原始碼]¶
Return the start date of each level of the accrual plan for this allocation.
A level starts
start_countstart_typeafterdate_from; with the transition mode'end_of_accrual', the levels after the first one start on their first accrual date on or after that date.- 回傳
one date per level, in order
- 回傳型別
- _get_next_lvl_start(level_idx)[原始碼]¶
Return the start date of the level following
level_idx,Nonefor the last one.- 回傳型別
- _get_current_accrual_plan_levels(target_date) dict[str, tuple] | None[原始碼]¶
Return the level(s) of the accrual plan in effect on
target_date.On a level transition, both levels are returned.
Nonebefore the first level starts, afterdate_to, or without levels.- 參數
target_date (datetime.date) – reference date
- 回傳
{'current_level': (level, index)}, plus'previous_level': (level, index)on a transition- 回傳型別
- _get_current_accrual_plan_level_idx(date)[原始碼]¶
Return the level in effect on
date; on a transition, the level that starts.- 回傳
(level, index),(None, None)when no level applies- 回傳型別
- _get_current_accrual_plan_level_idx_for_accrual(target_date)[原始碼]¶
Return the level in effect and the level accruing on
target_date.They differ on a level transition when the plan accrues at the end of the period (
accrued_gain_time = 'end'): the period that ends is accrued with the policy of the previous level.
- _get_additionnal_future_leaves_on(accrual_date, allocations_data={})[原始碼]¶
Return the time the accrual will add between now and
accrual_date.Possibly accrual inconsistent.
0for past dates, non accrual or non validated allocations, and allocations expired onaccrual_date.- 參數
accrual_date (datetime.date) – future date
allocations_data (dict) –
{allocation: allocation_data}; when the allocation is in it, the gain is computed from these data instead of the stored values
- 回傳
added duration, in the
unit_of_measureof the type- 回傳型別
Original definition from hr_holidays¶
- model odoo.addons.hr_holidays.models.hr_leave_accrual_plan.HrLeaveAccrualPlan[原始碼]¶
- _name = hr.leave.accrual.plan¶
- level_ids: Sequence[odoo.orm.commands.Command]¶
- Name
Milestones
- Comodel
- accrued_gain_time: str¶
- Required
- Name
Accrued Gain Time
- Selection
start: At the start of the accrual periodend: At the end of the accrual period- Default
end
- transition_mode: str¶
- Required
- Name
Transition Mode
- Selection
immediately: Immediatelyend_of_accrual: After this accrual’s period- Default
immediately
- is_based_on_worked_time: bool¶
- Name
Is Based On Worked Time
Only excludes requests where the time type is set as unpaid kind of.
Original definition from hr_holidays¶
- model odoo.addons.hr_holidays.models.hr_leave_accrual_plan_level.HrLeaveAccrualLevel[原始碼]¶
- _name = hr.leave.accrual.level¶
- start_count: int¶
- Name
Start Count
The accrual starts after a defined period from the allocation start date. This field defines the number of days, months or years after which accrual is used.
- start_type: str¶
- Required
- Name
Start Type
- Selection
day: Daysmonth: Monthsyear: Years- Default
day
This field defines the unit of time after which the accrual starts.
- frequency: str¶
- Required
- Name
Frequency
- Selection
hourly: Hourlydaily: Dailyweekly: Weeklybimonthly: Twice a monthmonthly: Monthlybiyearly: Twice a yearyearly: Yearly- Default
daily
- cap_accrued_time: bool¶
- Name
Cap Accrued Time
When the field is checked the balance of an allocation using this accrual plan will never exceed the specified amount.
- cap_accrued_time_yearly: bool¶
- Name
Cap Accrued Time Yearly
When the field is checked the total amount accrued each year will be capped at the specified amount
- action_with_unused_accruals: str¶
- Required
- Name
Action With Unused Accruals
- Selection
lost: Lost (Reset)all: Carried over- Default
lost
When the Carry-Over Time is reached, according to Plan’s setting, select what you want to happen with the unused time off: Lost (time will be reset to zero), Carried over (accrued time carried over to the next period.)
- carryover_options: str¶
- Required
- Name
Carryover Options
- Selection
unlimited: Unlimitedlimited: Up to- Default
unlimited
You can limit the accrued time carried over for the next period.
- max_carriedover_duration: int¶
- Name
Max Carriedover Duration
Set a maximum of accruals an allocation keeps at the end of the year.
- _get_hourly_frequencies()[原始碼]¶
Return the frequencies accruing per hour of the period instead of per period.
- _get_next_date(last_call)[原始碼]¶
Return the first accrual date of the level after
last_call(excluded).- 參數
last_call (datetime.date) – reference date
- 回傳型別
- _get_previous_date(last_call)[原始碼]¶
Return the last accrual date of the level on or before
last_call(included).For instance, the 1st of the month for a monthly level.
- 參數
last_call (datetime.date) – reference date
- 回傳型別
- _get_start_date(date_from)[原始碼]¶
Return
date_fromplus the start delay of the level (start_countstart_type).- 回傳型別
Additional fields with hr_holidays¶
- model odoo.addons.hr_holidays.models.hr_time_rule.HrTimeRule[原始碼]¶
-
- leave_compensation_rate: float¶
- Name
Allocate %
- Default
0.0
Leave allocated or taken at this rate of the excess or deficit. 100% = 1:1.
- _apply_leave_output(excess, deficit, active_iv=None)[原始碼]¶
Apply the time rule result on time off sources.
Creates the outputs (
_apply_output, defined byhr_work_entry), credits the allocations (_apply_allocation_credits()) and recreates the resource leaves of the sources and outputs.
- _apply_allocation_credits(excess_alloc, deficit_alloc, *, approve_ctx=None)[原始碼]¶
Credit (or deduct) the excess (or missing) hours of rules to allocations, and log it.
For rules with
leave_compensation_rateandallocation_type_id, the hours times the rate, divided by the employee’s hours per day, are added to (or deducted from) the validated allocation without end date of that type, created if needed. Each credit is logged inhr.time.rule.allocation.logso it can be reversed.
- _filter_deficit_exceeding_allocation(deficit)[原始碼]¶
Drop the deficits the allocation of the rule cannot cover.
When the total deduction of an employee and allocation type exceeds the balance, all the deficit intervals of that pair are dropped, so no output is created for them.
- _reverse_allocation_credits(source_model, source_ids)[原始碼]¶
Reverse the allocation credits logged for the given source records.
- 參數
source_model (str) –
'hr.leave'or'hr.attendance'source_ids – ids of the sources
- 引發
ValidationError – when the reversal would bring a balance below its minimum
- _get_output_leave_vals(employee, rule, date_from, date_to, source_leave, accumulated_pp=frozenset({}))[原始碼]¶
Return the creation values of a validated time off output by
rule.The output has the rule’s type,
time_rule_id, the given span and is linked tosource_leave.
- _get_output_leave_merge_key(accumulated_pp=frozenset({}))[原始碼]¶
Return the hashable key deciding when consecutive excess slices make one time off.
Override to add discriminators (e.g. the premium pays in Belgium). Default: the rule.
- _resolve_output_intervals(intervals)[原始碼]¶
Resolve the output intervals, then merge consecutive slices with the same merge key.
See
_get_output_leave_merge_key().- 回傳型別