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>
This commit is contained in:
jtricerolph 2026-07-07 11:25:27 +00:00
parent c2ab162870
commit 2f9b876d0d
5 changed files with 156 additions and 61 deletions

View file

@ -148,7 +148,9 @@ export async function reportRoutes(app) {
const gid = String(r.gl_group_id ?? '')
if (gid === col.gl_code || gid.toUpperCase() === col.gl_code.toUpperCase()) return true
const gName = glGroupById[gid] ?? ''
return gName.includes(code) || code.includes(gName)
// Only fuzzy-match when the column has a non-empty gl_code — prevents
// placeholder columns (empty code) from matching any GL group via gName.includes('')
return code.length > 0 && (gName.includes(code) || code.includes(gName))
})
const net = parseFloat(item?.earned_revenue_ex || 0)
const vat = parseFloat(item?.earned_revenue_tax || 0)
@ -209,20 +211,30 @@ export async function reportRoutes(app) {
const { from, to } = req.query
if (!from || !to) return reply.status(400).send({ error: 'from and to required' })
const { rows } = await pool.query(
`SELECT d.denomination_value,
ROUND(SUM(d.total_amount) / NULLIF(d.denomination_value, 0)) AS total_quantity,
SUM(d.total_amount) AS total_value
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
ORDER BY d.denomination_value DESC`,
[from, to]
)
const [denomResult, byDateResult] = await Promise.all([
pool.query(
`SELECT d.denomination_value,
ROUND(SUM(d.total_amount) / NULLIF(d.denomination_value, 0)) AS total_quantity,
SUM(d.total_amount) AS total_value
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
ORDER BY d.denomination_value DESC`,
[from, to]
),
pool.query(
`SELECT session_date, status, total_cash_counted, submitted_by
FROM cash_ups
WHERE session_date >= $1 AND session_date <= $2
ORDER BY session_date ASC`,
[from, to]
),
])
return {
denominations: rows,
denominations: denomResult.rows,
by_date: byDateResult.rows,
period: { from, to },
}
})