From 921bdb6b73f0c8f9c55f3a97133e235f7c26dcc0 Mon Sep 17 00:00:00 2001 From: Konrad du Plessis Date: Fri, 12 Jun 2026 18:04:01 +0200 Subject: [PATCH] chore: money-handling + template hygiene (audit items 11-16) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - money filter: format via Decimal(str(...)) instead of float — money never passes through binary floating point on its way to the screen - preview_payslip / worker_lookup_ajax: accumulate totals in Decimal, convert to float only at the JsonResponse boundary, so previews are bit-identical to what _process_single_payment records - price_overtime: explicit .quantize(0.01) instead of letting the DB engine silently round the 3rd decimal place - stacked-chart wage rollup: Decimal(str(salary)) — on SQLite dev the value arrives as float and Decimal(float) keeps the binary noise - payroll_dashboard fmt(): en-ZA space-separated thousands like every other money helper on the page (was the one comma-format outlier) - base.html admin gate: '(auth and staff) or superuser' precedence trap replaced with 'staff or superuser' — exact same truth table (both flags False on AnonymousUser), matches server-side is_admin() - attendance_log.html: worker day-rates now ship via the house json_script pattern instead of |safe-rendering a Python dict repr into the script block Co-Authored-By: Claude Fable 5 --- core/templates/base.html | 12 +++++-- core/templates/core/attendance_log.html | 8 ++++- core/templates/core/payroll_dashboard.html | 7 +++- core/templatetags/format_tags.py | 9 +++-- core/views.py | 40 +++++++++++++++------- 5 files changed, 57 insertions(+), 19 deletions(-) diff --git a/core/templates/base.html b/core/templates/base.html index d5b6c1c..f92b245 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -404,7 +404,11 @@ {# === WORK LOG PAYROLL MODAL — click handler + safe DOM builder === #} {# Builds the modal body from JSON via createElement + textContent. #} -{% if user.is_authenticated and user.is_staff or user.is_superuser %} +{# staff-or-superuser matches the server-side is_admin() helper. The old #} +{# "is_authenticated and is_staff or is_superuser" parsed as "(auth AND #} +{# staff) OR superuser" — template `and` binds tighter than `or`. Both #} +{# flags are False on AnonymousUser, so this simpler form is exact. #} +{% if user.is_staff or user.is_superuser %}