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>
25 lines
951 B
Python
25 lines
951 B
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
"""Backfill schedule state on upgrade to 19.0.3.12.0.
|
|
|
|
Before this version there was no draft/posted concept — every dated
|
|
``fusion.clock.schedule`` entry was authoritative and drove reminders, absence
|
|
checks and penalties. The new ``state`` field defaults to 'draft', and the
|
|
schedule resolver now only acts on POSTED entries. Without this backfill, every
|
|
pre-existing schedule entry would silently become draft on upgrade and stop
|
|
driving automation. Mark all pre-existing entries 'posted' to preserve prior
|
|
behaviour. (Runs only on upgrade, never on a fresh install.)
|
|
"""
|
|
|
|
|
|
def migrate(cr, version):
|
|
if not version:
|
|
return
|
|
cr.execute("""
|
|
UPDATE fusion_clock_schedule
|
|
SET state = 'posted',
|
|
posted_date = COALESCE(posted_date, now())
|
|
WHERE state IS NULL OR state = 'draft'
|
|
""")
|