diff --git a/myteamwallet_backend/src/mail/mail-templates/cashbox-export.hbs b/myteamwallet_backend/src/mail/mail-templates/cashbox-export.hbs new file mode 100644 index 0000000..4561292 --- /dev/null +++ b/myteamwallet_backend/src/mail/mail-templates/cashbox-export.hbs @@ -0,0 +1,5 @@ +{{#> layout}} +

Hallo,

+

im Anhang findest du den automatischen Kassenbuch-Export für {{teamName}} für den Zeitraum {{from}} bis {{to}}.

+

Diese E-Mail wurde automatisch von TeamWallet verschickt und benötigt keine weitere Aktion.

+{{/layout}} diff --git a/myteamwallet_backend/src/mail/mail-templates/mail-templates.spec.ts b/myteamwallet_backend/src/mail/mail-templates/mail-templates.spec.ts index 0caa9e1..034c29c 100644 --- a/myteamwallet_backend/src/mail/mail-templates/mail-templates.spec.ts +++ b/myteamwallet_backend/src/mail/mail-templates/mail-templates.spec.ts @@ -60,4 +60,20 @@ describe('mail templates rendering', () => { expect(html).toContain('Hallo,'); expect(html).not.toContain('Hallo Max,'); }); + + it('renders cashbox-export.hbs with team name and period', () => { + const source = fs.readFileSync(path.join(templatesDir, 'cashbox-export.hbs'), 'utf-8'); + const html = Handlebars.compile(source, { strict: true })({ + title: 'Kassenbuch-Export Team A', + year: 2026, + teamName: 'Team A', + from: '2026-08-01', + to: '2026-08-31', + }); + + expect(html).toContain('TeamWallet'); + expect(html).toContain('Team A'); + expect(html).toContain('2026-08-01'); + expect(html).toContain('2026-08-31'); + }); }); diff --git a/myteamwallet_backend/src/mail/mail.service.spec.ts b/myteamwallet_backend/src/mail/mail.service.spec.ts index 9e33ddc..15657ae 100644 --- a/myteamwallet_backend/src/mail/mail.service.spec.ts +++ b/myteamwallet_backend/src/mail/mail.service.spec.ts @@ -58,4 +58,28 @@ describe('MailService', () => { const call = sendMail.mock.calls[0][0]; expect(call.context.firstName).toBeUndefined(); }); + + it('sends the cashbox export mail with the PDF attachment', async () => { + const attachment = Buffer.from('%PDF-1.4 fake'); + + await service.cashboxExport( + { + to: 'vorstand@example.com, kassier@example.com', + data: { teamName: 'Team A', from: '2026-08-01', to: '2026-08-31' }, + }, + attachment, + 'kassenbuch_team-a_2026-08-01_2026-08-31.pdf', + ); + + expect(sendMail).toHaveBeenCalledTimes(1); + const call = sendMail.mock.calls[0][0]; + expect(call.to).toBe('vorstand@example.com, kassier@example.com'); + expect(call.template).toBe('cashbox-export'); + expect(call.context.teamName).toBe('Team A'); + expect(call.context.from).toBe('2026-08-01'); + expect(call.context.to).toBe('2026-08-31'); + expect(call.attachments).toEqual([ + { filename: 'kassenbuch_team-a_2026-08-01_2026-08-31.pdf', content: attachment }, + ]); + }); }); diff --git a/myteamwallet_backend/src/mail/mail.service.ts b/myteamwallet_backend/src/mail/mail.service.ts index a825da8..8607f3e 100644 --- a/myteamwallet_backend/src/mail/mail.service.ts +++ b/myteamwallet_backend/src/mail/mail.service.ts @@ -55,4 +55,24 @@ export class MailService { }, }); } + + async cashboxExport( + mailData: MailData<{ teamName: string; from: string; to: string }>, + attachment: Buffer, + filename: string, + ): Promise { + await this.mailerService.sendMail({ + to: mailData.to, + subject: `Kassenbuch-Export ${mailData.data.teamName}`, + template: 'cashbox-export', + context: { + title: `Kassenbuch-Export ${mailData.data.teamName}`, + year: new Date().getFullYear(), + teamName: mailData.data.teamName, + from: mailData.data.from, + to: mailData.data.to, + }, + attachments: [{ filename, content: attachment }], + }); + } }