Files
ecw-charge-validation/docs/superpowers/specs/2026-10-07-dental-claims-run-all-conditions-design.md
ManikandanandClaude Opus 5.5 ba15a574ab Initial import: eCW Charge Validation bot and results Portal
Snapshot of the working project as of 2026-10-23 (local 2d4d4fc), one
commit with no earlier history: the tracked files were de-identified
first (synthetic claim ids and patient data only; see Context.md
section 7). Credentials, run logs, screenshots, claim reports and client
workbooks are gitignored and not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 18:38:17 +05:30

7.1 KiB

Dental claims run every applicable condition — design

Date: 2026-10-07. Status: approved in chat (operator, 2026-10-07); implemented 2026-10-12 (operator: "this is our number one condition").

2026-10-12 update (as built)

  • The rule now also covers #12 (H codes: BH payer → modifier removed; any other payer → line unchecked + fee 0) and #14 (Medicare: G8510 / G8431 unchecked + fee 0, #6 not run). Both run on Dental claims like every other condition; #12's BH path has no modifier column to read on the Dental grid, so it never fires there.
  • A fix the Dental screen cannot hold → Review (operator): a condition module declares DENTAL_UNSUPPORTED = "<reason>" and run_all records that reason instead of applying it on a screen == "dental" read — telehealth, medicare_telehealth, vaccine_admin_codes.
  • Dental claims are never saved in this change (operator), whatever SAVE_CORRECTIONS says; the review-before-close box still shows.
  • A Dental claim is read and run through the conditions even with CHECK_HIGH_RISK and CHECK_SLIDING_FEE both off (it used to come back blank).
  • The Charge Summary applies the same claim-level checks (note read, CPT / ICD rows read, conditions run) to a Dental read as to UB/HCFA.
  • Row selectors gained a third (Dental) alternative, scoped to the Dental window on screen (:visible); extract() returns screen ("ub" / "hcfa" / "dental").
  • Not live-verified yet: the first live run should be SAVE-off on a few Dental claims (one with DCONS or Dscprit).

Rule (operator, 2026-10-07)

Every claim is checked against every condition whose Payer column is "All" / "All payers", plus every condition specific to that claim's payer (Medicare, Medicaid, Dental payers, ...). This holds for every payer and every claim screen — UB, HCFA and Dental alike.

UB and HCFA claims already work this way: each claim runs the whole registry (conditions/__init__.py CONDITIONS) and each condition's own detect() decides from the claim's codes and payer. The gap is Dental: a Dental claim today runs only #15 high risk and #8 sliding fee and never reaches run_all. So, for example, dummy_codes (DCONS/Dscprit, which are Dental codes) can never fire on any claim.

What a Dental claim will run

Doc # Condition Payer (document) Module
5 J2930/J2001 uncheck + fee 0 ALL j2930_j2001_update
6 Depression DX pointer All depression_dx_pointer
7 Zero-fee uncheck / priced line check ALL zero_fee_uncheck, priced_line_check
21 Telehealth POS 2 + modifier All telehealth
22 Medicare telehealth G2025 Medicare medicare_telehealth
18 Vaccine admin codes All except Medicare vaccine_admin_codes
8 DCONS/Dscprit uncheck + fee 0 All Dental Payer dummy_codes
8 Sliding fee date check All Dental Payer pages/sliding_fee (unchanged)
15 High risk in Billing Notes Dental Payers pages/dental_notes (unchanged)

No condition gains a form-type check: each still decides from codes and payer only. A condition whose codes are not on the claim does nothing.

Dental screen facts (from Dom.txt, claim screen .modal[id^="dentalClaim"])

  • CPT/CDT grid table[id^="claimCPTCodesTable"]; real rows are tr[ng-repeat^="CPT in CPTCodes"] (no CPTROW_ id).
  • Per row: checkbox [ng-click*="updateBillToIns("] (same as UB/HCFA), code [data-fieldname="web_cptcode"], pointers web_icd1..web_icd4, units web_units, fee web_billedFee (blur runs editCPTRow('BILLED_FEE')), DOS DentalClaimCPTSDOS.
  • No per-row POS and no modifier columns. POS is claim-level (ng-model="ClaimData.pos").
  • Prog. Notes button button[ng-click="viewProgNote()"] (dentalClaimProgressNoteBtn…) — the existing SEL_PROGRESS_NOTES matches.
  • Insurance grid: #DentalClaimTbl2 (Bill To, Ins Id, Name, ...).
  • Billing Notes: #dentalClaimNotes (already read by high risk).

None of the row fields has been exercised live yet; Dom.txt is one capture.

Design

  1. Selectors (selectors/claim_form.py): add the Dental alternative to each row selector the helpers already use — SEL_CPT_ROWS, SEL_CPT_CODE, SEL_CPT_ICD1..4, SEL_CPT_BILLED_FEE, SEL_CPT_UNITS. The Dental row selector is scoped under .modal[id^="dentalClaim"] so it cannot match a grid on another screen. Within one row only one alternative ever matches, the same contract the UB/HCFA pairs rely on.
  2. Reader (pages/claim_form.py _EXTRACT_JS): read Dental rows into the same cpt row shape (code, icd1..4, units, billed_fee, billed, sdos; pos/mod1..4 empty), insurance from #DentalClaimTbl2, the Dental claim number, ICD list, and notes from #dentalClaimNotes. One extract() for all three screens.
  3. Flow (flows/export_medcor_ready.py): a Dental claim runs high risk + sliding fee first (unchanged, read-only), then the same path as UB/HCFA: extract(), Prog. Notes (when OPEN_PROGRESS_NOTES), run_all, per-claim box, Charge Summary. The Dental results stay on the claim's data so the box and the summary show both.
  4. A fix the Dental screen cannot make — e.g. telehealth needs a row modifier and the Dental grid has none, or POS is claim-level: the condition returns declined(...) with the reason ("Dental screen has no modifier column"), so the claim is Review in the Charge Summary. Never a silent skip, never a guess.
  5. Charge Summary: one row per claim combining condition comments with the Dental findings (HIGH RISK, sliding fee). Category: Review beats Fail beats Pass, as today.
  6. Saving: Dental claims are never saved in this change, whatever SAVE_CORRECTIONS says. Their corrections are shown and listed as "Corrections pending (not saved)". Dental save is enabled only after a live verification-mode run confirms the row writes.

Error handling

  • Dental form not loaded (wait_claim_loaded): conditions skipped, claim is Review — same as HCFA today.
  • A Dental row field missing (fee or checkbox not found): the existing helpers already treat a missing field as unknown, not as zero/unchecked.
  • High risk / sliding fee failures keep their current Review handling.

Testing

  • Grow tests/fixtures/dental_claim.html from Dom.txt's real Dental grid (rows, checkbox, fee, pointers, insurance grid, Prog. Notes button) with no patient data.
  • extract() on the Dental fixture returns the expected cpt and insurance.
  • Per condition, a Dental case: dummy codes (DCONS/Dscprit) uncheck + zero; J2001 uncheck + zero; zero-fee uncheck; priced line check; depression pointer retag on web_icd*; telehealth on Dental → declined/Review.
  • Flow: a Dental claim gets high risk + sliding fee and condition results in one summary row; never offered Save.
  • Full suite stays green.
  • Live: one SAVE-off run on Dental test claims (with a DCONS or Dscprit line) before Dental save is considered.

Out of scope

  • New document conditions not yet built (#3, #4, #9-#14, #16, #19, #20, #23-#55).
  • Saving Dental claims.
  • "Special programs" half of #8.