diff --git a/templates/invoice-bold/invoice.html b/templates/invoice-bold/invoice.html
index 568fc41e..1685f856 100644
--- a/templates/invoice-bold/invoice.html
+++ b/templates/invoice-bold/invoice.html
@@ -75,7 +75,7 @@
{{ l.date }} |
{{ l.description }} |
{{ l.qty }} |
- {{ l.unit }} |
+ {{ unit_header }} |
{{ l.unit_price }} |
{{ l.vat }} |
{{ l.subtotal }} |
diff --git a/templates/invoice-classic/invoice.html b/templates/invoice-classic/invoice.html
index dd73b069..bd6babd7 100644
--- a/templates/invoice-classic/invoice.html
+++ b/templates/invoice-classic/invoice.html
@@ -68,7 +68,7 @@
{{ l.date }} |
{{ l.description }} |
{{ l.qty }} |
- {{ l.unit }} |
+ {{ unit_header }} |
{{ l.unit_price }} |
{{ l.vat }} |
{{ l.subtotal }} |
diff --git a/templates/invoice-minimal/invoice.html b/templates/invoice-minimal/invoice.html
index 0d145ee9..9ed0cd7e 100644
--- a/templates/invoice-minimal/invoice.html
+++ b/templates/invoice-minimal/invoice.html
@@ -77,7 +77,7 @@
{{ l.date }} |
{{ l.description }} |
{{ l.qty }} |
- {{ l.unit }} |
+ {{ unit_header }} |
{{ l.unit_price }} |
{{ l.vat }} |
{{ l.subtotal }} |
diff --git a/templates/invoice-modern/invoice.html b/templates/invoice-modern/invoice.html
index 07a7a9bd..4afde28d 100644
--- a/templates/invoice-modern/invoice.html
+++ b/templates/invoice-modern/invoice.html
@@ -76,7 +76,7 @@
{{ l.date }} |
{{ l.description }} |
{{ l.qty }} |
- {{ l.unit }} |
+ {{ unit_header }} |
{{ l.unit_price }} |
{{ l.vat }} |
{{ l.subtotal }} |
diff --git a/tuttle/rendering.py b/tuttle/rendering.py
index fab9f0b8..b9344c3a 100644
--- a/tuttle/rendering.py
+++ b/tuttle/rendering.py
@@ -227,11 +227,24 @@ def unit_label(raw_unit, quantity=None):
tpl = labels.get("reminder_n", "{n}. Payment Reminder")
reminder_title = tpl.format(n=n)
+ # Derive the column header from the contract's unit type so that the
+ # rendered invoice makes it explicit whether the quantity column refers
+ # to hours, days, or a fixed price — see issue #358.
+ if getattr(invoice.contract, "is_fixed_price", False):
+ unit_header = labels.get("fixed_price", "fixed price")
+ else:
+ contract_unit = getattr(invoice.contract, "unit", None)
+ if contract_unit is not None:
+ unit_header = unit_label(contract_unit.value, 2)
+ else:
+ unit_header = labels.get("unit", "Unit")
+
invoice_template = template_env.get_template("invoice.html")
html = invoice_template.render(
user=user,
invoice=invoice,
l=labels,
+ unit_header=unit_header,
is_reminder=is_reminder,
reminder_title=reminder_title,
notes=invoice.notes,