Commit Graph

24 Commits

Author SHA1 Message Date
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
2fb774e4fa feat(fusion_clock): portal routes for employee payslips (list / inline paystub / pdf)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 21:34:53 -04:00
gsinghpal
5c1f60b3b8 changes 2026-05-30 20:59:59 -04:00
gsinghpal
2c8ad83d43 fix(fusion_clock): NFC clock-out shows gross worked time, not net-of-penalty
The result card showed x_fclk_net_hours = worked_hours − break − early-out
penalty minutes. Tapping out before the scheduled end adds a 15-min early-out
penalty to the break field, so short shifts clamped to 0 → "Worked 0h 0m".

Show GROSS attendance.worked_hours (the actual clock-in → clock-out elapsed
time) instead, and format adaptively (Xh Ym / Ym / Ys) so brief shifts and
quick tests don't all read 0. Net-of-deductions stays in the payroll reports.

Live as 19.0.3.11.5 (verified worked_hours computes correctly in the DB).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:59:10 -04:00
gsinghpal
3fd074ff6d fix(fusion_clock): kiosk photo now shows on clock + profile (right image fields)
Root-caused on live entech (not guessed):
- The kiosk runs as a non-HR operator (uid 141) who gets AccessError reading
  hr.employee images, so /web/image served a placeholder. Point the result-card
  avatar at hr.employee.public/avatar_128 — verified readable as the operator,
  returns the real photo. (Odoo's own UI uses .public for employee images.)
- The Odoo profile/preferences avatar is res.users → res.partner.image_1920,
  which the capture never wrote. Propagate the captured photo to the linked
  user's partner image so the profile updates too.
- Enlarge the capture oval (it was small): stage 62vh/520px, guide width 64%.

Live as 19.0.3.11.4. Also backfilled the existing test photo to the user's
partner image so the profile shows it without re-capturing.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:29:46 -04:00
gsinghpal
e26a7cd9e8 feat(fusion_clock): NFC photo capture — 10s auto-capture, vertical oval, cache-busted avatar
- Profile photo DID save (verified: image_1920 attachment persists); the
  "doesn't update" was a browser-cache miss. Add ?unique=<write_date> to the
  result-card avatar URL so a freshly-captured photo shows on clock in/out.
- Capture now starts a 10-second countdown (time to get into frame) then
  auto-snaps; the button toggles to Cancel while counting.
- Face guide is now a VERTICAL oval (aspect-ratio 3/4) over a portrait stage —
  it was rendering horizontal. Faces are taller than wide.

Deployed live to entech (LXC 111) as 19.0.3.11.3; frontend bundle verified to
compile clean and contain the new rules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 18:14:19 -04:00
gsinghpal
55898dd1d4 feat(fusion_clock): NFC kiosk — enrollment, manager page, sounds, lock, profile photos
Kiosk work across this session (19.0.3.6.0 -> 19.0.3.10.0):
- Program-from-unknown-tap: amber prompt -> Manager PIN -> pick/create employee
  -> binds the captured UID (no re-tap). Reassign moves a card between employees.
- Manager page (gear, when unlocked): search employees + tag status; assign/re-tag,
  clear tag, archive employee, + new employee. Server-gated by the enroll password.
- Screen lock: kiosk starts locked (tap-only); Unlock -> Manager PIN, Lock button;
  PIN remembered for the session so the gear never re-prompts.
- Sounds: pleasant + loud sine chimes (rising in / descending out) + a low "denied"
  tone for wrong/unknown taps. Gated by fusion_clock.enable_sounds.
- Guided profile-photo capture for employees with no picture (clock-in or enroll):
  live camera + oval face guide -> capture -> preview -> save to hr.employee.
- PIN no longer re-renders per digit; centered result card; 12h time; clock-out shows
  "Worked Xh Ym this shift"; modern clock idle icon; faster animations/result timers;
  session keep-alive so the kiosk login never expires.
- New endpoints: create_employee, clear_tag, delete_employee (archive), verify_pin,
  save_profile_photo; enroll gains force-reassign.
- Docs: fusion_clock is now developed in Claude Code (dropped Cursor references).

Spec/plan under fusion_clock/docs/superpowers/. Deployed live on entech
(odoo-entech / LXC 111 on pve-worker5), v19.0.3.10.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 17:21:33 -04:00
gsinghpal
2a16f80d8d feat(fusion_clock): kiosk app + Kiosk Operator role, full-screen PWA, app-integrated permissions
- PWA manifest on the NFC kiosk page so it installs as a full-screen
  home-screen app (Chrome "Install" / Safari "Add to Home Screen").
- Dedicated "Kiosk Operator" permission + gated "Fusion Clock Kiosk"
  top-level app (act_url -> /fusion_clock/kiosk/nfc). Kiosk controllers
  accept Manager OR Kiosk Operator; all kiosk data ops already run sudo.
- Fix 403: read the company kiosk location via sudo on page-load and tap
  (Kiosk Operator has no fusion.clock.location ACL).
- Odoo 19 permissions UX: ir.module.category + res.groups.privilege so
  User/Team Lead/Manager and Kiosk Operator appear as application-access
  dropdowns on the user form (no developer mode). Short group display names.
- Docs: note res.groups.privilege as the Odoo 19 category_id replacement.

Deployed live to entech (odoo-entech / LXC 111 on pve-worker5). v19.0.3.6.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 14:51:14 -04:00
gsinghpal
005daade55 changes 2026-05-23 07:53:41 -04:00
gsinghpal
94249ba67d feat(fusion_clock): premium glass NFC kiosk + scope CSS to kiosk page
Visual rewrite of the NFC kiosk page:
- Animated mesh gradient background (drifts on a 28s loop)
- Glass-panel state cards with backdrop-filter blur
- Animated SVG NFC icon (concentric waves emanate from a chip)
- Company logo pulled from res.company.logo, displayed in header
- Dominant-hue extraction from logo sets --nfc-h CSS var; entire
  palette interpolates from that one HSL hue
- Success burst (green glow + scale), error shake, smooth state fades
- Reduced-motion fallback respects prefers-reduced-motion
- Glass numpad + employee picker in Enroll Mode

CRITICAL FIX: scoped all kiosk styles under :has(#nfc_kiosk_root) so
they no longer leak into other frontend pages. Previous version applied
html/body overflow:hidden + display:none on header/footer globally,
breaking website scrolling and chrome on every frontend page.
2026-05-14 08:22:47 -04:00
gsinghpal
03fd3d7c1c feat(fusion_clock): NFC kiosk employee search endpoint
Add /fusion_clock/kiosk/nfc/employee_search that delegates to the
existing kiosk_search method, avoiding logic duplication. Adds
TestEmployeeSearch HttpCase (33 tests total, all passing).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 01:11:28 -04:00
gsinghpal
f4c9ed3d24 feat(fusion_clock): NFC tap photo capture + photo-required gate
- Add _strip_data_url_prefix() helper to clean data-URL prefix from base64 photo payloads
- Gate nfc_tap on fusion_clock.nfc_photo_required ICP param (default True): rejects with error='photo_required' when photo absent
- Write x_fclk_check_in_photo / x_fclk_check_out_photo on clock-in/out attendance records
- Add TestTapPhotoHandling (3 tests): photo saved, required-rejects-missing, optional-succeeds-without

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:09:27 -04:00
gsinghpal
ef885c66dc feat(fusion_clock): NFC tap endpoint debounce + 6 error-case tests
Adds module-level 5s debounce (_is_debounced) with thread-safe dict +
GC. Inserts debounce guard in nfc_tap immediately after uid validation.
Adds TestTapEndpointErrors (6 tests): unknown_card, clock_disabled,
no_location_configured, kiosk_disabled, invalid_uid, debounce.
Adds setUp() to both tap test classes to clear _recent_taps between
tests, preventing cross-test debounce bleed. 29/29 pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 01:06:30 -04:00
gsinghpal
148aa5cba8 feat(fusion_clock): NFC tap endpoint (happy path)
Add /fusion_clock/kiosk/nfc/tap JSON-RPC endpoint that toggles attendance
via _attendance_action_change, writing x_fclk_clock_source='nfc_kiosk' and
location on clock-in, applying break deduction/penalty checks on clock-out.
Add 2 HttpCase tests (clock-in + clock-out with 6s debounce sleep).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:02:49 -04:00
gsinghpal
661c8ae227 feat(fusion_clock): NFC card enrollment endpoint
Adds /fusion_clock/kiosk/nfc/enroll (jsonrpc, auth=user) that validates
the enroll password, normalises the card UID, checks for duplicate
assignments, writes x_fclk_nfc_card_uid, and creates a card_enrollment
activity log entry. 4 new tests; 21 total passing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 00:58:25 -04:00
gsinghpal
a24a1ddf1a feat(fusion_clock): NFC card UID normalization helper
Add _normalize_uid static method to FusionClockNfcKiosk that strips
whitespace, uppercases, removes separators, validates hex-only content,
and reformats to canonical colon-separated pairs; returns None for
empty/invalid input. Covered by 7 new TransactionCase unit tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 00:56:02 -04:00
gsinghpal
f05cacec22 feat(fusion_clock): NFC kiosk page render route
Controller scaffold with GET /fusion_clock/kiosk/nfc, placeholder QWeb
template, and HttpCase tests (10 pass, 0 failures). Fixed Odoo 19
res.users create API: groups_id -> group_ids.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 00:53:03 -04:00
gsinghpal
595dccc17d changes 2026-03-17 13:32:08 -04:00
gsinghpal
e56974d46f update 2026-03-16 08:14:56 -04:00
gsinghpal
acd3fc455e changes 2026-03-09 15:21:22 -04:00
gsinghpal
a3e85a23ef changes 2026-03-01 14:42:49 -05:00
gsinghpal
b925766966 changes 2026-02-27 14:32:32 -05:00
gsinghpal
e8e554de95 changes 2026-02-23 00:32:20 -05:00
gsinghpal
5200d5baf0 Initial commit 2026-02-22 01:22:18 -05:00