payload-clienthub 0.0.1
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/README.md +90 -0
- package/dist/components/invoice-pdf.d.ts +60 -0
- package/dist/components/invoice-pdf.d.ts.map +1 -0
- package/dist/components/invoice-pdf.js +254 -0
- package/dist/components/invoice-pdf.js.map +1 -0
- package/dist/components/swiss-qr-bill.d.ts +74 -0
- package/dist/components/swiss-qr-bill.d.ts.map +1 -0
- package/dist/components/swiss-qr-bill.js +326 -0
- package/dist/components/swiss-qr-bill.js.map +1 -0
- package/dist/const.d.ts +12 -0
- package/dist/const.d.ts.map +1 -0
- package/dist/const.js +12 -0
- package/dist/const.js.map +1 -0
- package/dist/endpoints/process-all-clients.d.ts +4 -0
- package/dist/endpoints/process-all-clients.d.ts.map +1 -0
- package/dist/endpoints/process-all-clients.js +55 -0
- package/dist/endpoints/process-all-clients.js.map +1 -0
- package/dist/entities.d.ts +16 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +425 -0
- package/dist/entities.js.map +1 -0
- package/dist/exports/client.d.ts +2 -0
- package/dist/exports/client.d.ts.map +1 -0
- package/dist/exports/client.js +2 -0
- package/dist/exports/client.js.map +1 -0
- package/dist/exports/rsc.d.ts +2 -0
- package/dist/exports/rsc.d.ts.map +1 -0
- package/dist/exports/rsc.js +2 -0
- package/dist/exports/rsc.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/payload-types.d.ts +459 -0
- package/dist/payload-types.d.ts.map +1 -0
- package/dist/translations.d.ts +183 -0
- package/dist/translations.d.ts.map +1 -0
- package/dist/translations.js +242 -0
- package/dist/translations.js.map +1 -0
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/authentication.d.ts +3 -0
- package/dist/utils/authentication.d.ts.map +1 -0
- package/dist/utils/authentication.js +5 -0
- package/dist/utils/authentication.js.map +1 -0
- package/dist/utils/process-client-invoice.d.ts +13 -0
- package/dist/utils/process-client-invoice.d.ts.map +1 -0
- package/dist/utils/process-client-invoice.js +193 -0
- package/dist/utils/process-client-invoice.js.map +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# payload-clienthub
|
|
2
|
+
|
|
3
|
+
Automatic monthly invoicing with PDF generation, Swiss QR Bill support, and multi-language email delivery for Payload CMS.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/payload-clienthub)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
payload-clienthub adds a full invoicing workflow to Payload -- clients, services, and invoices are managed as collections. Recurring services are automatically detected when due, rendered as localized PDF invoices (with Swiss QR Bill support), and emailed to each client. A single endpoint processes all clients at once, so you can wire it up to a scheduler and forget about it.
|
|
11
|
+
|
|
12
|
+
**Features**
|
|
13
|
+
|
|
14
|
+
- **Client & service management** -- track clients, contacts, and one-time/monthly/yearly services.
|
|
15
|
+
- **PDF invoices** -- generated with itemized line items, company branding, and Swiss QR Bill payment slips for CH-based companies.
|
|
16
|
+
- **Multi-language** -- invoices and emails are localized in DE, FR, IT, and EN.
|
|
17
|
+
- **Batch endpoint** -- one endpoint processes all clients at once; authenticate with a shared secret to call it from any scheduler.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
pnpm add payload-clienthub
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// payload.config.ts
|
|
29
|
+
import { buildConfig } from 'payload';
|
|
30
|
+
import { clienthubPlugin } from 'payload-clienthub';
|
|
31
|
+
|
|
32
|
+
export default buildConfig({
|
|
33
|
+
// ...
|
|
34
|
+
plugins: [
|
|
35
|
+
clienthubPlugin({
|
|
36
|
+
cronSecret: process.env.CRON_SECRET!,
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Trigger invoice generation for all clients by calling the batch endpoint (e.g. from a monthly scheduler):
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
curl -H "Authorization: Bearer $CRON_SECRET" \
|
|
46
|
+
https://your-app.com/api/plugin-invoices/process-all-clients
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Options
|
|
50
|
+
|
|
51
|
+
| Option | Type | Default | Description |
|
|
52
|
+
|--------|------|---------|-------------|
|
|
53
|
+
| `cronSecret` | `string` | — | Required. Shared secret used to authenticate batch requests via the `Authorization: Bearer` header. |
|
|
54
|
+
| `clientsCollectionSlug` | `CollectionSlug` | `'clients'` | Slug for the auto-created clients collection. |
|
|
55
|
+
| `servicesCollectionSlug` | `CollectionSlug` | `'services'` | Slug for the auto-created services collection. |
|
|
56
|
+
| `invoicesCollectionSlug` | `CollectionSlug` | `'invoices'` | Slug for the auto-created invoices collection. |
|
|
57
|
+
| `invoicePdfsCollectionSlug` | `CollectionSlug` | `'invoice-pdfs'` | Slug for the auto-created invoice PDFs upload collection. |
|
|
58
|
+
| `onError` | `(error: Error, context: { operation: string; metadata?: Record<string, unknown> }) => void` | `console.error` | Custom error handler called when PDF generation or email delivery fails. |
|
|
59
|
+
|
|
60
|
+
## Contributing
|
|
61
|
+
|
|
62
|
+
This plugin lives in the [payload-plugins](https://github.com/davincicoding-org/payload-plugins) monorepo.
|
|
63
|
+
|
|
64
|
+
### Development
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
pnpm install
|
|
68
|
+
|
|
69
|
+
# watch this plugin for changes
|
|
70
|
+
pnpm --filter payload-clienthub dev
|
|
71
|
+
|
|
72
|
+
# run the Payload dev app (in a second terminal)
|
|
73
|
+
pnpm --filter sandbox dev
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The `sandbox/` directory is a Next.js + Payload app that imports plugins via `workspace:*` — use it to test changes locally.
|
|
77
|
+
|
|
78
|
+
### Code quality
|
|
79
|
+
|
|
80
|
+
- **Formatting & linting** — handled by [Biome](https://biomejs.dev/), enforced on commit via husky + lint-staged.
|
|
81
|
+
- **Commits** — must follow [Conventional Commits](https://www.conventionalcommits.org/) with a valid scope (e.g. `fix(payload-clienthub): ...`).
|
|
82
|
+
- **Changesets** — please include a [changeset](https://github.com/changesets/changesets) in your PR by running `pnpm release`.
|
|
83
|
+
|
|
84
|
+
### Issues & PRs
|
|
85
|
+
|
|
86
|
+
Bug reports and feature requests are welcome — [open an issue](https://github.com/davincicoding-org/payload-plugins/issues).
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { SwissQRBillLabels } from './swiss-qr-bill';
|
|
2
|
+
export interface InvoicePdfData {
|
|
3
|
+
invoiceNumber: string;
|
|
4
|
+
date: string;
|
|
5
|
+
paymentTerms: string;
|
|
6
|
+
client: {
|
|
7
|
+
name: string;
|
|
8
|
+
address: string;
|
|
9
|
+
zip: string;
|
|
10
|
+
city: string;
|
|
11
|
+
country: string;
|
|
12
|
+
};
|
|
13
|
+
company: {
|
|
14
|
+
name: string;
|
|
15
|
+
address: string;
|
|
16
|
+
zip: string;
|
|
17
|
+
city: string;
|
|
18
|
+
country: string;
|
|
19
|
+
website: string;
|
|
20
|
+
uid: string;
|
|
21
|
+
contact: {
|
|
22
|
+
name: string;
|
|
23
|
+
email: string;
|
|
24
|
+
phone: string;
|
|
25
|
+
};
|
|
26
|
+
bank: {
|
|
27
|
+
name: string;
|
|
28
|
+
iban: string;
|
|
29
|
+
bic: string;
|
|
30
|
+
};
|
|
31
|
+
logo: string | undefined | null;
|
|
32
|
+
};
|
|
33
|
+
items: Array<{
|
|
34
|
+
description: string;
|
|
35
|
+
cost: number;
|
|
36
|
+
}>;
|
|
37
|
+
total: number;
|
|
38
|
+
/** Reference number for QR Bill (optional) */
|
|
39
|
+
reference?: string;
|
|
40
|
+
/** Message for QR Bill (optional) */
|
|
41
|
+
message?: string;
|
|
42
|
+
/** Pre-translated labels */
|
|
43
|
+
labels: {
|
|
44
|
+
title: string;
|
|
45
|
+
invoiceNumber: string;
|
|
46
|
+
date: string;
|
|
47
|
+
paymentTerms: string;
|
|
48
|
+
greeting: string;
|
|
49
|
+
greetingBody: string;
|
|
50
|
+
tableService: string;
|
|
51
|
+
tableCost: string;
|
|
52
|
+
tableTotal: string;
|
|
53
|
+
footerCreditor: string;
|
|
54
|
+
footerContact: string;
|
|
55
|
+
footerBank: string;
|
|
56
|
+
qrBill: SwissQRBillLabels;
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export declare function generateInvoicePdf(data: InvoicePdfData): Promise<Buffer>;
|
|
60
|
+
//# sourceMappingURL=invoice-pdf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice-pdf.d.ts","sourceRoot":"","sources":["../../src/components/invoice-pdf.tsx"],"names":[],"mappings":"AAWA,OAAO,EAIL,KAAK,iBAAiB,EACvB,MAAM,iBAAiB,CAAC;AAEzB,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,EAAE;YACP,IAAI,EAAE,MAAM,CAAC;YACb,KAAK,EAAE,MAAM,CAAC;YACd,KAAK,EAAE,MAAM,CAAC;SACf,CAAC;QACF,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;YACb,IAAI,EAAE,MAAM,CAAC;YACb,GAAG,EAAE,MAAM,CAAC;SACb,CAAC;QACF,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAAC;KACjC,CAAC;IACF,KAAK,EAAE,KAAK,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,QAAQ,EAAE,MAAM,CAAC;QACjB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,iBAAiB,CAAC;KAC3B,CAAC;CACH;AAyHD,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,MAAM,CAAC,CA4CjB"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { jsx as t, jsxs as l } from "react/jsx-runtime";
|
|
2
|
+
import { StyleSheet as w, renderToBuffer as B, Document as C, Page as T, View as n, Image as x, Text as o, Link as f } from "@react-pdf/renderer";
|
|
3
|
+
import { createElement as D } from "react";
|
|
4
|
+
import { prepareSwissQRBill as R, SwissQRBill as S } from "./swiss-qr-bill.js";
|
|
5
|
+
const g = new Intl.NumberFormat("de-CH", {
|
|
6
|
+
style: "currency",
|
|
7
|
+
currency: "CHF"
|
|
8
|
+
});
|
|
9
|
+
function q({ data: r }) {
|
|
10
|
+
const {
|
|
11
|
+
invoiceNumber: d,
|
|
12
|
+
date: s,
|
|
13
|
+
paymentTerms: m,
|
|
14
|
+
client: a,
|
|
15
|
+
company: i,
|
|
16
|
+
items: b,
|
|
17
|
+
total: u,
|
|
18
|
+
qrBill: h,
|
|
19
|
+
labels: c
|
|
20
|
+
} = r;
|
|
21
|
+
return /* @__PURE__ */ t(C, { title: `${c.title} ${d}`, children: /* @__PURE__ */ l(T, { size: "A4", style: e.page, children: [
|
|
22
|
+
/* @__PURE__ */ l(n, { style: e.header, children: [
|
|
23
|
+
/* @__PURE__ */ l(n, { style: e.headerLeft, children: [
|
|
24
|
+
i.logo ? /* @__PURE__ */ t(x, { src: i.logo, style: e.logo }) : null,
|
|
25
|
+
/* @__PURE__ */ t(o, { style: e.title, children: c.title })
|
|
26
|
+
] }),
|
|
27
|
+
/* @__PURE__ */ l(n, { style: e.headerRight, children: [
|
|
28
|
+
/* @__PURE__ */ l(o, { style: e.headerRow, children: [
|
|
29
|
+
c.invoiceNumber,
|
|
30
|
+
": ",
|
|
31
|
+
d
|
|
32
|
+
] }),
|
|
33
|
+
/* @__PURE__ */ l(o, { style: e.headerRow, children: [
|
|
34
|
+
c.date,
|
|
35
|
+
": ",
|
|
36
|
+
s
|
|
37
|
+
] }),
|
|
38
|
+
/* @__PURE__ */ l(o, { style: e.headerRow, children: [
|
|
39
|
+
c.paymentTerms,
|
|
40
|
+
": ",
|
|
41
|
+
m
|
|
42
|
+
] })
|
|
43
|
+
] })
|
|
44
|
+
] }),
|
|
45
|
+
/* @__PURE__ */ l(n, { style: e.clientSection, children: [
|
|
46
|
+
/* @__PURE__ */ t(o, { style: e.clientName, children: a.name }),
|
|
47
|
+
/* @__PURE__ */ t(o, { children: a.address }),
|
|
48
|
+
/* @__PURE__ */ l(o, { children: [
|
|
49
|
+
a.zip,
|
|
50
|
+
" ",
|
|
51
|
+
a.city
|
|
52
|
+
] })
|
|
53
|
+
] }),
|
|
54
|
+
/* @__PURE__ */ l(n, { style: e.table, children: [
|
|
55
|
+
/* @__PURE__ */ l(n, { style: e.tableHeader, children: [
|
|
56
|
+
/* @__PURE__ */ t(o, { style: e.col1, children: "#" }),
|
|
57
|
+
/* @__PURE__ */ t(o, { style: e.col2, children: c.tableService }),
|
|
58
|
+
/* @__PURE__ */ t(o, { style: e.col3, children: c.tableCost })
|
|
59
|
+
] }),
|
|
60
|
+
b.map((y, p) => /* @__PURE__ */ l(n, { style: e.tableRow, children: [
|
|
61
|
+
/* @__PURE__ */ t(o, { style: e.col1, children: p + 1 }),
|
|
62
|
+
/* @__PURE__ */ t(o, { style: e.col2, children: y.description }),
|
|
63
|
+
/* @__PURE__ */ t(o, { style: e.col3, children: g.format(y.cost) })
|
|
64
|
+
] }, `${y.description}-${p}`)),
|
|
65
|
+
/* @__PURE__ */ l(n, { style: e.totalRow, children: [
|
|
66
|
+
/* @__PURE__ */ t(o, { style: e.col1 }),
|
|
67
|
+
/* @__PURE__ */ t(o, { style: e.col2, children: c.tableTotal }),
|
|
68
|
+
/* @__PURE__ */ t(o, { style: e.col3, children: g.format(u) })
|
|
69
|
+
] })
|
|
70
|
+
] }),
|
|
71
|
+
h ? /* @__PURE__ */ t(n, { style: e.qrBillContainer, children: /* @__PURE__ */ t(
|
|
72
|
+
S,
|
|
73
|
+
{
|
|
74
|
+
data: h.data,
|
|
75
|
+
labels: c.qrBill,
|
|
76
|
+
qrCodeDataUrl: h.qrCodeDataUrl
|
|
77
|
+
}
|
|
78
|
+
) }) : /* @__PURE__ */ l(n, { style: e.footer, children: [
|
|
79
|
+
/* @__PURE__ */ l(n, { style: e.footerCol, children: [
|
|
80
|
+
/* @__PURE__ */ t(o, { style: e.footerTitle, children: c.footerCreditor }),
|
|
81
|
+
/* @__PURE__ */ t(o, { children: i.name }),
|
|
82
|
+
/* @__PURE__ */ t(o, { children: i.address }),
|
|
83
|
+
/* @__PURE__ */ t(o, { children: i.uid }),
|
|
84
|
+
/* @__PURE__ */ t(f, { href: i.website, children: new URL(i.website).hostname })
|
|
85
|
+
] }),
|
|
86
|
+
/* @__PURE__ */ l(n, { style: e.footerCol, children: [
|
|
87
|
+
/* @__PURE__ */ t(o, { style: e.footerTitle, children: c.footerContact }),
|
|
88
|
+
/* @__PURE__ */ t(o, { children: i.contact.name }),
|
|
89
|
+
/* @__PURE__ */ t(o, { children: i.contact.phone }),
|
|
90
|
+
/* @__PURE__ */ t(f, { href: `mailto:${i.contact.email}`, children: i.contact.email })
|
|
91
|
+
] }),
|
|
92
|
+
/* @__PURE__ */ l(n, { style: e.footerCol, children: [
|
|
93
|
+
/* @__PURE__ */ t(o, { style: e.footerTitle, children: c.footerBank }),
|
|
94
|
+
/* @__PURE__ */ t(o, { children: i.bank.iban }),
|
|
95
|
+
/* @__PURE__ */ l(o, { children: [
|
|
96
|
+
i.bank.name,
|
|
97
|
+
" (",
|
|
98
|
+
i.bank.bic,
|
|
99
|
+
")"
|
|
100
|
+
] })
|
|
101
|
+
] })
|
|
102
|
+
] })
|
|
103
|
+
] }) });
|
|
104
|
+
}
|
|
105
|
+
async function $(r) {
|
|
106
|
+
let d = { ...r };
|
|
107
|
+
if (r.company.country === "CH") {
|
|
108
|
+
const m = {
|
|
109
|
+
creditor: {
|
|
110
|
+
iban: r.company.bank.iban,
|
|
111
|
+
name: r.company.name,
|
|
112
|
+
address: r.company.address.split(`
|
|
113
|
+
`)[0] ?? r.company.address,
|
|
114
|
+
zip: r.company.zip,
|
|
115
|
+
city: r.company.city,
|
|
116
|
+
country: r.company.country
|
|
117
|
+
},
|
|
118
|
+
amount: r.total,
|
|
119
|
+
currency: "CHF",
|
|
120
|
+
debtor: {
|
|
121
|
+
name: r.client.name,
|
|
122
|
+
address: r.client.address.split(`
|
|
123
|
+
`)[0] ?? r.client.address,
|
|
124
|
+
zip: r.client.zip,
|
|
125
|
+
city: r.client.city,
|
|
126
|
+
country: r.client.country
|
|
127
|
+
},
|
|
128
|
+
reference: r.reference,
|
|
129
|
+
message: r.message ?? `${r.labels.title} ${r.invoiceNumber}`
|
|
130
|
+
}, a = await R(m);
|
|
131
|
+
d = {
|
|
132
|
+
...r,
|
|
133
|
+
qrBill: {
|
|
134
|
+
data: a.data,
|
|
135
|
+
qrCodeDataUrl: a.qrCodeDataUrl
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const s = D(q, {
|
|
140
|
+
data: d
|
|
141
|
+
});
|
|
142
|
+
return B(
|
|
143
|
+
s
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
const e = w.create({
|
|
147
|
+
page: {
|
|
148
|
+
padding: 40,
|
|
149
|
+
fontSize: 10,
|
|
150
|
+
fontFamily: "Helvetica"
|
|
151
|
+
},
|
|
152
|
+
header: {
|
|
153
|
+
flexDirection: "row",
|
|
154
|
+
justifyContent: "space-between",
|
|
155
|
+
alignItems: "flex-start",
|
|
156
|
+
marginBottom: 40
|
|
157
|
+
},
|
|
158
|
+
headerLeft: {
|
|
159
|
+
flexDirection: "column"
|
|
160
|
+
},
|
|
161
|
+
logo: {
|
|
162
|
+
width: 140,
|
|
163
|
+
height: 12,
|
|
164
|
+
objectFit: "contain",
|
|
165
|
+
marginBottom: 8
|
|
166
|
+
},
|
|
167
|
+
title: {
|
|
168
|
+
fontSize: 24,
|
|
169
|
+
fontWeight: "bold",
|
|
170
|
+
marginTop: 4
|
|
171
|
+
},
|
|
172
|
+
headerRight: {
|
|
173
|
+
textAlign: "right"
|
|
174
|
+
},
|
|
175
|
+
headerRow: {
|
|
176
|
+
marginBottom: 4
|
|
177
|
+
},
|
|
178
|
+
clientSection: {
|
|
179
|
+
marginBottom: 24
|
|
180
|
+
},
|
|
181
|
+
clientName: {
|
|
182
|
+
fontSize: 12,
|
|
183
|
+
fontWeight: "bold",
|
|
184
|
+
marginBottom: 8
|
|
185
|
+
},
|
|
186
|
+
greeting: {
|
|
187
|
+
marginBottom: 24
|
|
188
|
+
},
|
|
189
|
+
table: {
|
|
190
|
+
marginTop: 16,
|
|
191
|
+
marginBottom: 24
|
|
192
|
+
},
|
|
193
|
+
tableHeader: {
|
|
194
|
+
flexDirection: "row",
|
|
195
|
+
borderBottomWidth: 1,
|
|
196
|
+
borderBottomColor: "#000",
|
|
197
|
+
paddingBottom: 8,
|
|
198
|
+
marginBottom: 8,
|
|
199
|
+
fontWeight: "bold"
|
|
200
|
+
},
|
|
201
|
+
tableRow: {
|
|
202
|
+
flexDirection: "row",
|
|
203
|
+
paddingVertical: 6,
|
|
204
|
+
borderBottomWidth: 0.5,
|
|
205
|
+
borderBottomColor: "#ccc"
|
|
206
|
+
},
|
|
207
|
+
col1: { width: "8%" },
|
|
208
|
+
col2: { width: "72%" },
|
|
209
|
+
col3: { width: "20%", textAlign: "right" },
|
|
210
|
+
totalRow: {
|
|
211
|
+
flexDirection: "row",
|
|
212
|
+
marginTop: 16,
|
|
213
|
+
paddingTop: 8,
|
|
214
|
+
borderTopWidth: 1,
|
|
215
|
+
borderTopColor: "#000",
|
|
216
|
+
fontWeight: "bold"
|
|
217
|
+
},
|
|
218
|
+
closing: {
|
|
219
|
+
marginTop: 32,
|
|
220
|
+
marginBottom: 16
|
|
221
|
+
},
|
|
222
|
+
footer: {
|
|
223
|
+
position: "absolute",
|
|
224
|
+
bottom: 40,
|
|
225
|
+
left: 40,
|
|
226
|
+
right: 40,
|
|
227
|
+
flexDirection: "row",
|
|
228
|
+
borderTopWidth: 1,
|
|
229
|
+
borderTopColor: "#ccc",
|
|
230
|
+
paddingTop: 16,
|
|
231
|
+
marginTop: 40
|
|
232
|
+
},
|
|
233
|
+
qrBillContainer: {
|
|
234
|
+
marginTop: "auto",
|
|
235
|
+
// Push to bottom if space available
|
|
236
|
+
marginLeft: -40,
|
|
237
|
+
// Compensate for page padding
|
|
238
|
+
marginRight: -40,
|
|
239
|
+
marginBottom: -40
|
|
240
|
+
},
|
|
241
|
+
footerCol: {
|
|
242
|
+
flex: 1
|
|
243
|
+
},
|
|
244
|
+
footerTitle: {
|
|
245
|
+
fontSize: 8,
|
|
246
|
+
textTransform: "uppercase",
|
|
247
|
+
marginBottom: 4,
|
|
248
|
+
color: "#666"
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
export {
|
|
252
|
+
$ as generateInvoicePdf
|
|
253
|
+
};
|
|
254
|
+
//# sourceMappingURL=invoice-pdf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice-pdf.js","sources":["../../src/components/invoice-pdf.tsx"],"sourcesContent":["import {\n Document,\n Image,\n Link,\n Page,\n renderToBuffer,\n StyleSheet,\n Text,\n View,\n} from '@react-pdf/renderer';\nimport { createElement } from 'react';\nimport {\n prepareSwissQRBill,\n SwissQRBill,\n type SwissQRBillData,\n type SwissQRBillLabels,\n} from './swiss-qr-bill';\n\nexport interface InvoicePdfData {\n invoiceNumber: string;\n date: string;\n paymentTerms: string;\n client: {\n name: string;\n address: string;\n zip: string;\n city: string;\n country: string;\n };\n company: {\n name: string;\n address: string;\n zip: string;\n city: string;\n country: string;\n website: string;\n uid: string;\n contact: {\n name: string;\n email: string;\n phone: string;\n };\n bank: {\n name: string;\n iban: string;\n bic: string;\n };\n logo: string | undefined | null;\n };\n items: Array<{\n description: string;\n cost: number;\n }>;\n total: number;\n /** Reference number for QR Bill (optional) */\n reference?: string;\n /** Message for QR Bill (optional) */\n message?: string;\n /** Pre-translated labels */\n labels: {\n title: string;\n invoiceNumber: string;\n date: string;\n paymentTerms: string;\n greeting: string;\n greetingBody: string;\n tableService: string;\n tableCost: string;\n tableTotal: string;\n footerCreditor: string;\n footerContact: string;\n footerBank: string;\n qrBill: SwissQRBillLabels;\n };\n}\n\n/** Internal data with pre-generated QR code */\ninterface InvoiceDocumentData extends InvoicePdfData {\n qrBill?: {\n data: SwissQRBillData;\n qrCodeDataUrl: string;\n };\n}\n\nconst currency = new Intl.NumberFormat('de-CH', {\n style: 'currency',\n currency: 'CHF',\n});\n\nfunction InvoiceDocument({ data }: { data: InvoiceDocumentData }) {\n const {\n invoiceNumber,\n date,\n paymentTerms,\n client,\n company,\n items,\n total,\n qrBill,\n labels,\n } = data;\n\n return (\n <Document title={`${labels.title} ${invoiceNumber}`}>\n <Page size=\"A4\" style={styles.page}>\n <View style={styles.header}>\n <View style={styles.headerLeft}>\n {company.logo ? (\n <Image src={company.logo} style={styles.logo} />\n ) : null}\n <Text style={styles.title}>{labels.title}</Text>\n </View>\n <View style={styles.headerRight}>\n <Text style={styles.headerRow}>\n {labels.invoiceNumber}: {invoiceNumber}\n </Text>\n <Text style={styles.headerRow}>\n {labels.date}: {date}\n </Text>\n <Text style={styles.headerRow}>\n {labels.paymentTerms}: {paymentTerms}\n </Text>\n </View>\n </View>\n\n <View style={styles.clientSection}>\n <Text style={styles.clientName}>{client.name}</Text>\n <Text>{client.address}</Text>\n <Text>\n {client.zip} {client.city}\n </Text>\n </View>\n\n <View style={styles.table}>\n <View style={styles.tableHeader}>\n <Text style={styles.col1}>#</Text>\n <Text style={styles.col2}>{labels.tableService}</Text>\n <Text style={styles.col3}>{labels.tableCost}</Text>\n </View>\n {items.map((item, index) => (\n <View key={`${item.description}-${index}`} style={styles.tableRow}>\n <Text style={styles.col1}>{index + 1}</Text>\n <Text style={styles.col2}>{item.description}</Text>\n <Text style={styles.col3}>{currency.format(item.cost)}</Text>\n </View>\n ))}\n <View style={styles.totalRow}>\n <Text style={styles.col1} />\n <Text style={styles.col2}>{labels.tableTotal}</Text>\n <Text style={styles.col3}>{currency.format(total)}</Text>\n </View>\n </View>\n\n {/* Swiss QR Bill or Legacy Footer */}\n {qrBill ? (\n <View style={styles.qrBillContainer}>\n <SwissQRBill\n data={qrBill.data}\n labels={labels.qrBill}\n qrCodeDataUrl={qrBill.qrCodeDataUrl}\n />\n </View>\n ) : (\n <View style={styles.footer}>\n <View style={styles.footerCol}>\n <Text style={styles.footerTitle}>{labels.footerCreditor}</Text>\n <Text>{company.name}</Text>\n <Text>{company.address}</Text>\n <Text>{company.uid}</Text>\n <Link href={company.website}>\n {new URL(company.website).hostname}\n </Link>\n </View>\n <View style={styles.footerCol}>\n <Text style={styles.footerTitle}>{labels.footerContact}</Text>\n <Text>{company.contact.name}</Text>\n <Text>{company.contact.phone}</Text>\n <Link href={`mailto:${company.contact.email}`}>\n {company.contact.email}\n </Link>\n </View>\n <View style={styles.footerCol}>\n <Text style={styles.footerTitle}>{labels.footerBank}</Text>\n <Text>{company.bank.iban}</Text>\n <Text>\n {company.bank.name} ({company.bank.bic})\n </Text>\n </View>\n </View>\n )}\n </Page>\n </Document>\n );\n}\n\nexport async function generateInvoicePdf(\n data: InvoicePdfData,\n): Promise<Buffer> {\n let documentData: InvoiceDocumentData = { ...data };\n\n // Prepare Swiss QR Bill if structured addresses are available and enabled\n if (data.company.country === 'CH') {\n const qrBillData: SwissQRBillData = {\n creditor: {\n iban: data.company.bank.iban,\n name: data.company.name,\n address: data.company.address.split('\\n')[0] ?? data.company.address,\n zip: data.company.zip,\n city: data.company.city,\n country: data.company.country,\n },\n amount: data.total,\n currency: 'CHF',\n debtor: {\n name: data.client.name,\n address: data.client.address.split('\\n')[0] ?? data.client.address,\n zip: data.client.zip,\n city: data.client.city,\n country: data.client.country,\n },\n reference: data.reference,\n message: data.message ?? `${data.labels.title} ${data.invoiceNumber}`,\n };\n\n const prepared = await prepareSwissQRBill(qrBillData);\n\n documentData = {\n ...data,\n qrBill: {\n data: prepared.data,\n qrCodeDataUrl: prepared.qrCodeDataUrl,\n },\n };\n }\n\n const documentElement = createElement(InvoiceDocument, {\n data: documentData,\n });\n return renderToBuffer(\n documentElement as Parameters<typeof renderToBuffer>[0],\n ) as Promise<Buffer>;\n}\n\nconst styles = StyleSheet.create({\n page: {\n padding: 40,\n fontSize: 10,\n fontFamily: 'Helvetica',\n },\n header: {\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n marginBottom: 40,\n },\n headerLeft: {\n flexDirection: 'column',\n },\n logo: {\n width: 140,\n height: 12,\n objectFit: 'contain',\n marginBottom: 8,\n },\n title: {\n fontSize: 24,\n fontWeight: 'bold',\n marginTop: 4,\n },\n headerRight: {\n textAlign: 'right',\n },\n headerRow: {\n marginBottom: 4,\n },\n clientSection: {\n marginBottom: 24,\n },\n clientName: {\n fontSize: 12,\n fontWeight: 'bold',\n marginBottom: 8,\n },\n greeting: {\n marginBottom: 24,\n },\n table: {\n marginTop: 16,\n marginBottom: 24,\n },\n tableHeader: {\n flexDirection: 'row',\n borderBottomWidth: 1,\n borderBottomColor: '#000',\n paddingBottom: 8,\n marginBottom: 8,\n fontWeight: 'bold',\n },\n tableRow: {\n flexDirection: 'row',\n paddingVertical: 6,\n borderBottomWidth: 0.5,\n borderBottomColor: '#ccc',\n },\n col1: { width: '8%' },\n col2: { width: '72%' },\n col3: { width: '20%', textAlign: 'right' },\n totalRow: {\n flexDirection: 'row',\n marginTop: 16,\n paddingTop: 8,\n borderTopWidth: 1,\n borderTopColor: '#000',\n fontWeight: 'bold',\n },\n closing: {\n marginTop: 32,\n marginBottom: 16,\n },\n footer: {\n position: 'absolute',\n bottom: 40,\n left: 40,\n right: 40,\n flexDirection: 'row',\n borderTopWidth: 1,\n borderTopColor: '#ccc',\n paddingTop: 16,\n marginTop: 40,\n },\n qrBillContainer: {\n marginTop: 'auto', // Push to bottom if space available\n marginLeft: -40, // Compensate for page padding\n marginRight: -40,\n marginBottom: -40,\n },\n footerCol: {\n flex: 1,\n },\n footerTitle: {\n fontSize: 8,\n textTransform: 'uppercase',\n marginBottom: 4,\n color: '#666',\n },\n});\n"],"names":["currency","InvoiceDocument","data","invoiceNumber","date","paymentTerms","client","company","items","total","qrBill","labels","jsx","Document","Page","styles","jsxs","View","Image","Text","item","index","SwissQRBill","Link","generateInvoicePdf","documentData","qrBillData","prepared","prepareSwissQRBill","documentElement","createElement","renderToBuffer","StyleSheet"],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export interface SwissQRBillData {
|
|
2
|
+
/** Creditor information */
|
|
3
|
+
creditor: {
|
|
4
|
+
/** IBAN or QR-IBAN (21 characters, CH/LI only) */
|
|
5
|
+
iban: string;
|
|
6
|
+
/** Name (max 70 characters) */
|
|
7
|
+
name: string;
|
|
8
|
+
/** Street and building number (max 70 characters) */
|
|
9
|
+
address: string;
|
|
10
|
+
/** Postal code (max 16 characters) */
|
|
11
|
+
zip: string;
|
|
12
|
+
/** City (max 35 characters) */
|
|
13
|
+
city: string;
|
|
14
|
+
/** Country code (2 characters, e.g., "CH") */
|
|
15
|
+
country: string;
|
|
16
|
+
};
|
|
17
|
+
/** Amount (optional, max 12 digits including decimals) */
|
|
18
|
+
amount?: number;
|
|
19
|
+
/** Currency: CHF or EUR */
|
|
20
|
+
currency: 'CHF' | 'EUR';
|
|
21
|
+
/** Debtor information (optional) */
|
|
22
|
+
debtor?: {
|
|
23
|
+
/** Name (max 70 characters) */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Street and building number (max 70 characters) */
|
|
26
|
+
address: string;
|
|
27
|
+
/** Postal code (max 16 characters) */
|
|
28
|
+
zip: string;
|
|
29
|
+
/** City (max 35 characters) */
|
|
30
|
+
city: string;
|
|
31
|
+
/** Country code (2 characters) */
|
|
32
|
+
country: string;
|
|
33
|
+
};
|
|
34
|
+
/** Reference number (QR reference or Creditor Reference, max 27 characters) */
|
|
35
|
+
reference?: string;
|
|
36
|
+
/** Additional information / message (max 140 characters) */
|
|
37
|
+
message?: string;
|
|
38
|
+
}
|
|
39
|
+
/** Pre-translated labels for Swiss QR Bill */
|
|
40
|
+
export interface SwissQRBillLabels {
|
|
41
|
+
paymentPart: string;
|
|
42
|
+
receipt: string;
|
|
43
|
+
account: string;
|
|
44
|
+
reference: string;
|
|
45
|
+
additionalInfo: string;
|
|
46
|
+
payableBy: string;
|
|
47
|
+
payableByBlank: string;
|
|
48
|
+
currency: string;
|
|
49
|
+
amount: string;
|
|
50
|
+
acceptancePoint: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Generate Swiss QR Code with Swiss Cross overlay as base64 data URL
|
|
54
|
+
*/
|
|
55
|
+
export declare function generateSwissQRCode(data: SwissQRBillData): Promise<string>;
|
|
56
|
+
export interface SwissQRBillProps {
|
|
57
|
+
data: SwissQRBillData;
|
|
58
|
+
qrCodeDataUrl: string;
|
|
59
|
+
labels: SwissQRBillLabels;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Swiss QR Bill component for react-pdf
|
|
63
|
+
* Flexible height - flows with document content
|
|
64
|
+
*/
|
|
65
|
+
export declare function SwissQRBill({ data, qrCodeDataUrl, labels }: SwissQRBillProps): import("react/jsx-runtime").JSX.Element;
|
|
66
|
+
/**
|
|
67
|
+
* Helper to prepare Swiss QR Bill data and generate QR code
|
|
68
|
+
* Call this before rendering to get the qrCodeDataUrl
|
|
69
|
+
*/
|
|
70
|
+
export declare function prepareSwissQRBill(data: SwissQRBillData): Promise<{
|
|
71
|
+
data: SwissQRBillData;
|
|
72
|
+
qrCodeDataUrl: string;
|
|
73
|
+
}>;
|
|
74
|
+
//# sourceMappingURL=swiss-qr-bill.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"swiss-qr-bill.d.ts","sourceRoot":"","sources":["../../src/components/swiss-qr-bill.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,2BAA2B;IAC3B,QAAQ,EAAE;QACR,kDAAkD;QAClD,IAAI,EAAE,MAAM,CAAC;QACb,+BAA+B;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,qDAAqD;QACrD,OAAO,EAAE,MAAM,CAAC;QAChB,sCAAsC;QACtC,GAAG,EAAE,MAAM,CAAC;QACZ,+BAA+B;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,8CAA8C;QAC9C,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2BAA2B;IAC3B,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAC;IACxB,oCAAoC;IACpC,MAAM,CAAC,EAAE;QACP,+BAA+B;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,qDAAqD;QACrD,OAAO,EAAE,MAAM,CAAC;QAChB,sCAAsC;QACtC,GAAG,EAAE,MAAM,CAAC;QACZ,+BAA+B;QAC/B,IAAI,EAAE,MAAM,CAAC;QACb,kCAAkC;QAClC,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,+EAA+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,8CAA8C;AAC9C,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,MAAM,CAAC;CACzB;AAgFD;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,MAAM,CAAC,CAejB;AAgMD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,gBAAgB,2CAkK5E;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,aAAa,EAAE,MAAM,CAAA;CAAE,CAAC,CAG3D"}
|