{"files":{"main.py":"from core import run\nfrom policy import POLICY\ndef evaluate(payload):\n    return run(payload, POLICY)\n","core.py":"from decimal import Decimal, ROUND_HALF_UP\n\n\ndef _cents(s):\n    return (Decimal(s) * 100)\n\n\ndef _q(d):\n    return int(d.quantize(Decimal(1), rounding=ROUND_HALF_UP))\n\n\ndef _status_case(s, mode):\n    if mode == 'upper':\n        return s.upper()\n    if mode == 'title':\n        return s.title()\n    return s.lower()\n\n\ndef run(payload, policy):\n    out = []\n    invoices = (payload or {}).get('invoices') or []\n    for inv in invoices:\n        if inv['currency'] != policy['currency']:\n            continue\n        if policy['rounding'] == 'per_line':\n            principal = sum(_q(_cents(l)) for l in inv['lines'])\n        else:\n            principal = _q(sum((_cents(l) for l in inv['lines']), Decimal(0)))\n        fee = inv['fee_cents']\n        charge = principal + fee\n        if charge < policy['min_invoice_cents']:\n            continue\n        evs = {}\n        for e in inv['events']:\n            if e['eid'] in evs:\n                if policy['duplicate_event'] == 'last':\n                    evs[e['eid']] = e\n            else:\n                evs[e['eid']] = e\n        events = list(evs.values())\n        if policy['refunds_first']:\n            events = [e for e in events if e['kind'] == 'refund'] + [e for e in events if e['kind'] != 'refund']\n        active = True\n        tomb = False\n        refunded = 0\n        ceiling = charge if policy['fee_refundable'] else principal\n        for e in events:\n            k = e['kind']\n            if k == 'void':\n                active = False\n                if policy['void_is_tombstone']:\n                    tomb = True\n            elif k == 'restore':\n                if not tomb:\n                    active = True\n            elif k == 'refund':\n                if not active:\n                    continue\n                age = e['day'] - inv['created']\n                lim = policy['max_refund_age_days']\n                ok = age >= 0 and (age <= lim if policy['inclusive_limit'] else age < lim)\n                if not ok:\n                    continue\n                remaining = ceiling - refunded\n                amt = e['cents']\n                if amt > remaining:\n                    if policy['refund_overflow'] == 'cap':\n                        amt = max(remaining, 0)\n                    else:\n                        continue\n                refunded += amt\n        if not active:\n            st = 'void'\n        elif refunded == charge:\n            st = 'refunded'\n        else:\n            st = 'open'\n        out.append({'id': inv['id'], 'created': inv['created'], 'charge': charge, 'refunded': refunded,\n                    'balance': charge - refunded, 'status': _status_case(st, policy['status_case'])})\n    if policy['order'] == 'created':\n        out.sort(key=lambda x: (x['created'], x['id']))\n    else:\n        out.sort(key=lambda x: x['id'])\n    for o in out:\n        del o['created']\n    return {'invoices': out}\n","policy.py":"POLICY = {\"currency\": \"CAD\", \"duplicate_event\": \"last\", \"fee_refundable\": False, \"inclusive_limit\": False, \"max_refund_age_days\": 45, \"min_invoice_cents\": 25, \"order\": \"created\", \"refund_overflow\": \"reject\", \"refunds_first\": False, \"rounding\": \"invoice\", \"status_case\": \"upper\", \"void_is_tombstone\": False}\n","helpers.py":"# Optional pure helper functions.\n"}}