Attendances¶
An attendance (hr.attendance, module hr_attendance) is a period during which an employee
was present: a check in, and a check out once the employee leaves. Attendances are recorded
from a kiosk (badge or employee selection), from the systray of the backend, or manually. They
feed three other mechanisms:
the time rules (
hr.time.rule) ofhr_work_entry, which reclassify the time beyond or missing from a threshold (overtime, undertime) on the attendances themselves;the work entries, which payroll turns into worked days: with
hr_holidays_attendance, validated attendances produce work entries, and attendance-based versions are paid on attendances only;the time off allocations, credited with the overtime (
hr_holidays_attendance).
In 20.0 there is no overtime model anymore (hr.attendance.overtime and the overtime rulesets
were removed): overtime is time rule output stored as attendances.
Consulta
Work entries, for the time rule engine and the generation of work entries, which this page does not repeat;
Employees and Versions and contracts for the employee and its versions;
Working schedules for the schedules giving the expected hours.
The attendance model¶
employee_id,check_inandcheck_outThe span, as naive UTC datetimes. An attendance without
check_outis open: the employee is checked in.dateThe local day of
check_inin the employee’s timezone (stored, indexed).worked_hourscheck_out - check_inin hours minusbreak_duration(an unpaid break in hours, only allowed on closed attendances). The schedule is not used: a lunch break planned in the schedule is not deducted.work_entry_type_id(Time Type)The type of the time, read by the time rules and the work entries. It defaults to the attendance type of the company (
res.company.attendance_work_entry_type_id: the002.00type of the company’s country, else the generic attendance type).statedraft,validatedorrefused, see Validation.in_mode/out_modeHow the employee checked in and out:
kiosk,systray,manual(default, also used for records created in code),technical(absence detection) and, for the check out only,auto_check_out.in_*/out_*fields store the location, IP address, browser and GPS coordinates when the company enablesattendance_device_tracking, andin_imagethe check-in picture (attendance_capture_check_in).time_rule_id,source_attendance_id,overtime_attendance_ids,source_staleThe time rule fields, see Time rules on attendances.
Three constraints protect the data:
_check_validity_check_in_check_out() (check_out after
check_in), _check_break_duration() and
_check_validity(): an employee has at most one open
attendance and no overlapping attendances. Attendances cannot be duplicated.
On hr.employee, hr_attendance adds attendance_ids, last_attendance_id (the last
attendance that started before now), last_check_in, last_check_out, attendance_state
(checked_in when the last attendance is open), attendance_manager_id (the Attendance
Approver, made attendance officer automatically) and the hour counters described in
Worked and overtime hours.
Example
from datetime import date, datetime
from odoo.exceptions import ValidationError
employee = env['hr.employee'].create({
'name': 'Ann Example',
'tz': 'Europe/Brussels',
'date_version': date(2026, 1, 1),
'contract_date_start': date(2026, 1, 1),
})
attendance = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 5, 6, 0), # 8:00 in Brussels
'check_out': datetime(2026, 10, 5, 15, 30), # 17:30 in Brussels
'break_duration': 0.5,
})
(attendance.date, attendance.worked_hours, attendance.in_mode, attendance.state,
attendance.work_entry_type_id.code)
# (datetime.date(2026, 10, 5), 9.0, 'manual', 'validated', '002.00')
try:
with env.cr.savepoint():
env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 5, 14, 0),
'check_out': datetime(2026, 10, 5, 16, 0),
})
except ValidationError as e:
print(e)
# Cannot create new attendance record for Ann Example, the employee was already checked in
# on 10/05/2026 04:00:00 PM
The constraints are checked when the records are flushed, after create returned: without
the savepoint, the overlapping record would stay in the transaction.
The next examples are independent of each other; they only assume the records of this first
example (employee, and company = employee.company_id), plus the overtime type once
defined.
Checking in and out¶
_attendance_action_change() is the single entry point of the
kiosk and the systray. Called on one employee, it checks the employee in (creates an
attendance starting now) or out (sets check_out on the open attendance), then sends the new
presence state on the bus. Its arguments are:
geo_informationA dict written on the attendance with the
in_prefix at check in and theout_prefix at check out:mode, and with device trackinglocation,latitude,longitude,ip_addressandbrowser.check_in_image_data{'image': bytes, 'type': mimetype}, stored inin_imageand posted on the attendance.
It returns False, or a warning notification ({'type': 'warning', 'message': ...}) when the
company requires a check-in picture that was not given. It raises a UserError if there is
nothing to check out.
When the company enables single_check_in (only possible with the automatic check out), an
employee with a non flexible schedule cannot check out: the call does nothing, and raises a
UserError from the systray (context is_from_systray_check_in_out). The automatic check out
then closes the attendance.
Example
employee.attendance_state # 'checked_out'
employee._attendance_action_change({'mode': 'kiosk', 'location': 'Brussels office'})
# False
attendance = employee.last_attendance_id
(employee.attendance_state, attendance.in_mode, attendance.in_location,
attendance.check_out)
# ('checked_in', 'kiosk', 'Brussels office', False)
employee._attendance_action_change({'mode': 'kiosk'}) # False
employee.attendance_state, attendance.out_mode, bool(attendance.check_out)
# ('checked_out', 'kiosk', True)
The HTTP layer is in hr_attendance/controllers/main.py (class HrAttendance):
- Kiosk
/hr_attendance/<token>renders the public kiosk of the company whoseattendance_kiosk_keyistoken(attendance_kiosk_url; regenerating the key with_regenerate_attendance_kiosk_key()invalidates the URL). Opening it logs out a user with a password.res.company.attendance_kiosk_modeselects how employees identify:barcode(badge or RFID:/hr_attendance/attendance_barcode_scanned, matchinghr.employee.barcode),manual(selection in a list:/hr_attendance/manual_selection, checkinghr.employee.pinwhenattendance_kiosk_use_pinis set) or both. These routes areauth='public': the token is the only credential, and most of them work as superuser on the employees of the token’s company.- Systray
/hr_attendance/systray_check_in_outchecks in or out the current user’s employee (modesystray), if the company enablesattendance_from_systray.- Breaks
With
attendance_break_management,/hr_attendance/update_break_durationsets the break of the last attendance after the check out, as long as it is not validated.
The static helpers of the controller build the responses and are the place to add data:
_get_user_attendance_data (state and hours of the employee, plus the company settings),
_get_employee_info_response (what the kiosk displays), _get_geoip_response (the
geo_information above) and _get_validated_check_in_image_and_type (decodes and checks the
picture: JPEG or WebP data URI, at most 20 KB decoded).
Worked and overtime hours¶
worked_hours is the only stored duration. The employee counters are computed on the fly:
hours_today,hours_previously_todayandlast_attendance_worked_hours: the time worked today (employee’s timezone) until now, the breaks being prorated (_get_break_duration_within_period());hours_last_monthandhours_last_month_overtime: despite their names, the current month; the first sums the attendances that are not time rule outputs, the second those that are;total_overtime: the hours of the validated attendances produced or reclassified by a time rule (time_rule_idset), whatever their type and date.
get_attendance_data_by_employee() returns, for a period, the
hours of the attendances overlapping it (full worked_hours, not clipped to the period), per
employee, with the overtime and one entry per type:
{employee_id: {'worked_hours', 'overtime_hours', 'entries': [{'name', 'worked_hours',
'color'}]}} (see the example in Time rules on attendances).
The expected hours come from the schedule:
_get_expected_attendances() (see
Working time and calendars). The validation tolerance and the automatic check out use
it; the time rules compute their own schedule intervals.
Validation¶
Only validated attendances count: they are the only time rule sources
(_get_source_extra_fields_domain()), and the only attendances
producing work entries or accruing time off. The initial state is set at creation by
create(), according to res.company.attendance_validation:
no_validation(default)Attendances are created
validated.manual_validationAttendances are created
draft; an officer validates (action_validate()) or refuses (action_refuse()) them.tolerance_validationClosed draft attendances are validated automatically when their duration (break included) differs from the expected hours of the day by at most
attendance_validation_tolerancehours, or when no hours are expected that day (_update_tolerance_state(), called at creation and whencheck_outis written); the time rules then run on them. The others staydraft.
Time rule outputs (time_rule_id or source_attendance_id given) are always created
validated. Passing state in the values bypasses the policy.
Example
company = employee.company_id
company.write({
'attendance_validation': 'tolerance_validation',
'attendance_validation_tolerance': 0.5,
})
attendances = env['hr.attendance'].create([{
'employee_id': employee.id,
'check_in': datetime(2026, 10, 6, 6, 0), # 8h15 for 8 expected hours
'check_out': datetime(2026, 10, 6, 14, 15),
}, {
'employee_id': employee.id,
'check_in': datetime(2026, 10, 7, 6, 0), # 10 hours
'check_out': datetime(2026, 10, 7, 16, 0),
}])
attendances.mapped('state') # ['validated', 'draft']
attendances[1].action_validate()
attendances[1].state # 'validated'
Time rules on attendances¶
hr.attendance inherits hr.time.rule.source.mixin: creating a validated attendance, or
changing the employee, span, type, state or break of one, runs the time rules (see
Time rules and
When rules run). By default, a rule created in an
attendance context matches the attendance type of the company
(condition_work_entry_type_ids).
The rules write their result on the attendances themselves:
when the excess starts with the attendance, the attendance is reclassified in place: it gets the output type and
time_rule_id, and ends where the excess ends;otherwise the attendance is cut at the start of the excess, and the excess becomes a new output attendance: same employee, the rule’s type,
time_rule_idset,source_attendance_idpointing to the source (inverse:overtime_attendance_ids), always validated;an undertime (
less_than) rule creates output attendances for the missing hours, in the free slots of the period (_get_time_rule_deficit_occupied()).
The span of an output is real time: the source and its outputs together cover the original
check in to check out. Output attendances are regular attendances: they appear in the views,
count in worked_hours and in the work entries with their own type.
Changing the span, employee, type or break of a source sets source_stale on the outputs that
existed before (write(), and on deletion of the source); the
rules run again on the source but do not delete the old outputs. A user reviews them, deletes
them or clears the flag (action_mark_reviewed()).
Example
A daily overtime rule on the default 8-hour schedule (8:00-16:00):
overtime = env['hr.work.entry.type'].search([('code', '=', 'USOVERTIME150')])
rule = env['hr.time.rule'].create({
'name': 'Daily overtime',
'company_id': employee.company_id.id,
'work_entry_type_id': overtime.id,
})
rule.condition_work_entry_type_ids == employee.company_id.attendance_work_entry_type_id
# True
attendance = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 5, 6, 0), # Monday 8:00 in Brussels
'check_out': datetime(2026, 10, 5, 16, 0), # 18:00 in Brussels
})
attendance.check_out, attendance.worked_hours, attendance.work_entry_type_id.code
# (datetime.datetime(2026, 10, 5, 14, 0), 8.0, '002.00'): cut at 16:00
output = attendance.overtime_attendance_ids
(output.check_in, output.check_out, output.work_entry_type_id.code,
output.time_rule_id.name, output.state)
# (datetime.datetime(2026, 10, 5, 14, 0), datetime.datetime(2026, 10, 5, 16, 0),
# 'USOVERTIME150', 'Daily overtime', 'validated')
employee.total_overtime # 2.0
employee.get_attendance_data_by_employee(datetime(2026, 10, 5), datetime(2026, 10, 6))
# {38: {'worked_hours': 10.0, 'overtime_hours': 2.0,
# 'entries': [{'name': 'Work', 'worked_hours': 8.0, 'color': 0},
# {'name': 'Overtime (1.5x)', 'worked_hours': 2.0, 'color': 4}]}}
# no schedule on Saturday: the whole attendance is overtime, reclassified in place
saturday = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 10, 7, 0),
'check_out': datetime(2026, 10, 10, 10, 0),
})
saturday.work_entry_type_id.code, saturday.time_rule_id.name, saturday.overtime_attendance_ids
# ('USOVERTIME150', 'Daily overtime', hr.attendance())
# shortening the source flags its output
attendance.check_out = datetime(2026, 10, 5, 13, 0)
attendance.worked_hours, output.source_stale # (7.0, True)
output.unlink()
attendance.check_out = datetime(2026, 10, 5, 16, 0) # evaluated again: new output
attendance.check_out, attendance.overtime_attendance_ids.check_in
# (datetime.datetime(2026, 10, 5, 14, 0), datetime.datetime(2026, 10, 5, 14, 0))
The attendance implementation of the source hooks is small: outputs are built by
_get_output_attendance_vals() (override it to add fields to
outputs, as hr_payroll_attendance does), the result is applied by
_apply_attendance_output(), and
_get_applicable_employees() skips the employees without
schedule for the rules based on the employee schedule.
Attendance-based work entries¶
With hr_holidays_attendance installed, the validated, closed attendances produce work
entries with their own type and their real duration (break deducted); each value carries its
attendances in attendance_ids. Two behaviors exist, chosen per version by
hr.version.attendance_based (Attendance Based, defaulted from
res.company.attendance_based and copied from contract templates):
- static version (
attendance_based = False) The schedule still produces work entries, except on the days with an attendance, where the attendances replace it.
- attendance-based version
has_static_work_entries()returnsFalse: the schedule produces nothing, only attendances and time off count.
In both cases absences are cut where the employee actually worked, and an attendance overlapping a working time leave is resolved by the type sequence. The generation itself is described in Static and attendance-based versions.
Example
With the daily overtime rule above, 10 hours on Monday, 4 hours on Tuesday and nothing on Wednesday:
env['hr.attendance'].create([{
'employee_id': employee.id,
'check_in': datetime(2026, 10, 5, 6, 0), # Monday 8:00-18:00
'check_out': datetime(2026, 10, 5, 16, 0),
}, {
'employee_id': employee.id,
'check_in': datetime(2026, 10, 6, 7, 0), # Tuesday 9:00-13:00
'check_out': datetime(2026, 10, 6, 11, 0),
}])
version = employee.version_id
def summary(vals_list):
return sorted(
(v['date'].isoformat(), v['work_entry_type_id'].code, v['duration'])
for v in vals_list
)
version.attendance_based, version.has_static_work_entries() # (False, True)
summary(version.generate_work_entries(date(2026, 10, 5), date(2026, 10, 7)))
# [('2026-10-05', '002.00', 8.0), ('2026-10-05', 'USOVERTIME150', 2.0),
# ('2026-10-06', '002.00', 4.0), ('2026-10-07', '002.00', 8.0)]
version.attendance_based = True
summary(version.generate_work_entries(date(2026, 10, 5), date(2026, 10, 7)))
# [('2026-10-05', '002.00', 8.0), ('2026-10-05', 'USOVERTIME150', 2.0),
# ('2026-10-06', '002.00', 4.0)]
On Wednesday, the static version is paid by its schedule; the attendance-based version is not. On Tuesday, both get the 4 hours worked, not the 8 hours of the schedule.
Scheduled actions¶
- Attendance: Automatically check-out employees (every 4 hours)
_cron_auto_check_out(), for the companies withauto_check_out. Intolerancemode (_cron_auto_check_out_tolerance()), an open attendance is closed once the time worked on its day exceeds the expected hours plusauto_check_out_tolerance; the check out is set to the moment the limit was reached. Employees with a flexible schedule are skipped. Inspecific_timemode (_cron_auto_check_out_specific_time()), open attendances are closed atauto_check_out_specific_time(local hour). The check out mode isauto_check_outand a message is posted.- Attendance: Detect Absences for employees (every 4 hours)
_cron_absence_detection(), for the companies withabsence_management: for each employee in contract with a schedule and without attendance on the previous day, it creates a validated 1-secondtechnicalattendance at local midnight, so that the daily undertime rules see the day. Technical attendances that produce no output are deleted.- Attendance: Process daily time rules and Attendance: Process weekly time rules (daily)
The crons of the source mixin, see When rules run.
Example
company.write({
'auto_check_out': True,
'auto_check_out_mode': 'tolerance',
'auto_check_out_tolerance': 2,
})
attendance = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 22, 6, 0), # yesterday, 8:00 in Brussels
})
env['hr.attendance']._cron_auto_check_out()
attendance.check_out, attendance.out_mode, attendance.worked_hours
# (datetime.datetime(2026, 10, 22, 16, 0), 'auto_check_out', 10.0): 8 hours + 2
# absence detection with a daily undertime rule
unpaid = env['hr.work.entry.type'].search([
('code', '=', '158.00'), ('country_id.code', '=', 'US'),
])
env['hr.time.rule'].create({
'name': 'Daily undertime',
'company_id': company.id,
'threshold_operator': 'less_than',
'work_entry_type_id': unpaid.id,
})
company.absence_management = True
bob = env['hr.employee'].create({
'name': 'Bob Example',
'tz': 'UTC',
'date_version': date(2026, 1, 1),
'contract_date_start': date(2026, 1, 1),
})
env['hr.attendance']._cron_absence_detection()
env['hr.attendance'].search([('employee_id', '=', bob.id)]).mapped(lambda a: (
a.check_in, a.check_out, a.in_mode, a.work_entry_type_id.code, a.time_rule_id.name))
# [(datetime.datetime(2026, 10, 22, 8, 0, 1), datetime.datetime(2026, 10, 22, 16, 0),
# 'manual', '158.00', 'Daily undertime'),
# (datetime.datetime(2026, 10, 22, 0, 0), datetime.datetime(2026, 10, 22, 0, 0, 1),
# 'technical', '002.00', False)]
Overtime and time off: hr_holidays_attendance¶
The bridge module hr_holidays_attendance (auto-installed with hr_attendance and
hr_holidays) adds, besides the work entries described above:
- Compensatory allocations
A rule with
leave_compensation_rate(Allocate %) andallocation_type_id(a type requiring an allocation) creditshours * rate / hours_per_daydays to an open-ended (date_to = False) validated allocation of the employee, created if needed; an undertime rule deducts them. Undertime that would overdraw the allocation is dropped entirely (no output, no deduction). Each credit is logged inhr.time.rule.allocation.logon the attendance that holds the time: the reclassified source, or the output attendance.- Reversal
Deleting that attendance, changing its span or employee, or setting a validated attendance back to
draftorrefusedreverses its logged credits (refusing a source also refuses its outputs) (write()); re-running the rules credits the new values. A reversal that would bring the allocation below what was already taken raises aValidationError.- Public holidays
Creating, changing or deleting a public holiday (
resource.calendar.leaveswithout resource) re-runs the rules on the attendances of the affected employees (_retrigger_time_rules()): a public holiday has no expected hours, so the time worked on it becomes excess.- Accrual on worked hours
Accrual plan levels get the frequency Per Hour Worked (
worked_hours): the accrued amount is prorated on the hours of the validated attendances of the period (_get_accrual_plan_level_work_entry_prorata()). It cannot be combined with an accrual at the start of the period.
The company attendance type (attendance_work_entry_type_id) is restricted to types that do
not require an allocation.
Example
compensatory = env['hr.work.entry.type'].search([
('code', '=', 'LEAVE105'), ('country_id', '=', False),
])
compensatory.name, compensatory.requires_allocation # ('Compensatory Time Off', True)
env['hr.time.rule'].create({
'name': 'Daily overtime',
'company_id': employee.company_id.id,
'work_entry_type_id': overtime.id,
'leave_compensation_rate': 1.0, # 100% of the excess
'allocation_type_id': compensatory.id,
})
attendance = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 5, 6, 0), # 10 hours: 2 hours of overtime
'check_out': datetime(2026, 10, 5, 16, 0),
})
allocation = env['hr.leave.allocation'].search([('employee_id', '=', employee.id)])
(allocation.work_entry_type_id.name, allocation.number_of_days, allocation.state,
allocation.date_to)
# ('Compensatory Time Off', 0.25, 'validate', False): 2 hours / 8 hours per day
output = attendance.overtime_attendance_ids
env['hr.time.rule.allocation.log'].search([('allocation_id', '=', allocation.id)]).mapped(
lambda log: (log.res_model, log.res_id == output.id, log.days))
# [('hr.attendance', True, 0.25)]
output.unlink()
allocation.number_of_days # 0.0
env['resource.calendar.leaves'].create({
'name': 'Public holiday',
'company_id': employee.company_id.id,
'date_from': datetime(2026, 10, 6, 22, 0), # Wednesday in Brussels
'date_to': datetime(2026, 10, 7, 21, 59, 59),
})
worked = env['hr.attendance'].create({
'employee_id': employee.id,
'check_in': datetime(2026, 10, 7, 6, 0),
'check_out': datetime(2026, 10, 7, 14, 0),
})
worked.work_entry_type_id.code, worked.time_rule_id.name, allocation.number_of_days
# ('USOVERTIME150', 'Daily overtime', 1.0)
Extending¶
- Check in and out
Override
_attendance_action_change()(one employee, returns a notification orFalse). Extra values for the attendance are best passed throughgeo_informationkeys matchingin_<key>/out_<key>fields. Add data to the kiosk and systray responses in the controller helpers_get_user_attendance_dataand_get_employee_info_response(static methods: override them in a subclass of the controller and callsuper(SubClass, SubClass)).- Validation
_update_tolerance_state()implements the tolerance policy;_get_source_extra_fields_domain()decides which attendances the rules see.- Time rule outputs
_get_output_attendance_vals()for the values of output attendances,_apply_attendance_output()for side effects after the rules (keep returning the result ofsuper()), and_get_write_source_extra_source_fields()to re-run the rules when another field changes.- Work entries
The
hr.versionhooks of Extending;hr_holidays_attendanceoverrides_get_version_work_entries_values()and passes its intervals to the other hooks through the context.
Pitfalls¶
check_inandcheck_outare naive UTC;dateand every «day» (tolerance, automatic check out, hours today) are in the employee’s timezone._check_validityis skipped when the context hasskip_time_rules, which the rule engine, the refusal and the automatic check out use. Code passing that context must keep the attendances consistent itself.A source reclassified or cut by a rule cannot be extended over its outputs: the overlap constraint fails. Delete the outputs first.
Outputs are not deleted when their source changes, only flagged
source_stale; code reading attendances (reports, payroll) must decide what to do with stale outputs.Only validated attendances are rule sources and produce work entries: with
manual_validation, nothing happens until an officer validates.The time rules produce nothing for the days before
contract_date_start.hours_last_month*cover the current month, andtotal_overtimeall the validated time rule outputs ever, whatever their type (an undertime output counts too).Kiosk routes are public and run as superuser: protect the kiosk URL like a password, and check the company of every record received from the client in custom routes.
Reference¶
Original definition from hr_attendance¶
- model odoo.addons.hr_attendance.models.hr_attendance.HrAttendance[fuente]¶
- _name = hr.attendance¶
- check_in: datetime.datetime¶
- Required
- Name
Check In
- Default
2026-11-03 10:37:44
- check_out: datetime.datetime¶
- Name
Check Out
- date: datetime.date¶
- Required
- Name
Date
- Readonly
this field is not supposed to/cannot be set manually
- worked_hours: float¶
- Name
Worked Hours
- Readonly
this field is not supposed to/cannot be set manually
- state: str¶
- Required
- Name
Status
- Readonly
this field is not supposed to/cannot be set manually
- Selection
draft: Draftvalidated: Validatedrefused: Refused- Default
draft
- in_mode: str¶
- Name
Mode
- Readonly
this field is not supposed to/cannot be set manually
- Selection
kiosk: Kiosksystray: Systraymanual: Manualtechnical: Technical- Default
manual
- out_mode: str¶
- Name
Out Mode
- Readonly
this field is not supposed to/cannot be set manually
- Selection
kiosk: Kiosksystray: Systraymanual: Manualtechnical: Technicalauto_check_out: Automatic Check-Out- Default
manual
- overtime_attendance_ids: Sequence[odoo.orm.commands.Command]¶
- Name
Overtime Attendance
- Comodel
- create(vals_list)[fuente]¶
Create attendances, with an initial
statederived from the validation policy.Without
statein the values, time rule outputs (time_rule_idorsource_attendance_idset) arevalidated; other attendances arevalidatedif the employee’s company hasattendance_validation = 'no_validation', elsedraft._update_tolerance_state()then applies the tolerance policy.
- write(vals)[fuente]¶
Write
vals, then flag the time rule outputs and validate within tolerance.Moving an attendance to another employee requires being that employee, an attendance administrator or the employee’s attendance approver. When a field of
_STALE_TRIGGER_FIELDSchanges, the outputs that existed before the write (and that survive it) getsource_stale = True. A newcheck_out(withoutstate) re-applies the tolerance policy (_update_tolerance_state()).- Muestra
AccessError – if the user cannot assign the attendance to
employee_id
- action_refuse()[fuente]¶
Refuse the attendances and the records the time rules created from them (
overtime_attendance_ids), without running the time rules (skip_time_rules).
- _check_validity()[fuente]¶
Check the attendance against the other attendances of the employee.
An employee has at most one open attendance (without
check_out) and no overlapping attendances. Skipped when the context hasskip_time_rules, i.e. for the writes of the time rule pipeline, the refusal and the automatic check-out.- Muestra
ValidationError – if the attendance overlaps another one or if another attendance of the employee is still open
- _check_validity_check_in_check_out()[fuente]¶
Check that
check_outis not earlier thancheck_in.- Muestra
ValidationError – if it is
- _check_break_duration()[fuente]¶
Check that
break_durationis positive, only set on closed attendances and not longer than the attendance.- Muestra
ValidationError – if one of these conditions is not met
- _compute_worked_hours()[fuente]¶
Compute
worked_hours:check_out - check_inin hours, minusbreak_duration.The schedule (lunch break included) is not used. Open attendances get
0.
- _update_tolerance_state()[fuente]¶
Validate the closed draft attendances within the tolerance of their company.
Only for the companies with
attendance_validation = 'tolerance_validation', on the attendances not produced by a time rule: an attendance is validated when its duration (break included) differs from the expected hours of its local day by at mostattendance_validation_tolerance, or when no hours are expected that day. As foraction_validate(), writing the state runs the time rules on them.
- _get_localized_times()[fuente]¶
Return
check_inandcheck_outin the timezone of the employee’s version.The attendance must be closed.
- Devuelve
(check_in, check_out), naive local datetimes- Tipo del valor devuelto
- _get_break_duration_within_period(start, stop)[fuente]¶
Return the part of the break durations of
selffalling within a period.The break of each closed attendance is prorated to the share of the attendance that lies within
[start, stop].- Parámetros
start (datetime) – naive local datetime (employee’s timezone)
stop (datetime) – naive local datetime
- Devuelve
hours
- Tipo del valor devuelto
- _cron_auto_check_out()[fuente]¶
Cron: check out the forgotten open attendances, for the companies with
auto_check_out, intoleranceand inspecific_timemode.
- _cron_auto_check_out_tolerance()[fuente]¶
Check out the open attendances exceeding the expected hours of their day plus the company’s
auto_check_out_tolerance.Applies to the companies in
tolerancemode, to employees with a non flexible schedule. The expected hours are those of the schedule on the local day of the check-in (hr.employee._get_expected_attendances); the hours already worked that day are deducted. The check-out is set to the moment the limit was reached (at least one second after the check-in), without_mode = 'auto_check_out', and a message is posted.
- _cron_auto_check_out_specific_time()[fuente]¶
Check out the open attendances once the company’s
auto_check_out_specific_timeis reached.Applies to the companies in
specific_timemode. The check-out is the first occurrence of that hour (employee’s timezone) after the check-in, as soon as it is past, without_mode = 'auto_check_out'; a message is posted.
- _cron_absence_detection()[fuente]¶
Cron: create a validated 1-second technical attendance for each employee without attendance yesterday.
Only for the companies with
absence_management, and the employees with a schedule whose current version is in contract yesterday. The attendance starts at local midnight and has the company’s attendance type, so that the daily undertime rules see the day and create output attendances for the missed hours. Technical attendances without any output are deleted afterwards.
- _apply_record_output(rules, excess, deficit, active_iv=None)[fuente]¶
Apply the time rule results through
hr.time.rule._apply_attendance_output.
- _get_time_rule_deficit_occupied(employee_id, start_utc, period_end_utc)[fuente]¶
Return the spans of the attendances of the employee overlapping the period, refused ones excepted, so that undertime outputs are placed outside of them.
- Tipo del valor devuelto
Intervals
- _get_time_rule_output_vals(rule, df, dt, pp)[fuente]¶
Return the values of an output attendance, see
hr.time.rule._get_output_attendance_vals.- Tipo del valor devuelto
- _get_time_rule_remainder_vals(df, dt)[fuente]¶
Return the values of a remainder attendance:
employee_id,check_in,check_outandsource_attendance_id.- Tipo del valor devuelto
- _get_source_extra_fields_domain()[fuente]¶
Only validated attendances are time rule sources.
- Tipo del valor devuelto
- _get_time_rule_break_hours()[fuente]¶
Return
break_duration, which the time rules do not count as worked time.- Tipo del valor devuelto
- _get_write_source_extra_source_fields()[fuente]¶
Writing
work_entry_type_id,stateorbreak_durationalso runs the rules.
Additional fields with hr_attendance¶
- model odoo.addons.hr_attendance.models.hr_employee.HrEmployee[fuente]¶
- attendance_manager_id: int¶
- Name
Attendance Approver
- Comodel
res.users
The user set in Attendance will access the attendance of the employee through the dedicated app and will be able to edit them.
- attendance_ids: Sequence[odoo.orm.commands.Command]¶
- Name
Attendance
- Comodel
- last_attendance_id: int¶
- Name
Last Attendance
- Readonly
this field is not supposed to/cannot be set manually
- Comodel
- attendance_state: str¶
- Name
Attendance Status
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- Selection
checked_out: Checked outchecked_in: Checked in
- hours_today: float¶
- Name
Hours Today
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- hours_last_month: float¶
- Name
Hours Last Month
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- hours_last_month_overtime: float¶
- Name
Hours Last Month Overtime
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- total_overtime: float¶
- Name
Total Overtime
- Readonly
this field is not supposed to/cannot be set manually
- Store
this field is there only for technical reasons
- _attendance_action_change(geo_information=None, check_in_image_data=None)[fuente]¶
Check the employee in or out, now.
If the employee is not checked in, create an attendance; otherwise set
check_outon the open attendance, unless the company usessingle_check_inand the employee’s schedule is not flexible (then nothing is done). The presence state is sent on the bus.- Parámetros
geo_information (dict) – values written with an
in_(check-in) orout_(check-out) prefix, e.g.{'mode': 'kiosk', 'latitude': ..., 'longitude': ..., 'location': ..., 'ip_address': ..., 'browser': ...}check_in_image_data (dict) –
{'image': bytes, 'type': str}, stored inin_imageand posted on the attendance at check-in
- Devuelve
False, or a notification{'type': 'warning', 'message': str}when the company requires a check-in picture and none was given- Muestra
UserError – if no open attendance is found to check out, or on a check-out from the systray (context
is_from_systray_check_in_out) withsingle_check_in
- _has_attendance_check_in_ability()[fuente]¶
Return whether the employee may check in and out from the systray (company’s
attendance_from_systray).- Tipo del valor devuelto
- get_attendance_data_by_employee(date_start, date_stop)[fuente]¶
Return the hours of the attendances overlapping a period, per employee.
Hours are the full
worked_hoursof the overlapping attendances (not clipped to the period);overtime_hourssums the attendances produced by a time rule.- Parámetros
date_start (datetime) – naive UTC
date_stop (datetime) – naive UTC
- Devuelve
{employee_id: {'worked_hours': float, 'overtime_hours': float, 'entries': [{'name': str, 'worked_hours': float, 'color': int}]}}, one entry per work entry type- Tipo del valor devuelto
- _compute_hours_today()[fuente]¶
Compute the hours worked today (employee’s timezone) until now, breaks deducted.
hours_todayis the total,last_attendance_worked_hoursthe part of the last attendance,hours_previously_todaythe rest;today_attendance_idsare the attendances overlapping today.
- _compute_hours_last_month()[fuente]¶
Compute the hours of the current month (despite the field names), in the employee’s timezone.
Only the closed attendances within the month count:
hours_last_monthsums those not produced by a time rule,hours_last_month_overtimethose produced by one.
- _compute_presence_state()[fuente]¶
Use the attendance state in the presence state, after the login.
A checked in employee (or an employee without user) is
present, unless the employee has no user and is out of contract; a checked out employee within working hours and in contract isabsent.
Additional fields with hr_attendance¶
Additional fields with hr_attendance¶
- model odoo.addons.hr_attendance.models.hr_time_rule.HrTimeRule[fuente]¶
- _get_applicable_employees(employees)[fuente]¶
Also drop the employees without schedule for the rules based on the employee schedule (
calendar_source = 'employee').
- _get_output_attendance_vals(employee, check_in, check_out, source_attendance=None, accumulated_pp=frozenset({}))[fuente]¶
Return the creation values of an output attendance of the rule.
- Parámetros
employee –
hr.employeecheck_in (datetime) – naive UTC
check_out (datetime) – naive UTC
source_attendance – the source
hr.attendanceaccumulated_pp (frozenset) – premium pay ids, used by overrides (
hr_payroll)
- Devuelve
employee_id,work_entry_type_id(the rule’s output type),check_in,check_out,source_attendance_idandtime_rule_id- Tipo del valor devuelto
- _apply_attendance_output(excess, deficit, active_iv=None)[fuente]¶
Write the time rule results on attendances (
hr.time.rule._apply_output).hr_holidays_attendanceextends it to credit or deduct allocations.- Devuelve
the result of
_apply_output:(new_records, all_source_ids, excess_alloc, deficit_alloc)- Tipo del valor devuelto
Additional fields with hr_attendance¶
- model odoo.addons.hr_attendance.models.res_company.ResCompany[fuente]¶
- attendance_kiosk_mode: str¶
- Name
Attendance Mode
- Selection
barcode: Barcode / RFIDbarcode_manual: Barcode / RFID and Manual Selectionmanual: Manual Selection- Default
barcode_manual
- auto_check_out_mode: str¶
- Name
Auto Check Out Mode
- Selection
tolerance: Tolerancespecific_time: Specific Time- Default
tolerance
- attendance_validation: str¶
- Name
Attendance Validation
- Selection
no_validation: Worked days are automatically approvedmanual_validation: Worked days require manual approvaltolerance_validation: Worked days require approval if outside tolerance- Default
no_validation
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.hr_attendance.HrAttendance[fuente]¶
- write(vals)[fuente]¶
Reverse the allocation credits logged on the attendances before an invalidating write.
Credits are reversed when
check_in,check_outoremployee_idchange (unless the context hasskip_time_rules), or when a validated attendance goes back todraftor isrefused. Re-running the rules credits the new values again.- Muestra
ValidationError – if the allocation was already used beyond its allowed balance
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.hr_version.HrVersion[fuente]¶
- has_static_work_entries()[fuente]¶
Attendance-based versions have no static work entries.
- Tipo del valor devuelto
- _get_attendance_intervals(start_dt, end_dt)[fuente]¶
Return empty intervals for the resources of attendance-based versions, the schedule intervals for the others.
- Devuelve
{resource_id: Intervals}- Tipo del valor devuelto
- _get_version_work_entries_values(date_start, date_stop)[fuente]¶
Add the raw values of the validated, closed attendances of the period.
Each attendance gives a value of its own type, from
check_intocheck_outminus the break, with the keyattendance_ids; where an attendance and a working time leave overlap, the lowest type sequence wins. The schedule part is computed bysuper()with three context keys ({resource_id: Intervals}, aware UTC):knocked_day_intervals: for static versions, the local days with an attendance, removed from the schedule (_get_real_attendances());time_on_intervals: the worked time (attendances and working time leaves), cut out of the absences (_get_valid_leave_intervals());att_coverage_intervals: the attendance segments that won over a working time leave, cut out of that leave.
- _get_real_attendances(attendances, leaves, worked_leaves)[fuente]¶
Also remove the days with an attendance (context
knocked_day_intervals).
- _get_valid_leave_intervals(attendances, interval)[fuente]¶
Cut absences where the employee worked (context
time_on_intervals) and working time leaves where an attendance won (contextatt_coverage_intervals).- Tipo del valor devuelto
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.hr_time_rule.HrTimeRule[fuente]¶
- _apply_attendance_output(excess, deficit, active_iv=None)[fuente]¶
Apply the results on attendances, then credit or deduct the allocations (
hr.time.rule._apply_allocation_credits).Deficits that would overdraw the allocation are dropped first (
_filter_deficit_exceeding_allocation): they create neither output nor deduction.- Devuelve
the result of the base method, see
hr.time.rule._apply_output- Tipo del valor devuelto
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.resource_calendar_leaves.ResourceCalendarLeaves[fuente]¶
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.hr_leave_allocation.HrLeaveAllocation[fuente]¶
- _get_accrual_plan_level_work_entry_prorata(level, start_period, start_date, end_period, end_date)[fuente]¶
For
worked_hourslevels, return the hours of the validated attendances of the employee betweenstart_dateandend_date.The attendance spans are united and clipped to the period; breaks are not deducted.
- Tipo del valor devuelto
Additional fields with hr_holidays_attendance¶
- model odoo.addons.hr_holidays_attendance.models.hr_leave_accrual_plan_level.HrLeaveAccrualLevel[fuente]¶
-
- _check_worked_hours()[fuente]¶
Forbid the
worked_hoursfrequency on levels accruing at the start of the period.- Muestra
ValidationError – if
frequency = 'worked_hours'andaccrued_gain_time = 'start'