@design.estate/dees-document 1.6.8 → 2.0.2

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.
Files changed (97) hide show
  1. package/dist_bundle/bundle.js +636 -590
  2. package/dist_bundle/bundle.js.map +4 -4
  3. package/dist_ts/00_commitinfo_data.js +1 -1
  4. package/dist_ts/classes.pdfservice.d.ts +3 -3
  5. package/dist_ts/classes.pdfservice.js +6 -3
  6. package/dist_ts/helpers.d.ts +1 -1
  7. package/dist_ts/helpers.js +2 -2
  8. package/dist_ts/paths.js +4 -2
  9. package/dist_ts/plugins.d.ts +2 -0
  10. package/dist_ts/plugins.js +3 -1
  11. package/dist_ts_shared/demoletter.d.ts +3 -3
  12. package/dist_ts_shared/demoletter.js +223 -192
  13. package/dist_ts_shared/index.d.ts +6 -7
  14. package/dist_ts_shared/index.js +10 -8
  15. package/dist_ts_shared/interfaces/document.d.ts +15 -2
  16. package/dist_ts_shared/interfaces/document.js +1 -1
  17. package/dist_ts_shared/translation.d.ts +79 -28
  18. package/dist_ts_shared/translation.js +121 -107
  19. package/dist_ts_web/00_commitinfo_data.js +2 -2
  20. package/dist_ts_web/elements/contentinvoice.js +54 -26
  21. package/dist_ts_web/elements/document.js +8 -18
  22. package/dist_ts_web/elements/letterheader.js +5 -12
  23. package/dist_ts_web/elements/page.js +10 -22
  24. package/dist_ts_web/elements/pagecontainer.js +4 -10
  25. package/dist_ts_web/elements/pagecontent.js +5 -12
  26. package/dist_ts_web/elements/pagefooter.js +6 -14
  27. package/dist_ts_web/elements/pageheader.js +6 -14
  28. package/dist_ts_web/elements/viewer.js +3 -8
  29. package/dist_ts_web/ts_shared/translation.d.ts +82 -0
  30. package/dist_ts_web/ts_shared/translation.js +134 -0
  31. package/dist_ts_web/ts_web/00_commitinfo_data.d.ts +8 -0
  32. package/dist_ts_web/ts_web/00_commitinfo_data.js +9 -0
  33. package/dist_ts_web/ts_web/elements/contentinvoice.d.ts +41 -0
  34. package/dist_ts_web/ts_web/elements/contentinvoice.js +466 -0
  35. package/dist_ts_web/ts_web/elements/document.d.ts +27 -0
  36. package/dist_ts_web/ts_web/elements/document.demo.d.ts +1 -0
  37. package/dist_ts_web/ts_web/elements/document.demo.js +9 -0
  38. package/dist_ts_web/ts_web/elements/document.js +306 -0
  39. package/dist_ts_web/ts_web/elements/index.d.ts +10 -0
  40. package/dist_ts_web/ts_web/elements/index.js +11 -0
  41. package/dist_ts_web/ts_web/elements/letterheader.d.ts +18 -0
  42. package/dist_ts_web/ts_web/elements/letterheader.js +224 -0
  43. package/dist_ts_web/ts_web/elements/page.d.ts +25 -0
  44. package/dist_ts_web/ts_web/elements/page.js +335 -0
  45. package/dist_ts_web/ts_web/elements/pagecontainer.d.ts +14 -0
  46. package/dist_ts_web/ts_web/elements/pagecontainer.js +114 -0
  47. package/dist_ts_web/ts_web/elements/pagecontent.d.ts +19 -0
  48. package/dist_ts_web/ts_web/elements/pagecontent.js +177 -0
  49. package/dist_ts_web/ts_web/elements/pagefooter.d.ts +17 -0
  50. package/dist_ts_web/ts_web/elements/pagefooter.js +234 -0
  51. package/dist_ts_web/ts_web/elements/pageheader.d.ts +17 -0
  52. package/dist_ts_web/ts_web/elements/pageheader.js +165 -0
  53. package/dist_ts_web/ts_web/elements/paymentcode.d.ts +19 -0
  54. package/dist_ts_web/ts_web/elements/paymentcode.js +162 -0
  55. package/dist_ts_web/ts_web/elements/viewer.d.ts +15 -0
  56. package/dist_ts_web/ts_web/elements/viewer.demo.d.ts +1 -0
  57. package/dist_ts_web/ts_web/elements/viewer.demo.js +9 -0
  58. package/dist_ts_web/ts_web/elements/viewer.js +150 -0
  59. package/dist_ts_web/ts_web/index.d.ts +1 -0
  60. package/dist_ts_web/ts_web/index.js +2 -0
  61. package/dist_ts_web/ts_web/pages/index.d.ts +2 -0
  62. package/dist_ts_web/ts_web/pages/index.js +3 -0
  63. package/dist_ts_web/ts_web/pages/page1.d.ts +1 -0
  64. package/dist_ts_web/ts_web/pages/page1.js +21 -0
  65. package/dist_ts_web/ts_web/pages/page2.d.ts +1 -0
  66. package/dist_ts_web/ts_web/pages/page2.js +18 -0
  67. package/dist_ts_web/ts_web/plugins.d.ts +9 -0
  68. package/dist_ts_web/ts_web/plugins.js +14 -0
  69. package/dist_ts_web/ts_web/style.d.ts +1 -0
  70. package/dist_ts_web/ts_web/style.js +38 -0
  71. package/dist_watch/bundle.js +20439 -12738
  72. package/dist_watch/bundle.js.map +4 -4
  73. package/license +2 -2
  74. package/package.json +21 -19
  75. package/readme.hints.md +40 -1
  76. package/readme.md +202 -125
  77. package/ts/00_commitinfo_data.ts +1 -1
  78. package/ts/classes.pdfservice.ts +15 -7
  79. package/ts/helpers.ts +1 -1
  80. package/ts/paths.ts +3 -1
  81. package/ts/plugins.ts +3 -0
  82. package/ts_web/00_commitinfo_data.ts +1 -1
  83. package/ts_web/elements/contentinvoice.ts +290 -203
  84. package/ts_web/elements/document.demo.ts +7 -4
  85. package/ts_web/elements/document.ts +68 -82
  86. package/ts_web/elements/index.ts +10 -9
  87. package/ts_web/elements/letterheader.ts +106 -39
  88. package/ts_web/elements/page.ts +106 -48
  89. package/ts_web/elements/pagecontainer.ts +14 -13
  90. package/ts_web/elements/pagecontent.ts +34 -53
  91. package/ts_web/elements/pagefooter.ts +125 -45
  92. package/ts_web/elements/pageheader.ts +22 -16
  93. package/ts_web/elements/paymentcode.ts +95 -0
  94. package/ts_web/elements/viewer.demo.ts +7 -4
  95. package/ts_web/elements/viewer.ts +26 -12
  96. package/ts_web/pages/page1.ts +10 -6
  97. package/ts_web/style.ts +34 -3
@@ -9,23 +9,21 @@ import {
9
9
  customElement,
10
10
  type TemplateResult,
11
11
  css,
12
- cssManager,
13
- unsafeCSS,
14
12
  render,
15
13
  domtools,
16
- } from '@design.estate/dees-element';
17
- import * as plugins from '../plugins.js';
18
-
19
- import { dedocumentSharedStyle } from '../style.js';
14
+ } from "@design.estate/dees-element";
15
+ import * as plugins from "../plugins.js";
20
16
 
17
+ import { dedocumentSharedStyle } from "../style.js";
18
+ import type { TranslationKey } from "ts_shared/translation.js";
21
19
 
22
20
  declare global {
23
21
  interface HTMLElementTagNameMap {
24
- 'dedocument-contentinvoice': DeContentInvoice;
22
+ "dedocument-contentinvoice": DeContentInvoice;
25
23
  }
26
24
  }
27
25
 
28
- @customElement('dedocument-contentinvoice')
26
+ @customElement("dedocument-contentinvoice")
29
27
  export class DeContentInvoice extends DeesElement {
30
28
  public static demo = () => html`
31
29
  <style>
@@ -43,13 +41,13 @@ export class DeContentInvoice extends DeesElement {
43
41
  type: Object,
44
42
  reflect: true,
45
43
  })
46
- public letterData: plugins.tsclass.business.ILetter;
44
+ accessor letterData: plugins.tsclass.finance.TInvoice;
47
45
 
48
46
  @property({
49
47
  type: Object,
50
48
  reflect: true,
51
49
  })
52
- public documentSettings: plugins.shared.interfaces.IDocumentSettings;
50
+ accessor documentSettings: plugins.shared.interfaces.IDocumentSettings;
53
51
 
54
52
  constructor() {
55
53
  super();
@@ -60,15 +58,96 @@ export class DeContentInvoice extends DeesElement {
60
58
  domtools.elementBasic.staticStyles,
61
59
  dedocumentSharedStyle,
62
60
  css`
63
- :host {
64
- color: #333;
65
- }
66
-
67
61
  .trimmedContent {
68
62
  display: none;
69
63
  }
70
64
 
71
- .repeatedContent {
65
+ .grid {
66
+ display: grid;
67
+ grid-template-columns: 40px auto 50px 50px 100px 50px 100px;
68
+ }
69
+
70
+ .topLine {
71
+ margin-top: 5px;
72
+ background: #e7e7e7;
73
+ font-weight: bold;
74
+ }
75
+
76
+ .lineItem {
77
+ font-size: 12px;
78
+ padding: 5px;
79
+ border-right: 1px dashed #ccc;
80
+ white-space: nowrap;
81
+ }
82
+
83
+ .lineItem:last-child {
84
+ border-right: none;
85
+ }
86
+
87
+ .value.rightAlign,
88
+ .lineItem.rightAlign {
89
+ text-align: right;
90
+ }
91
+
92
+ .invoiceLine {
93
+ background: #ffffff00;
94
+ border-bottom: 1px dotted #ccc;
95
+ }
96
+
97
+ .invoiceLine.highlighted {
98
+ transition: background 0.2s;
99
+ background: #ffc18f;
100
+ border: 1px solid #ff9d4d;
101
+ box-sizing: content-box;
102
+ }
103
+
104
+ .sums {
105
+ margin-top: 5px;
106
+ font-size: 12px;
107
+ padding-left: 50%;
108
+ }
109
+
110
+ .sums .sumline {
111
+ margin-top: 3px;
112
+ display: grid;
113
+ grid-template-columns: auto 100px;
114
+ }
115
+
116
+ .sums .sumline .label {
117
+ padding: 2px 5px;
118
+ border-right: 1px solid #ccc;
119
+ text-align: right;
120
+ font-weight: bold;
121
+ }
122
+
123
+ .sums .sumline .value {
124
+ padding: 2px 5px;
125
+ }
126
+
127
+ .sums .sumline .value--total {
128
+ font-weight: bold;
129
+ }
130
+
131
+ .divider {
132
+ margin-top: 8px;
133
+ border-top: 1px dotted #ccc;
134
+ }
135
+
136
+ .taxNote {
137
+ font-size: 12px;
138
+ padding: 4px;
139
+ background: #eeeeeb;
140
+ text-align: center;
141
+ }
142
+
143
+ .infoBox {
144
+ margin-top: 22px;
145
+ line-height: 1.4em;
146
+ }
147
+
148
+ .infoBox .label {
149
+ padding-bottom: 2px;
150
+ font-weight: bold;
72
151
  }
73
152
  `,
74
153
  ];
@@ -81,6 +160,17 @@ export class DeContentInvoice extends DeesElement {
81
160
  `;
82
161
  }
83
162
 
163
+ protected formatPrice(
164
+ value: number,
165
+ currency = "EUR",
166
+ lang = "de-DE"
167
+ ): string {
168
+ return new Intl.NumberFormat(lang, {
169
+ style: "currency",
170
+ currency,
171
+ }).format(value);
172
+ }
173
+
84
174
  public getTotalNet = (): number => {
85
175
  let totalNet = 0;
86
176
 
@@ -88,7 +178,7 @@ export class DeContentInvoice extends DeesElement {
88
178
  return totalNet;
89
179
  }
90
180
 
91
- for (const item of this.letterData.content.invoiceData.items) {
181
+ for (const item of this.letterData.items) {
92
182
  totalNet += item.unitNetPrice * item.unitQuantity;
93
183
  }
94
184
  return totalNet;
@@ -110,7 +200,7 @@ export class DeContentInvoice extends DeesElement {
110
200
  public getVatGroups = () => {
111
201
  const vatGroups: {
112
202
  vatPercentage: number;
113
- items: plugins.tsclass.finance.IInvoice['items'];
203
+ items: plugins.tsclass.finance.TInvoice["items"];
114
204
  vatAmountSum: number;
115
205
  }[] = [];
116
206
 
@@ -119,17 +209,22 @@ export class DeContentInvoice extends DeesElement {
119
209
  }
120
210
 
121
211
  const taxAmounts: number[] = [];
122
- for (const item of this.letterData.content.invoiceData.items) {
123
- taxAmounts.includes(item.vatPercentage) ? null : taxAmounts.push(item.vatPercentage);
212
+ for (const item of this.letterData.items) {
213
+ taxAmounts.includes(item.vatPercentage)
214
+ ? null
215
+ : taxAmounts.push(item.vatPercentage);
124
216
  }
125
217
 
126
218
  for (const taxAmount of taxAmounts) {
127
- const matchingItems = this.letterData.content.invoiceData.items.filter(
219
+ const matchingItems = this.letterData.items.filter(
128
220
  (itemArg) => itemArg.vatPercentage === taxAmount
129
221
  );
130
222
  let sum = 0;
131
223
  for (const matchingItem of matchingItems) {
132
- sum += matchingItem.unitNetPrice * matchingItem.unitQuantity * (taxAmount / 100);
224
+ sum +=
225
+ matchingItem.unitNetPrice *
226
+ matchingItem.unitQuantity *
227
+ (taxAmount / 100);
133
228
  }
134
229
  vatGroups.push({
135
230
  items: matchingItems,
@@ -137,15 +232,21 @@ export class DeContentInvoice extends DeesElement {
137
232
  vatAmountSum: Math.round(sum * 100) / 100,
138
233
  });
139
234
  }
140
- return vatGroups;
235
+ return vatGroups.sort((a, b) => b.vatPercentage - a.vatPercentage);
141
236
  };
142
237
 
143
238
  public async getContentNodes() {
144
239
  await this.elementDomReady;
145
240
  return {
146
- currentContent: this.shadowRoot.querySelector('.currentContent') as HTMLElement,
147
- trimmedContent: this.shadowRoot.querySelector('.trimmedContent') as HTMLElement,
148
- repeatedContent: this.shadowRoot.querySelector('.repeatedContent') as HTMLElement,
241
+ currentContent: this.shadowRoot.querySelector(
242
+ ".currentContent"
243
+ ) as HTMLElement,
244
+ trimmedContent: this.shadowRoot.querySelector(
245
+ ".trimmedContent"
246
+ ) as HTMLElement,
247
+ repeatedContent: this.shadowRoot.querySelector(
248
+ ".repeatedContent"
249
+ ) as HTMLElement,
149
250
  };
150
251
  }
151
252
 
@@ -157,7 +258,7 @@ export class DeContentInvoice extends DeesElement {
157
258
  public async trimEndByOne() {
158
259
  await this.elementDomReady;
159
260
  this.shadowRoot
160
- .querySelector('.trimmedContent')
261
+ .querySelector(".trimmedContent")
161
262
  .append(
162
263
  (await this.getContentNodes()).currentContent.children.item(
163
264
  (await this.getContentNodes()).currentContent.children.length - 1
@@ -167,7 +268,8 @@ export class DeContentInvoice extends DeesElement {
167
268
 
168
269
  public async trimStartToOffset(contentOffsetArg: number) {
169
270
  await this.elementDomReady;
170
- const beginningLength = (await this.getContentNodes()).currentContent.children.length;
271
+ const beginningLength = (await this.getContentNodes()).currentContent
272
+ .children.length;
171
273
  while (
172
274
  (await this.getContentNodes()).currentContent.children.length !==
173
275
  beginningLength - contentOffsetArg
@@ -179,13 +281,13 @@ export class DeContentInvoice extends DeesElement {
179
281
  if (
180
282
  (await this.getContentNodes()).currentContent.children
181
283
  .item(0)
182
- .classList.contains('needsDataHeader')
284
+ .classList.contains("needsDataHeader")
183
285
  ) {
184
286
  const trimmedContent = (await this.getContentNodes()).trimmedContent;
185
287
  let startPoint = trimmedContent.children.length;
186
288
  while (startPoint > 0) {
187
289
  const element = trimmedContent.children.item(startPoint - 1);
188
- if (element.classList.contains('dataHeader')) {
290
+ if (element.classList.contains("dataHeader")) {
189
291
  (await this.getContentNodes()).repeatedContent.append(element);
190
292
  break;
191
293
  }
@@ -194,209 +296,194 @@ export class DeContentInvoice extends DeesElement {
194
296
  }
195
297
  }
196
298
 
197
- public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
299
+ public translateKey(key: TranslationKey): string {
300
+ return plugins.shared.translation.translate(
301
+ this.documentSettings.languageCode,
302
+ key
303
+ );
304
+ }
305
+
306
+ public async firstUpdated(
307
+ _changedProperties: Map<string | number | symbol, unknown>
308
+ ) {
198
309
  super.firstUpdated(_changedProperties);
199
310
  this.attachInvoiceDom();
200
311
  }
201
312
 
313
+ private renderPaymentTerms(): TemplateResult {
314
+ return html`<div class="infoBox">
315
+ <div>
316
+ <div>
317
+ <div class="label">
318
+ ${this.translateKey("invoice@@payment.terms")}
319
+ </div>
320
+ <span>
321
+ ${this.translateKey("invoice@@payment.terms.direct")}
322
+ ${new Intl.DateTimeFormat(this.documentSettings.languageCode, {
323
+ dateStyle: this.documentSettings.dateStyle,
324
+ }).format(
325
+ new Date(this.letterData.date).setDate(
326
+ new Date(this.letterData.date).getDate() +
327
+ this.letterData?.dueInDays
328
+ )
329
+ )}
330
+ </span>
331
+ </div>
332
+ </div>
333
+ </div>`;
334
+ }
335
+
336
+ private renderPaymentInfo(): TemplateResult {
337
+ const bic = this.letterData?.from.sepaConnection.bic;
338
+ const name = this.letterData?.from.name;
339
+ const iban = this.letterData?.from.sepaConnection.iban;
340
+ const currency = this.letterData?.currency;
341
+ const totalGross = this.getTotalGross();
342
+ const reference = this.letterData?.id;
343
+
344
+ return html`<div class="infoBox">
345
+ <div>
346
+ <div>
347
+ <div class="label">${this.translateKey("invoice@@payment.qr")}</div>
348
+ <span> ${this.translateKey("invoice@@payment.qr.description")} </span>
349
+ </div>
350
+ <dedocument-paymentcode
351
+ bic="${bic}"
352
+ name="${name}"
353
+ iban="${iban}"
354
+ currency="${currency}"
355
+ totalGross="${totalGross}"
356
+ reference="${reference}"
357
+ />
358
+ </div>
359
+ </div>`;
360
+ }
361
+
362
+ private renderReferencedContract(): TemplateResult {
363
+ return null;
364
+ // return this.documentSettings.enableInvoiceContractRefSection &&
365
+ // this.invoiceData?.content?.contractData?.contractDate
366
+ // ? html`
367
+ // <div class="infoBox">
368
+ // <div class="label">
369
+ // ${this.translateKey("invoice@@referencedContract")}
370
+ // </div>
371
+ // ${this.translateKey("invoice@@referencedContract.text")}
372
+ // ${new Intl.DateTimeFormat(this.documentSettings.languageCode, {
373
+ // dateStyle: this.documentSettings.dateStyle,
374
+ // }).format(
375
+ // new Date(this.invoiceData?.content.contractData.contractDate)
376
+ // )}.
377
+ // </div>
378
+ // `
379
+ // : null;
380
+ }
381
+
202
382
  public async attachInvoiceDom() {
203
383
  const contentNodes = await this.getContentNodes();
204
384
  render(
205
385
  html`
206
- <style>
207
- .grid {
208
- display: grid;
209
- grid-template-columns: 40px auto 60px 60px 84px 84px 46px;
210
- }
211
- .topLine {
212
- margin-top: 5px;
213
- background: #e7e7e7;
214
- font-weight: bold;
215
- }
216
- .lineItem {
217
- font-size: 12px;
218
- padding: 5px;
219
- border-right: 1px dashed #ccc;
220
- }
221
-
222
- .lineItem.rightAlign {
223
- text-align: right;
224
- }
225
-
226
- .invoiceLine {
227
- border-bottom: 1px dotted #ccc;
228
- }
229
-
230
- .sums {
231
- margin-top: 5px;
232
- font-size: 12px;
233
- padding-left: 50%;
234
- }
235
-
236
- .sums .sumline {
237
- margin-top: 3px;
238
- display: grid;
239
- grid-template-columns: auto 90px;
240
- }
241
-
242
- .sums .sumline .label {
243
- padding: 2px 5px;
244
- border-right: 1px solid #ccc;
245
- text-align: right;
246
- font-weight: bold;
247
- }
248
-
249
- .sums .sumline .value {
250
- padding: 2px 5px;
251
- font-weight: bold;
252
- }
253
-
254
- .divider {
255
- margin-top: 8px;
256
- border-top: 1px dotted #ccc;
257
- }
258
-
259
- .taxNote {
260
- font-size: 12px;
261
- padding: 4px;
262
- background: #eeeeeb;
263
- text-align: center;
264
- }
265
-
266
- .infoBox {
267
- border-radius: 7px;
268
- border: 1px solid #ddd;
269
- border-left: 3px solid #c5e1a5;
270
- padding: 8px;
271
- margin-top: 16px;
272
- line-height: 1.4em;
273
- font-size: 16px;
274
- }
275
-
276
- .infoBox .label {
277
- padding-bottom: 2px;
278
- font-size: 12px;
279
- font-weight: bold;
280
- }
281
-
282
- .paymentCode {
283
- text-align: center;
284
- border-left: 2px solid #666;
285
- }
286
- </style>
287
- <div>We hereby invoice products and services provided to you by Lossless GmbH:</div>
386
+ <div>${this.translateKey("invoice@@introStatement")}</div>
288
387
  <div class="grid topLine dataHeader">
289
- <div class="lineItem rightAlign">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'itemPos', 'Item Pos.')}</div>
290
- <div class="lineItem">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'description', 'Description')}</div>
291
- <div class="lineItem rightAlign">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'quantity', 'Quantity')}</div>
292
- <div class="lineItem">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'unitType', 'Unit Type')}</div>
293
- <div class="lineItem rightAlign">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'unitNetPrice', 'Unit Net Price')}</div>
294
- <div class="lineItem rightAlign">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'totalNetPrice', 'Total Net Price')}</div>
295
- <div class="lineItem rightAlign">${plugins.shared.translation.translate(this.documentSettings.languageCode, 'vatShort', 'VAT')}</div>
388
+ <div class="lineItem rightAlign">
389
+ ${this.translateKey("invoice@@item.position")}
390
+ </div>
391
+ <div class="lineItem">
392
+ ${this.translateKey("invoice@@description")}
393
+ </div>
394
+ <div class="lineItem rightAlign">
395
+ ${this.translateKey("invoice@@quantity")}
396
+ </div>
397
+ <div class="lineItem">${this.translateKey("invoice@@unit.type")}</div>
398
+ <div class="lineItem rightAlign">
399
+ ${this.translateKey("invoice@@price.unit.net")}
400
+ </div>
401
+ <div class="lineItem rightAlign">
402
+ ${this.translateKey("invoice@@vat.short")}
403
+ </div>
404
+ <div class="lineItem rightAlign">
405
+ ${this.translateKey("invoice@@price.total.net")}
406
+ </div>
296
407
  </div>
297
- ${(() => {
298
- let counter = 1;
299
- return this.letterData?.content.invoiceData?.items?.map(
300
- (invoiceItem) => html`
301
- <div class="grid invoiceLine needsDataHeader">
302
- <div class="lineItem rightAlign">${counter++}</div>
303
- <div class="lineItem">${invoiceItem.name}</div>
304
- <div class="lineItem rightAlign">${invoiceItem.unitQuantity}</div>
305
- <div class="lineItem">${invoiceItem.unitType}</div>
306
- <div class="lineItem rightAlign">${invoiceItem.unitNetPrice} ${this.letterData?.content.invoiceData.currency}</div>
307
- <div class="lineItem rightAlign">
308
- ${invoiceItem.unitQuantity * invoiceItem.unitNetPrice} ${this.letterData?.content.invoiceData.currency}
309
- </div>
310
- <div class="lineItem rightAlign">
311
- ${invoiceItem.vatPercentage}%
312
- </div>
408
+ ${this.letterData?.items?.map(
409
+ (invoiceItem, index) => html`
410
+ <div class="grid needsDataHeader">
411
+ <div class="lineItem rightAlign">${index + 1}</div>
412
+ <div class="lineItem">${invoiceItem.name}</div>
413
+ <div class="lineItem rightAlign">${invoiceItem.unitQuantity}</div>
414
+ <div class="lineItem">${invoiceItem.unitType}</div>
415
+ <div class="lineItem rightAlign">
416
+ ${this.formatPrice(invoiceItem.unitNetPrice)}
417
+ </div>
418
+ <div class="lineItem rightAlign">
419
+ ${invoiceItem.vatPercentage}%
313
420
  </div>
314
- `
315
- );
316
- })()}
421
+ <div class="lineItem rightAlign">
422
+ ${this.formatPrice(
423
+ invoiceItem.unitQuantity * invoiceItem.unitNetPrice
424
+ )}
425
+ </div>
426
+ </div>
427
+ `
428
+ )}
317
429
  <div class="sums">
318
430
  <div class="sumline">
319
- <div class="label">Total net</div>
320
- <div class="value">${this.getTotalNet()} EUR</div>
431
+ <div class="label">
432
+ ${this.translateKey("invoice@@sum.total.net")}
433
+ </div>
434
+ <div class="value value--total rightAlign">
435
+ ${this.formatPrice(this.getTotalNet())}
436
+ </div>
321
437
  </div>
322
438
  ${this.getVatGroups().map((vatGroupArg) => {
323
- let itemNumbers = '';
324
- let first = true;
325
- for (const item of vatGroupArg.items) {
326
- const itemIndex = this.letterData.content.invoiceData.items.indexOf(item);
327
- itemNumbers += `${first ? '' : ', '}${itemIndex + 1}`;
328
- first = false;
329
- }
439
+ let itemNumbers = vatGroupArg.items
440
+ .map((item) => this.letterData.items.indexOf(item) + 1)
441
+ .join(", ");
330
442
  return html`
331
443
  <div class="sumline">
332
444
  <div class="label">
333
- Vat ${vatGroupArg.vatPercentage}%
334
- ${this.documentSettings.vatGroupPositions ? html`
335
- <br /><span style="font-weight: normal">(on item positions: ${itemNumbers})</span>
336
- ` : html``}
445
+ ${this.translateKey("vat.short")}
446
+ ${vatGroupArg.vatPercentage}%
447
+ ${this.documentSettings.vatGroupPositions
448
+ ? html`
449
+ <br /><span style="font-weight: normal"
450
+ >(${this.translateKey("invoice@@vat.position")}:
451
+ ${itemNumbers})</span
452
+ >
453
+ `
454
+ : html``}
455
+ </div>
456
+ <div class="value rightAlign">
457
+ ${this.formatPrice(vatGroupArg.vatAmountSum)}
337
458
  </div>
338
- <div class="value">${vatGroupArg.vatAmountSum} EUR</div>
339
459
  </div>
340
460
  `;
341
461
  })}
342
462
  <div class="sumline">
343
- <div class="label">Total gross</div>
344
- <div class="value">${this.getTotalGross()} EUR</div>
463
+ <div class="label">${this.translateKey("invoice@@totalGross")}</div>
464
+ <div class="value value--total rightAlign">
465
+ ${this.formatPrice(this.getTotalGross())}
466
+ </div>
345
467
  </div>
346
468
  </div>
347
469
  <div class="divider"></div>
348
- ${this.letterData?.content.invoiceData.reverseCharge
349
- ? html`
350
- <div class="taxNote">
351
- ${plugins.shared.translation.translate(this.documentSettings.languageCode, 'reverseVatNote', 'VAT arises on a reverse charge basis and is payable by the customer.')}
352
- </div>
353
- `
470
+
471
+ ${this.letterData?.reverseCharge
472
+ ? html`<div class="taxNote">
473
+ ${this.translateKey("invoice@@vat.reverseCharge.note")}
474
+ </div>`
354
475
  : ``}
355
- <div class="infoBox">
356
- <div class="label">Payment Terms:</div>
357
- Payment is due within 30 days starting from the reception of this invoice. Please use the
358
- following SEPA details:
359
- <br /><br />
360
- Beneficiary: ${this.letterData?.from.name}<br />
361
- IBAN: ${this.letterData?.from?.sepaConnection?.iban}<br />
362
- BIC: ${this.letterData?.from?.sepaConnection?.bic}<br />
363
- Description: ${this.letterData?.content.invoiceData?.id}<br />
364
- Amount: ${this.getTotalGross()} ${this.letterData?.content.invoiceData.currency}
365
- </div>
366
- ${this.letterData?.content?.contractData?.contractDate
367
- ? html`
368
- <div class="infoBox">
369
- <div class="label">Referenced contract:</div>
370
- This invoice is adhering to agreements made by contract between the parties on
371
- ${plugins.smarttime.ExtendedDate.fromMillis(this.letterData?.content.contractData.contractDate).format('MMMM D, YYYY')}.
372
- </div>
373
- `
374
- : html``}
375
- <div class="infoBox paymentCode">
376
- <div class="label">Sepa Payment Code:</div>
377
- </div>
476
+
477
+ <!-- REFERENCED CONTRACT -->
478
+ ${this.renderReferencedContract()}
479
+
480
+ <!-- PAYMENT TERMS -->
481
+ ${this.renderPaymentTerms()}
482
+
483
+ <!-- PAYMENT INFO -->
484
+ ${this.renderPaymentInfo()}
378
485
  `,
379
486
  contentNodes.currentContent
380
487
  );
381
- const canvas = document.createElement('canvas');
382
- plugins.qrcode.toCanvas(
383
- canvas,
384
- `BCD
385
- 001
386
- 1
387
- SCT
388
- ${this.letterData.content.invoiceData.billedBy.sepaConnection.bic}
389
- ${this.letterData.content.invoiceData.billedBy.name}
390
- ${this.letterData.content.invoiceData.billedBy.sepaConnection.iban}
391
- EUR${this.getTotalGross()}
392
- CHAR
393
- ${this.letterData.content.invoiceData.id}
394
- ${this.letterData.content.invoiceData.id}
395
- EPC QR Code`,
396
- (error) => {
397
- if (error) console.error(error);
398
- }
399
- );
400
- contentNodes.currentContent.querySelector('.paymentCode').append(canvas);
401
488
  }
402
489
  }
@@ -1,7 +1,10 @@
1
- import * as plugins from '../plugins.js';
1
+ import * as plugins from "../plugins.js";
2
2
 
3
- import { html } from '@design.estate/dees-element';
3
+ import { html } from "@design.estate/dees-element";
4
4
 
5
5
  export const demoFunc = () => html`
6
- <dedocument-dedocument .format="${'a4'}" .letterData=${plugins.shared.demoLetter}></dedocument-dedocument>
7
- `;
6
+ <dedocument-dedocument
7
+ .format="${"a4"}"
8
+ .letterData=${plugins.shared.demoLetter}
9
+ ></dedocument-dedocument>
10
+ `;