feat(backend): Pydantic v2 models for 837P claims
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
"""Pydantic v2 models for parsed 837P claims.
|
||||
|
||||
Models mirror the X12 837P structure (Loop 2000A → 2000B → 2300 → 2400) but
|
||||
flattened to one ``ClaimOutput`` per CLM segment, suitable for JSON serialization
|
||||
and consumption by the Cyclone frontend.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from typing import Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, model_serializer
|
||||
|
||||
|
||||
class _Base(BaseModel):
|
||||
model_config = ConfigDict(extra="ignore", str_strip_whitespace=True)
|
||||
|
||||
@model_serializer(mode="wrap")
|
||||
def _serialize(self, handler): # type: ignore[no-untyped-def]
|
||||
data = handler(self)
|
||||
for key, value in data.items():
|
||||
if isinstance(value, date):
|
||||
data[key] = value.isoformat()
|
||||
return data
|
||||
|
||||
|
||||
class Address(_Base):
|
||||
line1: str
|
||||
line2: str | None = None
|
||||
city: str
|
||||
state: str
|
||||
zip: str
|
||||
|
||||
|
||||
class BillingProvider(_Base):
|
||||
name: str
|
||||
npi: str
|
||||
tax_id: str | None = None
|
||||
address: Address | None = None
|
||||
|
||||
|
||||
class Subscriber(_Base):
|
||||
first_name: str
|
||||
last_name: str
|
||||
member_id: str
|
||||
dob: date | None = None
|
||||
gender: Literal["M", "F", "U"] | None = None
|
||||
address: Address | None = None
|
||||
|
||||
|
||||
class Payer(_Base):
|
||||
name: str
|
||||
id: str
|
||||
|
||||
|
||||
class ClaimHeader(_Base):
|
||||
claim_id: str
|
||||
total_charge: Decimal
|
||||
place_of_service: str | None = None
|
||||
frequency_code: str | None = None
|
||||
provider_signature: str | None = None
|
||||
assignment: str | None = None
|
||||
release_of_info: str | None = None
|
||||
prior_auth: str | None = None
|
||||
|
||||
|
||||
class Diagnosis(_Base):
|
||||
code: str
|
||||
qualifier: str | None = None
|
||||
|
||||
|
||||
class Procedure(_Base):
|
||||
qualifier: str
|
||||
code: str
|
||||
modifiers: list[str] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ServiceLine(_Base):
|
||||
line_number: int
|
||||
procedure: Procedure
|
||||
charge: Decimal
|
||||
unit_type: str | None = None
|
||||
units: Decimal | None = None
|
||||
place_of_service: str | None = None
|
||||
service_date: date | None = None
|
||||
provider_reference: str | None = None
|
||||
|
||||
|
||||
class ValidationIssue(_Base):
|
||||
rule: str
|
||||
severity: Literal["error", "warning"]
|
||||
message: str
|
||||
segment_index: int | None = None
|
||||
|
||||
|
||||
class ValidationReport(_Base):
|
||||
passed: bool
|
||||
errors: list[ValidationIssue] = Field(default_factory=list)
|
||||
warnings: list[ValidationIssue] = Field(default_factory=list)
|
||||
|
||||
|
||||
class Envelope(_Base):
|
||||
sender_id: str
|
||||
receiver_id: str
|
||||
control_number: str
|
||||
transaction_date: date
|
||||
transaction_time: str | None = None
|
||||
implementation_guide: str | None = None
|
||||
|
||||
|
||||
class BatchSummary(_Base):
|
||||
input_file: str
|
||||
control_number: str | None = None
|
||||
transaction_date: date | None = None
|
||||
total_claims: int = 0
|
||||
passed: int = 0
|
||||
failed: int = 0
|
||||
failed_claim_ids: list[str] = Field(default_factory=list)
|
||||
issues_by_rule: dict[str, int] = Field(default_factory=dict)
|
||||
output_dir: str | None = None
|
||||
|
||||
|
||||
class ClaimOutput(_Base):
|
||||
claim_id: str
|
||||
control_number: str
|
||||
transaction_date: date
|
||||
billing_provider: BillingProvider
|
||||
subscriber: Subscriber
|
||||
payer: Payer
|
||||
claim: ClaimHeader
|
||||
diagnoses: list[Diagnosis] = Field(default_factory=list)
|
||||
service_lines: list[ServiceLine] = Field(default_factory=list)
|
||||
validation: ValidationReport
|
||||
raw_segments: list[list[str]] = Field(default_factory=list)
|
||||
|
||||
|
||||
class ParseResult(_Base):
|
||||
envelope: Envelope | None = None
|
||||
claims: list[ClaimOutput] = Field(default_factory=list)
|
||||
summary: BatchSummary
|
||||
Reference in New Issue
Block a user