fix: počítání částek v haléřích z důvodu přesnosti
CI / Generate TypeScript types (push) Successful in 21s
CI / Build server (push) Successful in 25s
CI / Server unit tests (push) Successful in 55s
CI / Build client (push) Successful in 33s
CI / Playwright E2E tests (push) Successful in 1m20s
CI / Build and push Docker image (push) Successful in 35s
CI / Notify (push) Successful in 2s

This commit is contained in:
2026-05-07 13:05:04 +02:00
parent d91c8db49c
commit 8aef00ab05
18 changed files with 370 additions and 380 deletions
+12 -19
View File
@@ -33,9 +33,7 @@ function parseAmount(s: string): number | null {
if (!s || s.trim().length === 0) return null;
const n = parseFloat(s);
if (isNaN(n) || n < 0) return null;
const parts = s.split('.');
if (parts.length === 2 && parts[1].length > 2) return null;
return Math.round(n * 100) / 100;
return Math.round(n * 100);
}
export default function PayForAllModal({ isOpen, onClose, locationName, locationChoices, menu, payerLogin, bankAccount, bankAccountHolder }: Readonly<Props>) {
@@ -55,11 +53,11 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
let baseAmountParseFailed = false;
if (menu) {
for (const idx of selectedFoods) {
const price = parsePriceCzk(menu.food?.[idx]?.price);
if (price === null) {
const priceKc = parsePriceCzk(menu.food?.[idx]?.price);
if (priceKc === null) {
baseAmountParseFailed = true;
} else {
baseAmount += price;
baseAmount += Math.round(priceKc * 100);
}
}
}
@@ -84,19 +82,19 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
if (includedDiners.length === 0) return 0;
const tip = parseAmount(tipTotal);
if (tip === null || tip === 0) return 0;
const totalPeople = includedDiners.length + 1; // +1 for payer
return Math.round((tip / totalPeople) * 100) / 100;
const totalPeople = includedDiners.length + 1;
return Math.round(tip / totalPeople);
})();
const payerTipShare = (() => {
const tip = parseAmount(tipTotal);
if (!tip) return 0;
return Math.round((tip - tipPerPerson * includedDiners.length) * 100) / 100;
return tip - tipPerPerson * includedDiners.length;
})();
const getTotal = (d: DinerEntry): number => {
const surcharge = parseAmount(d.surchargeAmount) ?? 0;
const tip = d.login === payerLogin ? payerTipShare : tipPerPerson;
return Math.round((d.baseAmount + surcharge + tip) * 100) / 100;
return d.baseAmount + surcharge + tip;
};
const handleInclude = useCallback((login: string, checked: boolean) => {
@@ -122,11 +120,6 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
setError(`Celková částka pro ${d.login} musí být kladná`);
return;
}
const amountStr = total.toString();
if (amountStr.includes('.') && amountStr.split('.')[1].length > 2) {
setError(`Částka pro ${d.login} má více než 2 desetinná místa`);
return;
}
const foods = d.selectedFoods.map(i => menu?.food?.[i]?.name).filter(Boolean).join(', ');
const purposeBase = `Oběd ${locationName}${foods ? `${foods}` : ''}`;
recipients.push({
@@ -226,7 +219,7 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
<td>
<small>
{foodNames || <span className="text-muted">—</span>}
{hasMenu && d.baseAmount > 0 && <span className="text-muted"> ({d.baseAmount} Kč)</span>}
{hasMenu && d.baseAmount > 0 && <span className="text-muted"> ({d.baseAmount / 100} Kč)</span>}
{d.baseAmountParseFailed && <span className="text-warning"> ⚠</span>}
</small>
</td>
@@ -254,10 +247,10 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
</div>
</td>
<td className="text-end">
{(() => { const s = isPayer ? payerTipShare : tipPerPerson; return s > 0 ? `${s} Kč` : '—'; })()}
{(() => { const s = isPayer ? payerTipShare : tipPerPerson; return s > 0 ? `${s / 100} Kč` : '—'; })()}
</td>
<td className="text-end fw-bold">
{`${total} Kč`}
{`${total / 100} Kč`}
</td>
</tr>
);
@@ -278,7 +271,7 @@ export default function PayForAllModal({ isOpen, onClose, locationName, location
/>
<small className="text-muted">
{includedDiners.length > 0 && tipPerPerson > 0
? `(${tipPerPerson} Kč / osoba)`
? `(${tipPerPerson / 100} Kč / osoba)`
: ''}
</small>
</div>