fix: export nedává "prázdné" záznamy
CI / Generate TypeScript types (push) Successful in 11s
CI / Server unit tests (push) Successful in 27s
CI / Build server (push) Successful in 31s
CI / Build client (push) Successful in 43s
CI / Playwright E2E tests (push) Successful in 1m58s
CI / Build and push Docker image (push) Successful in 45s
CI / Notify (push) Successful in 1s

This commit is contained in:
Ondřej Anděl committed 2026-10-14 13:35:25 +02:00
1 parent 9fa00fa9c5
commit 8a7dbd94c8
3 files changed
+27 -5

No files matched your search

+16 -3
View File
@@ -167,18 +167,31 @@ describe('getUserExportRows', () => {
});
});
test('člen skupiny, který si nic neobjednal, nemá vyplněnou částku', async () => {
test('skupinu, kde si člen nic neobjednal a nemá poznámku, vynechá', async () => {
await saveLunch('2025-03-12', { OBJEDNAVAM: { [USER]: {} } });
await saveExtra('2025-03-12', [
{ id: 'g3', name: 'KFC', creatorLogin: USER, state: GroupState.ORDERED, members: { [USER]: {}, [OTHER]: { amount: 15000 } } },
{ id: 'g4', name: 'Namaste', creatorLogin: USER, state: GroupState.ORDERED, members: { [USER]: { amount: 22000, note: 'Chicken Tikka' } } },
]);
const rows = await getUserExportRows(USER, YEAR, MONTH);
// Volba "budu objednávat" se sloučí až se skupinou, kde si uživatel reálně objednal
expect(rows).toHaveLength(1);
expect(rows[0]).toMatchObject({ type: 'Budu objednávat', store: 'Namaste', food: 'Chicken Tikka', amount: 22000 });
});
test('člen skupiny, který si nic neobjednal, ale má poznámku, nemá vyplněnou částku', async () => {
await saveExtra('2025-03-12', [{
id: 'g3',
name: 'KFC',
creatorLogin: USER,
state: GroupState.ORDERED,
members: { [USER]: {}, [OTHER]: { amount: 15000 } },
members: { [USER]: { note: 'beru si jen pití od kolegy' }, [OTHER]: { amount: 15000 } },
}]);
const rows = await getUserExportRows(USER, YEAR, MONTH);
expect(rows).toHaveLength(1);
// Objednávající je uveden, ale částka zůstává prázdná — není co platit
// Záznam je uveden kvůli poznámce, ale částka zůstává prázdná — není co platit
expect(rows[0].orderedBy).toBe(USER);
expect(rows[0].amount).toBeUndefined();
expect(buildCsv(rows).split('\r\n')[1].split(';')[7]).toBe('');
+8 -2
View File
@@ -59,6 +59,11 @@ function isActiveMember(member: OrderGroupMember): boolean {
return (member.amount ?? 0) + (member.surchargeAmount ?? 0) > 0;
}
/** Vrátí true, pokud má členství ve skupině do přehledu co přinést (položku nebo poznámku). */
function isRelevantMember(member: OrderGroupMember | undefined): boolean {
return !!member && (isActiveMember(member) || !!member.note?.trim().length);
}
/**
* Vypočte částku člena skupiny po rozpočítání poplatků a slevy (v haléřích).
* Poplatky i pevná sleva se dělí pouze mezi členy, kteří si něco objednali.
@@ -177,8 +182,9 @@ export async function getUserExportRows(login: string, year: number, month: numb
break;
}
// Objednávkové skupiny, ve kterých byl uživatel členem
const groups = (extraData?.groups ?? []).filter(group => !!group.members[login]);
// Objednávkové skupiny, ve kterých si uživatel něco objednal nebo k nim má poznámku.
// Zakladatel skupiny, který si z ní nic nevzal, v ní figuruje jen formálně — řádek by byl prázdný.
const groups = (extraData?.groups ?? []).filter(group => isRelevantMember(group.members[login]));
const groupRows: UserExportRow[] = [];
let mergedGroup = false;
for (const group of groups) {