feat(fusion_clock): schedule-driven attendance automation
Reminders, absence detection, late/early penalties, and auto-clock-out are now driven by each employee's real schedule (posted planner entry -> recurring shift), never the global 9-5 default. Employees who aren't scheduled get no reminders/absence. Overtime past the scheduled end is never cut off — auto clock-out only fires at a max-shift safety cap (default raised 12 -> 16h). Team leads build the planner in draft and Post it (publishes + emails employees). - hr.employee._get_fclk_day_plan: explicit `scheduled` flag; posted-only planner entries (drafts ignored), else recurring shift covering that weekday, else not-scheduled; sources 'schedule'/'shift'/'none'. - fusion.clock.shift: day_mon..day_sun weekday pattern + covers_weekday(). - fusion.clock.schedule: draft/posted state + posted_date; planner edits reset to draft; fclk_email_posted_week notification. - Rewrote the reminder / absence / auto-clock-out crons: schedule-gated, per-employee savepoints, OT-aware cap, weekend hardcode removed. - Penalties + all three clock-in paths skip days the employee isn't scheduled. - shift_planner: Post Week route + planner Post button + draft count. - Migration backfills pre-existing schedule entries to 'posted' so they keep driving automation after upgrade. - Tests: resolver matrix, cron gating, OT cap; fixed the existing planner test for the new state/source semantics. Design: docs/superpowers/specs/2026-05-30-schedule-driven-attendance-design.md Frontend footprint kept at zero to avoid colliding with the concurrent employee-portal (payslips) work. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
<field name="end_time" widget="float_time"/>
|
||||
<field name="break_minutes"/>
|
||||
<field name="planned_hours"/>
|
||||
<field name="state" widget="badge" decoration-success="state == 'posted'" decoration-warning="state == 'draft'"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</list>
|
||||
</field>
|
||||
@@ -47,6 +48,8 @@
|
||||
</group>
|
||||
<group>
|
||||
<field name="note"/>
|
||||
<field name="state"/>
|
||||
<field name="posted_date" readonly="1"/>
|
||||
<field name="department_id" readonly="1"/>
|
||||
<field name="company_id" readonly="1" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
@@ -65,6 +68,9 @@
|
||||
<field name="schedule_date"/>
|
||||
<filter name="off" string="OFF" domain="[('is_off', '=', True)]"/>
|
||||
<filter name="working" string="Working" domain="[('is_off', '=', False)]"/>
|
||||
<separator/>
|
||||
<filter name="posted" string="Posted" domain="[('state', '=', 'posted')]"/>
|
||||
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
|
||||
<filter name="group_department" string="Department" context="{'group_by': 'department_id'}"/>
|
||||
<filter name="group_date" string="Date" context="{'group_by': 'schedule_date'}"/>
|
||||
</search>
|
||||
|
||||
@@ -39,6 +39,15 @@
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<group string="Working Days" col="7">
|
||||
<field name="day_mon"/>
|
||||
<field name="day_tue"/>
|
||||
<field name="day_wed"/>
|
||||
<field name="day_thu"/>
|
||||
<field name="day_fri"/>
|
||||
<field name="day_sat"/>
|
||||
<field name="day_sun"/>
|
||||
</group>
|
||||
<group string="Assigned Employees">
|
||||
<field name="employee_ids" nolabel="1" colspan="2">
|
||||
<list>
|
||||
|
||||
Reference in New Issue
Block a user