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:
commit
ba15a574ab
205 files changed
+56772
No files matched your search
Vendored
+506
@@ -0,0 +1,506 @@
|
||||
<!doctype html>
|
||||
<!--
|
||||
A cut-down UB Claim form carrying a VACCINE claim, for conditions
|
||||
/vaccine_admin_codes.py (Charge Condition Document row 18).
|
||||
|
||||
Reproduced by hand, never saved from the live page: a real claim is
|
||||
patient data and must never be committed. The per-open timestamp here is
|
||||
7777777777777 — deliberately different from ub_claim.html's
|
||||
9999999999999 and hcfa_claim.html's 8888888888888, so a selector that
|
||||
had one baked in fails against the others.
|
||||
|
||||
What this fixture exists to reproduce:
|
||||
* the UB form's CPT/HCPCS grid — `tr id="CPTROW_n"`, `uBClaim*<n>`
|
||||
field ids, and the code cell's `title` holding eCW's HOVER text
|
||||
("TETANUS DIPHTHERIA TOXOIDS AND ACELLULAR PERTUSSIS VACC", "PCV20"),
|
||||
which is what extract() saves as a row's `description` and what the
|
||||
condition recognises a vaccine by;
|
||||
* each row's "Assign To Patient" checkbox (`ng-click="updateBillToIns(n)"`)
|
||||
— only a CHECKED row is actually billed, so only checked vaccine and
|
||||
admin rows count;
|
||||
* the patient strip's DOB (`ng-bind="PatientInfo.dob"`) and age/sex
|
||||
text (" 50Y, M" / " 12M 12D, F");
|
||||
* the "Add" button + Fee Schedule picker, copied from hcfa_claim.html.
|
||||
NOTE: that picker flow is live-verified on the "Claim"/HCFA and Dental
|
||||
screens (claim 9109000), NOT yet on the UB form — it is here because
|
||||
the condition calls the same `claim_form.add_cpt_row()` either way.
|
||||
|
||||
The default grid is an adult (DOB 01/02/1976, 50 on the 07/07/2026 date
|
||||
of service), Medicaid, with three checked vaccines and NO admin code —
|
||||
exactly the shape the condition fires on: 90732, 90746 and 90734, all on
|
||||
the client's vaccine code list (2026-10-13; vaccines are recognised by
|
||||
that list only, so the earlier 90677 / 90750 / 90715 here were replaced).
|
||||
|
||||
Tests reshape it with the helpers in the script block at the bottom
|
||||
(seedCptRows, setPatient, setClaimDate, removeFromFeeSchedule, and the
|
||||
window.feeScheduleOk* / window.units* behaviour flags documented there)
|
||||
rather than keeping one fixture per scenario.
|
||||
-->
|
||||
<html>
|
||||
<body>
|
||||
|
||||
<div class="modal fade bluetheme ubClaimModalBackdrop in" id="UBClaimDiv7777777777777" style="display:block">
|
||||
<div class="modal-dialog visible" id="UBClaimDiv">
|
||||
<div id="UBClaimModalContent7777777777777" class="modal-content">
|
||||
|
||||
<div class="modal-header">
|
||||
<button id="UBClaimBtn3" type="button" class="close">×</button>
|
||||
<h4 class="modal-title" id="myModalLabel">UB Form Details</h4>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<!-- patient strip -->
|
||||
<div class="single-column middle">
|
||||
<span class="blue_txt" ng-bind="showEllipsisForField(PatientInfo.namewithsuffix,25)" title="Doe, Jordan">Doe, Jordan</span>
|
||||
<span class="blue_txt" id="patAgeSex" ng-bind="' ' + PatientInfo.Age + ', ' + PatientInfo.patSex"> 50Y, M</span>
|
||||
<span class="fnt11" id="patDob" ng-bind="PatientInfo.dob">01/02/1976</span>
|
||||
Acct No : <span ng-bind="showEllipsisForField(PatientInfo.ControlNo,10)">500001</span>
|
||||
</div>
|
||||
|
||||
<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="9113000">9113000</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>Claim Date</label></td>
|
||||
<td><input type="text" id="claimDate7777777777777" ng-model="ClaimData.ClaimDate" value="07/07/2026"></td>
|
||||
</tr>
|
||||
</tbody></table>
|
||||
</td>
|
||||
<td><label>Bill Type</label><input type="text" ng-model="Ub92Data.BillType" id="BillType" value="131"></td>
|
||||
</tr></tbody></table>
|
||||
|
||||
<!-- Insurance and Payments pane (shown, so extract() reads the payer) -->
|
||||
<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>
|
||||
</tr></thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="insurance in InvInsList">
|
||||
<td><span ng-bind="insurance.sequanceNo">P</span></td>
|
||||
<td><input type="checkbox" name="billto" checked></td>
|
||||
<td><span ng-bind="insurance.InsName">Medicaid</span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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>1</span></td><td></td>
|
||||
<td title="Z00.00"><input type="text" value="Z00.00"></td>
|
||||
<td title="Encounter for general adult medical examination">Encounter for general adult medical examination</td><td></td>
|
||||
</tr>
|
||||
<tr ng-repeat="icd in ICDCodes">
|
||||
<td class="text-center"><span>2</span></td><td></td>
|
||||
<td title="Z23"><input type="text" value="Z23"></td>
|
||||
<td title="Encounter for immunization">Encounter for immunization</td><td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<ul class="nav">
|
||||
<li id="liCptRev"><a class="cursor" data-toggle="tab" data-target="#cptRev7777777777777"
|
||||
ng-click="cptTabUpdate('cptRev')">CPT/Revenue Codes</a></li>
|
||||
<li class="active" id="liCPTHcpcs"><a class="cursor" data-toggle="tab" data-target="#cptHCPCS7777777777777"
|
||||
ng-click="cptTabUpdate('cptHcpcs')">CPT/HCPCS</a></li>
|
||||
</ul>
|
||||
|
||||
<!-- Not live-verified on the UB form — see the header comment. -->
|
||||
<button id="ubClaimAddCPTBtn7777777777777" type="button" class="btn btn-lgrey btn-xs"
|
||||
ng-click="addProcedureCode('');">Add</button>
|
||||
|
||||
<div class="tab-pane active" id="cptHCPCS7777777777777">
|
||||
<div class="allbrd cptTbl" id="CPTCodesDiv">
|
||||
<table class="table table-bordered blue-fade-table" id="claimCPTCodesTable7777777777777">
|
||||
<thead><tr>
|
||||
<th class="text-center">#</th><th> </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>1</span></td>
|
||||
<td><input type="checkbox" id="claimCPTBillToInsChk77777777777770" ng-click="updateBillToIns(0)" ng-checked="cpt.BillToIns=='1'" checked></td>
|
||||
<td title="PREVENTIVE VISIT EST AGE 40-64"><input id="uBClaimCPTCode0" type="text" value="99396" 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="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimEDOS0" value="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimMod10" value=""></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" ng-blur="padZero($index);editCPTRow('UNITS')"></td>
|
||||
<td title="250.00"><input type="text" id="uBClaimBillFee0" value="250.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="claimCPTBillToInsChk77777777777771" ng-click="updateBillToIns(1)" ng-checked="cpt.BillToIns=='1'" checked></td>
|
||||
<td title="PNEUMOCOCCAL VACCINE"><input id="uBClaimCPTCode1" type="text" value="90732" 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="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimEDOS1" value="07/07/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="2"></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="1" ng-blur="padZero($index);editCPTRow('UNITS')"></td>
|
||||
<td title="290.00"><input type="text" id="uBClaimBillFee1" value="290.00"></td>
|
||||
<td><input type="text" value="" readonly></td>
|
||||
</tr>
|
||||
<tr ng-repeat="cpt in CPTCodes" id="CPTROW_2">
|
||||
<td class="text-center"><span>3</span></td>
|
||||
<td><input type="checkbox" id="claimCPTBillToInsChk77777777777772" ng-click="updateBillToIns(2)" ng-checked="cpt.BillToIns=='1'" checked></td>
|
||||
<td title="HEPATITIS B VACCINE ADULT DOSAGE FOR INTRAMUSCULAR USE"><input id="uBClaimCPTCode2" type="text" value="90746" readonly></td>
|
||||
<td><input type="text" id="uBClaimPOS2" value="11"></td>
|
||||
<td><input type="text" id="uBClaimTOS2" value="1"></td>
|
||||
<td><input type="text" id="uBClaimSDOS2" value="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimEDOS2" value="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimMod12" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod22" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod32" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod42" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD12" value="2"></td>
|
||||
<td><input type="text" id="uBClaimICD22" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD32" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD42" value=""></td>
|
||||
<td><input type="text" id="uBClaimUnits2" value="1" ng-blur="padZero($index);editCPTRow('UNITS')"></td>
|
||||
<td title="240.00"><input type="text" id="uBClaimBillFee2" value="240.00"></td>
|
||||
<td><input type="text" value="" readonly></td>
|
||||
</tr>
|
||||
<tr ng-repeat="cpt in CPTCodes" id="CPTROW_3">
|
||||
<td class="text-center"><span>4</span></td>
|
||||
<td><input type="checkbox" id="claimCPTBillToInsChk77777777777773" ng-click="updateBillToIns(3)" ng-checked="cpt.BillToIns=='1'" checked></td>
|
||||
<td title="MENINGOCOCCAL VACCINE, IM"><input id="uBClaimCPTCode3" type="text" value="90734" readonly></td>
|
||||
<td><input type="text" id="uBClaimPOS3" value="11"></td>
|
||||
<td><input type="text" id="uBClaimTOS3" value="1"></td>
|
||||
<td><input type="text" id="uBClaimSDOS3" value="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimEDOS3" value="07/07/2026"></td>
|
||||
<td><input type="text" id="uBClaimMod13" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod23" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod33" value=""></td>
|
||||
<td><input type="text" id="uBClaimMod43" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD13" value="2"></td>
|
||||
<td><input type="text" id="uBClaimICD23" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD33" value=""></td>
|
||||
<td><input type="text" id="uBClaimICD43" value=""></td>
|
||||
<td><input type="text" id="uBClaimUnits3" value="1" ng-blur="padZero($index);editCPTRow('UNITS')"></td>
|
||||
<td title="60.00"><input type="text" id="uBClaimBillFee3" value="60.00"></td>
|
||||
<td><input type="text" value="" readonly></td>
|
||||
</tr>
|
||||
<!-- the blank entry row eCW leaves at the bottom: no CPTROW_ id -->
|
||||
<tr id="cptEntryRow">
|
||||
<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><!-- /modal-body -->
|
||||
|
||||
<!-- eCW's shared Fee Schedule picker — same stable ids as hcfa_claim.html. -->
|
||||
<div class="modal fade bluetheme" id="claimFeeScheduleModal" style="display:none">
|
||||
<div class="modal-dialog"><div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button id="claimFeeScheduleBtn1" type="button" class="close">×</button>
|
||||
<h4 class="modal-title">Fee Schedule</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<table class="table table-bordered claimFSCPTTbl" id="example1">
|
||||
<thead><tr><th>Id</th><th>CPT</th><th>Name</th><th>Fee</th></tr></thead>
|
||||
<tbody id="claimFSCPTTblBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<input id="claimFeeScheduleIpt6" type="text" placeholder="Search CPT">
|
||||
<button id="claimFeeScheduleBtn8" type="button">Cancel</button>
|
||||
<button id="claimFeeSchOkBtn" type="button">OK</button>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="grey-bg modal-footer">
|
||||
<button id="UBClaimProgressNoteBtn" type="button" ng-click="viewProgNote()">Prog. Notes</button>
|
||||
<button id="UBClaimBtn17" type="button">Cancel</button>
|
||||
<button id="UBClaimBtn18" type="button">OK</button>
|
||||
</div>
|
||||
|
||||
</div></div></div>
|
||||
|
||||
<script>
|
||||
document.getElementById('UBClaimBtn17').addEventListener('click', function () {
|
||||
document.getElementById('UBClaimDiv7777777777777').style.display = 'none';
|
||||
});
|
||||
document.getElementById('UBClaimBtn18').addEventListener('click', function () {
|
||||
document.getElementById('UBClaimDiv7777777777777').style.display = 'none';
|
||||
});
|
||||
|
||||
var CPT_TBODY = document.querySelector('#claimCPTCodesTable7777777777777 tbody');
|
||||
var ENTRY_ROW = document.getElementById('cptEntryRow');
|
||||
|
||||
function esc(s) {
|
||||
return String(s == null ? '' : s).replace(/&/g, '&').replace(/"/g, '"')
|
||||
.replace(/</g, '<');
|
||||
}
|
||||
|
||||
// One UB-style CPTROW_<n>, the same markup as the static rows above.
|
||||
// `r.noCheckbox` drops the "Assign To Patient" checkbox entirely — the
|
||||
// shape extract() must report as billed: null, not false. `r.noFee`
|
||||
// likewise drops the Billed Fee input — extract() must report
|
||||
// billed_fee: null (never read), not "" (read and blank, i.e. zero).
|
||||
function buildCptRow(n, r) {
|
||||
var tr = document.createElement('tr');
|
||||
tr.id = 'CPTROW_' + n;
|
||||
tr.setAttribute('ng-repeat', 'cpt in CPTCodes');
|
||||
var checked = r.checked === false ? '' : ' checked';
|
||||
var box = r.noCheckbox ? '' :
|
||||
'<input type="checkbox" id="claimCPTBillToInsChk7777777777777' + n + '"'
|
||||
+ ' ng-click="updateBillToIns(' + n + ')" ng-checked="cpt.BillToIns==\'1\'"' + checked + '>';
|
||||
var f = function (prefix, v) {
|
||||
return '<td><input type="text" id="' + prefix + n + '" value="' + esc(v) + '"></td>';
|
||||
};
|
||||
tr.innerHTML =
|
||||
'<td class="text-center"><span>' + (n + 1) + '</span></td>'
|
||||
+ '<td>' + box + '</td>'
|
||||
+ '<td title="' + esc(r.title) + '"><input id="uBClaimCPTCode' + n + '" type="text" value="'
|
||||
+ esc(r.code) + '" readonly></td>'
|
||||
+ f('uBClaimPOS', r.pos == null ? '11' : r.pos)
|
||||
+ f('uBClaimTOS', '1')
|
||||
+ f('uBClaimSDOS', r.sdos == null ? '07/07/2026' : r.sdos)
|
||||
+ f('uBClaimEDOS', r.sdos == null ? '07/07/2026' : r.sdos)
|
||||
+ f('uBClaimMod1', r.mod1 || '') + f('uBClaimMod2', '')
|
||||
+ f('uBClaimMod3', '') + f('uBClaimMod4', '')
|
||||
+ f('uBClaimICD1', r.icd1 == null ? '1' : r.icd1) + f('uBClaimICD2', r.icd2 || '')
|
||||
+ f('uBClaimICD3', r.icd3 || '') + f('uBClaimICD4', r.icd4 || '')
|
||||
+ '<td><input type="text" id="uBClaimUnits' + n + '" value="' + esc(r.units || '1') + '"'
|
||||
+ ' ng-blur="padZero($index);editCPTRow(\'UNITS\')"'
|
||||
+ (r.unitFee ? ' data-unit-fee="' + esc(r.unitFee) + '"' : '') + '></td>'
|
||||
+ (r.noFee ? '<td></td>'
|
||||
: '<td title="' + esc(r.fee || '0.00') + '"><input type="text" id="uBClaimBillFee' + n
|
||||
+ '" value="' + esc(r.fee || '0.00') + '"></td>')
|
||||
+ '<td><input type="text" value="" readonly></td>';
|
||||
|
||||
// Stand-in for eCW's own ng-blur="padZero($index);editCPTRow('UNITS')":
|
||||
// re-price the line from its per-unit fee when Units loses focus, so a
|
||||
// test reading the fee back proves the blur actually happened.
|
||||
// window.unitsRepriceDelayMs makes the re-price land LATER (an async
|
||||
// $http-style handler); window.unitsNoReprice makes it never land.
|
||||
var units = tr.querySelector('[id^="uBClaimUnits"]');
|
||||
units.addEventListener('blur', function () {
|
||||
units.dataset.blurred = '1';
|
||||
var per = parseFloat(units.dataset.unitFee || '');
|
||||
var qty = parseFloat(units.value || '0');
|
||||
if (window.unitsNoReprice || isNaN(per) || isNaN(qty)) return;
|
||||
var reprice = function () {
|
||||
tr.querySelector('[id^="uBClaimBillFee"]').value = (per * qty).toFixed(2);
|
||||
};
|
||||
if (window.unitsRepriceDelayMs) setTimeout(reprice, window.unitsRepriceDelayMs);
|
||||
else reprice();
|
||||
});
|
||||
return tr;
|
||||
}
|
||||
|
||||
function cptRowCount() {
|
||||
return CPT_TBODY.querySelectorAll('tr[id^="CPTROW_"]').length;
|
||||
}
|
||||
|
||||
// Replace every CPTROW_ with `rows` (objects of buildCptRow's shape).
|
||||
window.seedCptRows = function (rows) {
|
||||
CPT_TBODY.querySelectorAll('tr[id^="CPTROW_"]').forEach(function (tr) { tr.remove(); });
|
||||
rows.forEach(function (r, i) { CPT_TBODY.insertBefore(buildCptRow(i, r), ENTRY_ROW); });
|
||||
};
|
||||
|
||||
window.setPatient = function (dob, ageSex) {
|
||||
document.getElementById('patDob').textContent = dob;
|
||||
document.getElementById('patAgeSex').textContent = ageSex;
|
||||
};
|
||||
|
||||
window.setClaimDate = function (d) {
|
||||
document.getElementById('claimDate7777777777777').value = d;
|
||||
};
|
||||
|
||||
// The Fee Schedule picker, copied from hcfa_claim.html: a seed catalog,
|
||||
// filtered "Starts With" the way the real picker defaults to. The decoy
|
||||
// 904711 starts with 90471, so a search for 90471 lists both — proving
|
||||
// add_cpt_row() picks the EXACT match, not the first row.
|
||||
var feeScheduleCatalog = [
|
||||
{id: '610001', code: '90460', name: 'IMMUNIZATION ADMIN THROUGH 18 YRS 1ST COMPONENT', fee: '25.00'},
|
||||
{id: '610002', code: '90461', name: 'IMMUNIZATION ADMIN THROUGH 18 YRS EACH ADD COMPONENT', fee: '15.00'},
|
||||
{id: '610003', code: '90471', name: 'IMMUNIZATION ADMIN SINGLE OR COMBINATION', fee: '30.00'},
|
||||
{id: '610004', code: '90472', name: 'IMMUNIZATION ADMIN, EACH ADD', fee: '20.00'},
|
||||
{id: '610005', code: '96372', name: 'THER/PROPH/DIAG INJ SC/IM', fee: '25.00'},
|
||||
// PPS Codes (#25). G0467H is left out on purpose: a PPS Code the
|
||||
// picker cannot find.
|
||||
{id: '610010', code: 'G0466', name: 'FQHC VISIT, NEW PATIENT', fee: '180.00'},
|
||||
{id: '610011', code: 'G0467', name: 'FQHC VISIT, ESTABLISHED PATIENT', fee: '150.00'},
|
||||
{id: '610012', code: 'G0467NH', name: 'FQHC VISIT, ESTABLISHED, NURSING HOME', fee: '150.00'},
|
||||
{id: '610013', code: 'G0468', name: 'FQHC VISIT, IPPE OR AWV', fee: '200.00'},
|
||||
{id: '610099', code: '904711', name: 'Unrelated decoy code', fee: '99.00'},
|
||||
];
|
||||
var feeScheduleSelected = null;
|
||||
|
||||
// Tests take a code out of the catalog to make its add fail the way a
|
||||
// missing fee-schedule entry would on the live picker.
|
||||
// Tests re-price a code in the catalog — e.g. to 0.00, a Fee Schedule
|
||||
// entry with no fee, so an added admin line comes back unpriced.
|
||||
window.setFeeScheduleFee = function (code, fee) {
|
||||
feeScheduleCatalog.forEach(function (r) { if (r.code === code) r.fee = fee; });
|
||||
};
|
||||
|
||||
window.removeFromFeeSchedule = function (code) {
|
||||
feeScheduleCatalog = feeScheduleCatalog.filter(function (r) { return r.code !== code; });
|
||||
};
|
||||
|
||||
// Tests set this to make OK close the picker WITHOUT adding a row, the
|
||||
// shape add_cpt_row() cannot tell from success on its own when the same
|
||||
// code already sits on the claim (e.g. an unchecked 90460).
|
||||
window.feeScheduleOkAddsNothing = false;
|
||||
|
||||
// More ways the live picker's OK has not been verified NOT to behave,
|
||||
// each one a shape the condition must report rather than hide:
|
||||
// feeScheduleOkKeepsOpen — OK does nothing, the picker stays up
|
||||
// (eCW's own validation holding it open);
|
||||
// feeScheduleOkRechecksExisting — OK re-checks and re-prices the claim's
|
||||
// existing UNCHECKED line for the code
|
||||
// instead of appending a new one;
|
||||
// feeScheduleInsertBeforeCode — the new line goes in ABOVE the first
|
||||
// existing line with this code, not at
|
||||
// the bottom (a sorted grid);
|
||||
// feeScheduleOkAlsoAdds — OK also appends a line for this code
|
||||
// (a second open keeping the first pick).
|
||||
// feeScheduleNewLineUnits — the new line comes back with this Units
|
||||
// (e.g. '0') instead of 1, priced to match,
|
||||
// so the bot's Units write + re-price path
|
||||
// runs (it writes Units only when eCW did
|
||||
// not already give the new line 1).
|
||||
window.feeScheduleOkKeepsOpen = false;
|
||||
window.feeScheduleOkRechecksExisting = false;
|
||||
window.feeScheduleNewLineUnits = null;
|
||||
window.feeScheduleInsertBeforeCode = null;
|
||||
window.feeScheduleOkAlsoAdds = null;
|
||||
|
||||
function renderFeeScheduleResults(filterText) {
|
||||
var tbody = document.getElementById('claimFSCPTTblBody');
|
||||
tbody.innerHTML = '';
|
||||
var q = (filterText || '').toUpperCase();
|
||||
feeScheduleCatalog
|
||||
.filter(function (row) { return row.code.toUpperCase().indexOf(q) === 0; })
|
||||
.forEach(function (row) {
|
||||
var tr = document.createElement('tr');
|
||||
tr.innerHTML =
|
||||
'<td>' + row.id + '</td>'
|
||||
+ '<td><span>' + row.code + '</span></td>'
|
||||
+ '<td>' + row.name + '</td>'
|
||||
+ '<td>' + row.fee + '</td>';
|
||||
tr.addEventListener('click', function () { feeScheduleSelected = row; });
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
}
|
||||
|
||||
document.getElementById('ubClaimAddCPTBtn7777777777777').addEventListener('click', function () {
|
||||
feeScheduleSelected = null;
|
||||
document.getElementById('claimFeeScheduleIpt6').value = '';
|
||||
renderFeeScheduleResults('');
|
||||
document.getElementById('claimFeeScheduleModal').style.display = 'block';
|
||||
});
|
||||
|
||||
document.getElementById('claimFeeScheduleIpt6').addEventListener('input', function () {
|
||||
renderFeeScheduleResults(this.value);
|
||||
});
|
||||
|
||||
document.getElementById('claimFeeScheduleBtn8').addEventListener('click', function () {
|
||||
document.getElementById('claimFeeScheduleModal').style.display = 'none';
|
||||
});
|
||||
|
||||
// OK appends a row the way eCW's own addClaimFSCPTCode('save') does —
|
||||
// including filling POS, dates and the ICD pointers ITSELF (faked here by
|
||||
// copying the claim's first line). The bot never hand-fills those; a test
|
||||
// proves the added row keeps exactly what this "eCW" put there.
|
||||
function rowsWithCode(code) {
|
||||
return Array.prototype.filter.call(
|
||||
CPT_TBODY.querySelectorAll('tr[id^="CPTROW_"]'),
|
||||
function (tr) { return tr.querySelector('[id^="uBClaimCPTCode"]').value === code; });
|
||||
}
|
||||
|
||||
function appendFromCatalog(row) {
|
||||
var first = CPT_TBODY.querySelector('tr[id^="CPTROW_"]');
|
||||
var copy = function (prefix) {
|
||||
var e = first ? first.querySelector('[id^="' + prefix + '"]') : null;
|
||||
return e ? e.value : '';
|
||||
};
|
||||
var newUnits = window.feeScheduleNewLineUnits || '1';
|
||||
var anchor = ENTRY_ROW;
|
||||
if (window.feeScheduleInsertBeforeCode) {
|
||||
var hits = rowsWithCode(window.feeScheduleInsertBeforeCode);
|
||||
if (hits.length) anchor = hits[0];
|
||||
}
|
||||
CPT_TBODY.insertBefore(buildCptRow(cptRowCount(), {
|
||||
code: row.code, title: row.name, checked: true,
|
||||
pos: copy('uBClaimPOS'), sdos: copy('uBClaimSDOS'),
|
||||
icd1: copy('uBClaimICD1'), icd2: copy('uBClaimICD2'),
|
||||
icd3: copy('uBClaimICD3'), icd4: copy('uBClaimICD4'),
|
||||
units: newUnits, unitFee: row.fee,
|
||||
fee: newUnits === '1' ? row.fee
|
||||
: (parseFloat(row.fee) * parseFloat(newUnits || '0')).toFixed(2),
|
||||
}), anchor);
|
||||
}
|
||||
|
||||
document.getElementById('claimFeeSchOkBtn').addEventListener('click', function () {
|
||||
if (window.feeScheduleOkKeepsOpen) return;
|
||||
document.getElementById('claimFeeScheduleModal').style.display = 'none';
|
||||
if (!feeScheduleSelected || window.feeScheduleOkAddsNothing) return;
|
||||
var row = feeScheduleSelected;
|
||||
if (window.feeScheduleOkRechecksExisting) {
|
||||
var old = rowsWithCode(row.code).filter(function (tr) {
|
||||
var box = tr.querySelector('[ng-click*="updateBillToIns("]');
|
||||
return box && !box.checked;
|
||||
})[0];
|
||||
if (old) {
|
||||
old.querySelector('[ng-click*="updateBillToIns("]').checked = true;
|
||||
old.querySelector('[id^="uBClaimBillFee"]').value = row.fee;
|
||||
return;
|
||||
}
|
||||
}
|
||||
appendFromCatalog(row);
|
||||
if (window.feeScheduleOkAlsoAdds) {
|
||||
var extra = feeScheduleCatalog.filter(function (r) {
|
||||
return r.code === window.feeScheduleOkAlsoAdds;
|
||||
})[0];
|
||||
// only on a LATER pick of a different code — the stale first pick
|
||||
if (extra && extra.code !== row.code) appendFromCatalog(extra);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user