{"files": {"main.py": "from core import run\nfrom policy import POLICY\ndef evaluate(payload):\n    return run(payload, POLICY)\n", "policy.py": "POLICY = {\n    'currency': 'CAD',\n    'rounding': 'invoice',\n    'min_invoice_cents': 25,\n    'duplicate_event': 'last',\n    'refunds_first': False,\n    'void_is_tombstone': False,\n    'inclusive_limit': False,\n    'max_refund_age_days': 45,\n    'fee_refundable': False,\n    'refund_overflow': 'reject',\n    'order': 'created',\n    'status_case': 'upper',\n}\n", "helpers.py": "from decimal import Decimal, ROUND_HALF_UP\n\ndef to_cents(s):\n    return (Decimal(str(s)) * 100)\n\ndef rnd(d):\n    return int(d.quantize(Decimal(1), rounding=ROUND_HALF_UP))\n\ndef dedupe(events, mode):\n    d = {}\n    for e in events:\n        k = e.get('eid')\n        if k in d:\n            if mode == 'last':\n                d[k] = e\n        else:\n            d[k] = e\n    return list(d.values())\n", "core.py": "from helpers import to_cents, rnd, dedupe\n\ndef run(payload, policy):\n    if not payload:\n        return {'invoices': []}\n    if isinstance(payload, dict):\n        invs = payload.get('invoices') or []\n    else:\n        invs = payload\n    out = []\n    for inv in invs:\n        if inv.get('currency') != policy['currency']:\n            continue\n        created = inv['created']\n        lines = [to_cents(x) for x in inv.get('lines', [])]\n        if policy['rounding'] == 'per_line':\n            principal = sum(rnd(x) for x in lines)\n        else:\n            principal = rnd(sum(lines)) if lines else 0\n        fee = int(inv.get('fee_cents', 0))\n        charge = principal + fee\n        if charge < policy['min_invoice_cents']:\n            continue\n        events = dedupe(list(inv.get('events', [])), policy['duplicate_event'])\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        ceiling = principal + fee if policy['fee_refundable'] else principal\n        active = True\n        dead = False\n        refunded = 0\n        for e in events:\n            k = e['kind']\n            if k == 'void':\n                active = False\n                if policy['void_is_tombstone']:\n                    dead = True\n            elif k == 'restore':\n                if not (policy['void_is_tombstone'] and dead):\n                    active = True\n            elif k == 'refund':\n                if not active:\n                    continue\n                age = e['day'] - created\n                lim = policy['max_refund_age_days']\n                if age < 0 or not (age < lim or (policy['inclusive_limit'] and age == lim)):\n                    continue\n                amt = int(e['cents'])\n                room = ceiling - refunded\n                if amt > room:\n                    if policy['refund_overflow'] == 'cap':\n                        amt = max(room, 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        case = policy['status_case']\n        st = st.upper() if case == 'upper' else st.lower() if case == 'lower' else st.capitalize() if case == 'title' else st\n        out.append({'id': inv['id'], 'charge': charge, 'refunded': refunded, 'balance': charge - refunded, 'status': st, '_c': created})\n    if policy['order'] == 'created':\n        out.sort(key=lambda r: (r['_c'], r['id']))\n    else:\n        out.sort(key=lambda r: r['id'])\n    for r in out:\n        del r['_c']\n    return {'invoices': out}\n"}}