{"files": {"main.py": "from core import run\nfrom policy import POLICY\ndef evaluate(payload):\n    return run(payload, POLICY)\n", "core.py": "from helpers import principal_cents, dedup_events, ordered_events\n\ndef run(payload, policy):\n    if not payload or not payload.get('invoices'):\n        return {'invoices': []}\n    currency = policy.get('currency')\n    rounding = policy.get('rounding', 'invoice')\n    min_invoice_cents = policy.get('min_invoice_cents', 0)\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_refund_age_days = policy.get('max_refund_age_days', 0)\n    inclusive_limit = policy.get('inclusive_limit', False)\n    fee_refundable = policy.get('fee_refundable', False)\n    refund_overflow = policy.get('refund_overflow', 'reject')\n    status_case = policy.get('status_case', 'lower')\n    order = policy.get('order', 'id')\n    results = []\n    for inv in payload.get('invoices', []):\n        if inv.get('currency') != currency:\n            continue\n        principal = principal_cents(inv.get('lines', []), rounding)\n        fee = inv.get('fee_cents', 0)\n        charge = principal + fee\n        if charge < min_invoice_cents:\n            continue\n        events = dedup_events(inv.get('events', []), duplicate_event)\n        events = ordered_events(events, refunds_first)\n        ceiling = principal + (fee if fee_refundable else 0)\n        refunded = 0\n        active = True\n        tombstone = False\n        created = inv.get('created')\n        for ev in events:\n            kind = ev.get('kind')\n            if kind == 'void':\n                active = False\n                if void_is_tombstone:\n                    tombstone = True\n            elif kind == 'restore':\n                if not tombstone:\n                    active = True\n            elif kind == 'refund':\n                if not active:\n                    continue\n                diff = ev.get('day') - created\n                if diff < 0:\n                    continue\n                if inclusive_limit:\n                    if diff > max_refund_age_days:\n                        continue\n                else:\n                    if diff >= max_refund_age_days:\n                        continue\n                cents = ev.get('cents', 0)\n                if refund_overflow == 'reject':\n                    if refunded + cents > ceiling:\n                        continue\n                    refunded += cents\n                else:\n                    available = ceiling - refunded\n                    if available <= 0:\n                        continue\n                    refunded += cents if cents < available else available\n        if not active:\n            base = 'void'\n        elif refunded == charge:\n            base = 'refunded'\n        else:\n            base = 'open'\n        if status_case == 'upper':\n            status = base.upper()\n        elif status_case == 'lower':\n            status = base.lower()\n        else:\n            status = base\n        results.append((created, inv.get('id'), {'id': inv.get('id'), 'charge': charge, 'refunded': refunded, 'balance': charge - refunded, 'status': status}))\n    if order == 'created':\n        results_sorted = sorted(results, key=lambda x: (x[0], x[1]))\n    else:\n        results_sorted = sorted(results, key=lambda x: x[1])\n    return {'invoices': [item[2] for item in results_sorted]}\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": "from decimal import Decimal, ROUND_HALF_UP\n\ndef principal_cents(lines, rounding):\n    if rounding == 'per_line':\n        total = 0\n        for line in lines:\n            total += int((Decimal(line) * 100).quantize(Decimal('1'), rounding=ROUND_HALF_UP))\n        return total\n    total = sum((Decimal(line) for line in lines), Decimal('0'))\n    return int((total * 100).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 not in seen:\n            seen[eid] = ev\n        elif mode == 'last':\n            seen[eid] = ev\n    return list(seen.values())\n\ndef ordered_events(events, refunds_first):\n    if not refunds_first:\n        return list(events)\n    refunds = [ev for ev in events if ev.get('kind') == 'refund']\n    others = [ev for ev in events if ev.get('kind') != 'refund']\n    return refunds + others\n"}}