@stamhoofd/backend 2.120.5 → 2.121.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/src/audit-logs/RegistrationInvitationLogger.ts +46 -0
- package/src/audit-logs/init.ts +2 -0
- package/src/crons/index.ts +2 -0
- package/src/crons/invoices.ts +166 -0
- package/src/crons/mollie-chargebacks.ts +87 -0
- package/src/crons.ts +47 -10
- package/src/email-recipient-loaders/payments.ts +84 -41
- package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +51 -0
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +22 -3
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +4 -0
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +45 -0
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +495 -0
- package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +216 -0
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +405 -0
- package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +168 -0
- package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -0
- package/src/endpoints/{global → organization/dashboard}/billing/DeactivatePackageEndpoint.ts +3 -4
- package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +62 -0
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +56 -0
- package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +42 -19
- package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +64 -0
- package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +11 -3
- package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +308 -0
- package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +94 -0
- package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +7 -0
- package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +5 -4
- package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +7 -2
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +17 -8
- package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +3 -3
- package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +127 -0
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +13 -4
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +7 -1
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +1 -1
- package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +13 -11
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +14 -19
- package/src/helpers/AdminPermissionChecker.ts +11 -3
- package/src/helpers/AuthenticatedStructures.ts +94 -6
- package/src/helpers/FinancialSupportHelper.ts +21 -0
- package/src/helpers/RecordAnswerHelper.test.ts +746 -0
- package/src/helpers/RecordAnswerHelper.ts +116 -0
- package/src/helpers/StripeHelper.ts +2 -3
- package/src/helpers/ViesHelper.ts +7 -3
- package/src/seeds/1750090030-records-configuration.ts +68 -3
- package/src/seeds/1752848561-groups-registration-periods.ts +26 -2
- package/src/seeds/1779121239-default-invoice-email-template.sql +3 -0
- package/src/services/BalanceItemService.ts +12 -16
- package/src/services/InvoiceService.ts +372 -72
- package/src/services/MollieService.ts +537 -0
- package/src/services/PaymentMandateService.ts +214 -0
- package/src/services/PaymentService.ts +578 -222
- package/src/services/PlatformMembershipService.ts +1 -1
- package/src/services/RegistrationService.ts +66 -5
- package/src/services/STPackageService.ts +0 -7
- package/src/services/data/invoice.hbs.html +686 -0
- package/src/sql-filters/groups.ts +11 -1
- package/src/sql-filters/payments.ts +5 -0
- package/src/sql-filters/registration-invitations.ts +90 -0
- package/src/sql-sorters/registration-invitations.ts +36 -0
- package/vitest.config.js +1 -0
- package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +0 -216
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="nl">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<title>{{#if invoice.number}}{{#if isCreditNote}}{{$t "Creditnota"}}{{else}}{{$t "Factuur"}}{{/if}}
|
|
7
|
+
{{invoice.number}}{{else}}{{#if isCreditNote}}{{$t "Pro-forma creditnota"}}{{else}}{{$t "Pro-forma
|
|
8
|
+
factuur"}}{{/if}}{{/if}}</title>
|
|
9
|
+
<style>
|
|
10
|
+
@font-face {
|
|
11
|
+
font-family: 'Metropolis';
|
|
12
|
+
font-weight: 600;
|
|
13
|
+
font-style: normal;
|
|
14
|
+
font-display: swap;
|
|
15
|
+
src: url('https://www.stamhoofd.be/assets/fonts/clarity-city/WOFF2/ClarityCity-Medium.woff2') format('woff2');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@font-face {
|
|
19
|
+
font-family: 'Metropolis';
|
|
20
|
+
font-weight: 500;
|
|
21
|
+
font-style: normal;
|
|
22
|
+
font-display: swap;
|
|
23
|
+
src: url('https://www.stamhoofd.be/assets/fonts/clarity-city/WOFF2/ClarityCity-SemiBold.woff2') format('woff2');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
:root {
|
|
27
|
+
--color-primary: {{colors.primary}};
|
|
28
|
+
--color-dark: #000716;
|
|
29
|
+
--color-gray-dark: #5e5e5e;
|
|
30
|
+
--color-gray: #868686;
|
|
31
|
+
--color-line: rgba(0, 7, 22, 0.1);
|
|
32
|
+
--page-margin: 16mm;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@page {
|
|
36
|
+
size: A4;
|
|
37
|
+
margin: 16mm 0;
|
|
38
|
+
|
|
39
|
+
@bottom-left {
|
|
40
|
+
content: "{{invoice.id}}";
|
|
41
|
+
font-family: 'Metropolis', system-ui, sans-serif;
|
|
42
|
+
font-weight: 500;
|
|
43
|
+
font-size: 8.5pt;
|
|
44
|
+
color: #868686;
|
|
45
|
+
text-align: left;
|
|
46
|
+
z-index: 100;
|
|
47
|
+
margin-bottom: 32mm;
|
|
48
|
+
margin-left: 16mm;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
@bottom-right {
|
|
52
|
+
content: "{{$t " Pagina"}} " counter(page);
|
|
53
|
+
font-family: 'Metropolis', system-ui, sans-serif;
|
|
54
|
+
font-weight: 500;
|
|
55
|
+
font-size: 8.5pt;
|
|
56
|
+
color: #868686;
|
|
57
|
+
text-align: right;
|
|
58
|
+
z-index: 100;
|
|
59
|
+
margin-bottom: 32mm;
|
|
60
|
+
margin-right: 16mm;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
*,
|
|
65
|
+
*::before,
|
|
66
|
+
*::after {
|
|
67
|
+
box-sizing: border-box;
|
|
68
|
+
-webkit-print-color-adjust: exact;
|
|
69
|
+
print-color-adjust: exact;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
html {
|
|
73
|
+
margin: 0;
|
|
74
|
+
padding: 0;
|
|
75
|
+
overflow: visible;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
body {
|
|
79
|
+
margin: 0 0;
|
|
80
|
+
padding: 0;
|
|
81
|
+
/*width: 210mm;
|
|
82
|
+
min-height: 297mm;*/
|
|
83
|
+
position: relative;
|
|
84
|
+
font-family: 'Metropolis', system-ui, -apple-system, sans-serif;
|
|
85
|
+
font-weight: 500;
|
|
86
|
+
color: var(--color-dark);
|
|
87
|
+
font-size: 9.9pt;
|
|
88
|
+
/* ~3.5mm */
|
|
89
|
+
line-height: 1.4;
|
|
90
|
+
overflow: visible;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
.content {
|
|
95
|
+
position: relative;
|
|
96
|
+
z-index: 3;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* -------------------------------------------------------------------- */
|
|
100
|
+
/* Invoice header (page 1 only) */
|
|
101
|
+
/* -------------------------------------------------------------------- */
|
|
102
|
+
.invoice-header {
|
|
103
|
+
padding: 1mm var(--page-margin) 0;
|
|
104
|
+
position: relative;
|
|
105
|
+
/* min-height: 90mm; Only needed if we fix the background images */
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.invoice-header .logo {
|
|
109
|
+
height: 10mm;
|
|
110
|
+
max-width: 100%;
|
|
111
|
+
width: auto;
|
|
112
|
+
display: block;
|
|
113
|
+
margin-bottom: 13mm;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.header-grid {
|
|
117
|
+
display: flex;
|
|
118
|
+
justify-content: space-between;
|
|
119
|
+
align-items: flex-start;
|
|
120
|
+
gap: 8mm;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Left column: invoice title + dates */
|
|
124
|
+
.invoice-info {
|
|
125
|
+
flex: 0 0 80mm;
|
|
126
|
+
min-width: 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.invoice-title-row {
|
|
130
|
+
display: flex;
|
|
131
|
+
align-items: baseline;
|
|
132
|
+
gap: 5mm;
|
|
133
|
+
margin-bottom: 4mm;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.invoice-title-row .label {
|
|
137
|
+
font-weight: 600;
|
|
138
|
+
font-size: 12pt;
|
|
139
|
+
/* ~4.24mm */
|
|
140
|
+
color: var(--color-dark);
|
|
141
|
+
flex: 0 0 22mm;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.invoice-title-row .number {
|
|
145
|
+
font-weight: 600;
|
|
146
|
+
font-size: 12pt;
|
|
147
|
+
color: var(--color-primary);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.date-row {
|
|
151
|
+
display: flex;
|
|
152
|
+
gap: 5mm;
|
|
153
|
+
font-size: 8.5pt;
|
|
154
|
+
/* ~3mm */
|
|
155
|
+
color: var(--color-gray-dark);
|
|
156
|
+
margin-bottom: 1mm;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.date-row .label {
|
|
160
|
+
flex: 0 0 22mm;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/* Right column: sender + customer */
|
|
164
|
+
.sender-customer {
|
|
165
|
+
flex: 0 0 72mm;
|
|
166
|
+
min-width: 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.sender-name,
|
|
170
|
+
.customer-label {
|
|
171
|
+
font-weight: 600;
|
|
172
|
+
font-size: 12pt;
|
|
173
|
+
color: var(--color-dark);
|
|
174
|
+
margin-bottom: 3mm;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.customer-label {
|
|
178
|
+
margin-top: 8mm;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.sender-details,
|
|
182
|
+
.customer-details {
|
|
183
|
+
font-size: 8.5pt;
|
|
184
|
+
color: var(--color-gray-dark);
|
|
185
|
+
line-height: 1.5;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.sender-details>p,
|
|
189
|
+
.customer-details>p {
|
|
190
|
+
white-space: pre-line;
|
|
191
|
+
margin: 0;
|
|
192
|
+
padding: 0;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/* -------------------------------------------------------------------- */
|
|
196
|
+
/* Items table */
|
|
197
|
+
/* -------------------------------------------------------------------- */
|
|
198
|
+
.invoice-body {
|
|
199
|
+
padding: 0 var(--page-margin);
|
|
200
|
+
margin-top: 8mm;
|
|
201
|
+
min-height: 11cm;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.items-table {
|
|
205
|
+
width: 100%;
|
|
206
|
+
border-collapse: collapse;
|
|
207
|
+
table-layout: fixed;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.items-table col.c-num {
|
|
211
|
+
width: 12mm;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.items-table col.c-vat {
|
|
215
|
+
width: 20mm;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.items-table col.c-unit {
|
|
219
|
+
width: 20mm;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.items-table col.c-total {
|
|
223
|
+
width: 20mm;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.items-table thead th {
|
|
227
|
+
font-weight: 600;
|
|
228
|
+
font-size: 9.9pt;
|
|
229
|
+
color: var(--color-dark);
|
|
230
|
+
text-align: left;
|
|
231
|
+
padding: 0 0 2.5mm 0;
|
|
232
|
+
vertical-align: top;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
.items-table thead th.col-total {
|
|
236
|
+
text-align: right;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* Don't repeat header on subsequent printed pages */
|
|
240
|
+
.items-table thead {
|
|
241
|
+
display: table-row-group;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.items-table tbody td {
|
|
245
|
+
padding: 5mm 0;
|
|
246
|
+
vertical-align: top;
|
|
247
|
+
font-size: 9.9pt;
|
|
248
|
+
color: var(--color-dark);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.items-table tbody td.col-desc {
|
|
252
|
+
padding-right: 5mm;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.items-table tbody td.col-total {
|
|
256
|
+
text-align: right;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/* Faint separator above each row except the first one in the table.
|
|
260
|
+
Drawing the line on col-desc/col-unit/col-total mirrors the original PDF,
|
|
261
|
+
where the rule starts at x = 28 mm (skipping the # column). */
|
|
262
|
+
.items-table tbody tr:not(:first-child) td.col-desc,
|
|
263
|
+
.items-table tbody tr:not(:first-child) td.col-unit,
|
|
264
|
+
.items-table tbody tr:not(:first-child) td.col-vat,
|
|
265
|
+
.items-table tbody tr:not(:first-child) td.col-total {
|
|
266
|
+
border-top: 1px solid var(--color-line);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.items-table tbody tr {
|
|
270
|
+
break-inside: avoid;
|
|
271
|
+
page-break-inside: avoid;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.item-name {
|
|
275
|
+
color: var(--color-dark);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.item-desc {
|
|
279
|
+
font-size: 8.5pt;
|
|
280
|
+
color: var(--color-gray-dark);
|
|
281
|
+
margin-top: 1.5mm;
|
|
282
|
+
line-height: 1.6;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* -------------------------------------------------------------------- */
|
|
286
|
+
/* Price footer (last page, after items) */
|
|
287
|
+
/* -------------------------------------------------------------------- */
|
|
288
|
+
.price-footer {
|
|
289
|
+
padding: 14mm var(--page-margin) 0;
|
|
290
|
+
break-inside: avoid;
|
|
291
|
+
page-break-inside: avoid;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.totals-grid {
|
|
295
|
+
display: grid;
|
|
296
|
+
grid-template-columns: 1fr 1fr;
|
|
297
|
+
gap: 5mm;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.vat-breakdown-container {
|
|
301
|
+
align-self: end;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.totals {
|
|
305
|
+
margin-left: auto;
|
|
306
|
+
width: 78mm;
|
|
307
|
+
display: flex;
|
|
308
|
+
flex-direction: column;
|
|
309
|
+
gap: 4mm;
|
|
310
|
+
display: grid;
|
|
311
|
+
grid-template-columns: 1fr auto;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.totals .row {
|
|
315
|
+
display: grid;
|
|
316
|
+
align-items: baseline;
|
|
317
|
+
gap: 10mm;
|
|
318
|
+
grid-template-columns: subgrid;
|
|
319
|
+
grid-column: 1 / -1;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.totals .row .label {
|
|
323
|
+
font-weight: 600;
|
|
324
|
+
font-size: 9.9pt;
|
|
325
|
+
text-align: right;
|
|
326
|
+
text-box-trim: trim-both;
|
|
327
|
+
flex-grow: 1;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
.totals .row .value {
|
|
331
|
+
font-weight: 500;
|
|
332
|
+
font-size: 9.9pt;
|
|
333
|
+
text-box-trim: trim-both;
|
|
334
|
+
flex-shrink: 0;
|
|
335
|
+
text-align: right;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.totals .row.vat-shifted {
|
|
339
|
+
margin-top: -3mm;
|
|
340
|
+
margin-bottom: 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.totals .row.vat-shifted .label {
|
|
344
|
+
font-size: 7pt;
|
|
345
|
+
/* ~2.5mm */
|
|
346
|
+
font-weight: 500;
|
|
347
|
+
color: var(--color-gray);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.vat-breakdown {
|
|
351
|
+
width: 60mm;
|
|
352
|
+
border-collapse: collapse;
|
|
353
|
+
font-size: 8.5pt;
|
|
354
|
+
color: var(--color-gray-dark);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.vat-breakdown thead th {
|
|
358
|
+
font-weight: 600;
|
|
359
|
+
text-align: right;
|
|
360
|
+
padding: 0 0 1.5mm 0;
|
|
361
|
+
color: var(--color-dark);
|
|
362
|
+
border-bottom: 1px solid var(--color-line);
|
|
363
|
+
text-box-trim: trim-both;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.vat-breakdown thead th.col-rate {
|
|
367
|
+
text-align: left;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.vat-breakdown tbody td {
|
|
371
|
+
padding: 2mm 0 0 0;
|
|
372
|
+
vertical-align: top;
|
|
373
|
+
text-align: right;
|
|
374
|
+
text-box-trim: trim-both;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
.vat-breakdown tbody td.col-rate {
|
|
378
|
+
text-align: left;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.vat-breakdown tbody td.col-amount {
|
|
382
|
+
padding-left: 4mm;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.totals .row.total {
|
|
386
|
+
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.totals .row.total .label {
|
|
390
|
+
font-size: 13pt;
|
|
391
|
+
text-box-trim: trim-both;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.totals .row.total .value {
|
|
395
|
+
font-weight: 600;
|
|
396
|
+
text-box-trim: trim-both;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/* Messages block (archive notice + payment status) */
|
|
400
|
+
.messages {
|
|
401
|
+
margin-top: 14mm;
|
|
402
|
+
display: flex;
|
|
403
|
+
flex-direction: column;
|
|
404
|
+
gap: 5mm;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.message {
|
|
408
|
+
display: flex;
|
|
409
|
+
gap: 4mm;
|
|
410
|
+
font-size: 9.9pt;
|
|
411
|
+
color: var(--color-gray-dark);
|
|
412
|
+
line-height: 1.5;
|
|
413
|
+
align-items: center;
|
|
414
|
+
font-weight: 600;
|
|
415
|
+
text-box-trim: trim-both;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.message .icon {
|
|
419
|
+
flex: 0 0 16px;
|
|
420
|
+
width: 16px;
|
|
421
|
+
height: 16px;
|
|
422
|
+
fill: var(--color-gray-dark);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.message.paid {
|
|
426
|
+
color: var(--color-primary);
|
|
427
|
+
}
|
|
428
|
+
.message.paid .icon {
|
|
429
|
+
fill: var(--color-primary);
|
|
430
|
+
}
|
|
431
|
+
</style>
|
|
432
|
+
</head>
|
|
433
|
+
|
|
434
|
+
<body>
|
|
435
|
+
|
|
436
|
+
<div class="bg-other-pages" aria-hidden="true"></div>
|
|
437
|
+
<div class="bg-first-page" aria-hidden="true"></div>
|
|
438
|
+
|
|
439
|
+
<div class="content">
|
|
440
|
+
|
|
441
|
+
{{!-- ============================================================== --}}
|
|
442
|
+
{{!-- Header: logo, invoice info, sender, customer (page 1 only) --}}
|
|
443
|
+
{{!-- ============================================================== --}}
|
|
444
|
+
<header class="invoice-header">
|
|
445
|
+
<div class="header-grid">
|
|
446
|
+
<div class="invoice-info">
|
|
447
|
+
<img class="logo" src="{{logoUrl}}" alt="Logo">
|
|
448
|
+
|
|
449
|
+
<div class="invoice-title-row">
|
|
450
|
+
<span class="label">
|
|
451
|
+
{{#if invoice.number}}
|
|
452
|
+
{{#if isCreditNote}}{{$t "Creditnota"}}{{else}}{{$t "Factuur"}}{{/if}}
|
|
453
|
+
{{else}}
|
|
454
|
+
{{#if isCreditNote}}{{$t "Pro-forma creditnota"}}{{else}}{{$t "Pro-forma
|
|
455
|
+
factuur"}}{{/if}}
|
|
456
|
+
{{/if}}
|
|
457
|
+
</span>
|
|
458
|
+
{{#if invoice.number}}
|
|
459
|
+
<span class="number">{{invoice.number}}</span>
|
|
460
|
+
{{/if}}
|
|
461
|
+
</div>
|
|
462
|
+
|
|
463
|
+
<div class="date-row">
|
|
464
|
+
<span class="label">{{$t "Datum"}}</span>
|
|
465
|
+
<span class="value">{{formatDate invoice.meta.date}}</span>
|
|
466
|
+
</div>
|
|
467
|
+
|
|
468
|
+
{{#if showDueDate}}
|
|
469
|
+
<div class="date-row">
|
|
470
|
+
<span class="label">{{$t "Vervaldatum"}}</span>
|
|
471
|
+
<span class="value">{{formatDate dueDate}}</span>
|
|
472
|
+
</div>
|
|
473
|
+
{{/if}}
|
|
474
|
+
</div>
|
|
475
|
+
|
|
476
|
+
<div class="sender-customer">
|
|
477
|
+
<div class="sender-name">{{sender.name}}</div>
|
|
478
|
+
<div class="sender-details">
|
|
479
|
+
<p>{{sender.address}}</p>
|
|
480
|
+
<p>{{sender.vatNumber}}</p>
|
|
481
|
+
</div>
|
|
482
|
+
|
|
483
|
+
<div class="customer-label">
|
|
484
|
+
{{#if invoice.number}}
|
|
485
|
+
{{#if isCreditNote}}{{$t "Voor"}}{{else}}{{$t "Factuur voor"}}{{/if}}
|
|
486
|
+
{{else}}
|
|
487
|
+
{{$t "Voor"}}
|
|
488
|
+
{{/if}}
|
|
489
|
+
</div>
|
|
490
|
+
<div class="customer-details">
|
|
491
|
+
<p>{{invoice.customer.name}}</p>
|
|
492
|
+
{{#if invoice.customer.contactName }}
|
|
493
|
+
<p>{{ $t "T.a.v. "}} {{invoice.customer.contactName}}</p>
|
|
494
|
+
{{/if}}
|
|
495
|
+
{{#if invoice.customer.address }}
|
|
496
|
+
<p>{{invoice.customer.address}}</p>
|
|
497
|
+
{{/if}}
|
|
498
|
+
{{#if invoice.customer.companyNumber}}
|
|
499
|
+
<p>{{invoice.customer.companyNumber}}</p>
|
|
500
|
+
{{/if}}
|
|
501
|
+
{{#if invoice.customer.VATNumber}}
|
|
502
|
+
<p>{{#if invoice.customer.companyNumber}}{{$t "BTW"}}: {{/if}}{{invoice.customer.VATNumber}}</p>
|
|
503
|
+
{{/if}}
|
|
504
|
+
</div>
|
|
505
|
+
</div>
|
|
506
|
+
|
|
507
|
+
</div>
|
|
508
|
+
</header>
|
|
509
|
+
|
|
510
|
+
{{!-- ============================================================== --}}
|
|
511
|
+
{{!-- Items table — flows naturally across pages --}}
|
|
512
|
+
{{!-- ============================================================== --}}
|
|
513
|
+
<main class="invoice-body">
|
|
514
|
+
<table class="items-table">
|
|
515
|
+
<colgroup>
|
|
516
|
+
<col class="c-num">
|
|
517
|
+
<col class="c-desc">
|
|
518
|
+
{{#if invoice.meta.hasMultipleVATRates}}
|
|
519
|
+
<col class="c-vat">
|
|
520
|
+
{{/if}}
|
|
521
|
+
<col class="c-unit">
|
|
522
|
+
<col class="c-total">
|
|
523
|
+
</colgroup>
|
|
524
|
+
<thead>
|
|
525
|
+
<tr>
|
|
526
|
+
<th class="col-num">#</th>
|
|
527
|
+
<th class="col-desc">{{$t "Omschrijving"}}</th>
|
|
528
|
+
{{#if invoice.meta.hasMultipleVATRates}}
|
|
529
|
+
<th class="col-vat">{{$t "BTW %"}}</th>
|
|
530
|
+
{{/if}}
|
|
531
|
+
<th class="col-unit">{{$t "Per stuk"}}</th>
|
|
532
|
+
<th class="col-total">{{$t "Totaal"}}</th>
|
|
533
|
+
</tr>
|
|
534
|
+
</thead>
|
|
535
|
+
<tbody>
|
|
536
|
+
{{#each invoice.meta.items}}
|
|
537
|
+
<tr>
|
|
538
|
+
<td class="col-num">{{amount}}</td>
|
|
539
|
+
<td class="col-desc">
|
|
540
|
+
<div class="item-name">{{name}}</div>
|
|
541
|
+
{{#if description}}
|
|
542
|
+
<div class="item-desc">{{description}}</div>
|
|
543
|
+
{{/if}}
|
|
544
|
+
</td>
|
|
545
|
+
{{#if @root.invoice.meta.hasMultipleVATRates}}
|
|
546
|
+
<td class="col-vat">{{percentageLabel}}</td>
|
|
547
|
+
{{/if}}
|
|
548
|
+
<td class="col-unit">{{formatPrice unitPriceExclVAT}}</td>
|
|
549
|
+
<td class="col-total">{{formatPrice priceExclVAT}}</td>
|
|
550
|
+
</tr>
|
|
551
|
+
{{/each}}
|
|
552
|
+
</tbody>
|
|
553
|
+
</table>
|
|
554
|
+
</main>
|
|
555
|
+
|
|
556
|
+
{{!-- ============================================================== --}}
|
|
557
|
+
{{!-- Price footer (totals + messages) --}}
|
|
558
|
+
{{!-- ============================================================== --}}
|
|
559
|
+
<footer class="price-footer">
|
|
560
|
+
<div class="totals-grid">
|
|
561
|
+
<div class="vat-breakdown-container">
|
|
562
|
+
{{#if invoice.meta.hasMultipleVATRates}}
|
|
563
|
+
<table class="vat-breakdown">
|
|
564
|
+
<thead>
|
|
565
|
+
<tr>
|
|
566
|
+
<th class="col-rate">{{$t "BTW %"}}</th>
|
|
567
|
+
<th class="col-amount">{{$t "Excl. BTW"}}</th>
|
|
568
|
+
<th class="col-amount">{{$t "BTW"}}</th>
|
|
569
|
+
</tr>
|
|
570
|
+
</thead>
|
|
571
|
+
<tbody>
|
|
572
|
+
{{#each invoice.meta.VATTotal}}
|
|
573
|
+
<tr>
|
|
574
|
+
<td class="col-rate">{{#if VATExcempt}}{{VATExcemptName}}{{else}}{{percentageLabel}}{{/if}}</td>
|
|
575
|
+
<td class="col-amount">{{formatPrice taxablePrice}}</td>
|
|
576
|
+
<td class="col-amount">{{formatPrice VAT}}</td>
|
|
577
|
+
</tr>
|
|
578
|
+
{{/each}}
|
|
579
|
+
</tbody>
|
|
580
|
+
</table>
|
|
581
|
+
{{/if}}
|
|
582
|
+
</div>
|
|
583
|
+
<div class="totals">
|
|
584
|
+
<div class="row">
|
|
585
|
+
<span class="label">{{$t "Totaal excl. btw"}}</span>
|
|
586
|
+
<span class="value">{{formatPrice invoice.meta.priceWithoutVAT}}</span>
|
|
587
|
+
</div>
|
|
588
|
+
{{#if invoice.meta.hasMultipleVATRates}}
|
|
589
|
+
<div class="row">
|
|
590
|
+
<span class="label">{{$t "BTW"}}</span>
|
|
591
|
+
<span class="value">{{formatPrice invoice.meta.VAT}}</span>
|
|
592
|
+
</div>
|
|
593
|
+
{{else}}
|
|
594
|
+
<div class="row">
|
|
595
|
+
<span class="label">{{$t "BTW"}} ({{invoice.meta.singleVATRateLabel}})</span>
|
|
596
|
+
<span class="value">{{formatPrice invoice.meta.VAT}}</span>
|
|
597
|
+
</div>
|
|
598
|
+
{{#if invoice.meta.vatExcemptNote}}
|
|
599
|
+
<div class="row vat-shifted">
|
|
600
|
+
<span class="label">{{invoice.meta.vatExcemptNote}}</span>
|
|
601
|
+
<span></span>
|
|
602
|
+
</div>
|
|
603
|
+
{{/if}}
|
|
604
|
+
{{/if}}
|
|
605
|
+
{{#if hasRoundingAmount}}
|
|
606
|
+
<div class="row">
|
|
607
|
+
<span class="label">{{$t "Afrondingsverschil"}}</span>
|
|
608
|
+
<span class="value">{{formatPrice invoice.meta.payableRoundingAmount}}</span>
|
|
609
|
+
</div>
|
|
610
|
+
{{/if}}
|
|
611
|
+
<div class="row total">
|
|
612
|
+
<span class="label">{{$t "Totaal incl. BTW"}}</span>
|
|
613
|
+
<span class="value">{{formatPrice invoice.meta.totalPrice}}</span>
|
|
614
|
+
</div>
|
|
615
|
+
</div>
|
|
616
|
+
</div>
|
|
617
|
+
|
|
618
|
+
<div class="messages">
|
|
619
|
+
|
|
620
|
+
{{!-- Always-visible archive notice (varies by document type) --}}
|
|
621
|
+
<div class="message archive">
|
|
622
|
+
<svg class="icon" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
623
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
624
|
+
d="M3.67327 2.52862C1.50134 4.01571 1.21296 6.95436 2.11388 8.30055C4.78725 6.67111 6.69703 5.33679 8.70409 3.72095C8.46387 4.06251 8.14127 4.46052 7.74941 4.90029C7.12008 5.60656 6.34856 6.38067 5.54204 7.14116C3.92626 8.66473 2.20363 10.1022 1.26444 10.7931C0.967076 11.0118 0.903352 11.4303 1.12211 11.7276C1.34087 12.025 1.75928 12.0887 2.05665 11.87C2.70394 11.3938 3.67804 10.6022 4.73273 9.68002C9.48876 10.8971 12.1197 6.08032 11.5772 0.148376C9.9992 0.814142 8.7907 0.987292 7.69217 1.14468C6.34654 1.33748 5.16591 1.50664 3.67327 2.52862Z" />
|
|
625
|
+
</svg>
|
|
626
|
+
<span class="text">
|
|
627
|
+
{{#unless invoice.number}}
|
|
628
|
+
{{$t "Druk dit document niet af. Dit is nog geen officiële factuur"}}
|
|
629
|
+
{{else}}
|
|
630
|
+
{{#if isCreditNote}}
|
|
631
|
+
{{$t "Hou deze creditnota bij voorkeur digitaal bij"}}
|
|
632
|
+
{{else}}
|
|
633
|
+
{{$t "Hou deze factuur bij voorkeur digitaal bij"}}
|
|
634
|
+
{{/if}}
|
|
635
|
+
{{/unless}}
|
|
636
|
+
</span>
|
|
637
|
+
</div>
|
|
638
|
+
|
|
639
|
+
{{!-- Payment status messages (mutually exclusive) --}}
|
|
640
|
+
{{#if showPaidMessage}}
|
|
641
|
+
<div class="message paid">
|
|
642
|
+
<svg class="icon" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
643
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
644
|
+
d="M6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12ZM8.88815 4.54879C9.08076 4.27914 9.0183 3.90441 8.74865 3.71181C8.479 3.5192 8.10427 3.58165 7.91167 3.8513L5.3881 7.3843L4.07991 5.64005C3.88109 5.37495 3.50501 5.32122 3.23991 5.52005C2.97481 5.71887 2.92109 6.09495 3.11991 6.36005L4.91991 8.76005C5.0347 8.91309 5.21559 9.00223 5.40689 9C5.59818 8.99778 5.77695 8.90446 5.88815 8.74879L8.88815 4.54879Z" />
|
|
645
|
+
</svg>
|
|
646
|
+
<span class="text">{{$t "Deze factuur werd al betaald via"}} {{payment.methodName}}</span>
|
|
647
|
+
</div>
|
|
648
|
+
{{/if}}
|
|
649
|
+
|
|
650
|
+
{{#if showTransferMessage}}
|
|
651
|
+
<div class="message transfer">
|
|
652
|
+
<svg class="icon" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
653
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
654
|
+
d="M1.71429 0.714233C0.767512 0.714233 0 1.48174 0 2.42852V2.85714H12V2.42852C12 1.48175 11.2325 0.714233 10.2857 0.714233H1.71429ZM12 4.57143H0V7.57138C0 8.51815 0.767512 9.28566 1.71429 9.28566H10.2857C11.2325 9.28566 12 8.51815 12 7.57138V4.57143Z" />
|
|
655
|
+
</svg>
|
|
656
|
+
<span class="text">{{$t "Over te schrijven op"}} {{sender.bankAccount}}<br>{{$t "Met mededeling"}} {{payment.transferDescription}}</span>
|
|
657
|
+
</div>
|
|
658
|
+
{{/if}}
|
|
659
|
+
|
|
660
|
+
{{#if showDirectDebitMessage}}
|
|
661
|
+
<div class="message direct-debit">
|
|
662
|
+
<svg class="icon" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
663
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
664
|
+
d="M1.71429 0.714233C0.767512 0.714233 0 1.48174 0 2.42852V2.85714H12V2.42852C12 1.48175 11.2325 0.714233 10.2857 0.714233H1.71429ZM12 4.57143H0V7.57138C0 8.51815 0.767512 9.28566 1.71429 9.28566H10.2857C11.2325 9.28566 12 8.51815 12 7.57138V4.57143Z" />
|
|
665
|
+
</svg>
|
|
666
|
+
<span class="text">{{$t "De betaling gebeurt automatisch via domiciliëring"}}</span>
|
|
667
|
+
</div>
|
|
668
|
+
{{/if}}
|
|
669
|
+
|
|
670
|
+
{{#if showStripeMessage}}
|
|
671
|
+
<div class="message stripe">
|
|
672
|
+
<svg class="icon" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
|
|
673
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
674
|
+
d="M6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12ZM8.88815 4.54879C9.08076 4.27914 9.0183 3.90441 8.74865 3.71181C8.479 3.5192 8.10427 3.58165 7.91167 3.8513L5.3881 7.3843L4.07991 5.64005C3.88109 5.37495 3.50501 5.32122 3.23991 5.52005C2.97481 5.71887 2.92109 6.09495 3.11991 6.36005L4.91991 8.76005C5.0347 8.91309 5.21559 9.00223 5.40689 9C5.59818 8.99778 5.77695 8.90446 5.88815 8.74879L8.88815 4.54879Z" />
|
|
675
|
+
</svg>
|
|
676
|
+
<span class="text">{{$t "Het bedrag werd reeds ingehouden van jouw Stripe balans."}}</span>
|
|
677
|
+
</div>
|
|
678
|
+
{{/if}}
|
|
679
|
+
|
|
680
|
+
</div>
|
|
681
|
+
</footer>
|
|
682
|
+
|
|
683
|
+
</div>
|
|
684
|
+
</body>
|
|
685
|
+
|
|
686
|
+
</html>
|