from dataclasses import dataclass from decimal import Decimal, ROUND_HALF_UP from .models import Invoice CENT = Decimal('0.01') def rounded(value: Decimal) -> Decimal: return value.quantize(CENT, rounding=ROUND_HALF_UP) def line_net(item) -> Decimal: return rounded(item.quantity * item.unit_price_net) @dataclass(frozen=True) class Totals: net_total: Decimal tax_total: Decimal gross_total: Decimal tax_by_rate: dict[Decimal, Decimal] basis_by_rate: dict[Decimal, Decimal] def compute_totals(inv: Invoice) -> Totals: bases = {} for item in inv.items: bases[item.tax_rate] = bases.get(item.tax_rate, Decimal(0)) + line_net(item) taxes = {rate: rounded(base * rate / 100) for rate, base in bases.items()} net = sum(bases.values(), Decimal(0)) tax = sum(taxes.values(), Decimal(0)) return Totals(net, tax, net + tax, taxes, bases)