Compare commits
4 commits
5ba31fac03
...
0077e21cc6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0077e21cc6 | ||
|
|
03afd62caf | ||
|
|
f28b5bf39e | ||
|
|
a53728e424 |
80 changed files with 17618 additions and 15453 deletions
|
|
@ -2,7 +2,7 @@ v:1
|
||||||
|
|
||||||
# current-state
|
# current-state
|
||||||
|
|
||||||
ACTIVE: 2026-07-07 [CC]. SIGNAL BUILD UN-PAUSED — readiness-model completion in flight per docs/build-plans/. P1 (wiring) SHIPPED + LIVE-VERIFIED (commit a3af499, deployed to Railway, false-green kill observed live). Executing P2 (citation IDs) -> P3 (rollup) -> P4 (device overrides) -> P5 (plan-type enforcement) next, one item at a time with independent audit each. P6 (frontend nesting) BLOCKED on Kisa approving the rendered mockup (built, awaiting render+review).
|
ACTIVE: 2026-07-07 [CC]. READINESS-MODEL BACKEND COMPLETE: P1-P5 all SHIPPED + LIVE-VERIFIED (a3af499, d24340c, bd92126, a53728e, f28b5bf; Railway + Vercel deployed; doc_status migration applied to prod). 169 tests + Pi E2E 33/33 green. P6 (frontend nesting) is the ONLY remaining item — BLOCKED on Kisa approving docs/mockups/p6-worklist-mockup-2026-07-07.png (decisions A-D).
|
||||||
|
|
||||||
NEXT: (CC) P2-P5 per docs/build-plans/02-readiness-model-completion.md; (Kisa) approve/reject P6 mockup decisions A-D; (Kisa) confirm OQ1 plan_type-ingestion decision recorded 2026-07-07 (shipped per umbrella plan; two-line revert if reversed); (Kisa) attorney bundle READY TO SEND (signal/pitch/legal/attorney-bundle-2026-07-07, 5 Word docs + sendable memo): confirm recipient (Clyde Mathes vs Bittinger/Nixon), entity name + formation state, arbitration-vs-courts posture, Partner Concepts carve-out keep/drop, then email; Gaboro re-approach per reactivation plan 00 (unchanged). Queued behind Signal: UMSIS docs-only activation, "63% written off" Draft fix.
|
NEXT: (CC) P2-P5 per docs/build-plans/02-readiness-model-completion.md; (Kisa) approve/reject P6 mockup decisions A-D; (Kisa) confirm OQ1 plan_type-ingestion decision recorded 2026-07-07 (shipped per umbrella plan; two-line revert if reversed); (Kisa) attorney bundle READY TO SEND (signal/pitch/legal/attorney-bundle-2026-07-07, 5 Word docs + sendable memo): confirm recipient (Clyde Mathes vs Bittinger/Nixon), entity name + formation state, arbitration-vs-courts posture, Partner Concepts carve-out keep/drop, then email; Gaboro re-approach per reactivation plan 00 (unchanged). Queued behind Signal: UMSIS docs-only activation, "63% written off" Draft fix.
|
||||||
|
|
||||||
|
|
@ -25,6 +25,8 @@ Insight Engine (July 4 deadline = tomorrow) is the active project. Key files:
|
||||||
|
|
||||||
## Decisions (last
|
## Decisions (last
|
||||||
|
|
||||||
|
- 2026-07-07 [CC]: Readiness-model backend COMPLETE (P2-P5 shipped same day as P1): citation IDs live (R-registry), patient rollup + nested payload live, device-scoped overrides live (doc_status migration applied to prod; overrides now feed the verdict; the leak is dead, live-measured), plan-type enforcement live (zero greens without a mapped plan type, live-measured; Phase 2c deletion stays Kisa-gated). Every item independently audited SHIP before ship. P6 mockup rendered for Kisa (4 decisions annotated).
|
||||||
|
|
||||||
- 2026-07-07 [CC]: Attorney-review legal bundle PREPARED (lead-sttil drafted, ops-steward independently reviewed, 6 findings fixed incl. 4 HIGH counterparty-name leaks). LOI template v3 (product-agnostic body, Exhibit A pre-filled for Signal, labABLE negotiation learnings folded in), NDA template v3 (products list corrected to Signal/Vitality Med Tracker/UMSIS + catch-all), BAA template v1 (generalized from Gaboro draft, forward-looking posture block), cover memo bundling both templates + BAA + FDA CDS memo + labABLE AKS question per reactivation plan 00. Entity name corrected everywhere to KJF Professional Services LLC dba STTIL Solutions (per executed labABLE LOI; kg_add recorded); formation state left as placeholder (old docs disagree: Delaware/Florida/Pennsylvania) = attorney Q1. Templates: STTIL-Vault/Projects/Legal/ (LOI+NDA v3) + signal/pitch/legal/ (BAA, memo). Send-ready docx: signal/pitch/legal/attorney-bundle-2026-07-07/.
|
- 2026-07-07 [CC]: Attorney-review legal bundle PREPARED (lead-sttil drafted, ops-steward independently reviewed, 6 findings fixed incl. 4 HIGH counterparty-name leaks). LOI template v3 (product-agnostic body, Exhibit A pre-filled for Signal, labABLE negotiation learnings folded in), NDA template v3 (products list corrected to Signal/Vitality Med Tracker/UMSIS + catch-all), BAA template v1 (generalized from Gaboro draft, forward-looking posture block), cover memo bundling both templates + BAA + FDA CDS memo + labABLE AKS question per reactivation plan 00. Entity name corrected everywhere to KJF Professional Services LLC dba STTIL Solutions (per executed labABLE LOI; kg_add recorded); formation state left as placeholder (old docs disagree: Delaware/Florida/Pennsylvania) = attorney Q1. Templates: STTIL-Vault/Projects/Legal/ (LOI+NDA v3) + signal/pitch/legal/ (BAA, memo). Send-ready docx: signal/pitch/legal/attorney-bundle-2026-07-07/.
|
||||||
- 2026-07-07 [CC]: Readiness model WIRED LIVE (plan 01, commit a3af499, Railway deploy verified). Phase 2a seam confirmed: readiness AUGMENTS legacy output (byte-identical legacy proven by live diff). OQ1 executed per umbrella plan 00 ("ship plan_type ingestion with the wiring") — minimal client-mapped column, never guessed; flagged for Kisa's explicit confirmation, two-line revert if reversed. Adversarial review caught a false-green in the draft row-resolution; fixed via dedup-group-keyed ReadinessIndex, regression-locked. Grounded test count: 132 (the old "73 tests" figure corrected per plan 01 §12.5).
|
- 2026-07-07 [CC]: Readiness model WIRED LIVE (plan 01, commit a3af499, Railway deploy verified). Phase 2a seam confirmed: readiness AUGMENTS legacy output (byte-identical legacy proven by live diff). OQ1 executed per umbrella plan 00 ("ship plan_type ingestion with the wiring") — minimal client-mapped column, never guessed; flagged for Kisa's explicit confirmation, two-line revert if reversed. Adversarial review caught a false-green in the draft row-resolution; fixed via dedup-group-keyed ReadinessIndex, regression-locked. Grounded test count: 132 (the old "73 tests" figure corrected per plan 01 §12.5).
|
||||||
- 2026-07-06 [CC]: Model routing SETTLED (Kisa agreed) — strongest model in the orchestrator seat (plain claude, full MCP, skip-permissions), sonnet/haiku subagents for mechanical work, Fable-as-subagent only for cleanly separable hard problems. Docs-verified: delegation multiplies tokens on one shared pool; per-agent model override + mid-session /model GROUNDED. Config application PARKED. Discovered com.sttil.cos-model-switch: Fable-to-Opus swap fires 2026-07-07 09:00. Watcher audit: 9 agents healthy, clean exits; research watcher never built.
|
- 2026-07-06 [CC]: Model routing SETTLED (Kisa agreed) — strongest model in the orchestrator seat (plain claude, full MCP, skip-permissions), sonnet/haiku subagents for mechanical work, Fable-as-subagent only for cleanly separable hard problems. Docs-verified: delegation multiplies tokens on one shared pool; per-agent model override + mid-session /model GROUNDED. Config application PARKED. Discovered com.sttil.cos-model-switch: Fable-to-Opus swap fires 2026-07-07 09:00. Watcher audit: 9 agents healthy, clean exits; research watcher never built.
|
||||||
|
|
@ -59,4 +61,4 @@ Insight Engine (July 4 deadline = tomorrow) is the active project. Key files:
|
||||||
|
|
||||||
State protocol: read = `git pull --rebase` then read this file (warn if Updated > 24h old); write = edit ACTIVE/NEXT, append one author-stamped decision, then commit + push. Full protocol in the `state-sync` skill. Detailed ship-status (what shipped / didn't / why) = docs/ship-status-ledger.md. TriLane = searchable archive, not live state.
|
State protocol: read = `git pull --rebase` then read this file (warn if Updated > 24h old); write = edit ACTIVE/NEXT, append one author-stamped decision, then commit + push. Full protocol in the `state-sync` skill. Detailed ship-status (what shipped / didn't / why) = docs/ship-status-ledger.md. TriLane = searchable archive, not live state.
|
||||||
|
|
||||||
## Updated: 2026-07-07 (CC: Signal un-paused; P1 readiness wiring shipped+live-verified a3af499; P2-P5 executing; P6 mockup awaiting Kisa; OQ1 recorded for confirmation; attorney legal bundle prepared and ready to send.)
|
## Updated: 2026-07-07 (CC: readiness-model backend P1-P5 complete, live-verified, deployed; P6 gated on Kisa mockup approval.)
|
||||||
|
|
|
||||||
1358
docs/build-plans/03-game-center-token-layer.md
Normal file
1358
docs/build-plans/03-game-center-token-layer.md
Normal file
File diff suppressed because it is too large
Load diff
BIN
docs/mockups/p6-worklist-mockup-2026-07-07.png
Normal file
BIN
docs/mockups/p6-worklist-mockup-2026-07-07.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 200 KiB |
|
|
@ -85,3 +85,30 @@ byte-identical (live diff vs pre-deploy baseline: NONE).
|
||||||
Clear to Ship and normalizes "Medicare" -> "medicare".
|
Clear to Ship and normalizes "Medicare" -> "medicare".
|
||||||
- Frontend intentionally renders nothing new yet (P6, gated on Kisa's mockup
|
- Frontend intentionally renders nothing new yet (P6, gated on Kisa's mockup
|
||||||
approval).
|
approval).
|
||||||
|
|
||||||
|
## Shipped: readiness-model completion P2-P5 (2026-07-07, Claude, commits d24340c / bd92126 / a53728e / f28b5bf)
|
||||||
|
|
||||||
|
All four backend items shipped one at a time, each with an independent
|
||||||
|
code-auditor SHIP verdict and measured live verification:
|
||||||
|
|
||||||
|
- P2 citation IDs: every doc item cites its rule (R001-R004 plan-scoped,
|
||||||
|
R100-R102 universal per LCD L33822); registry-drift test guards the config.
|
||||||
|
Live: deployed verdict cites R004/R003/R100.
|
||||||
|
- P3 patient rollup: nested patients payload (worst gradeable line; Plan Type
|
||||||
|
Needed caps at Action Needed; non-gradeable displayed, never counted);
|
||||||
|
patient_stats count patients, not rows. Live-verified with a two-device
|
||||||
|
patient.
|
||||||
|
- P4 device-keyed overrides: doc_status migration applied to production
|
||||||
|
(device_type in the unique key, legacy '' rows honored); overrides now FEED
|
||||||
|
the verdict, device-scoped; recompute contract returns {lines, rollup}
|
||||||
|
through the same engine. Live: G7 override flipped only G7's line — the
|
||||||
|
leak is dead, measured against real Supabase state.
|
||||||
|
- P5 plan-type enforcement: full alias + value canonicalization; zero greens
|
||||||
|
reachable without a client-mapped plan type (live-measured); once-per-batch
|
||||||
|
deprecation fence; all 66 fixture CSVs authored with plan_type (drift
|
||||||
|
corpus uses variant headers/values; 66/66 map). _normalize_payer and the
|
||||||
|
default config entry remain (Phase 2c stays Kisa-gated).
|
||||||
|
|
||||||
|
Final state: 169 unit/API tests green, Pi E2E 33/33, live drives recorded
|
||||||
|
above. P6 (frontend nesting) BLOCKED on Kisa's mockup approval:
|
||||||
|
docs/mockups/p6-worklist-mockup-2026-07-07.png (decisions A-D annotated).
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,12 @@ from core.persistence import (
|
||||||
upsert_doc_status,
|
upsert_doc_status,
|
||||||
load_doc_statuses_for_org,
|
load_doc_statuses_for_org,
|
||||||
)
|
)
|
||||||
from api.normalizer import normalize_csv
|
from api.normalizer import _normalize_plan_type, normalize_csv
|
||||||
|
from core.overrides import (
|
||||||
|
Override,
|
||||||
|
OverrideKey,
|
||||||
|
overrides_from_saved,
|
||||||
|
)
|
||||||
from core.worklist_readiness import (
|
from core.worklist_readiness import (
|
||||||
build_readiness_index,
|
build_readiness_index,
|
||||||
merged_to_record,
|
merged_to_record,
|
||||||
|
|
@ -349,22 +354,129 @@ VALID_DOC_STATUSES = {
|
||||||
"pa": {"not_required", "requested", "approved", "denied"},
|
"pa": {"not_required", "requested", "approved", "denied"},
|
||||||
}
|
}
|
||||||
|
|
||||||
DOC_STATUS_LABELS = {
|
# Single source of truth for stored-status labels lives with the override
|
||||||
"pending": "Pending",
|
# engine (the same labels feed grading and display).
|
||||||
"requested": "Requested",
|
from core.overrides import STORED_STATUS_LABELS as DOC_STATUS_LABELS # noqa: E402
|
||||||
"on_file": "On File",
|
|
||||||
"not_required": "Not Required",
|
|
||||||
"approved": "Approved",
|
def _recompute_patient(
|
||||||
"denied": "Denied",
|
patient_id: str,
|
||||||
}
|
echo_lines: list["EchoLine"],
|
||||||
|
saved_doc_statuses: dict,
|
||||||
|
confirmed_visit: Optional[date] = None,
|
||||||
|
):
|
||||||
|
"""Stateless patient recompute (P4): rebuild the patient's lines from the
|
||||||
|
echoed CSV-truth inputs, apply ALL persisted staff overrides (the write
|
||||||
|
that triggered this call is already persisted) plus the confirmed visit,
|
||||||
|
re-grade through the same engine, and roll up through the same truth
|
||||||
|
table. Returns (lines_out, rollup_status)."""
|
||||||
|
from core.rollup import rollup_patient
|
||||||
|
from core.worklist_readiness import build_readiness_index as _bri
|
||||||
|
|
||||||
|
records = []
|
||||||
|
for el in echo_lines:
|
||||||
|
try:
|
||||||
|
ship = (
|
||||||
|
date_type.fromisoformat(el.shipment_date)
|
||||||
|
if el.shipment_date
|
||||||
|
else date.today()
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
ship = date.today()
|
||||||
|
csv_visit = None
|
||||||
|
if el.csv_visit_date:
|
||||||
|
try:
|
||||||
|
csv_visit = date_type.fromisoformat(el.csv_visit_date)
|
||||||
|
except ValueError:
|
||||||
|
csv_visit = None
|
||||||
|
records.append(
|
||||||
|
ShipmentRecord(
|
||||||
|
patient_id=patient_id,
|
||||||
|
device_type=el.device_type,
|
||||||
|
shipment_date=ship,
|
||||||
|
quantity=1,
|
||||||
|
payer="",
|
||||||
|
csv_swo_status=el.csv_swo_status,
|
||||||
|
csv_visit_date=csv_visit,
|
||||||
|
csv_pecos_verified=el.csv_pecos_verified,
|
||||||
|
csv_pa_status=el.csv_pa_status,
|
||||||
|
csv_diagnosis_on_file=el.csv_diagnosis_on_file,
|
||||||
|
plan_type=_normalize_plan_type(el.plan_type),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
patient_hash = hashlib.sha256(patient_id.encode()).hexdigest()
|
||||||
|
confirmed = (
|
||||||
|
{patient_hash: confirmed_visit} if confirmed_visit else None
|
||||||
|
)
|
||||||
|
overrides = overrides_from_saved(
|
||||||
|
{patient_hash: saved_doc_statuses.get(patient_hash, {})}
|
||||||
|
)
|
||||||
|
index = _bri(records, confirmed_visits=confirmed, overrides=overrides)
|
||||||
|
|
||||||
|
lines_out = []
|
||||||
|
for line_key, line in index.lines.items():
|
||||||
|
verdict = index.by_line.get(line_key)
|
||||||
|
lines_out.append(
|
||||||
|
LineRecomputeOut(
|
||||||
|
device_type=line.device_type,
|
||||||
|
plan_type=None if line.plan_type == "unknown" else line.plan_type,
|
||||||
|
line_status=line.line_status,
|
||||||
|
doc_items=_readiness_items_out(verdict),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
rollup = rollup_patient(list(index.lines.values()))
|
||||||
|
return lines_out, (
|
||||||
|
rollup.rollup_status.value if rollup.rollup_status else None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class EchoLine(BaseModel):
|
||||||
|
"""One coverage line echoed back for a stateless patient recompute.
|
||||||
|
Carries CSV-truth grading inputs only; the server applies all persisted
|
||||||
|
staff overrides and confirmed visits on top, then re-grades."""
|
||||||
|
|
||||||
|
device_type: str
|
||||||
|
gradeable: bool = True
|
||||||
|
plan_type: Optional[str] = None
|
||||||
|
shipment_date: Optional[str] = None # ISO; defaults to today (doc axis
|
||||||
|
# grading does not depend on it)
|
||||||
|
csv_swo_status: Optional[str] = None
|
||||||
|
csv_visit_date: Optional[str] = None
|
||||||
|
csv_pecos_verified: Optional[str] = None
|
||||||
|
csv_pa_status: Optional[str] = None
|
||||||
|
csv_diagnosis_on_file: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class LineRecomputeOut(BaseModel):
|
||||||
|
device_type: str
|
||||||
|
plan_type: Optional[str] = None
|
||||||
|
line_status: Optional[str] = None
|
||||||
|
doc_items: Optional[list["ReadinessItemOut"]] = None
|
||||||
|
|
||||||
|
|
||||||
class DocStatusRequest(BaseModel):
|
class DocStatusRequest(BaseModel):
|
||||||
patient_id: str
|
patient_id: str
|
||||||
doc_type: str
|
doc_type: str
|
||||||
status: str
|
status: str
|
||||||
|
# Device scope (P4). '' or omitted writes a legacy patient-scoped row
|
||||||
|
# that applies to all devices until a device-scoped row is saved.
|
||||||
|
device_type: str = ""
|
||||||
status_date: Optional[str] = None
|
status_date: Optional[str] = None
|
||||||
expiry_date: Optional[str] = None
|
expiry_date: Optional[str] = None
|
||||||
|
# Optional echo of the patient's lines for the {line, rollup} recompute.
|
||||||
|
lines: Optional[list[EchoLine]] = None
|
||||||
|
|
||||||
|
|
||||||
|
def _saved_for_device(
|
||||||
|
doc_statuses: dict, patient_hash: str, device_type: str
|
||||||
|
) -> dict:
|
||||||
|
"""Resolve the device-scoped saved statuses for one record: legacy ''
|
||||||
|
(patient-scoped) rows apply to all devices; a device-scoped row wins."""
|
||||||
|
by_pat = doc_statuses.get(patient_hash, {})
|
||||||
|
merged = dict(by_pat.get("", {}))
|
||||||
|
merged.update(by_pat.get(device_type, {}))
|
||||||
|
return merged
|
||||||
|
|
||||||
|
|
||||||
def _readiness_items_out(readiness) -> Optional[list[ReadinessItemOut]]:
|
def _readiness_items_out(readiness) -> Optional[list[ReadinessItemOut]]:
|
||||||
|
|
@ -671,6 +783,22 @@ async def upload_csv(
|
||||||
|
|
||||||
db_conn = get_client()
|
db_conn = get_client()
|
||||||
|
|
||||||
|
# P5 deprecation fence: when any record lacks a client-mapped plan_type,
|
||||||
|
# the TIMING rules fall back to the payer-name guess for those records
|
||||||
|
# (readiness never does — it reads Plan Type Needed). Once per batch.
|
||||||
|
_unmapped = sum(1 for rec in records if rec.plan_type is None)
|
||||||
|
if _unmapped:
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logging.getLogger(__name__).warning(
|
||||||
|
"plan_type not provided for %d/%d records. Timing rules guess "
|
||||||
|
"from the payer name (legacy path, to be removed); readiness "
|
||||||
|
"grades these records Plan Type Needed. Supply plan_type in "
|
||||||
|
"the CSV import.",
|
||||||
|
_unmapped,
|
||||||
|
len(records),
|
||||||
|
)
|
||||||
|
|
||||||
results = calculate_batch(
|
results = calculate_batch(
|
||||||
records, as_of=date.today(), confirmed_visits=confirmed_visits
|
records, as_of=date.today(), confirmed_visits=confirmed_visits
|
||||||
)
|
)
|
||||||
|
|
@ -683,8 +811,11 @@ async def upload_csv(
|
||||||
|
|
||||||
# Readiness index (Phase 2a: additive, augments the legacy scoring —
|
# Readiness index (Phase 2a: additive, augments the legacy scoring —
|
||||||
# replaces nothing). Row-to-line membership comes from the dedup output
|
# replaces nothing). Row-to-line membership comes from the dedup output
|
||||||
# itself, never re-derived from a row's own plan_type.
|
# itself, never re-derived from a row's own plan_type. Staff overrides
|
||||||
index = build_readiness_index(records, confirmed_visits)
|
# (P4) feed the grading inputs, device-scoped.
|
||||||
|
index = build_readiness_index(
|
||||||
|
records, confirmed_visits, overrides=overrides_from_saved(doc_statuses)
|
||||||
|
)
|
||||||
|
|
||||||
out = []
|
out = []
|
||||||
used_lines = {}
|
used_lines = {}
|
||||||
|
|
@ -718,8 +849,10 @@ async def upload_csv(
|
||||||
confirmed_visit_date=confirmed_visits.get(
|
confirmed_visit_date=confirmed_visits.get(
|
||||||
hashlib.sha256(r.patient_id.encode()).hexdigest()
|
hashlib.sha256(r.patient_id.encode()).hexdigest()
|
||||||
),
|
),
|
||||||
saved_doc_statuses=doc_statuses.get(
|
saved_doc_statuses=_saved_for_device(
|
||||||
hashlib.sha256(r.patient_id.encode()).hexdigest(), {}
|
doc_statuses,
|
||||||
|
hashlib.sha256(r.patient_id.encode()).hexdigest(),
|
||||||
|
r.device_type,
|
||||||
),
|
),
|
||||||
readiness=verdict,
|
readiness=verdict,
|
||||||
)
|
)
|
||||||
|
|
@ -883,6 +1016,10 @@ class ConfirmVisitRequest(BaseModel):
|
||||||
# Client-mapped plan type echoed from the upload — never guessed. None
|
# Client-mapped plan type echoed from the upload — never guessed. None
|
||||||
# keeps the recompute honest: the verdict reads Plan Type Needed.
|
# keeps the recompute honest: the verdict reads Plan Type Needed.
|
||||||
plan_type: str | None = None
|
plan_type: str | None = None
|
||||||
|
# Optional echo of ALL the patient's lines: the confirmed visit fans out
|
||||||
|
# to every line (the visit is the person), so the P4 recompute re-grades
|
||||||
|
# each and returns the re-rolled patient alongside the legacy record.
|
||||||
|
lines: Optional[list[EchoLine]] = None
|
||||||
|
|
||||||
|
|
||||||
@app.post("/api/confirm-visit")
|
@app.post("/api/confirm-visit")
|
||||||
|
|
@ -965,9 +1102,9 @@ async def confirm_visit(
|
||||||
csv_transfer_from=body.csv_transfer_from,
|
csv_transfer_from=body.csv_transfer_from,
|
||||||
order_number=body.order_number,
|
order_number=body.order_number,
|
||||||
hcpcs=body.hcpcs,
|
hcpcs=body.hcpcs,
|
||||||
# Same normalization the CSV path applies (lowercase + trim, never
|
# Same canonicalization the CSV path applies (value map, never
|
||||||
# guessed) so RecordOut.plan_type is consistent across both paths.
|
# guessed) so RecordOut.plan_type is consistent across both paths.
|
||||||
plan_type=(body.plan_type or "").strip().lower() or None,
|
plan_type=_normalize_plan_type(body.plan_type),
|
||||||
)
|
)
|
||||||
result = calculate_coverage(record, confirmed_visit_date=confirmed)
|
result = calculate_coverage(record, confirmed_visit_date=confirmed)
|
||||||
verdict = readiness_for_record(record, confirmed_visit_date=confirmed)
|
verdict = readiness_for_record(record, confirmed_visit_date=confirmed)
|
||||||
|
|
@ -985,9 +1122,23 @@ async def confirm_visit(
|
||||||
db_conn=db_conn,
|
db_conn=db_conn,
|
||||||
)
|
)
|
||||||
|
|
||||||
return _to_record_out(
|
record_out = _to_record_out(
|
||||||
result, record=record, confirmed_visit_date=confirmed, readiness=verdict
|
result, record=record, confirmed_visit_date=confirmed, readiness=verdict
|
||||||
)
|
)
|
||||||
|
if not body.lines:
|
||||||
|
return record_out
|
||||||
|
|
||||||
|
# P4: re-grade the patient's echoed lines with the new confirmed date
|
||||||
|
# (visit fans out to all lines) and return the re-rolled patient. All
|
||||||
|
# legacy RecordOut fields stay present.
|
||||||
|
saved = load_doc_statuses_for_org(org_id)
|
||||||
|
lines_out, rollup_status = _recompute_patient(
|
||||||
|
body.patient_id, body.lines, saved, confirmed_visit=confirmed
|
||||||
|
)
|
||||||
|
payload = record_out.model_dump()
|
||||||
|
payload["lines"] = [l.model_dump() for l in lines_out]
|
||||||
|
payload["rollup_status"] = rollup_status
|
||||||
|
return payload
|
||||||
|
|
||||||
|
|
||||||
@app.put("/api/doc-status")
|
@app.put("/api/doc-status")
|
||||||
|
|
@ -1039,7 +1190,13 @@ async def update_doc_status(
|
||||||
|
|
||||||
patient_hash = hashlib.sha256(body.patient_id.encode()).hexdigest()
|
patient_hash = hashlib.sha256(body.patient_id.encode()).hexdigest()
|
||||||
success = upsert_doc_status(
|
success = upsert_doc_status(
|
||||||
org_id, patient_hash, body.doc_type, body.status, status_date, expiry_date
|
org_id,
|
||||||
|
patient_hash,
|
||||||
|
body.doc_type,
|
||||||
|
body.status,
|
||||||
|
status_date,
|
||||||
|
expiry_date,
|
||||||
|
device_type=body.device_type or "",
|
||||||
)
|
)
|
||||||
if not success:
|
if not success:
|
||||||
raise HTTPException(status_code=503, detail="Failed to save doc status.")
|
raise HTTPException(status_code=503, detail="Failed to save doc status.")
|
||||||
|
|
@ -1057,9 +1214,24 @@ async def update_doc_status(
|
||||||
db_conn=db_conn,
|
db_conn=db_conn,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
response = {
|
||||||
"patient_id": body.patient_id,
|
"patient_id": body.patient_id,
|
||||||
"doc_type": body.doc_type,
|
"doc_type": body.doc_type,
|
||||||
"status": body.status,
|
"status": body.status,
|
||||||
|
"device_type": body.device_type or "",
|
||||||
"display": DOC_STATUS_LABELS.get(body.status, body.status),
|
"display": DOC_STATUS_LABELS.get(body.status, body.status),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# P4 recompute contract: when the client echoes the patient's lines,
|
||||||
|
# re-grade them (the write above is already persisted, so a fresh load
|
||||||
|
# picks it up) and return {lines, rollup} from the same engine.
|
||||||
|
if body.lines:
|
||||||
|
saved = load_doc_statuses_for_org(org_id)
|
||||||
|
confirmed = load_confirmed_visits_for_org(org_id).get(patient_hash)
|
||||||
|
lines_out, rollup_status = _recompute_patient(
|
||||||
|
body.patient_id, body.lines, saved, confirmed_visit=confirmed
|
||||||
|
)
|
||||||
|
response["lines"] = [l.model_dump() for l in lines_out]
|
||||||
|
response["rollup_status"] = rollup_status
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,15 @@ Tolerates header drift, alternative column names, and common date formats.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import csv
|
import csv
|
||||||
|
import hashlib
|
||||||
import io
|
import io
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
from datetime import date, datetime
|
from datetime import date, datetime
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||||||
|
|
@ -52,8 +56,10 @@ HEADER_MAP: dict[str, list[str]] = {
|
||||||
# name. Bare "plan"/"plan_name" stay payer aliases (a "Plan" column in the
|
# name. Bare "plan"/"plan_name" stay payer aliases (a "Plan" column in the
|
||||||
# wild is a payer name); stealing them would silently re-map existing CSVs.
|
# wild is a payer name); stealing them would silently re-map existing CSVs.
|
||||||
"plan_type": [
|
"plan_type": [
|
||||||
"plan_type", "plan type", "plan category", "plan_category",
|
"plan_type", "plan type", "plantype", "plan category", "plan_category",
|
||||||
"coverage type", "coverage_type", "insurance_type", "insurance type",
|
"coverage type", "coverage_type", "insurance_type", "insurance type",
|
||||||
|
"payer_type", "payer type", "lob", "line_of_business",
|
||||||
|
"line of business", "benefit_type", "benefit type",
|
||||||
],
|
],
|
||||||
"component": [
|
"component": [
|
||||||
"component", "item_type", "component_type", "type", "supply_type",
|
"component", "item_type", "component_type", "type", "supply_type",
|
||||||
|
|
@ -173,6 +179,30 @@ DATE_FORMATS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Canonicalization map for CLIENT-SUPPLIED plan-type VALUES (P5). The client
|
||||||
|
# asserted the plan type; Signal only canonicalizes spelling. Deriving plan
|
||||||
|
# type from the payer NAME remains forbidden (the never-guess lock).
|
||||||
|
PLAN_TYPE_VALUES = {
|
||||||
|
"medicare": "medicare", "medicare ffs": "medicare", "ffs": "medicare",
|
||||||
|
"medicare part b": "medicare", "part b": "medicare",
|
||||||
|
"traditional medicare": "medicare", "original medicare": "medicare",
|
||||||
|
"medicare advantage": "medicare_advantage", "ma": "medicare_advantage",
|
||||||
|
"medicare part c": "medicare_advantage", "part c": "medicare_advantage",
|
||||||
|
"medicare_advantage": "medicare_advantage",
|
||||||
|
"medicaid": "medicaid", "mcd": "medicaid", "state medicaid": "medicaid",
|
||||||
|
"commercial": "commercial", "private": "commercial",
|
||||||
|
"employer": "commercial", "group": "commercial",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_plan_type(raw: "Optional[str]") -> Optional[str]:
|
||||||
|
"""Canonicalize a CLIENT-SUPPLIED plan type value. Never called on payer
|
||||||
|
names. Unrecognized (including blank) -> None -> Plan Type Needed.
|
||||||
|
Never guess."""
|
||||||
|
s = (raw or "").strip().lower()
|
||||||
|
return PLAN_TYPE_VALUES.get(s)
|
||||||
|
|
||||||
|
|
||||||
def _normalize_key(s: str) -> str:
|
def _normalize_key(s: str) -> str:
|
||||||
return s.strip().lower().replace("-", " ").replace("_", " ")
|
return s.strip().lower().replace("-", " ").replace("_", " ")
|
||||||
|
|
||||||
|
|
@ -268,6 +298,7 @@ def normalize_csv(text: str) -> tuple[list[ShipmentRecord], list[str], dict]:
|
||||||
|
|
||||||
records: list[ShipmentRecord] = []
|
records: list[ShipmentRecord] = []
|
||||||
skipped: list[str] = []
|
skipped: list[str] = []
|
||||||
|
_warned_plan_values: set = set() # one warning per distinct value per file
|
||||||
|
|
||||||
for i, row in enumerate(reader, start=2): # noqa: B007
|
for i, row in enumerate(reader, start=2): # noqa: B007
|
||||||
mapped: dict[str, str] = {}
|
mapped: dict[str, str] = {}
|
||||||
|
|
@ -319,11 +350,19 @@ def normalize_csv(text: str) -> tuple[list[ShipmentRecord], list[str], dict]:
|
||||||
order_number = mapped.get("order_number") or None
|
order_number = mapped.get("order_number") or None
|
||||||
hcpcs = mapped.get("hcpcs") or None
|
hcpcs = mapped.get("hcpcs") or None
|
||||||
|
|
||||||
# Client-supplied plan type, carried verbatim (lowercased and trimmed
|
# Client-supplied plan type, canonicalized through the value map
|
||||||
# only — canonicalization of synonyms is a later, separate step).
|
# (spelling only — the client asserted the plan type). Unrecognized
|
||||||
# Anything the readiness engine does not recognize grades as
|
# values grade as "Plan Type Needed"; never guessed from payer name.
|
||||||
# "Plan Type Needed"; it is never guessed from the payer name.
|
raw_plan = (mapped.get("plan_type") or "").strip()
|
||||||
plan_type = (mapped.get("plan_type") or "").strip().lower() or None
|
plan_type = _normalize_plan_type(raw_plan)
|
||||||
|
if raw_plan and plan_type is None and raw_plan.lower() not in _warned_plan_values:
|
||||||
|
_warned_plan_values.add(raw_plan.lower())
|
||||||
|
logger.warning(
|
||||||
|
"Unrecognized plan_type value '%s' (first seen row %d, "
|
||||||
|
"patient hash %s) -> grades as Plan Type Needed",
|
||||||
|
raw_plan, i,
|
||||||
|
hashlib.sha256(patient_id.encode()).hexdigest()[:12],
|
||||||
|
)
|
||||||
|
|
||||||
records.append(ShipmentRecord(
|
records.append(ShipmentRecord(
|
||||||
patient_id=patient_id,
|
patient_id=patient_id,
|
||||||
|
|
|
||||||
130
python-backend/core/overrides.py
Normal file
130
python-backend/core/overrides.py
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
"""
|
||||||
|
overrides.py
|
||||||
|
Signal — STTIL Solutions
|
||||||
|
|
||||||
|
Device-keyed staff overrides (build plan 02, P4; phase-2 design Item 4).
|
||||||
|
|
||||||
|
Pilot scope is LOCKED to two override kinds:
|
||||||
|
- visit: patient-scoped (the visit is the person). It rides the existing
|
||||||
|
confirmed_visits path, which already fans out to every line of the patient
|
||||||
|
by construction (evaluate_readiness receives the confirmed date per
|
||||||
|
patient). This module does not duplicate that mechanism.
|
||||||
|
- swo / pa: line-scoped. They apply only to lines whose device_type matches;
|
||||||
|
device_type '' marks a legacy patient-scoped row and matches all devices
|
||||||
|
until staff re-saves it device-scoped.
|
||||||
|
|
||||||
|
Overrides feed the GRADING inputs (staff knowledge wins over the CSV cell,
|
||||||
|
matching the existing display precedence), then affected lines re-grade.
|
||||||
|
|
||||||
|
PHI CONTRACT: overrides carry patient_id_hash only (the storage key). Lines
|
||||||
|
carry raw patient_id; matching hashes it. Nothing here logs patient data.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import date, datetime
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
# Stored status -> display/grading label. Single source of truth; the API's
|
||||||
|
# display map imports this. The labels feed the readiness vocabularies
|
||||||
|
# ("On File" grades GOOD, "Denied" grades BAD, "Requested" grades PENDING).
|
||||||
|
STORED_STATUS_LABELS = {
|
||||||
|
"pending": "Pending",
|
||||||
|
"requested": "Requested",
|
||||||
|
"on_file": "On File",
|
||||||
|
"not_required": "Not Required",
|
||||||
|
"approved": "Approved",
|
||||||
|
"denied": "Denied",
|
||||||
|
}
|
||||||
|
|
||||||
|
# Legacy patient-scoped rows carry an empty device_type and match all devices.
|
||||||
|
LEGACY_ALL_DEVICES = ""
|
||||||
|
|
||||||
|
OVERRIDABLE_DOC_TYPES = ("swo", "pa")
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class OverrideKey:
|
||||||
|
org_id: str
|
||||||
|
patient_hash: str
|
||||||
|
device_type: str # '' = legacy patient-scoped, applies to all devices
|
||||||
|
doc_type: str # "swo" | "pa" (visit rides confirmed_visits)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Override:
|
||||||
|
key: OverrideKey
|
||||||
|
status: str # stored value, e.g. "on_file" | "approved" | "denied"
|
||||||
|
status_date: Optional[date] = None
|
||||||
|
expiry_date: Optional[date] = None
|
||||||
|
confirmed_by: str = "staff"
|
||||||
|
confirmed_at: Optional[datetime] = None
|
||||||
|
|
||||||
|
|
||||||
|
def _hash_pid(patient_id: str) -> str:
|
||||||
|
return hashlib.sha256(patient_id.encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def grading_value(override: Override) -> str:
|
||||||
|
"""The label fed to the readiness vocabularies for this override."""
|
||||||
|
return STORED_STATUS_LABELS.get(override.status, override.status)
|
||||||
|
|
||||||
|
|
||||||
|
def overrides_from_saved(saved: dict) -> list[Override]:
|
||||||
|
"""Build Override objects from the persistence load shape:
|
||||||
|
patient_hash -> device_type -> doc_type -> {status, status_date, ...}."""
|
||||||
|
out: list[Override] = []
|
||||||
|
for patient_hash, by_device in (saved or {}).items():
|
||||||
|
for device_type, by_doc in by_device.items():
|
||||||
|
for doc_type, row in by_doc.items():
|
||||||
|
if doc_type not in OVERRIDABLE_DOC_TYPES:
|
||||||
|
continue
|
||||||
|
out.append(
|
||||||
|
Override(
|
||||||
|
key=OverrideKey(
|
||||||
|
org_id="",
|
||||||
|
patient_hash=patient_hash,
|
||||||
|
device_type=device_type,
|
||||||
|
doc_type=doc_type,
|
||||||
|
),
|
||||||
|
status=row.get("status", ""),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def apply_overrides(lines: dict, overrides: list[Override]) -> set[str]:
|
||||||
|
"""Apply swo/pa overrides onto the grading inputs of matching lines.
|
||||||
|
|
||||||
|
Mutates each matching line's current_shipment csv fields (staff knowledge
|
||||||
|
wins over the CSV cell). Device-scoped rows win over legacy '' rows.
|
||||||
|
Returns the raw patient_ids of touched lines. Grading (or re-grading)
|
||||||
|
happens in the caller — build_readiness_index grades after application.
|
||||||
|
"""
|
||||||
|
if not overrides:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
by_patient: dict[str, list[Override]] = {}
|
||||||
|
for o in overrides:
|
||||||
|
by_patient.setdefault(o.key.patient_hash, []).append(o)
|
||||||
|
|
||||||
|
touched: set[str] = set()
|
||||||
|
for line in lines.values():
|
||||||
|
patient_overrides = by_patient.get(_hash_pid(line.patient_id))
|
||||||
|
if not patient_overrides:
|
||||||
|
continue
|
||||||
|
# Legacy '' first so a device-scoped row applied after it wins.
|
||||||
|
for o in sorted(
|
||||||
|
patient_overrides, key=lambda o: o.key.device_type != LEGACY_ALL_DEVICES
|
||||||
|
):
|
||||||
|
if o.key.device_type not in (LEGACY_ALL_DEVICES, line.device_type):
|
||||||
|
continue
|
||||||
|
label = grading_value(o)
|
||||||
|
if o.key.doc_type == "swo":
|
||||||
|
line.current_shipment.csv_swo_status = label
|
||||||
|
elif o.key.doc_type == "pa":
|
||||||
|
line.current_shipment.csv_pa_status = label
|
||||||
|
touched.add(line.patient_id)
|
||||||
|
return touched
|
||||||
|
|
@ -227,9 +227,12 @@ def upsert_doc_status(
|
||||||
status: str,
|
status: str,
|
||||||
status_date: "date | None" = None,
|
status_date: "date | None" = None,
|
||||||
expiry_date: "date | None" = None,
|
expiry_date: "date | None" = None,
|
||||||
|
device_type: str = "",
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Insert or update a doc status (swo or pa) for a patient.
|
Insert or update a doc status (swo or pa), scoped to a device.
|
||||||
|
device_type '' writes a legacy patient-scoped row (applies to all of the
|
||||||
|
patient's devices until a device-scoped row is saved).
|
||||||
Returns True on success, False if Supabase unavailable.
|
Returns True on success, False if Supabase unavailable.
|
||||||
"""
|
"""
|
||||||
client = get_client()
|
client = get_client()
|
||||||
|
|
@ -241,6 +244,7 @@ def upsert_doc_status(
|
||||||
"patient_id_hash": patient_id_hash,
|
"patient_id_hash": patient_id_hash,
|
||||||
"doc_type": doc_type,
|
"doc_type": doc_type,
|
||||||
"status": status,
|
"status": status,
|
||||||
|
"device_type": device_type or "",
|
||||||
"updated_at": "now()",
|
"updated_at": "now()",
|
||||||
}
|
}
|
||||||
if status_date is not None:
|
if status_date is not None:
|
||||||
|
|
@ -248,7 +252,7 @@ def upsert_doc_status(
|
||||||
if expiry_date is not None:
|
if expiry_date is not None:
|
||||||
payload["expiry_date"] = expiry_date.isoformat()
|
payload["expiry_date"] = expiry_date.isoformat()
|
||||||
client.table("doc_status").upsert(
|
client.table("doc_status").upsert(
|
||||||
payload, on_conflict="org_id,patient_id_hash,doc_type"
|
payload, on_conflict="org_id,patient_id_hash,doc_type,device_type"
|
||||||
).execute()
|
).execute()
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -258,23 +262,24 @@ def upsert_doc_status(
|
||||||
|
|
||||||
def load_doc_statuses_for_org(org_id: str) -> dict:
|
def load_doc_statuses_for_org(org_id: str) -> dict:
|
||||||
"""
|
"""
|
||||||
Load all SWO and PA statuses for an org.
|
Load all SWO and PA statuses for an org, device-scoped.
|
||||||
Returns dict: patient_id_hash -> {doc_type: {status, status_date, expiry_date}}
|
Returns dict: patient_id_hash -> device_type -> {doc_type: {status,
|
||||||
|
status_date, expiry_date}}. The '' device bucket holds legacy
|
||||||
|
patient-scoped rows (they apply to every device until re-saved).
|
||||||
"""
|
"""
|
||||||
client = get_client()
|
client = get_client()
|
||||||
if not client:
|
if not client:
|
||||||
return {}
|
return {}
|
||||||
try:
|
try:
|
||||||
result = client.table("doc_status") \
|
result = client.table("doc_status") \
|
||||||
.select("patient_id_hash,doc_type,status,status_date,expiry_date") \
|
.select("patient_id_hash,device_type,doc_type,status,status_date,expiry_date") \
|
||||||
.eq("org_id", org_id) \
|
.eq("org_id", org_id) \
|
||||||
.execute()
|
.execute()
|
||||||
out: dict = {}
|
out: dict = {}
|
||||||
for row in (result.data or []):
|
for row in (result.data or []):
|
||||||
h = row["patient_id_hash"]
|
h = row["patient_id_hash"]
|
||||||
if h not in out:
|
device = row.get("device_type") or ""
|
||||||
out[h] = {}
|
out.setdefault(h, {}).setdefault(device, {})[row["doc_type"]] = {
|
||||||
out[h][row["doc_type"]] = {
|
|
||||||
"status": row["status"],
|
"status": row["status"],
|
||||||
"status_date": row.get("status_date"),
|
"status_date": row.get("status_date"),
|
||||||
"expiry_date": row.get("expiry_date"),
|
"expiry_date": row.get("expiry_date"),
|
||||||
|
|
|
||||||
|
|
@ -82,18 +82,27 @@ def _confirmed_for(
|
||||||
def build_readiness_index(
|
def build_readiness_index(
|
||||||
records: list[ShipmentRecord],
|
records: list[ShipmentRecord],
|
||||||
confirmed_visits: Optional[dict[str, date]] = None,
|
confirmed_visits: Optional[dict[str, date]] = None,
|
||||||
|
overrides: Optional[list] = None,
|
||||||
) -> ReadinessIndex:
|
) -> ReadinessIndex:
|
||||||
"""Dedup records into coverage lines, grade each gradeable line, and
|
"""Dedup records into coverage lines, apply staff overrides to the
|
||||||
record the group->line membership map so row-level resolution never
|
grading inputs (P4: swo/pa device-scoped; staff knowledge wins over the
|
||||||
re-derives it.
|
CSV cell), grade each gradeable line, and record the group->line
|
||||||
|
membership map so row-level resolution never re-derives it.
|
||||||
|
|
||||||
Grades the CURRENT shipment only (latest DOS per line — locked rule);
|
Grades the CURRENT shipment only (latest DOS per line — locked rule);
|
||||||
prior shipments are collapsed history. Non-gradeable lines are skipped.
|
prior shipments are collapsed history. Non-gradeable lines are skipped.
|
||||||
|
Visit overrides arrive via confirmed_visits (patient-scoped fan-out by
|
||||||
|
construction).
|
||||||
"""
|
"""
|
||||||
confirmed_visits = confirmed_visits or {}
|
confirmed_visits = confirmed_visits or {}
|
||||||
merged = dedup(records)
|
merged = dedup(records)
|
||||||
lines = assign_to_coverage_lines(merged)
|
lines = assign_to_coverage_lines(merged)
|
||||||
|
|
||||||
|
if overrides:
|
||||||
|
from core.overrides import apply_overrides
|
||||||
|
|
||||||
|
apply_overrides(lines, overrides)
|
||||||
|
|
||||||
index = ReadinessIndex()
|
index = ReadinessIndex()
|
||||||
for key, line in lines.items():
|
for key, line in lines.items():
|
||||||
line_key = (key.patient_id, key.device_type, key.plan_type_id)
|
line_key = (key.patient_id, key.device_type, key.plan_type_id)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const FIELD_LABELS = {
|
||||||
shipment_date: "Shipment Date",
|
shipment_date: "Shipment Date",
|
||||||
quantity: "Quantity",
|
quantity: "Quantity",
|
||||||
payer: "Payer",
|
payer: "Payer",
|
||||||
|
plan_type: "Plan Type",
|
||||||
component: "Component",
|
component: "Component",
|
||||||
csv_visit_date: "Visit Date",
|
csv_visit_date: "Visit Date",
|
||||||
csv_swo_status: "SWO Status",
|
csv_swo_status: "SWO Status",
|
||||||
|
|
@ -25,6 +26,7 @@ const OVERRIDE_OPTIONS = [
|
||||||
{ value: "shipment_date", label: "Shipment Date" },
|
{ value: "shipment_date", label: "Shipment Date" },
|
||||||
{ value: "quantity", label: "Quantity" },
|
{ value: "quantity", label: "Quantity" },
|
||||||
{ value: "payer", label: "Payer" },
|
{ value: "payer", label: "Payer" },
|
||||||
|
{ value: "plan_type", label: "Plan Type" },
|
||||||
{ value: "skip", label: "Skip this column" },
|
{ value: "skip", label: "Skip this column" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -347,22 +347,22 @@ export default function WorklistTable({ records, activeFilter, onFilterChange, o
|
||||||
<div className="grid grid-cols-2 gap-y-[6px] gap-x-[20px] text-[12px]">
|
<div className="grid grid-cols-2 gap-y-[6px] gap-x-[20px] text-[12px]">
|
||||||
<DocItem
|
<DocItem
|
||||||
label="SWO"
|
label="SWO"
|
||||||
value={localDocStates[r.patient_id]?.swo ?? r.doc_state.swo}
|
value={localDocStates[`${r.patient_id}:${r.device_type}`]?.swo ?? r.doc_state.swo}
|
||||||
patientId={r.patient_id} docType="swo" cycle={SWO_CYCLE}
|
patientId={r.patient_id} deviceType={r.device_type} docType="swo" cycle={SWO_CYCLE}
|
||||||
getToken={getToken}
|
getToken={getToken}
|
||||||
onUpdated={(type, label) => setLocalDocStates(prev => ({
|
onUpdated={(type, label) => setLocalDocStates(prev => ({
|
||||||
...prev, [r.patient_id]: { ...prev[r.patient_id], [type]: label }
|
...prev, [`${r.patient_id}:${r.device_type}`]: { ...prev[`${r.patient_id}:${r.device_type}`], [type]: label }
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
<DocItem label="Qualifying Visit" value={r.doc_state.visit} />
|
<DocItem label="Qualifying Visit" value={r.doc_state.visit} />
|
||||||
<DocItem label="PECOS Enrollment" value={r.doc_state.pecos} />
|
<DocItem label="PECOS Enrollment" value={r.doc_state.pecos} />
|
||||||
<DocItem
|
<DocItem
|
||||||
label="Prior Authorization"
|
label="Prior Authorization"
|
||||||
value={localDocStates[r.patient_id]?.pa ?? r.doc_state.pa}
|
value={localDocStates[`${r.patient_id}:${r.device_type}`]?.pa ?? r.doc_state.pa}
|
||||||
patientId={r.patient_id} docType="pa" cycle={PA_CYCLE}
|
patientId={r.patient_id} deviceType={r.device_type} docType="pa" cycle={PA_CYCLE}
|
||||||
getToken={getToken}
|
getToken={getToken}
|
||||||
onUpdated={(type, label) => setLocalDocStates(prev => ({
|
onUpdated={(type, label) => setLocalDocStates(prev => ({
|
||||||
...prev, [r.patient_id]: { ...prev[r.patient_id], [type]: label }
|
...prev, [`${r.patient_id}:${r.device_type}`]: { ...prev[`${r.patient_id}:${r.device_type}`], [type]: label }
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
<DocItem label="Diagnosis on File" value={r.doc_state.diagnosis} />
|
<DocItem label="Diagnosis on File" value={r.doc_state.diagnosis} />
|
||||||
|
|
@ -492,7 +492,7 @@ function ActionCell({ flag, cascade, showConfirmVisit, onConfirmVisit, onExpand
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function DocItem({ label, value, patientId, docType, cycle, getToken, onUpdated }) {
|
function DocItem({ label, value, patientId, deviceType = "", docType, cycle, getToken, onUpdated }) {
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
|
|
||||||
const isGood = value && (
|
const isGood = value && (
|
||||||
|
|
@ -514,7 +514,7 @@ function DocItem({ label, value, patientId, docType, cycle, getToken, onUpdated
|
||||||
const nextLabel = DOC_STATUS_LABELS[nextKey];
|
const nextLabel = DOC_STATUS_LABELS[nextKey];
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
const token = getToken ? await getToken().catch(() => null) : null;
|
const token = getToken ? await getToken().catch(() => null) : null;
|
||||||
const result = await updateDocStatus(patientId, docType, nextKey, null, null, token);
|
const result = await updateDocStatus(patientId, docType, nextKey, null, null, token, deviceType);
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
if (result && onUpdated) onUpdated(docType, nextLabel);
|
if (result && onUpdated) onUpdated(docType, nextLabel);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ export async function confirmVisit(payload, token = null) {
|
||||||
* @param {string|null} token - Clerk JWT
|
* @param {string|null} token - Clerk JWT
|
||||||
* @returns {Promise<{patient_id, doc_type, status, display}|null>}
|
* @returns {Promise<{patient_id, doc_type, status, display}|null>}
|
||||||
*/
|
*/
|
||||||
export async function updateDocStatus(patientId, docType, status, statusDate = null, expiryDate = null, token = null) {
|
export async function updateDocStatus(patientId, docType, status, statusDate = null, expiryDate = null, token = null, deviceType = "") {
|
||||||
const authHeader = token
|
const authHeader = token
|
||||||
? { "Authorization": `Bearer ${token}` }
|
? { "Authorization": `Bearer ${token}` }
|
||||||
: {};
|
: {};
|
||||||
|
|
@ -153,6 +153,9 @@ export async function updateDocStatus(patientId, docType, status, statusDate = n
|
||||||
patient_id: patientId,
|
patient_id: patientId,
|
||||||
doc_type: docType,
|
doc_type: docType,
|
||||||
status,
|
status,
|
||||||
|
// Device scope (P4): an SWO/PA update applies to this device's line
|
||||||
|
// only, never to every device the patient has.
|
||||||
|
...(deviceType && { device_type: deviceType }),
|
||||||
...(statusDate && { status_date: statusDate }),
|
...(statusDate && { status_date: statusDate }),
|
||||||
...(expiryDate && { expiry_date: expiryDate }),
|
...(expiryDate && { expiry_date: expiryDate }),
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1001,freestyle_libre_3,2026-05-10,9,Medicaid - GA,sensor
|
PT-1001,freestyle_libre_3,2026-05-10,9,Medicaid - GA,sensor,medicaid
|
||||||
PT-1002,freestyle_libre_3,2026-05-10,9,Medicaid - GA,sensor
|
PT-1002,freestyle_libre_3,2026-05-10,9,Medicaid - GA,sensor,medicaid
|
||||||
PT-1003,freestyle_libre_3,2026-05-15,1,Medicaid - GA,sensor
|
PT-1003,freestyle_libre_3,2026-05-15,1,Medicaid - GA,sensor,medicaid
|
||||||
PT-1004,freestyle_libre_3,2026-05-09,1,Medicaid - GA,sensor
|
PT-1004,freestyle_libre_3,2026-05-09,1,Medicaid - GA,sensor,medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1001,FSL3,2026-05-03,9,Medicare Part A,sensor
|
PT-1001,FSL3,2026-05-03,9,Medicare Part A,sensor,medicare
|
||||||
PT-1002,FreeStyle Libre 3,2026-05-03,6,Medicare Part A,sensor
|
PT-1002,FreeStyle Libre 3,2026-05-03,6,Medicare Part A,sensor,medicare
|
||||||
PT-1003,fs libre 3,2026-04-29,1,Medicare Part A,sensor
|
PT-1003,fs libre 3,2026-04-29,1,Medicare Part A,sensor,medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1001,Omnipod,2025-04-27,6,Medicare Part B - CGM,pod
|
PT-1001,Omnipod,2025-04-27,6,Medicare Part B - CGM,pod,medicare
|
||||||
PT-1002,Omnipod,2025-07-18,2,Medicare Part B - CGM,pod
|
PT-1002,Omnipod,2025-07-18,2,Medicare Part B - CGM,pod,medicare
|
||||||
PT-1003,Omnipod 5,2025-07-15,6,Medicare Part B - CGM,pod
|
PT-1003,Omnipod 5,2025-07-15,6,Medicare Part B - CGM,pod,medicare
|
||||||
PT-1004,OmniPod 5,2025-05-16,9,Medicare Part B - CGM,pod
|
PT-1004,OmniPod 5,2025-05-16,9,Medicare Part B - CGM,pod,medicare
|
||||||
PT-1005,Omnipod 5,2025-07-02,6,Medicare Part B - CGM,pod
|
PT-1005,Omnipod 5,2025-07-02,6,Medicare Part B - CGM,pod,medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Patient ID,Item Description,Service Date,Qty,Insurance Name,Item Type,Prescriber NPI,Branch
|
Patient ID,Item Description,Service Date,Qty,Insurance Name,Item Type,Prescriber NPI,Branch,payer_type
|
||||||
PT-1011,FreeStyle Libre 3,12/15/2024,1,Aetna Commercial,sensor,1234567890,PA-001
|
PT-1011,FreeStyle Libre 3,12/15/2024,1,Aetna Commercial,sensor,1234567890,PA-001,employer
|
||||||
PT-1012,FSL3,12/26/2024,1,Aetna Commercial,sensor,1234567890,PA-001
|
PT-1012,FSL3,12/26/2024,1,Aetna Commercial,sensor,1234567890,PA-001,employer
|
||||||
PT-1013,FreeStyle Libre 3,11/06/2024,6,Aetna Commercial,sensor,1234567890,PA-001
|
PT-1013,FreeStyle Libre 3,11/06/2024,6,Aetna Commercial,sensor,1234567890,PA-001,employer
|
||||||
PT-1014,FSL3,11/09/2024,2,Aetna Commercial,sensor,1234567890,PA-001
|
PT-1014,FSL3,11/09/2024,2,Aetna Commercial,sensor,1234567890,PA-001,employer
|
||||||
PT-1015,Libre 3,11/20/2024,3,Aetna Commercial,sensor,1234567890,PA-001
|
PT-1015,Libre 3,11/20/2024,3,Aetna Commercial,sensor,1234567890,PA-001,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1011,dexcom_g7,2025-06-22,9,UnitedHealth,sensor
|
PT-1011,dexcom_g7,2025-06-22,9,UnitedHealth,sensor,commercial
|
||||||
PT-1012,dexcom_g7,2025-06-18,2,UnitedHealth,sensor
|
PT-1012,dexcom_g7,2025-06-18,2,UnitedHealth,sensor,commercial
|
||||||
PT-1013,dexcom_g7,2025-06-19,9,UnitedHealth,sensor
|
PT-1013,dexcom_g7,2025-06-19,9,UnitedHealth,sensor,commercial
|
||||||
PT-1014,dexcom_g7,2025-06-16,1,UnitedHealth,sensor
|
PT-1014,dexcom_g7,2025-06-16,1,UnitedHealth,sensor,commercial
|
||||||
PT-1015,dexcom_g7,2025-06-14,6,UnitedHealth,sensor
|
PT-1015,dexcom_g7,2025-06-14,6,UnitedHealth,sensor,commercial
|
||||||
PT-1016,dexcom_g7,2025-06-17,3,UnitedHealth,sensor
|
PT-1016,dexcom_g7,2025-06-17,3,UnitedHealth,sensor,commercial
|
||||||
PT-1017,dexcom_g7,2025-06-14,2,UnitedHealth,sensor
|
PT-1017,dexcom_g7,2025-06-14,2,UnitedHealth,sensor,commercial
|
||||||
PT-1018,dexcom_g7,2025-06-17,1,UnitedHealth,sensor
|
PT-1018,dexcom_g7,2025-06-17,1,UnitedHealth,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1021,dexcom_g7,2026-05-19,1,BCBS - FL,sensor
|
PT-1021,dexcom_g7,2026-05-19,1,BCBS - FL,sensor,commercial
|
||||||
PT-1022,dexcom_g7,2026-05-22,9,BCBS - FL,sensor
|
PT-1022,dexcom_g7,2026-05-22,9,BCBS - FL,sensor,commercial
|
||||||
PT-1023,dexcom_g7,2026-05-16,6,BCBS - FL,sensor
|
PT-1023,dexcom_g7,2026-05-16,6,BCBS - FL,sensor,commercial
|
||||||
PT-1024,dexcom_g7,2026-05-16,9,BCBS - FL,sensor
|
PT-1024,dexcom_g7,2026-05-16,9,BCBS - FL,sensor,commercial
|
||||||
PT-1025,dexcom_g7,2026-05-19,9,BCBS - FL,sensor
|
PT-1025,dexcom_g7,2026-05-19,9,BCBS - FL,sensor,commercial
|
||||||
PT-1026,dexcom_g7,2026-05-20,9,BCBS - FL,sensor
|
PT-1026,dexcom_g7,2026-05-20,9,BCBS - FL,sensor,commercial
|
||||||
PT-1027,dexcom_g7,2026-05-18,1,BCBS - FL,sensor
|
PT-1027,dexcom_g7,2026-05-18,1,BCBS - FL,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
PT_ID,DEVICE,SHIP DATE,UNITS,CARRIER,TYPE
|
PT_ID,DEVICE,SHIP DATE,UNITS,CARRIER,TYPE,payer_type
|
||||||
PT-1021,G7,2025-01-04,6,Medicaid - PA,sensor
|
PT-1021,G7,2025-01-04,6,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1022,G7,2024-11-21,3,Medicaid - PA,sensor
|
PT-1022,G7,2024-11-21,3,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1023,Dexcom G7,2025-01-14,2,Medicaid - PA,sensor
|
PT-1023,Dexcom G7,2025-01-14,2,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1024,Dexcom G7 CGM,2024-10-12,6,Medicaid - PA,sensor
|
PT-1024,Dexcom G7 CGM,2024-10-12,6,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1025,G7,2024-11-05,9,Medicaid - PA,sensor
|
PT-1025,G7,2024-11-05,9,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1026,G7,2025-01-03,6,Medicaid - PA,sensor
|
PT-1026,G7,2025-01-03,6,Medicaid - PA,sensor,state medicaid
|
||||||
PT-1027,dexcom g7,2024-11-26,2,Medicaid - PA,sensor
|
PT-1027,dexcom g7,2024-11-26,2,Medicaid - PA,sensor,state medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
PT_ID,DEVICE,SHIP DATE,UNITS,CARRIER,TYPE
|
PT_ID,DEVICE,SHIP DATE,UNITS,CARRIER,TYPE,Coverage Type
|
||||||
PT-1021,Dexcom G6 Pro,2026-05-03,2,Humana,sensor
|
PT-1021,Dexcom G6 Pro,2026-05-03,2,Humana,sensor,Commercial
|
||||||
PT-1022,G6,2026-04-29,3,Humana,sensor
|
PT-1022,G6,2026-04-29,3,Humana,sensor,Commercial
|
||||||
PT-1023,Dexcom G6,2026-05-05,9,Humana,sensor
|
PT-1023,Dexcom G6,2026-05-05,9,Humana,sensor,Commercial
|
||||||
PT-1024,G6,2026-05-01,2,Humana,sensor
|
PT-1024,G6,2026-05-01,2,Humana,sensor,Commercial
|
||||||
PT-1025,Dexcom G6 Pro,2026-05-01,9,Humana,sensor
|
PT-1025,Dexcom G6 Pro,2026-05-01,9,Humana,sensor,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1031,freestyle_libre_3,2026-05-18,3,Medicare Part B,sensor
|
PT-1031,freestyle_libre_3,2026-05-18,3,Medicare Part B,sensor,medicare
|
||||||
PT-1032,freestyle_libre_3,2026-05-19,3,Medicare Part B,sensor
|
PT-1032,freestyle_libre_3,2026-05-19,3,Medicare Part B,sensor,medicare
|
||||||
PT-1033,freestyle_libre_3,2026-05-14,3,Medicare Part B,sensor
|
PT-1033,freestyle_libre_3,2026-05-14,3,Medicare Part B,sensor,medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
MRN,Product Name,Dispense Date,Qty Dispensed,Plan Name,Supply Type,Supplier,State
|
MRN,Product Name,Dispense Date,Qty Dispensed,Plan Name,Supply Type,Supplier,State,payer_type
|
||||||
PT-1031,FreestyleLibre3,09-Nov-2024,6,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1031,FreestyleLibre3,09-Nov-2024,6,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1032,FSL3,18-Dec-2024,2,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1032,FSL3,18-Dec-2024,2,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1033,fs libre 3,23-Oct-2024,1,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1033,fs libre 3,23-Oct-2024,1,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1034,FreeStyle Libre 3,06-Jan-2025,2,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1034,FreeStyle Libre 3,06-Jan-2025,2,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1035,fs libre 3,22-Dec-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1035,fs libre 3,22-Dec-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1036,fs libre 3,13-Oct-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1036,fs libre 3,13-Oct-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
PT-1037,FSL3,04-Dec-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA
|
PT-1037,FSL3,04-Dec-2024,9,Medicare Part B - CGM,sensor,Gaboro DME,PA,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
MRN,Product Name,Dispense Date,Qty Dispensed,Plan Name,Supply Type,Supplier,State
|
MRN,Product Name,Dispense Date,Qty Dispensed,Plan Name,Supply Type,Supplier,State,Coverage Type
|
||||||
PT-1031,Dexcom G6,02-May-2026,3,Medicaid,sensor,Gaboro DME,PA
|
PT-1031,Dexcom G6,02-May-2026,3,Medicaid,sensor,Gaboro DME,PA,Medicaid
|
||||||
PT-1032,Dexcom G6,30-Apr-2026,2,Medicaid,sensor,Gaboro DME,PA
|
PT-1032,Dexcom G6,30-Apr-2026,2,Medicaid,sensor,Gaboro DME,PA,Medicaid
|
||||||
PT-1033,Dexcom G6 Pro,04-May-2026,2,Medicaid,sensor,Gaboro DME,PA
|
PT-1033,Dexcom G6 Pro,04-May-2026,2,Medicaid,sensor,Gaboro DME,PA,Medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1041,freestyle_libre_3,2024-10-23,9,Cigna,sensor
|
PT-1041,freestyle_libre_3,2024-10-23,9,Cigna,sensor,commercial
|
||||||
PT-1042,freestyle_libre_3,2024-11-01,2,Cigna,sensor
|
PT-1042,freestyle_libre_3,2024-11-01,2,Cigna,sensor,commercial
|
||||||
PT-1043,freestyle_libre_3,2024-10-30,2,Cigna,sensor
|
PT-1043,freestyle_libre_3,2024-10-30,2,Cigna,sensor,commercial
|
||||||
PT-1044,freestyle_libre_3,2024-10-24,6,Cigna,sensor
|
PT-1044,freestyle_libre_3,2024-10-24,6,Cigna,sensor,commercial
|
||||||
PT-1045,freestyle_libre_3,2024-10-28,3,Cigna,sensor
|
PT-1045,freestyle_libre_3,2024-10-28,3,Cigna,sensor,commercial
|
||||||
PT-1046,freestyle_libre_3,2024-11-01,9,Cigna,sensor
|
PT-1046,freestyle_libre_3,2024-11-01,9,Cigna,sensor,commercial
|
||||||
PT-1047,freestyle_libre_3,2024-10-25,3,Cigna,sensor
|
PT-1047,freestyle_libre_3,2024-10-25,3,Cigna,sensor,commercial
|
||||||
PT-1048,freestyle_libre_3,2024-10-22,2,Cigna,sensor
|
PT-1048,freestyle_libre_3,2024-10-22,2,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Account Number,Product,Fill Date,Count,Primary Payer,component
|
Account Number,Product,Fill Date,Count,Primary Payer,component,Coverage Type
|
||||||
PT-1041,Dexcom G7 CGM,05/05/26,3,Medicaid - GA,sensor
|
PT-1041,Dexcom G7 CGM,05/05/26,3,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1042,dexcom g7,04/27/26,2,Medicaid - GA,sensor
|
PT-1042,dexcom g7,04/27/26,2,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1043,Dexcom G7 CGM,04/28/26,9,Medicaid - GA,sensor
|
PT-1043,Dexcom G7 CGM,04/28/26,9,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1044,Dexcom G7,04/30/26,3,Medicaid - GA,sensor
|
PT-1044,Dexcom G7,04/30/26,3,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1045,G7,05/04/26,2,Medicaid - GA,sensor
|
PT-1045,G7,05/04/26,2,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1046,G7,05/03/26,9,Medicaid - GA,sensor
|
PT-1046,G7,05/03/26,9,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1047,Dexcom G7 CGM,04/29/26,6,Medicaid - GA,sensor
|
PT-1047,Dexcom G7 CGM,04/29/26,6,Medicaid - GA,sensor,Medicaid
|
||||||
PT-1048,Dexcom G7 CGM,04/25/26,3,Medicaid - GA,sensor
|
PT-1048,Dexcom G7 CGM,04/25/26,3,Medicaid - GA,sensor,Medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1051,omnipod_5,2026-05-23,3,BCBS - FL,pod
|
PT-1051,omnipod_5,2026-05-23,3,BCBS - FL,pod,commercial
|
||||||
PT-1052,omnipod_5,2026-05-17,6,BCBS - FL,pod
|
PT-1052,omnipod_5,2026-05-17,6,BCBS - FL,pod,commercial
|
||||||
PT-1053,omnipod_5,2026-05-20,6,BCBS - FL,pod
|
PT-1053,omnipod_5,2026-05-20,6,BCBS - FL,pod,commercial
|
||||||
PT-1054,omnipod_5,2026-05-16,3,BCBS - FL,pod
|
PT-1054,omnipod_5,2026-05-16,3,BCBS - FL,pod,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
External Patient Ref,Item,Date of Service,Qty Shipped,Insurance,item_type,Notes
|
External Patient Ref,Item,Date of Service,Qty Shipped,Insurance,item_type,Notes,Coverage Type
|
||||||
PT-1051,dexcom g6,2026-04-30T00:00:00,1,Medicare Part B - CGM,sensor,batch export
|
PT-1051,dexcom g6,2026-04-30T00:00:00,1,Medicare Part B - CGM,sensor,batch export,Medicare
|
||||||
PT-1052,G6,2026-05-05T00:00:00,2,Medicare Part B - CGM,sensor,batch export
|
PT-1052,G6,2026-05-05T00:00:00,2,Medicare Part B - CGM,sensor,batch export,Medicare
|
||||||
PT-1053,G6,2026-05-03T00:00:00,3,Medicare Part B - CGM,sensor,batch export
|
PT-1053,G6,2026-05-03T00:00:00,3,Medicare Part B - CGM,sensor,batch export,Medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
External Patient Ref,Item,Date of Service,Qty Shipped,Insurance,item_type,Notes
|
External Patient Ref,Item,Date of Service,Qty Shipped,Insurance,item_type,Notes,payer_type
|
||||||
PT-1051,Dexcom G7,2025-08-10T00:00:00,6,Medicare,sensor,batch export
|
PT-1051,Dexcom G7,2025-08-10T00:00:00,6,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1052,dexcom g7,2025-07-30T00:00:00,9,Medicare,sensor,batch export
|
PT-1052,dexcom g7,2025-07-30T00:00:00,9,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1053,Dexcom G7,2025-06-27T00:00:00,1,Medicare,sensor,batch export
|
PT-1053,Dexcom G7,2025-06-27T00:00:00,1,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1054,Dexcom G7 CGM,2025-09-10T00:00:00,3,Medicare,sensor,batch export
|
PT-1054,Dexcom G7 CGM,2025-09-10T00:00:00,3,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1055,dexcom g7,2025-05-20T00:00:00,2,Medicare,sensor,batch export
|
PT-1055,dexcom g7,2025-05-20T00:00:00,2,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1056,Dexcom G7 CGM,2025-08-14T00:00:00,9,Medicare,sensor,batch export
|
PT-1056,Dexcom G7 CGM,2025-08-14T00:00:00,9,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1057,Dexcom G7,2025-06-08T00:00:00,3,Medicare,sensor,batch export
|
PT-1057,Dexcom G7,2025-06-08T00:00:00,3,Medicare,sensor,batch export,Medicare Part B
|
||||||
PT-1058,G7,2025-08-31T00:00:00,2,Medicare,sensor,batch export
|
PT-1058,G7,2025-08-31T00:00:00,2,Medicare,sensor,batch export,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
Acct #,DME,Order Date,quantity,plan,component_type
|
Acct #,DME,Order Date,quantity,plan,component_type,LOB
|
||||||
PT-1061,OmniPod 5,20260523,6,United Healthcare,pod
|
PT-1061,OmniPod 5,20260523,6,United Healthcare,pod,private
|
||||||
PT-1062,op5,20260523,1,United Healthcare,pod
|
PT-1062,op5,20260523,1,United Healthcare,pod,private
|
||||||
PT-1063,Omnipod 5,20260519,3,United Healthcare,pod
|
PT-1063,Omnipod 5,20260519,3,United Healthcare,pod,private
|
||||||
PT-1064,Omnipod,20260519,9,United Healthcare,pod
|
PT-1064,Omnipod,20260519,9,United Healthcare,pod,private
|
||||||
PT-1065,Omnipod 5,20260518,1,United Healthcare,pod
|
PT-1065,Omnipod 5,20260518,1,United Healthcare,pod,private
|
||||||
PT-1066,Omnipod 5,20260518,3,United Healthcare,pod
|
PT-1066,Omnipod 5,20260518,3,United Healthcare,pod,private
|
||||||
PT-1067,Omnipod,20260520,3,United Healthcare,pod
|
PT-1067,Omnipod,20260520,3,United Healthcare,pod,private
|
||||||
PT-1068,Omnipod,20260523,9,United Healthcare,pod
|
PT-1068,Omnipod,20260523,9,United Healthcare,pod,private
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Acct #,DME,Order Date,quantity,plan,component_type
|
Acct #,DME,Order Date,quantity,plan,component_type,Coverage Type
|
||||||
PT-1061,FSL3,20260429,6,United Healthcare,sensor
|
PT-1061,FSL3,20260429,6,United Healthcare,sensor,Commercial
|
||||||
PT-1062,FSL3,20260425,3,United Healthcare,sensor
|
PT-1062,FSL3,20260425,3,United Healthcare,sensor,Commercial
|
||||||
PT-1063,Libre 3,20260426,9,United Healthcare,sensor
|
PT-1063,Libre 3,20260426,9,United Healthcare,sensor,Commercial
|
||||||
PT-1064,fs libre 3,20260425,1,United Healthcare,sensor
|
PT-1064,fs libre 3,20260425,1,United Healthcare,sensor,Commercial
|
||||||
PT-1065,Libre 3,20260505,2,United Healthcare,sensor
|
PT-1065,Libre 3,20260505,2,United Healthcare,sensor,Commercial
|
||||||
PT-1066,FreestyleLibre3,20260503,2,United Healthcare,sensor
|
PT-1066,FreestyleLibre3,20260503,2,United Healthcare,sensor,Commercial
|
||||||
PT-1067,FreestyleLibre3,20260501,6,United Healthcare,sensor
|
PT-1067,FreestyleLibre3,20260501,6,United Healthcare,sensor,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1061,freestyle_libre_3,2025-06-25,6,Cigna,sensor
|
PT-1061,freestyle_libre_3,2025-06-25,6,Cigna,sensor,commercial
|
||||||
PT-1062,freestyle_libre_3,2025-06-21,2,Cigna,sensor
|
PT-1062,freestyle_libre_3,2025-06-21,2,Cigna,sensor,commercial
|
||||||
PT-1063,freestyle_libre_3,2025-06-18,9,Cigna,sensor
|
PT-1063,freestyle_libre_3,2025-06-18,9,Cigna,sensor,commercial
|
||||||
PT-1064,freestyle_libre_3,2025-06-23,1,Cigna,sensor
|
PT-1064,freestyle_libre_3,2025-06-23,1,Cigna,sensor,commercial
|
||||||
PT-1065,freestyle_libre_3,2025-06-16,1,Cigna,sensor
|
PT-1065,freestyle_libre_3,2025-06-16,1,Cigna,sensor,commercial
|
||||||
PT-1066,freestyle_libre_3,2025-06-18,2,Cigna,sensor
|
PT-1066,freestyle_libre_3,2025-06-18,2,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
patient,device type,last ship date,units dispensed,payer name,type,Supplier Branch
|
patient,device type,last ship date,units dispensed,payer name,type,Supplier Branch,payer_type
|
||||||
PT-1071,Omnipod 5,10/26/2024,6,Medicare Part A,pod,NY-003
|
PT-1071,Omnipod 5,10/26/2024,6,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
PT-1072,op5,11/19/2024,6,Medicare Part A,pod,NY-003
|
PT-1072,op5,11/19/2024,6,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
PT-1073,Omnipod 5,01/03/2025,1,Medicare Part A,pod,NY-003
|
PT-1073,Omnipod 5,01/03/2025,1,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
PT-1074,OmniPod 5,11/27/2024,1,Medicare Part A,pod,NY-003
|
PT-1074,OmniPod 5,11/27/2024,1,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
PT-1075,Omnipod,11/03/2024,9,Medicare Part A,pod,NY-003
|
PT-1075,Omnipod,11/03/2024,9,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
PT-1076,op5,11/29/2024,2,Medicare Part A,pod,NY-003
|
PT-1076,op5,11/29/2024,2,Medicare Part A,pod,NY-003,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1071,dexcom_g7,2026-04-30,9,Aetna,sensor
|
PT-1071,dexcom_g7,2026-04-30,9,Aetna,sensor,commercial
|
||||||
PT-1072,dexcom_g7,2026-04-27,9,Aetna,sensor
|
PT-1072,dexcom_g7,2026-04-27,9,Aetna,sensor,commercial
|
||||||
PT-1073,dexcom_g7,2026-04-23,1,Aetna,sensor
|
PT-1073,dexcom_g7,2026-04-23,1,Aetna,sensor,commercial
|
||||||
PT-1074,dexcom_g7,2026-05-03,9,Aetna,sensor
|
PT-1074,dexcom_g7,2026-05-03,9,Aetna,sensor,commercial
|
||||||
PT-1075,dexcom_g7,2026-04-27,3,Aetna,sensor
|
PT-1075,dexcom_g7,2026-04-27,3,Aetna,sensor,commercial
|
||||||
PT-1076,dexcom_g7,2026-04-24,3,Aetna,sensor
|
PT-1076,dexcom_g7,2026-04-24,3,Aetna,sensor,commercial
|
||||||
PT-1077,dexcom_g7,2026-04-29,2,Aetna,sensor
|
PT-1077,dexcom_g7,2026-04-29,2,Aetna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1081,freestyle_libre_3,2026-04-20,3,UnitedHealth,sensor
|
PT-1081,freestyle_libre_3,2026-04-20,3,UnitedHealth,sensor,commercial
|
||||||
PT-1082,freestyle_libre_3,2026-04-29,9,UnitedHealth,sensor
|
PT-1082,freestyle_libre_3,2026-04-29,9,UnitedHealth,sensor,commercial
|
||||||
PT-1083,freestyle_libre_3,2026-04-28,2,UnitedHealth,sensor
|
PT-1083,freestyle_libre_3,2026-04-28,2,UnitedHealth,sensor,commercial
|
||||||
PT-1084,freestyle_libre_3,2026-04-21,3,UnitedHealth,sensor
|
PT-1084,freestyle_libre_3,2026-04-21,3,UnitedHealth,sensor,commercial
|
||||||
PT-1085,freestyle_libre_3,2026-04-21,9,UnitedHealth,sensor
|
PT-1085,freestyle_libre_3,2026-04-21,9,UnitedHealth,sensor,commercial
|
||||||
PT-1086,freestyle_libre_3,2026-04-27,1,UnitedHealth,sensor
|
PT-1086,freestyle_libre_3,2026-04-27,1,UnitedHealth,sensor,commercial
|
||||||
PT-1087,freestyle_libre_3,2026-04-28,3,UnitedHealth,sensor
|
PT-1087,freestyle_libre_3,2026-04-28,3,UnitedHealth,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pt_id,product_type,dos,qty,ins_name,component
|
pt_id,product_type,dos,qty,ins_name,component,payer_type
|
||||||
PT-1081,FreeStyle Libre 3,2025-09-07,9,Medicare Part B,sensor
|
PT-1081,FreeStyle Libre 3,2025-09-07,9,Medicare Part B,sensor,Medicare Part B
|
||||||
PT-1082,Libre 3,2025-04-23,2,Medicare Part B,sensor
|
PT-1082,Libre 3,2025-04-23,2,Medicare Part B,sensor,Medicare Part B
|
||||||
PT-1083,fs libre 3,2025-08-05,2,Medicare Part B,sensor
|
PT-1083,fs libre 3,2025-08-05,2,Medicare Part B,sensor,Medicare Part B
|
||||||
PT-1084,Libre 3,2025-07-31,6,Medicare Part B,sensor
|
PT-1084,Libre 3,2025-07-31,6,Medicare Part B,sensor,Medicare Part B
|
||||||
PT-1085,FSL3,2025-04-23,6,Medicare Part B,sensor
|
PT-1085,FSL3,2025-04-23,6,Medicare Part B,sensor,Medicare Part B
|
||||||
PT-1086,FreestyleLibre3,2025-07-05,6,Medicare Part B,sensor
|
PT-1086,FreestyleLibre3,2025-07-05,6,Medicare Part B,sensor,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
account_no,hcpcs_description,service_date,units,primary_payer,supply_type,HCPCS Code
|
account_no,hcpcs_description,service_date,units,primary_payer,supply_type,HCPCS Code,payer_type
|
||||||
PT-1091,Dexcom G6,12-20-2024,3,Medicare,sensor,A9277
|
PT-1091,Dexcom G6,12-20-2024,3,Medicare,sensor,A9277,Medicare Part B
|
||||||
PT-1092,dexcom g6,10-09-2024,9,Medicare,sensor,A9277
|
PT-1092,dexcom g6,10-09-2024,9,Medicare,sensor,A9277,Medicare Part B
|
||||||
PT-1093,Dexcom G6,12-09-2024,9,Medicare,sensor,A9277
|
PT-1093,Dexcom G6,12-09-2024,9,Medicare,sensor,A9277,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1091,dexcom_g7,2026-04-19,2,BCBS - FL,sensor
|
PT-1091,dexcom_g7,2026-04-19,2,BCBS - FL,sensor,commercial
|
||||||
PT-1092,dexcom_g7,2026-04-28,1,BCBS - FL,sensor
|
PT-1092,dexcom_g7,2026-04-28,1,BCBS - FL,sensor,commercial
|
||||||
PT-1093,dexcom_g7,2026-04-20,6,BCBS - FL,sensor
|
PT-1093,dexcom_g7,2026-04-20,6,BCBS - FL,sensor,commercial
|
||||||
PT-1094,dexcom_g7,2026-04-20,9,BCBS - FL,sensor
|
PT-1094,dexcom_g7,2026-04-20,9,BCBS - FL,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_account,description,ship_date,quantity_dispensed,carrier,component,Account Manager
|
patient_account,description,ship_date,quantity_dispensed,carrier,component,Account Manager,payer_type
|
||||||
PT-1101,G7,2024-10-15,6,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1101,G7,2024-10-15,6,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1102,G7,2024-10-21,9,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1102,G7,2024-10-21,9,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1103,Dexcom G7,2024-12-17,6,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1103,Dexcom G7,2024-12-17,6,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1104,Dexcom G7 CGM,2024-12-29,3,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1104,Dexcom G7 CGM,2024-12-29,3,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1105,Dexcom G7 CGM,2024-11-02,2,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1105,Dexcom G7 CGM,2024-11-02,2,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1106,G7,2024-11-07,3,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1106,G7,2024-11-07,3,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
PT-1107,Dexcom G7,2024-12-01,1,Blue Cross Blue Shield,sensor,J. Smith
|
PT-1107,Dexcom G7,2024-12-01,1,Blue Cross Blue Shield,sensor,J. Smith,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1101,omnipod_5,2025-05-24,9,UnitedHealth,pod
|
PT-1101,omnipod_5,2025-05-24,9,UnitedHealth,pod,commercial
|
||||||
PT-1102,omnipod_5,2025-05-22,2,UnitedHealth,pod
|
PT-1102,omnipod_5,2025-05-22,2,UnitedHealth,pod,commercial
|
||||||
PT-1103,omnipod_5,2025-05-24,2,UnitedHealth,pod
|
PT-1103,omnipod_5,2025-05-24,2,UnitedHealth,pod,commercial
|
||||||
PT-1104,omnipod_5,2025-05-20,6,UnitedHealth,pod
|
PT-1104,omnipod_5,2025-05-20,6,UnitedHealth,pod,commercial
|
||||||
PT-1105,omnipod_5,2025-05-26,3,UnitedHealth,pod
|
PT-1105,omnipod_5,2025-05-26,3,UnitedHealth,pod,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1111,omnipod_5,2026-04-24,3,Medicare Part B,pod
|
PT-1111,omnipod_5,2026-04-24,3,Medicare Part B,pod,medicare
|
||||||
PT-1112,omnipod_5,2026-04-23,9,Medicare Part B,pod
|
PT-1112,omnipod_5,2026-04-23,9,Medicare Part B,pod,medicare
|
||||||
PT-1113,omnipod_5,2026-05-01,2,Medicare Part B,pod
|
PT-1113,omnipod_5,2026-05-01,2,Medicare Part B,pod,medicare
|
||||||
PT-1114,omnipod_5,2026-05-02,2,Medicare Part B,pod
|
PT-1114,omnipod_5,2026-05-02,2,Medicare Part B,pod,medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
id,product,fill_date,qty_shipped,payer,item_type
|
id,product,fill_date,qty_shipped,payer,item_type,plan_type
|
||||||
PT-1111,Omnipod,05/12/2025,9,Centene,pod
|
PT-1111,Omnipod,05/12/2025,9,Centene,pod,commercial
|
||||||
PT-1112,OmniPod 5,06/27/2025,1,Centene,pod
|
PT-1112,OmniPod 5,06/27/2025,1,Centene,pod,commercial
|
||||||
PT-1113,OmniPod 5,06/23/2025,2,Centene,pod
|
PT-1113,OmniPod 5,06/23/2025,2,Centene,pod,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1121,dexcom_g7,2026-05-15,1,Medicaid - GA,sensor
|
PT-1121,dexcom_g7,2026-05-15,1,Medicaid - GA,sensor,medicaid
|
||||||
PT-1122,dexcom_g7,2026-05-18,2,Medicaid - GA,sensor
|
PT-1122,dexcom_g7,2026-05-18,2,Medicaid - GA,sensor,medicaid
|
||||||
PT-1123,dexcom_g7,2026-05-14,6,Medicaid - GA,sensor
|
PT-1123,dexcom_g7,2026-05-14,6,Medicaid - GA,sensor,medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
PT ID,Device Type,Shipment Date,Quantity,Insurance,Component,Region
|
PT ID,Device Type,Shipment Date,Quantity,Insurance,Component,Region,payer_type
|
||||||
PT-1121,Omnipod 5,2024-12-28,9,UHC,pod,Southeast
|
PT-1121,Omnipod 5,2024-12-28,9,UHC,pod,Southeast,employer
|
||||||
PT-1122,Omnipod 5,2024-11-14,2,UHC,pod,Southeast
|
PT-1122,Omnipod 5,2024-11-14,2,UHC,pod,Southeast,employer
|
||||||
PT-1123,Omnipod 5,2024-11-04,9,UHC,pod,Southeast
|
PT-1123,Omnipod 5,2024-11-04,9,UHC,pod,Southeast,employer
|
||||||
PT-1124,OmniPod 5,2024-10-23,9,UHC,pod,Southeast
|
PT-1124,OmniPod 5,2024-10-23,9,UHC,pod,Southeast,employer
|
||||||
PT-1125,OmniPod 5,2024-11-02,2,UHC,pod,Southeast
|
PT-1125,OmniPod 5,2024-11-02,2,UHC,pod,Southeast,employer
|
||||||
PT-1126,OmniPod 5,2025-01-02,9,UHC,pod,Southeast
|
PT-1126,OmniPod 5,2025-01-02,9,UHC,pod,Southeast,employer
|
||||||
PT-1127,Omnipod 5,2024-12-05,1,UHC,pod,Southeast
|
PT-1127,Omnipod 5,2024-12-05,1,UHC,pod,Southeast,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
PT ID,Device Type,Shipment Date,Quantity,Insurance,Component,Region
|
PT ID,Device Type,Shipment Date,Quantity,Insurance,Component,Region,payer_type
|
||||||
PT-1121,Omnipod,2025-05-12,9,Centene,pod,Southeast
|
PT-1121,Omnipod,2025-05-12,9,Centene,pod,Southeast,employer
|
||||||
PT-1122,OmniPod 5,2025-06-27,1,Centene,pod,Southeast
|
PT-1122,OmniPod 5,2025-06-27,1,Centene,pod,Southeast,employer
|
||||||
PT-1123,OmniPod 5,2025-06-23,2,Centene,pod,Southeast
|
PT-1123,OmniPod 5,2025-06-23,2,Centene,pod,Southeast,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patientid,devicetype,dispensedate,qty,payername,supplytype
|
patientid,devicetype,dispensedate,qty,payername,supplytype,plan_type
|
||||||
PT-1131,Omnipod,11/19/2024,3,BCBS - FL,pod
|
PT-1131,Omnipod,11/19/2024,3,BCBS - FL,pod,Commercial
|
||||||
PT-1132,op5,10/27/2024,9,BCBS - FL,pod
|
PT-1132,op5,10/27/2024,9,BCBS - FL,pod,Commercial
|
||||||
PT-1133,Omnipod 5,01/03/2025,1,BCBS - FL,pod
|
PT-1133,Omnipod 5,01/03/2025,1,BCBS - FL,pod,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patientid,devicetype,dispensedate,qty,payername,supplytype
|
patientid,devicetype,dispensedate,qty,payername,supplytype,plan_type
|
||||||
PT-1131,Omnipod 5,05/04/2026,9,UHC,pod
|
PT-1131,Omnipod 5,05/04/2026,9,UHC,pod,Commercial
|
||||||
PT-1132,Omnipod 5,05/02/2026,2,UHC,pod
|
PT-1132,Omnipod 5,05/02/2026,2,UHC,pod,Commercial
|
||||||
PT-1133,Omnipod 5,04/27/2026,9,UHC,pod
|
PT-1133,Omnipod 5,04/27/2026,9,UHC,pod,Commercial
|
||||||
PT-1134,OmniPod 5,04/28/2026,9,UHC,pod
|
PT-1134,OmniPod 5,04/28/2026,9,UHC,pod,Commercial
|
||||||
PT-1135,OmniPod 5,05/01/2026,2,UHC,pod
|
PT-1135,OmniPod 5,05/01/2026,2,UHC,pod,Commercial
|
||||||
PT-1136,OmniPod 5,05/05/2026,9,UHC,pod
|
PT-1136,OmniPod 5,05/05/2026,9,UHC,pod,Commercial
|
||||||
PT-1137,Omnipod 5,04/30/2026,1,UHC,pod
|
PT-1137,Omnipod 5,04/30/2026,1,UHC,pod,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1131,dexcom_g6,2025-09-06,2,Cigna,sensor
|
PT-1131,dexcom_g6,2025-09-06,2,Cigna,sensor,commercial
|
||||||
PT-1132,dexcom_g6,2025-09-06,6,Cigna,sensor
|
PT-1132,dexcom_g6,2025-09-06,6,Cigna,sensor,commercial
|
||||||
PT-1133,dexcom_g6,2025-09-02,1,Cigna,sensor
|
PT-1133,dexcom_g6,2025-09-02,1,Cigna,sensor,commercial
|
||||||
PT-1134,dexcom_g6,2025-08-31,6,Cigna,sensor
|
PT-1134,dexcom_g6,2025-08-31,6,Cigna,sensor,commercial
|
||||||
PT-1135,dexcom_g6,2025-09-04,6,Cigna,sensor
|
PT-1135,dexcom_g6,2025-09-04,6,Cigna,sensor,commercial
|
||||||
PT-1136,dexcom_g6,2025-09-05,6,Cigna,sensor
|
PT-1136,dexcom_g6,2025-09-05,6,Cigna,sensor,commercial
|
||||||
PT-1137,dexcom_g6,2025-08-30,1,Cigna,sensor
|
PT-1137,dexcom_g6,2025-08-30,1,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1141,freestyle_libre_3,2026-05-18,2,Humana,sensor
|
PT-1141,freestyle_libre_3,2026-05-18,2,Humana,sensor,commercial
|
||||||
PT-1142,freestyle_libre_3,2026-05-23,6,Humana,sensor
|
PT-1142,freestyle_libre_3,2026-05-23,6,Humana,sensor,commercial
|
||||||
PT-1143,freestyle_libre_3,2026-05-17,6,Humana,sensor
|
PT-1143,freestyle_libre_3,2026-05-17,6,Humana,sensor,commercial
|
||||||
PT-1144,freestyle_libre_3,2026-05-17,3,Humana,sensor
|
PT-1144,freestyle_libre_3,2026-05-17,3,Humana,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
account_number,item_description,order_date,units_dispensed,plan_name,component,Facility
|
account_number,item_description,order_date,units_dispensed,plan_name,component,Facility,Coverage Type
|
||||||
PT-1141,Dexcom G7 CGM,01/05/2026,9,Aetna,sensor,Gaboro PA Main
|
PT-1141,Dexcom G7 CGM,01/05/2026,9,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1142,dexcom g7,30/04/2026,2,Aetna,sensor,Gaboro PA Main
|
PT-1142,dexcom g7,30/04/2026,2,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1143,Dexcom G7 CGM,27/04/2026,1,Aetna,sensor,Gaboro PA Main
|
PT-1143,Dexcom G7 CGM,27/04/2026,1,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1144,G7,28/04/2026,1,Aetna,sensor,Gaboro PA Main
|
PT-1144,G7,28/04/2026,1,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1145,dexcom g7,03/05/2026,9,Aetna,sensor,Gaboro PA Main
|
PT-1145,dexcom g7,03/05/2026,9,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1146,G7,01/05/2026,2,Aetna,sensor,Gaboro PA Main
|
PT-1146,G7,01/05/2026,2,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
PT-1147,Dexcom G7,29/04/2026,2,Aetna,sensor,Gaboro PA Main
|
PT-1147,Dexcom G7,29/04/2026,2,Aetna,sensor,Gaboro PA Main,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
account_number,item_description,order_date,units_dispensed,plan_name,component,Facility
|
account_number,item_description,order_date,units_dispensed,plan_name,component,Facility,payer_type
|
||||||
PT-1141,Omnipod,20/07/2025,3,BCBS - FL,pod,Gaboro PA Main
|
PT-1141,Omnipod,20/07/2025,3,BCBS - FL,pod,Gaboro PA Main,employer
|
||||||
PT-1142,op5,05/06/2025,9,BCBS - FL,pod,Gaboro PA Main
|
PT-1142,op5,05/06/2025,9,BCBS - FL,pod,Gaboro PA Main,employer
|
||||||
PT-1143,Omnipod 5,11/08/2025,1,BCBS - FL,pod,Gaboro PA Main
|
PT-1143,Omnipod 5,11/08/2025,1,BCBS - FL,pod,Gaboro PA Main,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
MRN,Product Type,Service Date,Qty,Insurance Name,Component Type
|
MRN,Product Type,Service Date,Qty,Insurance Name,Component Type,LOB
|
||||||
PT-1151,Dexcom G7 CGM,2026-05-21,9,Aetna,sensor
|
PT-1151,Dexcom G7 CGM,2026-05-21,9,Aetna,sensor,private
|
||||||
PT-1152,dexcom g7,2026-05-24,2,Aetna,sensor
|
PT-1152,dexcom g7,2026-05-24,2,Aetna,sensor,private
|
||||||
PT-1153,Dexcom G7 CGM,2026-05-17,1,Aetna,sensor
|
PT-1153,Dexcom G7 CGM,2026-05-17,1,Aetna,sensor,private
|
||||||
PT-1154,G7,2026-05-21,1,Aetna,sensor
|
PT-1154,G7,2026-05-21,1,Aetna,sensor,private
|
||||||
PT-1155,dexcom g7,2026-05-26,9,Aetna,sensor
|
PT-1155,dexcom g7,2026-05-26,9,Aetna,sensor,private
|
||||||
PT-1156,G7,2026-05-18,2,Aetna,sensor
|
PT-1156,G7,2026-05-18,2,Aetna,sensor,private
|
||||||
PT-1157,G7,2026-05-21,3,Aetna,sensor
|
PT-1157,G7,2026-05-21,3,Aetna,sensor,private
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1151,dexcom_g7,2026-04-20,9,Aetna,sensor
|
PT-1151,dexcom_g7,2026-04-20,9,Aetna,sensor,commercial
|
||||||
PT-1152,dexcom_g7,2026-04-20,1,Aetna,sensor
|
PT-1152,dexcom_g7,2026-04-20,1,Aetna,sensor,commercial
|
||||||
PT-1153,dexcom_g7,2026-04-23,2,Aetna,sensor
|
PT-1153,dexcom_g7,2026-04-23,2,Aetna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
MRN,Product Type,Service Date,Qty,Insurance Name,Component Type
|
MRN,Product Type,Service Date,Qty,Insurance Name,Component Type,payer_type
|
||||||
PT-1151,Libre 3,2025-06-24,1,Humana,sensor
|
PT-1151,Libre 3,2025-06-24,1,Humana,sensor,employer
|
||||||
PT-1152,FreeStyle Libre 3,2025-08-01,6,Humana,sensor
|
PT-1152,FreeStyle Libre 3,2025-08-01,6,Humana,sensor,employer
|
||||||
PT-1153,fs libre 3,2025-06-16,3,Humana,sensor
|
PT-1153,fs libre 3,2025-06-16,3,Humana,sensor,employer
|
||||||
PT-1154,Libre 3,2025-07-13,2,Humana,sensor
|
PT-1154,Libre 3,2025-07-13,2,Humana,sensor,employer
|
||||||
PT-1155,Libre 3,2025-05-01,6,Humana,sensor
|
PT-1155,Libre 3,2025-05-01,6,Humana,sensor,employer
|
||||||
PT-1156,FreeStyle Libre 3,2025-07-15,3,Humana,sensor
|
PT-1156,FreeStyle Libre 3,2025-07-15,3,Humana,sensor,employer
|
||||||
PT-1157,FreestyleLibre3,2025-07-23,6,Humana,sensor
|
PT-1157,FreestyleLibre3,2025-07-23,6,Humana,sensor,employer
|
||||||
PT-1158,FreeStyle Libre 3,2025-09-06,1,Humana,sensor
|
PT-1158,FreeStyle Libre 3,2025-09-06,1,Humana,sensor,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Patient_ID,Device,Ship_Date,Units,Plan,Type,Export Type
|
Patient_ID,Device,Ship_Date,Units,Plan,Type,Export Type,payer_type
|
||||||
PT-1161,fs libre 3,10/19/2024 00:00:00,3,CMS,sensor,CGM Only
|
PT-1161,fs libre 3,10/19/2024 00:00:00,3,CMS,sensor,CGM Only,employer
|
||||||
PT-1162,FSL3,01/09/2025 00:00:00,6,CMS,sensor,CGM Only
|
PT-1162,FSL3,01/09/2025 00:00:00,6,CMS,sensor,CGM Only,employer
|
||||||
PT-1163,FreeStyle Libre 3,12/22/2024 00:00:00,6,CMS,sensor,CGM Only
|
PT-1163,FreeStyle Libre 3,12/22/2024 00:00:00,6,CMS,sensor,CGM Only,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1161,omnipod_5,2026-04-24,6,Medicaid - GA,pod
|
PT-1161,omnipod_5,2026-04-24,6,Medicaid - GA,pod,medicaid
|
||||||
PT-1162,omnipod_5,2026-04-22,6,Medicaid - GA,pod
|
PT-1162,omnipod_5,2026-04-22,6,Medicaid - GA,pod,medicaid
|
||||||
PT-1163,omnipod_5,2026-04-26,6,Medicaid - GA,pod
|
PT-1163,omnipod_5,2026-04-26,6,Medicaid - GA,pod,medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Patient_ID,Device,Ship_Date,Units,Plan,Type,Export Type
|
Patient_ID,Device,Ship_Date,Units,Plan,Type,Export Type,payer_type
|
||||||
PT-1161,Omnipod 5,06/05/2025 00:00:00,6,UnitedHealth,pod,CGM Only
|
PT-1161,Omnipod 5,06/05/2025 00:00:00,6,UnitedHealth,pod,CGM Only,employer
|
||||||
PT-1162,op5,05/05/2025 00:00:00,2,UnitedHealth,pod,CGM Only
|
PT-1162,op5,05/05/2025 00:00:00,2,UnitedHealth,pod,CGM Only,employer
|
||||||
PT-1163,op5,06/16/2025 00:00:00,3,UnitedHealth,pod,CGM Only
|
PT-1163,op5,06/16/2025 00:00:00,3,UnitedHealth,pod,CGM Only,employer
|
||||||
PT-1164,Omnipod,07/13/2025 00:00:00,2,UnitedHealth,pod,CGM Only
|
PT-1164,Omnipod,07/13/2025 00:00:00,2,UnitedHealth,pod,CGM Only,employer
|
||||||
PT-1165,Omnipod,05/01/2025 00:00:00,6,UnitedHealth,pod,CGM Only
|
PT-1165,Omnipod,05/01/2025 00:00:00,6,UnitedHealth,pod,CGM Only,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
patient id,item,dispense date,count,carrier,supply_type,Billing Staff,Auth Number
|
patient id,item,dispense date,count,carrier,supply_type,Billing Staff,Auth Number,payer_type
|
||||||
PT-1171,FreestyleLibre3,2024-11-20,6,Medicare Part B,sensor,M. Jones,CGM-2026-001
|
PT-1171,FreestyleLibre3,2024-11-20,6,Medicare Part B,sensor,M. Jones,CGM-2026-001,Medicare Part B
|
||||||
PT-1172,FreestyleLibre3,2025-01-02,3,Medicare Part B,sensor,M. Jones,CGM-2026-001
|
PT-1172,FreestyleLibre3,2025-01-02,3,Medicare Part B,sensor,M. Jones,CGM-2026-001,Medicare Part B
|
||||||
PT-1173,FSL3,2024-10-05,2,Medicare Part B,sensor,M. Jones,CGM-2026-001
|
PT-1173,FSL3,2024-10-05,2,Medicare Part B,sensor,M. Jones,CGM-2026-001,Medicare Part B
|
||||||
PT-1174,FreeStyle Libre 3,2024-12-17,1,Medicare Part B,sensor,M. Jones,CGM-2026-001
|
PT-1174,FreeStyle Libre 3,2024-12-17,1,Medicare Part B,sensor,M. Jones,CGM-2026-001,Medicare Part B
|
||||||
PT-1175,FSL3,2024-12-20,3,Medicare Part B,sensor,M. Jones,CGM-2026-001
|
PT-1175,FSL3,2024-12-20,3,Medicare Part B,sensor,M. Jones,CGM-2026-001,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient id,item,dispense date,count,carrier,supply_type,Billing Staff,Auth Number
|
patient id,item,dispense date,count,carrier,supply_type,Billing Staff,Auth Number,Coverage Type
|
||||||
PT-1171,G6,2026-05-05,3,Medicare Part A,sensor,M. Jones,CGM-2026-001
|
PT-1171,G6,2026-05-05,3,Medicare Part A,sensor,M. Jones,CGM-2026-001,Medicare
|
||||||
PT-1172,Dexcom G6 Pro,2026-04-28,9,Medicare Part A,sensor,M. Jones,CGM-2026-001
|
PT-1172,Dexcom G6 Pro,2026-04-28,9,Medicare Part A,sensor,M. Jones,CGM-2026-001,Medicare
|
||||||
PT-1173,Dexcom G6,2026-05-02,3,Medicare Part A,sensor,M. Jones,CGM-2026-001
|
PT-1173,Dexcom G6,2026-05-02,3,Medicare Part A,sensor,M. Jones,CGM-2026-001,Medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Acct No,Product Name,Last Ship Date,Qty Dispensed,Primary Payer,Component
|
Acct No,Product Name,Last Ship Date,Qty Dispensed,Primary Payer,Component,LOB
|
||||||
PT-1181,Libre 3,"May 23, 2026",2,Molina Healthcare,sensor
|
PT-1181,Libre 3,"May 23, 2026",2,Molina Healthcare,sensor,private
|
||||||
PT-1182,fs libre 3,"May 26, 2026",2,Molina Healthcare,sensor
|
PT-1182,fs libre 3,"May 26, 2026",2,Molina Healthcare,sensor,private
|
||||||
PT-1183,FSL3,"May 28, 2026",6,Molina Healthcare,sensor
|
PT-1183,FSL3,"May 28, 2026",6,Molina Healthcare,sensor,private
|
||||||
PT-1184,FreeStyle Libre 3,"May 29, 2026",3,Molina Healthcare,sensor
|
PT-1184,FreeStyle Libre 3,"May 29, 2026",3,Molina Healthcare,sensor,private
|
||||||
PT-1185,fs libre 3,"May 20, 2026",9,Molina Healthcare,sensor
|
PT-1185,fs libre 3,"May 20, 2026",9,Molina Healthcare,sensor,private
|
||||||
PT-1186,FSL3,"May 29, 2026",6,Molina Healthcare,sensor
|
PT-1186,FSL3,"May 29, 2026",6,Molina Healthcare,sensor,private
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Acct No,Product Name,Last Ship Date,Qty Dispensed,Primary Payer,Component
|
Acct No,Product Name,Last Ship Date,Qty Dispensed,Primary Payer,Component,payer_type
|
||||||
PT-1181,Omnipod,"Jul 31, 2025",3,Centene,pod
|
PT-1181,Omnipod,"Jul 31, 2025",3,Centene,pod,employer
|
||||||
PT-1182,op5,"May 06, 2025",1,Centene,pod
|
PT-1182,op5,"May 06, 2025",1,Centene,pod,employer
|
||||||
PT-1183,Omnipod,"Sep 06, 2025",3,Centene,pod
|
PT-1183,Omnipod,"Sep 06, 2025",3,Centene,pod,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Member ID,DME Description,DOS,QTY,Insurance,Item Type,Payer ID
|
Member ID,DME Description,DOS,QTY,Insurance,Item Type,Payer ID,payer_type
|
||||||
PT-1191,Omnipod,2024-12-07,1,Medicare,pod,00019
|
PT-1191,Omnipod,2024-12-07,1,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1192,OmniPod 5,2024-11-11,1,Medicare,pod,00019
|
PT-1192,OmniPod 5,2024-11-11,1,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1193,OmniPod 5,2025-01-07,2,Medicare,pod,00019
|
PT-1193,OmniPod 5,2025-01-07,2,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1194,Omnipod 5,2024-10-28,1,Medicare,pod,00019
|
PT-1194,Omnipod 5,2024-10-28,1,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1195,Omnipod 5,2024-11-05,6,Medicare,pod,00019
|
PT-1195,Omnipod 5,2024-11-05,6,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1196,Omnipod,2024-11-29,6,Medicare,pod,00019
|
PT-1196,Omnipod,2024-11-29,6,Medicare,pod,00019,Medicare Part B
|
||||||
PT-1197,Omnipod,2024-12-07,2,Medicare,pod,00019
|
PT-1197,Omnipod,2024-12-07,2,Medicare,pod,00019,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
Member ID,DME Description,DOS,QTY,Insurance,Item Type,Payer ID
|
Member ID,DME Description,DOS,QTY,Insurance,Item Type,Payer ID,Coverage Type
|
||||||
PT-1191,Omnipod 5,2026-05-02,3,CMS,pod,00019
|
PT-1191,Omnipod 5,2026-05-02,3,CMS,pod,00019,Commercial
|
||||||
PT-1192,op5,2026-05-01,3,CMS,pod,00019
|
PT-1192,op5,2026-05-01,3,CMS,pod,00019,Commercial
|
||||||
PT-1193,OmniPod 5,2026-05-03,9,CMS,pod,00019
|
PT-1193,OmniPod 5,2026-05-03,9,CMS,pod,00019,Commercial
|
||||||
PT-1194,op5,2026-04-27,6,CMS,pod,00019
|
PT-1194,op5,2026-04-27,6,CMS,pod,00019,Commercial
|
||||||
PT-1195,Omnipod,2026-05-05,9,CMS,pod,00019
|
PT-1195,Omnipod,2026-05-05,9,CMS,pod,00019,Commercial
|
||||||
PT-1196,op5,2026-05-01,9,CMS,pod,00019
|
PT-1196,op5,2026-05-01,9,CMS,pod,00019,Commercial
|
||||||
PT-1197,OmniPod 5,2026-04-27,2,CMS,pod,00019
|
PT-1197,OmniPod 5,2026-04-27,2,CMS,pod,00019,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1191,dexcom_g7,2025-09-19,9,UnitedHealth,sensor
|
PT-1191,dexcom_g7,2025-09-19,9,UnitedHealth,sensor,commercial
|
||||||
PT-1192,dexcom_g7,2025-09-18,9,UnitedHealth,sensor
|
PT-1192,dexcom_g7,2025-09-18,9,UnitedHealth,sensor,commercial
|
||||||
PT-1193,dexcom_g7,2025-09-14,3,UnitedHealth,sensor
|
PT-1193,dexcom_g7,2025-09-14,3,UnitedHealth,sensor,commercial
|
||||||
PT-1194,dexcom_g7,2025-09-12,3,UnitedHealth,sensor
|
PT-1194,dexcom_g7,2025-09-12,3,UnitedHealth,sensor,commercial
|
||||||
PT-1195,dexcom_g7,2025-09-12,3,UnitedHealth,sensor
|
PT-1195,dexcom_g7,2025-09-12,3,UnitedHealth,sensor,commercial
|
||||||
PT-1196,dexcom_g7,2025-09-15,2,UnitedHealth,sensor
|
PT-1196,dexcom_g7,2025-09-15,2,UnitedHealth,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
pt id,device_type,service date,quantity,payer,component
|
pt id,device_type,service date,quantity,payer,component,plan_type
|
||||||
PT-1201,dexcom g7,05/19/2026,1,Blue Cross Blue Shield,sensor
|
PT-1201,dexcom g7,05/19/2026,1,Blue Cross Blue Shield,sensor,commercial
|
||||||
PT-1202,Dexcom G7,05/24/2026,6,Blue Cross Blue Shield,sensor
|
PT-1202,Dexcom G7,05/24/2026,6,Blue Cross Blue Shield,sensor,commercial
|
||||||
PT-1203,dexcom g7,05/23/2026,9,Blue Cross Blue Shield,sensor
|
PT-1203,dexcom g7,05/23/2026,9,Blue Cross Blue Shield,sensor,commercial
|
||||||
PT-1204,Dexcom G7 CGM,05/27/2026,6,Blue Cross Blue Shield,sensor
|
PT-1204,Dexcom G7 CGM,05/27/2026,6,Blue Cross Blue Shield,sensor,commercial
|
||||||
PT-1205,dexcom g7,05/30/2026,9,Blue Cross Blue Shield,sensor
|
PT-1205,dexcom g7,05/30/2026,9,Blue Cross Blue Shield,sensor,commercial
|
||||||
PT-1206,dexcom g7,05/23/2026,6,Blue Cross Blue Shield,sensor
|
PT-1206,dexcom g7,05/23/2026,6,Blue Cross Blue Shield,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
pt id,device_type,service date,quantity,payer,component
|
pt id,device_type,service date,quantity,payer,component,plan_type
|
||||||
PT-1201,op5,11/15/2024,6,Aetna Commercial,pod
|
PT-1201,op5,11/15/2024,6,Aetna Commercial,pod,commercial
|
||||||
PT-1202,op5,12/28/2024,2,Aetna Commercial,pod
|
PT-1202,op5,12/28/2024,2,Aetna Commercial,pod,commercial
|
||||||
PT-1203,OmniPod 5,12/25/2024,9,Aetna Commercial,pod
|
PT-1203,OmniPod 5,12/25/2024,9,Aetna Commercial,pod,commercial
|
||||||
PT-1204,OmniPod 5,12/30/2024,1,Aetna Commercial,pod
|
PT-1204,OmniPod 5,12/30/2024,1,Aetna Commercial,pod,commercial
|
||||||
PT-1205,OmniPod 5,01/07/2025,2,Aetna Commercial,pod
|
PT-1205,OmniPod 5,01/07/2025,2,Aetna Commercial,pod,commercial
|
||||||
PT-1206,Omnipod 5,10/28/2024,1,Aetna Commercial,pod
|
PT-1206,Omnipod 5,10/28/2024,1,Aetna Commercial,pod,commercial
|
||||||
PT-1207,Omnipod 5,11/05/2024,6,Aetna Commercial,pod
|
PT-1207,Omnipod 5,11/05/2024,6,Aetna Commercial,pod,commercial
|
||||||
PT-1208,Omnipod,11/29/2024,6,Aetna Commercial,pod
|
PT-1208,Omnipod,11/29/2024,6,Aetna Commercial,pod,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
acct_no,product,fill date,units,insurance name,type,Branch Code
|
acct_no,product,fill date,units,insurance name,type,Branch Code,payer_type
|
||||||
PT-1211,Omnipod 5,2024-12-29,6,Medicare,pod,GA-02
|
PT-1211,Omnipod 5,2024-12-29,6,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1212,op5,2024-10-31,1,Medicare,pod,GA-02
|
PT-1212,op5,2024-10-31,1,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1213,Omnipod 5,2024-12-13,6,Medicare,pod,GA-02
|
PT-1213,Omnipod 5,2024-12-13,6,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1214,op5,2024-10-25,9,Medicare,pod,GA-02
|
PT-1214,op5,2024-10-25,9,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1215,OmniPod 5,2024-12-16,6,Medicare,pod,GA-02
|
PT-1215,OmniPod 5,2024-12-16,6,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1216,op5,2024-12-25,9,Medicare,pod,GA-02
|
PT-1216,op5,2024-12-25,9,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1217,op5,2024-11-29,6,Medicare,pod,GA-02
|
PT-1217,op5,2024-11-29,6,Medicare,pod,GA-02,Medicare Part B
|
||||||
PT-1218,Omnipod,2024-11-10,3,Medicare,pod,GA-02
|
PT-1218,Omnipod,2024-11-10,3,Medicare,pod,GA-02,Medicare Part B
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
acct_no,product,fill date,units,insurance name,type,Branch Code
|
acct_no,product,fill date,units,insurance name,type,Branch Code,Coverage Type
|
||||||
PT-1211,Libre 3,2026-05-03,3,UHC,sensor,GA-02
|
PT-1211,Libre 3,2026-05-03,3,UHC,sensor,GA-02,Commercial
|
||||||
PT-1212,FSL3,2026-04-28,2,UHC,sensor,GA-02
|
PT-1212,FSL3,2026-04-28,2,UHC,sensor,GA-02,Commercial
|
||||||
PT-1213,FSL3,2026-04-29,9,UHC,sensor,GA-02
|
PT-1213,FSL3,2026-04-29,9,UHC,sensor,GA-02,Commercial
|
||||||
PT-1214,Libre 3,2026-04-26,2,UHC,sensor,GA-02
|
PT-1214,Libre 3,2026-04-26,2,UHC,sensor,GA-02,Commercial
|
||||||
PT-1215,Libre 3,2026-05-03,2,UHC,sensor,GA-02
|
PT-1215,Libre 3,2026-05-03,2,UHC,sensor,GA-02,Commercial
|
||||||
PT-1216,fs libre 3,2026-04-28,3,UHC,sensor,GA-02
|
PT-1216,fs libre 3,2026-04-28,3,UHC,sensor,GA-02,Commercial
|
||||||
PT-1217,fs libre 3,2026-05-02,1,UHC,sensor,GA-02
|
PT-1217,fs libre 3,2026-05-02,1,UHC,sensor,GA-02,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1211,freestyle_libre_3,2025-08-24,3,Medicaid - GA,sensor
|
PT-1211,freestyle_libre_3,2025-08-24,3,Medicaid - GA,sensor,medicaid
|
||||||
PT-1212,freestyle_libre_3,2025-08-25,2,Medicaid - GA,sensor
|
PT-1212,freestyle_libre_3,2025-08-25,2,Medicaid - GA,sensor,medicaid
|
||||||
PT-1213,freestyle_libre_3,2025-08-28,9,Medicaid - GA,sensor
|
PT-1213,freestyle_libre_3,2025-08-28,9,Medicaid - GA,sensor,medicaid
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1221,dexcom_g7,2024-12-23,1,Cigna,sensor
|
PT-1221,dexcom_g7,2024-12-23,1,Cigna,sensor,commercial
|
||||||
PT-1222,dexcom_g7,2024-12-15,3,Cigna,sensor
|
PT-1222,dexcom_g7,2024-12-15,3,Cigna,sensor,commercial
|
||||||
PT-1223,dexcom_g7,2024-12-14,1,Cigna,sensor
|
PT-1223,dexcom_g7,2024-12-14,1,Cigna,sensor,commercial
|
||||||
PT-1224,dexcom_g7,2024-12-21,2,Cigna,sensor
|
PT-1224,dexcom_g7,2024-12-21,2,Cigna,sensor,commercial
|
||||||
PT-1225,dexcom_g7,2024-12-17,3,Cigna,sensor
|
PT-1225,dexcom_g7,2024-12-17,3,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
External Patient Ref,Item Description,Dispense Date,Quantity,Plan Name,Supply Type
|
External Patient Ref,Item Description,Dispense Date,Quantity,Plan Name,Supply Type,Coverage Type
|
||||||
PT-1221,OmniPod 5,04/30/2026 00:00:00,2,Molina Healthcare,pod
|
PT-1221,OmniPod 5,04/30/2026 00:00:00,2,Molina Healthcare,pod,Commercial
|
||||||
PT-1222,OmniPod 5,04/29/2026 00:00:00,9,Molina Healthcare,pod
|
PT-1222,OmniPod 5,04/29/2026 00:00:00,9,Molina Healthcare,pod,Commercial
|
||||||
PT-1223,Omnipod,04/26/2026 00:00:00,2,Molina Healthcare,pod
|
PT-1223,Omnipod,04/26/2026 00:00:00,2,Molina Healthcare,pod,Commercial
|
||||||
PT-1224,Omnipod,05/03/2026 00:00:00,2,Molina Healthcare,pod
|
PT-1224,Omnipod,05/03/2026 00:00:00,2,Molina Healthcare,pod,Commercial
|
||||||
PT-1225,op5,04/28/2026 00:00:00,3,Molina Healthcare,pod
|
PT-1225,op5,04/28/2026 00:00:00,3,Molina Healthcare,pod,Commercial
|
||||||
PT-1226,op5,05/02/2026 00:00:00,1,Molina Healthcare,pod
|
PT-1226,op5,05/02/2026 00:00:00,1,Molina Healthcare,pod,Commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
External Patient Ref,Item Description,Dispense Date,Quantity,Plan Name,Supply Type
|
External Patient Ref,Item Description,Dispense Date,Quantity,Plan Name,Supply Type,payer_type
|
||||||
PT-1221,dexcom g6,05/01/2025 00:00:00,6,Humana,sensor
|
PT-1221,dexcom g6,05/01/2025 00:00:00,6,Humana,sensor,employer
|
||||||
PT-1222,Dexcom G6 Pro,04/23/2025 00:00:00,6,Humana,sensor
|
PT-1222,Dexcom G6 Pro,04/23/2025 00:00:00,6,Humana,sensor,employer
|
||||||
PT-1223,G6,08/09/2025 00:00:00,6,Humana,sensor
|
PT-1223,G6,08/09/2025 00:00:00,6,Humana,sensor,employer
|
||||||
PT-1224,dexcom g6,06/17/2025 00:00:00,6,Humana,sensor
|
PT-1224,dexcom g6,06/17/2025 00:00:00,6,Humana,sensor,employer
|
||||||
PT-1225,Dexcom G6 Pro,04/30/2025 00:00:00,6,Humana,sensor
|
PT-1225,Dexcom G6 Pro,04/30/2025 00:00:00,6,Humana,sensor,employer
|
||||||
PT-1226,dexcom g6,06/07/2025 00:00:00,2,Humana,sensor
|
PT-1226,dexcom g6,06/07/2025 00:00:00,2,Humana,sensor,employer
|
||||||
PT-1227,dexcom g6,09/03/2025 00:00:00,9,Humana,sensor
|
PT-1227,dexcom g6,09/03/2025 00:00:00,9,Humana,sensor,employer
|
||||||
|
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component,Internal Code,Region,Staff ID
|
patient_id,device_type,shipment_date,quantity,payer,component,Internal Code,Region,Staff ID,plan_type
|
||||||
PT-1231,Dexcom G7,2024-12-01,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001
|
PT-1231,Dexcom G7,2024-12-01,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001,medicare
|
||||||
PT-1232,G7,2024-11-21,6,Medicare Part A,sensor,DME-99,Northeast,STAFF-001
|
PT-1232,G7,2024-11-21,6,Medicare Part A,sensor,DME-99,Northeast,STAFF-001,medicare
|
||||||
PT-1233,dexcom g7,2024-11-14,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001
|
PT-1233,dexcom g7,2024-11-14,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001,medicare
|
||||||
PT-1234,dexcom g7,2025-01-12,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001
|
PT-1234,dexcom g7,2025-01-12,3,Medicare Part A,sensor,DME-99,Northeast,STAFF-001,medicare
|
||||||
|
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1231,dexcom_g6,2025-07-18,6,Cigna,sensor
|
PT-1231,dexcom_g6,2025-07-18,6,Cigna,sensor,commercial
|
||||||
PT-1232,dexcom_g6,2025-07-14,1,Cigna,sensor
|
PT-1232,dexcom_g6,2025-07-14,1,Cigna,sensor,commercial
|
||||||
PT-1233,dexcom_g6,2025-07-11,6,Cigna,sensor
|
PT-1233,dexcom_g6,2025-07-11,6,Cigna,sensor,commercial
|
||||||
PT-1234,dexcom_g6,2025-07-14,1,Cigna,sensor
|
PT-1234,dexcom_g6,2025-07-14,1,Cigna,sensor,commercial
|
||||||
PT-1235,dexcom_g6,2025-07-10,3,Cigna,sensor
|
PT-1235,dexcom_g6,2025-07-10,3,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Acct #,Device,Order Date,Qty,Insurance,Component,Supplier Code
|
Acct #,Device,Order Date,Qty,Insurance,Component,Supplier Code,LOB
|
||||||
PT-1241,Dexcom G7,"May 21, 2026",1,Medicare Part B - CGM,sensor,STTIL-01
|
PT-1241,Dexcom G7,"May 21, 2026",1,Medicare Part B - CGM,sensor,STTIL-01,medicare ffs
|
||||||
PT-1242,G7,"May 16, 2026",1,Medicare Part B - CGM,sensor,STTIL-01
|
PT-1242,G7,"May 16, 2026",1,Medicare Part B - CGM,sensor,STTIL-01,medicare ffs
|
||||||
PT-1243,G7,"May 25, 2026",2,Medicare Part B - CGM,sensor,STTIL-01
|
PT-1243,G7,"May 25, 2026",2,Medicare Part B - CGM,sensor,STTIL-01,medicare ffs
|
||||||
|
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,component
|
patient_id,device_type,shipment_date,quantity,payer,component,plan_type
|
||||||
PT-1241,dexcom_g6,2025-06-26,9,Cigna,sensor
|
PT-1241,dexcom_g6,2025-06-26,9,Cigna,sensor,commercial
|
||||||
PT-1242,dexcom_g6,2025-06-20,1,Cigna,sensor
|
PT-1242,dexcom_g6,2025-06-20,1,Cigna,sensor,commercial
|
||||||
PT-1243,dexcom_g6,2025-06-21,2,Cigna,sensor
|
PT-1243,dexcom_g6,2025-06-21,2,Cigna,sensor,commercial
|
||||||
PT-1244,dexcom_g6,2025-06-28,1,Cigna,sensor
|
PT-1244,dexcom_g6,2025-06-28,1,Cigna,sensor,commercial
|
||||||
PT-1245,dexcom_g6,2025-06-25,9,Cigna,sensor
|
PT-1245,dexcom_g6,2025-06-25,9,Cigna,sensor,commercial
|
||||||
PT-1246,dexcom_g6,2025-06-28,2,Cigna,sensor
|
PT-1246,dexcom_g6,2025-06-28,2,Cigna,sensor,commercial
|
||||||
PT-1247,dexcom_g6,2025-06-26,2,Cigna,sensor
|
PT-1247,dexcom_g6,2025-06-26,2,Cigna,sensor,commercial
|
||||||
|
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
patient_id,device_type,shipment_date,quantity,payer,visit_date,swo_status,pecos_verified,pa_status,diagnosis_on_file
|
patient_id,device_type,shipment_date,quantity,payer,visit_date,swo_status,pecos_verified,pa_status,diagnosis_on_file,plan_type
|
||||||
PT-GREEN-1,dexcom_g7,2026-06-10,3,Medicare Part B,2026-04-15,On File,Yes,Not Required,Yes
|
PT-GREEN-1,dexcom_g7,2026-06-10,3,Medicare Part B,2026-04-15,On File,Yes,Not Required,Yes,medicare
|
||||||
|
|
|
||||||
|
311
tests/test_overrides.py
Normal file
311
tests/test_overrides.py
Normal file
|
|
@ -0,0 +1,311 @@
|
||||||
|
"""
|
||||||
|
Tests for device-keyed staff overrides (build plan 02, P4).
|
||||||
|
|
||||||
|
Locked semantics (phase-2 design Item 4 / brief section 6):
|
||||||
|
- visit overrides are patient-scoped and fan out to ALL the patient's lines
|
||||||
|
(they ride the confirmed_visits path by construction);
|
||||||
|
- swo/pa overrides apply only to lines whose device_type matches;
|
||||||
|
- device_type '' marks a legacy patient-scoped row and matches all devices;
|
||||||
|
- staff knowledge wins over the CSV cell;
|
||||||
|
- after a write, the recompute returns {lines, rollup} from the same engine.
|
||||||
|
|
||||||
|
PHI CONTRACT: synthetic patient_ids only; overrides carry hashes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
|
from datetime import date, timedelta
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
sys.path.insert(0, str(Path(__file__).parent.parent / "python-backend"))
|
||||||
|
|
||||||
|
from core.coverage_calculator import ShipmentRecord # noqa: E402
|
||||||
|
from core.overrides import ( # noqa: E402
|
||||||
|
Override,
|
||||||
|
OverrideKey,
|
||||||
|
apply_overrides,
|
||||||
|
overrides_from_saved,
|
||||||
|
)
|
||||||
|
from core.worklist_readiness import build_readiness_index # noqa: E402
|
||||||
|
|
||||||
|
TODAY = date.today()
|
||||||
|
|
||||||
|
|
||||||
|
def _hash(pid: str) -> str:
|
||||||
|
return hashlib.sha256(pid.encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def _record(**kwargs) -> ShipmentRecord:
|
||||||
|
defaults = dict(
|
||||||
|
patient_id="PT-OV-1",
|
||||||
|
device_type="dexcom_g7",
|
||||||
|
shipment_date=TODAY - timedelta(days=5),
|
||||||
|
quantity=3,
|
||||||
|
payer="Medicare Part B",
|
||||||
|
component="sensor",
|
||||||
|
plan_type="medicare",
|
||||||
|
csv_visit_date=TODAY - timedelta(days=30),
|
||||||
|
csv_pecos_verified="Yes",
|
||||||
|
csv_diagnosis_on_file="Yes",
|
||||||
|
)
|
||||||
|
defaults.update(kwargs)
|
||||||
|
return ShipmentRecord(**defaults)
|
||||||
|
|
||||||
|
|
||||||
|
def _swo_override(pid="PT-OV-1", device="dexcom_g7", status="on_file"):
|
||||||
|
return Override(
|
||||||
|
key=OverrideKey(
|
||||||
|
org_id="org", patient_hash=_hash(pid), device_type=device,
|
||||||
|
doc_type="swo",
|
||||||
|
),
|
||||||
|
status=status,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_swo_applies_only_to_one_device():
|
||||||
|
# Two devices, both missing SWO -> Action Needed. Override device A only.
|
||||||
|
g7 = _record(device_type="dexcom_g7")
|
||||||
|
libre = _record(device_type="freestyle_libre_2")
|
||||||
|
index = build_readiness_index(
|
||||||
|
[g7, libre], overrides=[_swo_override(device="dexcom_g7")]
|
||||||
|
)
|
||||||
|
assert index.by_line[("PT-OV-1", "dexcom_g7", "medicare")].line_status.value == "Clear to Ship"
|
||||||
|
assert index.by_line[("PT-OV-1", "freestyle_libre_2", "medicare")].line_status.value == "Action Needed"
|
||||||
|
|
||||||
|
|
||||||
|
def test_legacy_blank_device_row_applies_patient_wide():
|
||||||
|
g7 = _record(device_type="dexcom_g7")
|
||||||
|
libre = _record(device_type="freestyle_libre_2")
|
||||||
|
index = build_readiness_index(
|
||||||
|
[g7, libre], overrides=[_swo_override(device="")]
|
||||||
|
)
|
||||||
|
for key, verdict in index.by_line.items():
|
||||||
|
assert verdict.line_status.value == "Clear to Ship", key
|
||||||
|
|
||||||
|
|
||||||
|
def test_device_scoped_row_wins_over_legacy_row():
|
||||||
|
g7 = _record(device_type="dexcom_g7")
|
||||||
|
index = build_readiness_index(
|
||||||
|
[g7],
|
||||||
|
overrides=[
|
||||||
|
_swo_override(device="", status="on_file"),
|
||||||
|
_swo_override(device="dexcom_g7", status="pending"),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
verdict = index.by_line[("PT-OV-1", "dexcom_g7", "medicare")]
|
||||||
|
swo = next(i for i in verdict.doc_items if i.doc_type == "swo")
|
||||||
|
assert swo.quality.value == "PENDING" # device-scoped Pending won
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_triggers_recompute_to_better_status():
|
||||||
|
# SWO missing is the last open required item; the override flips the line.
|
||||||
|
rec = _record()
|
||||||
|
base = build_readiness_index([rec])
|
||||||
|
assert base.by_line[("PT-OV-1", "dexcom_g7", "medicare")].line_status.value == "Action Needed"
|
||||||
|
fixed = build_readiness_index([rec], overrides=[_swo_override()])
|
||||||
|
assert fixed.by_line[("PT-OV-1", "dexcom_g7", "medicare")].line_status.value == "Clear to Ship"
|
||||||
|
|
||||||
|
|
||||||
|
def test_override_visit_applies_to_all_patient_lines():
|
||||||
|
# Visit rides confirmed_visits: patient-scoped fan-out by construction.
|
||||||
|
g7 = _record(device_type="dexcom_g7", csv_visit_date=None,
|
||||||
|
csv_swo_status="On File")
|
||||||
|
libre = _record(device_type="freestyle_libre_2", csv_visit_date=None,
|
||||||
|
csv_swo_status="On File")
|
||||||
|
confirmed = {_hash("PT-OV-1"): TODAY - timedelta(days=10)}
|
||||||
|
index = build_readiness_index([g7, libre], confirmed_visits=confirmed)
|
||||||
|
for key, verdict in index.by_line.items():
|
||||||
|
visit = next(i for i in verdict.doc_items if i.doc_type == "visit")
|
||||||
|
assert visit.satisfied, key
|
||||||
|
|
||||||
|
|
||||||
|
def test_overrides_from_saved_shape():
|
||||||
|
saved = {
|
||||||
|
_hash("PT-OV-1"): {
|
||||||
|
"": {"swo": {"status": "on_file"}},
|
||||||
|
"dexcom_g7": {"pa": {"status": "approved"}},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
overrides = overrides_from_saved(saved)
|
||||||
|
assert len(overrides) == 2
|
||||||
|
kinds = {(o.key.device_type, o.key.doc_type, o.status) for o in overrides}
|
||||||
|
assert kinds == {("", "swo", "on_file"), ("dexcom_g7", "pa", "approved")}
|
||||||
|
|
||||||
|
|
||||||
|
def test_apply_overrides_returns_touched_patients():
|
||||||
|
g7 = _record()
|
||||||
|
other = _record(patient_id="PT-OV-2")
|
||||||
|
index_lines = build_readiness_index([g7, other]).lines
|
||||||
|
touched = apply_overrides(index_lines, [_swo_override()])
|
||||||
|
assert touched == {"PT-OV-1"}
|
||||||
|
|
||||||
|
|
||||||
|
# --- API level ---------------------------------------------------------------
|
||||||
|
|
||||||
|
httpx = pytest.importorskip("httpx", reason="httpx required for TestClient")
|
||||||
|
from fastapi.testclient import TestClient # noqa: E402
|
||||||
|
|
||||||
|
import api.main as api_main # noqa: E402
|
||||||
|
|
||||||
|
client = TestClient(api_main.app)
|
||||||
|
|
||||||
|
|
||||||
|
def test_doc_status_put_accepts_device_and_returns_line_and_rollup(monkeypatch):
|
||||||
|
saved_writes = {}
|
||||||
|
|
||||||
|
def fake_upsert(org_id, patient_hash, doc_type, status,
|
||||||
|
status_date=None, expiry_date=None, device_type=""):
|
||||||
|
saved_writes[(patient_hash, doc_type, device_type)] = status
|
||||||
|
return True
|
||||||
|
|
||||||
|
def fake_load(org_id):
|
||||||
|
# Echo the persisted write back, as a fresh load would.
|
||||||
|
out = {}
|
||||||
|
for (ph, dt, dev), status in saved_writes.items():
|
||||||
|
out.setdefault(ph, {}).setdefault(dev, {})[dt] = {"status": status}
|
||||||
|
return out
|
||||||
|
|
||||||
|
monkeypatch.setattr(api_main, "get_or_create_org", lambda **kw: "org-test")
|
||||||
|
monkeypatch.setattr(api_main, "upsert_doc_status", fake_upsert)
|
||||||
|
monkeypatch.setattr(api_main, "load_doc_statuses_for_org", fake_load)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main, "load_confirmed_visits_for_org", lambda org: {}
|
||||||
|
)
|
||||||
|
|
||||||
|
resp = client.put(
|
||||||
|
"/api/doc-status",
|
||||||
|
json={
|
||||||
|
"patient_id": "PT-API-1",
|
||||||
|
"doc_type": "swo",
|
||||||
|
"status": "on_file",
|
||||||
|
"device_type": "dexcom_g7",
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"device_type": "dexcom_g7",
|
||||||
|
"plan_type": "medicare",
|
||||||
|
"csv_visit_date": (TODAY - timedelta(days=20)).isoformat(),
|
||||||
|
"csv_pecos_verified": "Yes",
|
||||||
|
"csv_diagnosis_on_file": "Yes",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"device_type": "freestyle_libre_2",
|
||||||
|
"plan_type": "medicare",
|
||||||
|
"csv_visit_date": (TODAY - timedelta(days=20)).isoformat(),
|
||||||
|
"csv_pecos_verified": "Yes",
|
||||||
|
"csv_diagnosis_on_file": "Yes",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
body = resp.json()
|
||||||
|
assert body["device_type"] == "dexcom_g7"
|
||||||
|
by_dev = {l["device_type"]: l for l in body["lines"]}
|
||||||
|
# The override satisfied G7's SWO; the Libre line is untouched (no leak).
|
||||||
|
assert by_dev["dexcom_g7"]["line_status"] == "Clear to Ship"
|
||||||
|
assert by_dev["freestyle_libre_2"]["line_status"] == "Action Needed"
|
||||||
|
assert body["rollup_status"] == "Action Needed" # worst line
|
||||||
|
|
||||||
|
|
||||||
|
def test_doc_status_put_without_lines_keeps_legacy_shape(monkeypatch):
|
||||||
|
monkeypatch.setattr(api_main, "get_or_create_org", lambda **kw: "org-test")
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main, "upsert_doc_status", lambda *a, **kw: True
|
||||||
|
)
|
||||||
|
resp = client.put(
|
||||||
|
"/api/doc-status",
|
||||||
|
json={"patient_id": "PT-API-2", "doc_type": "pa", "status": "approved"},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
body = resp.json()
|
||||||
|
assert body["display"] == "Approved"
|
||||||
|
assert "lines" not in body
|
||||||
|
|
||||||
|
|
||||||
|
def test_confirm_visit_with_lines_returns_rerolled_patient(monkeypatch):
|
||||||
|
monkeypatch.setattr(api_main, "get_or_create_org", lambda **kw: "org-test")
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main, "upsert_confirmed_visit", lambda *a, **kw: True
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main, "load_doc_statuses_for_org", lambda org: {}
|
||||||
|
)
|
||||||
|
ship = (TODAY - timedelta(days=5)).isoformat()
|
||||||
|
resp = client.post(
|
||||||
|
"/api/confirm-visit",
|
||||||
|
json={
|
||||||
|
"patient_id": "PT-API-3",
|
||||||
|
"confirmed_date": (TODAY - timedelta(days=15)).isoformat(),
|
||||||
|
"shipment_date": ship,
|
||||||
|
"payer": "Medicare Part B",
|
||||||
|
"device_type": "dexcom_g7",
|
||||||
|
"quantity": 3,
|
||||||
|
"csv_swo_status": "On File",
|
||||||
|
"csv_pecos_verified": "Yes",
|
||||||
|
"csv_diagnosis_on_file": "Yes",
|
||||||
|
"plan_type": "medicare",
|
||||||
|
"lines": [
|
||||||
|
{
|
||||||
|
"device_type": "dexcom_g7",
|
||||||
|
"plan_type": "medicare",
|
||||||
|
"csv_swo_status": "On File",
|
||||||
|
"csv_pecos_verified": "Yes",
|
||||||
|
"csv_diagnosis_on_file": "Yes",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"device_type": "freestyle_libre_2",
|
||||||
|
"plan_type": "medicare",
|
||||||
|
"csv_swo_status": "On File",
|
||||||
|
"csv_pecos_verified": "Yes",
|
||||||
|
"csv_diagnosis_on_file": "Yes",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
body = resp.json()
|
||||||
|
# Legacy record fields still present
|
||||||
|
assert body["readiness_status"] == "Clear to Ship"
|
||||||
|
# The confirmed visit fanned out to BOTH echoed lines
|
||||||
|
assert all(l["line_status"] == "Clear to Ship" for l in body["lines"])
|
||||||
|
assert body["rollup_status"] == "Clear to Ship"
|
||||||
|
|
||||||
|
|
||||||
|
def test_upload_grades_with_saved_device_scoped_override(monkeypatch):
|
||||||
|
"""An SWO override saved for device A feeds the verdict for A's line only."""
|
||||||
|
pid_hash = hashlib.sha256("PT-UP-1".encode()).hexdigest()
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main,
|
||||||
|
"load_doc_statuses_for_org",
|
||||||
|
lambda org: {
|
||||||
|
pid_hash: {"dexcom_g7": {"swo": {"status": "on_file"}}}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(api_main, "get_or_create_org", lambda **kw: "org-test")
|
||||||
|
monkeypatch.setattr(
|
||||||
|
api_main, "load_confirmed_visits_for_org", lambda org: {}
|
||||||
|
)
|
||||||
|
ship = (TODAY - timedelta(days=5)).isoformat()
|
||||||
|
visit = (TODAY - timedelta(days=30)).isoformat()
|
||||||
|
header = (
|
||||||
|
"patient_id,device_type,shipment_date,quantity,payer,plan_type,"
|
||||||
|
"visit_date,pecos_verified,diagnosis_on_file"
|
||||||
|
)
|
||||||
|
csv_text = (
|
||||||
|
header
|
||||||
|
+ f"\nPT-UP-1,Dexcom G7,{ship},3,Medicare Part B,medicare,{visit},Yes,Yes"
|
||||||
|
+ f"\nPT-UP-1,Libre 2,{ship},1,Medicare Part B,medicare,{visit},Yes,Yes"
|
||||||
|
)
|
||||||
|
resp = client.post(
|
||||||
|
"/api/upload",
|
||||||
|
files={"file": ("f.csv", io.BytesIO(csv_text.encode()), "text/csv")},
|
||||||
|
)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
recs = {r["device_type"]: r for r in resp.json()["records"]}
|
||||||
|
assert recs["dexcom_g7"]["readiness_status"] == "Clear to Ship"
|
||||||
|
assert recs["freestyle_libre_2"]["readiness_status"] == "Action Needed"
|
||||||
|
# Display follows the same device scope
|
||||||
|
assert recs["dexcom_g7"]["doc_state"]["swo"] == "On File"
|
||||||
|
|
@ -609,3 +609,110 @@ def test_upload_readiness_items_carry_rule_ids():
|
||||||
assert items["pecos"]["rule_id"] == "R004"
|
assert items["pecos"]["rule_id"] == "R004"
|
||||||
assert items["pa"]["rule_id"] == "R003"
|
assert items["pa"]["rule_id"] == "R003"
|
||||||
assert items["swo"]["rule_id"] == "R100"
|
assert items["swo"]["rule_id"] == "R100"
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# P5: plan-type enforcement in the live path (plan 02)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
def test_plan_type_value_normalization():
|
||||||
|
"""Synonyms canonicalize; the same string in a PAYER column changes
|
||||||
|
nothing about readiness."""
|
||||||
|
from api.normalizer import _normalize_plan_type
|
||||||
|
|
||||||
|
for raw, want in [
|
||||||
|
("Medicare Part B", "medicare"), ("FFS", "medicare"),
|
||||||
|
("Original Medicare", "medicare"), ("MA", "medicare_advantage"),
|
||||||
|
("Part C", "medicare_advantage"), ("state medicaid", "medicaid"),
|
||||||
|
("Private", "commercial"), ("Employer", "commercial"),
|
||||||
|
("", None), (" ", None), ("Tricare Select", None),
|
||||||
|
]:
|
||||||
|
assert _normalize_plan_type(raw) == want, raw
|
||||||
|
|
||||||
|
|
||||||
|
def test_payer_name_never_sets_plan_type():
|
||||||
|
"""A payer of 'Medicare Part B' with NO plan_type column yields
|
||||||
|
Plan Type Needed — never a guess from the payer name."""
|
||||||
|
header = (
|
||||||
|
"patient_id,device_type,shipment_date,quantity,payer,"
|
||||||
|
"swo_status,visit_date,pecos_verified,pa_status,diagnosis_on_file"
|
||||||
|
)
|
||||||
|
csv_text = (
|
||||||
|
header
|
||||||
|
+ f"\nPT-NG-1,Dexcom G7,{SHIP},3,Medicare Part B,"
|
||||||
|
+ f"On File,{VISIT},Yes,,Yes"
|
||||||
|
)
|
||||||
|
resp = _upload(csv_text)
|
||||||
|
rec = resp.json()["records"][0]
|
||||||
|
assert rec["plan_type"] is None
|
||||||
|
assert rec["readiness_status"] == "Plan Type Needed"
|
||||||
|
|
||||||
|
|
||||||
|
def test_plan_type_synonym_flows_end_to_end():
|
||||||
|
csv_text = (
|
||||||
|
HEADER
|
||||||
|
+ f"\nPT-SYN-1,Dexcom G7,{SHIP},3,Medicare Part B,Medicare Part B,"
|
||||||
|
+ f"On File,{VISIT},Yes,,Yes"
|
||||||
|
)
|
||||||
|
resp = _upload(csv_text)
|
||||||
|
rec = resp.json()["records"][0]
|
||||||
|
assert rec["plan_type"] == "medicare" # value map canonicalized it
|
||||||
|
assert rec["readiness_status"] == "Clear to Ship"
|
||||||
|
|
||||||
|
|
||||||
|
def test_unknown_plan_type_value_yields_plan_type_needed():
|
||||||
|
csv_text = (
|
||||||
|
HEADER
|
||||||
|
+ f"\nPT-UNK-1,Dexcom G7,{SHIP},3,Tricare,Tricare Select,"
|
||||||
|
+ f"On File,{VISIT},Yes,,Yes"
|
||||||
|
)
|
||||||
|
resp = _upload(csv_text)
|
||||||
|
rec = resp.json()["records"][0]
|
||||||
|
assert rec["plan_type"] is None
|
||||||
|
assert rec["readiness_status"] == "Plan Type Needed"
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_config_never_reaches_readiness():
|
||||||
|
"""'default' is not a known plan type; it must grade Plan Type Needed,
|
||||||
|
never through the default payer_rules entry."""
|
||||||
|
from core.readiness import evaluate_readiness
|
||||||
|
|
||||||
|
v = evaluate_readiness(
|
||||||
|
"default",
|
||||||
|
csv_swo_status="On File",
|
||||||
|
csv_pecos_verified="Yes",
|
||||||
|
csv_diagnosis_on_file="Yes",
|
||||||
|
)
|
||||||
|
assert v.line_status.value == "Plan Type Needed"
|
||||||
|
|
||||||
|
|
||||||
|
def test_deprecation_warning_logged_once_per_batch(caplog):
|
||||||
|
header = (
|
||||||
|
"patient_id,device_type,shipment_date,quantity,payer,"
|
||||||
|
"swo_status,visit_date,pecos_verified,pa_status,diagnosis_on_file"
|
||||||
|
)
|
||||||
|
csv_text = (
|
||||||
|
header
|
||||||
|
+ f"\nPT-DW-1,Dexcom G7,{SHIP},3,Medicare Part B,On File,{VISIT},Yes,,Yes"
|
||||||
|
+ f"\nPT-DW-2,Libre 3,{SHIP},1,Aetna,On File,{VISIT},,,Yes"
|
||||||
|
)
|
||||||
|
with caplog.at_level("WARNING"):
|
||||||
|
resp = _upload(csv_text)
|
||||||
|
assert resp.status_code == 200
|
||||||
|
hits = [r for r in caplog.records if "plan_type not provided" in r.getMessage()]
|
||||||
|
assert len(hits) == 1 # once per batch, not per record
|
||||||
|
assert "2/2 records" in hits[0].getMessage()
|
||||||
|
|
||||||
|
|
||||||
|
def test_unrecognized_plan_value_warning_hashes_patient(caplog):
|
||||||
|
csv_text = (
|
||||||
|
HEADER
|
||||||
|
+ f"\nPT-RAW-SECRET,Dexcom G7,{SHIP},3,Tricare,Tricare Select,"
|
||||||
|
+ f"On File,{VISIT},Yes,,Yes"
|
||||||
|
)
|
||||||
|
with caplog.at_level("WARNING"):
|
||||||
|
_upload(csv_text)
|
||||||
|
hits = [r for r in caplog.records if "Unrecognized plan_type" in r.getMessage()]
|
||||||
|
assert len(hits) == 1
|
||||||
|
assert "PT-RAW-SECRET" not in hits[0].getMessage()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue