feat: Fixes #6772 adds twig email templates to emails (#6773)
[openemr.git] / interface / billing / billing_report.php
blob203a7fe68e9f6c62898e928526771188ddf9b8a7
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 parent.left_nav.setPatient(pname, pid, pubpid, '', dobstr);
351 parent.left_nav.setEncounter(datestr, enc, 'enc');
352 parent.left_nav.loadFrame('enc2', 'enc', encurl);
355 // Process a click to go to an patient.
356 function topatient(pid, pubpid, pname, enc, datestr, dobstr) {
357 top.restoreSession();
358 paturl = 'patient_file/summary/demographics_full.php?pid=' + encodeURIComponent(pid);
359 parent.left_nav.setPatient(pname, pid, pubpid, '', dobstr);
362 function popMBO(pid, enc, mboid) {
363 if (!window.focus) return true;
364 if (!ProcessBeforeSubmitting()) return false;
365 top.restoreSession();
366 let qstring = "&pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc) + "&id=" + encodeURIComponent(mboid);
367 let href = "<?php echo $GLOBALS['web_root']?>/interface/patient_file/encounter/view_form.php?formname=misc_billing_options&isBilling=1" + qstring;
368 dlgopen(href, 'mbopop', 'modal-lg', 750, false, '', {
369 sizeHeight: 'full' // override min height auto size.
371 return true;
374 function popUB04(pid, enc) {
375 if (!window.focus) return true;
376 if (!ProcessBeforeSubmitting()) return false;
377 top.restoreSession();
378 let href = "<?php echo $GLOBALS['web_root']?>/interface/billing/ub04_form.php?pid=" + encodeURIComponent(pid) + "&enc=" + encodeURIComponent(enc);
379 dlgopen(href, 'ub04pop', 1175, 750, false, '', {
380 sizeHeight: 'full' // override min height auto size.
382 return true;
385 var EncounterDateArray = new Array;
386 var CalendarCategoryArray = new Array;
387 var EncounterIdArray = new Array;
388 var EncounterNoteArray = new Array;
390 function SubmitTheScreen() { //Action on Update List link
391 if (!ProcessBeforeSubmitting()) return false;
392 if (!criteriaSelectHasValue('final_this_page_criteria')) return false;
393 $("#update-tooltip").replaceWith("<i class='fa fa-sync fa-spin fa-1x' style=\"color:red\"></i>");
394 top.restoreSession();
395 document.the_form.mode.value = 'change';
396 document.the_form.target = '_self';
397 document.the_form.action = 'billing_report.php';
398 document.the_form.submit();
399 return true;
402 function SubmitTheScreenPrint() { //Action on View Printable Report link
403 if (!ProcessBeforeSubmitting()) return false;
404 top.restoreSession();
405 document.the_form.target = 'new';
406 document.the_form.action = 'print_billing_report.php';
407 document.the_form.submit();
408 return true;
411 function SubmitTheEndDayPrint() { //Action on View End of Day Report link
412 if (!ProcessBeforeSubmitting()) return false;
413 top.restoreSession();
414 document.the_form.target = 'new';
415 <?php if ($GLOBALS['use_custom_daysheet'] == 1) { ?>
416 document.the_form.action = 'print_daysheet_report_num1.php';
417 <?php } ?>
418 <?php if ($GLOBALS['use_custom_daysheet'] == 2) { ?>
419 document.the_form.action = 'print_daysheet_report_num2.php';
420 <?php } ?>
421 <?php if ($GLOBALS['use_custom_daysheet'] == 3) { ?>
422 document.the_form.action = 'print_daysheet_report_num3.php';
423 <?php } ?>
424 document.the_form.submit();
425 return true;
428 function SubmitTheScreenExportOFX() { //Action on Export OFX link
429 if (!ProcessBeforeSubmitting()) return false;
430 top.restoreSession();
431 document.the_form.mode.value = 'export';
432 document.the_form.target = '_self';
433 document.the_form.action = 'billing_report.php';
434 document.the_form.submit();
435 return true;
438 function TestExpandCollapse() { //Checks whether the Expand All, Collapse All labels need to be placed.If any result set is there these will be placed.
439 var set = -1;
440 for (i = 1; i <= document.getElementById("divnos").value; i++) {
441 var ele = document.getElementById("divid_" + i);
442 if (ele) {
443 set = 1;
444 break;
447 if (set == -1) {
448 if (document.getElementById("expandAllCollapseAll")) {
449 document.getElementById("expandAllCollapseAll").innerHTML = '';
454 function expandcollapse(atr) {
455 if (atr == "expand") { //Called in the Expand All, Collapse All links(All items will be expanded or collapsed)
456 for (i = 1; i <= document.getElementById("divnos").value; i++) {
457 var mydivid = "divid_" + i;
458 var myspanid = "spanid_" + i;
459 var ele = document.getElementById(mydivid);
460 var text = document.getElementById(myspanid);
461 if (ele) {
462 ele.style.display = "inline";
463 text.innerHTML =
464 jsText(<?php echo xlj('Collapse'); ?>);
467 } else {
468 for (i = 1; i <= document.getElementById("divnos").value; i++) {
469 var mydivid = "divid_" + i;
470 var myspanid = "spanid_" + i;
471 var ele = document.getElementById(mydivid);
472 var text = document.getElementById(myspanid);
473 if (ele) {
474 ele.style.display = "none";
475 text.innerHTML =
476 jsText(<?php echo xlj('Expand'); ?>);
482 function divtoggle(spanid, divid) { //Called in the Expand, Collapse links(This is for a single item)
483 var ele = document.getElementById(divid);
484 if (ele) {
485 var text = document.getElementById(spanid);
486 if (ele.style.display == "inline") {
487 ele.style.display = "none";
488 text.innerHTML =
489 jsText(<?php echo xlj('Expand'); ?>);
490 } else {
491 ele.style.display = "inline";
492 text.innerHTML =
493 jsText(<?php echo xlj('Collapse'); ?>);
498 function criteriaSelectHasValue(select) {
499 obj = document.getElementById(select);
500 if (obj.options.length == 0) {
501 var checkstr = confirm(<?php echo xlj("Do you really want to submit with no criteria selected?"); ?>);
502 return checkstr;
504 return true;
506 </script>
507 <?php require_once "$srcdir/../interface/reports/report.script.php"; ?>
508 <!-- Criteria Section common javascript page-->
509 <!-- =============Included for Insurance ajax criteria==== -->
510 <?php require_once "{$GLOBALS['srcdir']}/ajax/payment_ajax_jav.inc.php"; ?>
511 <style>
512 #ajax_div_insurance {
513 position: absolute;
514 z-index: 10;
515 background-color: #FBFDD0;
516 border: 1px solid #ccc;
517 padding: 10px;
520 button[type="submit"].subbtn-warning {
521 background: #ec971f !important;
522 color: black !important;
525 button[type="submit"].subbtn-warning:hover {
526 background: #da8104 !important;
527 color: var(--white) !important;
530 @media only screen and (max-width: 1024px) {
531 [class*="col-"] {
532 width: 100%;
533 text-align: left !Important;
537 .table {
538 margin: auto;
541 @media (min-width: 992px) {
542 .modal-lg {
543 width: 1000px !Important;
547 .table th,
548 .table td {
549 border-top: none !important;
553 a:visited,
554 a:hover {
555 text-decoration: none;
556 color: var(--black);
558 </style>
559 <script>
560 document.onclick = TakeActionOnHide;
561 </script>
562 <!-- =============Included for Insurance ajax criteria==== -->
563 <title><?php echo xlt('Billing Manager'); ?></title>
564 <?php
565 $arrOeUiSettings = array(
566 'heading_title' => xl('Billing Manager'),
567 'include_patient_name' => false,// use only in appropriate pages
568 'expandable' => false,
569 'expandable_files' => array('billing_report_xpd'),//all file names need suffix _xpd
570 'action' => "conceal",//conceal, reveal, search, reset, link or back
571 'action_title' => "",
572 'action_href' => "",//only for actions - reset, link or back
573 'show_help_icon' => false,
574 'help_file_name' => ""
576 $oemr_ui = new OemrUI($arrOeUiSettings);
578 </head>
580 <body onload="TestExpandCollapse()">
581 <div id="container_div" class="<?php echo attr($oemr_ui->oeContainer()); ?> mt-3">
582 <div class="row">
583 <div class="col-sm-12">
584 <?php echo $oemr_ui->pageHeading() . "\r\n"; ?>
585 </div>
586 </div>
587 <div class="hideaway">
588 <div>
589 <form class="form" name='the_form' method='post' action='billing_report.php' onsubmit='return top.restoreSession()'>
590 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
591 <input type='hidden' name='mode' value='change' />
592 <!-- Criteria section Starts -->
593 <?php
594 // TPS = This Page Search
595 // The following are the search criteria per page.All the following variable which ends with 'Master' need to be filled properly.
596 // Each item is seperated by a comma(,).
597 // $TPSCriteriaDisplayMaster ==>It is the display on screen for the set of criteria.
598 // $TPSCriteriaKeyMaster ==>Corresponding database fields in the same order.
599 // $TPSCriteriaDataTypeMaster ==>Corresponding data type in the same order.
600 $TPSCriteriaDisplayRadioMaster = array();
601 $TPSCriteriaRadioKeyMaster = array();
602 $TPSCriteriaQueryDropDownMaster = array();
603 $TPSCriteriaQueryDropDownMasterDefault = array();
604 $TPSCriteriaQueryDropDownMasterDefaultKey = array();
605 $TPSCriteriaIncludeMaster = array();
607 if ($daysheet) {
608 $TPSCriteriaDisplayMaster = array(
609 xl("Date of Service"),
610 xl("Date of Entry"),
611 xl("Date of Billing"),
612 xl("Claim Type"),
613 xl("Patient Name"),
614 xl("Patient Id"),
615 xl("Insurance Company"),
616 xl("Encounter"),
617 xl("Whether Insured"),
618 xl("Charge Coded"),
619 xl("Billing Status"),
620 xl("Authorization Status"),
621 xl("Last Level Billed"),
622 xl("X12 Partner"),
623 xl("User")
625 $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";
626 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down,text";
627 } else {
628 $TPSCriteriaDisplayMaster = array(
629 xl("Date of Service"),
630 xl("Date of Entry"),
631 xl("Date of Billing"),
632 xl("Claim Type"),
633 xl("Patient Name"),
634 xl("Patient Id"),
635 xl("Insurance Company"),
636 xl("Encounter"),
637 xl("Whether Insured"),
638 xl("Charge Coded"),
639 xl("Billing Status"),
640 xl("Authorization Status"),
641 xl("Last Level Billed"),
642 xl("X12 Partner")
644 $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";
645 $TPSCriteriaDataTypeMaster = "datetime,datetime,datetime,radio,text_like," . "text,include,text,radio,radio,radio," . "radio_like,radio,query_drop_down";
647 // The below section is needed if there is any 'radio' or 'radio_like' type in the $TPSCriteriaDataTypeMaster
648 // $TPSCriteriaDisplayRadioMaster,$TPSCriteriaRadioKeyMaster ==>For each radio data type this pair comes.
649 // 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.
650 $TPSCriteriaDisplayRadioMaster[1] = array(
651 xl("All"),
652 xl("eClaims"),
653 xl("Paper")
654 ); // Display Value
655 $TPSCriteriaRadioKeyMaster[1] = "all,standard,hcfa"; // Key
656 $TPSCriteriaDisplayRadioMaster[2] = array(
657 xl("All"),
658 xl("Insured"),
659 xl("Non-Insured")
660 ); // Display Value
661 $TPSCriteriaRadioKeyMaster[2] = "all,1,0"; // Key
662 $TPSCriteriaDisplayRadioMaster[3] = array(
663 xl("All"),
664 xl("Coded"),
665 xl("Not Coded")
666 ); // Display Value
667 $TPSCriteriaRadioKeyMaster[3] = "all,not null,null"; // Key
668 $TPSCriteriaDisplayRadioMaster[4] = array(
669 xl("All"),
670 xl("Unbilled"),
671 xl("Billed"),
672 xl("Denied")
673 ); // Display Value
674 $TPSCriteriaRadioKeyMaster[4] = "all,0,1,7"; // Key
675 $TPSCriteriaDisplayRadioMaster[5] = array(
676 xl("All"),
677 xl("Authorized"),
678 xl("Unauthorized")
680 $TPSCriteriaRadioKeyMaster[5] = "%,1,0";
681 $TPSCriteriaDisplayRadioMaster[6] = array(
682 xl("All"),
683 xl("None{{Insurance}}"),
684 xl("Ins 1"),
685 xl("Ins 2 or Ins 3")
687 $TPSCriteriaRadioKeyMaster[6] = "all,0,1,2";
688 // The below section is needed if there is any 'query_drop_down' type in the $TPSCriteriaDataTypeMaster
689 $TPSCriteriaQueryDropDownMaster[1] = "SELECT name,id FROM x12_partners;";
690 $TPSCriteriaQueryDropDownMasterDefault[1] = xl("All"); // Only one item will be here
691 $TPSCriteriaQueryDropDownMasterDefaultKey[1] = "all"; // Only one item will be here
692 // The below section is needed if there is any 'include' type in the $TPSCriteriaDataTypeMaster
693 // Function name is added here.Corresponding include files need to be included in the respective pages as done in this page.
694 // It is labled(Included for Insurance ajax criteria)(Line:-279-299).
695 $TPSCriteriaIncludeMaster[1] = "OpenEMR\Billing\BillingReport::insuranceCompanyDisplay";
696 if (!isset($_REQUEST['mode'])) {// default case
697 $_REQUEST['final_this_page_criteria'][0] = "form_encounter.date|between|" . date("Y-m-d 00:00:00") . "|" . date("Y-m-d 23:59:59");
698 $_REQUEST['final_this_page_criteria_text'][0] = xl("Date of Service = Today");
699 $_REQUEST['final_this_page_criteria'][1] = "billing.billed|=|0";
700 $_REQUEST['final_this_page_criteria_text'][1] = xl("Billing Status = Unbilled");
701 $_REQUEST['date_master_criteria_form_encounter_date'] = "today";
702 $_REQUEST['master_from_date_form_encounter_date'] = date("Y-m-d");
703 $_REQUEST['master_to_date_form_encounter_date'] = date("Y-m-d");
704 $_REQUEST['radio_billing_billed'] = 0;
705 $_REQUEST['query_drop_down_master_billing_x12_partner_id'] = "";
708 <?php
709 require_once "$srcdir/../interface/reports/criteria.tab.php";
711 <!-- end criteria -->
712 </form>
713 </div>
714 </div>
715 </div>
716 <div class="container-fluid mt-1">
717 <form class="form-inline" name='update_form' method='post' action='billing_process.php'>
718 <nav class="nav navbar-expand-md navbar-light bg-light px-3 py-2">
719 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#billing-nav-detail" aria-controls="" aria-expanded="false" aria-label="Actions">
720 <span><?php echo xlt('More Actions'); ?></span>
721 </button>
722 <!-- begin detail nav -->
723 <div class="collapse navbar-collapse clearfix" id="billing-nav-detail" role="group">
724 <div class="btn-group dropdown">
725 <button type="button" class="btn nav-link btn-link dropdown-toggle" data-toggle="dropdown" name="bn_x12_support" title=""><?php echo xla('X12 OPTIONS') ?>
726 <span class="caret"></span>
727 </button>
728 <ul class="dropdown-menu" role="menu">
729 <?php if (file_exists($EXPORT_INC)) { ?>
730 <li class="nav-item">
731 <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") ?>">
732 <?php echo xlt("Export Billing") ?>
733 </button>
734 </li>
735 <li class="nav-item">
736 <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') ?>">
737 <?php echo xlt("Mark as Cleared") ?>
738 </button>
739 </li>
740 <?php } else { ?>
741 <li class="nav-item">
742 <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') ?>">
743 <?php echo xlt('Generate X12') ?>
744 </button>
745 </li>
746 <?php } ?>
747 <?php if ($GLOBALS['ub04_support']) { ?>
748 <li class="nav-item">
749 <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') ?>">
750 <?php echo xlt('Generate X12 837I') ?>
751 </button>
752 </li>
753 <?php } ?>
754 <?php if ($GLOBALS['support_encounter_claims']) { ?>
755 <li class="nav-item">
756 <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') ?>">
757 <?php echo xlt('Generate X12 Encounter') ?>
758 </button>
759 </li>
760 <?php } ?>
761 </ul>
762 </div>
763 <div class="btn-group dropdown">
764 <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') ?>
765 <span class="caret"></span>
766 </button>
767 <ul class="dropdown-menu" role="menu">
768 <li class="nav-item">
769 <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') ?>">
770 <?php echo xlt('CMS 1500 PDF') ?>
771 </button>
772 </li>
773 <?php if ($GLOBALS['preprinted_cms_1500']) { ?>
774 <li class="nav-item">
775 <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') ?>">
776 <?php echo xlt('CMS 1500 Form') ?>
777 </button>
778 </li>
779 <?php } ?>
780 <li class="nav-item">
781 <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') ?>">
782 <?php echo xlt('CMS 1500 TEXT') ?>
783 </button>
784 </li>
785 </ul>
786 </div>
787 <?php if ($GLOBALS['ub04_support']) { ?>
788 <div class="btn-group dropdown">
789 <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') ?>
790 <span class="caret"></span>
791 </button>
792 <ul class="dropdown-menu" role="menu">
793 <li class="nav-item">
794 <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') ?>">
795 <?php echo xlt('UB04 FORM PDF') ?>
796 </button>
797 </li>
798 <li class="nav-item">
799 <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') ?>">
800 <?php echo xlt('UB04 TEXT PDF') ?>
801 </button>
802 </li>
803 </ul>
804 </div>
805 <?php } ?>
806 <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">
807 <?php echo xla('Mark as Cleared') ?>
808 </button>
809 <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">
810 <?php echo xlt('Re-Open') ?>
811 </button>
812 <span class="input-group">
813 <label for="left_margin"><?php echo xlt('CMS Margins Left'); ?>:</label>
814 <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'); ?>' />
815 <label for="top_margin"><?php echo xlt('Top'); ?>:</label>
816 <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'); ?>' />
817 </span>
818 <?php if ($ub04_support) { ?>
819 <span class="input-group">
820 <label for="left_ubmargin"><?php echo xlt('UB04 Margins Left'); ?>:</label>
821 <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'); ?>' />
822 <label for="top_ubmargin"><?php echo xlt('Top'); ?>:</label>
823 <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'); ?>' />
824 </span>
825 <?php } ?>
826 </div>
827 </nav>
828 <input type="hidden" name="csrf_token_form" value="<?php echo attr(CsrfUtils::collectCsrfToken()); ?>" />
829 <input name='mode' type='hidden' value="bill" />
830 <input name='authorized' type='hidden' value="<?php echo attr($my_authorized); ?>" />
831 <input name='unbilled' type='hidden' value="<?php echo attr($unbilled); ?>" />
832 <input name='code_type' type='hidden' value="%" />
833 <input name='to_date' type='hidden' value="<?php echo attr($to_date); ?>" />
834 <input name='from_date' type='hidden' value="<?php echo attr($from_date); ?>" />
835 <?php
836 if ($my_authorized == "on") {
837 $my_authorized = "1";
838 } else {
839 $my_authorized = "%";
841 if ($unbilled == "on") {
842 $unbilled = "0";
843 } else {
844 $unbilled = "%";
846 $list = BillingReport::getBillsListBetween("%");
847 // don't query the whole encounter table if no criteria selected
849 if (!isset($_POST["mode"])) {
850 if (!isset($_POST["from_date"])) {
851 $from_date = date("Y-m-d");
852 } else {
853 $from_date = $_POST["from_date"];
855 if (empty($_POST["to_date"])) {
856 $to_date = '';
857 } else {
858 $to_date = $_POST["to_date"];
860 if (!isset($_POST["code_type"])) {
861 $code_type = "all";
862 } else {
863 $code_type = $_POST["code_type"];
865 if (!isset($_POST["unbilled"])) {
866 $unbilled = "on";
867 } else {
868 $unbilled = $_POST["unbilled"];
870 if (!isset($_POST["authorized"])) {
871 $my_authorized = "on";
872 } else {
873 $my_authorized = $_POST["authorized"];
875 } else {
876 $from_date = $_POST["from_date"] ?? null;
877 $to_date = $_POST["to_date"] ?? null;
878 $code_type = $_POST["code_type"] ?? null;
879 $unbilled = $_POST["unbilled"] ?? null;
880 $my_authorized = $_POST["authorized"] ?? null;
883 if ($my_authorized == "on") {
884 $my_authorized = "1";
885 } else {
886 $my_authorized = "%";
889 if ($unbilled == "on") {
890 $unbilled = "0";
891 } else {
892 $unbilled = "%";
895 if (isset($_POST["mode"]) && $_POST["mode"] == "bill") {
896 billCodesList($list);
899 <div class="table-responsive">
900 <table class="table table-sm">
901 <?php
902 $divnos = 0;
903 if ($ret = BillingReport::getBillsBetween("%")) {
904 if (is_array($ret)) { ?>
905 <tr>
906 <td class="text-right" colspan='9'>
907 <table>
908 <tr>
909 <td id='expandAllCollapseAll'>
910 <div class="btn-group">
911 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('expand');">
912 <?php echo '(' . xlt('Expand All') . ')' ?>
913 </button>
914 <button type="button" class="btn btn-primary btn-sm" onclick="expandcollapse('collapse');">
915 <?php echo '(' . xlt('Collapse All') . ')' ?>
916 </button>
917 </div>
918 </td>
919 </tr>
920 </table>
921 </td>
922 </tr>
923 <?php } ?>
925 <?php
926 $loop = 0;
927 $oldcode = "";
928 $last_encounter_id = "";
929 $lhtml = "";
930 $rhtml = "";
931 $lcount = 0;
932 $rcount = 0;
933 $bgcolor = "var(--light)";
934 $skipping = false;
936 $mmo_empty_mod = false;
937 $mmo_num_charges = 0;
939 foreach ($ret as $iter) {
940 // We include encounters here that have never been billed. However
941 // if it had no selected billing items but does have non-selected
942 // billing items, then it is not of interest.
943 if (!$iter['id']) {
944 $res = sqlQuery(
945 "SELECT count(*) AS count FROM billing WHERE " .
946 "encounter = ? AND " .
947 "pid=? AND " .
948 "activity = 1",
949 array(
950 $iter['enc_encounter'],
951 $iter['enc_pid']
954 if ($res['count'] > 0) {
955 continue;
959 $this_encounter_id = $iter['enc_pid'] . "-" . $iter['enc_encounter'];
961 if ($last_encounter_id != $this_encounter_id) {
962 // This dumps all HTML for the previous encounter.
963 if ($lhtml) {
964 while ($rcount < $lcount) {
965 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
966 ++$rcount;
968 // This test handles the case where we are only listing encounters
969 // that appear to have a missing "25" modifier.
970 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
971 if ($DivPut == 'yes') {
972 $lhtml .= '</div>';
973 $DivPut = 'no';
975 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td class='align-top' rowspan='" . attr($rcount) . "'>\n$lhtml</td>$rhtml\n";
976 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n\n";
977 $encount = $encount ?? null;
978 ++$encount;
982 $lhtml = "";
983 $rhtml = "";
984 $mmo_empty_mod = false;
985 $mmo_num_charges = 0;
987 // If there are ANY unauthorized items in this encounter and this is
988 // the normal case of viewing only authorized billing, then skip the
989 // entire encounter.
990 $skipping = false;
991 if ($my_authorized == '1') {
992 $res = sqlQuery(
993 "SELECT count(*) AS count FROM billing WHERE " .
994 "encounter = ? AND " .
995 "pid=? AND " .
996 "activity = 1 AND authorized = 0",
997 array(
998 $iter['enc_encounter'],
999 $iter['enc_pid']
1002 if ($res['count'] > 0) {
1003 $skipping = true;
1004 $last_encounter_id = $this_encounter_id;
1005 continue;
1008 // Is there a MBO
1009 $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']));
1010 $iter['mboid'] = $mboid ? attr($mboid['form_id']) : 0;
1012 $name = getPatientData($iter['enc_pid'], "fname, mname, lname, pubpid, billing_note, DATE_FORMAT(DOB,'%Y-%m-%d') as DOB_YMD");
1014 // Check if patient has primary insurance and a subscriber exists for it.
1015 // If not we will highlight their name in red.
1016 // TBD: more checking here.
1017 $res = sqlQuery(
1018 "SELECT count(*) AS count FROM insurance_data WHERE " .
1019 "pid = ? AND " .
1020 "type='primary' AND " .
1021 "subscriber_lname IS NOT NULL AND " .
1022 "subscriber_lname != '' LIMIT 1",
1023 array(
1024 $iter['enc_pid']
1027 $namecolor = ($res['count'] > 0) ? "black" : "#ff7777";
1029 $bgcolor = ((($encount ?? null) & 1) ? "var(--light)" : "var(--gray300)");
1030 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1031 $lcount = 1;
1032 $rcount = 0;
1033 $oldcode = "";
1035 $ptname = $name['fname'] . " " . $name['lname'];
1036 $raw_encounter_date = date("Y-m-d", strtotime($iter['enc_date']));
1037 $billing_note = $name['billing_note'];
1038 // Add Encounter Date to display with "To Encounter" button 2/17/09 JCH
1039 $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>";
1041 // Encounter details are stored to javacript as array.
1042 $result4 = sqlStatement(
1043 "SELECT fe.encounter,fe.date,fe.billing_note,openemr_postcalendar_categories.pc_catname FROM form_encounter AS fe " .
1044 " LEFT JOIN openemr_postcalendar_categories ON fe.pc_catid=openemr_postcalendar_categories.pc_catid WHERE fe.pid = ? ORDER BY fe.date DESC",
1045 array(
1046 $iter['enc_pid']
1049 if (sqlNumRows($result4) > 0) {
1051 } ?>
1052 <script>
1053 Count = 0;
1054 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1055 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1056 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1057 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>] = new Array;
1058 <?php
1059 while ($rowresult4 = sqlFetchArray($result4)) {
1061 EncounterIdArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['encounter']); ?>;
1062 EncounterDateArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(oeFormatShortDate(date("Y-m-d", strtotime($rowresult4['date'])))); ?>;
1063 CalendarCategoryArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape(xl_appt_category($rowresult4['pc_catname'])); ?>;
1064 EncounterNoteArray[<?php echo attr($iter['enc_pid']); ?>][Count] = <?php echo js_escape($rowresult4['billing_note']); ?>;
1065 Count++;
1066 <?php
1067 $enc_billing_note[$rowresult4['encounter']] = $rowresult4['billing_note'];
1068 } ?>
1069 </script>
1070 <?php
1071 $lhtml .= "<div class='button-group'>";
1072 // Not sure why the next section seems to do nothing except post "To Encounter" button 2/17/09 JCH
1073 $lhtml .= "<a class='btn btn-sm btn-primary' role='button'" . "href='javascript:
1074 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'])) . ");
1075 top.window.parent.left_nav.setPatientEncounter(EncounterIdArray[" . attr($iter['enc_pid']) . "],EncounterDateArray[" . attr($iter['enc_pid']) . "], CalendarCategoryArray[" . attr($iter['enc_pid']) . "]);
1076 top.setEncounter(" . attr_js($iter['enc_encounter']) . ");
1077 '>" . xlt('Encounter') . " " . text(oeFormatShortDate($raw_encounter_date)) . "</a>";
1079 // Changed "To xxx" buttons to allow room for encounter date display 2/17/09 JCH
1080 $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'])) . ");
1081 top.window.parent.left_nav.setPatientEncounter(EncounterIdArray[" . attr($iter['enc_pid']) . "],EncounterDateArray[" . attr($iter['enc_pid']) . "], CalendarCategoryArray[" . attr($iter['enc_pid']) . "])\">" . xlt('Patient') . "</a>";
1082 $is_edited = $iter['mboid'] ? 'btn-success' : 'btn-secondary';
1083 $title = $iter['mboid'] ? xlt("This claim has HCFA 1500 miscellaneous billing options") : xlt("Click to add HCFA 1500 miscellaneous billing options");
1084 $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>";
1085 if ($ub04_support && isset($iter['billed'])) {
1086 $c = sqlQuery(
1087 "SELECT submitted_claim AS status FROM claims WHERE " .
1088 "encounter_id = ? AND " .
1089 "patient_id=? " .
1090 "ORDER BY version DESC LIMIT 1",
1091 array(
1092 $iter['enc_encounter'],
1093 $iter['enc_pid']
1096 $is_edited = ($c['status'] ?? null) ? 'btn-success' : 'btn-warning';
1097 $bname = ($c['status'] ?? null) ? xl('Reviewed') : xl('Review UB04');
1098 $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>";
1100 $lhtml .= "</div>";
1101 $divnos = $divnos + 1;
1102 $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>';
1103 if ($GLOBALS['notes_to_display_in_Billing'] == 2 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1104 $lhtml .= '<span class="font-weight-bold text-danger" style="margin-left: 20px;">' . text($billing_note) . '</span>';
1107 if ($iter['id']) {
1108 $lcount += 2;
1109 $lhtml .= "<br />\n";
1110 $lhtml .= "&nbsp;<span class='form-group'>" . xlt('Bill') . ": ";
1111 $lhtml .= "<select name='claims[" . attr($this_encounter_id) . "][payer]' onchange='onNewPayer(event)' class='form-control'>";
1113 $query = "SELECT id.provider AS id, id.type, id.date, " .
1114 "ic.x12_default_partner_id AS ic_x12id, ic.name AS provider " .
1115 "FROM insurance_data AS id, insurance_companies AS ic WHERE " .
1116 "ic.id = id.provider AND " .
1117 "id.pid = ? AND " .
1118 "(id.date <= ? OR id.date IS NULL) AND " .
1119 "(id.date_end >= ? OR id.date_end IS NULL) " .
1120 "ORDER BY id.type ASC, id.date DESC";
1122 $result = sqlStatement(
1123 $query,
1124 array(
1125 $iter['enc_pid'],
1126 $raw_encounter_date,
1127 $raw_encounter_date
1130 $count = 0;
1131 $default_x12_partner = $iter['ic_x12id'] ?? null;
1132 $prevtype = '';
1134 while ($row = sqlFetchArray($result)) {
1135 if (strcmp($row['type'], $prevtype) == 0) {
1136 continue;
1138 $prevtype = $row['type'];
1139 if (strlen($row['provider']) > 0) {
1140 // This preserves any existing insurance company selection, which is
1141 // important when EOB posting has re-queued for secondary billing.
1142 $lhtml .= "<option value=\"" . attr(substr($row['type'], 0, 1) . $row['id']) . "\"";
1143 if (($count == 0 && !$iter['payer_id']) || $row['id'] == $iter['payer_id']) {
1144 $lhtml .= " selected";
1145 if (!is_numeric($default_x12_partner)) {
1146 $default_x12_partner = $row['ic_x12id'];
1149 $lhtml .= " data-partner='" . attr($row['ic_x12id']) . "'>" . text($row['type']) . ": " . text($row['provider']) . "</option>";
1151 $count++;
1154 $lhtml .= "<option value='-1'>" . xlt("Unassigned") . "</option>\n";
1155 $lhtml .= "</select>&nbsp;&nbsp;\n";
1156 $lhtml .= "&nbsp;<span class='form-group'>X12: ";
1157 $lhtml .= "<select class='form-control' id='partners' name='claims[" . attr($this_encounter_id) . "][partner]'>";
1158 $lhtml .= "<option value='-1' label='Unassigned'>" . xlt("Partner not configured") . "</option>\n";
1159 foreach ($partners as $xid => $xname) {
1160 if (empty(trim($xname))) {
1161 continue;
1163 $lhtml .= '<option label="' . attr($xname) . '" value="' . attr($xid) . '"';
1164 if ($xid == $default_x12_partner) {
1165 $lhtml .= "selected";
1167 $lhtml .= '>' . text($xname) . '</option>';
1169 $lhtml .= "</select></span>";
1170 $DivPut = 'yes';
1172 if ($GLOBALS['notes_to_display_in_Billing'] == 1 || $GLOBALS['notes_to_display_in_Billing'] == 3) {
1173 $lhtml .= "<br /><span class='font-weight-bold text-success ml-3'>" . text($enc_billing_note[$iter['enc_encounter']]) . "</span>";
1175 $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");
1177 $query = "SELECT * FROM claims WHERE patient_id = ? AND encounter_id = ? ORDER BY version";
1178 $cres = sqlStatement(
1179 $query,
1180 array(
1181 $iter['enc_pid'],
1182 $iter['enc_encounter']
1186 $lastcrow = false;
1188 while ($crow = sqlFetchArray($cres)) {
1189 $query = "SELECT id.type, ic.name " .
1190 "FROM insurance_data AS id, insurance_companies AS ic WHERE " .
1191 "id.pid = ? AND " .
1192 "id.provider = ? AND " .
1193 "(id.date <= ? OR id.date IS NULL) AND " .
1194 "(id.date_end >= ? OR id.date_end IS NULL) AND " .
1195 "ic.id = id.provider " .
1196 "ORDER BY id.type ASC, id.date DESC";
1198 $irow = sqlQuery(
1199 $query,
1200 array(
1201 $iter['enc_pid'],
1202 $crow['payer_id'],
1203 $raw_encounter_date,
1204 $raw_encounter_date
1208 if ($crow['bill_process']) {
1209 $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'] ?? '');
1210 ++$lcount;
1211 } elseif ($crow['status'] < 6) {
1212 if ($crow['status'] > 1) {
1213 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Marked as cleared");
1214 ++$lcount;
1215 } else {
1216 $lhtml .= "<br />\n&nbsp;" . text(oeFormatShortDate(substr($crow['bill_time'], 0, 10))) . text(substr($crow['bill_time'], 10, 6)) . " " . xlt("Re-opened");
1217 ++$lcount;
1219 } elseif ($crow['status'] == 6) {
1220 $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.");
1221 ++$lcount;
1222 } elseif ($crow['status'] == 7) {
1223 $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:-");
1224 if ($crow['process_file']) {
1225 $code_array = explode(',', $crow['process_file']);
1226 foreach ($code_array as $code_key => $code_value) {
1227 $lhtml .= "<br />\n&nbsp;&nbsp;&nbsp;";
1228 $reason_array = explode('_', $code_value);
1229 if (!isset($adjustment_reasons[$reason_array[3]])) {
1230 $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]) . ']';
1231 } else {
1232 $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]]);
1235 } else {
1236 $lhtml .= xlt("Not Specified.");
1238 ++$lcount;
1241 if ($crow['process_time']) {
1242 $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>";
1243 ++$lcount;
1246 $lastcrow = $crow;
1247 } // end while ($crow = sqlFetchArray($cres))
1249 if ($lastcrow && $lastcrow['status'] == 4) {
1250 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been closed.");
1251 ++$lcount;
1254 if ($lastcrow && $lastcrow['status'] == 5) {
1255 $lhtml .= "<br />\n&nbsp;" . xlt("This claim has been canceled.");
1256 ++$lcount;
1258 } // end if ($iter['id'])
1259 } // end if ($last_encounter_id != $this_encounter_id)
1261 if ($skipping) {
1262 continue;
1265 // Collect info related to the missing modifiers test.
1266 if ($iter['fee'] > 0) {
1267 ++$mmo_num_charges;
1268 $tmp = substr($iter['code'], 0, 3);
1269 if (($tmp == '992' || $tmp == '993') && empty($iter['modifier'])) {
1270 $mmo_empty_mod = true;
1274 ++$rcount;
1276 if ($rhtml) {
1277 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1279 $rhtml .= "<td width='50'>";
1280 if ($iter['id'] && $oldcode != $iter['code_type']) {
1281 $rhtml .= "<span class='text'>" . text($iter['code_type']) . ": </span>";
1284 $oldcode = $iter['code_type'];
1285 $rhtml .= "</td>\n";
1286 $justify = "";
1288 if ($iter['id'] && !empty($code_types[$iter['code_type']]['just'])) {
1289 $js = explode(":", $iter['justify']);
1290 $counter = 0;
1291 foreach ($js as $j) {
1292 if (!empty($j)) {
1293 if ($counter == 0) {
1294 $justify .= " (<b>" . text($j) . "</b>)";
1295 } else {
1296 $justify .= " (" . text($j) . ")";
1298 $counter++;
1303 $rhtml .= "<td><span class='text'>" . ($iter['code_type'] == 'COPAY' ? text(oeFormatMoney($iter['code'])) : text($iter['code']));
1304 if ($iter['modifier']) {
1305 $rhtml .= ":" . text($iter['modifier']);
1307 $rhtml .= "</span><span style='font-size:8pt;'>$justify</span></td>\n";
1309 $rhtml .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1310 if ($iter['id'] && $iter['fee'] > 0) {
1311 $rhtml .= text(oeFormatMoney($iter['fee']));
1313 $rhtml .= "</span></td>\n";
1314 $rhtml .= '<td><span style="font-size:8pt; font-weight:900; background:#ffff9e">&nbsp;&nbsp;&nbsp;';
1315 if ($iter['id']) {
1316 $rhtml .= getProviderName(empty($iter['provider_id']) ? text($iter['enc_provider_id']) : text($iter['provider_id']));
1318 $rhtml .= "</span></td>\n";
1319 $rhtml .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1320 if ($GLOBALS['display_units_in_billing'] != 0) {
1321 if ($iter['id']) {
1322 $rhtml .= xlt("Units") . ":" . text($iter["units"]);
1325 $rhtml .= "</span></td>\n";
1326 $rhtml .= '<td width="100">&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1327 if ($iter['id']) {
1328 $rhtml .= text(oeFormatSDFT(strtotime($iter["date"])));
1330 $rhtml .= "</span></td>\n";
1331 // This error message is generated if the authorized check box is not checked
1332 if ($iter['id'] && $iter['authorized'] != 1) {
1333 $rhtml .= "<td><span class='alert'>" . xlt("Note: This code has not been authorized.") . "</span></td>\n";
1334 } else {
1335 $rhtml .= "<td></td>\n";
1337 if ($iter['id'] && $last_encounter_id != $this_encounter_id) {
1338 $tmpbpr = $iter['bill_process'];
1339 if ($tmpbpr == '0' && $iter['billed']) {
1340 $tmpbpr = '2';
1342 $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";
1343 $CheckBoxBilling = ($CheckBoxBilling ?? null) + 1;
1344 } else {
1345 $rhtml .= "<td></td>\n";
1347 if ($last_encounter_id != $this_encounter_id) {
1348 $rhtml2 = "";
1349 $rowcnt = 0;
1350 $resMoneyGot = sqlStatement(
1351 "SELECT pay_amount AS PatientPay,date(post_time) AS date FROM ar_activity WHERE " .
1352 "pid = ? AND encounter = ? AND deleted IS NULL AND payer_type = 0 AND account_code = 'PCP'",
1353 array(
1354 $iter['enc_pid'],
1355 $iter['enc_encounter']
1358 // new fees screen copay gives account_code='PCP'
1359 if (sqlNumRows($resMoneyGot) > 0) {
1360 $lcount += 2;
1361 $rcount++;
1363 // checks whether a copay exists for the encounter and if exists displays it.
1364 while ($rowMoneyGot = sqlFetchArray($resMoneyGot)) {
1365 $rowcnt++;
1366 $PatientPay = $rowMoneyGot['PatientPay'];
1367 $date = $rowMoneyGot['date'];
1368 if ($PatientPay > 0) {
1369 if ($rhtml) {
1370 $rhtml2 .= "<tr style='background-color: " . attr($bgcolor) . ";'>\n";
1372 $rhtml2 .= "<td width='50'>";
1373 $rhtml2 .= "<span class='text'>" . xlt('COPAY') . ": </span>";
1374 $rhtml2 .= "</td>\n";
1375 $rhtml2 .= "<td><span class='text'>" . text(oeFormatMoney($PatientPay)) . "</span><span style='font-size:8pt;'>&nbsp;</span></td>\n";
1376 $rhtml2 .= '<td align="right"><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1377 $rhtml2 .= "</span></td>\n";
1378 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1379 $rhtml2 .= "</span></td>\n";
1380 $rhtml2 .= '<td><span style="font-size:8pt;">&nbsp;&nbsp;&nbsp;';
1381 $rhtml2 .= "</span></td>\n";
1382 $rhtml2 .= '<td width=100>&nbsp;&nbsp;&nbsp;<span style="font-size:8pt;">';
1383 $rhtml2 .= text(oeFormatSDFT(strtotime($date)));
1384 $rhtml2 .= "</span></td>\n";
1385 if ($iter['id'] && $iter['authorized'] != 1) {
1386 $rhtml2 .= "<td><span class='alert'>" . xlt("Note: This copay was entered against billing that has not been authorized. Please review status.") . "</span></td>\n";
1387 } else {
1388 $rhtml2 .= "<td></td>\n";
1390 if (!$iter['id'] && $rowcnt == 1) {
1391 $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";
1392 $CheckBoxBilling++;
1393 } else {
1394 $rhtml2 .= "<td></td>\n";
1398 $rhtml .= $rhtml2;
1400 $rhtml .= "</tr>\n";
1401 $last_encounter_id = $this_encounter_id;
1402 } // end foreach
1404 if ($lhtml) {
1405 while ($rcount < $lcount) {
1406 $rhtml .= "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9'></td></tr>";
1407 ++$rcount;
1409 if (!$missing_mods_only || ($mmo_empty_mod && $mmo_num_charges > 1)) {
1410 if ($DivPut == 'yes') {
1411 $lhtml .= '</div>';
1412 $DivPut = 'no';
1414 echo "<tr style='background-color: " . attr($bgcolor) . ";'>\n<td rowspan='" . attr($rcount) . "' valign='top' width='25%'>\n$lhtml</td>$rhtml\n";
1415 echo "<tr style='background-color: " . attr($bgcolor) . ";'><td colspan='9' height='5'></td></tr>\n";
1422 </table>
1423 </div>
1424 </form>
1426 </div>
1427 <!--end of container div -->
1428 <?php $oemr_ui->oeBelowContainerDiv(); ?>
1429 <script>
1430 set_button_states();
1431 <?php
1432 if ($alertmsg) {
1433 echo "alert(" . js_escape($alertmsg) . ");\n";
1436 $(function () {
1437 $("#view-log-link").click(function() {
1438 top.restoreSession();
1439 dlgopen('customize_log.php', '_blank', 750, 400);
1441 $("#clear-log").click(function() {
1442 var checkstr = confirm(<?php echo xlj("Do you really want to clear the log?"); ?>);
1443 if (checkstr == true) {
1444 top.restoreSession();
1445 dlgopen("clear_log.php?csrf_token_form=" + <?php echo js_escape(CsrfUtils::collectCsrfToken()); ?>, '_blank', 500, 400);
1446 } else {
1447 return false;
1451 $('button[type="submit"]').click(function() {
1452 top.restoreSession();
1453 $(this).attr('data-clicked', true);
1456 $('form[name="update_form"]').on('submit', function(e) {
1457 var clickedButton = $("button[type=submit][data-clicked='true'")[0];
1458 // clear clicked button indicator
1459 $('button[type="submit"]').attr('data-clicked', false);
1461 if (!clickedButton || $(clickedButton).attr("data-open-popup") !== "true") {
1462 $(this).removeAttr("target");
1463 return top.restoreSession();
1464 } else {
1465 top.restoreSession();
1466 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');
1467 this.target = 'Popup_Window';
1471 $('.datepicker').datetimepicker({
1472 <?php $datetimepicker_timepicker = false; ?>
1473 <?php $datetimepicker_showseconds = false; ?>
1474 <?php $datetimepicker_formatInput = false; ?>
1475 <?php require $GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'; ?>
1476 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
1478 // jquery-ui tooltip converted to bootstrap tooltip
1479 $('#update-tooltip').attr("title", <?php echo xlj('Click Update List to display billing information filtered by the selected Current Criteria'); ?>).tooltip();
1481 </script>
1482 <input type="hidden" name="divnos" id="divnos" value="<?php echo attr($divnos ?? '') ?>" />
1483 <input type='hidden' name='ajax_mode' id='ajax_mode' value='' />
1484 </body>
1486 </html>