Commit Graph

1498 Commits

Author SHA1 Message Date
gsinghpal
b17bd615bf feat(fusion_portal): Phase 1b - Assessment Visit model + accessibility funding grouping
Adds fusion.assessment.visit: the hub that bundles a home visit's assessments and,
on completion, groups its ACCESSIBILITY assessments by funding workflow
(x_fc_sale_type) and creates ONE draft sale order per workflow, reusing the existing
MOD/ODSP/etc. pipelines + the chatter-note pattern. ADP assessments keep one-SO-each
for now (ADP multi-device grouping is Phase 2).

- New model + sequence (VISIT/YYYY/NNNN) + ACL + backend list/form/menu.
- visit_id added to fusion.assessment, fusion.accessibility.assessment, sale.order.
- action_complete_visit() group-and-routes; MOD $15k cap + income-threshold flag
  surfaced (informational, no auto-enforcement).

NOT YET: completion-email consolidation; ADP multi-device (Phase 2); portal
add-as-you-go workspace (Phase 3). Untested locally (Enterprise knowledge dep) -
to be verified on a westin-v19 clone before prod.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 02:00:53 -04:00
gsinghpal
e36aaab306 fix(fusion_portal): validate funding_source in accessibility save (parity with booking)
Coerce an unexpected/tampered funding_source to direct_private instead of passing
it raw into create() (which would raise on the Selection field). Mirrors the
/book-assessment controller; the whitelist is derived from the model selection so
it auto-covers hardship and any future values.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 01:38:42 -04:00
gsinghpal
37efc5b858 feat(fusion_portal): funding-source selector on accessibility forms
Reps can now mark an accessibility assessment's funding source on the web form
(Private / March of Dimes / ODSP / WSIB / Hardship / Insurance / Other) so the
generated draft sale order routes to the correct funding pipeline instead of
always defaulting to private pay. Adds Hardship to the x_fc_funding_source
selection + sale_type_map; the new form <select> is auto-serialised by the
existing FormData submit, and accessibility_assessment_save now maps
funding_source -> x_fc_funding_source. The model + SO routing were already in
place (2026-04 audit fix) — this closes the form + controller gap.

Plan: docs/superpowers/plans/2026-06-02-accessibility-funding-selector.md
Spec: docs/superpowers/specs/2026-06-02-assessment-visit-funding-design.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 01:33:24 -04:00
gsinghpal
aafc2db8a8 docs(fusion_portal): spec for assessment Visit + funding-routed sale orders
Brainstormed design: bundle a home visit's assessments (ADP + accessibility),
measurement-first with client/funding deferred, add-as-you-go workspace,
per-item funding selector (fixes the March-of-Dimes routing gap), and on
completion group items into ONE draft sale order per funding workflow
(ADP / MOD / ODSP / Hardship / private) reusing the existing pipelines.
Adds ADP multi-device + combination rules, a new mobility-scooter type, and a
power-mobility home-accessibility rule that feeds the accessibility upsell.
v1 keeps manual quotation (no auto-pricing); MOD $15k cap is a reminder only.
Phased 1-3; risks + file map included.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 01:20:26 -04:00
gsinghpal
747c814249 refactor(fusion_portal): rename from fusion_authorizer_portal + modern photo cards on accessibility selector
Rename module fusion_authorizer_portal -> fusion_portal everywhere:
manifest/assets, controllers, models, views, JS (odoo.define + asset URLs),
migration MODULE constants; plus cross-module refs in fusion_schedule,
fusion_repairs, fusion_quotations (depends + inherit_id) and the pdf_filler
import in fusion_claims. Add rename_module.sql for the one-time in-place DB
rename (ir_module_module, ir_model_data, ir_ui_view.key,
ir_module_module_dependency) required on installed envs before -u fusion_portal.
Document the rename gotcha as rule 16 in CLAUDE.md.

Redesign the Accessibility Assessment selector: replace Font Awesome icon tiles
with photo-banner cards using 7 optimized images (1000x750 PNG -> 800x600 JPEG,
~8MB -> 488KB), per-type colour accent bar + centered pill button, hover
lift/zoom. Images ship as module static files so they deploy/sync with the module.

Drop the regenerable graphify-out cache from the module.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 22:38:14 -04:00
gsinghpal
c527c7cade fix(fusion_clock): migration must recompute net_hours/overtime, not just break
Recomputing only x_fclk_break_minutes left historical x_fclk_net_hours / x_fclk_overtime_hours stale (add_to_compute+flush of one field does not cascade to dependents). Recompute the full chain in dependency order. Caught verifying the entech deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 00:28:12 -04:00
gsinghpal
f7ec1e28f9 feat(fusion_clock): province-aware automatic unpaid break (2-tier)
Statutory unpaid break now deducts automatically from worked hours on every path - portal, kiosk, NFC, auto-clock-out cron, AND manual backend entry.

- new fusion.clock.break.rule per-province table (seed Ontario 5h->30, 10h->+30), resolved from the employee's company province with a global default fallback
- x_fclk_break_minutes is now a single idempotent stored compute (statutory(worked_hours) + penalties), replacing the 4 duplicated write sites (_apply_break_deduction x3 callsites + auto-clock-out cron + penalty write)
- retire break_threshold_hours (superseded by per-rule break1_after_hours); post-migrate drops the param and recomputes historical breaks
- 11 tests all green; module install + 19.0.4.1.0 migration verified on modsdev

Bump 19.0.4.0.3 -> 19.0.4.1.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 00:15:42 -04:00
gsinghpal
96b3f124f8 docs(fusion_clock): fix plan so the 19.0.4.1.0 migration fires in dev (bump in Task 4)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:50:08 -04:00
gsinghpal
2c32e7bcd0 docs(fusion_clock): implementation plan for province-aware auto break
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:46:42 -04:00
gsinghpal
aa9b95bd5d docs(fusion_clock): spec for province-aware automatic unpaid break
2-tier statutory break deduction: new fusion.clock.break.rule per-province table (seed Ontario 5h/30 + 10h/30); x_fclk_break_minutes becomes an idempotent stored compute (statutory + penalties) firing on every path incl. manual backend entry; collapses the 4 duplicated break-write sites into one calculator.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 23:35:58 -04:00
gsinghpal
493f01827e Update res_config_settings.cpython-312.pyc 2026-05-31 22:53:43 -04:00
gsinghpal
2ab59bccde feat(fusion_clock): default clock-in/out times as 12-hour AM/PM dropdowns
People aren't good with 24h. Default Clock-In/Out are now AM/PM dropdowns (15-min
grid) instead of 24h float_time inputs. Stored value stays the float-string
(e.g. '9.0'), so all downstream float(get_param(...)) reads are unchanged;
persisted manually with get-snap for any off-grid value. Bump 19.0.4.0.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:47:12 -04:00
gsinghpal
914c96a09a fix(fusion_clock): add role=button to kiosk Open links (a11y warning)
Odoo warns that <a class=btn> needs role=button. Bump 19.0.4.0.2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:31:30 -04:00
gsinghpal
b015958edc feat(fusion_clock): unify + label kiosk settings, add quick-open buttons
Settings tidy-up: one 'Kiosk' block holding both PIN Kiosk and NFC Kiosk
(clearly described so users know which is which), each with an Open-kiosk
button when enabled; Corrections + Sounds split into a 'Portal' block. Move
Auto-Wipe Photos under Photo Verification (was hidden for PIN-only clients).
Bump 19.0.4.0.0 -> 19.0.4.0.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 22:07:00 -04:00
gsinghpal
ca94a4c42a changes 2026-05-31 21:33:44 -04:00
gsinghpal
a5ec79013a feat(fusion_clock): PIN kiosk — polished photo-tile + PIN clock (opt-in)
A proper shared-device PIN kiosk for clients who don't want NFC: photo-tile grid
(+search) -> tap -> PIN (or first-use create) -> optional master-gated selfie ->
clock, in the NFC kiosk's dark glass + brand-gradient style. Built as an Odoo 19
Interaction; new pin_kiosk.scss (scoped); reworked clock_kiosk.py
(search +avatar/has_pin, verify_pin needs_setup, set_pin, clock via kiosk location).
Drops the redundant kiosk_pin_required (PIN always required); relabels the company
kiosk location; adds a PIN-kiosk app icon. Opt-in via enable_kiosk (off by default).
HttpCase tests added. Bump 19.0.4.0.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 21:25:32 -04:00
gsinghpal
b61e159e6f docs(fusion_clock): PIN kiosk implementation plan (TDD, 7 tasks)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 21:09:03 -04:00
gsinghpal
13a892c7ab docs(fusion_clock): PIN kiosk design spec (photo-tile + PIN, NFC-matching style)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 20:56:21 -04:00
gsinghpal
2ee01fd1f2 fix(fusion_clock): Photo Verification is now a real master switch (was ignored)
The global enable_photo_verification toggle only fed the portal get_settings flag;
the actual writes ignored it — the NFC kiosk gated on nfc_photo_required and the
portal on location.require_photo, so photos were captured even with the toggle OFF.
Now it's the master: OFF => no photo captured/stored anywhere (NFC kiosk config +
tap, and portal check-in); ON => per-location / NFC settings apply. Test + help
text updated. Bump 3.16.0 -> 3.16.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 12:02:42 -04:00
gsinghpal
d6d6bbe161 fix(fusion_clock): settings audit — remove 2 dead knobs, make IP-fallback + all Boolean toggles work
Audit of all 41 settings found 3 that were shown but read nowhere, and 17 Boolean
toggles that couldn't be turned OFF.

- Remove grace_period_minutes (orphaned by the schedule-driven cron rewrite) and
  weekly_overtime_threshold (never implemented): field + view + seed.
- enable_ip_fallback now actually gates _verify_location's IP-whitelist check
  (default ON to preserve current behaviour).
- All 17 fusion_clock Boolean settings now persist explicitly as 'True'/'False'
  via a _FCLK_BOOL_PARAMS loop in get_values/set_values (config_parameter Booleans
  can't store False, so OFF never stuck). Add round-trip tests. Bump 3.15.2 -> 3.16.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:51:40 -04:00
gsinghpal
31098c4d14 fix(fusion_clock): Anchor Date is a real date picker (Date field, manual persist)
The Pay Period Anchor Date was a free-text Char. Make it a fields.Date (date
picker) persisted manually in get_values/set_values as 'YYYY-MM-DD' under
fusion_clock.pay_period_start (res.config.settings Date fields don't round-trip
via config_parameter in Odoo 19). Reader code unchanged. Bump 3.15.1 -> 3.15.2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:30:47 -04:00
gsinghpal
1a1ab2da4f fix(fusion_clock): tz resolver uses company.partner_id.tz (res.company has no tz in Odoo 19)
_resolve_tz fell back to env.company.tz, which raises AttributeError for any
user without a personal tz (surfaced by the new list-wide pay-period filters,
which resolve a company-level tz). Use env.company.partner_id.tz. Regression
test added. Bump 3.15.0 -> 3.15.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:23:27 -04:00
gsinghpal
3f78f652e7 feat(fusion_clock): bi-weekly attendance filter — pay-period filters + picker
Reuse the existing Pay Period setting (Frequency + Anchor) as the single
source of truth via a shared pure helper (models/pay_period.py); fusion.clock.report
delegates to it. Add Current/Previous/Next Pay Period filters to the attendance
search view (search-method computed booleans on hr.attendance), a Bi-Weekly Period
picker wizard (pick start -> auto +2 weeks, editable; Apply opens the filtered list)
reachable from an Attendance menu item and a dashboard tile. Window follows the
configured frequency; TZ-correct via local-day boundaries. Bump 3.14.4 -> 3.15.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:20:06 -04:00
gsinghpal
e230e42d81 docs(fusion_clock): bi-weekly attendance filter implementation plan (TDD, 4 tasks)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:10:49 -04:00
gsinghpal
06346cfa6b docs(fusion_clock): bi-weekly attendance filter spec (reuse pay-period config, filters + picker)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 11:05:02 -04:00
gsinghpal
a858693d9c fix(fusion_clock): dashboard 'All Attendances' opens list, not gantt
hr_attendance's action is gantt-first and the native gantt timeline renders collapsed until a manual resize; open viewType:list so the button lands on a working list. Bump 3.14.3 -> 3.14.4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:48:41 -04:00
gsinghpal
68b10e1199 feat(fusion_clock): move dashboard Quick Actions above the team/org cards
Quick Actions were at the very bottom, so managers had to scroll past the whole team band to reach the nav shortcuts. Relocate the block to just above the Team/Org section (still below the personal band everyone has). Bump 3.14.2 -> 3.14.3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 10:28:37 -04:00
gsinghpal
e260f030d1 fix(fusion_clock): make dashboard actually scroll (flex column + min-height:0)
Plain height:100%+overflow-y:auto did not scroll under the flex action container. Use the proven pattern: root flex column height:100%; inner .fclk-dash-wrap flex:1; min-height:0; overflow-y:auto. Bump 3.14.1 -> 3.14.2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:46:59 -04:00
gsinghpal
8d6fcb75a7 fix(fusion_clock): dashboard uses full page width + owns its scroll container
Drop the 1200px centred cap (wasted side space) and make .fclk-dash height:100%; overflow-y:auto so tall content scrolls. Bump 3.14.0 -> 3.14.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:42:28 -04:00
gsinghpal
fef99809e5 feat(fusion_clock): redesign dashboard — layered, role-aware, gradient cards (dark+light)
- Rework /fusion_clock/dashboard_data into a personal block (everyone)
  plus a team block (team lead = direct reports, manager = org-wide).
  A regular employee's payload never contains another employee's data.
- New OWL stacked layout: gradient KPI cards (Today/Week/OT/Streak),
  Today's Shift, Recent Activity, Upcoming Leave, Recent Penalties; team
  band adds Present/Absent/Late/Pending, roster, and Needs Attention.
- Dark/light via compile-time $o-webclient-color-scheme branching;
  drop the old runtime html.o_dark dashboard block.
- Open the Dashboard menu to group_fusion_clock_user (lead/manager imply).
- Add HttpCase permission/no-leak tests. Bump 3.13.2 -> 3.14.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:28:53 -04:00
gsinghpal
ea4f216c1a docs(fusion_clock): dashboard redesign implementation plan (TDD, 8 tasks)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:17:54 -04:00
gsinghpal
db48029e61 docs(fusion_clock): correct dashboard spec data contract (leaves auto-approved; add on_leave_count; drop very_late)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:09:54 -04:00
gsinghpal
be721f82ae docs(fusion_clock): dashboard redesign spec (layered, role-aware, gradient cards, dark+light)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 02:07:34 -04:00
gsinghpal
806ec5a5a6 refactor(fusion_clock): reorganize backend menus into logical groups
- Attendance now groups the operational records: All Attendances, Leave
  Requests, Correction Requests, Penalties (Leaves + Penalties moved in from
  top level).
- Scheduling groups all schedule-building: Shift Planner, Scheduled Shifts,
  Shifts (templates, moved from Configuration), Schedule Audit.
- Configuration: Settings, Locations, Enroll NFC Card (the NFC wizard moved in
  from top level).
- Removed the duplicate top-level Locations menu (kept the one under Config).
Only parent/sequence changed; no actions/views touched. Live on entech 3.13.2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 01:44:53 -04:00
gsinghpal
0acd2251e6 fix(fusion_planning): My Schedule shows posted fusion_clock shifts, not just Planning slots
The "My Schedule" portal page read only published planning.slot (Odoo Planning),
but team leads post in the fusion_clock Shift Planner, which writes
fusion.clock.schedule -> so posted schedules never appeared. Merge both sources:
the page now lists published planning.slot AND posted fusion.clock.schedule
(employee, state=posted, not OFF, within the 60-day horizon), sorted together.
Verified on entech: Garry's 7 posted shifts (Jun 1-7) now render. 19.0.1.5.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-31 01:37:18 -04:00
gsinghpal
defa7250e1 changes 2026-05-31 01:15:15 -04:00
gsinghpal
719853c251 fix(fusion_clock): leave From/To use CSS grid so they don't stack on iOS
iOS Safari date inputs have a large intrinsic min-width that can break a flex
row; switch .fclk-leave-daterange to grid 1fr 1fr + min-width:0 on the inputs
so the two fields always share the row and shrink. Also changes the bundle hash
to force iOS to drop the cached CSS. Live on entech 19.0.3.13.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 23:07:32 -04:00
gsinghpal
6a9c7c74ea feat(fusion_clock): multi-day leave requests (date range)
Request Leave now takes a From/To date range instead of a single day (the To
field is optional -> single-day). Added date_to to fusion.clock.leave.request
(start kept as leave_date), with overlap detection on submit and a date_to >=
leave_date constraint. The absence check and reports now treat a leave as
covering its whole span. The form shows two date inputs; the controller accepts
date_from/date_to (the old single leave_date payload is still honoured). A
migration backfills date_to = leave_date for existing rows.

Live and verified on entech 19.0.3.13.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 23:01:19 -04:00
gsinghpal
87639a12b5 fix(fusion_planning): add Schedule tab to the Payslips page navs
The Schedule tab is injected into the Clock/Timesheets/Reports navs via xpath
inherits, but the two payslip templates (portal_payslip_list_page,
portal_payslip_detail_page) had no inherit, so Payslips showed only 4 tabs.
Add the matching inherits. Verified on the rendered /my/clock/payslips page:
5 nav items incl. Schedule. Live on entech 19.0.1.4.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:50:12 -04:00
gsinghpal
360370db15 fix(fusion_clock): kill portal white border — neutralise .o_fp_portal_shell
Verified from the live DOM that fusion_plating_portal wraps the app in
#wrapwrap > main > .o_fp_portal_shell > .o_fp_portal_main > #wrap.o_portal_wrap
> .container. The white frame was .o_fp_portal_shell (+ .container max-width),
which my earlier wrapper-neutralisation didn't target. Add the shell + inner
main + force all wrappers transparent/full-width/no-padding under
body:has(.fclk-app). Live on entech 19.0.3.12.4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:46:19 -04:00
gsinghpal
85bbd8a20e fix(portal): recover full-bleed wrapper fix + Schedule Payslips tab
These round-2 portal fixes (white-border wrapper neutralisation in
portal_clock.css, and the Payslips nav tab on the fusion_planning Schedule
page) were briefly bundled into a concurrent NFC commit that a parallel session
then rebased, dropping them from main. They are deployed and verified on entech
(fusion_clock 3.12.3 / fusion_planning 1.3.0); re-committing so git matches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:36:38 -04:00
gsinghpal
136a64ea21 fix(fusion_clock): enforce NFC card-UID uniqueness via declarative UniqueIndex
Odoo 19 silently ignores the legacy `_sql_constraints` list (repo CLAUDE.md
rule 9), so it never created a DB constraint — two employees could be assigned
the same x_fclk_nfc_card_uid and the NFC tap's search(limit=1) then picked an
arbitrary one. Replace it with a declarative models.UniqueIndex carrying a
partial WHERE predicate, so uniqueness is enforced only when a UID is set;
employees without a card keep sharing a blank/NULL value.

Makes test_nfc_models.TestNfcModels.test_card_uid_is_unique_when_set pass.
Verified on entech (DB admin): 0 pre-existing duplicate UIDs, full upgrade +
61/61 fusion_clock tests green, and the unique partial index
hr_employee_fclk_nfc_card_uid_unique now exists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 22:34:14 -04:00
gsinghpal
a479052b72 fix(fusion_clock): portal white-border + responsive timesheet entries
- White border on every portal page: the .fclk-app full-bleed relied on exact
  negative margins to cancel the portal layout's container padding; when it
  didn't match, the white page chrome showed through. Match the PAGE background
  to the app (light #f3f4f6 / dark #0f1117, via body:has(.fclk-app)) so the
  gutter is invisible, and clip horizontal overflow.
- Timesheets not responsive: the 6-column table crammed/wrapped on phones.
  Replaced the table with stacked cards (date + net up top, in -> out, then
  break / location / Correct) that read cleanly at any width. Correction-link
  data attributes preserved; the xpath-inherited .fclk-nav-bar untouched.

Live on entech 19.0.3.12.2 (both rules verified in the served frontend bundle).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:20:56 -04:00
gsinghpal
11108dfea3 Merge: employee portal — staff Clock + Payslips, customer-sidebar gating
Internal staff now land on /my/clock with no customer sidebar; new
finalized-payslip portal under /my/clock/payslips (inline paystub from
payslip.line_ids + PDF). Customers' portal is unchanged. Live on entech.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 22:02:28 -04:00
gsinghpal
85cdecddea fix(fusion_clock): keep inline nav bars instead of a shared template
A shared portal_employee_navbar template broke fusion_planning, which
xpath-inherits each clock page's inline fclk-nav-bar to inject its
Schedule tab (anchored on a[@href='/my/clock/timesheets']). Revert to the
original inline-nav pattern on all four pages and append the Payslips item
to each — zero changes needed in fusion_planning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:56:54 -04:00
gsinghpal
2aaa1a57e7 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>
2026-05-30 21:54:05 -04:00
gsinghpal
b5d5a9acba fix(fusion_clock): build paystub from payslip.line_ids, not fusion_payroll fields
entech runs the enterprise hr_payroll module (not the custom fusion_payroll),
whose hr.payslip lacks employee_cpp/ytd_* fields. Render the inline paystub
from payslip.line_ids (name + total) so it works on any payroll provider.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:49:53 -04:00
gsinghpal
0d94af6532 fix(fusion_clock): render payslip PDF via report.id, not report_name
Odoo 19's _get_report() resolves a dotted string report_ref through
env.ref() as an XML ID, which lands on the QWeb view rather than the
ir.actions.report action. Pass the action id (matches every other
_render_qweb_pdf call site in the repo).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:45:05 -04:00
gsinghpal
95abd2e337 style(fusion_clock): payslip list/detail, 4-item nav, and sign-out styles
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:38:22 -04:00
gsinghpal
b1db851e29 feat(fusion_clock): add Payslips tab to employee nav + Sign Out in clock header
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:37:17 -04:00