29 lines
894 B
Python
29 lines
894 B
Python
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)
|