Skip to content

Commit 204619e

Browse files
invoice-pro:0.3.1 (#4802)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent 4e97b16 commit 204619e

58 files changed

Lines changed: 5405 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Leonie Ziechmann
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# invoice-pro
2+
3+
Modern Invoice Template for Typst
4+
5+
A professional, compliant, and automated invoice template for [Typst](https://typst.app). This package follows the German **DIN 5008** standard (Form A & B) and automates calculations, VAT handling, and payment details.
6+
7+
![Example Invoice](thumbnail.png)
8+
9+
## Features
10+
11+
- **Internationalization (i18n) (New in v0.3.0):** Built-in support for English and German out of the box, plus a highly flexible `locale` API to inject custom translations for any language.
12+
- **DIN 5008 Compliant:** Supports both Form A and Form B layouts natively via the flexible Theming API.
13+
- **Block-based API:** Clean, scoped, and declarative data structure using `#line-items`, `#item`, and `#bundle`—inspired by CeTZ, keeping your document clutter-free.
14+
- **Automatic Calculations:** Effortlessly handles line items, nested bundles, sub-totals, and calculates taxes automatically.
15+
- **EPC QR-Code (GiroCode):** Automatically generates a scannable banking QR code for quick and easy payments using banking apps.
16+
- **Advanced Modifiers:** Apply specific discounts, surcharges, and custom tax rates at the item, bundle, or global level.
17+
- **Highly Customizable:** Easy configuration of sender, recipient, payment goals, bank details, and visual themes to match your corporate identity.
18+
19+
## Documentation
20+
21+
For comprehensive guides, API references, theming instructions, and advanced examples, please visit our official documentation:
22+
23+
👉 **[Read the Full Documentation Here](https://leonieziechmann.github.io/invoice-pro/)**
24+
25+
## Getting Started
26+
27+
### Installation
28+
29+
Import the package at the top of your Typst file:
30+
31+
```typst
32+
#import "@preview/invoice-pro:0.3.1": *
33+
```
34+
35+
### Basic Usage
36+
37+
Here is an example of how to create an invoice using the new v0.3 API:
38+
39+
```typst
40+
#import "@preview/invoice-pro:0.3.1": *
41+
42+
#show: invoice.with(
43+
theme: themes.DIN-5008(form: "A"), // or form: "B"
44+
locale: locale.en-de,
45+
sender: (
46+
name: "Your Company / Name",
47+
address: "1 Example Street",
48+
city: "12345 Example City",
49+
),
50+
recipient: (
51+
name: "Customer Name",
52+
address: "5 Customer Street",
53+
city: "98765 Customer City",
54+
),
55+
invoice-nr: "2026-01",
56+
tax-nr: "123/456/789",
57+
)
58+
59+
// Add Invoice Items inside a scoped block
60+
#line-items[
61+
#item(
62+
[Consulting & Concept],
63+
price: 85.00,
64+
quantity: 5,
65+
unit: "hrs"
66+
)
67+
68+
#item(
69+
[Web Design Layout (Flat Rate)],
70+
price: 1200.00,
71+
)
72+
73+
#item(
74+
[Stock Licenses (Images)],
75+
price: 25.00,
76+
quantity: 4,
77+
)
78+
79+
#discount([Project Discount (Regular Customer)], amount: 10%)
80+
]
81+
82+
// Payment Terms
83+
#payment-goal(days: 14)
84+
85+
// Bank Details with QR Code
86+
#bank-details(
87+
bank: "Example Bank",
88+
iban: "DE07100202005821158846",
89+
bic: "EXAMPLEBIC",
90+
)
91+
92+
#signature()
93+
```
94+
95+
## API Stability
96+
97+
With the major refactoring introduced in version 0.2.0, the package structure is solidifying. Here is the current stability status of the various API components:
98+
99+
- **Invoice Header (`invoice` arguments):** **Mostly Stable**. The core invoice configuration is established. Future updates to the header will be non-breaking and will primarily consist of adding new optional fields.
100+
- **Data Model (`#line-items`, `#bundle`, `#item`):** **Stable**. The new block-based data model is considered almost finished and safe to use.
101+
- _Exception:_ The `unit` argument in `#item` and `#bundle` will change in a future release to strictly comply with the standardized unit formats and codes required for upcoming ZUGFeRD e-invoicing support.
102+
- **Theming (`theme`):** **Under Construction**. The theming engine is still evolving and will most likely experience breaking changes in the next updates as we refine customization capabilities.
103+
- **Localization (`locale`):** **Under Construction**. The localization and internationalization systems are actively being worked on and are subject to change.
104+
105+
## Dependencies
106+
107+
This template relies on these amazing packages:
108+
109+
- `letter-pro` for the DIN layout.
110+
- `sepay` for EPC-QR-Code generation.
111+
- `ibanator` for IBAN formatting.
112+
- `loom` for reactive document rendering.
113+
114+
**Acknowledgements:**
115+
116+
- Special thanks to [classy-german-invoice](https://github.com/erictapen/typst-invoice) by Kerstin Humm, which served as inspiration and provided the logic for the EPC-QR-Code implementation.
117+
118+
## License
119+
120+
MIT
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#import "../loom-wrapper.typ": loom, managed-motif
2+
#import "../utils/types.typ"
3+
#import "../utils/coercion.typ"
4+
5+
/// Defines and renders the bank account information for payments.
6+
///
7+
/// -> content
8+
#let bank-details(
9+
/// The name of the account holder. Defaults to the sender's name.
10+
/// -> auto | none | string
11+
name: auto,
12+
13+
/// The name of the banking institution.
14+
/// -> none | string
15+
bank: none,
16+
17+
/// The International Bank Account Number (IBAN).
18+
/// -> none | string
19+
iban: none,
20+
21+
/// The Bank Identifier Code (BIC/SWIFT).
22+
/// -> none | string
23+
bic: none,
24+
25+
/// The payment reference to be used by the customer.
26+
/// -> auto | none | string
27+
reference: auto,
28+
29+
/// The specific amount to be paid. If `auto`, it uses the document total.
30+
/// -> auto | none | decimal | float | int
31+
payment-amount: auto,
32+
33+
/// Whether to display the reference field in the output.
34+
/// -> bool
35+
show-reference: true,
36+
37+
/// Optional custom text to label the account holder field.
38+
/// -> auto
39+
account-holder-text: auto,
40+
41+
/// Configuration for a payment QR code (e.g., EPC-QR).
42+
/// -> dictionary
43+
qr-code: (:),
44+
) = {
45+
types.require(name, "bank-details::name", none, auto, str)
46+
types.require(bank, "bank-details::bank", none, str)
47+
types.require(iban, "bank-details::iban", none, str)
48+
types.require(bic, "bank-details::bic", none, str)
49+
50+
types.require(reference, "bank-details::reference", none, auto, str)
51+
types.require(
52+
payment-amount,
53+
"bank-details::payment-amount",
54+
none,
55+
auto,
56+
types.decimal-like,
57+
)
58+
59+
types.require(show-reference, "bank-details::show-reference", bool)
60+
61+
if name == none { name = "" }
62+
if iban == none { iban = "" }
63+
if bank == none { bank = "" }
64+
if bic == none { bic = "" }
65+
if payment-amount == none { payment-amount = 0 }
66+
if payment-amount != auto {
67+
payment-amount = coercion.to-decimal(payment-amount)
68+
}
69+
70+
managed-motif(
71+
"bank-details",
72+
scope: ctx => loom.mutator.batch(ctx, {
73+
import loom.mutator: *
74+
75+
derive("sender", "name", name, default: "")
76+
77+
put("reference", ctx.invoice-nr)
78+
derive("reference", reference)
79+
80+
nest("theme", {
81+
ensure("bank-details", (..) => panic(
82+
"theme::bank-details is not provided",
83+
))
84+
})
85+
86+
nest("global", {
87+
nest("total", {
88+
ensure("gross", 0)
89+
})
90+
})
91+
}),
92+
measure: (ctx, _) => {
93+
let data = (
94+
sender: (
95+
name: ctx.sender.name,
96+
bank: bank,
97+
iban: iban,
98+
bic: bic,
99+
),
100+
101+
qr-code: (
102+
size: qr-code.at("size", default: 5em),
103+
display: qr-code.at("display", default: true),
104+
),
105+
106+
reference: ctx.reference,
107+
show-reference: show-reference,
108+
payment-amount: if payment-amount == auto {
109+
ctx.global.total.gross
110+
} else {
111+
payment-amount
112+
},
113+
)
114+
115+
(none, data)
116+
},
117+
draw: (ctx, _, view, ..) => (ctx.theme.bank-details)(ctx, view),
118+
none,
119+
)
120+
}

0 commit comments

Comments
 (0)