Laskutys is a template for making invoices satisfying (mostly) the VAT invoice requirements by the Finnish Tax Administration. Among other things, this template features:
- Finnish/English/Swedish translations
- VAT calculations by VAT base
- Optional bank barcode (fi. Pankkiviivakoodi)
- Optional EPC QR Code (European Payment Council’s Quick Response Code)
- Invoice number generation from date
- RF creditor reference (ISO 11649) generation from invoice number
- Customizable colors
[!NOTE] VAT-calculation might have rounding errors due to division. The errors are at most a few cents.
Usage
See API documentation for all arguments.
#import "@preview/laskutys:1.0.0": invoice
#let data = yaml("data.yaml")
#invoice(
/// Optional, defaults to today
date: datetime(year: 2025, month: 09, day: 30),
/// Optional logo, displayed as is
logo: image("logo.svg", height: 4em),
iban: "FI2112345600000785",
bic: "NDEAFIHH",
seller: (
name: "Yritys Oy",
business-id: "1234567-8",
address: [Talousosasto\ PL 12\ 00100 Helsinki],
),
/// Recipient can also have business-id
recipient: (
name: "Kuluttaja Nimi",
address: [Kotikatu 1\ 00100 Helsinki],
),
/// fi: Finnish
/// en: English (default)
/// sv: Swedish
lang: "fi",
footnotes: [Company Oy, Phone: +358 123 4567, Email: sales.person\@company.com],
data,
)
YAML data of items:
- description: Ruoka
quantity: 10
# Unit price including VAT
unit-price: "2"
vat-rate: "0.14"
- description: AA paristo
quantity: 2
unit-price: "1.99"
vat-rate: "0.255"
- description: Sanomalehti
quantity: 3
unit-price: "9.99"
vat-rate: "0.10"
- description: "!Phone"
quantity: 1
unit-price: "1000"
# \_ is non breaking space
- description: "Sijoituskulta, AVL\_43\_a\_§"
quantity: 3
unit-price: "10"
vat-rate: "0"
Output of the above code:
[!IMPORTANT] Pass
unit-price
andvat-rate
as string, so that they can be converted to decimal without errors. This avoids rounding errors due to imprecision of floating-point numbers.
The data can also be defined directly in Typst as an array:
#let data = (
(
description: "Apple",
quantity: 10,
unit-price: "2",
vat-rate: "0.14",
),
(
description: "Battery AA",
quantity: 2,
unit-price: "2",
vat-rate: "0.255",
),
(
description: "Item with default VAT",
quantity: 3,
unit-price: "10",
),
),
You can also use other loader functions if they can produce an array in the same format.
Documentation
Examples
Customize colors
#import "@preview/laskutys:1.0.0": DEFAULT-COLORS, invoice
#let data = yaml("data.yaml")
#invoice(
...
colors: (
..DEFAULT-COLORS
active: blue,
bg-passive: teal.lighten(85%),
passive: teal,
),
data,
)
[!TIP] The
DEFAULT-COLORS
is needed if you don’t want to override all colors. You can also override any other preset similarly.
See Typst documentation for more colors and API documentation for configurable colors. There are also some presets available, see Color presets.
Change language
Pass ISO 639 language code as lang
.
Supported languages are
en
: English (default)fi
: Finnishsv
: Swedish
#import "@preview/laskutys:1.0.0": invoice
#let data = yaml("data.yaml")
#invoice(
...
lang: "fi",
data,
)
Read configuration from file
Using spread syntax, configurations can also be read from a file. For instance, from a YAML file.
#import "@preview/laskutys:1.0.0": *
#let data = yaml("data.yaml")
#let config = yaml("config.yaml")
#invoice(
..config,
data,
)
YAML config file
iban: FI2112345600000785
bic: OKOYFIHH
seller:
name: Company Oy
business-id: 1234567-8
address: "Street 123\n01234 City"
recipient:
name: Recipient Name
address: "Street 123\n01234 City"
footnotes: "Company Oy, Phone: +358 123 4567, Email: sales.person@company.com"
[!NOTE]
date
andlogo
cannot be read from non-Typst file since Typst cannot convert them. Also, use quotes"
for string containing newline\n
or something that is converted incorrectly.
Automated invoice generation
Typst CLI can pass inputs to Typst file using
typst compile file.typ --input key1=val1`
The key value pairs can be accessed in Typst file using sys.inputs
as a dictionary.
#import "@preview/laskutys:1.0.0": *
#let data = yaml("data.yaml")
#let config = sys.inputs
#invoice(
..config,
data,
)
Since all values are strings, some preprocessing is required.
For example, the values can be JSON strings which can be parsed using json
.
Hide QR code or bank barcode
Set qrcode
or barcode
to false
:
...
#invoice(
...
qrcode: false,
barcode: false,
)
- Bank barcode supports only Finnish IBAN, so disable it if non-Finnish IBAN is used.
- EPC QR code supports non-Finnish IBAN [^epc_qr]
License
The project is licensed under the MIT-0 license. Licenses of libraries used in this project are listed in /licenses.
[^epc_qr]: European Payments Council, Quick Response Code: Guidelines to Enable Data Capture for the Initiation of a SEPA Credit Transfer, https://www.europeanpaymentscouncil.eu/document-library/guidance-documents/quick-response-code-guidelines-enable-data-capture-initiation