chore(deps): bump twig/twig from 3.17.1 to 3.19.0 (#7951)
[openemr.git] / interface / billing / billing_report.php
blobaa9836429b0d428d1e3e81fe1e8f38938038f223
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 async function toPatient(type, pid, pubpid, pname, enc, datestr, dobstr, enc_pid_array, enc_date_array, cal_cat_array) {
346 const encUrl = 'patient_file/encounter/encounter_top.php?set_encounter=' + encodeURIComponent(enc) + '&pid=' + encodeURIComponent(pid);
347 if (type == 'enc') {
348 patUrl = 'patient_file/summary/demographics.php?pid=' + encodeURIComponent(pid);
349 } else {
350 patUrl = 'patient_file/summary/insurance_edit.php?pid=' + encodeURIComponent(pid);
352 pid = parseInt(pid, 10);
353 enc = parseInt(enc, 10);
354 // Restore the session (getSessionValue calls restoreSession()) and load the encounter
355 let curpid = await top.getSessionValue('pid');
356 try {
357 if (curpid != pid) { // set patient
358 top.clearPatient(false);
359 await parent.left_nav.setPatient(pname, pid, pubpid, '', dobstr);
360 await parent.asyncLoadFrame('dem1', 'pat', patUrl);
361 await parent.left_nav.setPatientEncounter(enc_pid_array, enc_date_array, cal_cat_array);
363 if (type == 'enc') { // to encounter
364 await parent.left_nav.setEncounter(datestr, enc, 'enc');
365 await parent.asyncLoadFrame('enc2', 'enc', encUrl);
366 await parent.activateTabByName('enc', true);
367 } else { // to insurance
368 await parent.asyncLoadFrame('ens1', 'enc', 'patient_file/history/encounters.php?pid=' + encodeURIComponent(pid));
369 await parent.activateTabByName('pat', true);
371 } catch (error) {
372 console.error('Failed to process patient:', error);
376 function popMBO(pid, enc, mboid) {
377 if (!window.focus) return true;
378 if (!ProcessBeforeSubmitting()) return false;
379 top.restoreSession();
380 let qstring = "&pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc) + "&id=" + encodeURIComponent(mboid);
381 let href = "<?php echo $GLOBALS['web_root']?>/interface/patient_file/encounter/view_form.php?formname=misc_billing_options&isBilling=1" + qstring;
382 dlgopen(href, 'mbopop', 'modal-lg', 750, false, '', {
383 sizeHeight: 'full' // override min height auto size.
385 return true;
388 function popUB04(pid, enc) {
389 if (!window.focus) return true;
390 if (!ProcessBeforeSubmitting()) return false;
391 top.restoreSession();
392 let href = "<?php echo $GLOBALS['web_root']?>/interface/billing/ub04_form.php?pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc);
393 dlgopen(href, 'ub04pop', 1175, 750, false, '', {
394 sizeHeight: 'full' // override min height auto size.
396 return true;
399 var EncounterDateArray = new Array;
400 var CalendarCategoryArray = new Array;
401 var EncounterIdArray = new Array;
402 var EncounterNoteArray = new Array;
404 function SubmitTheScreen() { //Action on Update List link
405 if (!ProcessBeforeSubmitting()) return false;
406 if (!criteriaSelectHasValue('final_this_page_criteria')) return false;
407 $("#update-tooltip").replaceWith("<i class='fa fa-sync fa-spin fa-1x' style=\"color:red\"></i>");
408 top.restoreSession();
409 document.the_form.mode.value = 'change';
410 document.the_form.target = '_self';
411 document.the_form.action = 'billing_report.php';
412 document.the_form.submit();
413 return true;
416 function SubmitTheScreenPrint() { //Action on View Printable Report link
417 if (!ProcessBeforeSubmitting()) return false;
418 top.restoreSession();
419 document.the_form.target = 'new';
420 document.the_form.action = 'print_billing_report.php';
421 document.the_form.submit();
422 return true;
425 function SubmitTheEndDayPrint() { //Action on View End of Day Report link
426 if (!ProcessBeforeSubmitting()) return false;
427 top.restoreSession();
428 document.the_form.target = 'new';
429 <?php if ($GLOBALS['use_custom_daysheet'] == 1) { ?>
430 document.the_form.action = 'print_daysheet_report_num1.php';
431 <?php } ?>
432 <?php if ($GLOBALS['use_custom_daysheet'] == 2) { ?>
433 document.the_form.action = 'print_daysheet_report_num2.php';
434 <?php } ?>
435 <?php if ($GLOBALS['use_custom_daysheet'] == 3) { ?>
436 document.the_form.action = 'print_daysheet_report_num3.php';
437 <?php } ?>
438 document.the_form.submit();
439 return true;
442 function SubmitTheScreenExportOFX() { //Action on Export OFX link
443 if (!ProcessBeforeSubmitting()) return false;
444 top.restoreSession();
445 document.the_form.mode.value = 'export';
446 document.the_form.target = '_self';
447 document.the_form.action = 'billing_report.php';
448 document.the_form.submit();
449 return true;
452 function TestExpandCollapse() { //Checks whether the Expand All, Collapse All labels need to be placed.If any result set is there these will be placed.
453 var set = -1;
454 for (i = 1; i <= document.getElementById("divnos").value; i++) {
455 var ele = document.getElementById("divid_" + i);
456 if (ele) {
457 set = 1;
458 break;
461 if (set == -1) {
462 if (document.getElementById("expandAllCollapseAll")) {
463 document.getElementById("expandAllCollapseAll").innerHTML = '';
468 function expandcollapse(atr) {
469 if (atr == "expand") { //Called in the Expand All, Collapse All links(All items will be expanded or collapsed)
470 for (i = 1; i <= document.getElementById("divnos").value; i++) {
471 var mydivid = "divid_" + i;
472 var myspanid = "spanid_" + i;
473 var ele = document.getElementById(mydivid);
474 var text = document.getElementById(myspanid);
475 if (ele) {
476 ele.style.display = "inline";
477 text.innerHTML =
478 jsText(<?php echo xlj('Collapse'); ?>);
481 } else {
482 for (i = 1; i <= document.getElementById("divnos").value; i++) {
483 var mydivid = "divid_" + i;
484 var myspanid = "spanid_" + i;
485 var ele = document.getElementById(mydivid);
486 var text = document.getElementById(myspanid);
487 if (ele) {
488 ele.style.display = "none";
489 text.innerHTML =
490 jsText(<?php echo xlj('Expand'); ?>);
496 function divtoggle(spanid, divid) { //Called in the Expand, Collapse links(This is for a single item)
497 var ele = document.getElementById(divid);
498 if (ele) {
499 var text = document.getElementById(spanid);
500 if (ele.style.display == "inline") {
501 ele.style.display = "none";
502 text.innerHTML =
503 jsText(<?php echo xlj('Expand'); ?>);
504 } else {
505 ele.style.display = "inline";
506 text.innerHTML =
507 jsText(<?php echo xlj('Collapse'); ?>);
512 function criteriaSelectHasValue(select) {
513 obj = document.getElementById(select);
514 if (obj.options.length == 0) {
515 var checkstr = confirm(<?php echo xlj("Do you really want to submit with no criteria selected?"); ?>);
516 return checkstr;
518 return true;
520 </script>
521 <?php require_once "$srcdir/../interface/reports/report.script.php"; ?>
522 <!-- Criteria Section common javascript page-->
523 <!-- =============Included for Insurance ajax criteria==== -->
524 <?php require_once "{$GLOBALS['srcdir']}/ajax/payment_ajax_jav.inc.php"; ?>
525 <style>
526 #ajax_div_insurance {
527 position: absolute;
528 z-index: 10;
529 background-color: #FBFDD0;
530 border: 1px solid #ccc;
531 padding: 10px;
534 button[type="submit"].subbtn-warning {
535 background: #ec971f !important;
536 color: black !important;
539 button[type="submit"].subbtn-warning:hover {
540 background: #da8104 !important;
541 color: var(--white) !important;
544 @media only screen and (max-width: 1024px) {
545 [class*="col-"] {
546 width: 100%;
547 text-align: left !Important;
551 .table {
552 margin: auto;
555 @media (min-width: 992px) {
556 .modal-lg {
557 width: 1000px !Important;
561 .table th,
562 .table td {
563 border-top: none !important;
567 a:visited,
568 a:hover {
569 text-decoration: none;
570 color: var(--black);
572 </style>
573 <script>
574 document.onclick = TakeActionOnHide;
575 </script>
576 <!-- =============Included for Insurance ajax criteria==== -->
577 <title><?php echo xlt('Billing Manager'); ?></title>
578 <?php
579 $arrOeUiSettings = array(
580 'heading_title' => xl('Billing Manager'),
581 'include_patient_name' => false,// use only in appropriate pages
582 'expandable' => false,
583 'expandable_files' => array('billing_report_xpd'),//all file names need suffix _xpd
584 'action' => "conceal",//conceal, reveal, search, reset, link or back
585 'action_title' => "",
586 'action_href' => "",//only for actions - reset, link or back
587 'show_help_icon' => false,
588 'help_file_name' => ""
590 $oemr_ui = new OemrUI($arrOeUiSettings);
592 </head>
594 <body onload="TestExpandCollapse()">
595 <div id="container_div" class="<?php echo attr($oemr_ui->oeContainer()); ?> mt-3">
596 <div class="row">
597 <div class="col-sm-12">
598 <?php echo $oemr_ui->pageHeading() . "\r\n"; ?>
599 </div>
600 </div>
601 <div class="hideaway">
602 <div>
603 <form class="form" name='the_form' method='post' action='billing_report.php' onsubmit='return top.restoreSession()'>
604 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
605 <input type='hidden' name='mode' value='change' />
606 <!-- Criteria section Starts -->
607 <?php
608 // TPS = This Page Search
609 // The following are the search criteria per page.All the following variable which ends with 'Master' need to be filled properly.
610 // Each item is seperated by a comma(,).
611 // $TPSCriteriaDisplayMaster ==>It is the display on screen for the set of criteria.
612 // $TPSCriteriaKeyMaster ==>Corresponding database fields in the same order.
613 // $TPSCriteriaDataTypeMaster ==>Corresponding data type in the same order.
614 $TPSCriteriaDisplayRadioMaster = array();
615 $TPSCriteriaRadioKeyMaster = array();
616 $TPSCriteriaQueryDropDownMaster = array();
617 $TPSCriteriaQueryDropDownMasterDefault = array();
618 $TPSCriteriaQueryDropDownMasterDefaultKey = array();
619 $TPSCriteriaIncludeMaster = array();
621 if ($daysheet) {
622 $TPSCriteriaDisplayMaster = array(
623 xl("Date of Service"),
624 xl("Date of Entry"),
625 xl("Date of Billing"),
626 xl("Claim Type"),
627 xl("Patient Name"),
628 xl("Patient Id"),
629 xl("Insurance Company"),
630 xl("Encounter"),
631 xl("Whether Insured"),
632 xl("Charge Coded"),
633 xl("Billing Status"),
634 xl("Authorization Status"),
635 xl("Last Level Billed"),
636 xl("X12 Partner"),
637 xl("User")
639 $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";
640 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down,text";
641 } else {
642 $TPSCriteriaDisplayMaster = array(
643 xl("Date of Service"),
644 xl("Date of Entry"),
645 xl("Date of Billing"),
646 xl("Claim Type"),
647 xl("Patient Name"),
648 xl("Patient Id"),
649 xl("Insurance Company"),
650 xl("Encounter"),
651 xl("Whether Insured"),
652 xl("Charge Coded"),
653 xl("Billing Status"),
654 xl("Authorization Status"),
655 xl("Last Level Billed"),
656 xl("X12 Partner")
658 $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";
659 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down";
661 // The below section is needed if there is any 'radio' or 'radio_like' type in the $TPSCriteriaDataTypeMaster
662 // $TPSCriteriaDisplayRadioMaster,$TPSCriteriaRadioKeyMaster ==>For each radio data type this pair comes.
663 // 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.
664 $TPSCriteriaDisplayRadioMaster[1] = array(
665 xl("All"),
666 xl("eClaims"),
667 xl("Paper")
668 ); // Display Value
669 $TPSCriteriaRadioKeyMaster[1] = "all,standard,hcfa"; // Key
670 $TPSCriteriaDisplayRadioMaster[2] = array(
671 xl("All"),
672 xl("Insured"),
673 xl("Non-Insured")
674 ); // Display Value
675 $TPSCriteriaRadioKeyMaster[2] = "all,1,0"; // Key
676 $TPSCriteriaDisplayRadioMaster[3] = array(
677 xl("All"),
678 xl("Coded"),
679 xl("Not Coded")
680 ); // Display Value
681 $TPSCriteriaRadioKeyMaster[3] = "all,not null,null"; // Key
682 $TPSCriteriaDisplayRadioMaster[4] = array(
683 xl("All"),
684 xl("Unbilled"),
685 xl("Billed"),
686 xl("Denied")
687 ); // Display Value
688 $TPSCriteriaRadioKeyMaster[4] = "all,0,1,7"; // Key
689 $TPSCriteriaDisplayRadioMaster[5] = array(
690 xl("All"),
691 xl("Authorized"),
692 xl("Unauthorized")
694 $TPSCriteriaRadioKeyMaster[5] = "%,1,0";
695 $TPSCriteriaDisplayRadioMaster[6] = array(
696 xl("All"),
697 xl("None{{Insurance}}"),
698 xl("Ins 1"),
699 xl("Ins 2 or Ins 3")
701 $TPSCriteriaRadioKeyMaster[6] = "all,0,1,2";
702 // The below section is needed if there is any 'query_drop_down' type in the $TPSCriteriaDataTypeMaster
703 $TPSCriteriaQueryDropDownMaster[1] = "SELECT name,id FROM x12_partners;";
704 $TPSCriteriaQueryDropDownMasterDefault[1] = xl("All"); // Only one item will be here
705 $TPSCriteriaQueryDropDownMasterDefaultKey[1] = "all"; // Only one item will be here
706 // The below section is needed if there is any 'include' type in the $TPSCriteriaDataTypeMaster
707 // Function name is added here.Corresponding include files need to be included in the respective pages as done in this page.
708 // It is labled(Included for Insurance ajax criteria)(Line:-279-299).
709 $TPSCriteriaIncludeMaster[1] = "OpenEMR\Billing\BillingReport::insuranceCompanyDisplay";
710 if (!isset($_REQUEST['mode'])) {// default case
711 $_REQUEST['final_this_page_criteria'][0] = "form_encounter.date|between|" . date("Y-m-d 00:00:00") . "|" . date("Y-m-d 23:59:59");
712 $_REQUEST['final_this_page_criteria_text'][0] = xl("Date of Service = Today");
713 $_REQUEST['final_this_page_criteria'][1] = "billing.billed|=|0";
714 $_REQUEST['final_this_page_criteria_text'][1] = xl("Billing Status = Unbilled");
715 $_REQUEST['date_master_criteria_form_encounter_date'] = "today";
716 $_REQUEST['master_from_date_form_encounter_date'] = date("Y-m-d");
717 $_REQUEST['master_to_date_form_encounter_date'] = date("Y-m-d");
718 $_REQUEST['radio_billing_billed'] = 0;
719 $_REQUEST['query_drop_down_master_billing_x12_partner_id'] = "";
722 <?php
723 require_once "$srcdir/../interface/reports/criteria.tab.php";
725 <!-- end criteria -->
726 </form>
727 </div>
728 </div>
729 </div>
730 <div class="container-fluid mt-1">
731 <form class="form-inline" name='update_form' method='post' action='billing_process.php'>
732 <nav class="nav navbar-expand-md navbar-light bg-light px-3 py-2">
733 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#billing-nav-detail" aria-controls="" aria-expanded="false" aria-label="Actions">
734 <span><?php echo xlt('More Actions'); ?></span>
735 </button>
736 <!-- begin detail nav -->
737 <div class="collapse navbar-collapse clearfix" id="billing-nav-detail" role="group">
738 <div class="btn-group dropdown">
739 <button type="button" class="btn nav-link btn-link dropdown-toggle" data-toggle="dropdown" name="bn_x12_support" title=""><?php echo xla('X12 OPTIONS') ?>
740 <span class="caret"></span>
741 </button>
742 <ul class="dropdown-menu" role="menu">
743 <?php if (file_exists($EXPORT_INC)) { ?>
744 <li class="nav-item">
745 <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") ?>">
746 <?php echo xlt("Export Billing") ?>
747 </button>
748 </li>
749 <li class="nav-item">
750 <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') ?>">
751 <?php echo xlt("Mark as Cleared") ?>
752 </button>
753 </li>
754 <?php } else { ?>
755 <li class="nav-item">
756 <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') ?>">
757 <?php echo xlt('Generate X12') ?>
758 </button>
759 </li>
760 <?php } ?>
761 <?php if ($GLOBALS['ub04_support']) { ?>
762 <li class="nav-item">
763 <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') ?>">
764 <?php echo xlt('Generate X12 837I') ?>
765 </button>
766 </li>
767 <?php } ?>
768 <?php if ($GLOBALS['support_encounter_claims']) { ?>
769 <li class="nav-item">
770 <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') ?>">
771 <?php echo xlt('Generate X12 Encounter') ?>
772 </button>
773 </li>
774 <?php } ?>
775 </ul>
776 </div>
777 <div class="btn-group dropdown">
778 <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') ?>
779 <span class="caret"></span>
780 </button>
781 <ul class="dropdown-menu" role="menu">
782 <li class="nav-item">
783 <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') ?>">
784 <?php echo xlt('CMS 1500 PDF') ?>
785 </button>
786 </li>
787 <?php if ($GLOBALS['preprinted_cms_1500']) { ?>
788 <li class="nav-item">
789 <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') ?>">
790 <?php echo xlt('CMS 1500 Form') ?>
791 </button>
792 </li>
793 <?php } ?>
794 <li class="nav-item">
795 <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') ?>">
796 <?php echo xlt('CMS 1500 TEXT') ?>
797 </button>
798 </li>
799 </ul>
800 </div>
801 <?php if ($GLOBALS['ub04_support']) { ?>
802 <div class="btn-group dropdown">
803 <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') ?>
804 <span class="caret"></span>
805 </button>
806 <ul class="dropdown-menu" role="menu">
807 <li class="nav-item">
808 <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') ?>">
809 <?php echo xlt('UB04 FORM PDF') ?>
810 </button>
811 </li>
812 <li class="nav-item">
813 <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') ?>">
814 <?php echo xlt('UB04 TEXT PDF') ?>
815 </button>
816 </li>
817 </ul>
818 </div>
819 <?php } ?>
820 <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">
821 <?php echo xla('Mark as Cleared') ?>
822 </button>
823 <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">
824 <?php echo xlt('Re-Open') ?>
825 </button>
826 <span class="input-group">
827 <label for="left_margin"><?php echo xlt('CMS Margins Left'); ?>:</label>
828 <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'); ?>' />
829 <label for="top_margin"><?php echo xlt('Top'); ?>:</label>
830 <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'); ?>' />
831 </span>
832 <?php if ($ub04_support) { ?>
833 <span class="input-group">
834 <label for="left_ubmargin"><?php echo xlt('UB04 Margins Left'); ?>:</label>
835 <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'); ?>' />
836 <label for="top_ubmargin"><?php echo xlt('Top'); ?>:</label>
837 <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'); ?>' />
838 </span>
839 <?php } ?>
840 </div>
841 </nav>
842 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
843 <input name='mode' type='hidden' value="bill" />
844 <input name='authorized' type='hidden' value="<?php echo attr($my_authorized); ?>" />
845 <input name='unbilled' type='hidden' value="<?php echo attr($unbilled); ?>" />
846 <input name='code_type' type='hidden' value="%" />
847 <input name='to_date' type='hidden' value="<?php echo attr($to_date); ?>" />
848 <input name='from_date' type='hidden' value="<?php echo attr($from_date); ?>" />
849 <?php
850 if ($my_authorized == "on") {
851 $my_authorized = "1";
852 } else {
853 $my_authorized = "%";
855 if ($unbilled == "on") {
856 $unbilled = "0";
857 } else {
858 $unbilled = "%";
860 $list = BillingReport::getBillsListBetween("%");
861 // don't query the whole encounter table if no criteria selected
863 if (!isset($_POST["mode"])) {
864 if (!isset($_POST["from_date"])) {
865 $from_date = date("Y-m-d");
866 } else {
867 $from_date = $_POST["from_date"];
869 if (empty($_POST["to_date"])) {
870 $to_date = '';
871 } else {
872 $to_date = $_POST["to_date"];
874 if (!isset($_POST["code_type"])) {
875 $code_type = "all";
876 } else {
877 $code_type = $_POST["code_type"];
879 if (!isset($_POST["unbilled"])) {
880 $unbilled = "on";
881 } else {
882 $unbilled = $_POST["unbilled"];
884 if (!isset($_POST["authorized"])) {
885 $my_authorized = "on";
886 } else {
887 $my_authorized = $_POST["authorized"];
889 } else {
890 $from_date = $_POST["from_date"] ?? null;
891 $to_date = $_POST["to_date"] ?? null;
892 $code_type = $_POST["code_type"] ?? null;
893 $unbilled = $_POST["unbilled"] ?? null;
894 $my_authorized = $_POST["authorized"] ?? null;
897 if ($my_authorized == "on") {
898 $my_authorized = "1";
899 } else {
900 $my_authorized = "%";
903 if ($unbilled == "on") {
904 $unbilled = "0";
905 } else {
906 $unbilled = "%";
909 if (isset($_POST["mode"]) && $_POST["mode"] == "bill") {
910 billCodesList($list);
913 <div class="table-responsive">
914 <table class="table table-sm">
915 <?php
916 $divnos = 0;
917 if ($ret = BillingReport::getBillsBetween("%")) {
918 if (is_array($ret)) { ?>
919 <tr>
920 <td class="text-right" colspan='9'>
921 <table>
922 <tr>
923 <td id='expandAllCollapseAll'>
924 <div class="btn-group">
925 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('expand');">
926 <?php echo '(' . xlt('Expand All') . ')' ?>
927 </button>
928 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('collapse');">
929 <?php echo '(' . xlt('Collapse All') . ')' ?>
930 </button>
931 </div>
932 </td>
933 </tr>
934 </table>
935 </td>
936 </tr>
937 <?php } ?>
939 <?php
940 $loop = 0;
941 $oldcode = "";
942 $last_encounter_id = "";
943 $lhtml = "";
944 $rhtml = "";
945 $lcount = 0;
946 $rcount = 0;
947 $bgcolor = "var(--light)";
948 $skipping = false;
950 $mmo_empty_mod = false;
951 $mmo_num_charges = 0;
953 foreach ($ret as $iter) {
954 // We include encounters here that have never been billed. However
955 // if it had no selected billing items but does have non-selected
956 // billing items, then it is not of interest.
957 if (!$iter['id']) {
958 $res = sqlQuery(
959 "SELECT count(*) AS count FROM billing WHERE " .
960 "encounter = ? AND " .
961 "pid=? AND " .
962 "activity = 1",
963 array(
964 $iter['enc_encounter'],
965 $iter['enc_pid']
968 if ($res['count'] > 0) {
969 continue;
973 $this_encounter_id = $iter['enc_pid'] . "-" . $iter['enc_encounter'];
975 if ($last_encounter_id != $this_encounter_id) {
976 // This dumps all HTML for the previous encounter.
977 if ($lhtml) {
978 while ($rcount < $lcount) {
979 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
980 ++$rcount;
982 // This test handles the case where we are only listing encounters
983 // that appear to have a missing "25" modifier.
984 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
985 if ($DivPut == 'yes') {
986 $lhtml .= '</div>';
987 $DivPut = 'no';
989 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td class='align-top' rowspan='" . attr($rcount) . "'>\n$lhtml</td>$rhtml\n";
990 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n\n";
991 $encount = $encount ?? null;
992 ++$encount;
996 $lhtml = "";
997 $rhtml = "";
998 $mmo_empty_mod = false;
999 $mmo_num_charges = 0;
1001 // If there are ANY unauthorized items in this encounter and this is
1002 // the normal case of viewing only authorized billing, then skip the
1003 // entire encounter.
1004 $skipping = false;
1005 if ($my_authorized == '1') {
1006 $res = sqlQuery(
1007 "SELECT count(*) AS count FROM billing WHERE " .
1008 "encounter = ? AND " .
1009 "pid=? AND " .
1010 "activity = 1 AND authorized = 0",
1011 array(
1012 $iter['enc_encounter'],
1013 $iter['enc_pid']
1016 if ($res['count'] > 0) {
1017 $skipping = true;
1018 $last_encounter_id = $this_encounter_id;
1019 continue;
1022 // Is there a MBO
1023 $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']));
1024 $iter['mboid'] = $mboid ? attr($mboid['form_id']) : 0;
1026 $name = getPatientData($iter['enc_pid'], "fname, mname, lname, pubpid, billing_note, DATE_FORMAT(DOB,'%Y-%m-%d') as DOB_YMD");
1028 // Check if patient has primary insurance and a subscriber exists for it.
1029 // If not we will highlight their name in red.
1030 // TBD: more checking here.
1031 $res = sqlQuery(
1032 "SELECT count(*) AS count FROM insurance_data WHERE " .
1033 "pid = ? AND " .
1034 "type='primary' AND " .
1035 "subscriber_lname IS NOT NULL AND " .
1036 "subscriber_lname != '' LIMIT 1",
1037 array(
1038 $iter['enc_pid']
1041 $namecolor = ($res['count'] > 0) ? "black" : "#ff7777";
1043 $bgcolor = ((($encount ?? null) & 1) ? "var(--light)" : "var(--gray300)");
1044 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1045 $lcount = 1;
1046 $rcount = 0;
1047 $oldcode = "";
1049 $ptname = $name['fname'] . " " . $name['lname'];
1050 $raw_encounter_date = date("Y-m-d", strtotime($iter['enc_date']));
1051 $billing_note = $name['billing_note'];
1052 // Add Encounter Date to display with "To Encounter" button 2/17/09 JCH
1053 $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>";
1055 // Encounter details are stored to javacript as array.
1056 $result4 = sqlStatement(
1057 "SELECT fe.encounter,fe.date,fe.billing_note,openemr_postcalendar_categories.pc_catname FROM form_encounter AS fe " .
1058 " LEFT JOIN openemr_postcalendar_categories ON fe.pc_catid=openemr_postcalendar_categories.pc_catid WHERE fe.pid = ? ORDER BY fe.date DESC",
1059 array(
1060 $iter['enc_pid']
1063 if (sqlNumRows($result4) > 0) {
1065 } ?>
1066 <script>
1067 Count = 0;
1068 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1069 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1070 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1071 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1072 <?php
1073 while ($rowresult4 = sqlFetchArray($result4)) {
1075 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['encounter']); ?>;
1076 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(oeFormatShortDate(date("Y-m-d", strtotime($rowresult4['date'])))); ?>;
1077 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(xl_appt_category($rowresult4['pc_catname'])); ?>;
1078 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['billing_note']); ?>;
1079 Count++;
1080 <?php
1081 $enc_billing_note[$rowresult4['encounter']] = $rowresult4['billing_note'];
1082 } ?>
1083 </script>
1084 <?php
1085 $lhtml .= "<div class='button-group'>";
1086 // Not sure why the next section seems to do nothing except post "To Encounter" button 2/17/09 JCH
1087 $lhtml .= "<a class='btn btn-sm btn-primary' role='button'" .
1088 "href='javascript: window.toPatient(" .
1089 "\"enc\"" . "," .
1090 attr_js($iter['enc_pid']) . "," .
1091 attr_js($name['pubpid']) . "," .
1092 attr_js($ptname) . "," .
1093 attr_js($iter['enc_encounter']) . "," .
1094 attr_js(oeFormatShortDate($raw_encounter_date)) . "," .
1095 attr_js(" " . xl('DOB') . ": " .
1096 oeFormatShortDate($name['DOB_YMD']) . " " .
1097 xl('Age') . ": " .
1098 getPatientAge($name['DOB_YMD'])) . "," .
1099 "EncounterIdArray[" . attr_js($iter['enc_pid']) . "]" . "," .
1100 "EncounterDateArray[" . attr_js($iter['enc_pid']) . "]" . "," .
1101 "CalendarCategoryArray[" . attr_js($iter['enc_pid']) . "]" .
1102 ");" . " '>" . xlt('Encounter') . " " . text(oeFormatShortDate($raw_encounter_date)) . "</a>";
1104 // Changed "To xxx" buttons to allow room for encounter date display 2/17/09 JCH
1105 $lhtml .= "<a class='btn btn-sm btn-primary' role='button' " .
1106 "href='javascript:window.toPatient(" .
1107 "\"ins\"" . "," .
1108 attr_js($iter['enc_pid']) . "," .
1109 attr_js($name['pubpid']) . "," .
1110 attr_js($ptname) . "," .
1111 attr_js($iter['enc_encounter']) . "," .
1112 attr_js(oeFormatShortDate($raw_encounter_date)) . "," .
1113 attr_js(" " . xl('DOB') . ": " .
1114 oeFormatShortDate($name['DOB_YMD']) . " " .
1115 xl('Age') . ": " .
1116 getPatientAge($name['DOB_YMD'])) . "," .
1117 "EncounterIdArray[" . attr_js($iter['enc_pid']) . "]" . "," .
1118 "EncounterDateArray[" . attr_js($iter['enc_pid']) . "]" . "," .
1119 "CalendarCategoryArray[" . attr_js($iter['enc_pid']) . "]" .
1120 ");" . " '>" . xlt('Insurance') . "</a>";
1121 $is_edited = $iter['mboid'] ? 'btn-success' : 'btn-secondary';
1122 $title = $iter['mboid'] ? xlt("This claim has HCFA 1500 miscellaneous billing options") : xlt("Click to add HCFA 1500 miscellaneous billing options");
1123 $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>";
1124 if ($ub04_support && isset($iter['billed'])) {
1125 $c = sqlQuery(
1126 "SELECT submitted_claim AS status FROM claims WHERE " .
1127 "encounter_id = ? AND " .
1128 "patient_id=? " .
1129 "ORDER BY version DESC LIMIT 1",
1130 array(
1131 $iter['enc_encounter'],
1132 $iter['enc_pid']
1135 $is_edited = ($c['status'] ?? null) ? 'btn-success' : 'btn-warning';
1136 $bname = ($c['status'] ?? null) ? xl('Reviewed') : xl('Review UB04');
1137 $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>";
1139 $lhtml .= "</div>";
1140 $divnos = $divnos + 1;
1141 $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>';
1142 if ($GLOBALS['notes_to_display_in_Billing'] == 2 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1143 $lhtml .= '<span class="font-weight-bold text-danger" style="margin-left: 20px;">' . text($billing_note) . '</span>';
1146 if ($iter['id']) {
1147 $lcount += 2;
1148 $lhtml .= "<br />\n";
1149 $lhtml .= "&nbsp;<span class='form-group'>" . xlt('Bill') . ": ";
1150 $lhtml .= "<select name='claims[" . attr($this_encounter_id) . "][payer]' onchange='onNewPayer(event)' class='form-control'>";
1152 $last_level_closed = sqlQuery("SELECT `last_level_closed` FROM `form_encounter` WHERE `encounter` = ?", array($iter['enc_encounter']))['last_level_closed'];
1153 $effective_insurances = getEffectiveInsurances($iter['pid'], $iter['enc_date']);
1154 $insuranceCount = count($effective_insurances ?? []);
1156 foreach ($effective_insurances as $key => $row) {
1157 $insuranceName = sqlQuery("SELECT `name` FROM `insurance_companies` WHERE `id` = ?", array($row['provider']))['name'];
1158 $x12Partner = sqlQuery("SELECT `x12_default_partner_id` FROM `insurance_companies` WHERE `id` = ?", array($row['provider']))['x12_default_partner_id'];
1159 $lhtml .= "<option value=\"" . attr(substr($row['type'], 0, 1) . $row['provider']) . "\"";
1160 if (
1161 $key == $last_level_closed
1162 || $insuranceCount == 1
1164 $lhtml .= " selected";
1165 $default_x12_partner = $x12Partner;
1168 $lhtml .= " data-partner='" . attr($x12Partner) . "'>" . text($row['type']) . ": " . text($insuranceName) . "</option>";
1171 $lhtml .= "<option value='-1'>" . xlt("Unassigned") . "</option>\n";
1172 $lhtml .= "</select>&nbsp;&nbsp;\n";
1173 $lhtml .= "&nbsp;<span class='form-group'>X12: ";
1174 $lhtml .= "<select class='form-control' id='partners' name='claims[" . attr($this_encounter_id) . "][partner]'>";
1175 $lhtml .= "<option value='-1' label='Unassigned'>" . xlt("Partner not configured") . "</option>\n";
1176 foreach ($partners as $xid => $xname) {
1177 if (empty(trim($xname))) {
1178 continue;
1180 $lhtml .= '<option label="' . attr($xname) . '" value="' . attr($xid) . '"';
1181 if ($xid == $default_x12_partner) {
1182 $lhtml .= "selected";
1184 $lhtml .= '>' . text($xname) . '</option>';
1186 $lhtml .= "</select></span>";
1187 $DivPut = 'yes';
1189 if ($GLOBALS['notes_to_display_in_Billing'] == 1 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1190 $lhtml .= "<br /><span class='font-weight-bold text-success ml-3'>" . text($enc_billing_note[$iter['enc_encounter']]) . "</span>";
1192 $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");
1194 $query = "SELECT * FROM claims WHERE patient_id = ? AND encounter_id = ? ORDER BY version";
1195 $cres = sqlStatement(
1196 $query,
1197 array(
1198 $iter['enc_pid'],
1199 $iter['enc_encounter']
1203 $lastcrow = false;
1205 while ($crow = sqlFetchArray($cres)) {
1206 $query = "SELECT id.type, ic.name " .
1207 "FROM insurance_data AS id, insurance_companies AS ic WHERE " .
1208 "id.pid = ? AND " .
1209 "id.provider = ? AND " .
1210 "(id.date <= ? OR id.date IS NULL) AND " .
1211 "(id.date_end >= ? OR id.date_end IS NULL) AND " .
1212 "ic.id = id.provider " .
1213 "ORDER BY id.type ASC, id.date DESC";
1215 $irow = sqlQuery(
1216 $query,
1217 array(
1218 $iter['enc_pid'],
1219 $crow['payer_id'],
1220 $raw_encounter_date,
1221 $raw_encounter_date
1225 if ($crow['bill_process']) {
1226 $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'] ?? '');
1227 ++$lcount;
1228 } elseif ($crow['status'] < 6) {
1229 if ($crow['status'] > 1) {
1230 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Marked as cleared");
1231 ++$lcount;
1232 } else {
1233 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Re-opened");
1234 ++$lcount;
1236 } elseif ($crow['status'] == 6) {
1237 $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.");
1238 ++$lcount;
1239 } elseif ($crow['status'] == 7) {
1240 $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:-");
1241 if ($crow['process_file']) {
1242 $code_array = explode(',', $crow['process_file']);
1243 foreach ($code_array as $code_key => $code_value) {
1244 $lhtml .= "<br />\n&nbsp;&nbsp;&nbsp;";
1245 $reason_array = explode('_', $code_value);
1246 if (!isset($adjustment_reasons[$reason_array[3]])) {
1247 $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]) . ']';
1248 } else {
1249 $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]]);
1252 } else {
1253 $lhtml .= xlt("Not Specified.");
1255 ++$lcount;
1258 if ($crow['process_time']) {
1259 $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>";
1260 ++$lcount;
1263 $lastcrow = $crow;
1264 } // end while ($crow = sqlFetchArray($cres))
1266 if ($lastcrow && $lastcrow['status'] == 4) {
1267 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been closed.");
1268 ++$lcount;
1271 if ($lastcrow && $lastcrow['status'] == 5) {
1272 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been canceled.");
1273 ++$lcount;
1275 } // end if ($iter['id'])
1276 } // end if ($last_encounter_id != $this_encounter_id)
1278 if ($skipping) {
1279 continue;
1282 // Collect info related to the missing modifiers test.
1283 if ($iter['fee'] > 0) {
1284 ++$mmo_num_charges;
1285 $tmp = substr($iter['code'], 0, 3);
1286 if (($tmp == '992' || $tmp == '993') && empty($iter['modifier'])) {
1287 $mmo_empty_mod = true;
1291 ++$rcount;
1293 if ($rhtml) {
1294 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1296 $rhtml .= "<td width='50'>";
1297 if ($iter['id'] && $oldcode != $iter['code_type']) {
1298 $rhtml .= "<span class='text'>" . text($iter['code_type']) . ": </span>";
1301 $oldcode = $iter['code_type'];
1302 $rhtml .= "</td>\n";
1303 $justify = "";
1305 if ($iter['id'] && !empty($code_types[$iter['code_type']]['just'])) {
1306 $js = explode(":", $iter['justify']);
1307 $counter = 0;
1308 foreach ($js as $j) {
1309 if (!empty($j)) {
1310 if ($counter == 0) {
1311 $justify .= " (<b>" . text($j) . "</b>)";
1312 } else {
1313 $justify .= " (" . text($j) . ")";
1315 $counter++;
1320 $rhtml .= "<td><span class='text'>" . ($iter['code_type'] == 'COPAY' ? text(oeFormatMoney($iter['code'])) : text($iter['code']));
1321 if ($iter['modifier']) {
1322 $rhtml .= ":" . text($iter['modifier']);
1324 $rhtml .= "</span><span style='font-size:8pt;'>$justify</span></td>\n";
1326 $rhtml .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1327 if ($iter['id'] && $iter['fee'] > 0) {
1328 $rhtml .= text(oeFormatMoney($iter['fee']));
1330 $rhtml .= "</span></td>\n";
1331 $rhtml .= '<td><span style="font-size:8pt; font-weight:900; background:#ffff9e">&nbsp;&nbsp;&nbsp;';
1332 if ($iter['id']) {
1333 $rhtml .= getProviderName(empty($iter['provider_id']) ? text($iter['enc_provider_id']) : text($iter['provider_id']));
1335 $rhtml .= "</span></td>\n";
1336 $rhtml .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1337 if ($GLOBALS['display_units_in_billing'] != 0) {
1338 if ($iter['id']) {
1339 $rhtml .= xlt("Units") . ":" . text($iter["units"]);
1342 $rhtml .= "</span></td>\n";
1343 $rhtml .= '<td width="100">&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1344 if ($iter['id']) {
1345 $rhtml .= text(oeFormatSDFT(strtotime($iter["date"])));
1347 $rhtml .= "</span></td>\n";
1348 // This error message is generated if the authorized check box is not checked
1349 if ($iter['id'] && $iter['authorized'] != 1) {
1350 $rhtml .= "<td><span class='alert'>" . xlt("Note: This code has not been authorized.") . "</span></td>\n";
1351 } else {
1352 $rhtml .= "<td></td>\n";
1354 if ($iter['id'] && $last_encounter_id != $this_encounter_id) {
1355 $tmpbpr = $iter['bill_process'];
1356 if ($tmpbpr == '0' && $iter['billed']) {
1357 $tmpbpr = '2';
1359 $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";
1360 $CheckBoxBilling = ($CheckBoxBilling ?? null) + 1;
1361 } else {
1362 $rhtml .= "<td></td>\n";
1364 if ($last_encounter_id != $this_encounter_id) {
1365 $rhtml2 = "";
1366 $rowcnt = 0;
1367 $resMoneyGot = sqlStatement(
1368 "SELECT pay_amount AS PatientPay,date(post_time) AS date FROM ar_activity WHERE " .
1369 "pid = ? AND encounter = ? AND deleted IS NULL AND payer_type = 0 AND account_code = 'PCP'",
1370 array(
1371 $iter['enc_pid'],
1372 $iter['enc_encounter']
1375 // new fees screen copay gives account_code='PCP'
1376 if (sqlNumRows($resMoneyGot) > 0) {
1377 $lcount += 2;
1378 $rcount++;
1380 // checks whether a copay exists for the encounter and if exists displays it.
1381 while ($rowMoneyGot = sqlFetchArray($resMoneyGot)) {
1382 $rowcnt++;
1383 $PatientPay = $rowMoneyGot['PatientPay'];
1384 $date = $rowMoneyGot['date'];
1385 if ($PatientPay > 0) {
1386 if ($rhtml) {
1387 $rhtml2 .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1389 $rhtml2 .= "<td width='50'>";
1390 $rhtml2 .= "<span class='text'>" . xlt('COPAY') . ": </span>";
1391 $rhtml2 .= "</td>\n";
1392 $rhtml2 .= "<td><span class='text'>" . text(oeFormatMoney($PatientPay)) . "</span><span style='font-size:8pt;'>&nbsp;</span></td>\n";
1393 $rhtml2 .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1394 $rhtml2 .= "</span></td>\n";
1395 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1396 $rhtml2 .= "</span></td>\n";
1397 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1398 $rhtml2 .= "</span></td>\n";
1399 $rhtml2 .= '<td width=100>&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1400 $rhtml2 .= text(oeFormatSDFT(strtotime($date)));
1401 $rhtml2 .= "</span></td>\n";
1402 if ($iter['id'] && $iter['authorized'] != 1) {
1403 $rhtml2 .= "<td><span class='alert'>" . xlt("Note: This copay was entered against billing that has not been authorized. Please review status.") . "</span></td>\n";
1404 } else {
1405 $rhtml2 .= "<td></td>\n";
1407 if (!$iter['id'] && $rowcnt == 1) {
1408 $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";
1409 $CheckBoxBilling++;
1410 } else {
1411 $rhtml2 .= "<td></td>\n";
1415 $rhtml .= $rhtml2;
1417 $rhtml .= "</tr>\n";
1418 $last_encounter_id = $this_encounter_id;
1419 } // end foreach
1421 if ($lhtml) {
1422 while ($rcount < $lcount) {
1423 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
1424 ++$rcount;
1426 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
1427 if ($DivPut == 'yes') {
1428 $lhtml .= '</div>';
1429 $DivPut = 'no';
1431 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td rowspan='" . attr($rcount) . "' valign='top' width='25%'>\n$lhtml</td>$rhtml\n";
1432 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1439 </table>
1440 </div>
1441 </form>
1443 </div>
1444 <!--end of container div -->
1445 <?php $oemr_ui->oeBelowContainerDiv(); ?>
1446 <script>
1447 set_button_states();
1448 <?php
1449 if ($alertmsg) {
1450 echo "alert(" . js_escape($alertmsg) . ");\n";
1453 $(function () {
1454 $("#view-log-link").click(function() {
1455 top.restoreSession();
1456 dlgopen('customize_log.php', '_blank', 750, 400);
1458 $("#clear-log").click(function() {
1459 var checkstr = confirm(<?php echo xlj("Do you really want to clear the log?"); ?>);
1460 if (checkstr == true) {
1461 top.restoreSession();
1462 dlgopen("clear_log.php?csrf_token_form=" + <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>, '_blank', 500, 400);
1463 } else {
1464 return false;
1468 $('button[type="submit"]').click(function() {
1469 top.restoreSession();
1470 $(this).attr('data-clicked', true);
1473 $('form[name="update_form"]').on('submit', function(e) {
1474 var clickedButton = $("button[type=submit][data-clicked='true'")[0];
1475 // clear clicked button indicator
1476 $('button[type="submit"]').attr('data-clicked', false);
1478 if (!clickedButton || $(clickedButton).attr("data-open-popup") !== "true") {
1479 $(this).removeAttr("target");
1480 return top.restoreSession();
1481 } else {
1482 top.restoreSession();
1483 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');
1484 this.target = 'Popup_Window';
1488 $('.datepicker').datetimepicker({
1489 <?php $datetimepicker_timepicker = false; ?>
1490 <?php $datetimepicker_showseconds = false; ?>
1491 <?php $datetimepicker_formatInput = false; ?>
1492 <?php require $GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'; ?>
1493 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
1495 // jquery-ui tooltip converted to bootstrap tooltip
1496 $('#update-tooltip').attr("title", <?php echo xlj('Click Update List to display billing information filtered by the selected Current Criteria'); ?>).tooltip();
1498 </script>
1499 <input type="hidden" name="divnos" id="divnos" value="<?php echo attr($divnos ?? '') ?>" />
1500 <input type='hidden' name='ajax_mode' id='ajax_mode' value='' />
1501 </body>
1503 </html>