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>
This commit is contained in:
jtricerolph 2026-07-07 11:56:45 +00:00
parent 8b2dc4ad78
commit ed9cce1d76
4 changed files with 392 additions and 103 deletions

View file

@ -211,7 +211,7 @@ export async function reportRoutes(app) {
const { from, to } = req.query
if (!from || !to) return reply.status(400).send({ error: 'from and to required' })
const [denomResult, byDateResult] = await Promise.all([
const [denomResult, byDateResult, byDateDenomResult] = await Promise.all([
pool.query(
`SELECT d.denomination_value,
ROUND(SUM(d.total_amount) / NULLIF(d.denomination_value, 0)) AS total_quantity,
@ -230,11 +230,21 @@ export async function reportRoutes(app) {
ORDER BY session_date ASC`,
[from, to]
),
pool.query(
`SELECT d.denomination_value, c.session_date, SUM(d.total_amount) AS total_amount
FROM denominations d
JOIN cash_ups c ON d.cash_up_id = c.id
WHERE c.session_date >= $1 AND c.session_date <= $2 AND d.count_type = 'takings'
GROUP BY d.denomination_value, c.session_date
ORDER BY d.denomination_value DESC, c.session_date ASC`,
[from, to]
),
])
return {
denominations: denomResult.rows,
by_date: byDateResult.rows,
by_date_denom: byDateDenomResult.rows,
period: { from, to },
}
})