From 8a7dbd94c806a249517bb4cdb9cd0a135f722c7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20And=C4=9Bl?= Date: Wed, 14 Oct 2026 13:35:25 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20export=20ned=C3=A1v=C3=A1=20"pr=C3=A1zdn?= =?UTF-8?q?=C3=A9"=20z=C3=A1znamy?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/changelogs/2026-10-14.json | 3 +++ server/src/tests/userExport.test.ts | 19 ++++++++++++++++--- server/src/userExport.ts | 10 ++++++++-- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 server/changelogs/2026-10-14.json diff --git a/server/changelogs/2026-10-14.json b/server/changelogs/2026-10-14.json new file mode 100644 index 0000000..c72f944 --- /dev/null +++ b/server/changelogs/2026-10-14.json @@ -0,0 +1,3 @@ +[ + "Export stravování už neobsahuje objednávky, ve kterých jste si nic neobjednali a nemáte k nim poznámku" +] diff --git a/server/src/tests/userExport.test.ts b/server/src/tests/userExport.test.ts index 008cb67..5d05488 100644 --- a/server/src/tests/userExport.test.ts +++ b/server/src/tests/userExport.test.ts @@ -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(''); diff --git a/server/src/userExport.ts b/server/src/userExport.ts index 40e199e..9001f4a 100644 --- a/server/src/userExport.ts +++ b/server/src/userExport.ts @@ -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) {