{"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 convert_lines\n\ndef run(payload, policy):\n    policy = policy or {}\n    currency = policy.get('currency', 'USD')\n    rounding = policy.get('rounding', 'per_line')\n    min_invoice_cents = policy.get('min_invoice_cents', 10)\n    duplicate_event = policy.get('duplicate_event', 'first')\n    refunds_first = policy.get('refunds_first', True)\n    void_is_tombstone = policy.get('void_is_tombstone', True)\n    max_refund_age_days = policy.get('max_refund_age_days', 30)\n    inclusive_limit = policy.get('inclusive_limit', True)\n    fee_refundable = policy.get('fee_refundable', True)\n    refund_overflow = policy.get('refund_overflow', 'cap')\n    status_case = policy.get('status_case', 'lower')\n    order = policy.get('order', 'id')\n    if not payload:\n        return {'invoices': []}\n    if isinstance(payload, dict):\n        invoices_in = payload.get('invoices')\n        if invoices_in is None:\n            return {'invoices': []}\n    elif isinstance(payload, (list, tuple)):\n        invoices_in = list(payload)\n    else:\n        return {'invoices': []}\n    results = []\n    for invoice in invoices_in:\n        if not isinstance(invoice, dict):\n            continue\n        if invoice.get('currency') != currency:\n            continue\n        lines = invoice.get('lines') or []\n        principal = convert_lines(lines, rounding)\n        fee = invoice.get('fee_cents', 0)\n        fee_cents = int(fee) if fee is not None else 0\n        charge = principal + fee_cents\n        if charge < min_invoice_cents:\n            continue\n        created = invoice.get('created')\n        if created is None:\n            created = invoice.get('created_day', 0)\n        created = int(created)\n        events = invoice.get('events') or []\n        deduped = []\n        index_by_eid = {}\n        for event in events:\n            if not isinstance(event, dict):\n                continue\n            eid = event.get('eid')\n            if eid is None:\n                deduped.append(event)\n                continue\n            if duplicate_event == 'last':\n                if eid in index_by_eid:\n                    deduped[index_by_eid[eid]] = event\n                else:\n                    index_by_eid[eid] = len(deduped)\n                    deduped.append(event)\n            else:\n                if eid not in index_by_eid:\n                    index_by_eid[eid] = len(deduped)\n                    deduped.append(event)\n        if refunds_first:\n            ordered_events = [e for e in deduped if e.get('kind') == 'refund'] + [e for e in deduped if e.get('kind') != 'refund']\n        else:\n            ordered_events = list(deduped)\n        active = True\n        tombstoned = False\n        refunded = 0\n        ceiling = principal + fee_cents if fee_refundable else principal\n        for event in ordered_events:\n            kind = event.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 = event.get('day')\n                if day is None:\n                    continue\n                age = int(day) - created\n                if age < 0:\n                    continue\n                if max_refund_age_days is not None:\n                    if inclusive_limit:\n                        if age > max_refund_age_days:\n                            continue\n                    else:\n                        if age >= max_refund_age_days:\n                            continue\n                cents = event.get('cents', 0)\n                cents = int(cents) if cents is not None else 0\n                if cents < 0:\n                    continue\n                remaining = ceiling - refunded\n                if remaining < 0:\n                    remaining = 0\n                if cents <= remaining:\n                    refunded += cents\n                else:\n                    if refund_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 isinstance(status_case, str) and status_case.lower() == 'upper':\n            status = status.upper()\n        else:\n            status = status.lower()\n        record = {'id': invoice.get('id'), 'charge': charge, 'refunded': refunded, 'balance': charge - refunded, 'status': status}\n        results.append((record, created))\n    if order == 'created':\n        results.sort(key=lambda item: (item[1], item[0]['id']))\n    else:\n        results.sort(key=lambda item: item[0]['id'])\n    return {'invoices': [record for record, _created in results]}\n", "policy.py": "POLICY = {'duplicate_event': 'first', 'inclusive_limit': True, 'max_refund_age_days': 30, 'rounding': 'per_line', 'order': 'id', 'refund_overflow': 'cap', 'refunds_first': True, 'void_is_tombstone': True, 'min_invoice_cents': 10, 'status_case': 'lower', 'currency': 'USD', 'fee_refundable': True}\n", "helpers.py": "from decimal import Decimal, ROUND_HALF_UP\n\ndef convert_lines(lines, rounding):\n    values = [Decimal(str(line)) for line in lines]\n    if rounding == 'per_line':\n        total = 0\n        for value in values:\n            total += int((value * 100).quantize(Decimal('1'), rounding=ROUND_HALF_UP))\n        return total\n    total_decimal = sum(values, Decimal('0'))\n    return int((total_decimal * 100).quantize(Decimal('1'), rounding=ROUND_HALF_UP))\n"}}