@stamhoofd/models 2.19.0 → 2.20.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/dist/src/models/Member.js.map +1 -1
- package/dist/src/models/MemberResponsibilityRecord.d.ts +5 -0
- package/dist/src/models/MemberResponsibilityRecord.d.ts.map +1 -1
- package/dist/src/models/MemberResponsibilityRecord.js +16 -1
- package/dist/src/models/MemberResponsibilityRecord.js.map +1 -1
- package/dist/src/models/Organization.d.ts +2 -0
- package/dist/src/models/Organization.d.ts.map +1 -1
- package/dist/src/models/Organization.js +19 -3
- package/dist/src/models/Organization.js.map +1 -1
- package/dist/src/models/RegisterCode.d.ts +0 -10
- package/dist/src/models/RegisterCode.d.ts.map +1 -1
- package/dist/src/models/RegisterCode.js +0 -86
- package/dist/src/models/RegisterCode.js.map +1 -1
- package/dist/src/models/STCredit.d.ts +0 -7
- package/dist/src/models/STCredit.d.ts.map +1 -1
- package/dist/src/models/STCredit.js +0 -69
- package/dist/src/models/STCredit.js.map +1 -1
- package/dist/src/models/STInvoice.d.ts +2 -20
- package/dist/src/models/STInvoice.d.ts.map +1 -1
- package/dist/src/models/STInvoice.js +0 -364
- package/dist/src/models/STInvoice.js.map +1 -1
- package/dist/src/models/STPendingInvoice.d.ts +1 -21
- package/dist/src/models/STPendingInvoice.d.ts.map +1 -1
- package/dist/src/models/STPendingInvoice.js +0 -213
- package/dist/src/models/STPendingInvoice.js.map +1 -1
- package/dist/src/models/UsedRegisterCode.d.ts +0 -5
- package/dist/src/models/UsedRegisterCode.d.ts.map +1 -1
- package/dist/src/models/UsedRegisterCode.js +0 -101
- package/dist/src/models/UsedRegisterCode.js.map +1 -1
- package/package.json +2 -2
- package/src/models/Member.ts +5 -5
- package/src/models/MemberResponsibilityRecord.ts +21 -2
- package/src/models/Organization.ts +23 -3
- package/src/models/RegisterCode.ts +0 -95
- package/src/models/STCredit.ts +0 -82
- package/src/models/STInvoice.ts +2 -433
- package/src/models/STPendingInvoice.ts +2 -247
- package/src/models/UsedRegisterCode.ts +0 -115
- package/dist/src/helpers/InvoiceBuilder.d.ts +0 -29
- package/dist/src/helpers/InvoiceBuilder.d.ts.map +0 -1
- package/dist/src/helpers/InvoiceBuilder.js +0 -407
- package/dist/src/helpers/InvoiceBuilder.js.map +0 -1
- package/dist/src/helpers/InvoiceBuilder.test.d.ts +0 -2
- package/dist/src/helpers/InvoiceBuilder.test.d.ts.map +0 -1
- package/dist/src/helpers/InvoiceBuilder.test.js +0 -52
- package/dist/src/helpers/InvoiceBuilder.test.js.map +0 -1
- package/src/helpers/InvoiceBuilder.test.ts +0 -57
- package/src/helpers/InvoiceBuilder.ts +0 -501
|
@@ -1,501 +0,0 @@
|
|
|
1
|
-
import { SimpleError } from "@simonbackx/simple-errors";
|
|
2
|
-
import { File, PaymentMethod, PaymentMethodHelper, PaymentStatus, STInvoiceItem } from "@stamhoofd/structures";
|
|
3
|
-
import { Formatter } from "@stamhoofd/utility";
|
|
4
|
-
import AWS from 'aws-sdk';
|
|
5
|
-
import PDFDocument from 'pdfkit';
|
|
6
|
-
import { v4 as uuidv4 } from "uuid";
|
|
7
|
-
|
|
8
|
-
import { Payment, STInvoice } from "../models";
|
|
9
|
-
|
|
10
|
-
// 1 mm
|
|
11
|
-
const MM = 2.834666666666667
|
|
12
|
-
const COLOR_PRIMARY = "#0053ff"
|
|
13
|
-
const COLOR_DARK = "#000716"
|
|
14
|
-
const COLOR_GRAY_DARK = "#5e5e5e"
|
|
15
|
-
const COLOR_GRAY = "#868686";
|
|
16
|
-
|
|
17
|
-
const PAGE_WIDTH = 595.28
|
|
18
|
-
const PAGE_HEIGHT = 841.89
|
|
19
|
-
|
|
20
|
-
const ITEM_MARGIN = 5*MM
|
|
21
|
-
|
|
22
|
-
const PAGE_MARGIN = 16*MM
|
|
23
|
-
|
|
24
|
-
const END_MAX_Y = 567; // End of page line for last page
|
|
25
|
-
const MAX_Y = PAGE_HEIGHT - 24*MM
|
|
26
|
-
|
|
27
|
-
// Can we fit everything on one page?
|
|
28
|
-
const FIRST_START_Y = 100*MM;
|
|
29
|
-
const NORMAL_START_Y = PAGE_MARGIN;
|
|
30
|
-
|
|
31
|
-
export class InvoiceBuilder {
|
|
32
|
-
invoice: STInvoice
|
|
33
|
-
payment: Payment | null = null
|
|
34
|
-
document: PDFKit.PDFDocument
|
|
35
|
-
|
|
36
|
-
private remainingItems: STInvoiceItem[]
|
|
37
|
-
|
|
38
|
-
private posY = 0
|
|
39
|
-
private page = 1
|
|
40
|
-
|
|
41
|
-
private dataBuffer: any[] = []
|
|
42
|
-
|
|
43
|
-
constructor(invoice: STInvoice) {
|
|
44
|
-
this.invoice = invoice
|
|
45
|
-
this.document = new PDFDocument({ size: [PAGE_WIDTH, PAGE_HEIGHT], margin: PAGE_MARGIN});
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async build() {
|
|
49
|
-
if (!STAMHOOFD.SPACES_BUCKET || !STAMHOOFD.SPACES_ENDPOINT || !STAMHOOFD.SPACES_KEY || !STAMHOOFD.SPACES_SECRET) {
|
|
50
|
-
throw new SimpleError({
|
|
51
|
-
code: "not_available",
|
|
52
|
-
message: "Uploading is not available",
|
|
53
|
-
statusCode: 503
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
this.payment = (this.invoice.paymentId ? await Payment.getByID(this.invoice.paymentId) : null) ?? null
|
|
58
|
-
|
|
59
|
-
const buffer = await new Promise<Buffer>((resolve, reject) => {
|
|
60
|
-
try {
|
|
61
|
-
this.dataBuffer = [];
|
|
62
|
-
this.document.on('data', (d) => { this.dataBuffer.push(d); });
|
|
63
|
-
this.document.on('end', () => {
|
|
64
|
-
const buf = Buffer.concat(this.dataBuffer);
|
|
65
|
-
resolve(buf)
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
this.document.registerFont('Metropolis-SemiBold', __dirname +'/../assets/Metropolis-SemiBold.woff2');
|
|
69
|
-
this.document.registerFont('Metropolis-Medium', __dirname +'/../assets/Metropolis-Medium.woff2');
|
|
70
|
-
|
|
71
|
-
this.remainingItems = this.invoice.meta.items.slice()
|
|
72
|
-
|
|
73
|
-
// Initiate building
|
|
74
|
-
this.drawNextPages()
|
|
75
|
-
this.drawPriceFooter()
|
|
76
|
-
this.document.end()
|
|
77
|
-
} catch (e) {
|
|
78
|
-
reject(e)
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const fileId = uuidv4();
|
|
83
|
-
|
|
84
|
-
let prefix = (STAMHOOFD.SPACES_PREFIX ?? "")
|
|
85
|
-
if (prefix.length > 0) {
|
|
86
|
-
prefix += "/"
|
|
87
|
-
}
|
|
88
|
-
const key = prefix + (STAMHOOFD.environment ?? "development") + "/invoices/" + fileId + ".pdf";
|
|
89
|
-
|
|
90
|
-
const s3 = new AWS.S3({
|
|
91
|
-
endpoint: STAMHOOFD.SPACES_ENDPOINT,
|
|
92
|
-
accessKeyId: STAMHOOFD.SPACES_KEY,
|
|
93
|
-
secretAccessKey: STAMHOOFD.SPACES_SECRET
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const params = {
|
|
97
|
-
Bucket: STAMHOOFD.SPACES_BUCKET,
|
|
98
|
-
Key: key,
|
|
99
|
-
Body: buffer,
|
|
100
|
-
ContentType: 'application/pdf',
|
|
101
|
-
ACL: "public-read"
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
await s3.putObject(params).promise()
|
|
105
|
-
|
|
106
|
-
return new File({
|
|
107
|
-
id: fileId,
|
|
108
|
-
server: "https://"+STAMHOOFD.SPACES_BUCKET+"."+STAMHOOFD.SPACES_ENDPOINT,
|
|
109
|
-
path: key,
|
|
110
|
-
size: buffer.byteLength,
|
|
111
|
-
name: "Invoice "+this.invoice.id
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
private writeHeader() {
|
|
116
|
-
const logoX = 16
|
|
117
|
-
const logoY = 17
|
|
118
|
-
const logoHeight = 13
|
|
119
|
-
|
|
120
|
-
this.document.image(__dirname + '/../assets/logo.png', (logoX - 1) * MM, logoY * MM, { height: logoHeight * MM })
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.posY = 44
|
|
124
|
-
|
|
125
|
-
// Invoice number
|
|
126
|
-
this.document.fontSize(4.24 * MM);
|
|
127
|
-
this.document.fillColor(COLOR_DARK);
|
|
128
|
-
this.document.font('Metropolis-SemiBold')
|
|
129
|
-
|
|
130
|
-
if (this.invoice.number) {
|
|
131
|
-
this.document.text("Factuur", logoX * MM, this.posY * MM, { align: 'left' })
|
|
132
|
-
this.document.fillColor(COLOR_PRIMARY);
|
|
133
|
-
this.document.text(this.invoice.number + "", 43 * MM, this.posY * MM, { align: 'left' })
|
|
134
|
-
} else {
|
|
135
|
-
this.document.text("Pro-forma factuur", logoX * MM, this.posY * MM, { align: 'left' })
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
this.posY = 53
|
|
139
|
-
this.document.fontSize(3 * MM);
|
|
140
|
-
this.document.fillColor(COLOR_GRAY_DARK);
|
|
141
|
-
this.document.font('Metropolis-Medium')
|
|
142
|
-
const date = this.invoice.meta.date ?? this.invoice.paidAt ?? this.invoice.createdAt ?? new Date()
|
|
143
|
-
|
|
144
|
-
this.document.text("Datum", logoX * MM, this.posY * MM, { align: 'left' })
|
|
145
|
-
this.document.text(Formatter.date(date, true), 43 * MM, this.posY * MM, { align: 'left' })
|
|
146
|
-
|
|
147
|
-
if (this.invoice.number) {
|
|
148
|
-
this.document.moveDown()
|
|
149
|
-
const savedY = this.document.y
|
|
150
|
-
this.document.text("Vervaldatum", logoX * MM, savedY, { align: 'left' })
|
|
151
|
-
this.document.text(Formatter.date(((this.payment && this.payment.status === PaymentStatus.Succeeded) || (!this.payment && this.invoice.organizationId)) ? date : new Date(date.getTime() + 1000 * 60 * 60 * 24 * 30), true), 43 * MM, savedY, { align: 'left' })
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Write Codawood BV
|
|
155
|
-
const x = 120
|
|
156
|
-
const y = 21
|
|
157
|
-
|
|
158
|
-
this.document.fontSize(4.24 * MM);
|
|
159
|
-
this.document.fillColor(COLOR_DARK);
|
|
160
|
-
this.document.font('Metropolis-SemiBold')
|
|
161
|
-
|
|
162
|
-
this.document.text("Codawood BV", x * MM, y * MM, { align: 'left' })
|
|
163
|
-
|
|
164
|
-
this.document.fontSize(3 * MM);
|
|
165
|
-
this.document.fillColor(COLOR_GRAY_DARK);
|
|
166
|
-
this.document.font('Metropolis-Medium')
|
|
167
|
-
|
|
168
|
-
this.document.text("Collegiebaan 54, Wetteren, België\nBE0747.832.683", x * MM, this.document.y + 4*MM, { align: 'left', width: 72 * MM, lineGap: 2*MM })
|
|
169
|
-
|
|
170
|
-
// Write customer
|
|
171
|
-
|
|
172
|
-
this.document.fontSize(4.24 * MM);
|
|
173
|
-
this.document.fillColor(COLOR_DARK);
|
|
174
|
-
this.document.font('Metropolis-SemiBold')
|
|
175
|
-
|
|
176
|
-
this.document.text(this.invoice.number ? "Factuur voor" : "Voor", x * MM, this.document.y + 10*MM, { align: 'left' })
|
|
177
|
-
|
|
178
|
-
this.document.fontSize(3 * MM);
|
|
179
|
-
this.document.fillColor(COLOR_GRAY_DARK);
|
|
180
|
-
this.document.font('Metropolis-Medium')
|
|
181
|
-
|
|
182
|
-
const showNumber = this.invoice.meta.companyNumber && (!this.invoice.meta.companyVATNumber || (this.invoice.meta.companyNumber !== this.invoice.meta.companyVATNumber.substring(2) && this.invoice.meta.companyNumber !== this.invoice.meta.companyVATNumber));
|
|
183
|
-
|
|
184
|
-
this.document.text(
|
|
185
|
-
this.invoice.meta.companyName
|
|
186
|
-
+ (this.invoice.meta.companyContact ? ("\n"+this.invoice.meta.companyContact) : "")
|
|
187
|
-
+ "\n"
|
|
188
|
-
+ this.invoice.meta.companyAddress.toString()
|
|
189
|
-
+ (showNumber ? ("\n"+this.invoice.meta.companyNumber) : "")
|
|
190
|
-
+ (this.invoice.meta.companyVATNumber ? ("\n"+(showNumber ? "BTW: " : "")+this.invoice.meta.companyVATNumber) : "")
|
|
191
|
-
, x * MM
|
|
192
|
-
, this.document.y + 4*MM
|
|
193
|
-
, { align: 'left', width: 72 * MM, lineGap: 2*MM }
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
drawSinglePageShape() {
|
|
199
|
-
const grad = this.document.linearGradient(0, 0, 0, PAGE_HEIGHT);
|
|
200
|
-
grad.stop(0, COLOR_PRIMARY, 0.05)
|
|
201
|
-
grad.stop(1, COLOR_PRIMARY, 0.0125)
|
|
202
|
-
this.document.path("M77.7712 218.083L171.619 235.042C243.199 247.977 296.942 170.932 260.082 108.224C227.956 53.5718 264.75 -15.7544 328.017 -19.7785L448.398 -27.4352C464.702 -28.4722 480.75 -32.0117 495.978 -37.9294L675 -107.5L620.736 657.908C632.149 683.877 636.326 712.954 632.019 741.981L599 964.5L620.736 657.908C610.866 635.452 595.586 615.319 575.701 599.553C517.911 553.731 435.178 556.051 379.56 604.487C336.64 641.865 276.285 652.913 223.063 632.745L207.613 626.89C152.353 605.95 90.367 613.137 41.3649 646.167L-82.2193 729.468C-100.412 741.73 -124.568 726.81 -121.748 705.052L-72.9101 328.306C-63.4384 255.239 5.26735 204.981 77.7712 218.083Z").fill(grad)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
drawLastPageShape() {
|
|
206
|
-
const grad = this.document.linearGradient(0, 0, 0, PAGE_HEIGHT);
|
|
207
|
-
grad.stop(0, COLOR_PRIMARY, 0.05)
|
|
208
|
-
grad.stop(1, COLOR_PRIMARY, 0.0125)
|
|
209
|
-
this.document.path("M-0.5 217.5L0 0H596L597.916 613.667L634.755 642.877C641.094 647.903 644.268 655.931 643.081 663.933C638.973 691.617 598.15 688.669 598.062 660.681L597.916 613.667L575.701 596.053C517.911 550.231 435.178 552.551 379.56 600.987C336.64 638.365 276.285 649.413 223.063 629.245L207.613 623.39C152.353 602.45 90.367 609.637 41.3649 642.667L-76.3939 722.041C-95.0939 734.646 -119.534 717.721 -114.314 695.783L-0.5 217.5Z").fill(grad)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
drawFirstPageShape() {
|
|
213
|
-
const grad = this.document.linearGradient(0, 0, 0, PAGE_HEIGHT);
|
|
214
|
-
grad.stop(0, COLOR_PRIMARY, 0.05)
|
|
215
|
-
grad.stop(1, COLOR_PRIMARY, 0.0125)
|
|
216
|
-
this.document.path("M75.804 217.728L171.619 235.042C243.199 247.977 296.942 170.932 260.082 108.224C227.956 53.5718 264.75 -15.7544 328.017 -19.7785L473 -29H658L617 853.5H187.043C61.057 853.5 -56.3482 789.664 -124.84 683.922C-127.52 679.785 -128.591 674.809 -127.85 669.935L-75.5533 325.915C-64.5699 253.664 3.88734 204.732 75.804 217.728Z").fill(grad)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
drawBackground() {
|
|
220
|
-
// Create a linear gradient
|
|
221
|
-
const grad = this.document.linearGradient(0, 0, 0, PAGE_HEIGHT);
|
|
222
|
-
grad.stop(0, "#F1F6FF", 1)
|
|
223
|
-
grad.stop(1, "#FFFFFF", 1)
|
|
224
|
-
this.document.rect(0, 0, PAGE_WIDTH, PAGE_HEIGHT).fill(grad)
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
private remainingItemHeight() {
|
|
228
|
-
let y = 0
|
|
229
|
-
for (const item of this.remainingItems) {
|
|
230
|
-
y += ITEM_MARGIN
|
|
231
|
-
y += this.drawInvoiceItem(item, y, true)
|
|
232
|
-
y += ITEM_MARGIN
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
return y
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
drawNextPages() {
|
|
239
|
-
if (this.page == 1) {
|
|
240
|
-
this.posY = FIRST_START_Y
|
|
241
|
-
} else {
|
|
242
|
-
this.posY = NORMAL_START_Y
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
this.drawBackground()
|
|
246
|
-
|
|
247
|
-
if (this.remainingItemHeight() + this.posY > END_MAX_Y) {
|
|
248
|
-
// No end on this page
|
|
249
|
-
if (this.page === 1) {
|
|
250
|
-
// First page
|
|
251
|
-
this.drawFirstPageShape()
|
|
252
|
-
|
|
253
|
-
} else {
|
|
254
|
-
// Middle page
|
|
255
|
-
// No background
|
|
256
|
-
}
|
|
257
|
-
} else {
|
|
258
|
-
// Will end on this page
|
|
259
|
-
if (this.page === 1) {
|
|
260
|
-
// Single page
|
|
261
|
-
this.drawSinglePageShape()
|
|
262
|
-
} else {
|
|
263
|
-
// Last page
|
|
264
|
-
this.drawLastPageShape()
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
if (this.page === 1) {
|
|
269
|
-
this.posY += this.drawTableHeader(this.posY)
|
|
270
|
-
this.posY += ITEM_MARGIN/2;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
for (const [index, item] of this.remainingItems.entries()) {
|
|
274
|
-
let h = 0
|
|
275
|
-
h += ITEM_MARGIN
|
|
276
|
-
h += this.drawInvoiceItem(item, this.posY, true)
|
|
277
|
-
h += ITEM_MARGIN
|
|
278
|
-
if (h + this.posY > MAX_Y) {
|
|
279
|
-
// Remove all items that were already printed (excluding the current one)
|
|
280
|
-
this.remainingItems.splice(0, index)
|
|
281
|
-
|
|
282
|
-
// Doesn't fit on this page
|
|
283
|
-
this.endPage()
|
|
284
|
-
this.page++
|
|
285
|
-
this.document.addPage()
|
|
286
|
-
this.drawNextPages()
|
|
287
|
-
return
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
if (index > 0) {
|
|
291
|
-
// Print line
|
|
292
|
-
this.document.lineWidth(1)
|
|
293
|
-
this.document.lineCap('round')
|
|
294
|
-
this.document.moveTo(28*MM, this.posY - 1) // We use the line gap of the last text
|
|
295
|
-
.lineTo(PAGE_WIDTH, this.posY - 1)
|
|
296
|
-
.strokeOpacity(0.1)
|
|
297
|
-
.stroke(COLOR_DARK);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
// Does fit
|
|
301
|
-
this.posY += ITEM_MARGIN
|
|
302
|
-
this.posY += this.drawInvoiceItem(item, this.posY, false)
|
|
303
|
-
this.posY += ITEM_MARGIN
|
|
304
|
-
|
|
305
|
-
// TODO: print line
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
this.endPage()
|
|
309
|
-
|
|
310
|
-
// TODO: print pricing footer
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
endPage() {
|
|
314
|
-
if (this.page == 1) {
|
|
315
|
-
this.writeHeader()
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
this.drawPageFooter()
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Returns the height of the drawn item
|
|
323
|
-
*/
|
|
324
|
-
drawInvoiceItem(item: STInvoiceItem, y: number, dryRun: boolean) {
|
|
325
|
-
const x1 = PAGE_MARGIN;
|
|
326
|
-
const x2 = 28*MM;
|
|
327
|
-
const x4 = PAGE_WIDTH - PAGE_MARGIN - 20*MM;
|
|
328
|
-
const x3 = x4 - 20*MM;
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
this.document.fontSize(3.5 * MM);
|
|
332
|
-
this.document.fillColor(COLOR_DARK);
|
|
333
|
-
this.document.font('Metropolis-Medium')
|
|
334
|
-
|
|
335
|
-
let height = 0
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
if (!dryRun) {
|
|
339
|
-
this.document.text(item.amount+"", x1, y, { align: 'left', width: x2 - x1 })
|
|
340
|
-
this.document.text(item.name, x2, y, { align: 'left', width: x3 - x2 - 5*MM, lineGap: 2*MM })
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
height += this.document.heightOfString(item.name, { align: 'left', width: x3 - x2 - 5*MM, lineGap: 2*MM })
|
|
344
|
-
|
|
345
|
-
if (item.description) {
|
|
346
|
-
height += 1*MM
|
|
347
|
-
this.document.fontSize(3 * MM);
|
|
348
|
-
this.document.fillColor(COLOR_GRAY_DARK);
|
|
349
|
-
if (!dryRun) {
|
|
350
|
-
this.document.text(item.description, x2, this.document.y + 1*MM, { align: 'left', width: x3 - x2 - 5*MM, lineGap: 2*MM })
|
|
351
|
-
}
|
|
352
|
-
height += this.document.heightOfString(item.description, { align: 'left', width: x3 - x2 - 5*MM, lineGap: 2*MM })
|
|
353
|
-
|
|
354
|
-
this.document.fillColor(COLOR_DARK);
|
|
355
|
-
this.document.fontSize(3.5 * MM);
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
if (!dryRun) {
|
|
359
|
-
// We need to show prices exluding VAT and round here if needed
|
|
360
|
-
let unitPrice = item.unitPrice
|
|
361
|
-
let price = item.price
|
|
362
|
-
|
|
363
|
-
if (this.invoice.meta.areItemsIncludingVAT) {
|
|
364
|
-
unitPrice = this.invoice.meta.includingVATToExcludingVAT(unitPrice)
|
|
365
|
-
price = this.invoice.meta.includingVATToExcludingVAT(price)
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
369
|
-
this.document.text(Formatter.price(unitPrice).replace(/ /g, " "), x3, y, { align: 'left', width: x4 - x3 })
|
|
370
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
371
|
-
this.document.text(Formatter.price(price).replace(/ /g, " "), x4, y, { align: 'right', width: PAGE_WIDTH - x4 - PAGE_MARGIN })
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
return height
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
drawTableHeader(y: number) {
|
|
378
|
-
const x1 = PAGE_MARGIN;
|
|
379
|
-
const x2 = 28*MM;
|
|
380
|
-
const x4 = PAGE_WIDTH - PAGE_MARGIN - 20*MM;
|
|
381
|
-
const x3 = x4 - 20*MM;
|
|
382
|
-
|
|
383
|
-
this.document.fontSize(3.5 * MM);
|
|
384
|
-
this.document.fillColor(COLOR_DARK);
|
|
385
|
-
this.document.font('Metropolis-SemiBold')
|
|
386
|
-
this.document.text("#", x1, y, { align: 'left', width: x2 - x1 })
|
|
387
|
-
this.document.text("Omschrijving", x2, y, { align: 'left', width: x3 - x2 - 5*MM })
|
|
388
|
-
this.document.text("Per stuk", x3, y, { align: 'left', width: x4 - x3 })
|
|
389
|
-
this.document.text("Totaal", x4, y, { align: 'right', width: PAGE_WIDTH - x4 - PAGE_MARGIN })
|
|
390
|
-
|
|
391
|
-
return this.document.heightOfString("Omschrijving", { align: 'left', width: x3 - x2 - 5*MM })
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
drawPriceFooter() {
|
|
395
|
-
let y = END_MAX_Y + 40*MM;
|
|
396
|
-
const x4 = PAGE_WIDTH - PAGE_MARGIN - 30*MM;
|
|
397
|
-
|
|
398
|
-
this.document.fontSize(3.5 * MM);
|
|
399
|
-
this.document.fillColor(COLOR_DARK);
|
|
400
|
-
this.document.font('Metropolis-SemiBold')
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
this.document.text("Totaal excl. BTW", x4 - 40*MM, y, { align: 'right', width: 40*MM })
|
|
404
|
-
this.document.font('Metropolis-Medium')
|
|
405
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
406
|
-
this.document.text(Formatter.price(this.invoice.meta.priceWithoutVAT).replace(/ /g, " ").replace(/,00/g, ""), x4, y, { align: 'right', width: PAGE_WIDTH - x4 - PAGE_MARGIN })
|
|
407
|
-
|
|
408
|
-
y = this.document.y + 5*MM
|
|
409
|
-
this.document.font('Metropolis-SemiBold')
|
|
410
|
-
this.document.text("BTW ("+this.invoice.meta.VATPercentage+"%)", x4 - 40*MM, y, { align: 'right', width: 40*MM })
|
|
411
|
-
this.document.font('Metropolis-Medium')
|
|
412
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
413
|
-
this.document.text(Formatter.price(this.invoice.meta.VAT).replace(/ /g, " ").replace(/,00/g, ""), x4, y, { align: 'right', width: PAGE_WIDTH - x4 - PAGE_MARGIN })
|
|
414
|
-
|
|
415
|
-
// Keep semibold
|
|
416
|
-
this.document.font('Metropolis-SemiBold')
|
|
417
|
-
y = this.document.y + 5*MM
|
|
418
|
-
this.document.fontSize(4 * MM);
|
|
419
|
-
this.document.text("Totaal incl. BTW", x4 - 40*MM, y, { align: 'right', width: 40*MM })
|
|
420
|
-
this.document.fontSize(3.5 * MM);
|
|
421
|
-
// eslint-disable-next-line no-irregular-whitespace
|
|
422
|
-
this.document.text(Formatter.price(this.invoice.meta.priceWithVAT).replace(/ /g, " ").replace(/,00/g, ""), x4, y, { align: 'right', width: PAGE_WIDTH - x4 - PAGE_MARGIN })
|
|
423
|
-
|
|
424
|
-
y = this.document.y - 12
|
|
425
|
-
this.document.fillColor(COLOR_GRAY_DARK)
|
|
426
|
-
this.document.translate(PAGE_MARGIN, y).path("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").fill('even-odd')
|
|
427
|
-
|
|
428
|
-
let text = "Hou deze factuur bij voorkeur digitaal bij"
|
|
429
|
-
if (!this.invoice.number) {
|
|
430
|
-
text = "Druk dit document niet af. Dit is nog geen officiële factuur"
|
|
431
|
-
}
|
|
432
|
-
this.document.translate(-PAGE_MARGIN, -y)
|
|
433
|
-
const hh = this.document.heightOfString(text, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 })
|
|
434
|
-
this.document.text(text, PAGE_MARGIN + 8*MM, y + 12/2 - hh/2, { align: 'left' })
|
|
435
|
-
|
|
436
|
-
if (this.payment && this.payment.method) {
|
|
437
|
-
if (this.payment.status === PaymentStatus.Succeeded) {
|
|
438
|
-
y -= 10*MM
|
|
439
|
-
this.document.fillColor(COLOR_PRIMARY)
|
|
440
|
-
this.document.translate(PAGE_MARGIN, y).path("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").fill('even-odd')
|
|
441
|
-
|
|
442
|
-
this.document.translate(-PAGE_MARGIN, -y)
|
|
443
|
-
const payText = "Deze factuur werd al betaald via "+PaymentMethodHelper.getName(this.payment.method)
|
|
444
|
-
const h = this.document.heightOfString(payText, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 })
|
|
445
|
-
this.document.text(payText, PAGE_MARGIN + 8*MM, y + 12/2 - h/2, { align: 'left' })
|
|
446
|
-
} else if (this.payment.method === PaymentMethod.Transfer) {
|
|
447
|
-
y -= 10*MM
|
|
448
|
-
|
|
449
|
-
const payText = "Over te schrijven op BE93 7330 5887 3067\nMet mededeling "+this.payment.transferDescription
|
|
450
|
-
const h = this.document.heightOfString(payText, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 - 30*MM - 40*MM, lineGap: 2*MM })
|
|
451
|
-
|
|
452
|
-
y += 12/2 - h/2
|
|
453
|
-
|
|
454
|
-
this.document.fillColor(COLOR_PRIMARY)
|
|
455
|
-
this.document.translate(PAGE_MARGIN, y).path("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").fill('even-odd')
|
|
456
|
-
|
|
457
|
-
this.document.translate(-PAGE_MARGIN, -y)
|
|
458
|
-
|
|
459
|
-
this.document.text(payText, PAGE_MARGIN + 8*MM, y + 12/2 - h/2, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 - 30*MM - 40*MM, lineGap: 2*MM })
|
|
460
|
-
} else if (this.payment.method === PaymentMethod.DirectDebit) {
|
|
461
|
-
y -= 10*MM
|
|
462
|
-
|
|
463
|
-
const payText = "De betaling gebeurt automatisch via domiciliëring"
|
|
464
|
-
const h = this.document.heightOfString(payText, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 - 30*MM - 40*MM, lineGap: 2*MM })
|
|
465
|
-
|
|
466
|
-
y += 12/2 - h/2
|
|
467
|
-
|
|
468
|
-
this.document.fillColor(COLOR_PRIMARY)
|
|
469
|
-
this.document.translate(PAGE_MARGIN, y).path("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").fill('even-odd')
|
|
470
|
-
|
|
471
|
-
this.document.translate(-PAGE_MARGIN, -y)
|
|
472
|
-
|
|
473
|
-
this.document.text(payText, PAGE_MARGIN + 8*MM, y + 12/2 - h/2 + 0.5*MM, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 - 30*MM - 40*MM, lineGap: 2*MM })
|
|
474
|
-
}
|
|
475
|
-
} else {
|
|
476
|
-
if (this.invoice.organizationId) {
|
|
477
|
-
y -= 10*MM
|
|
478
|
-
this.document.fillColor(COLOR_PRIMARY)
|
|
479
|
-
this.document.translate(PAGE_MARGIN, y).path("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").fill('even-odd')
|
|
480
|
-
|
|
481
|
-
this.document.translate(-PAGE_MARGIN, -y)
|
|
482
|
-
const payText = "Het bedrag werd reeds ingehouden van jouw Stripe balans."
|
|
483
|
-
const h = this.document.heightOfString(payText, { align: 'left', width: PAGE_WIDTH - PAGE_MARGIN*2 })
|
|
484
|
-
this.document.text(payText, PAGE_MARGIN + 8*MM, y + 12/2 - h/2, { align: 'left' })
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
drawPageFooter() {
|
|
490
|
-
this.document.fillColor(COLOR_GRAY)
|
|
491
|
-
this.document.font('Metropolis-Medium')
|
|
492
|
-
this.document.fontSize(3 * MM);
|
|
493
|
-
let suffix = ''
|
|
494
|
-
if (this.invoice.meta.VATPercentage == 0) {
|
|
495
|
-
suffix = ' - BTW verlegd'
|
|
496
|
-
}
|
|
497
|
-
this.document.text(this.invoice.id+"", PAGE_MARGIN, PAGE_HEIGHT - PAGE_MARGIN, { align: 'left', baseline: "bottom", lineBreak: false, width: (PAGE_WIDTH - PAGE_MARGIN*2)/2, height: 10*MM })
|
|
498
|
-
this.document.text("Pagina "+this.page, PAGE_WIDTH - PAGE_MARGIN - 31*MM, PAGE_HEIGHT - PAGE_MARGIN, { align: 'right', baseline: "bottom", width: 30*MM, lineBreak: false, height: 10*MM })
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
}
|