Metadata-Version: 2.4
Name: pyoce
Version: 0.1.0
Summary: Python port of the CMS Integrated Outpatient Code Editor (I/OCE)
Project-URL: Homepage, https://github.com/Bedrock-Billing/pyoce
Project-URL: Repository, https://github.com/Bedrock-Billing/pyoce
Author-email: BedrockBilling <support@bedrockbilling.com>
License: Apache-2.0
License-File: LICENSE
Keywords: billing,claims,cms,ioce,medical,outpatient
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Healthcare Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.12
Requires-Dist: lmdb>=1.4.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Description-Content-Type: text/markdown

# PyOCE

[![Python Version](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE)
[![Ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
[![Mypy](https://img.shields.io/badge/type%20checker-mypy-blue.svg)](https://github.com/python/mypy)

**PyOCE** is a production-grade Python port of the CMS Integrated Outpatient Code Editor (I/OCE) — the official rules engine used by the Centers for Medicare & Medicaid Services to edit, group, and price hospital outpatient claims under the OPPS (Outpatient Prospective Payment System).

## What Does the I/OCE Do?

The I/OCE applies 150+ clinical and administrative edit rules to each outpatient claim, including:

- **Validity checks** — bill type, dates, diagnosis codes, HCPCS/CPT codes, modifiers, revenue codes
- **NCCI edits** — procedure-to-procedure code pairs that should not be billed together
- **APC assignment** — grouping services into Ambulatory Payment Classifications for pricing
- **Status indicator assignment** — determining whether each line is payable, packaged, or denied
- **Discounting and packaging** — applying OPPS payment logic (multiple procedure discounting, composite APCs, etc.)
- **Specialty handling** — FQHC visits, biosimilars, telehealth, mental health, non-opioid therapies, Section 603, and more

PyOCE replicates this logic in pure Python, verified against the CMS Java reference implementation.

## Features

- **Parity-tested** — Cross-validated against official CMS Java TESTDB outputs across thousands of claims
- **High throughput** — Optimized LMDB-backed reference data with zero-copy memory mapping; processes 1,000+ claims per second
- **Zero-config data** — Reference database is bundled as a compressed archive and auto-extracted on first use
- **Version-aware** — Full support for IOCE version ranges; lookups respect historical data boundaries
- **Thread-safe** — LMDB supports concurrent reads from multiple processes/threads
- **Simple API** — Plain `dict` in, plain `dict` out; no ORM, no protobuf, no ceremony
- **Self-contained** — Single package with bundled reference data; no external services needed
- **Reusable engine** — `IoceComponent` gives access to edit descriptions, APC descriptions, and other lookup utilities

## Installation

```bash
pip install pyoce
```

**Requirements**: Python 3.12+, no system dependencies beyond the Python standard library.

On first use, the bundled reference database (~2.7 MB compressed, ~10 MB uncompressed LMDB) is automatically inflated to `~/.cache/pyoce/`.

## Quick Start

```python
import pyoce

claim = {
    "claimId": "DEMO-001",
    "billType": "131",
    "dateStarted": "20240101",
    "dateEnded": "20240101",
    "principalDiagnosisCode": {"diagnosis": "J449"},
    "lineItemList": [
        {
            "serviceDate": "20240101",
            "hcpcs": "99213",
            "revenueCode": "0510",
            "unitsInput": "1",
            "charge": "15000",
        }
    ],
}

result = pyoce.process_claim(claim)

# Inspect results
print(f"Return code: {result['processingInformation']['returnCode']}")
for li in result["lineItemList"]:
    print(f"  {li['hcpcs']} → APC {li['paymentApc']}, SI {li['statusIndicator']}")

# Look up edit descriptions (human-readable)
engine = pyoce.IoceComponent()
assert result is engine.process(claim)  # same API, reusable
print(engine.get_edit_description("001"))
print(engine.get_apc_description("5021"))
```

### Input Fields

| Field | Type | Notes |
|---|---|---|
| `claimId` | `str` | Unique claim identifier |
| `billType` | `str` | 3-char bill type (e.g. `"131"` for hospital outpatient) |
| `dateStarted` / `dateEnded` | `str` | `YYYYMMDD` format |
| `receiptDate` | `str` | `YYYYMMDD`, used for version range lookups |
| `principalDiagnosisCode` | `dict` | `{"diagnosis": "J449", "presentOnAdmission": "Y"}` |
| `secondaryDiagnosisCodeList` | `list[dict]` | Additional diagnosis codes |
| `lineItemList` | `list[dict]` | Per-line: `hcpcs`, `revenueCode`, `serviceDate`, `unitsInput`, `charge`, optional modifiers |

See the [`src/pyoce/model/external/`](src/pyoce/model/external/) package for the full external model.

### Output Fields

The output dict mirrors the input structure with additions:
- **Claim-level**: `claimDisposition`, `claimRejectionEditList`, `claimDenialEditList`, etc.
- **Line-level**: `paymentApc`, `statusIndicator`, `paymentIndicator`, `discountingFormula`, `rejectionDenialFlag`, edit lists per buffer type
- **Processing metadata**: `returnCode`, `version`, timing information

## How It Works

Claims flow through a 5-phase sequential pipeline:

```
INITIALIZATION → PREPROCESSING → PROCESSING → POSTPROCESSING → FINALIZATION
```

| Phase | Responsibility |
|---|---|
| **Initialization** | Load and validate reference data tables (cached after first claim) |
| **Preprocessing** | Copy input to internal model, validate bill type/dates, load table data per claim, validate contractor overrides |
| **Processing** | Execute 150+ edit rules, routed by bill type (see below) |
| **Postprocessing** | Calculate disposition, payment flags, discounting, composite APCs, units |
| **Finalization** | Copy internal processing state back to external output model |

### Bill Type Routing

The processing phase dispatches to one of 24 bill-type-specific logic paths based on the claim's bill type, OPPS/non-OPPS flag, and condition codes. The most common path — **13x (Hospital Outpatient)** — applies approximately 150 sequential rule checks including NCCI edits, status/payment indicator assignment, add-on code pairing, modifier validation, and specialty payment logic.

For a complete bill-type routing table, see the [internal architecture documentation](src/pyoce/logic/processing/).

## Reference Data

PyOCE ships with a pre-built LMDB database containing 39 CMS reference tables (213,277 records) covering APC assignments, HCPCS code attributes, ICD-10 diagnoses, NCCI edit pairs, offset tables, status/payment indicators, composite APCs, and all add-on code mappings — versioned across the full IOCE version range.

### Overriding the Database Location

```python
from pyoce.dao.provider import LmdbDataProvider

# Point to a custom LMDB database
LmdbDataProvider.reset_instance()
provider = LmdbDataProvider(env_path="/path/to/pyoce.mdb")
```

### Rebuilding the Database

To rebuild the LMDB database from CMS flat files:

```bash
uv run python scripts/build_db.py
```

This reads `Report-Tables/` (not included in the repository) and writes `src/pyoce/data/pyoce.mdb.xz`.

## Development

```bash
# Clone and install in editable mode with dev dependencies
git clone https://github.com/cms-gov/pyoce.git
cd pyoce
uv pip install -e ".[dev]"
```

### CI Verification

Run the exact checks used in CI:

```bash
uv run ruff format --check .   # code formatting
uv run ruff check .             # linting
uv run mypy src                 # strict type checking
uv run pytest                   # full test suite
```

## Testing

| Suite | Command | Requires |
|---|---|---|
| Unit tests | `uv run pytest tests/unit` | Nothing |
| Integration (parity) | `uv run pytest tests/integration` | `cms_mf/claims.json` (CMS TESTDB) |
| Full suite | `uv run pytest` | `cms_mf/claims.json` |

Unit tests cover flag enums, data providers, DAOs, external models, converters, utilities, and individual logic rules. Integration tests feed real CMS TESTDB claims through the engine and compare output field-by-field against the Java reference implementation.

### Parity Report

Generate a detailed mismatch report for all claims with expected outputs:

```bash
PYTHONPATH=. uv run python tests/integration/test_parity_report.py
```

Or test a single claim by ID:

```bash
PYTHONPATH=. uv run python tests/integration/test_parity_report.py --claim <id>
```

## Project Structure

```
src/pyoce/
├── __init__.py             # Public API: process_claim(), IoceComponent
├── api/                    # Entry points, claim execution engine
├── model/
│   ├── external/           # Public claim/line models (dataclasses)
│   └── internal/           # Processing state models (~50 fields per claim)
├── logic/
│   ├── initialization/     # Phase 1: load & validate tables
│   ├── preprocessing/      # Phase 2: validate inputs, load per-claim data
│   ├── processing/         # Phase 3: 150+ edit rules, bill-type paths
│   │   ├── addon/          # Add-on code pairing logic
│   │   └── specialty/      # FQHC, biosimilar, telehealth, S603, etc.
│   ├── postprocessing/     # Phase 4: disposition, flags, composites
│   └── finalization/       # Phase 5: output marshaling
├── dao/                    # Data access layer (42 table DAOs, description provider)
├── rsc/                    # Flag enums, edit registry, constants
├── util/                   # FlagSet, Navigator, range maps, utilities
└── data/                   # Bundled LMDB database (compressed)
```

## License

Apache License, Version 2.0 — see [LICENSE](LICENSE).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, coding standards, and pull request guidelines.
