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>
This commit is contained in:
ManikandanandClaude Opus 5.5 committed 2026-10-23 18:38:17 +05:30
commit ba15a574ab
205 files changed
+56772

No files matched your search

+458
View File
@@ -0,0 +1,458 @@
<!doctype html>
<!--
A faithful cut-down of the UB Claim modal eCW served on 2026-09-07.
Reproduced on purpose, rather than saved from the live page: the real form is
patient data and must never be committed. Everything the extractor reaches for
is here with the real attribute names, the real nesting, and — the point of the
whole fixture — the real **timestamped ids**.
The timestamp here is 9999999999999, deliberately different from the
1788790287089 of the captured DOM. Any selector that had the number baked in
would fail against this file, which is exactly what the test is for.
Also reproduced faithfully:
* the ICD code lives in an <input value="R69">, not in text
* the CPT grid is entirely inputs, ids ending in the row index
* eCW pads every grid with blank ng-repeat rows to hold its height
* the address text is ellipsised, with the full value in title=
-->
<html>
<body>
<div class="modal fade bluetheme ubClaimModalBackdrop in" id="UBClaimDiv9999999999999" style="display:block">
<div class="modal-dialog visible" id="UBClaimDiv">
<div id="UBClaimModalContent9999999999999" class="modal-content">
<div class="modal-header">
<button id="UBClaimBtn3" type="button" class="close">&times;</button>
<h4 class="modal-title" id="myModalLabel">UB Form Details
<span class="ml5 fs11 patient-identifier-span">SAMPLE, Pat Q &nbsp; May 11, 1979 (48 yo F) &nbsp; Acc No. 900123</span>
</h4>
</div>
<div class="modal-body">
<!-- patient strip -->
<div class="single-column middle">
<span class="blue_txt" ng-bind="showEllipsisForField(PatientInfo.namewithsuffix,25)" title="Sample, Pat, Q">Sample, Pat, Q</span>
<span class="blue_txt" ng-bind="' ' + PatientInfo.Age + ', ' + PatientInfo.patSex"> 48Y, F</span>
<span class="fnt11" ng-bind="PatientInfo.dob">05/11/1979</span>
<span class="fnt11" ng-bind="showEllipsisForField(PatientInfo.address +', '+ PatientInfo.address2 + ', ' + PatientInfo.state+ ' ' + PatientInfo.zip,45)" title="100 SAMPLE ST, , CO 80000-0000">100 SAMPLE ST, , CO 806...</span>
<span class="fnt11" ng-bind="PatientInfo.phone">555-010-0100</span>
Acct No : <span ng-bind="showEllipsisForField(PatientInfo.ControlNo,10)">900123</span>
</div>
<!-- header block -->
<table class="table section-table"><tbody><tr>
<td>
<table class="table"><tbody>
<tr>
<td><label>Claim No:</label></td>
<td class="w60p ubClaimNumberText"><span title="9104000">9104000</span></td>
</tr>
<tr>
<td><label>Claim Date</label></td>
<td><input type="text" class="form-control MMDDYYYYDatePicker hasDatepicker"
ng-model="ClaimData.ClaimDate" id="claimDate9999999999999"
value="06/29/2026" placeholder="MM/DD/YYYY"></td>
</tr>
</tbody></table>
</td>
<td>
<table class="table"><tbody>
<tr><td><label>Bill Type</label></td>
<td><input type="text" ng-model="Ub92Data.BillType" id="BillType" value="131"></td></tr>
</tbody></table>
</td>
<td>
<label>Facility:</label>
<input id="UBClaimIpt23" type="text" ng-model="selectApptFacilityData.facility.Name"
title="MWC:Brighton Womens Clinic" value="MWC:Brighton Womens Clinic" readonly>
<label>Copay</label>
<input type="text" id="ClaimDataCopay" ng-model="ClaimData.copay" value="0.00">
<label>Pt. Uncovered Amt:</label>
<input type="text" id="ClaimDataPtUnCovAmt" ng-model="ClaimData.PtUnCovAmt" value="0.00">
</td>
<td>
<label>Attending</label>
<input id="UBClaimIpt29" type="text" ng-model="ClaimData.PayToProviderName"
value="Clinician, Casey M" readonly>
<label>Claim Status</label>
<select id="claimStatusSel9999999999999" ng-model="selectedClaimStatusCodes" ng-change="claimStatusChanged()">
<option value="CMC">Ready to Submit (Electronic)</option>
<option value="113ME">Medcor Testing</option>
<option value="108ME" selected="selected">Medcor Ready</option>
<option value="CMS">Submitted</option>
</select>
</td>
</tr></tbody></table>
<!-- upper tabs -->
<ul id="UBClaimUl1" class="nav">
<li class="active"><a id="UBClaimLink4" href="javascript:void(0)" data-toggle="tab" data-target="#claimedi9999999999999">ICD, CPT and Revenue Codes</a></li>
<li><a id="UBClaimLink3" href="javascript:void(0)" data-toggle="tab" data-target="#inp9999999999999">Occurrence and Value Codes</a></li>
<li><a id="UBClaimLink2" href="javascript:void(0)" data-toggle="tab" data-target="#addinf9999999999999">Insurance and Payments</a></li>
<li><a id="UBClaimLink1" href="javascript:void(0)" data-toggle="tab" data-target="#icd9999999999999">Additional Information</a></li>
</ul>
<!-- Insurance and Payments pane -->
<div class="tab-pane" id="addinf9999999999999">
<table id="UBClaimTbl3" class="table table-bordered blue-fade-table">
<thead><tr>
<th style="width:30px"><div class="th-inner"></div></th>
<th><div class="th-inner">Bill To</div></th>
<th><div class="th-inner">Name</div></th>
<th><div class="th-inner">State</div></th>
<th><div class="th-inner">Subscriber No.</div></th>
<th><div class="th-inner">Rel</div></th>
<th><div class="th-inner">Insured</div></th>
<th><div class="th-inner">Group No.</div></th>
</tr></thead>
<tbody>
<tr ng-repeat="insurance in InvInsList">
<td><span ng-bind="insurance.sequanceNo">P</span></td>
<td><input id="UBClaimIpt1ngR0" type="checkbox" name="billto" checked></td>
<td><span ng-bind="insurance.InsName">BH COLORADO ACCESS</span></td>
<td><span ng-bind="insurance.InsState">CO</span></td>
<td><span ng-bind="insurance.SubscriberNo">J000000</span></td>
<td><span ng-bind="insurance.SubscriberRel">1</span></td>
<td><span ng-bind="insurance.SubscriberName">Sample, Pat, Q</span></td>
<td><span ng-bind="insurance.GroupNo"></span></td>
</tr>
<tr ng-repeat="temp in InvInsListBlankRows">
<td>&nbsp;</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td>
</tr>
</tbody>
</table>
<table id="UBClaimTbl4" class="table table-bordered blue-fade-table">
<thead><tr>
<th><div class="th-inner">Id</div></th>
<th><div class="th-inner">Date</div></th>
<th><div class="th-inner">From</div></th>
<th><div class="th-inner">Allowed</div></th>
<th><div class="th-inner">Deduct</div></th>
<th><div class="th-inner">Coins</div></th>
<th><div class="th-inner">Copay</div></th>
<th><div class="th-inner">Paid</div></th>
<th><div class="th-inner">Adjust</div></th>
<th><div class="th-inner">Withheld</div></th>
<th><div class="th-inner">E</div></th>
</tr></thead>
<tbody>
<tr ng-repeat="PayAdjRef in PayAdjRefund">
<td ng-bind="PayAdjRef.id">2000001</td>
<td ng-bind="PayAdjRef.date">06/29/2026</td>
<td ng-bind="PayAdjRef.from">Patient</td>
<td class="text-right" ng-bind="PayAdjRef.allowed">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.deduct">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.coins">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.copay">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.paid">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.adjust">0.00</td>
<td class="text-right" ng-bind="PayAdjRef.withheld">0.00</td>
<td></td>
</tr>
<tr ng-repeat="temp in PayAdjRefundBlankRows">
<td></td><td></td><td></td><td></td><td></td><td></td>
<td></td><td></td><td></td><td></td><td></td>
</tr>
</tbody>
</table>
</div>
<!-- ICD, CPT and Revenue pane -->
<div class="tab-pane active" id="claimedi9999999999999">
<div id="icdCodesTableDiv">
<table class="table table-bordered blue-fade-table" id="icdCodesTable">
<thead><tr>
<th class="text-center">#</th>
<th></th>
<th>Code</th>
<th>Name</th>
<th></th>
</tr></thead>
<tbody ng-model="ICDCodes">
<tr ng-repeat="icd in ICDCodes">
<td class="text-center"><span ng-bind="$index+1">1</span></td>
<td class="text-center"><span class="icd10-green">10</span></td>
<td title="R69"><input id="UBClaimIpt2ngR0" type="text"
class="input-xs editableTDText" value="R69"></td>
<td title="Illness, unspecified">Illness, unspecified</td>
<td class="text-center"><button id="UBClaimBtn1ngR0"></button></td>
</tr>
<tr id="2">
<td class="text-center">*</td>
<td></td>
<td><input type="text" ng-model="newICD" id="txtnewIcd" class="input-xs editableTDText"></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
<!-- Condition Codes FL 18-28, as the real form (Dom.txt, 2026-10-16):
select-claim-code inputs uBClaimCondtnCode1..11, no blur / change
handler. setConditionCodes([...]) fills them per test case. -->
<table class="table table-bordered blue-fade-table" id="example4">
<thead><tr><th colspan="11" class="text-center">Condition Codes</th></tr></thead>
<thead><tr><th>18</th><th>19</th><th>20</th><th>21</th><th>22</th><th>23</th>
<th>24</th><th>25</th><th>26</th><th>27</th><th>28</th></tr></thead>
<tbody><tr id="conditionCodeRow"></tr></tbody>
</table>
<script>
(function () {
var row = document.getElementById('conditionCodeRow');
for (var n = 1; n <= 11; n++) {
row.insertAdjacentHTML('beforeend',
'<td><select-claim-code field-id="uBClaimCondtnCode' + n + '" max-length="2"' +
' table-name="UB92_conditioncodes" search-record="Ub92Data.ConditionCode' + n + '">' +
'<div class="select-record"><div class="input-group">' +
'<input type="text" class="form-control editableTDText text-center" maxlength="2"' +
' id="uBClaimCondtnCode' + n + '" ng-model="searchRecord" ng-focus="loadCodes();"' +
' ng-keydown="validateKey($event);" ng-keyup="showCodes($event);">' +
'</div></div></select-claim-code></td>');
}
// A test sets this to have the box marked invalid on input, as
// select-claim-code's ng-class does for a code it does not know.
window.conditionCodeInvalid = false;
row.addEventListener('input', function (e) {
if (window.conditionCodeInvalid) e.target.classList.add('invalid');
});
window.setConditionCodes = function (codes) {
for (var n = 1; n <= 11; n++) {
document.getElementById('uBClaimCondtnCode' + n).value = codes[n - 1] || '';
}
};
})();
</script>
<!-- CPT / Revenue tabs -->
<ul class="nav">
<li class="active" id="liCptRev"><a class="cursor addBrdr" data-toggle="tab"
data-target="#cptRev9999999999999" ng-click="cptTabUpdate('cptRev')">CPT/Revenue Codes (1)</a></li>
<li id="liCPTHcpcs"><a class="cursor" data-toggle="tab"
data-target="#cptHCPCS9999999999999" ng-click="cptTabUpdate('cptHcpcs')">CPT/HCPCS (1)</a></li>
</ul>
<div class="tab-content claim-tab">
<div class="tab-pane active" id="cptRev9999999999999">
<table id="UBClaimTbl10" class="table table-bordered blue-fade-table">
<thead><tr>
<th class="text-center"></th>
<th>42 RV CC</th>
<th>43 Description</th>
<th>44 HCPCS/Rates</th>
<th>45 Srvc Date</th>
<th>46 Srvc Unit</th>
<th>47 Total Charges</th>
<th>48 Non Convered</th>
<th>49 </th>
</tr></thead>
<tbody>
<tr ng-repeat="cptdetails in UB92CPTDetails">
<td class="text-center">1</td>
<td>0900</td>
<td>Psychological Services</td>
<td>H0023 GT</td>
<td>06/29/2026</td>
<td>1</td>
<td class="text-right">74.00</td>
<td></td>
<td></td>
</tr>
<tr ng-repeat="temp in UB92CPTDetailsBlankRows">
<td></td><td>&nbsp;</td><td></td><td></td><td></td>
<td></td><td></td><td></td><td></td>
</tr>
</tbody>
</table>
<table id="UBClaimTbl11" class="table">
<thead><tr>
<th></th><th></th><th></th><th></th>
<th class="text-center">Total Charges </th>
<th class="text-right" ng-bind="TotalCharges">74.00</th>
<th></th><th></th>
</tr></thead>
</table>
</div>
<div class="tab-pane" id="cptHCPCS9999999999999">
<div class="allbrd cptTbl" id="CPTCodesDiv">
<table class="table table-bordered blue-fade-table" id="claimCPTCodesTable9999999999999">
<thead><tr>
<th class="text-center">#</th><th>&nbsp;</th><th>Code</th><th>POS</th><th>TOS</th>
<th>SDOS</th><th>EDOS</th><th>M1</th><th>M2</th><th>M3</th><th>M4</th>
<th>ICD1</th><th>ICD2</th><th>ICD3</th><th>ICD4</th><th>Units</th>
<th>Billed Fee</th><th>Pro Id</th>
</tr></thead>
<tbody>
<tr ng-repeat="cpt in CPTCodes" id="CPTROW_0">
<td class="text-center"><span ng-bind="$index + 1">1</span></td>
<td><input type="checkbox" id="claimCPTBillToInsChk0" checked></td>
<td title="Behavioral Health Outreach Service (TH)"><input id="uBClaimCPTCode0" type="text" value="H0023" readonly></td>
<td><input type="text" id="uBClaimPOS0" value="11"></td>
<td><input type="text" id="uBClaimTOS0" value="1"></td>
<td><input type="text" id="uBClaimSDOS0" value="06/29/2026"></td>
<td><input type="text" id="uBClaimEDOS0" value="06/29/2026"></td>
<td><input type="text" id="uBClaimMod10" value="GT"></td>
<td><input type="text" id="uBClaimMod20" value=""></td>
<td><input type="text" id="uBClaimMod30" value=""></td>
<td><input type="text" id="uBClaimMod40" value=""></td>
<td><input type="text" id="uBClaimICD10" value="1"></td>
<td><input type="text" id="uBClaimICD20" value=""></td>
<td><input type="text" id="uBClaimICD30" value=""></td>
<td><input type="text" id="uBClaimICD40" value=""></td>
<td><input type="text" id="uBClaimUnits0" value="1"></td>
<td title="74.00"><input type="text" id="uBClaimBillFee0" value="74.00"></td>
<td><input type="text" value="" readonly></td>
</tr>
<tr ng-repeat="cpt in CPTCodes" id="CPTROW_1">
<td class="text-center"><span>2</span></td>
<td><input type="checkbox" id="claimCPTBillToInsChk1" checked></td>
<td title="Psychiatric diagnostic evaluation"><input id="uBClaimCPTCode1" type="text" value="90791" readonly></td>
<td><input type="text" id="uBClaimPOS1" value="11"></td>
<td><input type="text" id="uBClaimTOS1" value="1"></td>
<td><input type="text" id="uBClaimSDOS1" value="06/30/2026"></td>
<td><input type="text" id="uBClaimEDOS1" value="06/30/2026"></td>
<td><input type="text" id="uBClaimMod11" value=""></td>
<td><input type="text" id="uBClaimMod21" value=""></td>
<td><input type="text" id="uBClaimMod31" value=""></td>
<td><input type="text" id="uBClaimMod41" value=""></td>
<td><input type="text" id="uBClaimICD11" value="1"></td>
<td><input type="text" id="uBClaimICD21" value=""></td>
<td><input type="text" id="uBClaimICD31" value=""></td>
<td><input type="text" id="uBClaimICD41" value=""></td>
<td><input type="text" id="uBClaimUnits1" value="2"></td>
<td title="150.00"><input type="text" id="uBClaimBillFee1" value="150.00"></td>
<td><input type="text" value="" readonly></td>
</tr>
<!-- the blank entry row eCW leaves at the bottom: no CPTROW_ id -->
<tr>
<td class="text-center">*</td>
<td class="text-center"><input type="checkbox" checked></td>
<td><input type="text" id="editableTDTextNewCPTcode" ng-model="newCPT"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td><input type="text"></td><td><input type="text"></td>
<td></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- bottom tabs: notes, error logs -->
<div class="tab-content error-claim-tab">
<div class="tab-pane active" id="tab19999999999999">
<label>Billing Notes</label>
<textarea class="form-control" ng-model="ClaimData.notes" id="ubClaimNotes">Awaiting coding review.</textarea>
<table id="UBClaimTbl15" class="table table-condensed">
<thead><tr><th colspan="2"><label>Patient Portion</label></th></tr></thead>
<tbody>
<tr><td>Charges</td><td class="text-right boldTd" ng-bind="InvBalances[0].PtResp">0.00</td></tr>
<tr><td>Payments ...</td><td class="text-right boldTd" ng-bind="InvBalances[0].PtPayment">0.00</td></tr>
<tr><td>Balance</td><td class="text-right boldTd" ng-bind="InvBalances[0].PtBalance">0.00</td></tr>
</tbody>
</table>
<table id="UBClaimTbl16" class="table table-condensed">
<thead><tr><th colspan="2"><label>Total</label></th></tr></thead>
<tbody>
<tr><td>Charges</td><td class="text-right boldTd" ng-bind="InvBalances[0].InvoiceAmount">224.00</td></tr>
<tr><td>Payments ...</td><td class="text-right boldTd" ng-bind="InvBalances[0].Payment">0.00</td></tr>
<tr><td>Balance</td><td class="text-right boldTd" ng-bind="InvBalances[0].Balance">224.00</td></tr>
</tbody>
</table>
</div>
<div class="tab-pane" id="tab29999999999999">
<table id="UBClaimTbl17" class="table table-bordered blue-fade-table">
<thead><tr>
<th class="text-center">Sl No</th>
<th class="text-center">Claim/Batch #</th>
<th class="text-center">Error</th>
<th>Actions</th>
<th>&nbsp;</th>
</tr></thead>
<tbody>
<!-- ngRepeat: chkError in ChkCurUB92Batch -->
</tbody>
</table>
</div>
</div>
</div><!-- /modal-body -->
<div class="grey-bg modal-footer">
<button id="UBClaimProgressNoteBtn" type="button" class="btn btn-lgrey btn-sm btn-xs pull-left"
ng-click="viewProgNote()">Prog. Notes</button>
<button id="UBClaimBtn17" type="button" class="btn btn-lgrey btn-sm btn-xs pull-right">Cancel</button>
<button id="UBClaimBtn18" type="button" class="btn btn-blue btn-sm btn-xs pull-right">OK</button>
</div>
</div></div></div>
<script>
// Prog. Notes opens the note in an IFRAME inside a modal, with Close on this
// parent page - which is how eCW actually serves it. The note is a whole
// printable document with its own <html>, so it cannot be inline.
//
// Reproduced faithfully because the split is the trap: reading this modal's
// innerText finds none of the note, and looking for Close inside the note
// finds nothing either. progress_note.find() walks the frames; close()
// clicks here. The ng-click typo "closeProgressNoteViwer" is eCW's own.
// Cancel and OK both hide the same backdrop eCW's real closeUBClaimScreen()
// / saveAllData(true) do — added so tests can prove the modal actually
// closes on both paths, not just that the button was clicked. Neither
// button did anything at all before this: the original fixture only ever
// needed to test reading, never closing.
document.getElementById('UBClaimBtn17').addEventListener('click', function () {
document.getElementById('UBClaimDiv9999999999999').style.display = 'none';
});
document.getElementById('UBClaimBtn18').addEventListener('click', function () {
document.getElementById('UBClaimDiv9999999999999').style.display = 'none';
});
// The real DOM (claim 9120000) carries ng-blur="updateCPTMod(...)" on every
// M1 input — Angular does not commit the modifier to CPTCodes[$index].mod1
// until that fires. Reproduced here as a data attribute, not real Angular,
// so a test can prove set_cpt_pos_modifier() actually blurs the field
// instead of just filling it and trusting the fill to be enough.
document.querySelectorAll('[id^="uBClaimMod1"]').forEach(function (el) {
el.addEventListener('blur', function () { el.dataset.blurred = '1'; });
});
document.getElementById('UBClaimProgressNoteBtn').addEventListener('click', function () {
var m = document.createElement('div');
m.className = 'modal in';
m.id = 'progressNoteViewerDiv9999999999999';
m.style.display = 'block';
m.innerHTML =
'<div class="modal-dialog"><div class="modal-content">'
+ '<div class="modal-header"><h4 class="modal-title">Progress Note</h4></div>'
+ '<div class="modal-body">'
+ '<iframe id="progressNoteFrame" src="progress_note.html" '
+ 'style="width:900px;height:400px;border:0"></iframe>'
+ '</div>'
+ '<div class="modal-footer">'
+ '<button type="button" class="btn btn-blue btn-sm btn-xs pull-right" '
+ 'ng-click="closeProgressNoteViwer()">Close</button>'
+ '</div>'
+ '</div></div>';
document.body.appendChild(m);
m.querySelector('[ng-click="closeProgressNoteViwer()"]')
.addEventListener('click', function () { m.style.display = 'none'; });
});
</script>
</body>
</html>