Qty entered for coins = number of bags, so total = BAG_VALUES[denom] × qty
not denom × qty. Fixes totalCounted, row totals, change order counted column,
and save payload. Also shows £X/bag hint under coin denomination labels.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change tin count: remove bags/loose split — single qty per denomination
- After save: show saved record inline with Print button (clean new-window
printout with denomination table, receipts, totals/variance, signature lines)
- Change tin print: bank exchange order table (surplus=to bank, shortfall=in exchange)
- Petty cash history: Cash | Receipts | Total | Variance columns
- Fix uploads path: /app/src/../../uploads resolved to /uploads (container root,
outside Docker volume). Changed to /app/src/../uploads = /app/uploads so files
persist across rebuilds on the named volume.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Change tin targets:
- Add £5/£10/£20/£50 note rows (qty in individual notes, not bags)
- Fix label: (= £40.00 @ £20.00 each) instead of (= £40.00 each)
- Add per-denomination Notes text field (stored as change_tin_notes setting)
- Table layout replaces 2-col grid for all 10 denominations
Float count form:
- Notes denominations show a single Qty input; coins keep Bags + Loose
- Change order correctly shows "notes" vs "bags" needed per denomination
Sales breakdown columns:
- Add placeholder column button (gl_code='', labelled PLACEHOLDER)
- Add delete (×) button on every column row
- Fix key={i} to support multiple placeholders with same empty gl_code
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix history nav: type underscore → hyphen for route match
- Change tin: Bags + Loose inputs per denomination with UK bag values
- Change tin target: per-denomination bag count in Settings
- Change order sheet: inline table showing bags to order vs counted
- db: bag_quantity column on float_denominations
- api.ts: put text fields before file in FormData so busboy doesn't drain file stream early
- db.js: additive migration for uploaded_by column on cash_count_attachments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Auto-save: every 60s while editing, silently saves draft if form has data.
Status "Auto-saved at HH:MM" appears next to the Save Draft button briefly.
- Float Count moved above Cash Takings and defaults to open so staff count
the float first before counting takings.
- Reconciliation table gains a fifth "Card Total" column: PDQ Visa/MC and
PDQ Amex rows share a rowspan=2 cell showing the combined PDQ variance.
If the per-category rows are red but the combined is green it means only
the Visa/Amex split was mis-allocated, not an actual cash discrepancy
(labelled "split only"). Gateway rows similarly grouped (always auto 0).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Persist transaction breakdown checked state in cash_ups.checked_transactions
(JSONB column); saved on each draft/final save and restored on page load.
Re-fetching Newbook no longer resets the checked items.
- Add till_float_target setting; Float Count card shows target and variance
so staff can see at a glance whether the till balances.
- Compress images client-side (max 1600px, 85% JPEG) before upload to avoid
504 gateway timeouts from NPM when uploading large mobile photos.
- File input accepts image/* only (was image/*+PDF which confuses mobile pickers).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds three new granular capabilities:
- history: gates /history page and GET /api/cashup/history
- cash_summary: gates /summary page and GET /api/reports/cash-summary
- safe_count: gates /safe page and safe_cash float routes
Updates legacy-token fallback to include all seven non-settings caps.
Route guards and nav items updated to use the split caps.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DB:
- Add attachment_type ('pdq_z_report' | 'receipt_error' | 'other') and
label columns to cash_count_attachments; migrate existing rows via
ALTER TABLE IF NOT EXISTS (no data loss)
Backend:
- Upload route now reads attachment_type and label from multipart form
fields alongside the file, stores them in the DB
Frontend:
- PhotoUploader component: thumbnail grid, upload button (images + PDF),
spinner during upload, ✕ delete button on each photo, click opens in
new tab
- DailyCashUp: PDQ Z-Reports card (one section per machine — Front Desk /
Restaurant Bar) appears after Card Machines when a cash up exists
- DailyCashUp: Receipt Evidence card at bottom for any discrepancy photos;
stays editable even on final cash ups so receipts can be added later
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Variance = banked total - reported total across all payment categories.
Green badge = balanced, red = short (▼), amber = over (▲).
Days with no cash up show no variance (nothing was counted).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch from onClick to onMouseDown + e.preventDefault() so the
browser never starts its own text-selection on click or drag
- Add document-level mousemove/mouseup listeners for drag-to-select:
hold mouse button and sweep across cells to highlight a range
- Shift+click still extends the rectangle from the anchor cell
- userSelect: none on tables prevents any residual text highlighting
- Stats bar (Count/Sum/Avg) now appears after mouseup so it reads the
final selection, not mid-drag state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Backend: sales_breakdown column matching was always failing because
Newbook returns numeric gl_group_id but column settings use string codes
like 'ACCOMMODATION'. Added normalised name-fuzzy fallback matching and
a daily_gross_sales field that sums ALL earned revenue for the date,
bypassing column config entirely.
- Frontend: dayGrossSales() now uses daily_gross_sales from backend first
- Add floating Excel-style status bar (bottom-right): when cells are
selected it shows Count, Sum, and Average of the selected values;
disappears when ✕ clicked or selection cleared
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Reconciliation now has two side-by-side tables (BANKED left, REPORTED right)
with dates on rows and payment categories on columns — matching original orientation
- BANKED table: green bg for manual cells (cash/PDQ), orange for auto (gateway/BACS),
red/amber bg + ▼/▲ indicator when variance vs reported
- REPORTED table: orange background, Audit column showing daily gross sales
- Gross Sales sub-table below reconciliation
- Sales Breakdown: dates now on rows, GL categories on columns (was transposed)
with Total Net / VAT / Gross Total / Audit columns
- Occupancy: dates on rows, metric columns, hover tooltips with category breakdown
- Copy/Paste Format section: spreadsheet-ready 2-row-per-date tables
- Excel-like cell selection: click to select, Shift+click for range,
Ctrl+C copies selected cells as TSV to clipboard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Occupancy table now calculates from raw Newbook data:
- Rooms occupied (from per-category occupancy API)
- Occ % (rooms occupied / total rooms from sites_data)
- Guests (adults + children + infants from bookings_data)
- Net accommodation revenue (from earned_revenue, ACC GL group)
- Avg net per room, REVPAR
- GGR (average guest rate from tariffs_quoted)
- Avg lead time (arriving bookings only)
Sales breakdown now shows Net, VAT, Gross as separate total columns.
Debtors/Creditors adds Period Close row.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- History: slice session_date to YYYY-MM-DD before Date parse (postgres
returns date columns as ISO timestamps in JSON)
- History: fix Edit/View navigate link passing full ISO string as date param
- Weekly report: add daily status row, reconciliation variance (banked vs
Newbook reported), sales with gross+net, debtors/creditors lazy-loaded
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Newbook payments now fetched automatically when a date loads (in
parallel with the cash up fetch), not just on button click
- Refresh button still available for manual re-fetch
- Transaction breakdown section below reconciliation table: three
collapsible groups (Reception Manual, Reception Gateway, Restaurant/Bar)
each showing individual transactions with click-to-tick checkboxes
for tracking down discrepancies — local state, clears on refresh
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PostgreSQL NUMERIC columns return as strings in node-postgres. denomTotal
was doing 0 + "40.00" + "30.00" → "040.0030.00", and parseFloat in
fmtGBP read only the first portion, giving a wrong total (£40.00 instead
of £78.80 etc).
Fix: coerce total_amount and value_entered to numbers in applyLoaded;
make denomTotal's reducer defensively use Number() so strings can't
silently break the sum again.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cash summary: derive total_quantity from total_amount/denomination_value
so value_entered rows are counted (previously SUM(quantity) returned
NULL for those rows)
- Safe Count: moved safe_cash out of Float Management tabs into its own
/safe/* route with a dedicated sidebar entry (Vault icon)
- FloatManagement now only shows Petty Cash and Change Tin tabs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- On mount/date change: auto-fetch existing cash up
- Draft found → auto-load into editing state
- Finalised → auto-load into locked state (read-only + banner)
- Not found → show 'Start Cash Up' prompt
- Removed manual 'Load Existing' / 'New' buttons
- Submitting final transitions immediately to locked state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tab now moves down the Qty column first (£50→£20→...→1p), then down
the Value Override column, for both takings and float grids.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AuthGate was calling /cashup/api/auth/verify and /cashup/api/auth/login,
which hit the cashup backend (404). Should call /api/auth/* which NPM
routes to the central auth service, matching all other apps.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add vite-env.d.ts for import.meta.env type support
- Remove unused imports: ChevronRight, useCallback (x2), today
- Silence unused attachments state read (keep setter for future use)
- Fix FloatManagement changeTinTargets reducer: drop unused k, fix v type
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>