{"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\nfrom helpers import line_cents, dedup_events, ordered_events\n\ndef run(payload, policy):\n    if not payload or not isinstance(payload, dict):\n        return {\"invoices\": []}\n    invoices_in = payload.get(\"invoices\") or []\n    currency_want = policy.get(\"currency\")\n    min_cents = policy.get(\"min_invoice_cents\", 0)\n    rounding = policy.get(\"rounding\", \"invoice\")\n    fee_refundable = policy.get(\"fee_refundable\", False)\n    duplicate_event = policy.get(\"duplicate_event\", \"first\")\n    refunds_first = policy.get(\"refunds_first\", False)\n    void_is_tombstone = policy.get(\"void_is_tombstone\", False)\n    max_age = policy.get(\"max_refund_age_days\", 0)\n    inclusive = policy.get(\"inclusive_limit\", False)\n    overflow = policy.get(\"refund_overflow\", \"cap\")\n    order = policy.get(\"order\", \"id\")\n    status_case = policy.get(\"status_case\", \"lower\")\n    results = []\n    for inv in invoices_in:\n        if not isinstance(inv, dict):\n            continue\n        if inv.get(\"currency\") != currency_want:\n            continue\n        lines = inv.get(\"lines\") or []\n        fee = inv.get(\"fee_cents\", 0)\n        principal = line_cents(lines, rounding)\n        charge = principal + fee\n        if charge < min_cents:\n            continue\n        created = inv.get(\"created\")\n        events = inv.get(\"events\") or []\n        deduped = dedup_events(events, duplicate_event)\n        seq = ordered_events(deduped, refunds_first)\n        ceiling = principal + fee if fee_refundable else principal\n        refunded = 0\n        active = True\n        tombstoned = False\n        for ev in seq:\n            kind = ev.get(\"kind\")\n            if kind == \"void\":\n                active = False\n                if void_is_tombstone:\n                    tombstoned = True\n            elif kind == \"restore\":\n                if not tombstoned:\n                    active = True\n            elif kind == \"refund\":\n                if not active:\n                    continue\n                day = ev.get(\"day\")\n                try:\n                    age = day - created\n                except Exception:\n                    continue\n                if age < 0:\n                    continue\n                if inclusive:\n                    if age > max_age:\n                        continue\n                else:\n                    if age >= max_age:\n                        continue\n                cents = ev.get(\"cents\", 0)\n                remaining = ceiling - refunded\n                if remaining < 0:\n                    remaining = 0\n                if cents <= remaining:\n                    refunded += cents\n                else:\n                    if overflow == \"cap\":\n                        refunded += remaining\n                    else:\n                        continue\n        if not active:\n            status = \"void\"\n        elif refunded == charge:\n            status = \"refunded\"\n        else:\n            status = \"open\"\n        if status_case == \"upper\":\n            status = status.upper()\n        else:\n            status = status.lower()\n        results.append({\"id\": inv.get(\"id\"), \"charge\": charge, \"refunded\": refunded, \"balance\": charge - refunded, \"status\": status, \"_created\": created})\n    if order == \"created\":\n        results.sort(key=lambda x: (x[\"_created\"], x[\"id\"]))\n    else:\n        results.sort(key=lambda x: x[\"id\"])\n    out = [{\"id\": r[\"id\"], \"charge\": r[\"charge\"], \"refunded\": r[\"refunded\"], \"balance\": r[\"balance\"], \"status\": r[\"status\"]} for r in results]\n    return {\"invoices\": out}\n", "policy.py": "POLICY = {\"duplicate_event\": \"last\", \"inclusive_limit\": False, \"max_refund_age_days\": 45, \"rounding\": \"invoice\", \"order\": \"created\", \"refund_overflow\": \"reject\", \"refunds_first\": False, \"void_is_tombstone\": False, \"min_invoice_cents\": 25, \"status_case\": \"upper\", \"currency\": \"CAD\", \"fee_refundable\": False}\n", "helpers.py": "from decimal import Decimal, ROUND_HALF_UP\n\ndef _to_cents_value(line):\n    return Decimal(str(line)) * Decimal(100)\n\ndef line_cents(lines, rounding):\n    if rounding == \"per_line\":\n        total = 0\n        for line in lines:\n            cents = _to_cents_value(line).quantize(Decimal('1'), rounding=ROUND_HALF_UP)\n            total += int(cents)\n        return total\n    total_dec = sum((_to_cents_value(line) for line in lines), Decimal(0))\n    return int(total_dec.quantize(Decimal('1'), rounding=ROUND_HALF_UP))\n\ndef dedup_events(events, mode):\n    seen = {}\n    for ev in events:\n        eid = ev.get(\"eid\")\n        if eid in seen:\n            if mode == \"last\":\n                seen[eid] = dict(ev)\n        else:\n            seen[eid] = dict(ev)\n    return list(seen.values())\n\ndef ordered_events(events, refunds_first):\n    seq = list(events)\n    if refunds_first:\n        refunds = [e for e in seq if e.get(\"kind\") == \"refund\"]\n        others = [e for e in seq if e.get(\"kind\") != \"refund\"]\n        return refunds + others\n    return seq\n"}}