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>
This commit is contained in:
gsinghpal
2026-05-30 18:14:19 -04:00
parent 09cea73e50
commit e26a7cd9e8
4 changed files with 73 additions and 11 deletions

View File

@@ -307,6 +307,11 @@ class FusionClockNfcKiosk(http.Controller):
api = FusionClockAPI()
is_checked_in = employee.attendance_state == 'checked_in'
# Cache-buster: /web/image is browser-cached, so without a unique token a
# freshly-saved profile photo never shows. write_date bumps on every
# write (incl. saving image_1920), so it refreshes exactly when needed.
avatar_unique = employee.write_date.strftime('%Y%m%d%H%M%S') if employee.write_date else ''
avatar_url = f'/web/image/hr.employee/{employee.id}/avatar_128?unique={avatar_unique}'
now = fields.Datetime.now()
today = get_local_today(request.env, employee)
day_plan = employee._get_fclk_day_plan(today)
@@ -351,7 +356,7 @@ class FusionClockNfcKiosk(http.Controller):
'action': 'clock_in',
'employee_id': employee.id,
'employee_name': employee.name,
'employee_avatar_url': f'/web/image/hr.employee/{employee.id}/avatar_128',
'employee_avatar_url': avatar_url,
'message': f'{employee.name} clocked in at {location.name}',
'net_hours_today': 0.0,
'needs_photo': not employee.image_1920,
@@ -377,7 +382,7 @@ class FusionClockNfcKiosk(http.Controller):
'action': 'clock_out',
'employee_id': employee.id,
'employee_name': employee.name,
'employee_avatar_url': f'/web/image/hr.employee/{employee.id}/avatar_128',
'employee_avatar_url': avatar_url,
'message': f'{employee.name} clocked out',
'net_hours_today': round(attendance.x_fclk_net_hours or 0, 2),
'needs_photo': not employee.image_1920,