feat: add MailService.cashboxExport and email template

This commit is contained in:
Bastian Wagner
2026-08-04 07:44:12 +02:00
parent 42e2bbc4ff
commit 196898b993
4 changed files with 65 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
{{#> layout}}
<p>Hallo,</p>
<p>im Anhang findest du den automatischen Kassenbuch-Export für <strong>{{teamName}}</strong> für den Zeitraum {{from}} bis {{to}}.</p>
<p>Diese E-Mail wurde automatisch von TeamWallet verschickt und benötigt keine weitere Aktion.</p>
{{/layout}}

View File

@@ -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');
});
});

View File

@@ -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 },
]);
});
});

View File

@@ -55,4 +55,24 @@ export class MailService {
},
});
}
async cashboxExport(
mailData: MailData<{ teamName: string; from: string; to: string }>,
attachment: Buffer,
filename: string,
): Promise<void> {
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 }],
});
}
}