chore: complete integration of flex-3.20 (alpine 3.20) into ci (#7538)
[openemr.git] / interface / billing / billing_report.php
blobd4a3e5fad46cab0a06ebfdf5c18236c20eef81be
1 <?php
3 /**
4 * Billing Report Program
6 * @package OpenEMR
7 * @link https://www.open-emr.org
8 * @author Terry Hill <terry@lilysystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Jerry Padgett <sjpadgett@gmail.com>
11 * @author Sherwin Gaddis <sherwingaddis@gmail.com>
12 * @author Stephen Waite <stephen.waite@cmsvt.com>
13 * @copyright Copyright (c) 2016 Terry Hill <terry@lillysystems.com>
14 * @copyright Copyright (c) 2017-2020 Brady Miller <brady.g.miller@gmail.com>
15 * @copyright Copyright (c) 2018-2020 Jerry Padgett <sjpadgett@gmail.com>
16 * @copyright Copyright (c) 2019-2020 Sherwin Gaddis <sherwingaddis@gmail.com>
17 * @copyright Copyright (c) 2021 Stephen Waite <stephen.waite@cmsvt.com>
18 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
21 require_once "../globals.php";
22 require_once "../../custom/code_types.inc.php";
23 require_once "$srcdir/patient.inc.php";
24 require_once "$srcdir/options.inc.php";
26 use OpenEMR\Billing\BillingReport;
27 use OpenEMR\Billing\BillingUtilities;
28 use OpenEMR\Common\Acl\AclMain;
29 use OpenEMR\Common\Csrf\CsrfUtils;
30 use OpenEMR\Common\Twig\TwigContainer;
31 use OpenEMR\Core\Header;
32 use OpenEMR\OeUI\OemrUI;
34 //ensure user has proper access
35 if (!AclMain::aclCheckCore('acct', 'eob', '', 'write') && !AclMain::aclCheckCore('acct', 'bill', '', 'write')) {
36 echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Billing Manager")]);
37 exit;
40 $EXPORT_INC = "$webserver_root/custom/BillingExport.php";
41 // echo $GLOBALS['daysheet_provider_totals'];
43 $daysheet = false;
44 $daysheet_total = false;
45 $provider_run = false;
47 if ($GLOBALS['use_custom_daysheet'] != 0) {
48 $daysheet = true;
49 if ($GLOBALS['daysheet_provider_totals'] == 1) {
50 $daysheet_total = true;
51 $provider_run = false;
53 if ($GLOBALS['daysheet_provider_totals'] == 0) {
54 $daysheet_total = false;
55 $provider_run = true;
59 $alertmsg = '';
61 if (isset($_POST['mode'])) {
62 if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) {
63 CsrfUtils::csrfNotVerified();
66 if ($_POST['mode'] == 'export') {
67 $sql = BillingReport::returnOFXSql();
68 $db = get_db();
69 $results = $db->Execute($sql);
70 $billings = array();
71 if ($results->RecordCount() == 0) {
72 echo "<fieldset id='error_info' style='border:1px solid var(--danger) !important; background-color: var(--danger) !important; color: var(--white) !important; font-weight: bold; font-family: sans-serif; border-radius: 5px; padding: 20px 5px !important;'>";
73 echo xlt("No Bills Found to Include in OFX Export") . "<br />";
74 echo "</fieldset>";
75 } else {
76 while (!$results->EOF) {
77 $billings[] = $results->fields;
78 $results->MoveNext();
80 $ofx = new OFX($billings);
81 header("Pragma: public");
82 header("Expires: 0");
83 header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
84 header("Content-Disposition: attachment; filename=openemr_ofx.ofx");
85 header("Content-Type: text/xml");
86 echo $ofx->get_OFX();
87 exit();
92 // global variables:
93 $from_date = isset($_POST['from_date']) ? $_POST['from_date'] : date('Y-m-d');
94 $to_date = isset($_POST['to_date']) ? $_POST['to_date'] : '';
95 $code_type = isset($_POST['code_type']) ? $_POST['code_type'] : 'all';
96 $unbilled = isset($_POST['unbilled']) ? $_POST['unbilled'] : 'on';
97 $my_authorized = isset($_POST["authorized"]) ? $_POST["authorized"] : '';
99 // This tells us if only encounters that appear to be missing a "25" modifier
100 // are to be reported.
101 $missing_mods_only = (isset($_POST['missing_mods_only']) && !empty($_POST['missing_mods_only']));
103 $left_margin = isset($_POST["left_margin"]) ? $_POST["left_margin"] : $GLOBALS['cms_left_margin_default'];
104 $top_margin = isset($_POST["top_margin"]) ? $_POST["top_margin"] : $GLOBALS['cms_top_margin_default'];
105 if ($left_margin + 0 === 20 && $top_margin + 0 === 24) {
106 // defaults are flipped. No easy way to reset existing. Global defaults fixed.
107 $left_margin = '24';
108 $top_margin = '20';
110 if ($ub04_support) {
111 $left_ubmargin = isset($_POST["left_ubmargin"]) ? $_POST["left_ubmargin"] : $GLOBALS['left_ubmargin_default'];
112 $top_ubmargin = isset($_POST["top_ubmargin"]) ? $_POST["top_ubmargin"] : $GLOBALS['top_ubmargin_default'];
114 $ofrom_date = $from_date;
115 $oto_date = $to_date;
116 $ocode_type = $code_type;
117 $ounbilled = $unbilled;
118 $oauthorized = $my_authorized;
119 $x = new X12Partner();
120 $partners = $x->_utility_array($x->x12_partner_factory());
122 <!DOCTYPE html>
123 <html>
125 <head>
127 <?php Header::setupHeader(['datetime-picker', 'common']); ?>
128 <style>
129 .modal {
130 overflow-y: auto;
133 .modal-open {
134 overflow: auto;
137 .modal-open[style] {
138 padding-right: 0px !important;
140 </style>
141 <script>
142 var partners = <?php echo json_encode($partners); ?>;
144 // next set of 4 functions are for a wait confirm action then submit.
145 // I wrote this a little more involved than it needs to be
146 // to example the pattern. Ideal submit part would be via a fetch or ajax
147 // then could do refresh or after submit actions.
149 function doSubmit(action) {
150 top.restoreSession();
151 return new Promise(function(resolve, reject) {
152 var showLog = function() {
153 $("#view-log-link").click();
155 // Pre-open a dialog and target dialogs iframe for content from billing_process
156 // text or PDF.
157 dlgopen('', 'ValidateShowBatch', 875, 500, false, '', {
158 buttons: [{
159 text: '<?php echo xlt("Logs"); ?>',
160 close: false,
161 style: 'default btn-sm',
162 click: showLog
165 text: '<i class="fa fa-thumbs-up"></i>&nbsp;<?php echo xlt("Close"); ?>',
166 close: true,
167 style: 'default btn-sm'
170 //onClosed: 'SubmitTheScreen', // future and/or example of onClosed.
171 sizeHeight: 'full'
173 // target content from submit to dialogs iframe
174 document.update_form.target = 'ValidateShowBatch';
176 // Now submit form and populate dialog.
177 top.restoreSession(); // Not sure if this is needed but something in billing is causing 'SITE ID' error
178 document.update_form.submit();
179 // go fulfill the promise.
180 resolve(true);
184 function doConfirm(Message) {
185 placeModal(Message);
186 return new Promise(function(resolve, reject) {
187 $('#confirmDialog').modal('show');
188 $('#confirmDialog .btn-continue').click(function() {
189 $(this).off();
190 resolve("btn-continue");
192 $('#confirmDialog .btn-clear').click(function() {
193 $(this).off();
194 resolve("btn-clear");
196 $('#confirmDialog .btn-validate').click(function() {
197 $(this).off();
198 resolve("btn-validate");
200 $('#confirmDialog .btn-danger').click(function() {
201 $(this).off();
202 reject("btn-cancel");
207 async function confirmActions(e, mType) {
208 e.preventDefault();
209 let Message = "";
210 let ClaimCount = 0;
211 for (var CheckBoxBillingIndex = 0;; CheckBoxBillingIndex++) {
212 CheckBoxBillingObject = document.getElementById('CheckBoxBilling' +
213 CheckBoxBillingIndex);
214 if (!CheckBoxBillingObject) break;
215 if (CheckBoxBillingObject.checked) {
216 ++ClaimCount;
219 let addOn = <?php echo xlj('click View Log and review for errors.'); ?>;
220 if (mType == '1') {
221 Message = <?php echo xlj('After saving your batch'); ?> + ", " + addOn;
222 } else if (mType == '2') {
223 Message = <?php echo xlj('After saving the PDF'); ?> + ", " + addOn;
224 } else if (mType == '3') {
225 Message = <?php echo xlj('After saving the TEXT file'); ?> + "(s), " + addOn;
227 Message += "<br/><br/>" + <?php echo xlj('Validate and Clear validates then sets claims status only, to billed, leaving billing process unaltered and claim submission resets to unsubmitted.'); ?>;
228 Message += "<br/><br/>" + <?php echo xlj('Validate Only does a claim validation dry run for errors leaving claim status unaltered.'); ?>;
229 Message += "<br/><br/>" + <?php echo xlj('Continue completes selected billing option normally.'); ?>;
230 Message += "<br/><br/>" + <?php echo xlj('Total of'); ?> + ' ' + ClaimCount + ' ' + <?php echo xlj('claims selected.'); ?> + "\n";
231 let sName = e.currentTarget.name;
232 // wait for confirm result
233 await doConfirm(Message).then(action => {
234 console.log(sName, action);
235 // set post button for form submit
236 $('<input>').attr({
237 type: 'hidden',
238 id: "submitTask",
239 name: sName,
240 value: 'true'
241 }).prependTo(document.update_form);
242 // passing confirm clicked button
243 $('<input>').attr({
244 type: 'hidden',
245 id: "confirmTask",
246 name: action,
247 value: 1
248 }).prependTo(document.update_form);
249 return action;
250 }).then(action => {
251 // submit update_form then cleanup
252 doSubmit(action).then(function() {
253 $("#submitTask").remove();
254 $("#confirmTask").remove();
256 }).catch(function(why) {
257 // cancel clicked in confirm. do nothing...
258 console.warn("Task was canceled", why);
261 return false;
264 function placeModal(Message) {
265 let mConfirm = <?php echo xlj('Please Confirm') ?>;
266 let mClear = <?php echo xlj('Validate and Clear') ?>;
267 let mVal = <?php echo xlj('Validate Only') ?>;
268 let mCont = <?php echo xlj('Continue') ?>;
269 let mCancel = <?php echo xlj('Cancel') ?>;
270 let dModal = "<div class='modal fade' id='confirmDialog' aria-hidden='true'><div class='modal-dialog'><div class='modal-content'>" +
271 "<div class='modal-header'><h4 class='modal-title'>" + mConfirm + "</h4></div><div class='modal-body'>" +
272 "<label>" + Message + "</label></div><div class='modal-footer'>" +
273 "<button type='button' class='btn btn-primary btn-clear' data-dismiss='modal'>" + mClear + "</button>" +
274 "<button type='button' class='btn btn-primary btn-validate' data-dismiss='modal'>" + mVal + "</button>" +
275 "<button type='button' class='btn btn-primary btn-continue' data-dismiss='modal'>" + mCont + "</button>" +
276 "<button type='button' class='btn btn-secondary btn-cancel' data-dismiss='modal'>" + mCancel + "</button>" +
277 "</div></div></div></div>";
279 $("body").append(dModal);
281 $('#confirmDialog').on('hidden.bs.modal', function(e) {
282 // remove modal
283 $(this).remove();
284 console.log("Confirm Modal Removed");
285 // remove this event for next time.
286 $(this).off(e);
290 function onNewPayer(oEvent) {
291 let p = oEvent.target.options[event.target.selectedIndex].dataset.partner;
292 let partnerSelect = oEvent.target.options[event.target.selectedIndex].dataset.partner;
293 partnerSelect = partnerSelect ? partnerSelect : -1;
294 document.getElementById("partners").value = partnerSelect;
297 function select_all() {
298 for ($i = 0; $i < document.update_form.length; $i++) {
299 $name = document.update_form[$i].name;
300 if ($name.substring(0, 7) == "claims[" && $name.substring($name.length -
301 6) == "[bill]") {
302 document.update_form[$i].checked = true;
305 set_button_states();
308 function set_button_states() {
309 var f = document.update_form;
310 var count0 = 0; // selected and not billed or queued
311 var count1 = 0; // selected and queued
312 var count2 = 0; // selected and billed
313 for ($i = 0; $i < f.length; ++$i) {
314 $name = f[$i].name;
315 if ($name.substring(0, 7) == "claims[" && $name.substring($name.length -
316 6) == "[bill]" && f[$i].checked == true) {
317 if (f[$i].value == '0') ++count0;
318 else if (f[$i].value == '1' || f[$i].value == '5') ++count1;
319 else ++count2;
322 var can_generate = (count0 > 0 || count1 > 0 || count2 > 0);
323 var can_mark = (count1 > 0 || count0 > 0 || count2 > 0);
324 var can_bill = (count0 == 0 && count1 == 0 && count2 > 0);
325 <?php if (file_exists($EXPORT_INC)) { ?>
326 f.bn_external.disabled = !can_generate;
327 <?php } else { ?>
328 f.bn_x12_support.disabled = !can_generate;
329 <?php if ($GLOBALS['support_encounter_claims']) { ?>
330 f.bn_x12_encounter.disabled = !can_generate;
331 <?php } ?>
332 f.bn_process_hcfa_support.disabled = !can_generate;
333 <?php if ($GLOBALS['preprinted_cms_1500']) { ?>
334 f.bn_process_hcfa_form.disabled = !can_generate;
335 <?php } ?>
336 <?php if ($GLOBALS['ub04_support']) { ?>
337 f.bn_process_ub04_support.disabled = !can_generate;
338 <?php } ?>
339 f.bn_hcfa_txt_file.disabled = !can_generate;
340 f.bn_reopen.disabled = !can_bill;
341 <?php } ?>
342 f.bn_mark.disabled = !can_mark;
345 // Process a click to go to an encounter.
346 function toencounter(pid, pubpid, pname, enc, datestr, dobstr) {
347 top.restoreSession();
348 encurl = 'patient_file/encounter/encounter_top.php?set_encounter=' + encodeURIComponent(enc) +
349 '&pid=' + encodeURIComponent(pid);
350 paturl = 'patient_file/summary/demographics_full.php?pid=' + encodeURIComponent(pid);
351 parent.left_nav.setPatient(pname, pid, pubpid, '', dobstr);
352 parent.left_nav.setEncounter(datestr, enc, 'enc');
353 parent.left_nav.loadFrame('enc2', 'enc', encurl);
354 parent.left_nav.loadFrame('dem1', 'pat', paturl);
357 // Process a click to go to an patient.
358 function topatient(pid, pubpid, pname, enc, datestr, dobstr) {
359 top.restoreSession();
360 paturl = 'patient_file/summary/insurance_edit.php?pid=' + encodeURIComponent(pid);
361 parent.left_nav.setPatient(pname, pid, pubpid, '', dobstr);
362 parent.left_nav.loadFrame('ens1', 'enc',
363 'patient_file/history/encounters.php?pid=' + encodeURIComponent(pid));
364 parent.left_nav.loadFrame('dem1', 'pat', paturl);
367 function popMBO(pid, enc, mboid) {
368 if (!window.focus) return true;
369 if (!ProcessBeforeSubmitting()) return false;
370 top.restoreSession();
371 let qstring = "&pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc) + "&id=" + encodeURIComponent(mboid);
372 let href = "<?php echo $GLOBALS['web_root']?>/interface/patient_file/encounter/view_form.php?formname=misc_billing_options&isBilling=1" + qstring;
373 dlgopen(href, 'mbopop', 'modal-lg', 750, false, '', {
374 sizeHeight: 'full' // override min height auto size.
376 return true;
379 function popUB04(pid, enc) {
380 if (!window.focus) return true;
381 if (!ProcessBeforeSubmitting()) return false;
382 top.restoreSession();
383 let href = "<?php echo $GLOBALS['web_root']?>/interface/billing/ub04_form.php?pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc);
384 dlgopen(href, 'ub04pop', 1175, 750, false, '', {
385 sizeHeight: 'full' // override min height auto size.
387 return true;
390 var EncounterDateArray = new Array;
391 var CalendarCategoryArray = new Array;
392 var EncounterIdArray = new Array;
393 var EncounterNoteArray = new Array;
395 function SubmitTheScreen() { //Action on Update List link
396 if (!ProcessBeforeSubmitting()) return false;
397 if (!criteriaSelectHasValue('final_this_page_criteria')) return false;
398 $("#update-tooltip").replaceWith("<i class='fa fa-sync fa-spin fa-1x' style=\"color:red\"></i>");
399 top.restoreSession();
400 document.the_form.mode.value = 'change';
401 document.the_form.target = '_self';
402 document.the_form.action = 'billing_report.php';
403 document.the_form.submit();
404 return true;
407 function SubmitTheScreenPrint() { //Action on View Printable Report link
408 if (!ProcessBeforeSubmitting()) return false;
409 top.restoreSession();
410 document.the_form.target = 'new';
411 document.the_form.action = 'print_billing_report.php';
412 document.the_form.submit();
413 return true;
416 function SubmitTheEndDayPrint() { //Action on View End of Day Report link
417 if (!ProcessBeforeSubmitting()) return false;
418 top.restoreSession();
419 document.the_form.target = 'new';
420 <?php if ($GLOBALS['use_custom_daysheet'] == 1) { ?>
421 document.the_form.action = 'print_daysheet_report_num1.php';
422 <?php } ?>
423 <?php if ($GLOBALS['use_custom_daysheet'] == 2) { ?>
424 document.the_form.action = 'print_daysheet_report_num2.php';
425 <?php } ?>
426 <?php if ($GLOBALS['use_custom_daysheet'] == 3) { ?>
427 document.the_form.action = 'print_daysheet_report_num3.php';
428 <?php } ?>
429 document.the_form.submit();
430 return true;
433 function SubmitTheScreenExportOFX() { //Action on Export OFX link
434 if (!ProcessBeforeSubmitting()) return false;
435 top.restoreSession();
436 document.the_form.mode.value = 'export';
437 document.the_form.target = '_self';
438 document.the_form.action = 'billing_report.php';
439 document.the_form.submit();
440 return true;
443 function TestExpandCollapse() { //Checks whether the Expand All, Collapse All labels need to be placed.If any result set is there these will be placed.
444 var set = -1;
445 for (i = 1; i <= document.getElementById("divnos").value; i++) {
446 var ele = document.getElementById("divid_" + i);
447 if (ele) {
448 set = 1;
449 break;
452 if (set == -1) {
453 if (document.getElementById("expandAllCollapseAll")) {
454 document.getElementById("expandAllCollapseAll").innerHTML = '';
459 function expandcollapse(atr) {
460 if (atr == "expand") { //Called in the Expand All, Collapse All links(All items will be expanded or collapsed)
461 for (i = 1; i <= document.getElementById("divnos").value; i++) {
462 var mydivid = "divid_" + i;
463 var myspanid = "spanid_" + i;
464 var ele = document.getElementById(mydivid);
465 var text = document.getElementById(myspanid);
466 if (ele) {
467 ele.style.display = "inline";
468 text.innerHTML =
469 jsText(<?php echo xlj('Collapse'); ?>);
472 } else {
473 for (i = 1; i <= document.getElementById("divnos").value; i++) {
474 var mydivid = "divid_" + i;
475 var myspanid = "spanid_" + i;
476 var ele = document.getElementById(mydivid);
477 var text = document.getElementById(myspanid);
478 if (ele) {
479 ele.style.display = "none";
480 text.innerHTML =
481 jsText(<?php echo xlj('Expand'); ?>);
487 function divtoggle(spanid, divid) { //Called in the Expand, Collapse links(This is for a single item)
488 var ele = document.getElementById(divid);
489 if (ele) {
490 var text = document.getElementById(spanid);
491 if (ele.style.display == "inline") {
492 ele.style.display = "none";
493 text.innerHTML =
494 jsText(<?php echo xlj('Expand'); ?>);
495 } else {
496 ele.style.display = "inline";
497 text.innerHTML =
498 jsText(<?php echo xlj('Collapse'); ?>);
503 function criteriaSelectHasValue(select) {
504 obj = document.getElementById(select);
505 if (obj.options.length == 0) {
506 var checkstr = confirm(<?php echo xlj("Do you really want to submit with no criteria selected?"); ?>);
507 return checkstr;
509 return true;
511 </script>
512 <?php require_once "$srcdir/../interface/reports/report.script.php"; ?>
513 <!-- Criteria Section common javascript page-->
514 <!-- =============Included for Insurance ajax criteria==== -->
515 <?php require_once "{$GLOBALS['srcdir']}/ajax/payment_ajax_jav.inc.php"; ?>
516 <style>
517 #ajax_div_insurance {
518 position: absolute;
519 z-index: 10;
520 background-color: #FBFDD0;
521 border: 1px solid #ccc;
522 padding: 10px;
525 button[type="submit"].subbtn-warning {
526 background: #ec971f !important;
527 color: black !important;
530 button[type="submit"].subbtn-warning:hover {
531 background: #da8104 !important;
532 color: var(--white) !important;
535 @media only screen and (max-width: 1024px) {
536 [class*="col-"] {
537 width: 100%;
538 text-align: left !Important;
542 .table {
543 margin: auto;
546 @media (min-width: 992px) {
547 .modal-lg {
548 width: 1000px !Important;
552 .table th,
553 .table td {
554 border-top: none !important;
558 a:visited,
559 a:hover {
560 text-decoration: none;
561 color: var(--black);
563 </style>
564 <script>
565 document.onclick = TakeActionOnHide;
566 </script>
567 <!-- =============Included for Insurance ajax criteria==== -->
568 <title><?php echo xlt('Billing Manager'); ?></title>
569 <?php
570 $arrOeUiSettings = array(
571 'heading_title' => xl('Billing Manager'),
572 'include_patient_name' => false,// use only in appropriate pages
573 'expandable' => false,
574 'expandable_files' => array('billing_report_xpd'),//all file names need suffix _xpd
575 'action' => "conceal",//conceal, reveal, search, reset, link or back
576 'action_title' => "",
577 'action_href' => "",//only for actions - reset, link or back
578 'show_help_icon' => false,
579 'help_file_name' => ""
581 $oemr_ui = new OemrUI($arrOeUiSettings);
583 </head>
585 <body onload="TestExpandCollapse()">
586 <div id="container_div" class="<?php echo attr($oemr_ui->oeContainer()); ?> mt-3">
587 <div class="row">
588 <div class="col-sm-12">
589 <?php echo $oemr_ui->pageHeading() . "\r\n"; ?>
590 </div>
591 </div>
592 <div class="hideaway">
593 <div>
594 <form class="form" name='the_form' method='post' action='billing_report.php' onsubmit='return top.restoreSession()'>
595 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
596 <input type='hidden' name='mode' value='change' />
597 <!-- Criteria section Starts -->
598 <?php
599 // TPS = This Page Search
600 // The following are the search criteria per page.All the following variable which ends with 'Master' need to be filled properly.
601 // Each item is seperated by a comma(,).
602 // $TPSCriteriaDisplayMaster ==>It is the display on screen for the set of criteria.
603 // $TPSCriteriaKeyMaster ==>Corresponding database fields in the same order.
604 // $TPSCriteriaDataTypeMaster ==>Corresponding data type in the same order.
605 $TPSCriteriaDisplayRadioMaster = array();
606 $TPSCriteriaRadioKeyMaster = array();
607 $TPSCriteriaQueryDropDownMaster = array();
608 $TPSCriteriaQueryDropDownMasterDefault = array();
609 $TPSCriteriaQueryDropDownMasterDefaultKey = array();
610 $TPSCriteriaIncludeMaster = array();
612 if ($daysheet) {
613 $TPSCriteriaDisplayMaster = array(
614 xl("Date of Service"),
615 xl("Date of Entry"),
616 xl("Date of Billing"),
617 xl("Claim Type"),
618 xl("Patient Name"),
619 xl("Patient Id"),
620 xl("Insurance Company"),
621 xl("Encounter"),
622 xl("Whether Insured"),
623 xl("Charge Coded"),
624 xl("Billing Status"),
625 xl("Authorization Status"),
626 xl("Last Level Billed"),
627 xl("X12 Partner"),
628 xl("User")
630 $TPSCriteriaKeyMaster = "form_encounter.date,billing.date,claims.process_time,claims.target,patient_data.fname," . "form_encounter.pid,claims.payer_id,form_encounter.encounter,insurance_data.provider,billing.id,billing.billed," . "billing.authorized,form_encounter.last_level_billed,billing.x12_partner_id,billing.user";
631 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down,text";
632 } else {
633 $TPSCriteriaDisplayMaster = array(
634 xl("Date of Service"),
635 xl("Date of Entry"),
636 xl("Date of Billing"),
637 xl("Claim Type"),
638 xl("Patient Name"),
639 xl("Patient Id"),
640 xl("Insurance Company"),
641 xl("Encounter"),
642 xl("Whether Insured"),
643 xl("Charge Coded"),
644 xl("Billing Status"),
645 xl("Authorization Status"),
646 xl("Last Level Billed"),
647 xl("X12 Partner")
649 $TPSCriteriaKeyMaster = "form_encounter.date,billing.date,claims.process_time,claims.target,patient_data.fname," . "form_encounter.pid,claims.payer_id,form_encounter.encounter,insurance_data.provider,billing.id,billing.billed," . "billing.authorized,form_encounter.last_level_billed,billing.x12_partner_id";
650 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down";
652 // The below section is needed if there is any 'radio' or 'radio_like' type in the $TPSCriteriaDataTypeMaster
653 // $TPSCriteriaDisplayRadioMaster,$TPSCriteriaRadioKeyMaster ==>For each radio data type this pair comes.
654 // The key value 'all' indicates that no action need to be taken based on this.For that the key must be 'all'.Display value can be any thing.
655 $TPSCriteriaDisplayRadioMaster[1] = array(
656 xl("All"),
657 xl("eClaims"),
658 xl("Paper")
659 ); // Display Value
660 $TPSCriteriaRadioKeyMaster[1] = "all,standard,hcfa"; // Key
661 $TPSCriteriaDisplayRadioMaster[2] = array(
662 xl("All"),
663 xl("Insured"),
664 xl("Non-Insured")
665 ); // Display Value
666 $TPSCriteriaRadioKeyMaster[2] = "all,1,0"; // Key
667 $TPSCriteriaDisplayRadioMaster[3] = array(
668 xl("All"),
669 xl("Coded"),
670 xl("Not Coded")
671 ); // Display Value
672 $TPSCriteriaRadioKeyMaster[3] = "all,not null,null"; // Key
673 $TPSCriteriaDisplayRadioMaster[4] = array(
674 xl("All"),
675 xl("Unbilled"),
676 xl("Billed"),
677 xl("Denied")
678 ); // Display Value
679 $TPSCriteriaRadioKeyMaster[4] = "all,0,1,7"; // Key
680 $TPSCriteriaDisplayRadioMaster[5] = array(
681 xl("All"),
682 xl("Authorized"),
683 xl("Unauthorized")
685 $TPSCriteriaRadioKeyMaster[5] = "%,1,0";
686 $TPSCriteriaDisplayRadioMaster[6] = array(
687 xl("All"),
688 xl("None{{Insurance}}"),
689 xl("Ins 1"),
690 xl("Ins 2 or Ins 3")
692 $TPSCriteriaRadioKeyMaster[6] = "all,0,1,2";
693 // The below section is needed if there is any 'query_drop_down' type in the $TPSCriteriaDataTypeMaster
694 $TPSCriteriaQueryDropDownMaster[1] = "SELECT name,id FROM x12_partners;";
695 $TPSCriteriaQueryDropDownMasterDefault[1] = xl("All"); // Only one item will be here
696 $TPSCriteriaQueryDropDownMasterDefaultKey[1] = "all"; // Only one item will be here
697 // The below section is needed if there is any 'include' type in the $TPSCriteriaDataTypeMaster
698 // Function name is added here.Corresponding include files need to be included in the respective pages as done in this page.
699 // It is labled(Included for Insurance ajax criteria)(Line:-279-299).
700 $TPSCriteriaIncludeMaster[1] = "OpenEMR\Billing\BillingReport::insuranceCompanyDisplay";
701 if (!isset($_REQUEST['mode'])) {// default case
702 $_REQUEST['final_this_page_criteria'][0] = "form_encounter.date|between|" . date("Y-m-d 00:00:00") . "|" . date("Y-m-d 23:59:59");
703 $_REQUEST['final_this_page_criteria_text'][0] = xl("Date of Service = Today");
704 $_REQUEST['final_this_page_criteria'][1] = "billing.billed|=|0";
705 $_REQUEST['final_this_page_criteria_text'][1] = xl("Billing Status = Unbilled");
706 $_REQUEST['date_master_criteria_form_encounter_date'] = "today";
707 $_REQUEST['master_from_date_form_encounter_date'] = date("Y-m-d");
708 $_REQUEST['master_to_date_form_encounter_date'] = date("Y-m-d");
709 $_REQUEST['radio_billing_billed'] = 0;
710 $_REQUEST['query_drop_down_master_billing_x12_partner_id'] = "";
713 <?php
714 require_once "$srcdir/../interface/reports/criteria.tab.php";
716 <!-- end criteria -->
717 </form>
718 </div>
719 </div>
720 </div>
721 <div class="container-fluid mt-1">
722 <form class="form-inline" name='update_form' method='post' action='billing_process.php'>
723 <nav class="nav navbar-expand-md navbar-light bg-light px-3 py-2">
724 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#billing-nav-detail" aria-controls="" aria-expanded="false" aria-label="Actions">
725 <span><?php echo xlt('More Actions'); ?></span>
726 </button>
727 <!-- begin detail nav -->
728 <div class="collapse navbar-collapse clearfix" id="billing-nav-detail" role="group">
729 <div class="btn-group dropdown">
730 <button type="button" class="btn nav-link btn-link dropdown-toggle" data-toggle="dropdown" name="bn_x12_support" title=""><?php echo xla('X12 OPTIONS') ?>
731 <span class="caret"></span>
732 </button>
733 <ul class="dropdown-menu" role="menu">
734 <?php if (file_exists($EXPORT_INC)) { ?>
735 <li class="nav-item">
736 <button type="submit" data-open-popup="true" class="btn nav-link btn-link btn-download" name="bn_external" title="<?php echo xla('Export to external billing system') ?>" value="<?php echo xla("Export Billing") ?>">
737 <?php echo xlt("Export Billing") ?>
738 </button>
739 </li>
740 <li class="nav-item">
741 <button type="submit" data-open-popup="true" class="btn nav-link btn-link btn-download" name="bn_mark" title="<?php echo xla('Mark as billed but skip billing') ?>">
742 <?php echo xlt("Mark as Cleared") ?>
743 </button>
744 </li>
745 <?php } else { ?>
746 <li class="nav-item">
747 <button type="button" class="btn nav-link btn-link btn-download" name="bn_x12" onclick="confirmActions(event, '1');" title="<?php echo xla('Generate and download X12 batch') ?>">
748 <?php echo xlt('Generate X12') ?>
749 </button>
750 </li>
751 <?php } ?>
752 <?php if ($GLOBALS['ub04_support']) { ?>
753 <li class="nav-item">
754 <button type="submit" class="btn nav-link btn-link btn-download" name="bn_ub04_x12" onclick="confirmActions(event, '1');" title="<?php echo xla('Generate Institutional X12 837I') ?>">
755 <?php echo xlt('Generate X12 837I') ?>
756 </button>
757 </li>
758 <?php } ?>
759 <?php if ($GLOBALS['support_encounter_claims']) { ?>
760 <li class="nav-item">
761 <button type="submit" class="btn nav-link btn-link btn-download" name="bn_x12_encounter" onclick="confirmActions(event, '1');" title="<?php echo xla('Generate and download X12 encounter claim batch') ?>">
762 <?php echo xlt('Generate X12 Encounter') ?>
763 </button>
764 </li>
765 <?php } ?>
766 </ul>
767 </div>
768 <div class="btn-group dropdown">
769 <button type="button" class="btn nav-link btn-link dropdown-toggle" data-toggle="dropdown" name="bn_process_hcfa_support" title=""><?php echo xlt('HCFA FORM') ?>
770 <span class="caret"></span>
771 </button>
772 <ul class="dropdown-menu" role="menu">
773 <li class="nav-item">
774 <button type="button" class="btn nav-link btn-link btn-download" name="bn_process_hcfa" onclick="confirmActions(event, '2');" title="<?php echo xla('Generate and download CMS 1500 paper claims') ?>">
775 <?php echo xlt('CMS 1500 PDF') ?>
776 </button>
777 </li>
778 <?php if ($GLOBALS['preprinted_cms_1500']) { ?>
779 <li class="nav-item">
780 <button type="button" class="btn nav-link btn-link btn-download" onclick="confirmActions(event, '2');" name="bn_process_hcfa_form" title="<?php echo xla('Generate and download CMS 1500 paper claims on Preprinted form') ?>">
781 <?php echo xlt('CMS 1500 Form') ?>
782 </button>
783 </li>
784 <?php } ?>
785 <li class="nav-item">
786 <button type="button" class="btn nav-link btn-link btn-download" name="bn_hcfa_txt_file" onclick="confirmActions(event, '3');" title="<?php echo xla('Making batch text files for uploading to Clearing House and will mark as billed') ?>">
787 <?php echo xlt('CMS 1500 TEXT') ?>
788 </button>
789 </li>
790 </ul>
791 </div>
792 <?php if ($GLOBALS['ub04_support']) { ?>
793 <div class="btn-group dropdown">
794 <button type="button" class="btn nav-link btn-link dropdown-toggle" data-toggle="dropdown" name="bn_process_ub04_support" title=""><?php echo xlt('UB04 FORM') ?>
795 <span class="caret"></span>
796 </button>
797 <ul class="dropdown-menu" role="menu">
798 <li class="nav-item">
799 <button type="submit" class="btn nav-link btn-link btn-download" name="bn_process_ub04_form" title="<?php echo xla('Generate and download UB-04 CMS1450 with form') ?>">
800 <?php echo xlt('UB04 FORM PDF') ?>
801 </button>
802 </li>
803 <li class="nav-item">
804 <button type="submit" class="btn nav-link btn-link btn-download" name="bn_process_ub04" title="<?php echo xla('Generate and download UB-04 CMS1450') ?>">
805 <?php echo xlt('UB04 TEXT PDF') ?>
806 </button>
807 </li>
808 </ul>
809 </div>
810 <?php } ?>
811 <button class="btn nav-link btn-secondary btn-download" data-open-popup="true" name="bn_mark" title="<?php echo xla('Post to accounting and mark as billed') ?>" type="submit">
812 <?php echo xla('Mark as Cleared') ?>
813 </button>
814 <button class="btn nav-link btn-secondary btn-undo" data-open-popup="true" name="bn_reopen" title="<?php echo xla('Mark as not billed') ?>" type="submit">
815 <?php echo xlt('Re-Open') ?>
816 </button>
817 <span class="input-group">
818 <label for="left_margin"><?php echo xlt('CMS Margins Left'); ?>:</label>
819 <input type='text' size='2' class='form-control' id='left_margin' name='left_margin' value='<?php echo attr($left_margin); ?>' title='<?php echo xla('HCFA left margin in points'); ?>' />
820 <label for="top_margin"><?php echo xlt('Top'); ?>:</label>
821 <input type='text' size='2' class='form-control' id='top_margin' name='top_margin' value='<?php echo attr($top_margin); ?>' title='<?php echo xla('HCFA top margin in points'); ?>' />
822 </span>
823 <?php if ($ub04_support) { ?>
824 <span class="input-group">
825 <label for="left_ubmargin"><?php echo xlt('UB04 Margins Left'); ?>:</label>
826 <input type='text' size='2' class='form-control' id='left_ubmargin' name='left_ubmargin' value='<?php echo attr($left_ubmargin); ?>' title='<?php echo xla('UB04 left margin in points'); ?>' />
827 <label for="top_ubmargin"><?php echo xlt('Top'); ?>:</label>
828 <input type='text' size='2' class='form-control' id='top_ubmargin' name='top_ubmargin' value='<?php echo attr($top_ubmargin); ?>' title='<?php echo xla('UB04 top margin in points'); ?>' />
829 </span>
830 <?php } ?>
831 </div>
832 </nav>
833 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
834 <input name='mode' type='hidden' value="bill" />
835 <input name='authorized' type='hidden' value="<?php echo attr($my_authorized); ?>" />
836 <input name='unbilled' type='hidden' value="<?php echo attr($unbilled); ?>" />
837 <input name='code_type' type='hidden' value="%" />
838 <input name='to_date' type='hidden' value="<?php echo attr($to_date); ?>" />
839 <input name='from_date' type='hidden' value="<?php echo attr($from_date); ?>" />
840 <?php
841 if ($my_authorized == "on") {
842 $my_authorized = "1";
843 } else {
844 $my_authorized = "%";
846 if ($unbilled == "on") {
847 $unbilled = "0";
848 } else {
849 $unbilled = "%";
851 $list = BillingReport::getBillsListBetween("%");
852 // don't query the whole encounter table if no criteria selected
854 if (!isset($_POST["mode"])) {
855 if (!isset($_POST["from_date"])) {
856 $from_date = date("Y-m-d");
857 } else {
858 $from_date = $_POST["from_date"];
860 if (empty($_POST["to_date"])) {
861 $to_date = '';
862 } else {
863 $to_date = $_POST["to_date"];
865 if (!isset($_POST["code_type"])) {
866 $code_type = "all";
867 } else {
868 $code_type = $_POST["code_type"];
870 if (!isset($_POST["unbilled"])) {
871 $unbilled = "on";
872 } else {
873 $unbilled = $_POST["unbilled"];
875 if (!isset($_POST["authorized"])) {
876 $my_authorized = "on";
877 } else {
878 $my_authorized = $_POST["authorized"];
880 } else {
881 $from_date = $_POST["from_date"] ?? null;
882 $to_date = $_POST["to_date"] ?? null;
883 $code_type = $_POST["code_type"] ?? null;
884 $unbilled = $_POST["unbilled"] ?? null;
885 $my_authorized = $_POST["authorized"] ?? null;
888 if ($my_authorized == "on") {
889 $my_authorized = "1";
890 } else {
891 $my_authorized = "%";
894 if ($unbilled == "on") {
895 $unbilled = "0";
896 } else {
897 $unbilled = "%";
900 if (isset($_POST["mode"]) && $_POST["mode"] == "bill") {
901 billCodesList($list);
904 <div class="table-responsive">
905 <table class="table table-sm">
906 <?php
907 $divnos = 0;
908 if ($ret = BillingReport::getBillsBetween("%")) {
909 if (is_array($ret)) { ?>
910 <tr>
911 <td class="text-right" colspan='9'>
912 <table>
913 <tr>
914 <td id='expandAllCollapseAll'>
915 <div class="btn-group">
916 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('expand');">
917 <?php echo '(' . xlt('Expand All') . ')' ?>
918 </button>
919 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('collapse');">
920 <?php echo '(' . xlt('Collapse All') . ')' ?>
921 </button>
922 </div>
923 </td>
924 </tr>
925 </table>
926 </td>
927 </tr>
928 <?php } ?>
930 <?php
931 $loop = 0;
932 $oldcode = "";
933 $last_encounter_id = "";
934 $lhtml = "";
935 $rhtml = "";
936 $lcount = 0;
937 $rcount = 0;
938 $bgcolor = "var(--light)";
939 $skipping = false;
941 $mmo_empty_mod = false;
942 $mmo_num_charges = 0;
944 foreach ($ret as $iter) {
945 // We include encounters here that have never been billed. However
946 // if it had no selected billing items but does have non-selected
947 // billing items, then it is not of interest.
948 if (!$iter['id']) {
949 $res = sqlQuery(
950 "SELECT count(*) AS count FROM billing WHERE " .
951 "encounter = ? AND " .
952 "pid=? AND " .
953 "activity = 1",
954 array(
955 $iter['enc_encounter'],
956 $iter['enc_pid']
959 if ($res['count'] > 0) {
960 continue;
964 $this_encounter_id = $iter['enc_pid'] . "-" . $iter['enc_encounter'];
966 if ($last_encounter_id != $this_encounter_id) {
967 // This dumps all HTML for the previous encounter.
968 if ($lhtml) {
969 while ($rcount < $lcount) {
970 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
971 ++$rcount;
973 // This test handles the case where we are only listing encounters
974 // that appear to have a missing "25" modifier.
975 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
976 if ($DivPut == 'yes') {
977 $lhtml .= '</div>';
978 $DivPut = 'no';
980 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td class='align-top' rowspan='" . attr($rcount) . "'>\n$lhtml</td>$rhtml\n";
981 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n\n";
982 $encount = $encount ?? null;
983 ++$encount;
987 $lhtml = "";
988 $rhtml = "";
989 $mmo_empty_mod = false;
990 $mmo_num_charges = 0;
992 // If there are ANY unauthorized items in this encounter and this is
993 // the normal case of viewing only authorized billing, then skip the
994 // entire encounter.
995 $skipping = false;
996 if ($my_authorized == '1') {
997 $res = sqlQuery(
998 "SELECT count(*) AS count FROM billing WHERE " .
999 "encounter = ? AND " .
1000 "pid=? AND " .
1001 "activity = 1 AND authorized = 0",
1002 array(
1003 $iter['enc_encounter'],
1004 $iter['enc_pid']
1007 if ($res['count'] > 0) {
1008 $skipping = true;
1009 $last_encounter_id = $this_encounter_id;
1010 continue;
1013 // Is there a MBO
1014 $mboid = sqlQuery("SELECT forms.form_id FROM forms WHERE forms.encounter = ? AND forms.authorized = 1 AND forms.formdir = 'misc_billing_options' AND forms.deleted != 1 LIMIT 1", array($iter['enc_encounter']));
1015 $iter['mboid'] = $mboid ? attr($mboid['form_id']) : 0;
1017 $name = getPatientData($iter['enc_pid'], "fname, mname, lname, pubpid, billing_note, DATE_FORMAT(DOB,'%Y-%m-%d') as DOB_YMD");
1019 // Check if patient has primary insurance and a subscriber exists for it.
1020 // If not we will highlight their name in red.
1021 // TBD: more checking here.
1022 $res = sqlQuery(
1023 "SELECT count(*) AS count FROM insurance_data WHERE " .
1024 "pid = ? AND " .
1025 "type='primary' AND " .
1026 "subscriber_lname IS NOT NULL AND " .
1027 "subscriber_lname != '' LIMIT 1",
1028 array(
1029 $iter['enc_pid']
1032 $namecolor = ($res['count'] > 0) ? "black" : "#ff7777";
1034 $bgcolor = ((($encount ?? null) & 1) ? "var(--light)" : "var(--gray300)");
1035 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1036 $lcount = 1;
1037 $rcount = 0;
1038 $oldcode = "";
1040 $ptname = $name['fname'] . " " . $name['lname'];
1041 $raw_encounter_date = date("Y-m-d", strtotime($iter['enc_date']));
1042 $billing_note = $name['billing_note'];
1043 // Add Encounter Date to display with "To Encounter" button 2/17/09 JCH
1044 $lhtml .= "<span class='font-weight-bold' style='color: " . attr($namecolor) . "'>" . text($ptname) . "</span><span class=small>&nbsp;(" . text($iter['enc_pid']) . "-" . text($iter['enc_encounter']) . ")</span>";
1046 // Encounter details are stored to javacript as array.
1047 $result4 = sqlStatement(
1048 "SELECT fe.encounter,fe.date,fe.billing_note,openemr_postcalendar_categories.pc_catname FROM form_encounter AS fe " .
1049 " LEFT JOIN openemr_postcalendar_categories ON fe.pc_catid=openemr_postcalendar_categories.pc_catid WHERE fe.pid = ? ORDER BY fe.date DESC",
1050 array(
1051 $iter['enc_pid']
1054 if (sqlNumRows($result4) > 0) {
1056 } ?>
1057 <script>
1058 Count = 0;
1059 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1060 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1061 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1062 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1063 <?php
1064 while ($rowresult4 = sqlFetchArray($result4)) {
1066 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['encounter']); ?>;
1067 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(oeFormatShortDate(date("Y-m-d", strtotime($rowresult4['date'])))); ?>;
1068 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(xl_appt_category($rowresult4['pc_catname'])); ?>;
1069 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['billing_note']); ?>;
1070 Count++;
1071 <?php
1072 $enc_billing_note[$rowresult4['encounter']] = $rowresult4['billing_note'];
1073 } ?>
1074 </script>
1075 <?php
1076 $lhtml .= "<div class='button-group'>";
1077 // Not sure why the next section seems to do nothing except post "To Encounter" button 2/17/09 JCH
1078 $lhtml .= "<a class='btn btn-sm btn-primary' role='button'" . "href='javascript:
1079 window.toencounter(" . attr_js($iter['enc_pid']) . "," . attr_js($name['pubpid']) . "," . attr_js($ptname) . "," . attr_js($iter['enc_encounter']) . "," . attr_js(oeFormatShortDate($raw_encounter_date)) . "," . attr_js(" " . xl('DOB') . ": " . oeFormatShortDate($name['DOB_YMD']) . " " . xl('Age') . ": " . getPatientAge($name['DOB_YMD'])) . ");
1080 top.window.parent.left_nav.setPatientEncounter(EncounterIdArray[" . attr($iter['enc_pid']) . "],EncounterDateArray[" . attr($iter['enc_pid']) . "], CalendarCategoryArray[" . attr($iter['enc_pid']) . "]);
1081 top.setEncounter(" . attr_js($iter['enc_encounter']) . ");
1082 '>" . xlt('Encounter') . " " . text(oeFormatShortDate($raw_encounter_date)) . "</a>";
1084 // Changed "To xxx" buttons to allow room for encounter date display 2/17/09 JCH
1085 $lhtml .= "<a class='btn btn-sm btn-primary' role='button' " . "href=\"javascript:window.topatient(" . attr_js($iter['enc_pid']) . "," . attr_js($name['pubpid']) . "," . attr_js($ptname) . "," . attr_js($iter['enc_encounter']) . "," . attr_js(oeFormatShortDate($raw_encounter_date)) . "," . attr_js(" " . xl('DOB') . ": " . oeFormatShortDate($name['DOB_YMD']) . " " . xl('Age') . ": " . getPatientAge($name['DOB_YMD'])) . ");
1086 top.window.parent.left_nav.setPatientEncounter(EncounterIdArray[" . attr($iter['enc_pid']) . "],EncounterDateArray[" . attr($iter['enc_pid']) . "], CalendarCategoryArray[" . attr($iter['enc_pid']) . "])\">" . xlt('Insurance') . "</a>";
1087 $is_edited = $iter['mboid'] ? 'btn-success' : 'btn-secondary';
1088 $title = $iter['mboid'] ? xlt("This claim has HCFA 1500 miscellaneous billing options") : xlt("Click to add HCFA 1500 miscellaneous billing options");
1089 $lhtml .= "<a class='btn btn-sm $is_edited' role='button' title='" . attr($title) . "' onclick='popMBO(" . attr_js($iter['enc_pid']) . "," . attr_js($iter['enc_encounter']) . "," . attr_js($iter['mboid']) . "); return false;'>" . xlt('MBO ') . "</a>";
1090 if ($ub04_support && isset($iter['billed'])) {
1091 $c = sqlQuery(
1092 "SELECT submitted_claim AS status FROM claims WHERE " .
1093 "encounter_id = ? AND " .
1094 "patient_id=? " .
1095 "ORDER BY version DESC LIMIT 1",
1096 array(
1097 $iter['enc_encounter'],
1098 $iter['enc_pid']
1101 $is_edited = ($c['status'] ?? null) ? 'btn-success' : 'btn-warning';
1102 $bname = ($c['status'] ?? null) ? xl('Reviewed') : xl('Review UB04');
1103 $lhtml .= "<a class='btn btn-sm $is_edited' role='button' onclick='popUB04(" . attr_js($iter['enc_pid']) . "," . attr_js($iter['enc_encounter']) . "); return false;'>" . text($bname) . "</a>";
1105 $lhtml .= "</div>";
1106 $divnos = $divnos + 1;
1107 $lhtml .= "&nbsp;&nbsp;&nbsp;<a onclick='divtoggle(" . attr_js("spanid_" . $divnos) . "," . attr_js("divid_" . $divnos) . ");' class='small' id='aid_" . attr($divnos) . "' href=\"JavaScript:void(0);" . "\">(<span id=spanid_" . attr($divnos) . " class=\"indicator\">" . xlt('Expand') . '</span>)<br /></a>';
1108 if ($GLOBALS['notes_to_display_in_Billing'] == 2 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1109 $lhtml .= '<span class="font-weight-bold text-danger" style="margin-left: 20px;">' . text($billing_note) . '</span>';
1112 if ($iter['id']) {
1113 $lcount += 2;
1114 $lhtml .= "<br />\n";
1115 $lhtml .= "&nbsp;<span class='form-group'>" . xlt('Bill') . ": ";
1116 $lhtml .= "<select name='claims[" . attr($this_encounter_id) . "][payer]' onchange='onNewPayer(event)' class='form-control'>";
1118 $last_level_closed = sqlQuery("SELECT `last_level_closed` FROM `form_encounter` WHERE `encounter` = ?", array($iter['enc_encounter']))['last_level_closed'];
1119 $effective_insurances = getEffectiveInsurances($iter['pid'], $iter['enc_date']);
1121 foreach ($effective_insurances as $key => $row) {
1122 $insuranceName = sqlQuery("SELECT `name` FROM `insurance_companies` WHERE `id` = ?", array($row['provider']))['name'];
1123 $x12Partner = sqlQuery("SELECT `x12_default_partner_id` FROM `insurance_companies` WHERE `id` = ?", array($row['provider']))['x12_default_partner_id'];
1124 $lhtml .= "<option value=\"" . attr(substr($row['type'], 0, 1) . $row['provider']) . "\"";
1125 if ($key == $last_level_closed) {
1126 $lhtml .= " selected";
1127 $default_x12_partner = $x12Partner;
1130 $lhtml .= " data-partner='" . attr($x12Partner) . "'>" . text($row['type']) . ": " . text($insuranceName) . "</option>";
1133 $lhtml .= "<option value='-1'>" . xlt("Unassigned") . "</option>\n";
1134 $lhtml .= "</select>&nbsp;&nbsp;\n";
1135 $lhtml .= "&nbsp;<span class='form-group'>X12: ";
1136 $lhtml .= "<select class='form-control' id='partners' name='claims[" . attr($this_encounter_id) . "][partner]'>";
1137 $lhtml .= "<option value='-1' label='Unassigned'>" . xlt("Partner not configured") . "</option>\n";
1138 foreach ($partners as $xid => $xname) {
1139 if (empty(trim($xname))) {
1140 continue;
1142 $lhtml .= '<option label="' . attr($xname) . '" value="' . attr($xid) . '"';
1143 if ($xid == $default_x12_partner) {
1144 $lhtml .= "selected";
1146 $lhtml .= '>' . text($xname) . '</option>';
1148 $lhtml .= "</select></span>";
1149 $DivPut = 'yes';
1151 if ($GLOBALS['notes_to_display_in_Billing'] == 1 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1152 $lhtml .= "<br /><span class='font-weight-bold text-success ml-3'>" . text($enc_billing_note[$iter['enc_encounter']]) . "</span>";
1154 $lhtml .= "<br />\n&nbsp;<div id='divid_" . attr($divnos) . "' style='display:none'>" . text(oeFormatShortDate(substr($iter['date'], 0, 10))) . text(substr($iter['date'], 10, 6)) . " " . xlt("Encounter was coded");
1156 $query = "SELECT * FROM claims WHERE patient_id = ? AND encounter_id = ? ORDER BY version";
1157 $cres = sqlStatement(
1158 $query,
1159 array(
1160 $iter['enc_pid'],
1161 $iter['enc_encounter']
1165 $lastcrow = false;
1167 while ($crow = sqlFetchArray($cres)) {
1168 $query = "SELECT id.type, ic.name " .
1169 "FROM insurance_data AS id, insurance_companies AS ic WHERE " .
1170 "id.pid = ? AND " .
1171 "id.provider = ? AND " .
1172 "(id.date <= ? OR id.date IS NULL) AND " .
1173 "(id.date_end >= ? OR id.date_end IS NULL) AND " .
1174 "ic.id = id.provider " .
1175 "ORDER BY id.type ASC, id.date DESC";
1177 $irow = sqlQuery(
1178 $query,
1179 array(
1180 $iter['enc_pid'],
1181 $crow['payer_id'],
1182 $raw_encounter_date,
1183 $raw_encounter_date
1187 if ($crow['bill_process']) {
1188 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Queued for") . " " . text($irow['type'] ?? '') . " " . text($crow['target'] ?? '') . " " . xlt("billing to ") . text($irow['name'] ?? '');
1189 ++$lcount;
1190 } elseif ($crow['status'] < 6) {
1191 if ($crow['status'] > 1) {
1192 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Marked as cleared");
1193 ++$lcount;
1194 } else {
1195 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Re-opened");
1196 ++$lcount;
1198 } elseif ($crow['status'] == 6) {
1199 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("This claim has been forwarded to next level.");
1200 ++$lcount;
1201 } elseif ($crow['status'] == 7) {
1202 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("This claim has been denied.Reason:-");
1203 if ($crow['process_file']) {
1204 $code_array = explode(',', $crow['process_file']);
1205 foreach ($code_array as $code_key => $code_value) {
1206 $lhtml .= "<br />\n&nbsp;&nbsp;&nbsp;";
1207 $reason_array = explode('_', $code_value);
1208 if (!isset($adjustment_reasons[$reason_array[3]])) {
1209 $lhtml .= xlt("For code") . ' [' . text($reason_array[0]) . '] ' . xlt("and modifier") . ' [' . text($reason_array[1]) . '] ' . xlt("the Denial code is") . ' [' . text($reason_array[2]) . ' ' . text($reason_array[3]) . ']';
1210 } else {
1211 $lhtml .= xlt("For code") . ' [' . text($reason_array[0]) . '] ' . xlt("and modifier") . ' [' . text($reason_array[1]) . '] ' . xlt("the Denial Group code is") . ' [' . text($reason_array[2]) . '] ' . xlt("and the Reason is") . ':- ' . text($adjustment_reasons[$reason_array[3]]);
1214 } else {
1215 $lhtml .= xlt("Not Specified.");
1217 ++$lcount;
1220 if ($crow['process_time']) {
1221 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['process_time'], 0, 10))) . text(substr($crow['process_time'], 10, 6)) . " " . xlt("Claim was generated to file") . " " . "<a href='get_claim_file.php?key=" . attr_url($crow['process_file']) . "&csrf_token_form=" . attr_url(CsrfUtils::collectCsrfToken()) . "' onclick='top.restoreSession()'>" . text($crow['process_file']) . "</a>";
1222 ++$lcount;
1225 $lastcrow = $crow;
1226 } // end while ($crow = sqlFetchArray($cres))
1228 if ($lastcrow && $lastcrow['status'] == 4) {
1229 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been closed.");
1230 ++$lcount;
1233 if ($lastcrow && $lastcrow['status'] == 5) {
1234 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been canceled.");
1235 ++$lcount;
1237 } // end if ($iter['id'])
1238 } // end if ($last_encounter_id != $this_encounter_id)
1240 if ($skipping) {
1241 continue;
1244 // Collect info related to the missing modifiers test.
1245 if ($iter['fee'] > 0) {
1246 ++$mmo_num_charges;
1247 $tmp = substr($iter['code'], 0, 3);
1248 if (($tmp == '992' || $tmp == '993') && empty($iter['modifier'])) {
1249 $mmo_empty_mod = true;
1253 ++$rcount;
1255 if ($rhtml) {
1256 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1258 $rhtml .= "<td width='50'>";
1259 if ($iter['id'] && $oldcode != $iter['code_type']) {
1260 $rhtml .= "<span class='text'>" . text($iter['code_type']) . ": </span>";
1263 $oldcode = $iter['code_type'];
1264 $rhtml .= "</td>\n";
1265 $justify = "";
1267 if ($iter['id'] && !empty($code_types[$iter['code_type']]['just'])) {
1268 $js = explode(":", $iter['justify']);
1269 $counter = 0;
1270 foreach ($js as $j) {
1271 if (!empty($j)) {
1272 if ($counter == 0) {
1273 $justify .= " (<b>" . text($j) . "</b>)";
1274 } else {
1275 $justify .= " (" . text($j) . ")";
1277 $counter++;
1282 $rhtml .= "<td><span class='text'>" . ($iter['code_type'] == 'COPAY' ? text(oeFormatMoney($iter['code'])) : text($iter['code']));
1283 if ($iter['modifier']) {
1284 $rhtml .= ":" . text($iter['modifier']);
1286 $rhtml .= "</span><span style='font-size:8pt;'>$justify</span></td>\n";
1288 $rhtml .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1289 if ($iter['id'] && $iter['fee'] > 0) {
1290 $rhtml .= text(oeFormatMoney($iter['fee']));
1292 $rhtml .= "</span></td>\n";
1293 $rhtml .= '<td><span style="font-size:8pt; font-weight:900; background:#ffff9e">&nbsp;&nbsp;&nbsp;';
1294 if ($iter['id']) {
1295 $rhtml .= getProviderName(empty($iter['provider_id']) ? text($iter['enc_provider_id']) : text($iter['provider_id']));
1297 $rhtml .= "</span></td>\n";
1298 $rhtml .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1299 if ($GLOBALS['display_units_in_billing'] != 0) {
1300 if ($iter['id']) {
1301 $rhtml .= xlt("Units") . ":" . text($iter["units"]);
1304 $rhtml .= "</span></td>\n";
1305 $rhtml .= '<td width="100">&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1306 if ($iter['id']) {
1307 $rhtml .= text(oeFormatSDFT(strtotime($iter["date"])));
1309 $rhtml .= "</span></td>\n";
1310 // This error message is generated if the authorized check box is not checked
1311 if ($iter['id'] && $iter['authorized'] != 1) {
1312 $rhtml .= "<td><span class='alert'>" . xlt("Note: This code has not been authorized.") . "</span></td>\n";
1313 } else {
1314 $rhtml .= "<td></td>\n";
1316 if ($iter['id'] && $last_encounter_id != $this_encounter_id) {
1317 $tmpbpr = $iter['bill_process'];
1318 if ($tmpbpr == '0' && $iter['billed']) {
1319 $tmpbpr = '2';
1321 $rhtml .= "<td><input type='checkbox' value='" . attr($tmpbpr) . "' name='claims[" . attr($this_encounter_id) . "][bill]' onclick='set_button_states()' id='CheckBoxBilling" . attr(($CheckBoxBilling ?? null) * 1) . "'>&nbsp;</td>\n";
1322 $CheckBoxBilling = ($CheckBoxBilling ?? null) + 1;
1323 } else {
1324 $rhtml .= "<td></td>\n";
1326 if ($last_encounter_id != $this_encounter_id) {
1327 $rhtml2 = "";
1328 $rowcnt = 0;
1329 $resMoneyGot = sqlStatement(
1330 "SELECT pay_amount AS PatientPay,date(post_time) AS date FROM ar_activity WHERE " .
1331 "pid = ? AND encounter = ? AND deleted IS NULL AND payer_type = 0 AND account_code = 'PCP'",
1332 array(
1333 $iter['enc_pid'],
1334 $iter['enc_encounter']
1337 // new fees screen copay gives account_code='PCP'
1338 if (sqlNumRows($resMoneyGot) > 0) {
1339 $lcount += 2;
1340 $rcount++;
1342 // checks whether a copay exists for the encounter and if exists displays it.
1343 while ($rowMoneyGot = sqlFetchArray($resMoneyGot)) {
1344 $rowcnt++;
1345 $PatientPay = $rowMoneyGot['PatientPay'];
1346 $date = $rowMoneyGot['date'];
1347 if ($PatientPay > 0) {
1348 if ($rhtml) {
1349 $rhtml2 .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1351 $rhtml2 .= "<td width='50'>";
1352 $rhtml2 .= "<span class='text'>" . xlt('COPAY') . ": </span>";
1353 $rhtml2 .= "</td>\n";
1354 $rhtml2 .= "<td><span class='text'>" . text(oeFormatMoney($PatientPay)) . "</span><span style='font-size:8pt;'>&nbsp;</span></td>\n";
1355 $rhtml2 .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1356 $rhtml2 .= "</span></td>\n";
1357 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1358 $rhtml2 .= "</span></td>\n";
1359 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1360 $rhtml2 .= "</span></td>\n";
1361 $rhtml2 .= '<td width=100>&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1362 $rhtml2 .= text(oeFormatSDFT(strtotime($date)));
1363 $rhtml2 .= "</span></td>\n";
1364 if ($iter['id'] && $iter['authorized'] != 1) {
1365 $rhtml2 .= "<td><span class='alert'>" . xlt("Note: This copay was entered against billing that has not been authorized. Please review status.") . "</span></td>\n";
1366 } else {
1367 $rhtml2 .= "<td></td>\n";
1369 if (!$iter['id'] && $rowcnt == 1) {
1370 $rhtml2 .= "<td><input type='checkbox' value='0' name='claims[" . attr($this_encounter_id) . "][bill]' onclick='set_button_states()' id='CheckBoxBilling" . attr($CheckBoxBilling * 1) . "'>&nbsp;</td>\n";
1371 $CheckBoxBilling++;
1372 } else {
1373 $rhtml2 .= "<td></td>\n";
1377 $rhtml .= $rhtml2;
1379 $rhtml .= "</tr>\n";
1380 $last_encounter_id = $this_encounter_id;
1381 } // end foreach
1383 if ($lhtml) {
1384 while ($rcount < $lcount) {
1385 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
1386 ++$rcount;
1388 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
1389 if ($DivPut == 'yes') {
1390 $lhtml .= '</div>';
1391 $DivPut = 'no';
1393 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td rowspan='" . attr($rcount) . "' valign='top' width='25%'>\n$lhtml</td>$rhtml\n";
1394 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1401 </table>
1402 </div>
1403 </form>
1405 </div>
1406 <!--end of container div -->
1407 <?php $oemr_ui->oeBelowContainerDiv(); ?>
1408 <script>
1409 set_button_states();
1410 <?php
1411 if ($alertmsg) {
1412 echo "alert(" . js_escape($alertmsg) . ");\n";
1415 $(function () {
1416 $("#view-log-link").click(function() {
1417 top.restoreSession();
1418 dlgopen('customize_log.php', '_blank', 750, 400);
1420 $("#clear-log").click(function() {
1421 var checkstr = confirm(<?php echo xlj("Do you really want to clear the log?"); ?>);
1422 if (checkstr == true) {
1423 top.restoreSession();
1424 dlgopen("clear_log.php?csrf_token_form=" + <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>, '_blank', 500, 400);
1425 } else {
1426 return false;
1430 $('button[type="submit"]').click(function() {
1431 top.restoreSession();
1432 $(this).attr('data-clicked', true);
1435 $('form[name="update_form"]').on('submit', function(e) {
1436 var clickedButton = $("button[type=submit][data-clicked='true'")[0];
1437 // clear clicked button indicator
1438 $('button[type="submit"]').attr('data-clicked', false);
1440 if (!clickedButton || $(clickedButton).attr("data-open-popup") !== "true") {
1441 $(this).removeAttr("target");
1442 return top.restoreSession();
1443 } else {
1444 top.restoreSession();
1445 var w = window.open('about:blank', 'Popup_Window', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=400,height=300,left = 312,top = 234');
1446 this.target = 'Popup_Window';
1450 $('.datepicker').datetimepicker({
1451 <?php $datetimepicker_timepicker = false; ?>
1452 <?php $datetimepicker_showseconds = false; ?>
1453 <?php $datetimepicker_formatInput = false; ?>
1454 <?php require $GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'; ?>
1455 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
1457 // jquery-ui tooltip converted to bootstrap tooltip
1458 $('#update-tooltip').attr("title", <?php echo xlj('Click Update List to display billing information filtered by the selected Current Criteria'); ?>).tooltip();
1460 </script>
1461 <input type="hidden" name="divnos" id="divnos" value="<?php echo attr($divnos ?? '') ?>" />
1462 <input type='hidden' name='ajax_mode' id='ajax_mode' value='' />
1463 </body>
1465 </html>