Adds POST /api/cashup/:id/unfinalise (admin-only) to revert a
finalised cash up back to draft so it can be corrected, plus an
Unfinalise button in the history table for admin users.
Fetch reports_daily_audit_summary per day. Use cash_income total as the
reconciliation audit column (independent payment cross-check vs transaction
flow). Add a second Audit (DAS) column on the sales breakdown using
accrual_income totals alongside the earned revenue Audit (ER) column —
both highlight in amber if they diverge from the configured columns gross.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Switch sales breakdown column matching from fuzzy name matching to exact
gl_group_id comparison. Add gl_account_groups_list endpoint for settings
sync so columns store real Newbook group IDs. Removes the name-based
fallback that was causing sundries VAT to bleed into sundries no-VAT.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Safe Count (new flow):
- Replaces simple re-use of FloatCountForm with a dedicated 3-column table:
Current in Safe | Adjustment | New Total
- Loads the most recent safe_cash float count on mount to pre-populate Current
- Adjustment inputs accept positive (deposit) or negative (uplift/exchange) values
- New Total = Current + Adjustment per denomination; minimum clamped to 0
- Saves a new safe_cash float_count record via existing /floats/save endpoint
Cash Summary (redesign):
- Backend adds a per-date denomination query (by_date_denom) to the
cash-summary endpoint in addition to the existing aggregate query
- Frontend rewritten as a cross-tab: denominations down rows, dates across
columns, row totals on the right, per-day cash totals in the footer
- Status badges (draft/final) shown per column in a header row
- "+ Add to Safe" button navigates to /safe passing the period's denomination
totals as React Router state, pre-filling the adjustment column
Float Management:
- Denomination entry form switched from CSS grid divs to a proper <table>
matching the style of the print view (header row, qty input right-aligned,
amount column, total in tfoot)
- DetailRecord type and FloatRecordPrint component exported so SafeCount can
reuse the existing print/view component for safe cash records
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Settings: add Card Machines section to configure number of PDQ terminals
and their names (1–6 machines, defaults to Front Desk + Restaurant / Bar).
Names are stored under the 'card_machines' settings key.
DailyCashUp: machine names now load from settings instead of hardcoded
const. Card Machines section changed from a 2-column grid to a vertical
list; each machine row shows the amount inputs on the left and its PDQ
Z-report photo uploader on the right. Separate PDQ Z-Reports card removed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Issue #1: Parse card machine amounts as floats in applyLoaded — pg returns
DECIMAL as strings which caused JS string concatenation in totalPdq and
reconciliation banked amounts. After draft save, reload cashUp to get the
persisted ID so PDQ Z-report uploads work on first save.
Issue #2: Guard empty gl_code in sales breakdown name-matching — an empty
column code caused gName.includes('') to always be true, making placeholder
columns (like WET 5%) match the first available GL group (dry dept).
Issue #3: Move Cash Summary above Safe Count in sidebar nav. Extend
cash-summary endpoint with per-day breakdown. Rewrite CashSummary.tsx
with a daily cash takings table above the denomination summary.
Issue #4: Add @media print CSS — hide sidebar nav, force colour printing,
style disabled inputs as plain text, and keep tables/cards intact on paper.
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>
INSERT RETURNING * was succeeding but response threw TypeError trying to
access .rows[0] on the already-unwrapped rows array. File was saved, DB
record created, but 500 returned. Frontend now gets the record immediately
without needing a refresh.
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>
- 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>
- 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>
- 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>
All @fastify/* plugins (cookie, cors, multipart, static) were already
on 5.x-targeted versions; fastify itself was still on 4.29.1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>