Commit graph

21 commits

Author SHA1 Message Date
af1560d58f Show refunds as refunds in transaction breakdown checklist
Refunds were rendered like payments (abs value, no marker). Backend now
flags items with is_refund from NewBook item_type (refunds_raised /
refunds_voided) and labels the type '-refund'; frontend shows them in
red with a leading minus.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 10:50:06 +00:00
2e9b4a2ca3 Let admins unfinalise a cash up from history
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.
2026-08-03 08:53:00 +00:00
e9cf648f8c Add daily audit summary cross-checks to multiday report
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>
2026-07-20 09:23:30 +00:00
dbef4b9f7a Fix sales breakdown GL matching — exact group ID instead of fuzzy names
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>
2026-07-20 08:23:54 +00:00
37453ddfda Return 200+null instead of 404 when no cash up found for date — eliminates browser console error 2026-07-07 20:56:34 +00:00
ed9cce1d76 Cashup: safe count adjust flow, cash summary cross-tab, table denomination view
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>
2026-07-07 11:56:45 +00:00
dcb450bd99 Cashup: configurable card machines — settings + inline Z-report layout
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>
2026-07-07 11:32:37 +00:00
2f9b876d0d Fix cashup bugs: PDQ totals, WET placeholder, print styles, cash summary
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>
2026-07-07 11:25:27 +00:00
8193b05acc Float management: save→view/print, history columns, uploads path fix
- 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>
2026-07-02 20:15:50 +00:00
6c805ce5a7 Settings: change tin notes/notes, label fix, placeholder GL columns
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>
2026-07-02 15:58:46 +00:00
618992206e Fix upload response: ins.rows[0] → ins[0] (rows already destructured)
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>
2026-07-02 15:47:50 +00:00
5623f64732 Float management: bagged coins, history nav fix, change order sheet, upload 500 fix
- 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>
2026-07-02 15:29:38 +00:00
fb66dcd6bf Save transaction checks, till float variance, fix image upload
- 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>
2026-07-02 14:46:52 +00:00
4754231f6f Split floats→safe_count, reports→cash_summary, add history cap
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>
2026-07-02 14:35:56 +00:00
be670f724d Enforce granular capabilities across cashup
Backend (server-side enforcement, not just UI):
- auth.js: read caps from JWT; hasCap() + requireCap() helpers;
  legacy-token fallback (full access minus settings) so existing
  sessions keep working until re-login
- finalise: submit final, delete draft, bulk-finalise, attachments
- reports: multiday report, cash summary, debtors
- floats: float management + safe count
- settings: settings mutations (was is_admin)
- count: draft save, newbook fetch

Frontend:
- can(user, cap) helper; User.caps from /verify
- Nav items, routes and actions (Submit Final, delete, bulk-finalise)
  gated on capabilities; non-finalisers see a draft-only hint

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 14:19:30 +00:00
43c332be9b Add photo upload for PDQ Z-reports and receipt evidence
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>
2026-07-02 09:22:22 +00:00
f62aa6f347 Fix gross sales zero bug; add Excel stats bar
- 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>
2026-07-02 00:14:40 +00:00
4ea5238e62 Fix cash summary quantity bug; add Safe Count as own nav item
- 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>
2026-07-01 21:36:19 +00:00
b623f806d8 Pin all fastify plugins to 4.x-compatible versions
cookie v9 + cors v9 = Fastify 4.x
multipart v8 = Fastify 4.x (downgrade from v9 which targets 5.x)
static v7 = Fastify 4.x (downgrade from v8 which targets 5.x)
fastify reverted to 4.x

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 20:19:33 +00:00
fc6d1baa79 Upgrade fastify to 5.x to match plugin version requirements
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>
2026-07-01 20:14:46 +00:00
63a5a72fa3 Wire Newbook credentials to settings service 2026-07-01 19:33:16 +00:00