from typing import List, Sequence from .legal_retainer_drawdown_types import RetainerApplication, RetainerBill, RetainerDrawdown from .money_amount import Money, money def retainer_drawdown(on_account: Money, bills: Sequence[RetainerBill]) -> RetainerDrawdown: """Apply money on account to bills in the order given.""" currency = on_account.currency if on_account.minor < 0: raise ValueError("onAccount must not be negative, received %s" % (on_account.minor,)) left = on_account.minor applied = 0 outstanding = 0 lines: List[RetainerApplication] = [] for bill in bills: if bill.amount.currency != currency: raise ValueError("currency mismatch: %s and %s" % (currency, bill.amount.currency)) if bill.amount.minor < 0: raise ValueError('bill "%s" must not be negative, received %s' % (bill.reference, bill.amount.minor)) take = min(left, bill.amount.minor) left -= take applied += take outstanding += bill.amount.minor - take lines.append( RetainerApplication( reference=bill.reference, billed=bill.amount, applied=money(take, currency), outstanding=money(bill.amount.minor - take, currency), ) ) return RetainerDrawdown( bills=lines, applied=money(applied, currency), outstanding=money(outstanding, currency), balance=money(left, currency), )