Improvements mostly concerning inventory.
[openemr.git] / interface / forms / LBF / new.php
blobb1248563907258a6f33197467b682b3e37795cb8
1 <?php
3 /**
4 * LBF form.
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Rod Roark <rod@sunsetsystems.com>
9 * @author Brady Miller <brady.g.miller@gmail.com>
10 * @author Jerry Padgett <sjpadgett@gmail.com>
11 * @copyright Copyright (c) 2009-2021 Rod Roark <rod@sunsetsystems.com>
12 * @copyright Copyright (c) 2019 Brady Miller <brady.g.miller@gmail.com>
13 * @copyright Copyright (c) 2018-2020 Jerry Padgett <sjpadgett@gmail.com>
14 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
17 if (isset($_GET['isPortal']) && (int)$_GET['isPortal'] !== 0) {
18 require_once(__DIR__ . "/../../../src/Common/Session/SessionUtil.php");
19 OpenEMR\Common\Session\SessionUtil::portalSessionStart();
20 if (isset($_SESSION['pid']) && isset($_SESSION['patient_portal_onsite_two'])) {
21 $ignoreAuth_onsite_portal = true;
22 } else {
23 OpenEMR\Common\Session\SessionUtil::portalSessionCookieDestroy();
24 exit;
28 require_once("../../globals.php");
29 require_once("$srcdir/api.inc");
30 require_once("$srcdir/forms.inc");
31 require_once("$srcdir/options.inc.php");
32 require_once("$srcdir/patient.inc");
33 require_once($GLOBALS['fileroot'] . '/custom/code_types.inc.php');
34 require_once("$srcdir/FeeSheetHtml.class.php");
36 use OpenEMR\Common\Acl\AclMain;
37 use OpenEMR\Common\Csrf\CsrfUtils;
38 use OpenEMR\Core\Header;
40 $CPR = 4; // cells per row
42 $pprow = array();
44 $alertmsg = '';
46 function end_cell()
48 global $item_count, $cell_count, $historical_ids;
49 if ($item_count > 0) {
50 // echo "&nbsp;</td>";
51 echo "</td>";
53 foreach ($historical_ids as $key => $dummy) {
54 // $historical_ids[$key] .= "&nbsp;</td>";
55 $historical_ids[$key] .= "</td>";
58 $item_count = 0;
62 function end_row()
64 global $cell_count, $CPR, $historical_ids;
65 end_cell();
66 if ($cell_count > 0) {
67 for (; $cell_count < $CPR; ++$cell_count) {
68 echo "<td class='border-top-0'></td>";
69 foreach ($historical_ids as $key => $dummy) {
70 $historical_ids[$key] .= "<td class='border-top-0'></td>";
74 foreach ($historical_ids as $key => $dummy) {
75 echo $historical_ids[$key];
78 echo "</tr>\n";
79 $cell_count = 0;
83 // $is_lbf is defined in trend_form.php and indicates that we are being
84 // invoked from there; in that case the current encounter is irrelevant.
85 $from_trend_form = !empty($is_lbf);
86 // Yet another invocation from somewhere other than encounter.
87 // don't show any action buttons.
88 $from_lbf_edit = isset($_GET['isShow']) ? 1 : 0;
89 $patient_portal = $ignoreAuth_onsite_portal ? 1 : 0;
90 $from_lbf_edit = $patient_portal ? 1 : $from_lbf_edit;
91 // This is true if the page is loaded into an iframe in add_edit_issue.php.
92 $from_issue_form = !empty($_REQUEST['from_issue_form']);
94 $formname = isset($_GET['formname']) ? $_GET['formname'] : '';
95 $formid = isset($_GET['id']) ? (int)$_GET['id'] : 0;
96 $portalid = isset($_GET['portalid']) ? (int)$_GET['portalid'] : 0;
97 // know LBF origin
98 $form_origin = isset($_GET['formOrigin']) ? (int)$_GET['formOrigin'] : null;
99 $is_portal_module = $form_origin === 2;
100 $is_portal_dashboard = $form_origin === 1; // 0 is portal
101 // can be used to assign to existing encounter
102 $portal_form_pid = 0;
103 if ($form_origin !== null) {
104 $portal_form_pid = sqlQuery(
105 "SELECT id, pid FROM `onsite_documents` WHERE `encounter` != 0 AND `encounter` = ?",
106 array($formid)
107 )['pid'] ?? 0;
109 $is_core = !($portal_form_pid || $patient_portal || $is_portal_dashboard || $is_portal_module);
111 $visitid = (int)(empty($_GET['visitid']) ? $encounter : $_GET['visitid']);
113 // If necessary get the encounter from the forms table entry for this form.
114 if ($formid && !$visitid && $is_core) {
115 $frow = sqlQuery(
116 "SELECT pid, encounter FROM forms WHERE " .
117 "form_id = ? AND formdir = ? AND deleted = 0",
118 array($formid, $formname)
120 $visitid = (int)$frow['encounter'];
121 if ($frow['pid'] != $pid) {
122 die("Internal error: patient ID mismatch!");
126 if (!$from_trend_form && !$visitid && !$from_lbf_edit && $is_core) {
127 die("Internal error: we do not seem to be in an encounter!");
130 $grparr = array();
131 getLayoutProperties($formname, $grparr, '*');
132 $lobj = $grparr[''];
133 $formtitle = $lobj['grp_title'];
134 $formhistory = 0 + $lobj['grp_repeats'];
135 $grp_last_update = $lobj['grp_last_update'];
137 if (!empty($lobj['grp_columns'])) {
138 $CPR = (int)$lobj['grp_columns'];
140 if (!empty($lobj['grp_size'])) {
141 $FONTSIZE = (int)$lobj['grp_size'];
143 if (!empty($lobj['grp_issue_type'])) {
144 $LBF_ISSUE_TYPE = $lobj['grp_issue_type'];
146 if (!empty($lobj['grp_aco_spec'])) {
147 $LBF_ACO = explode('|', $lobj['grp_aco_spec']);
149 if ($lobj['grp_services']) {
150 $LBF_SERVICES_SECTION = $lobj['grp_services'] == '*' ? '' : $lobj['grp_services'];
152 if ($lobj['grp_products']) {
153 $LBF_PRODUCTS_SECTION = $lobj['grp_products'] == '*' ? '' : $lobj['grp_products'];
155 if ($lobj['grp_diags']) {
156 $LBF_DIAGS_SECTION = $lobj['grp_diags'] == '*' ? '' : $lobj['grp_diags'];
159 $LBF_REFERRALS_SECTION = !empty($lobj['grp_referrals']);
161 $LBF_SECTION_DISPLAY_STYLE = $lobj['grp_init_open'] ? 'block' : 'none';
163 // $LBF_ENABLE_SAVE_CLOSE = !empty($lobj['grp_save_close']);
164 $LBF_ENABLE_SAVE_CLOSE = !empty($GLOBALS['gbl_form_save_close']);
166 // Check access control.
167 if (!AclMain::aclCheckCore('admin', 'super') && !empty($LBF_ACO)) {
168 $auth_aco_write = AclMain::aclCheckCore($LBF_ACO[0], $LBF_ACO[1], '', 'write');
169 $auth_aco_addonly = AclMain::aclCheckCore($LBF_ACO[0], $LBF_ACO[1], '', 'addonly');
170 // echo "\n<!-- '$auth_aco_write' '$auth_aco_addonly' -->\n"; // debugging
171 if (!$auth_aco_write && !($auth_aco_addonly && !$formid)) {
172 die(xlt('Access denied'));
176 if (isset($LBF_SERVICES_SECTION) || isset($LBF_PRODUCTS_SECTION) || isset($LBF_DIAGS_SECTION)) {
177 $fs = new FeeSheetHtml($pid, $visitid);
180 if (!$from_trend_form) {
181 $fname = $GLOBALS['OE_SITE_DIR'] . "/LBF/$formname.plugin.php";
182 if (file_exists($fname)) {
183 include_once($fname);
187 // If Save was clicked, save the info.
189 if (
190 !empty($_POST['bn_save']) ||
191 !empty($_POST['bn_save_print']) ||
192 !empty($_POST['bn_save_continue']) ||
193 !empty($_POST['bn_save_checkout']) ||
194 !empty($_POST['bn_save_close'])
196 $newid = 0;
197 if (!$formid) {
198 // Creating a new form. Get the new form_id by inserting and deleting a dummy row.
199 // This is necessary to create the form instance even if it has no native data.
200 $newid = sqlInsert("INSERT INTO lbf_data " .
201 "( field_id, field_value ) VALUES ( '', '' )");
202 sqlStatement("DELETE FROM lbf_data WHERE form_id = ? AND " .
203 "field_id = ''", array($newid));
204 addForm($visitid, $formtitle, $newid, $formname, $pid, $userauthorized);
207 $my_form_id = $formid ? $formid : $newid;
209 // If there is an issue ID, update it in the forms table entry.
210 if (isset($_POST['form_issue_id'])) {
211 sqlStatement(
212 "UPDATE forms SET issue_id = ? WHERE formdir = ? AND form_id = ? AND deleted = 0",
213 array($_POST['form_issue_id'], $formname, $my_form_id)
217 // If there is a provider ID, update it in the forms table entry.
218 if (isset($_POST['form_provider_id'])) {
219 sqlStatement(
220 "UPDATE forms SET provider_id = ? WHERE formdir = ? AND form_id = ? AND deleted = 0",
221 array($_POST['form_provider_id'], $formname, $my_form_id)
225 $sets = "";
226 $fres = sqlStatement("SELECT * FROM layout_options " .
227 "WHERE form_id = ? AND uor > 0 AND field_id != '' AND " .
228 "edit_options != 'H' AND edit_options NOT LIKE '%0%' " .
229 "ORDER BY group_id, seq", array($formname));
230 while ($frow = sqlFetchArray($fres)) {
231 $field_id = $frow['field_id'];
232 $data_type = $frow['data_type'];
233 // If the field was not in the web form, skip it.
234 // Except if it's checkboxes, if unchecked they are not returned.
236 // if ($data_type != 21 && !isset($_POST["form_$field_id"])) continue;
238 // The above statement commented out 2015-01-12 because a LBF plugin might conditionally
239 // disable a field that is not applicable, and we need the ability to clear out the old
240 // garbage in there so it does not show up in the "report" view of the data. So we will
241 // trust that it's OK to clear any field that is defined in the layout but not returned
242 // by the form.
244 if ($data_type == 31) {
245 continue; // skip static text fields
247 $value = get_layout_form_value($frow);
248 // If edit option P or Q, save to the appropriate different table and skip the rest.
249 $source = $frow['source'];
250 if ($source == 'D' || $source == 'H') {
251 // Save to patient_data, employer_data or history_data.
252 if ($source == 'H') {
253 $new = array($field_id => $value);
254 updateHistoryData($pid, $new);
255 } elseif (strpos($field_id, 'em_') === 0) {
256 $field_id = substr($field_id, 3);
257 $new = array($field_id => $value);
258 updateEmployerData($pid, $new);
259 } else {
260 $esc_field_id = escape_sql_column_name($field_id, array('patient_data'));
261 sqlStatement(
262 "UPDATE patient_data SET `$esc_field_id` = ? WHERE pid = ?",
263 array($value, $pid)
267 continue;
268 } elseif ($source == 'E') {
269 // Save to shared_attributes. Can't delete entries for empty fields because with the P option
270 // it's important to know when a current empty value overrides a previous value.
271 sqlStatement(
272 "REPLACE INTO shared_attributes SET " .
273 "pid = ?, encounter = ?, field_id = ?, last_update = NOW(), " .
274 "user_id = ?, field_value = ?",
275 array($pid, $visitid, $field_id, $_SESSION['authUserID'], $value)
277 continue;
278 } elseif ($source == 'V') {
279 // Save to form_encounter.
280 $esc_field_id = escape_sql_column_name($field_id, array('form_encounter'));
281 sqlStatement(
282 "UPDATE form_encounter SET `$esc_field_id` = ? WHERE " .
283 "pid = ? AND encounter = ?",
284 array($value, $pid, $visitid)
286 continue;
289 // It's a normal form field, save to lbf_data.
290 if ($formid) { // existing form
291 if ($value === '') {
292 $query = "DELETE FROM lbf_data WHERE " .
293 "form_id = ? AND field_id = ?";
294 sqlStatement($query, array($formid, $field_id));
295 } else {
296 $query = "REPLACE INTO lbf_data SET field_value = ?, " .
297 "form_id = ?, field_id = ?";
298 sqlStatement($query, array($value, $formid, $field_id));
300 } else { // new form
301 if ($value !== '') {
302 sqlStatement(
303 "INSERT INTO lbf_data " .
304 "( form_id, field_id, field_value ) VALUES ( ?, ?, ? )",
305 array($newid, $field_id, $value)
309 } // end while save
311 if ($portalid) {
312 // Delete the request from the portal.
313 $result = cms_portal_call(array('action' => 'delpost', 'postid' => $portalid));
314 if ($result['errmsg']) {
315 die(text($result['errmsg']));
319 if (isset($fs)) {
320 $bill = is_array($_POST['form_fs_bill']) ? $_POST['form_fs_bill'] : null;
321 $prod = is_array($_POST['form_fs_prod']) ? $_POST['form_fs_prod'] : null;
322 $alertmsg = $fs->checkInventory($prod);
323 // If there is an inventory error then no services or products will be saved, and
324 // the form will be redisplayed with an error alert and everything else saved.
325 if (!$alertmsg) {
326 $fs->save($bill, $prod, null, null);
327 $fs->updatePriceLevel($_POST['form_fs_pricelevel']);
331 if (!$alertmsg && !empty($_POST['bn_save_close'])) {
332 $alertmsg = FeeSheet::closeVisit($pid, $visitid);
335 if (!$formid) {
336 $formid = $newid;
339 if (!$alertmsg && !$from_issue_form && empty($_POST['bn_save_continue'])) {
340 // Support custom behavior at save time, such as going to another form.
341 if (function_exists($formname . '_save_exit')) {
342 if (call_user_func($formname . '_save_exit')) {
343 exit;
346 formHeader("Redirecting....");
347 // If Save and Print, write the JavaScript to open a window for printing.
348 if (!empty($_POST['bn_save_print'])) {
349 echo "<script>\n" .
350 "top.restoreSession();\n" .
351 "window.open('$rootdir/forms/LBF/printable.php?" .
352 "formname=" . attr_url($formname) .
353 "&formid=" . attr_url($formid) .
354 "&visitid=" . attr_url($visitid) .
355 "&patientid=" . attr_url($pid) .
356 "', '_blank');\n" .
357 "</script>\n";
359 formJump();
360 formFooter();
361 exit;
364 // For portal and documents templates we need a fluid container.
365 // default container.
366 $form_container = "container";
367 if (empty($is_core)) {
368 $form_container = "container-fluid";
371 <html>
372 <head>
373 <?php Header::setupHeader(['opener', 'common', 'datetime-picker', 'select2']); ?>
375 <style>
377 div.section {
378 border: 1px solid var(--primary);
379 margin: 0 0 0 0.8125rem;
380 padding: 0.4375rem;
383 .RS {
384 border-style: solid;
385 border-width: 0 0 1px 0;
386 border-color: var(--gray600);
389 .RO {
390 border-width: 1px solid var(--gray600) !important;
393 .linkcolor {
394 color:blue;
397 </style>
399 <?php include_once("{$GLOBALS['srcdir']}/options.js.php"); ?>
401 <!-- LiterallyCanvas support -->
402 <?php echo lbf_canvas_head(); ?>
403 <?php echo signer_head(); ?>
405 <script>
407 // Support for beforeunload handler.
408 var somethingChanged = false;
410 function verifyCancel() {
411 if (somethingChanged) {
412 if (!confirm(<?php echo xlj('You have unsaved changes. Do you really want to close this form?'); ?>)) {
413 return false;
416 somethingChanged = false;
417 parent.closeTab(window.name, false);
420 $(function () {
422 if (window.tabbify) {
423 tabbify();
425 if (window.checkSkipConditions) {
426 checkSkipConditions();
429 $(".select-dropdown").select2({
430 theme: "bootstrap4",
431 <?php require($GLOBALS['srcdir'] . '/js/xl/select2.js.php'); ?>
433 if (typeof error !== 'undefined') {
434 if (error) {
435 alertMsg(error);
439 $(".iframe_medium").on('click', function (e) {
440 e.preventDefault();
441 e.stopPropagation();
442 let url = $(this).attr('href');
443 url = encodeURI(url);
444 dlgopen('', '', 950, 550, '', '', {
445 buttons: [
446 {text: <?php echo xlj('Close'); ?>, close: true, style: 'default btn-sm'}
448 type: 'iframe',
449 url: url
453 // Support for beforeunload handler.
454 $('.lbfdata input, .lbfdata select, .lbfdata textarea').change(function () {
455 somethingChanged = true;
457 window.addEventListener("beforeunload", function (e) {
458 if (somethingChanged && !top.timed_out) {
459 var msg = <?php echo xlj('You have unsaved changes.'); ?>;
460 e.returnValue = msg; // Gecko, Trident, Chrome 34+
461 return msg; // Gecko, WebKit, Chrome <34
465 $('.datepicker').datetimepicker({
466 <?php $datetimepicker_timepicker = false; ?>
467 <?php $datetimepicker_showseconds = false; ?>
468 <?php $datetimepicker_formatInput = true; ?>
469 <?php $datetimepicker_minDate = false; ?>
470 <?php $datetimepicker_maxDate = false; ?>
471 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
472 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
474 $('.datetimepicker').datetimepicker({
475 <?php $datetimepicker_timepicker = true; ?>
476 <?php $datetimepicker_showseconds = false; ?>
477 <?php $datetimepicker_formatInput = true; ?>
478 <?php $datetimepicker_minDate = false; ?>
479 <?php $datetimepicker_maxDate = false; ?>
480 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
481 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
483 $('.datepicker-past').datetimepicker({
484 <?php $datetimepicker_timepicker = false; ?>
485 <?php $datetimepicker_showseconds = false; ?>
486 <?php $datetimepicker_formatInput = true; ?>
487 <?php $datetimepicker_minDate = false; ?>
488 <?php $datetimepicker_maxDate = '+1970/01/01'; ?>
489 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
490 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
492 $('.datetimepicker-past').datetimepicker({
493 <?php $datetimepicker_timepicker = true; ?>
494 <?php $datetimepicker_showseconds = false; ?>
495 <?php $datetimepicker_formatInput = true; ?>
496 <?php $datetimepicker_minDate = false; ?>
497 <?php $datetimepicker_maxDate = '+1970/01/01'; ?>
498 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
499 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
501 $('.datepicker-future').datetimepicker({
502 <?php $datetimepicker_timepicker = false; ?>
503 <?php $datetimepicker_showseconds = false; ?>
504 <?php $datetimepicker_formatInput = true; ?>
505 <?php $datetimepicker_minDate = '-1970/01/01'; ?>
506 <?php $datetimepicker_maxDate = false; ?>
507 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
508 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
510 $('.datetimepicker-future').datetimepicker({
511 <?php $datetimepicker_timepicker = true; ?>
512 <?php $datetimepicker_showseconds = false; ?>
513 <?php $datetimepicker_formatInput = true; ?>
514 <?php $datetimepicker_minDate = '-1970/01/01'; ?>
515 <?php $datetimepicker_maxDate = false; ?>
516 <?php require($GLOBALS['srcdir'] . '/js/xl/jquery-datetimepicker-2-5-4.js.php'); ?>
517 <?php // can add any additional javascript settings to datetimepicker here; need to prepend first setting with a comma ?>
521 var mypcc = <?php echo js_escape($GLOBALS['phone_country_code']); ?>;
523 // Supports customizable forms.
524 function divclick(cb, divid) {
525 var divstyle = document.getElementById(divid).style;
526 if (cb.checked) {
527 divstyle.display = 'block';
528 } else {
529 divstyle.display = 'none';
531 return true;
534 // The ID of the input element to receive a found code.
535 var current_sel_name = '';
537 // This is for callback by the find-code popup.
538 // Appends to or erases the current list of related codes.
539 function set_related(codetype, code, selector, codedesc) {
540 var f = document.forms[0];
541 <?php if (isset($fs)) { ?>
542 // This is the case of selecting a code for the Fee Sheet:
543 if (!current_sel_name) {
544 if (code) {
545 $.getScript('<?php echo $GLOBALS['web_root'] ?>/library/ajax/code_attributes_ajax.php' +
546 '?codetype=' + encodeURIComponent(codetype) +
547 '&code=' + encodeURIComponent(code) +
548 '&selector=' + encodeURIComponent(selector) +
549 '&pricelevel=' + encodeURIComponent(f.form_fs_pricelevel ? f.form_fs_pricelevel.value : "") +
550 '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>);
552 return '';
554 <?php } ?>
555 // frc will be the input element containing the codes.
556 // frcd, if set, will be the input element containing their descriptions.
557 var frc = f[current_sel_name];
558 var frcd;
559 var matches = current_sel_name.match(/^(.*)__desc$/);
560 if (matches) {
561 frcd = frc;
562 frc = f[matches[1]];
564 // Allow only one code in a field unless edit option E is present.
565 var s = '';
566 var sd = '';
567 if ((' ' + frc.className + ' ').indexOf(' EditOptionE ') > -1) {
568 s = frc.value;
569 sd = frcd ? frcd.value : s;
572 if (code) {
573 if (s.length > 0) {
574 s += ';';
575 sd += ';';
577 s += codetype + ':' + code;
578 sd += codedesc;
579 } else {
580 s = '';
581 sd = '';
583 frc.value = s;
584 if (frcd) frcd.value = sd;
585 return '';
588 // This invokes the "dynamic" find-code popup.
589 function sel_related(elem, codetype) {
590 current_sel_name = elem ? elem.name : '';
591 var url = '<?php echo $rootdir ?>/patient_file/encounter/find_code_dynamic.php';
592 if (codetype) url += '?codetype=' + encodeURIComponent(codetype);
593 dlgopen(url, '_blank', 800, 500);
596 // Compute the length of a string without leading and trailing spaces.
597 function trimlen(s) {
598 var i = 0;
599 var j = s.length - 1;
600 for (; i <= j && s.charAt(i) == ' '; ++i) ;
601 for (; i <= j && s.charAt(j) == ' '; --j) ;
602 if (i > j) return 0;
603 return j + 1 - i;
606 // This capitalizes the first letter of each word in the passed input
607 // element. It also strips out extraneous spaces.
608 function capitalizeMe(elem) {
609 var a = elem.value.split(' ');
610 var s = '';
611 for (var i = 0; i < a.length; ++i) {
612 if (a[i].length > 0) {
613 if (s.length > 0) s += ' ';
614 s += a[i].charAt(0).toUpperCase() + a[i].substring(1);
617 elem.value = s;
620 // Validation logic for form submission.
621 // Added prevent restoreSession for remotes
622 var submitButtonName = '';
623 function validate(f, restore = true) {
624 var errMsgs = new Array();
625 <?php generate_layout_validation($formname); ?>
626 // Validation for Fee Sheet stuff. Skipping this because CV decided (2015-11-03)
627 // that these warning messages are not appropriate for layout based visit forms.
629 // if (window.jsLineItemValidation && !jsLineItemValidation(f)) return false;
631 if (submitButtonName == 'bn_save_close') {
632 // For "Save and Close Visit" we check for unsaved form data in the sibling iframes.
633 for (var i = 0; i < parent.frames.length; ++i) {
634 var w = parent.frames[i];
635 var tmpId = w.name;
636 if (tmpId.indexOf('enctabs-') == 0 && tmpId != window.name) {
637 if (typeof w.somethingChanged !== 'undefined' && w.somethingChanged) {
638 alert(<?php echo xlj('Hold on! You have unsaved changes in another form. Please just Save this form and then complete the other one.'); ?>);
639 return false;
645 somethingChanged = false; // turn off "are you sure you want to leave"
646 if (restore) {
647 top.restoreSession();
650 return true;
653 // Called to open the data entry form of a specified encounter form instance.
654 // TBD: Move this to TabsWrapper.class.php.
655 function openLBFEncounterForm(formdir, formname, formid) {
656 top.restoreSession();
657 var url = '<?php echo "$rootdir/patient_file/encounter/view_form.php?formname=" ?>' +
658 encodeURIComponent(formdir) + '&id=' + encodeURIComponent(formid);
659 parent.twAddFrameTab('enctabs', formname, url);
660 return false;
663 function openLBFNewForm(formdir, formname) {
664 top.restoreSession();
665 var url = '<?php echo "$rootdir/patient_file/encounter/load_form.php?formname=" ?>' +
666 encodeURIComponent(formdir);
667 parent.twAddFrameTab('enctabs', formname, url);
670 <?php
671 if (isset($fs)) {
672 // jsLineItemValidation() function for the fee sheet stuff.
673 echo $fs->jsLineItemValidation('form_fs_bill', 'form_fs_prod');
676 // Add a service line item.
677 function fs_append_service(code_type, code, desc, price) {
678 var telem = document.getElementById('fs_services_table');
679 var lino = telem.rows.length - 1;
680 var trelem = telem.insertRow(telem.rows.length);
681 trelem.innerHTML =
682 "<td class='text border-top-0'>" + code + "&nbsp;</td>" +
683 "<td class='text border-top-0'>" + desc + "&nbsp;</td>" +
684 "<td class='text border-top-0'>" +
685 "<select class='form-control' name='form_fs_bill[" + lino + "][provid]'>" +
686 "<?php echo addslashes($fs->genProviderOptionList('-- ' . xl('Default') . ' --')) ?>" +
687 "</select>&nbsp;" +
688 "</td>" +
689 "<td class='text border-top-0 text-right'>" + price + "&nbsp;</td>" +
690 "<td class='text border-top-0 text-right'>" +
691 "<input type='checkbox' name='form_fs_bill[" + lino + "][del]' value='1' />" +
692 "<input type='hidden' name='form_fs_bill[" + lino + "][code_type]' value='" + code_type + "' />" +
693 "<input type='hidden' name='form_fs_bill[" + lino + "][code]' value='" + code + "' />" +
694 "<input type='hidden' name='form_fs_bill[" + lino + "][price]' value='" + price + "' />" +
695 "</td>";
698 // Add a product line item.
699 function fs_append_product(code_type, code, desc, price, warehouses) {
700 var telem = document.getElementById('fs_products_table');
701 if (!telem) {
702 alert(<?php echo xlj('A product was selected but there is no product section in this form.'); ?>);
703 return;
705 var lino = telem.rows.length - 1;
706 var trelem = telem.insertRow(telem.rows.length);
707 trelem.innerHTML =
708 "<td class='text border-top-0'>" + desc + "&nbsp;</td>" +
709 "<td class='text border-top-0'>" +
710 "<select class='form-control' name='form_fs_prod[" + lino + "][warehouse]'>" + warehouses + "</select>&nbsp;" +
711 "</td>" +
712 "<td class='text border-top-0 text-right'>" +
713 "<input type='text' class='form-control' name='form_fs_prod[" + lino + "][units]' size='3' value='1' />&nbsp;" +
714 "</td>" +
715 "<td class='text border-top-0 text-right'>" + price + "&nbsp;</td>" +
716 "<td class='text border-top-0 text-right'>" +
717 "<input type='checkbox' name='form_fs_prod[" + lino + "][del]' value='1' />" +
718 "<input type='hidden' name='form_fs_prod[" + lino + "][drug_id]' value='" + code + "' />" +
719 "<input type='hidden' name='form_fs_prod[" + lino + "][price]' value='" + price + "' />" +
720 "</td>";
723 // Add a diagnosis line item.
724 function fs_append_diag(code_type, code, desc) {
725 var telem = document.getElementById('fs_diags_table');
726 // Adding 1000 because form_fs_bill[] is shared with services and we want to avoid collisions.
727 var lino = telem.rows.length - 1 + 1000;
728 var trelem = telem.insertRow(telem.rows.length);
729 trelem.innerHTML =
730 "<td class='text border-top-0'>" + code + "&nbsp;</td>" +
731 "<td class='text border-top-0'>" + desc + "&nbsp;</td>" +
732 "<td class='text border-top-0 text-right'>" +
733 "<input type='checkbox' name='form_fs_bill[" + lino + "][del]' value='1' />" +
734 "<input type='hidden' name='form_fs_bill[" + lino + "][code_type]' value='" + code_type + "' />" +
735 "<input type='hidden' name='form_fs_bill[" + lino + "][code]' value='" + code + "' />" +
736 "<input type='hidden' name='form_fs_bill[" + lino + "][price]' value='" + 0 + "' />" +
737 "</td>";
740 // Respond to clicking a checkbox for adding (or removing) a specific service.
741 function fs_service_clicked(cb) {
742 var f = cb.form;
743 // The checkbox value is a JSON array containing the service's code type, code, description,
744 // and price for each price level.
745 var a = JSON.parse(cb.value);
746 if (!cb.checked) {
747 // The checkbox was UNchecked.
748 // Find last row with a matching code_type and code and set its del flag.
749 var telem = document.getElementById('fs_services_table');
750 var lino = telem.rows.length - 2;
751 for (; lino >= 0; --lino) {
752 var pfx = "form_fs_bill[" + lino + "]";
753 if (f[pfx + "[code_type]"].value == a[0] && f[pfx + "[code]"].value == a[1]) {
754 f[pfx + "[del]"].checked = true;
755 break;
758 return;
760 $.getScript('<?php echo $GLOBALS['web_root'] ?>/library/ajax/code_attributes_ajax.php' +
761 '?codetype=' + encodeURIComponent(a[0]) +
762 '&code=' + encodeURIComponent(a[1]) +
763 '&pricelevel=' + encodeURIComponent(f.form_fs_pricelevel.value) +
764 '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>);
767 // Respond to clicking a checkbox for adding (or removing) a specific product.
768 function fs_product_clicked(cb) {
769 var f = cb.form;
770 // The checkbox value is a JSON array containing the product's code type, code and selector.
771 var a = JSON.parse(cb.value);
772 if (!cb.checked) {
773 // The checkbox was UNchecked.
774 // Find last row with a matching product ID and set its del flag.
775 var telem = document.getElementById('fs_products_table');
776 var lino = telem.rows.length - 2;
777 for (; lino >= 0; --lino) {
778 var pfx = "form_fs_prod[" + lino + "]";
779 if (f[pfx + "[code_type]"].value == a[0] && f[pfx + "[code]"].value == a[1]) {
780 f[pfx + "[del]"].checked = true;
781 break;
784 return;
786 $.getScript('<?php echo $GLOBALS['web_root'] ?>/library/ajax/code_attributes_ajax.php' +
787 '?codetype=' + encodeURIComponent(a[0]) +
788 '&code=' + encodeURIComponent(a[1]) +
789 '&selector=' + encodeURIComponent(a[2]) +
790 '&pricelevel=' + encodeURIComponent(f.form_fs_pricelevel.value) +
791 '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>);
794 // Respond to clicking a checkbox for adding (or removing) a specific diagnosis.
795 function fs_diag_clicked(cb) {
796 var f = cb.form;
797 // The checkbox value is a JSON array containing the diagnosis's code type, code, description.
798 var a = JSON.parse(cb.value);
799 if (!cb.checked) {
800 // The checkbox was UNchecked.
801 // Find last row with a matching code_type and code and set its del flag.
802 var telem = document.getElementById('fs_diags_table');
803 var lino = telem.rows.length - 2 + 1000;
804 for (; lino >= 0; --lino) {
805 var pfx = "form_fs_bill[" + lino + "]";
806 if (f[pfx + "[code_type]"].value == a[0] && f[pfx + "[code]"].value == a[1]) {
807 f[pfx + "[del]"].checked = true;
808 break;
811 return;
813 $.getScript('<?php echo $GLOBALS['web_root'] ?>/library/ajax/code_attributes_ajax.php' +
814 '?codetype=' + encodeURIComponent(a[0]) +
815 '&code=' + encodeURIComponent(a[1]) +
816 '&pricelevel=' + encodeURIComponent(f.form_fs_pricelevel ? f.form_fs_pricelevel.value : "") +
817 '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>);
820 // Respond to selecting a package of codes.
821 function fs_package_selected(sel) {
822 var f = sel.form;
823 // The option value is an encoded string of code types and codes.
824 if (sel.value) {
825 $.getScript('<?php echo $GLOBALS['web_root'] ?>/library/ajax/code_attributes_ajax.php' +
826 '?list=' + encodeURIComponent(sel.value) +
827 '&pricelevel=' + encodeURIComponent(f.form_fs_pricelevel ? f.form_fs_pricelevel.value : "") +
828 '&csrf_token_form=' + <?php echo js_url(CsrfUtils::collectCsrfToken()); ?>);
830 sel.selectedIndex = 0;
833 // This is called back by code_attributes_ajax.php to complete the appending of a line item.
834 function code_attributes_handler(codetype, code, desc, price, warehouses) {
835 if (codetype == 'PROD') {
836 fs_append_product(codetype, code, desc, price, warehouses);
838 else if (codetype == 'ICD9' || codetype == 'ICD10') {
839 fs_append_diag(codetype, code, desc);
841 else {
842 fs_append_service(codetype, code, desc, price);
846 function warehouse_changed(sel) {
847 if (!confirm(<?php echo xlj('Do you really want to change Warehouse?'); ?>)) {
848 // They clicked Cancel so reset selection to its default state.
849 for (var i = 0; i < sel.options.length; ++i) {
850 sel.options[i].selected = sel.options[i].defaultSelected;
855 <?php } // end if (isset($fs))
857 if (function_exists($formname . '_javascript')) {
858 call_user_func($formname . '_javascript');
862 </script>
863 </head>
865 <body class="body_top"<?php if ($from_issue_form) {
866 echo " style='background-color:var(--white)'";
867 } ?>>
868 <div class="<?php echo $form_container ?>">
869 <?php
870 echo "<form method='post' " .
871 "action='$rootdir/forms/LBF/new.php?formname=" . attr_url($formname) . "&id=" . attr_url($formid) . "&portalid=" . attr_url($portalid) . "&formOrigin=" . attr_url($form_origin) . "&isPortal=" . attr_url($patient_portal) . "' " .
872 "onsubmit='return validate(this)'>\n";
874 $cmsportal_login = '';
875 $portalres = false;
878 if (!$from_trend_form) {
879 $enrow = sqlQuery("SELECT p.fname, p.mname, p.lname, p.cmsportal_login, " .
880 "fe.date FROM " .
881 "form_encounter AS fe, forms AS f, patient_data AS p WHERE " .
882 "p.pid = ? AND f.pid = p.pid AND f.encounter = ? AND " .
883 "f.formdir = 'newpatient' AND f.deleted = 0 AND " .
884 "fe.id = f.form_id LIMIT 1", array($pid, $visitid)); ?>
886 <div class="<?php echo $form_container ?>">
887 <div class="flex-row">
888 <div class="col-12">
889 <h3>
890 <?php echo text($formtitle);
891 if ($is_core) {
892 echo " " . xlt('for') . ' ';
893 echo text($enrow['fname'] ?? '') . ' ' . text($enrow['mname'] ?? '') . ' ' . text($enrow['lname'] ?? '');
894 echo ' ' . xlt('on') . ' ' . text(oeFormatShortDate(substr($enrow['date'] ?? '', 0, 10)));
895 } ?>
896 </h3>
897 <?php
898 $firow = sqlQuery(
899 "SELECT issue_id, provider_id FROM forms WHERE " .
900 "formdir = ? AND form_id = ? AND deleted = 0",
901 array($formname, $formid)
903 $form_issue_id = empty($firow['issue_id']) ? 0 : intval($firow['issue_id']);
904 $default = empty($firow['provider_id']) ? $_SESSION['authUserID'] : intval($firow['provider_id']);
906 if (!$patient_portal) {
907 // Provider selector.
908 echo "&nbsp;&nbsp;";
909 echo xlt('Provider') . ": ";
910 // TBD: Refactor this function out of the FeeSheetHTML class as that is not the best place for it.
911 echo FeeSheetHtml::genProviderSelect('form_provider_id', '-- ' . xl("Please Select") . ' --', ($form_provider_id ?? ''));
913 // If appropriate build a drop-down selector of issues of this type for this patient.
914 // We skip this if in an issue form tab because removing and adding visit form tabs is
915 // beyond the current scope of that code.
916 if (!empty($LBF_ISSUE_TYPE) && !$from_issue_form) {
917 echo "&nbsp;&nbsp;";
918 $query = "SELECT id, title, date, begdate FROM lists WHERE pid = ? AND type = ? " .
919 "ORDER BY COALESCE(begdate, date) DESC, id DESC";
920 $ires = sqlStatement($query, array($pid, $LBF_ISSUE_TYPE));
921 echo "<select name='form_issue_id'>\n";
922 echo " <option value='0'>-- " . xlt('Select Case') . " --</option>\n";
923 while ($irow = sqlFetchArray($ires)) {
924 $issueid = $irow['id'];
925 $issuedate = oeFormatShortDate(empty($irow['begdate']) ? $irow['date'] : $irow['begdate']);
926 echo " <option value='" . attr($issueid) . "'";
927 if ($issueid == $form_issue_id) {
928 echo " selected";
930 echo ">" . text("$issuedate " . $irow['title']) . "</option>\n";
932 echo "</select>\n";
935 </div>
937 <?php $cmsportal_login = $enrow['cmsportal_login'] ?? '';
938 } // end not from trend form
941 <!-- This is where a chart might display. -->
942 <div id="chart"></div>
944 <?php
945 $shrow = getHistoryData($pid);
947 /**********************************************************
948 // Determine if this layout uses edit option "I" anywhere.
949 // If not we default to only the first group being initially open.
950 $tmprow = sqlQuery("SELECT form_id FROM layout_options " .
951 "WHERE form_id = ? AND uor > 0 AND edit_options LIKE '%I%' " .
952 "LIMIT 1", array($formname));
953 $some_group_is_open = !empty($tmprow['form_id']);
954 **********************************************************/
956 $fres = sqlStatement("SELECT * FROM layout_options " .
957 "WHERE form_id = ? AND uor > 0 " .
958 "ORDER BY group_id, seq", array($formname));
959 $cell_count = 0;
960 $item_count = 0;
961 // $display_style = 'block';
963 // This string is the active group levels. Each leading substring represents an instance of nesting.
964 $group_levels = '';
966 // This indicates if </table> will need to be written to end the fields in a group.
967 $group_table_active = false;
969 // This is an array keyed on forms.form_id for other occurrences of this
970 // form type. The maximum number of such other occurrences to display is
971 // in list_options.option_value for this form's list item. Values in this
972 // array are work areas for building the ending HTML for each displayed row.
974 $historical_ids = array();
976 // True if any data items in this form can be graphed.
977 $form_is_graphable = false;
979 $condition_str = '';
981 while ($frow = sqlFetchArray($fres)) {
982 $this_group = $frow['group_id'];
983 $titlecols = $frow['titlecols'];
984 $datacols = $frow['datacols'];
985 $data_type = $frow['data_type'];
986 $field_id = $frow['field_id'];
987 $list_id = $frow['list_id'];
988 $edit_options = $frow['edit_options'];
989 $source = $frow['source'];
990 $jump_new_row = isOption($edit_options, 'J');
991 $prepend_blank_row = isOption($edit_options, 'K');
993 $graphable = isOption($edit_options, 'G') !== false;
994 if ($graphable) {
995 $form_is_graphable = true;
998 if (isOption($edit_options, 'EP') && $patient_portal) {
999 continue;
1002 // Accumulate action conditions into a JSON expression for the browser side.
1003 accumActionConditions($frow, $condition_str);
1005 $currvalue = '';
1007 if (isOption($edit_options, 'H') !== false) {
1008 // This data comes from static history
1009 if (isset($shrow[$field_id])) {
1010 $currvalue = $shrow[$field_id];
1012 } else {
1013 if (!$formid && $portalres) {
1014 // Copying CMS Portal form data into this field if appropriate.
1015 $currvalue = cms_field_to_lbf($data_type, $field_id, $portalres['fields']);
1018 if ($currvalue === '') {
1019 $currvalue = lbf_current_value($frow, $formid, (!empty($is_lbf)) ? 0 : $encounter);
1022 if ($currvalue === false) {
1023 continue; // column does not exist, should not happen
1026 // Handle "P" edit option to default to the previous value of a form field.
1027 if (!$from_trend_form && empty($currvalue) && isOption($edit_options, 'P') !== false) {
1028 if ($source == 'F' && !$formid) {
1029 // Form attribute for new form, get value from most recent form instance.
1030 // Form attributes of existing forms are expected to have existing values.
1031 $tmp = sqlQuery(
1032 "SELECT encounter, form_id FROM forms WHERE " .
1033 "pid = ? AND formdir = ? AND deleted = 0 " .
1034 "ORDER BY date DESC LIMIT 1",
1035 array($pid, $formname)
1037 if (!empty($tmp['encounter'])) {
1038 $currvalue = lbf_current_value($frow, $tmp['form_id'], $tmp['encounter']);
1040 } elseif ($source == 'E') {
1041 // Visit attribute, get most recent value as of this visit.
1042 // Even if the form already exists for this visit it may have a readonly value that only
1043 // exists in a previous visit and was created from a different form.
1044 $tmp = sqlQuery(
1045 "SELECT sa.field_value FROM form_encounter AS e1 " .
1046 "JOIN form_encounter AS e2 ON " .
1047 "e2.pid = e1.pid AND (e2.date < e1.date OR (e2.date = e1.date AND e2.encounter <= e1.encounter)) " .
1048 "JOIN shared_attributes AS sa ON " .
1049 "sa.pid = e2.pid AND sa.encounter = e2.encounter AND sa.field_id = ?" .
1050 "WHERE e1.pid = ? AND e1.encounter = ? " .
1051 "ORDER BY e2.date DESC, e2.encounter DESC LIMIT 1",
1052 array($field_id, $pid, $visitid)
1054 if (isset($tmp['field_value'])) {
1055 $currvalue = $tmp['field_value'];
1058 } // End "P" option logic.
1061 $this_levels = $this_group;
1062 $i = 0;
1063 $mincount = min(strlen($this_levels), strlen($group_levels));
1064 while ($i < $mincount && $this_levels[$i] == $group_levels[$i]) {
1065 ++$i;
1067 // $i is now the number of initial matching levels.
1069 // If ending a group or starting a subgroup, terminate the current row and its table.
1070 if ($group_table_active && ($i != strlen($group_levels) || $i != strlen($this_levels))) {
1071 end_row();
1072 echo " </table>\n";
1073 $group_table_active = false;
1076 // Close any groups that we are done with.
1077 while (strlen($group_levels) > $i) {
1078 $gname = $grparr[$group_levels]['grp_title'];
1079 $group_levels = substr($group_levels, 0, -1); // remove last character
1080 // No div for an empty group name.
1081 if (strlen($gname)) {
1082 echo "</div>\n";
1086 // If there are any new groups, open them.
1087 while ($i < strlen($this_levels)) {
1088 end_row();
1089 if ($group_table_active) {
1090 echo " </table>\n";
1091 $group_table_active = false;
1093 $group_levels .= $this_levels[$i++];
1094 $grouprow = $grparr[substr($group_levels, 0, $i)];
1095 $gname = $grouprow['grp_title'];
1096 $subtitle = xl_layout_label($grouprow['grp_subtitle']);
1097 // Compute a short unique identifier for this group.
1098 $group_seq = 'lbf' . $group_levels;
1099 $group_name = $gname;
1101 $display_style = $grouprow['grp_init_open'] ? 'block' : 'none';
1103 // If group name is blank, no checkbox or div.
1104 if (strlen($gname)) {
1105 echo "<br /><span><label class='mb-1' role='button'><input class='mr-1' type='checkbox' name='form_cb_" . attr($group_seq) . "' value='1' " . "onclick='return divclick(this," . attr_js('div_' . $group_seq) . ");'";
1106 if ($display_style == 'block') {
1107 echo " checked";
1109 echo " /><strong>" . text(xl_layout_label($group_name)) . "</strong></label></span>\n";
1110 echo "<div id='div_" . attr($group_seq) . "' class='section table-responsive clearfix' style='display:" . attr($display_style) . ";'>\n";
1113 $group_table_active = true;
1114 echo " <table cellspacing='0' cellpadding='0' class='border-0 lbfdata'>\n";
1116 if ($subtitle) {
1117 // There is a group subtitle so show it.
1118 echo "<tr><td class='font-weight-bold border-top-0 text-primary' colspan='" . attr($CPR) . "'>" . text($subtitle) . "</td></tr>\n";
1119 echo "<tr><td class='font-weight-bold border-top-0' style='height:0.3125rem;' colspan='" . attr($CPR) . "'></td></tr>\n";
1122 // $display_style = 'none';
1124 // Initialize historical data array and write date headers.
1125 $historical_ids = array();
1126 if ($formhistory > 0) {
1127 echo " <tr>";
1128 echo "<td colspan='" . attr($CPR) . "' class='font-weight-bold border-top-0 text-right'>";
1129 if (empty($is_lbf)) {
1130 // Including actual date per IPPF request 2012-08-23.
1131 echo text(oeFormatShortDate(substr($enrow['date'], 0, 10)));
1132 echo ' (' . xlt('Current') . ')';
1135 echo "&nbsp;</td>\n";
1136 $hres = sqlStatement(
1137 "SELECT f.form_id, fe.date " .
1138 "FROM forms AS f, form_encounter AS fe WHERE " .
1139 "f.pid = ? AND f.formdir = ? AND " .
1140 "f.form_id != ? AND f.deleted = 0 AND " .
1141 "fe.pid = f.pid AND fe.encounter = f.encounter " .
1142 "ORDER BY fe.date DESC, f.encounter DESC, f.date DESC " .
1143 "LIMIT ?",
1144 array($pid, $formname, $formid, $formhistory)
1146 // For some readings like vitals there may be multiple forms per encounter.
1147 // We sort these sensibly, however only the encounter date is shown here;
1148 // at some point we may wish to show also the data entry date/time.
1149 while ($hrow = sqlFetchArray($hres)) {
1150 echo "<td colspan='" . attr($CPR) . "' class='font-weight-bold border-top-0 text-right'>&nbsp;" .
1151 text(oeFormatShortDate(substr($hrow['date'], 0, 10))) . "</td>\n";
1152 $historical_ids[$hrow['form_id']] = '';
1155 echo " </tr>";
1159 // Handle starting of a new row.
1160 if (($titlecols > 0 && $cell_count >= $CPR) || $cell_count == 0 || $prepend_blank_row || $jump_new_row) {
1161 end_row();
1162 if ($prepend_blank_row) {
1163 echo "<tr><td class='text border-top-0' colspan='" . attr($CPR) . "'>&nbsp;</td></tr>\n";
1165 if (isOption($edit_options, 'RS')) {
1166 echo " <tr class='RS'>";
1167 } elseif (isOption($edit_options, 'RO')) {
1168 echo " <tr class='RO'>";
1169 } else {
1170 echo " <tr>";
1173 // Clear historical data string.
1174 foreach ($historical_ids as $key => $dummy) {
1175 $historical_ids[$key] = '';
1179 if ($item_count == 0 && $titlecols == 0) {
1180 $titlecols = 1;
1183 // First item is on the "left-border"
1184 $leftborder = true;
1186 // Handle starting of a new label cell.
1187 if ($titlecols > 0) {
1188 end_cell();
1189 if (isOption($edit_options, 'SP')) {
1190 $datacols = 0;
1191 $titlecols = $CPR;
1192 echo "<td class='border-top-0 align-top' colspan='" . attr($titlecols) . "'";
1193 } else {
1194 // unsure why this was set to always text-nowrap. will monitor and perhaps this should be
1195 // an option in line options.
1196 echo "<td class='border-top-0 align-top text-wrap' colspan='" . attr($titlecols) . "'";
1198 echo " class='";
1199 echo ($frow['uor'] == 2) ? "required" : "font-weight-bold";
1200 if ($graphable) {
1201 echo " graph";
1204 echo "'";
1206 if ($cell_count > 0) {
1207 echo " style='padding-left: 0.8125rem'";
1209 // This ID is used by action conditions and also show_graph().
1210 echo " id='label_id_" . attr($field_id) . "'";
1211 echo ">";
1213 foreach ($historical_ids as $key => $dummy) {
1214 $historical_ids[$key] .= "<td colspan='" . attr($titlecols) . "' class='text border-top-0 align-top text-nowrap'>";
1217 $cell_count += $titlecols;
1220 ++$item_count;
1222 echo "<strong>";
1223 if ($frow['title']) {
1224 $tmp = xl_layout_label($frow['title']);
1225 echo text($tmp);
1226 // Append colon only if label does not end with punctuation.
1227 if (strpos('?!.,:-=', substr($tmp, -1, 1)) === false) {
1228 echo ':';
1230 } else {
1231 echo "&nbsp;";
1233 echo "</strong>";
1235 // Note the labels are not repeated in the history columns.
1237 // Handle starting of a new data cell.
1238 if ($datacols > 0) {
1239 end_cell();
1240 if (isOption($edit_options, 'DS')) {
1241 echo "<td colspan='" . attr($datacols) . "' class='border-top-0 align-top text RS'";
1243 if (isOption($edit_options, 'DO')) {
1244 echo "<td colspan='" . attr($datacols) . "' class='border-top-0 align-top text RO'";
1245 } else {
1246 echo "<td colspan='" . attr($datacols) . "' class='border-top-0 align-top text'";
1248 // This ID is used by action conditions.
1249 echo " id='value_id_" . attr($field_id) . "'";
1250 if ($cell_count > 0) {
1251 echo " style='padding-left: 0.4375rem'";
1254 echo ">";
1256 foreach ($historical_ids as $key => $dummy) {
1257 $historical_ids[$key] .= "<td colspan='" . attr($datacols) . "' class='text border-top-0 align-top text-right'>";
1260 $cell_count += $datacols;
1263 ++$item_count;
1265 // Skip current-value fields for the display-only case.
1266 if (!$from_trend_form) {
1267 if ($frow['edit_options'] == 'H') {
1268 echo generate_display_field($frow, $currvalue);
1269 } else {
1270 generate_form_field($frow, $currvalue);
1274 // Append to historical data of other dates for this item.
1275 foreach ($historical_ids as $key => $dummy) {
1276 $value = lbf_current_value($frow, $key, 0);
1277 $historical_ids[$key] .= generate_display_field($frow, $value);
1281 // Close all open groups.
1282 if ($group_table_active) {
1283 end_row();
1284 echo " </table>\n";
1285 $group_table_active = false;
1287 while (strlen($group_levels)) {
1288 $gname = $grparr[$group_levels]['grp_title'];
1289 $group_levels = substr($group_levels, 0, -1); // remove last character
1290 // No div for an empty group name.
1291 if (strlen($gname)) {
1292 echo "</div>\n";
1296 $display_style = $LBF_SECTION_DISPLAY_STYLE;
1298 if (isset($LBF_SERVICES_SECTION) || isset($LBF_DIAGS_SECTION)) {
1299 $fs->loadServiceItems();
1302 if (isset($LBF_SERVICES_SECTION)) {
1303 // Create the checkbox and div for the Services Section.
1304 echo "<br /><span class='font-weight-bold'><input type='checkbox' name='form_cb_fs_services' value='1' " .
1305 "onclick='return divclick(this, \"div_fs_services\");'";
1306 if ($display_style == 'block') {
1307 echo " checked";
1309 echo " /><strong>" . xlt('Services') . "</strong></span>\n";
1310 echo "<div id='div_fs_services' class='section' style='display:" . attr($display_style) . ";'>\n";
1311 echo "<center>\n";
1312 // $display_style = 'none';
1314 // If there are associated codes, generate a checkbox for each one.
1315 if ($LBF_SERVICES_SECTION) {
1316 echo "<table class='w-100' cellpadding='0' cellspacing='0'>\n";
1317 $cols = 3;
1318 $tdpct = (int)(100 / $cols);
1319 $count = 0;
1320 $relcodes = explode(';', $LBF_SERVICES_SECTION);
1321 foreach ($relcodes as $codestring) {
1322 if ($codestring === '') {
1323 continue;
1325 $codes_esc = attr($codestring);
1326 $cbval = $fs->genCodeSelectorValue($codestring);
1327 if ($count % $cols == 0) {
1328 if ($count) {
1329 echo " </tr>\n";
1331 echo " <tr>\n";
1333 echo " <td class='border-top-0' width='" . attr($tdpct) . "%'>";
1334 echo "<input type='checkbox' id='form_fs_services[$codes_esc]' " .
1335 "onclick='fs_service_clicked(this)' value='" . attr($cbval) . "'";
1336 if ($fs->code_is_in_fee_sheet) {
1337 echo " checked";
1339 list($codetype, $code) = explode(':', $codestring);
1340 $title = lookup_code_descriptions($codestring);
1341 $title = empty($title) ? $code : xl_list_label($title);
1342 echo " />" . text($title);
1343 echo "</td>\n";
1344 ++$count;
1346 if ($count) {
1347 echo " </tr>\n";
1349 echo "</table>\n";
1352 // A row for Search, Add Package, Main Provider.
1353 $ctype = $GLOBALS['ippf_specific'] ? 'MA' : '';
1354 echo "<p class='font-weight-bold'>";
1355 echo "<input type='button' value='" . xla('Search Services') . "' onclick='sel_related(null," . attr_js($ctype) . ")' />&nbsp;&nbsp;\n";
1356 $fscres = sqlStatement("SELECT * FROM fee_sheet_options ORDER BY fs_category, fs_option");
1357 if (sqlNumRows($fscres)) {
1358 $last_category = '';
1359 echo "<select class='form-control' onchange='fs_package_selected(this)'>\n";
1360 echo " <option value=''>" . xlt('Add Package') . "</option>\n";
1361 while ($row = sqlFetchArray($fscres)) {
1362 $fs_category = $row['fs_category'];
1363 $fs_option = $row['fs_option'];
1364 $fs_codes = $row['fs_codes'];
1365 if ($fs_category !== $last_category) {
1366 if ($last_category) {
1367 echo " </optgroup>\n";
1369 echo " <optgroup label='" . xla(substr($fs_category, 1)) . "'>\n";
1370 $last_category = $fs_category;
1372 echo " <option value='" . attr($fs_codes) . "'>" . xlt(substr($fs_option, 1)) . "</option>\n";
1374 if ($last_category) {
1375 echo " </optgroup>\n";
1377 echo "</select>&nbsp;&nbsp;\n";
1379 $tmp_provider_id = $fs->provider_id ? $fs->provider_id : 0;
1380 if (!$tmp_provider_id && $userauthorized) {
1381 // Default to the logged-in user if they are a provider.
1382 $tmp_provider_id = $_SESSION['authUserID'];
1384 echo xlt('Main Provider') . ": ";
1385 echo $fs->genProviderSelect("form_fs_provid", ' ', $tmp_provider_id);
1386 echo "\n";
1387 echo "</p>\n";
1389 // Generate a line for each service already in this FS.
1390 echo "<table cellpadding='0' cellspacing='2' id='fs_services_table'>\n";
1391 echo " <tr>\n";
1392 echo " <td class='border-top-0 font-weight-bold' colspan='2'>" . xlt('Services Provided') . "&nbsp;</td>\n";
1393 echo " <td class='border-top-0 font-weight-bold'>" . xlt('Provider') . "&nbsp;</td>\n";
1394 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Price') . "&nbsp;</td>\n";
1395 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Delete') . "</td>\n";
1396 echo " </tr>\n";
1397 foreach ($fs->serviceitems as $lino => $li) {
1398 // Skip diagnoses; those would be in the Diagnoses section below.
1399 if ($code_types[$li['codetype']]['diag']) {
1400 continue;
1402 echo " <tr>\n";
1403 echo " <td class='border-top-0 text'>" . text($li['code']) . "&nbsp;</td>\n";
1404 echo " <td class='border-top-0 text'>" . text($li['code_text']) . "&nbsp;</td>\n";
1405 echo " <td class='border-top-0 text'>" .
1406 $fs->genProviderSelect("form_fs_bill[$lino][provid]", '-- ' . xl("Default") . ' --', $li['provid']) .
1407 " &nbsp;</td>\n";
1408 echo " <td class='border-top-0 text text-right'>" . text(oeFormatMoney($li['price'])) . "&nbsp;</td>\n";
1409 echo " <td class='border-top-0 text text-right'>\n" .
1410 " <input type='checkbox' name='form_fs_bill[" . attr($lino) . "][del]' " .
1411 "value='1'" . ($li['del'] ? " checked" : "") . " />\n";
1412 foreach ($li['hidden'] as $hname => $hvalue) {
1413 echo " <input type='hidden' name='form_fs_bill[" . attr($lino) . "][" . attr($hname) . "]' value='" . attr($hvalue) . "' />\n";
1415 echo " </td>\n";
1416 echo " </tr>\n";
1418 echo "</table>\n";
1419 echo "</center>\n";
1420 echo "</div>\n";
1421 } // End Services Section
1423 if (isset($LBF_PRODUCTS_SECTION)) {
1424 // Create the checkbox and div for the Products Section.
1425 echo "<br /><span class='font-weight-bold'><input type='checkbox' name='form_cb_fs_products' value='1' " .
1426 "onclick='return divclick(this, \"div_fs_products\");'";
1427 if ($display_style == 'block') {
1428 echo " checked";
1430 echo " /><strong>" . xlt('Products') . "</strong></span>\n";
1431 echo "<div id='div_fs_products' class='section' style='display:" . attr($display_style) . ";'>\n";
1432 echo "<center>\n";
1433 // $display_style = 'none';
1435 // If there are associated codes, generate a checkbox for each one.
1436 if ($LBF_PRODUCTS_SECTION) {
1437 echo "<table class='w-100' cellpadding='0' cellspacing='0'>\n";
1438 $cols = 3;
1439 $tdpct = (int)(100 / $cols);
1440 $count = 0;
1441 $relcodes = explode(';', $LBF_PRODUCTS_SECTION);
1442 foreach ($relcodes as $codestring) {
1443 if ($codestring === '') {
1444 continue;
1446 $codes_esc = attr($codestring);
1447 $cbval = $fs->genCodeSelectorValue($codestring);
1448 if ($count % $cols == 0) {
1449 if ($count) {
1450 echo " </tr>\n";
1452 echo " <tr>\n";
1454 echo " <td class='border-top-0' width='" . attr($tdpct) . "%'>";
1455 echo "<input type='checkbox' id='form_fs_products[$codes_esc]' " .
1456 "onclick='fs_product_clicked(this)' value='" . attr($cbval) . "'";
1457 if ($fs->code_is_in_fee_sheet) {
1458 echo " checked";
1460 list($codetype, $code) = explode(':', $codestring);
1461 $crow = sqlQuery(
1462 "SELECT name FROM drugs WHERE " .
1463 "drug_id = ? ORDER BY drug_id LIMIT 1",
1464 array($code)
1466 $title = empty($crow['name']) ? $code : xl_list_label($crow['name']);
1467 echo " />" . text($title);
1468 echo "</td>\n";
1469 ++$count;
1471 if ($count) {
1472 echo " </tr>\n";
1474 echo "</table>\n";
1477 // A row for Search
1478 $ctype = $GLOBALS['ippf_specific'] ? 'MA' : '';
1479 echo "<p class='font-weight-bold'>";
1480 echo "<input type='button' value='" . xla('Search Products') . "' onclick='sel_related(null,\"PROD\")' />&nbsp;&nbsp;";
1481 echo "</p>\n";
1483 // Generate a line for each product already in this FS.
1484 echo "<table cellpadding='0' cellspacing='2' id='fs_products_table'>\n";
1485 echo " <tr>\n";
1486 echo " <td class='border-top-0 font-weight-bold'>" . xlt('Products Provided') . "&nbsp;</td>\n";
1487 echo " <td class='border-top-0 font-weight-bold'>" . xlt('Warehouse') . "&nbsp;</td>\n";
1488 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Quantity') . "&nbsp;</td>\n";
1489 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Price') . "&nbsp;</td>\n";
1490 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Delete') . "</td>\n";
1491 echo " </tr>\n";
1492 $fs->loadProductItems();
1493 foreach ($fs->productitems as $lino => $li) {
1494 echo " <tr>\n";
1495 echo " <td class='border-top-0 text'>" . text($li['code_text']) . "&nbsp;</td>\n";
1496 echo " <td class='border-top-0 text'>" .
1497 $fs->genWarehouseSelect("form_fs_prod[$lino][warehouse]", '', $li['warehouse'], false, $li['hidden']['drug_id'], true) .
1498 " &nbsp;</td>\n";
1499 echo " <td class='border-top-0 text text-right'>" .
1500 "<input class='form-control' type='text' name='form_fs_prod[" . attr($lino) . "][units]' size='3' value='" . attr($li['units']) . "' />" .
1501 "&nbsp;</td>\n";
1502 echo " <td class='border-top-0 text text-right'>" . text(oeFormatMoney($li['price'])) . "&nbsp;</td>\n";
1503 echo " <td class='border-top-0 text text-right'>\n" .
1504 " <input type='checkbox' name='form_fs_prod[" . attr($lino) . "][del]' " .
1505 "value='1'" . ($li['del'] ? " checked" : "") . " />\n";
1506 foreach ($li['hidden'] as $hname => $hvalue) {
1507 echo " <input type='hidden' name='form_fs_prod[" . attr($lino) . "][" . attr($hname) . "]' value='" . attr($hvalue) . "' />\n";
1509 echo " </td>\n";
1510 echo " </tr>\n";
1512 echo "</table>\n";
1513 echo "</center>\n";
1514 echo "</div>\n";
1515 } // End Products Section
1517 if (isset($LBF_DIAGS_SECTION)) {
1518 // Create the checkbox and div for the Diagnoses Section.
1519 echo "<br /><span class='font-weight-bold'><input type='checkbox' name='form_cb_fs_diags' value='1' " .
1520 "onclick='return divclick(this, \"div_fs_diags\");'";
1521 if ($display_style == 'block') {
1522 echo " checked";
1524 echo " /><b>" . xlt('Diagnoses') . "</b></span>\n";
1525 echo "<div id='div_fs_diags' class='section' style='display:" . attr($display_style) . ";'>\n";
1526 echo "<center>\n";
1527 // $display_style = 'none';
1529 // If there are associated codes, generate a checkbox for each one.
1530 if ($LBF_DIAGS_SECTION) {
1531 echo "<table class='w-100' cellpadding='0' cellspacing='0'>\n";
1532 $cols = 3;
1533 $tdpct = (int)(100 / $cols);
1534 $count = 0;
1535 $relcodes = explode(';', $LBF_DIAGS_SECTION);
1536 foreach ($relcodes as $codestring) {
1537 if ($codestring === '') {
1538 continue;
1540 $codes_esc = attr($codestring);
1541 $cbval = $fs->genCodeSelectorValue($codestring);
1542 if ($count % $cols == 0) {
1543 if ($count) {
1544 echo " </tr>\n";
1546 echo " <tr>\n";
1548 echo " <td class='border-top-0' width='" . attr($tdpct) . "%'>";
1549 echo "<input type='checkbox' id='form_fs_diags[$codes_esc]' " .
1550 "onclick='fs_diag_clicked(this)' value='" . attr($cbval) . "'";
1551 if ($fs->code_is_in_fee_sheet) {
1552 echo " checked";
1554 list($codetype, $code) = explode(':', $codestring);
1555 $title = lookup_code_descriptions($codestring);
1556 $title = empty($title) ? $code : xl_list_label($title);
1557 echo " />" . text($title);
1558 echo "</td>\n";
1559 ++$count;
1561 if ($count) {
1562 echo " </tr>\n";
1564 echo "</table>\n";
1567 // A row for Search.
1568 $ctype = collect_codetypes('diagnosis', 'csv');
1569 echo "<p class='font-weight-bold'>";
1570 echo "<input type='button' class='btn btn-primary' value='" . xla('Search Diagnoses') . "' onclick='sel_related(null," . attr_js($ctype) . ")' />";
1571 echo "</p>\n";
1573 // Generate a line for each diagnosis already in this FS.
1574 echo "<table cellpadding='0' cellspacing='2' id='fs_diags_table'>\n";
1575 echo " <tr>\n";
1576 echo " <td class='border-top-0 font-weight-bold' colspan='2'>" . xlt('Diagnosis') . "&nbsp;</td>\n";
1577 echo " <td class='border-top-0 font-weight-bold text-right'>" . xlt('Delete') . "</td>\n";
1578 echo " </tr>\n";
1579 foreach ($fs->serviceitems as $lino => $li) {
1580 // Skip anything that is not a diagnosis; those are in the Services section above.
1581 if (!$code_types[$li['codetype']]['diag']) {
1582 continue;
1584 echo " <tr>\n";
1585 echo " <td class='border-top-0 text'>" . text($li['code']) . "&nbsp;</td>\n";
1586 echo " <td class='border-top-0 text'>" . text($li['code_text']) . "&nbsp;</td>\n";
1587 // The Diagnoses section shares the form_fs_bill array with the Services section.
1588 echo " <td class='border-top-0 text text-right'>\n" .
1589 " <input type='checkbox' name='form_fs_bill[" . attr($lino) . "][del]' " .
1590 "value='1'" . ($li['del'] ? " checked" : "") . " />\n";
1591 foreach ($li['hidden'] as $hname => $hvalue) {
1592 echo " <input type='hidden' name='form_fs_bill[" . attr($lino) . "][" . attr($hname) . "]' value='" . attr($hvalue) . "' />\n";
1594 echo " </td>\n";
1595 echo " </tr>\n";
1597 echo "</table>\n";
1598 echo "</center>\n";
1599 echo "</div>\n";
1600 } // End Diagnoses Section
1602 if ($LBF_REFERRALS_SECTION) {
1603 // Create the checkbox and div for the Referrals Section.
1604 echo "<br /><span class='bold'><input type='checkbox' name='form_cb_referrals' value='1' " .
1605 "onclick='return divclick(this, \"div_referrals\");'";
1606 if ($display_style == 'block') {
1607 echo " checked";
1609 echo " /><b>" . xlt('Referrals') . "</b></span>\n";
1610 echo "<div id='div_referrals' class='section' style='display:" . attr($display_style) . ";'>\n";
1611 echo "<center>\n";
1612 // $display_style = 'none';
1614 // Generate a table row for each referral in the visit.
1615 echo "<table cellpadding='0' cellspacing='5' id='referrals_table'>\n";
1616 echo " <tr>\n";
1617 echo " <td class='bold'>" . xlt('Date') . "&nbsp;</td>\n";
1618 echo " <td class='bold'>" . xlt('Type') . "&nbsp;</td>\n";
1619 echo " <td class='bold'>" . xlt('Reason') . "&nbsp;</td>\n";
1620 echo " <td class='bold'>" . xlt('Referred To') . "&nbsp;</td>\n";
1621 echo " <td class='bold'>" . xlt('Requested Service') . "</td>\n";
1622 echo " </tr>\n";
1624 $refres = sqlStatement(
1625 "SELECT f.form_id, " .
1626 "d1.field_value AS refer_external, " .
1627 "d2.field_value AS body, " .
1628 "lo.title AS refer_type, " .
1629 "ut.organization, " .
1630 "CONCAT(ut.fname,' ', ut.lname) AS referto_name, " .
1631 "d4.field_value AS refer_related_code, " .
1632 "d5.field_value AS refer_date " .
1633 "FROM forms AS f " .
1634 "LEFT JOIN lbf_data AS d1 ON d1.form_id = f.form_id AND d1.field_id = 'refer_external' " .
1635 "LEFT JOIN list_options AS lo ON list_id = 'reftype' and option_id = d1.field_value " .
1636 "LEFT JOIN lbf_data AS d2 ON d2.form_id = f.form_id AND d2.field_id = 'body' " .
1637 "LEFT JOIN lbf_data AS d3 ON d3.form_id = f.form_id AND d3.field_id = 'refer_to' " .
1638 "LEFT JOIN users AS ut ON ut.id = d3.field_value " .
1639 "LEFT JOIN lbf_data AS d4 ON d4.form_id = f.form_id AND d4.field_id = 'refer_related_code' " .
1640 "LEFT JOIN lbf_data AS d5 ON d5.form_id = f.form_id AND d5.field_id = 'refer_date' " .
1641 "WHERE " .
1642 "f.pid = ? AND f.encounter = ? AND f.formdir = 'LBFref' AND f.deleted = 0 " .
1643 "ORDER BY refer_date, f.form_id",
1644 array($pid, $encounter)
1647 while ($refrow = sqlFetchArray($refres)) {
1648 $svcstring = '';
1649 if (!empty($refrow['refer_related_code'])) {
1650 // Get referred services.
1651 $relcodes = explode(';', $refrow['refer_related_code']);
1652 foreach ($relcodes as $codestring) {
1653 if ($codestring === '') {
1654 continue;
1656 ++$svccount;
1657 list($codetype, $code) = explode(':', $codestring);
1658 $rrow = sqlQuery(
1659 "SELECT code_text FROM codes WHERE " .
1660 "code_type = ? AND code = ? " .
1661 "ORDER BY active DESC, id ASC LIMIT 1",
1662 array($code_types[$codetype]['id'], $code)
1664 $code_text = empty($rrow['code_text']) ? '' : $rrow['code_text'];
1665 if ($svcstring) {
1666 $svcstring .= '<br />';
1668 $svcstring .= text("$code: $code_text");
1671 echo " <tr style='cursor:pointer;cursor:hand' " .
1672 "onclick=\"openLBFEncounterForm('LBFref', 'Referral', " .
1673 attr_js($refrow['form_id']) . ")\">\n";
1674 echo " <td class='text linkcolor'>" . text(oeFormatShortDate($refrow['refer_date'])) . "&nbsp;</td>\n";
1675 echo " <td class='text linkcolor'>" . text($refrow['refer_type']) . "&nbsp;</td>\n";
1676 echo " <td class='text linkcolor'>" . text($refrow['body']) . "&nbsp;</td>\n";
1677 echo " <td class='text linkcolor'>" . text($refrow['organization'] ? $refrow['organization'] : $refrow['referto_name']) . "&nbsp;</td>\n";
1678 echo " <td class='text linkcolor'>" . $svcstring . "&nbsp;</td>\n";
1679 echo " </tr>\n";
1682 echo " <tr style='cursor:pointer;cursor:hand' onclick=\"openLBFNewForm('LBFref', 'Referral')\">\n";
1683 echo " <td class='bold linkcolor' colspan='5'>" . xlt('Create New Referral') . "</td>\n";
1684 echo " </tr>\n";
1685 echo "</table>\n";
1686 echo "</center>\n";
1687 echo "</div>\n";
1688 } // End Referrals Section
1691 <br />
1693 <div class="col-12">
1694 <div class="btn-group">
1695 <?php
1696 if (!$from_trend_form && !$from_lbf_edit && $is_core) {
1697 // Generate price level selector if we are doing services or products.
1698 if (isset($LBF_SERVICES_SECTION) || isset($LBF_PRODUCTS_SECTION)) {
1699 echo xlt('Price Level') . ": ";
1700 echo $fs->generatePriceLevelSelector('form_fs_pricelevel');
1701 echo "&nbsp;&nbsp;";
1704 <button type="submit" class="btn btn-primary btn-save" name="bn_save"
1705 onclick='submitButtonName = this.name;'
1706 value="<?php echo xla('Save'); ?>">
1707 <?php echo xlt('Save'); ?>
1708 </button>
1710 <button type='submit' class="btn btn-secondary" name='bn_save_continue'
1711 onclick='submitButtonName = this.name;'
1712 value='<?php echo xla('Save and Continue') ?>'>
1713 <?php echo xlt('Save and Continue'); ?>
1714 </button>
1716 <?php if ($LBF_ENABLE_SAVE_CLOSE) { ?>
1717 <button type='submit' class="btn btn-secondary" name='bn_save_close'
1718 onclick='submitButtonName = this.name;'
1719 value='<?php echo xla('Save and Close Visit') ?>'>
1720 <?php echo xlt('Save and Close Visit'); ?>
1721 </button>
1722 <?php } ?>
1724 <?php
1725 if (!$from_issue_form) {
1727 <button type='submit' class="btn btn-secondary" name='bn_save_print'
1728 onclick='submitButtonName = this.name;'
1729 value='<?php echo xla('Save and Print') ?>'>
1730 <?php echo xlt('Save and Print'); ?>
1731 </button>
1732 <?php
1733 if (function_exists($formname . '_additional_buttons')) {
1734 // Allow the plug-in to insert more action buttons here.
1735 call_user_func($formname . '_additional_buttons');
1738 if ($form_is_graphable) {
1740 <button type='button' class="btn btn-secondary btn-graph"
1741 onclick="top.restoreSession();location='../../patient_file/encounter/trend_form.php?formname=<?php echo attr_url($formname); ?>'">
1742 <?php echo xlt('Show Graph') ?>
1743 </button>
1744 &nbsp;
1745 <?php
1746 } // end form is graphable
1748 <button type='button' class="btn btn-secondary btn-cancel" onclick="verifyCancel()">
1749 <?php echo xlt('Cancel'); ?>
1750 </button>
1751 <?php
1752 } // end not from issue form
1754 <?php
1755 } elseif (!$from_lbf_edit && $is_core) { // $from_trend_form is true but lbf edit doesn't want button
1757 <button type='button' class="btn btn-secondary btn-back" onclick='window.history.back();'>
1758 <?php echo xlt('Back') ?>
1759 </button>
1760 <?php
1761 } // end from trend form
1763 </div>
1764 <hr>
1765 </div>
1766 <?php if (!$from_trend_form) { // end row and container divs ?>
1767 </div>
1768 </div>
1770 <p style='text-align:center' class='small'>
1771 <?php echo text(xl('Rev.') . ' ' . substr($grp_last_update, 0, 10)); ?>
1772 </p>
1774 <?php } ?>
1776 <input type='hidden' name='from_issue_form' value='<?php echo attr($from_issue_form); ?>'/>
1777 <?php if (!$is_core) {
1778 echo '<input type="hidden" name="csrf_token_form" value="' . CsrfUtils::collectCsrfToken() . '" />';
1779 echo "\n<input type='hidden' name='bn_save_continue' value='set' />\n";
1780 } ?>
1781 </form>
1783 <!-- include support for the list-add selectbox feature -->
1784 <?php include $GLOBALS['fileroot'] . "/library/options_listadd.inc"; ?>
1786 <script>
1788 // Array of action conditions for the checkSkipConditions() function.
1789 var skipArray = [
1790 <?php echo $condition_str; ?>
1793 <?php echo $date_init; ?>
1794 <?php
1795 if (function_exists($formname . '_javascript_onload')) {
1796 call_user_func($formname . '_javascript_onload');
1799 if ($alertmsg) {
1800 echo "alert(" . js_escape($alertmsg) . ");\n";
1804 * Setup channel with portal
1805 * Mainly for form submission from remote for now.
1806 * umm you never know!
1807 * */
1808 <?php if (empty($is_core)) { ?>
1809 $(function () {
1810 window.addEventListener("message", (e) => {
1811 if (event.origin !== window.location.origin) {
1812 signerAlertMsg(<?php echo xlj("Request is not same origin!") ?>, 15000);
1813 return false;
1815 if (e.data.submitForm === true) {
1816 let pass = validate(document.forms[0], false);
1817 if (pass) {
1818 signerAlertMsg(<?php echo xlj("Working on request.") ?>, 5000, 'info');
1819 e.preventDefault();
1820 document.forms[0].submit();
1821 } else {
1822 signerAlertMsg(<?php echo xlj("Form validation failed. Fix any errors and resubmit.") ?>);
1823 return false;
1825 } else if (e.data.submitForm === 'history') {
1826 e.preventDefault();
1827 let portal_form_pid = Number(<?php echo js_escape($portal_form_pid); ?>);
1828 if (portal_form_pid) {
1829 signerAlertMsg(<?php echo xlj("Charting History.") ?>, 5000, 'info');
1830 } else {
1831 signerAlertMsg(<?php echo xlj("Sorry. Can not update history.") ?>, 8000, 'danger');
1832 return false;
1834 top.restoreSession();
1835 document.forms[0].action = "<?php echo $rootdir; ?>/patient_file/history/history_save.php?requestPid=" + encodeURIComponent(portal_form_pid);
1836 document.forms[0].onsubmit = "";
1837 document.forms[0].submit();
1841 <?php }
1842 if (empty($is_core) && !empty($_POST['bn_save_continue'])) { ?>
1843 /* post event to portal with current formid from save/edit action */
1844 parent.postMessage({formid:<?php echo attr($formid) ?>}, window.location.origin);
1845 <?php } ?>
1846 </script>
1847 </div>
1848 </body>
1849 </html>