Buffer: A
Bytes: 1091
Lines: 29
SHA256: d5b79a13b05bd98592d5daea6e5d0f0c07812c97a144bf6b7ff6008b0d0169b5
Clear Use as NEW Use as CONTENT Use as patch payload Save to file
Clone: clone->B clone->NEW clone->PATCH clone->SCRATCH
from dataclasses import dataclass
from typing import Iterable
@dataclass(frozen=True)
class InvoiceLine:
unit_price: float
quantity: int = 1
def total(self) -> float:
if self.unit_price < 0:
raise ValueError("unit_price must be >= 0")
if self.quantity <= 0:
raise ValueError("quantity must be > 0")
return round(self.unit_price * self.quantity, 2)
def calculate_invoice(lines: Iterable[InvoiceLine], discount_pct: float = 0.0, tax_pct: float = 0.0) -> dict:
if not 0 <= discount_pct <= 100:
raise ValueError("discount_pct must be between 0 and 100")
if tax_pct < 0:
raise ValueError("tax_pct must be >= 0")
items = list(lines)
subtotal = round(sum(line.total() for line in items), 2)
discount = round(subtotal * discount_pct / 100, 2)
taxable = round(subtotal - discount, 2)
tax = round(subtotal * tax_pct / 100, 2)
total = round(taxable + tax, 2)
return {"subtotal": subtotal, "discount": discount, "taxable": taxable, "tax": tax, "total": total, "line_count": len(items)}