Cashup: fix change tin count — use bag values not coin face values

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>
This commit is contained in:
jtricerolph 2026-07-02 20:25:27 +00:00
parent 8193b05acc
commit 4b0b73c520

View file

@ -237,7 +237,10 @@ export function FloatCountForm({ type }: { type: CountType }) {
}).catch(() => {}) }).catch(() => {})
}, [type]) }, [type])
const totalCounted = denoms.reduce((s, d) => s + d.value * (denomQtys[d.value] ?? 0), 0) function unitVal(d: { value: number }) {
return type === 'change_tin' ? (BAG_VALUES[d.value] ?? d.value) : d.value
}
const totalCounted = denoms.reduce((s, d) => s + unitVal(d) * (denomQtys[d.value] ?? 0), 0)
const totalReceipts = receipts.reduce((s, r) => s + (parseFloat(r.amount) || 0), 0) const totalReceipts = receipts.reduce((s, r) => s + (parseFloat(r.amount) || 0), 0)
const targetAmount = type === 'petty_cash' ? pettyTarget : type === 'change_tin' const targetAmount = type === 'petty_cash' ? pettyTarget : type === 'change_tin'
? Object.entries(changeTinTargets).reduce((s, [, v]) => s + (v || 0), 0) ? Object.entries(changeTinTargets).reduce((s, [, v]) => s + (v || 0), 0)
@ -252,7 +255,7 @@ export function FloatCountForm({ type }: { type: CountType }) {
try { try {
const denominations = denoms.filter(d => (denomQtys[d.value] ?? 0) > 0).map(d => ({ const denominations = denoms.filter(d => (denomQtys[d.value] ?? 0) > 0).map(d => ({
denomination: d.value, quantity: denomQtys[d.value] ?? 0, bag_quantity: 0, denomination: d.value, quantity: denomQtys[d.value] ?? 0, bag_quantity: 0,
total: d.value * (denomQtys[d.value] ?? 0), total: unitVal(d) * (denomQtys[d.value] ?? 0),
})) }))
const result = await api.post<{ count_id: number }>('/floats/save', { const result = await api.post<{ count_id: number }>('/floats/save', {
count_type: type, count_type: type,
@ -308,10 +311,15 @@ export function FloatCountForm({ type }: { type: CountType }) {
<h2 style={{ fontSize: '0.875rem', fontWeight: 700, marginBottom: '0.75rem', color: 'var(--text-mid)' }}>DENOMINATIONS</h2> <h2 style={{ fontSize: '0.875rem', fontWeight: 700, marginBottom: '0.75rem', color: 'var(--text-mid)' }}>DENOMINATIONS</h2>
{denoms.map(d => { {denoms.map(d => {
const qty = denomQtys[d.value] ?? 0 const qty = denomQtys[d.value] ?? 0
const rowTotal = d.value * qty const uv = unitVal(d)
const rowTotal = uv * qty
const isBag = type === 'change_tin' && BAG_VALUES[d.value] !== undefined
return ( return (
<div key={d.value} style={{ display: 'grid', gridTemplateColumns: '64px 1fr 90px', gap: '0.4rem 0.75rem', alignItems: 'center', marginBottom: '0.35rem' }}> <div key={d.value} style={{ display: 'grid', gridTemplateColumns: '80px 1fr 90px', gap: '0.4rem 0.75rem', alignItems: 'center', marginBottom: '0.35rem' }}>
<span style={{ fontWeight: 600, fontSize: '0.875rem' }}>{d.label}</span> <div>
<span style={{ fontWeight: 600, fontSize: '0.875rem' }}>{d.label}</span>
{isBag && <div style={{ fontSize: '0.65rem', color: 'var(--text-mid)' }}>{fmtGBP(uv)}/bag</div>}
</div>
<input type="number" min="0" step="1" value={qty || ''} <input type="number" min="0" step="1" value={qty || ''}
onChange={e => setDenomQtys(prev => ({ ...prev, [d.value]: parseInt(e.target.value) || 0 }))} onChange={e => setDenomQtys(prev => ({ ...prev, [d.value]: parseInt(e.target.value) || 0 }))}
placeholder="0" style={inpSt} /> placeholder="0" style={inpSt} />
@ -380,7 +388,7 @@ export function FloatCountForm({ type }: { type: CountType }) {
const target = parseFloat(String(changeTinTargets[d.value.toFixed(2)] ?? 0)) const target = parseFloat(String(changeTinTargets[d.value.toFixed(2)] ?? 0))
if (target <= 0) return null if (target <= 0) return null
const targetUnits = unitVal > 0 ? Math.round(target / unitVal) : 0 const targetUnits = unitVal > 0 ? Math.round(target / unitVal) : 0
const counted = d.value * (denomQtys[d.value] ?? 0) const counted = unitVal * (denomQtys[d.value] ?? 0)
const needed = target - counted const needed = target - counted
const orderUnits = needed > 0.005 ? Math.ceil(needed / unitVal) : 0 const orderUnits = needed > 0.005 ? Math.ceil(needed / unitVal) : 0
return { d, target, targetUnits, counted, orderUnits, unitLabel } return { d, target, targetUnits, counted, orderUnits, unitLabel }