From c3156c27afc476d63b2eedb9ff88f817545074e7 Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Tue, 30 Jan 2024 20:25:59 -0500 Subject: [PATCH 01/11] Weno bug fixes (#7198) * Weno bug fixes - rename class file because of case difference. windows doesn't care but linux does * -Weno Management download fixes. - wrong global.php path - using short codes is a no no - add a confirm warning to pharmacy download. * - Fix demographic Coices pharmacy search - somecode cleanup (cherry picked from commit 5a7dfb8cfe4c072ce37c43cd5fde4880e5527764) --- .../oe-module-weno/scripts/file_download.php | 2 +- .../scripts/weno_pharmacy_search.php | 34 +-- .../src/Services/LogImportBuild.php | 4 +- .../src/Services/PharmacyService.php | 2 +- ...iesImport.php => WenoPharmaciesImport.php} | 5 + .../oe-module-weno/templates/facilities.php | 7 +- .../templates/pharmacy_list_form.php | 263 +++++++++--------- 7 files changed, 166 insertions(+), 151 deletions(-) rename interface/modules/custom_modules/oe-module-weno/src/Services/{wenoPharmaciesImport.php => WenoPharmaciesImport.php} (98%) diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php index a4b7185182f..4e120cb9dee 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php @@ -3,7 +3,7 @@ // Disable PHP timeout @ini_set('max_execution_time', '0'); -require_once dirname(__DIR__, 5) . "/globals.php"; +require_once dirname(__DIR__, 4) . "/globals.php"; use OpenEMR\Common\Logging\EventAuditLogger; diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php index 915cfca70a7..ac4490daad1 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php @@ -52,12 +52,12 @@ $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . "FROM weno_pharmacy WHERE Business_Name LIKE ?"; - $weno_coverage = $_GET['coverage'] ? $_GET['coverage'] : ''; - $weno_state = $_GET['weno_state'] ? $_GET['weno_state'] : ''; - $weno_city = $_GET['weno_city'] ? $_GET['weno_city'] : ''; + $weno_coverage = $_GET['coverage'] ?: ''; + $weno_state = $_GET['weno_state'] ?: ''; + $weno_city = $_GET['weno_city'] ?: ''; $full_day = $_GET['full_day'] ? 'Yes' : ''; $weno_only = $_GET['weno_only'] ? 'True' : ''; - $weno_zipcode = $_GET['weno_zipcode'] ? $_GET['weno_zipcode'] : ''; + $weno_zipcode = $_GET['weno_zipcode'] ?: ''; $weno_test_pharmacies = $_GET['test_pharmacy'] ? 'True' : ''; @@ -103,24 +103,24 @@ } if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_drop') { - $term = filter_input(INPUT_GET, "term"); - $val = '%' . $term . '%'; - $params[] = $val; - $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . - "FROM weno_pharmacy WHERE"; + "FROM weno_pharmacy WHERE 1=1"; - $weno_coverage = $_GET['coverage'] ? $_GET['coverage'] : ''; - $weno_state = $_GET['weno_state'] ? $_GET['weno_state'] : ''; - $weno_city = $_GET['weno_city'] ? $_GET['weno_city'] : ''; + $weno_coverage = $_GET['coverage'] ?: ''; + $weno_state = $_GET['weno_state'] ?: ''; + $weno_city = $_GET['weno_city'] ?: ''; $full_day = $_GET['full_day'] ? 'Yes' : ''; - $weno_zipcode = $_GET['weno_zipcode'] ? $_GET['weno_zipcode'] : ''; - $weno_test_pharmacies = $_GET['test_pharmacy'] ? 'True' : ''; + $weno_zipcode = $_GET['weno_zipcode'] ?: ''; + $weno_test_pharmacies = $_GET['test_pharmacy'] == 'true' ? 'True' : ''; if (!empty($weno_state)) { - $sql .= " state = ?"; + $sql .= " AND state = ?"; $params[] = $weno_state; } + if (!empty($weno_zipcode)) { + $sql .= " AND ZipCode = ?"; + $params[] = $weno_zipcode; + } if (!empty($weno_coverage)) { $sql .= " AND state_wide_mail_order = ?"; $params[] = $weno_coverage; @@ -133,10 +133,6 @@ $sql .= " AND 24HR = ?"; $params[] = $full_day; } - if (!empty($weno_zipcode)) { - $sql .= " AND ZipCode = ?"; - $params[] = $weno_zipcode; - } if (!empty($weno_test_pharmacies)) { $sql .= " AND test_pharmacy = ?"; $params[] = $weno_test_pharmacies; diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php index 0f9e572def7..8ac1d093ed6 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php @@ -22,11 +22,13 @@ public function __construct() public function getUserIdByWenoId($external_provider_id) { + // This is important so a user is set in prescription table. $provider = sqlQuery("SELECT id FROM users WHERE weno_prov_id = ? ", array($external_provider_id)); if ($provider) { return $provider['id']; } else { - return null; + // logged in user is auth weno user so let's ensure a user is set. + return $_SESSION["authUserID"] ?? null; } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php index c906ec55336..38566fb227d 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php @@ -158,7 +158,7 @@ public function insertPharmacies($insertdata) $insertdata['pharmacy_phone'], $insertdata['on_weno'], $insertdata['test_pharmacy'], - $insertdata['state_wide_mail'], + $insertdata['state_wide_mail'] ?? '', $insertdata['fullDay'], ]); } catch (Exception $e) { diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php similarity index 98% rename from interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php rename to interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php index 8a78cb55701..9bf7d1cba4f 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/wenoPharmaciesImport.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php @@ -18,6 +18,11 @@ public function __construct() { } + /** + * @param $csvFile + * @param $files + * @return string|void + */ public function importPharmacy($csvFile, $files) { $insertPharmacy = new PharmacyService(); diff --git a/interface/modules/custom_modules/oe-module-weno/templates/facilities.php b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php index a8937c4a70e..c7fde34c858 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/facilities.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php @@ -73,10 +73,13 @@ function activateFacility(){ } function downloadPharmacies(){ + if (!window.confirm(jsText("This download may take several minutes. Do you want to continue?"))) { + return false; + } $('#notch-pharm').removeClass("hide"); $('#pharm-btn').attr("disabled", true); $.ajax({ - url: "" + "/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php", + url: "" + "/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php", type: "GET", success: function (data) { $('#notch-pharm').addClass("hide"); @@ -96,7 +99,7 @@ function downloadPresLog(){ $('#notch-presc').removeClass("hide"); $('#presc-btn').attr("disabled", true); $.ajax({ - url: "" + "/interface/modules/custom_modules/oe-module-weno/templates/synch.php", + url: "" + "/interface/modules/custom_modules/oe-module-weno/templates/synch.php", type: "GET", data: {key:'downloadLog'}, success: function (data) { diff --git a/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php index 9857c3de3c6..a1a39346cf7 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/pharmacy_list_form.php @@ -17,10 +17,10 @@ require_once $GLOBALS['srcdir'] . '/options.inc.php'; -use OpenEMR\Modules\WenoModule\Services\PharmacyService; -use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Twig\TwigContainer; +use OpenEMR\Modules\WenoModule\Services\PharmacyService; if (!AclMain::aclCheckCore('patients', 'med')) { echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Pharmacy Selector")]); @@ -29,8 +29,8 @@ $widgetConstants = [ 'listWithAddButton' => 26 - ,'textDate' => 4 - ,'textbox' => 2 + , 'textDate' => 4 + , 'textbox' => 2 ]; global $pid; // we need to grab our pid from our global settings. @@ -53,10 +53,10 @@ ?>
@@ -69,7 +69,8 @@
-

+
+
@@ -81,9 +82,9 @@
@@ -124,7 +125,7 @@
-
@@ -159,7 +160,7 @@ var wenoOnly = null; var testPharmacies = null; var wenoPrimPharm = null; - var wenoValChanged= null; + var wenoValChanged = null; var wenoAltPharm = null; var requirdField = "Field is required"; @@ -169,82 +170,83 @@ var weno_form = document.getElementById("weno_form"); var clone = document.importNode(template.content, true); weno_form.appendChild(clone); - + let pid = ; let prevPrimPharmacy = ; let prevAltPharmacy = ; - if(pid > 0){ + if (pid > 0) { init(prevPrimPharmacy, prevAltPharmacy); } //checking if weno_pharmacy div exists initialize select2 var pharmacySelector = document.getElementById("weno_pharmacy"); - if(pharmacySelector !== null){ + if (pharmacySelector !== null) { createWenoPharmacySelect2(); - } + } //checking if city div div exists and initialize select2 var citySelector = document.getElementById("weno_city"); - if(citySelector !== null){ + if (citySelector !== null) { createWenoCitySelect2(); } - + }; - function init(prevPrimPharmacy, prevAltPharmacy){ - let jsPrim = JSON.parse(prevPrimPharmacy); + function init(prevPrimPharmacy, prevAltPharmacy) { + let jsPrim = JSON.parse(prevPrimPharmacy); let jsAlt = JSON.parse(prevAltPharmacy); - if(jsPrim != false){ - var html= (''); + if (jsPrim != false) { + var html = (''); $("#weno_pharmacy").html(html); - + //setting the form value for Weno Primary Pharmacy and Disply Text respectivley $('#weno_primary').text(" " + jsPrim.business_name); $('#primary_pharmacy').val(jsPrim.primary_ncpdp); } - - if(jsAlt != false){ + + if (jsAlt != false) { $('#weno_alt').text(" " + jsAlt.business_name); $('#alternate_pharmacy').val(jsAlt.alternate_ncpdp); } } - function pharmSelChanged(){ + function pharmSelChanged() { var e = document.getElementById("weno_pharmacy"); this.wenoValChanged = e.options[e.selectedIndex].value; this.wenoPrimPharm = e.options[e.selectedIndex].text; } - function stateChanged(){ + function stateChanged() { var wenoState = document.getElementById('weno_state').selectedOptions[0].value; this.wenoState = wenoState; } - function cityChanged(){ + function cityChanged() { var wenoCity = document.getElementById('weno_city').selectedOptions[0].value; this.wenoCity = wenoCity; } - function onWenoChanged(cb){ + function onWenoChanged(cb) { this.wenoOnly = cb.checked; } - function coverageChanged(){ + function coverageChanged() { var coverage = document.getElementById('weno_coverage').selectedOptions[0].value; this.coverage = coverage; } - function fullDayChanged(cb){ + function fullDayChanged(cb) { this.fullDay = cb.checked; } - function testPharmaciesChanged(cb){ + + function testPharmaciesChanged(cb) { this.testPharmacies = cb.checked; } - function doAjax(){ + function doAjax() { var state = document.getElementById('form_weno_state').selectedOptions[0].value; var coverage = document.getElementById('weno_coverage').selectedOptions[0].value; @@ -252,115 +254,122 @@ function doAjax(){ url: url, cache: false, type: "GET", - data: {state: state, coverage: coverage }, - success: function(data){ + data: {state: state, coverage: coverage}, + success: function (data) { var html = ''; - if(data.length > 0){ - $.each(JSON.parse(data), function (i, value){ - html += (''); - }); + if (data.length > 0) { + $.each(JSON.parse(data), function (i, value) { + html += (''); + }); $("#weno_pharmacy").html(html); } } }); } - function createWenoPharmacySelect2(){ + function createWenoPharmacySelect2() { $('#weno_pharmacy').select2({ - width: '500px', - ajax: { - url: '' + '/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php', - dataType: 'json', - data: function(params){ - return { - term: params.term, - searchFor: 'weno_pharmacy', - coverage: coverage, - weno_state: wenoState, - weno_city: wenoCity, - weno_only: wenoOnly, - full_day: fullDay, - csrf_token_form: csrf - }; + width: '500px', + ajax: { + url: '' + '/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php', + dataType: 'json', + data: function (params) { + return { + term: params.term, + searchFor: 'weno_pharmacy', + coverage: coverage, + weno_state: wenoState, + weno_city: wenoCity, + weno_only: wenoOnly, + full_day: fullDay, + csrf_token_form: csrf + }; + }, + processResults: function (data) { + return { + results: $.map(data, function (item, index) { + return { + text: item.name, + id: item.ncpdp, + value: item.ncpdp + } + }) + }; + } }, - processResults: function(data) { - return { - results: $.map(data, function(item, index) { - return { - text: item.name, - id: item.ncpdp, - value: item.ncpdp - } - }) - }; - } - }, - minimumInputLength: 3, - cache: true, - placeholder: 'Enter desired Pharmacy', - allowClear: true, - }); + minimumInputLength: 3, + cache: true, + placeholder: 'Enter desired Pharmacy', + allowClear: true, + }); } - function createWenoCitySelect2(){ + function createWenoCitySelect2() { $('#weno_city').select2({ - width: '98%', - allowClear: true, - ajax: { - url: '' + '/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php', - dataType: 'json', - data: function(params){ - return { - term: params.term, - searchFor: 'weno_city', - csrf_token_form: csrf - }; + width: '98%', + allowClear: true, + ajax: { + url: '' + '/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php', + dataType: 'json', + data: function (params) { + return { + term: params.term, + searchFor: 'weno_city', + csrf_token_form: csrf + }; + }, + processResults: function (data) { + return { + results: $.map(data, function (item, index) { + return { + text: item, + id: item, + value: item + } + }) + }; + } }, - processResults: function(data) { - return { - results: $.map(data, function(item, index) { - return { - text: item, - id: item, - value: item - } - }) - }; - } - }, - minimumInputLength: 3, - cache: true, - placeholder: 'Enter City *' - }); + minimumInputLength: 3, + cache: true, + placeholder: 'Enter City *' + }); } - function search(){ + function search() { this.wenoZipcode = $('#weno_zipcode').val(); - if(wenoState !== null && wenoCity !== null && coverage !== null){ + if (( wenoCity > '' || this.wenoZipcode > '') && wenoState > '' && coverage > '') { + $('#weno_city').removeClass("is-invalid"); + $('.warn').text(''); + $('#weno_state').removeClass("is-invalid"); + $('#weno_coverage').removeClass("is-invalid"); var select2field = document.getElementById('weno_pharmacy'); var field = select2field.classList.contains('select2-hidden-accessible'); //check if select2 is active and remove it before using the normal dropdown - if(field){ + if (field) { $('#weno_pharmacy').select2('destroy').off('select2:open'); } makeRequest(); - }else{ - if(wenoCity !== ''){ + } else { + // reset errors + $('#weno_city').removeClass("is-invalid"); + $('.warn').text(''); + $('#weno_state').removeClass("is-invalid"); + $('#weno_coverage').removeClass("is-invalid"); + if (wenoCity <= '' && this.wenoZipcode <= '') { $('#weno_city').addClass("is-invalid"); $('.warn').text(requirdField); } - if(this.wenoState == ''){ + if (this.wenoState <= '') { $('#weno_state').addClass("is-invalid"); } - if(coverage != ''){ + if (coverage <= '') { $('#weno_coverage').addClass("is-invalid"); } - - //$('.warn').text(requirdField); } } - function makeRequest(){ + function makeRequest() { let data = { searchFor: 'weno_drop', weno_state: wenoState, @@ -374,19 +383,19 @@ function makeRequest(){ $.ajax({ url: '' + '/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php', type: "GET", - data:data, + data: data, success: function (data) { var html = ''; data = JSON.parse(data); - if(data == null){ - html += (''); - }else{ - html += (''); + if (data == null) { + html += (''); + } else { + html += (''); $.each(data, function (i, value) { html += (''); }); } - + $("#weno_pharmacy").html(html); }, // Error handling @@ -396,21 +405,21 @@ function makeRequest(){ } - function assignPrimaryPharmacy(){ + function assignPrimaryPharmacy() { weno_pharm = $('#weno_pharmacy').val(); weno_pharm_text = $('#weno_pharmacy').text(); $('#weno_primary').text(" " + wenoPrimPharm); $('#primary_pharmacy').val(weno_pharm); } - function assignAlternatePharmacy(){ + function assignAlternatePharmacy() { weno_alt = $('#weno_pharmacy').val(); weno_alt_text = $('#weno_pharmacy').text(); $('#weno_alt').text(" " + wenoPrimPharm); $('#alternate_pharmacy').val(weno_alt); } - function resetForm(){ + function resetForm() { var searchbox = document.getElementById("weno_state"); searchbox.selectedIndex = 0; @@ -423,15 +432,15 @@ function resetForm(){ resetSelect2(); } - function resetSelect2(){ + function resetSelect2() { var select2field = document.getElementById('weno_pharmacy'); var field = select2field.classList.contains('select2-hidden-accessible'); - if(field){ + if (field) { $('#weno_pharmacy').val('').trigger('change'); - }else { + } else { $('#weno_pharmacy').val(''); } } - + From dc36725a7efe38c768de5107c25f37e81b44b39a Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Fri, 2 Feb 2024 21:50:27 -0500 Subject: [PATCH 02/11] Weno fixes and updates (#7204) * Weno fixes and updates - Improve pharmacy import by using transactional queries. From 4 minutes to 40 seconds. - improve validation and error reporting. - some code cleanup for warnings and in general - fix frame screen output to use the current theme so user always see content. * - fix block style how nitpicking is this! * - fix all header blocks. * - no clue * php warning * styles * - I was running ci on wrong directory! tsktsk * - don't log thounsands of inserts --------- Co-authored-by: stephen waite (cherry picked from commit e77ac66edb5655233d67314af76235ef13fc7962) --- .../oe-module-weno/scripts/file_download.php | 163 ++++++++++-------- .../oe-module-weno/scripts/weno_log_sync.php | 3 +- .../oe-module-weno/src/Services/Container.php | 2 +- .../src/Services/DownloadWenoPharmacies.php | 9 +- .../src/Services/FacilityProperties.php | 2 +- .../src/Services/LogDataInsert.php | 2 +- .../src/Services/LogImportBuild.php | 2 +- .../src/Services/LogProperties.php | 2 +- .../src/Services/PharmacyService.php | 2 +- .../src/Services/TransmitProperties.php | 20 ++- .../src/Services/WenoPharmaciesImport.php | 159 ++++++++--------- .../src/Services/WenoPharmaciesJson.php | 4 +- .../oe-module-weno/templates/facilities.php | 4 +- .../oe-module-weno/templates/indexrx.php | 5 +- .../oe-module-weno/templates/rxlogmanager.php | 9 +- .../oe-module-weno/templates/synch.php | 3 +- interface/super/edit_globals.php | 2 +- 17 files changed, 210 insertions(+), 183 deletions(-) diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php index 4e120cb9dee..501c3eaecca 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php @@ -13,9 +13,9 @@ use OpenEMR\Modules\WenoModule\Services\PharmacyService; $cryptoGen = new CryptoGen(); -$weno_username = $GLOBALS['weno_admin_username']; -$weno_password = $cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); -$encryption_key = $cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); +$weno_username = $GLOBALS['weno_admin_username'] ?? ''; +$weno_password = $cryptoGen->decryptStandard($GLOBALS['weno_admin_password'] ?? ''); +$encryption_key = $cryptoGen->decryptStandard($GLOBALS['weno_encryption_key'] ?? ''); $baseurl = "https://online.wenoexchange.com/en/EPCS/DownloadPharmacyDirectory"; $data = array( @@ -105,87 +105,98 @@ function download_zipfile($fileUrl, $zipped_file) $l = 0; if (file_exists($csvFile)) { + // let's do transaction as this is long import $records = fopen($csvFile, "r"); - - while (!feof($records)) { - $line = fgetcsv($records); - - if ($l <= 1) { - $l++; - continue; - } - if (!isset($line[1])) { - continue; + try { + if ($records ?? null) { + sqlStatementNoLog('SET autocommit=0'); + sqlStatementNoLog('START TRANSACTION'); } - if (!isset($line[1])) { - continue; - } - if (!empty($line)) { - if ($data['Daily'] == 'N') { - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[5]); - $business_name = $line[6]; - $address_line_1 = $line[7]; - $address_line_2 = $line[8]; - $city = $line[9]; - $state = $line[10]; - $zipcode = str_replace(['[', ']'], '', $line[11]); - $country = $line[12]; - $international = $line[13]; - $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); - $on_weno = $line[21]; - $test_pharmacy = $line[17]; - $state_wide_mail = $line[18]; - $fullDay = $line[22]; - } else { - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[7]); - $business_name = $line[8]; - $city = $line[11]; - $state = $line[12]; - $zipcode = str_replace(['[', ']'], '', $line[14]); - $country = $line[15]; - $address_line_1 = $line[9]; - $address_line_2 = $line[10]; - $international = $line[16]; - $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); - $county = $line[33]; - $on_weno = $line[37]; - $compounding = $line[41]; - $medicaid_id = $line[45]; - $dea = $line[44]; - $test_pharmacy = $line[29]; - $fullDay = $line[40]; - $state_wide_mail = $line[47]; - } + while (!feof($records)) { + $line = fgetcsv($records); - $insertdata['ncpdp'] = $ncpdp; - $insertdata['npi'] = $npi; - $insertdata['business_name'] = $business_name; - $insertdata['address_line_1'] = $address_line_1; - $insertdata['address_line_2'] = $address_line_2; - $insertdata['city'] = $city; - $insertdata['state'] = $state; - $insertdata['zipcode'] = $zipcode; - $insertdata['country'] = $country; - $insertdata['international'] = $international; - $insertdata['pharmacy_phone'] = $pharmacy_phone; - $insertdata['on_weno'] = $on_weno; - $insertdata['test_pharmacy'] = $test_pharmacy; - $insertdata['state_wide_mail'] = $state_wide_mail; - $insertdata['fullDay'] = $fullDay; - - if ($data['Daily'] == 'Y') { - $insertPharmacy->updatePharmacies($insertdata); - } else { - $insertPharmacy->insertPharmacies($insertdata); + if ($l <= 1) { + $l++; + continue; + } + if (!isset($line[1])) { + continue; + } + if (!isset($line[1])) { + continue; + } + if (!empty($line)) { + if ($data['Daily'] == 'N') { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[5]); + $business_name = $line[6]; + $address_line_1 = $line[7]; + $address_line_2 = $line[8]; + $city = $line[9]; + $state = $line[10]; + $zipcode = str_replace(['[', ']'], '', $line[11]); + $country = $line[12]; + $international = $line[13]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); + $on_weno = $line[21]; + $test_pharmacy = $line[17]; + $state_wide_mail = $line[18]; + $fullDay = $line[22]; + } else { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[7]); + $business_name = $line[8]; + $city = $line[11]; + $state = $line[12]; + $zipcode = str_replace(['[', ']'], '', $line[14]); + $country = $line[15]; + $address_line_1 = $line[9]; + $address_line_2 = $line[10]; + $international = $line[16]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); + $county = $line[33]; + $on_weno = $line[37]; + $compounding = $line[41]; + $medicaid_id = $line[45]; + $dea = $line[44]; + $test_pharmacy = $line[29]; + $fullDay = $line[40]; + $state_wide_mail = $line[47]; + } + + $insertdata['ncpdp'] = $ncpdp; + $insertdata['npi'] = $npi; + $insertdata['business_name'] = $business_name; + $insertdata['address_line_1'] = $address_line_1; + $insertdata['address_line_2'] = $address_line_2; + $insertdata['city'] = $city; + $insertdata['state'] = $state; + $insertdata['zipcode'] = $zipcode; + $insertdata['country'] = $country; + $insertdata['international'] = $international; + $insertdata['pharmacy_phone'] = $pharmacy_phone; + $insertdata['on_weno'] = $on_weno; + $insertdata['test_pharmacy'] = $test_pharmacy; + $insertdata['state_wide_mail'] = $state_wide_mail; + $insertdata['fullDay'] = $fullDay; + + if ($data['Daily'] == 'Y') { + $insertPharmacy->updatePharmacies($insertdata); + } else { + $insertPharmacy->insertPharmacies($insertdata); + } + + ++$l; } - - ++$l; } + } catch (Exception $e) { + throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } $wenolog->insertWenoLog("pharmacy", "Success"); fclose($records); + sqlStatementNoLog('COMMIT'); + sqlStatementNoLog('SET autocommit=1'); + foreach ($files as $file) { if (is_file($file)) { unlink($file); diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php index 62ac8531043..114c989c577 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php @@ -1,12 +1,13 @@ * @copyright Copyright (c) 2021 Sherwin Gaddis * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ + use OpenEMR\Common\Crypto\CryptoGen; use OpenEMR\Modules\WenoModule\Services\LogProperties; use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesJson; diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php b/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php index 0367820a5a9..1bca4abed7b 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php @@ -1,6 +1,6 @@ diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php index 50767b7d80b..553e50a3099 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php @@ -1,6 +1,6 @@ @@ -38,9 +38,9 @@ public function retrieveDataFile($url, $storelocation) $result = $this->extractFile($path_to_extract, $storelocation); if ($result == "Imported") { - return "complete"; + return "Imported"; } else { - return "failed"; + return $result; } } @@ -74,6 +74,9 @@ public function extractFile($path_to_extract, $storelocation) $result = $import->importPharmacy($csvFile, $files); if ($result == "Imported") { $wenolog->insertWenoLog("pharmacy", "Success"); + return $result; + } else { + return $result; } return "Imported"; diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php index 8f837f343f2..a1f627f38cf 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/FacilityProperties.php @@ -1,6 +1,6 @@ diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php index e4fe30b702e..3b21c4ade65 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php @@ -1,6 +1,6 @@ diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php index 8ac1d093ed6..20abc03f089 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php @@ -1,6 +1,6 @@ diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php index 110a7fee76e..bc145872d0a 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php @@ -1,6 +1,6 @@ diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php index 38566fb227d..448a63b100d 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/PharmacyService.php @@ -144,7 +144,7 @@ public function insertPharmacies($insertdata) $sql .= "24hr = ? "; try { - sqlInsert($sql, [ + sqlStatementNoLog($sql, [ $insertdata['ncpdp'], $insertdata['npi'], $insertdata['business_name'], diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php index 4f47599b778..263d8ddc40d 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php @@ -171,12 +171,19 @@ private function getPatientInfo() ++$missing; } if ($missing > 0) { - echo "
" . $log . "
"; - die('Please add the missing data and try again'); + $this->errorWithDie($log); } return $patient; } + public function errorWithDie($error) + { + $log = "

" . + $error . "
" . xlt('Please address errors and try again') . + "

"; + die($log); + } + /** * @return string * New Rx @@ -230,7 +237,8 @@ public function getPharmacy() { $data = sqlQuery("SELECT * FROM `weno_assigned_pharmacy` WHERE `pid` = ? ", [$_SESSION["pid"]]); if (empty($data)) { - die("Weno Pharmacies not set. head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Pharmacies"); + $log = xlt("Weno Pharmacies not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Pharmacies"); + $this->errorWithDie($log); } $response = array( "primary" => $data['primary_ncpdp'], @@ -238,11 +246,13 @@ public function getPharmacy() ); if (empty($response['primary'])) { - die("Weno Primary Pharmacy not set. Head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Primary Pharmacy"); + $log = xlt("Weno Primary Pharmacy not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); + $this->errorWithDie($log); } if (empty($response['alternate'])) { - die("Weno Alternate Pharmacy not set. Head over to Patient's Demographics select Choices select Weno Pharmacy Selector to Assign Primary Pharmacy"); + $log = xlt("Weno Alternate Pharmacy not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); + $this->errorWithDie($log); } return $response; } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php index 9bf7d1cba4f..845c855e045 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php @@ -1,6 +1,6 @@ @@ -10,7 +10,7 @@ namespace OpenEMR\Modules\WenoModule\Services; -use OpenEMR\Modules\WenoModule\Services\PharmacyService; +use Exception; class WenoPharmaciesImport { @@ -27,94 +27,99 @@ public function importPharmacy($csvFile, $files) { $insertPharmacy = new PharmacyService(); $insertdata = []; - $checkWenoDb = new PharmacyService(); - $has_data = $checkWenoDb->checkWenoDb(); + $has_data = $insertPharmacy->checkWenoDb(); $l = 0; if (file_exists($csvFile)) { $records = fopen($csvFile, "r"); - while (!feof($records)) { - $line = fgetcsv($records); + try { + while (!feof($records)) { + $line = fgetcsv($records); - if ($l <= 1) { - $l++; - continue; - } - if (!isset($line[1])) { - continue; - } - if (!isset($line[1])) { - continue; - } - if (!empty($line)) { - if (date("l") == 'Monday' || !$has_data) { //build for weekly file - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[5]); - $business_name = $line[6]; - $address_line_1 = $line[7]; - $address_line_2 = $line[8]; - $city = $line[9]; - $state = $line[10]; - $zipcode = str_replace(['[', ']'], '', $line[11]); - $country = $line[12]; - $international = $line[13]; - $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); - $on_weno = $line[21]; - $test_pharmacy = $line[17]; - $state_wide_mail = $line[18]; - $fullDay = $line[22]; - } else { - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[7]); - $business_name = $line[8]; - $city = $line[11]; - $state = $line[12]; - $zipcode = str_replace(['[', ']'], '', $line[14]); - $country = $line[15]; - $address_line_1 = $line[9]; - $address_line_2 = $line[10]; - $international = $line[16]; - $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); - $county = $line[33]; - $on_weno = $line[37]; - $compounding = $line[41]; - $medicaid_id = $line[45]; - $dea = $line[44]; - $test_pharmacy = $line[29]; - $fullDay = $line[40]; - $state_wide_mail = $line[47]; + if ($l <= 1) { + $l++; + continue; } - - $insertdata['ncpdp'] = $ncpdp; - $insertdata['npi'] = $npi; - $insertdata['business_name'] = $business_name; - $insertdata['address_line_1'] = $address_line_1; - $insertdata['address_line_2'] = $address_line_2; - $insertdata['city'] = $city; - $insertdata['state'] = $state; - $insertdata['zipcode'] = $zipcode; - $insertdata['country'] = $country; - $insertdata['international'] = $international; - $insertdata['pharmacy_phone'] = $pharmacy_phone; - $insertdata['on_weno'] = $on_weno; - $insertdata['test_pharmacy'] = $test_pharmacy; - $insertdata['state_wide_mail'] = $state_wide_mail; - $insertdata['fullDay'] = $fullDay; - if ($has_data && date("l") == 'Monday') { - $insertPharmacy->updatePharmacies($insertdata); + if (!isset($line[1])) { + continue; } - if ($has_data && date("l") != 'Monday') { - $insertPharmacy->updatePharmacies($insertdata); - } - if (!$has_data) { - $insertPharmacy->insertPharmacies($insertdata); + if (!isset($line[1])) { + continue; } + if (!empty($line)) { + if (date("l") == 'Monday' || !$has_data) { //build for weekly file + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[5]); + $business_name = $line[6]; + $address_line_1 = $line[7]; + $address_line_2 = $line[8]; + $city = $line[9]; + $state = $line[10]; + $zipcode = str_replace(['[', ']'], '', $line[11]); + $country = $line[12]; + $international = $line[13]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); + $on_weno = $line[21]; + $test_pharmacy = $line[17]; + $state_wide_mail = $line[18]; + $fullDay = $line[22]; + } else { + $ncpdp = str_replace(['[', ']'], '', $line[3]); + $npi = str_replace(['[', ']'], '', $line[7]); + $business_name = $line[8]; + $city = $line[11]; + $state = $line[12]; + $zipcode = str_replace(['[', ']'], '', $line[14]); + $country = $line[15]; + $address_line_1 = $line[9]; + $address_line_2 = $line[10]; + $international = $line[16]; + $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); + $county = $line[33]; + $on_weno = $line[37]; + $compounding = $line[41]; + $medicaid_id = $line[45]; + $dea = $line[44]; + $test_pharmacy = $line[29]; + $fullDay = $line[40]; + $state_wide_mail = $line[47]; + } + + $insertdata['ncpdp'] = $ncpdp; + $insertdata['npi'] = $npi; + $insertdata['business_name'] = $business_name; + $insertdata['address_line_1'] = $address_line_1; + $insertdata['address_line_2'] = $address_line_2; + $insertdata['city'] = $city; + $insertdata['state'] = $state; + $insertdata['zipcode'] = $zipcode; + $insertdata['country'] = $country; + $insertdata['international'] = $international; + $insertdata['pharmacy_phone'] = $pharmacy_phone; + $insertdata['on_weno'] = $on_weno; + $insertdata['test_pharmacy'] = $test_pharmacy; + $insertdata['state_wide_mail'] = $state_wide_mail; + $insertdata['fullDay'] = $fullDay; + if ($has_data && date("l") == 'Monday') { + $insertPharmacy->updatePharmacies($insertdata); + } + if ($has_data && date("l") != 'Monday') { + $insertPharmacy->updatePharmacies($insertdata); + } + if (!$has_data) { + $insertPharmacy->insertPharmacies($insertdata); + } - ++$l; + ++$l; + } } + } catch (Exception $e) { + return $e->getMessage(); } fclose($records); + sqlStatementNoLog('COMMIT'); + sqlStatementNoLog('SET autocommit=1'); foreach ($files as $file) { if (is_file($file)) { unlink($file); diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php index 31d6327fafa..ab674f7e3ab 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesJson.php @@ -1,6 +1,6 @@ @@ -34,7 +34,7 @@ public function storePharmacyDataJson() $url = $this->wenoPharmacyDirectoryLink() . "?useremail=" . urlencode($this->providerEmail()) . "&data=" . urlencode($this->encrypted); $getWenoPharmaciesCsv = new DownloadWenoPharmacies(); $storageLocation = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/"; - $c = $getWenoPharmaciesCsv->retrieveDataFile($url, $storageLocation); + return $getWenoPharmaciesCsv->retrieveDataFile($url, $storageLocation); } private function buildJson() diff --git a/interface/modules/custom_modules/oe-module-weno/templates/facilities.php b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php index c7fde34c858..cabf408afb9 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/facilities.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/facilities.php @@ -1,6 +1,6 @@ @@ -73,7 +73,7 @@ function activateFacility(){ } function downloadPharmacies(){ - if (!window.confirm(jsText("This download may take several minutes. Do you want to continue?"))) { + if (!window.confirm(xl("This download may take several minutes. Do you want to continue?"))) { return false; } $('#notch-pharm').removeClass("hide"); diff --git a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php index d690f23689b..76bca3f7caa 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php @@ -1,6 +1,6 @@ @@ -15,7 +15,7 @@ use OpenEMR\Common\Acl\AclMain; use OpenEMR\Common\Twig\TwigContainer; - +use OpenEMR\Core\Header; use OpenEMR\Modules\WenoModule\Services\PharmacyService; use OpenEMR\Modules\WenoModule\Services\Container; @@ -73,6 +73,7 @@ <?php echo xlt('Weno eRx') ?> + diff --git a/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php index a145c2efdf2..34f2c7cf5b0 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php @@ -1,6 +1,6 @@ @@ -32,12 +32,7 @@ $url = "https://online.wenoexchange.com/en/EPCS/RxLog?useremail="; -// I don't understand why you wouldn't escape email -// Let me know if there is a good reason not to. -//**warning** do not add urlencode to $provider_info['email']. -$urlOut = $url . urlencode($provider_info['email']) . "&data=" . urlencode($logurlparam); -// Setting a location header here overrides tab html and iFrame. -//header("Location: " . $urlOut); +$urlOut = $url . urlencode($provider_info['email'] ?? '') . "&data=" . urlencode($logurlparam); ?> <?php echo xlt("Weno RxLog") ?> diff --git a/interface/modules/custom_modules/oe-module-weno/templates/synch.php b/interface/modules/custom_modules/oe-module-weno/templates/synch.php index 45e5bae872a..17d53c17c60 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/synch.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/synch.php @@ -1,12 +1,13 @@ * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ + require_once(dirname(__DIR__, 4) . "/globals.php"); use OpenEMR\Modules\WenoModule\Services\LogProperties; diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index 585acb24890..968bd7d3850 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -142,7 +142,7 @@ function checkBackgroundServices() * Setup background services for Weno when it is enabled * this is to sync the prescription logs */ - $wenoservices = $GLOBALS['weno_rx_enable'] == 1 ? '1' : '0'; + $wenoservices = ($GLOBALS['weno_rx_enable'] ?? '') == 1 ? '1' : '0'; updateBackgroundService('WenoExchange', $wenoservices, 60); updateBackgroundService('WenoExchangePharmacies', $wenoservices, 1440); } From df4165d5f993e15abe75b4e404006094e5a48d2f Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Sun, 4 Feb 2024 21:13:26 -0500 Subject: [PATCH 03/11] - fix transaction for pharmacy download (#7208) - refactor user defualt fac to include select from user facility when user is not logged into facility. - convert error to interface style helper to static - create static styler for echo to interface. - refactor all show errors to include a style compatable with themes. (cherry picked from commit 520263d6921e2a8c79b5cc35fb3c61ff741cdc57) --- .../src/Services/LogProperties.php | 9 +-- .../src/Services/TransmitProperties.php | 67 ++++++++++++------- .../src/Services/WenoPharmaciesImport.php | 4 ++ .../oe-module-weno/templates/indexrx.php | 3 +- .../oe-module-weno/templates/rxlogmanager.php | 5 +- .../oe-module-weno/templates/synch.php | 3 +- 6 files changed, 57 insertions(+), 34 deletions(-) diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php index bc145872d0a..8fcd64de1e9 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php @@ -143,7 +143,7 @@ public function logSync() $logurlparam = $this->logEpcs(); $syncLogs = "https://online.wenoexchange.com/en/EPCS/DownloadNewRxSyncDataVal?useremail="; if ($logurlparam == 'error') { - echo xlt("Cipher failure check encryption key"); + echo TransmitProperties::styleErrors(xlt("Cipher failure check encryption key")); error_log("Cipher failure check encryption key", time()); exit; } @@ -187,16 +187,17 @@ public function getProviderEmail() if (!empty($provider_info)) { return $provider_info; } else { - $error = "Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"; + $error = xlt("Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"); error_log($error); - exit; + TransmitProperties::errorWithDie($error); } } else if ($GLOBALS['weno_admin_username']) { $provider_info["email"] = $GLOBALS['weno_admin_username']; return $provider_info; } else { - $error = "Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"; + $error = xlt("Provider email address is missing. Go to User settings Weno tab to add provider's weno registered email address"); error_log($error); + echo TransmitProperties::styleErrors($error); exit; } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php index 263d8ddc40d..320ba60befb 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php @@ -15,6 +15,7 @@ namespace OpenEMR\Modules\WenoModule\Services; use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Services\FacilityService; class TransmitProperties { @@ -98,13 +99,13 @@ public function createJsonObject() } /** - * @return mixed + * @return array|void */ public function getProviderEmail() { $provider_info = ['email' => $GLOBALS['weno_provider_email']]; if (empty($provider_info['email'])) { - echo xlt('Provider email address is missing. Go to [User Settings select Weno Tab] and enter your Weno Provider Password'); + echo self::styleErrors(xlt('Provider email address is missing and required. Go to User Settings select Weno Tab and enter your Weno Provider Password')); exit; } else { return $provider_info; @@ -112,24 +113,31 @@ public function getProviderEmail() } /** - * @return mixed + * @return array|false|null */ - public function getFacilityInfo() + public function getFacilityInfo(): array|null|false { - $locid = sqlQuery("select name, street, city, state, postal_code, phone, fax, weno_id from facility where id = ?", [$_SESSION['facilityId'] ?? null]); + // is user logged into facility + if (!empty($_SESSION['facilityId'])) { + $locId = sqlQuery("select name, street, city, state, postal_code, phone, fax, weno_id from facility where id = ?", [$_SESSION['facilityId'] ?? null]); + } else { + // from users facility + $facilityService = new FacilityService(); + $locId = $facilityService->getFacilityForUser($_SESSION['authUserID']); + } - if (empty($locid['weno_id'])) { + if (empty($locId['weno_id'])) { //if not in an encounter then get the first facility location id as default - $default_facility = sqlQuery("SELECT name, street, city, state, postal_code, phone, fax, weno_id from facility order by id asc limit 1"); + $default_facility = sqlQuery("SELECT name, street, city, state, postal_code, phone, fax, weno_id from facility order by id limit 1"); - if (empty($default_facility)) { - echo xlt('Facility ID is missing. head over to Admin -> Other -> Weno Management. Enter the Weno ID of your facility'); + if (empty($default_facility['weno_id'])) { + echo self::styleErrors(xlt('Facility ID is missing. From Admin select Other then Weno Management. Enter the Weno ID of your facility')); exit; } else { return $default_facility; } } - return $locid; + return $locId; } /** @@ -147,40 +155,47 @@ private function getPatientInfo() } $patient = sqlQuery("select title, fname, lname, mname, street, state, city, email, phone_cell, postal_code, dob, sex, pid from patient_data where pid=?", [$_SESSION['pid']]); if (empty($patient['fname'])) { - $log .= xlt("First Name Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . ""; + $log .= xlt("Last Name Missing, From the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['dob'])) { - $log .= xlt("Date of Birth Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . "
"; + $log .= xlt("Date of Birth Missing, From the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['sex'])) { - $log .= xlt("Gender Missing, head over to the Patient Chart select Demographics select Who. Save and retry") . "
"; + $log .= xlt("Gender Missing, From the Patient Chart select Demographics select Who. Save and retry") . "
"; ++$missing; } if (empty($patient['postal_code'])) { - $log .= xlt("Zip Code Missing, head over to the Patient Chart select Demographics select Contact select Postal Code. Save and retry") . "
"; + $log .= xlt("Zip Code Missing, From the Patient Chart select Demographics select Contact select Postal Code. Save and retry") . "
"; ++$missing; } if (empty($patient['street'])) { - $log .= xlt("Street Address incomplete Missing, head over to the Patient Chart select Demographics select Contact. Save and retry") . "
"; + $log .= xlt("Street Address incomplete Missing, From the Patient Chart select Demographics select Contact. Save and retry") . "
"; ++$missing; } if ($missing > 0) { - $this->errorWithDie($log); + self::errorWithDie($log); } return $patient; } - public function errorWithDie($error) + public static function styleErrors($error): string { - $log = "

" . - $error . "
" . xlt('Please address errors and try again') . + $log = "

" . + $error . "
" . xlt('Please address errors and try again!') . + "
" . xlt("Use browser Back button or Click Patient Name from top Patient bar.") . "

"; + return $log; + } + + public static function errorWithDie($error): void + { + $log = self::styleErrors($error); die($log); } @@ -237,8 +252,8 @@ public function getPharmacy() { $data = sqlQuery("SELECT * FROM `weno_assigned_pharmacy` WHERE `pid` = ? ", [$_SESSION["pid"]]); if (empty($data)) { - $log = xlt("Weno Pharmacies not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Pharmacies"); - $this->errorWithDie($log); + $log = xlt("Weno Pharmacies not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Pharmacies"); + self::errorWithDie($log); } $response = array( "primary" => $data['primary_ncpdp'], @@ -246,13 +261,13 @@ public function getPharmacy() ); if (empty($response['primary'])) { - $log = xlt("Weno Primary Pharmacy not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); - $this->errorWithDie($log); + $log = xlt("Weno Primary Pharmacy not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); + self::errorWithDie($log); } if (empty($response['alternate'])) { - $log = xlt("Weno Alternate Pharmacy not set. Head over to Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); - $this->errorWithDie($log); + $log = xlt("Weno Alternate Pharmacy not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); + self::errorWithDie($log); } return $response; } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php index 845c855e045..91cd93c0d76 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoPharmaciesImport.php @@ -34,6 +34,10 @@ public function importPharmacy($csvFile, $files) $records = fopen($csvFile, "r"); try { + if ($records ?? null) { + sqlStatementNoLog('SET autocommit=0'); + sqlStatementNoLog('START TRANSACTION'); + } while (!feof($records)) { $line = fgetcsv($records); diff --git a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php index 76bca3f7caa..1e4fb953a6a 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php @@ -18,6 +18,7 @@ use OpenEMR\Core\Header; use OpenEMR\Modules\WenoModule\Services\PharmacyService; use OpenEMR\Modules\WenoModule\Services\Container; +use OpenEMR\Modules\WenoModule\Services\TransmitProperties; //ensure user has proper access @@ -46,7 +47,7 @@ $newRxUrl = "https://online.wenoexchange.com/en/NewRx/ComposeRx?useremail="; if ($urlParam == 'error') { //check to make sure there were no errors - echo xlt("Cipher failure check encryption key"); + echo TransmitProperties::styleErrors(xlt("Cipher failure check encryption key")); exit; } ?> diff --git a/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php index 34f2c7cf5b0..2ad2eba07f5 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/rxlogmanager.php @@ -12,12 +12,13 @@ use OpenEMR\Common\Acl\AclMain; use OpenEMR\Modules\WenoModule\Services\LogProperties; +use OpenEMR\Modules\WenoModule\Services\TransmitProperties; /* * access control is on Weno side based on the user login */ if (!AclMain::aclCheckCore('patient', 'med')) { - echo xlt('Prescriptions Review Not Authorized'); + echo TransmitProperties::styleErrors(xlt('Prescriptions Review Not Authorized')); exit; } @@ -26,7 +27,7 @@ $provider_info = $log_properties->getProviderEmail(); if ($logurlparam == 'error') { - echo xlt("Cipher failure check encryption key"); + echo TransmitProperties::styleErrors(xlt("Cipher failure check encryption key")); exit; } diff --git a/interface/modules/custom_modules/oe-module-weno/templates/synch.php b/interface/modules/custom_modules/oe-module-weno/templates/synch.php index 17d53c17c60..e5a1017f291 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/synch.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/synch.php @@ -12,12 +12,13 @@ use OpenEMR\Modules\WenoModule\Services\LogProperties; use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Modules\WenoModule\Services\TransmitProperties; /* * access control is on Weno side based on the user login */ if (!AclMain::aclCheckCore('patient', 'med')) { - echo xlt('Prescriptions Review Not Authorized'); + echo TransmitProperties::styleErrors(xlt('Prescriptions Review Not Authorized')); exit; } From 714f409dd24a593a59c699ff2318981c11cf2a1c Mon Sep 17 00:00:00 2001 From: stephen waite Date: Wed, 7 Feb 2024 14:04:29 -0500 Subject: [PATCH 04/11] feat: support worker's comp electronic claims (#7207) (cherry picked from commit 74279455c5881de6b4f5b9e38e5176a9d989bc76) --- src/Billing/X125010837P.php | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Billing/X125010837P.php b/src/Billing/X125010837P.php index f601efaa7b2..be0ca7bb29e 100644 --- a/src/Billing/X125010837P.php +++ b/src/Billing/X125010837P.php @@ -17,6 +17,7 @@ namespace OpenEMR\Billing; +use OpenEMR\Billing\BillingProcessor\BillingClaimBatchControlNumber; use OpenEMR\Billing\Claim; class X125010837P @@ -678,8 +679,11 @@ public static function genX12837P( "*" . "Y" . "*" . ($claim->billingFacilityAssignment() ? 'A' : 'C') . "*" . ($claim->billingFacilityAssignment() ? 'Y' : 'N') . - "*" . "Y" . - "~\n"; + "*" . "Y" . "*" . "P"; // added patient signature source code CLM10 + if ($claim->isRelatedEmployment()) { + $out .= "*" . "EM"; + } + $out .= "~\n"; // above is for historical use of encounter onset date, now in misc_billing_options // Segment DTP*431 (Onset of Current Symptoms or Illness) @@ -764,9 +768,25 @@ public static function genX12837P( // Segments DTP (Assumed and Relinquished Care Dates) omitted. // Segment DTP*444 (Property and Casualty Date of First Contact) omitted. // Segment DTP*050 (Repricer Received Date) omitted. - // Segment PWK (Claim Supplemental Information) omitted. // Segment CN1 (Contract Information) omitted. + /* Segment PWK for medical attachments + * TODO: implement medical attachments :) + * Hardcode OZ, support data for claim, PWK01 report type code + * Hardcode EL, electronic, PWK02 report transmission code + * Hardcode AC, attachment control number + * Billing claim batch control number 9 digits for PWK06 + */ + if ($claim->isRelatedEmployment()) { + $out .= "PWK" . + "*" . "OZ" . + "*" . "EL" . + "*" . "*" . + "*" . "AC" . + "*" . BillingClaimBatchControlNumber::getIsa13() . + "~"; + } + $patientpaid = $claim->patientPaidAmount(); if ($patientpaid != 0) { ++$edicount; From 5a9f23bc41b3d0cec183a3c1eac5e79c53b575ef Mon Sep 17 00:00:00 2001 From: Stephen Nielson Date: Sat, 10 Feb 2024 19:21:49 -0500 Subject: [PATCH 05/11] Fixes #7214 pass action status to listener (#7215) Action status was not being passed in the listener. Fixes #7214 (cherry picked from commit b0cfafc45ce5601edc30b06ec55926251db7f835) --- .../Installer/src/Installer/Controller/InstallerController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/modules/zend_modules/module/Installer/src/Installer/Controller/InstallerController.php b/interface/modules/zend_modules/module/Installer/src/Installer/Controller/InstallerController.php index 82883f403f9..74fbf92b8a0 100644 --- a/interface/modules/zend_modules/module/Installer/src/Installer/Controller/InstallerController.php +++ b/interface/modules/zend_modules/module/Installer/src/Installer/Controller/InstallerController.php @@ -213,7 +213,7 @@ private function callModuleAfterAction($action, $modId, $dirModule, $currentStat $instance = $className::initListenerSelf(); if (class_exists($instance::class)) { if (method_exists($instance, 'moduleManagerAction')) { - return call_user_func([$instance, 'moduleManagerAction'], $methodName, $modId); + return call_user_func([$instance, 'moduleManagerAction'], $methodName, $modId, $currentStatus); } else { return $currentStatus; } From 5c9473429ab864358353e42ca9c27644ed0b4c1e Mon Sep 17 00:00:00 2001 From: Stephen Nielson Date: Mon, 12 Feb 2024 09:47:19 -0500 Subject: [PATCH 06/11] Fixes #7219 email validate allow empty strings. (#7220) This allows empty strings to be validated. Fixes #7219. (cherry picked from commit 8ac331bea71de2fe110dbb941e929d1ac3615a32) --- src/Validators/PatientValidator.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Validators/PatientValidator.php b/src/Validators/PatientValidator.php index 0c8b2ebbbee..9dbd0486751 100644 --- a/src/Validators/PatientValidator.php +++ b/src/Validators/PatientValidator.php @@ -58,7 +58,11 @@ function (Validator $context) { $context->required("sex", 'Gender')->lengthBetween(4, 30); $context->required("DOB", 'Date of Birth')->datetime('Y-m-d'); // callback functions are not called for optional parameters unless allowEmpty is false - $context->optional("email", "Email", false)->callback(function ($value) { + $context->optional("email", "Email") + ->required(function ($values) { + return array_key_exists('email', $values) && $values['email'] !== '' && $values['email'] !== null; + }) + ->callback(function ($value) { // Validator->email() does not cover unicode characters in the local part so we use // the OpenEMR email validator for this. if (!ValidationUtils::isValidEmail($value)) { From e531b18cf3c3d06b1ac7703eba46ef0ebec4e743 Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Mon, 12 Feb 2024 22:51:58 -0500 Subject: [PATCH 07/11] - restyle logs view (#7222) - code standards usergroup_admin (cherry picked from commit e153cbb0e537eb2c6a343d7fc9a3a63aef7d304c) --- interface/logview/logview.php | 886 ++++++++++++------------ interface/usergroup/usergroup_admin.php | 28 +- 2 files changed, 463 insertions(+), 451 deletions(-) diff --git a/interface/logview/logview.php b/interface/logview/logview.php index 9870290ba07..57227b2234b 100644 --- a/interface/logview/logview.php +++ b/interface/logview/logview.php @@ -6,7 +6,9 @@ * @package OpenEMR * @link http://www.open-emr.org * @author Brady Miller + * @author Jerry Padgett * @copyright Copyright (c) 2017-2019 Brady Miller + * @copyright Copyright (c) 2024 Jerry Padgett * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ @@ -38,19 +40,16 @@ - -
-
-
-
-

+
+
+
+
+

+
-
-
-
- -
-
-
-
-
- $end_date) { - echo "
"; - echo xlt('Start Date should not be greater than End Date'); - echo "
"; - $err_message = 1; - } - - if (!empty($_GET["form_patient"])) { - $form_patient = isset($_GET["form_patient"]) ? $_GET["form_patient"] : ""; - } - - ?> - - -
-

-
- - - - - -
- -
- -
- -
- -
- -
- ' onclick='sel_patient()' title='' /> - -
-
-
- -
- -
- +
+

+ + + + + + +
+ +
+ +
+ +
+ +
+ +
+ ' onclick='sel_patient()' title='' /> + +
+
+
+ +
+ +
+ - -
- -
- -
- \n"; - echo " \n"; - echo "\n"; - } else { - echo " -
-
- -
- -
- - - - -
- -
- - -
- - - - - - - - - - - - - - - " /> - getEvents(array('sdate' => $start_date,'edate' => $end_date, 'user' => $form_user, 'patient' => $form_pid, 'sortby' => $_GET['sortby'], 'levent' => $gev, 'tevent' => $tevent,'direction' => $_GET['direction']))) { - // Set up crypto object (object will increase performance since caches used keys) - $cryptoGen = new CryptoGen(); - - while ($iter = sqlFetchArray($ret)) { - if (empty($iter['id'])) { - //skip empty log items (this means they were deleted and will show up as deleted in the audit log tamper script) - continue; - } - - //translate comments - $patterns = array ('/^success/','/^failure/','/ encounter/'); - $replace = array ( xl('success'), xl('failure'), xl('encounter', '', ' ')); - - if (!empty($iter['encrypt'])) { - $commentEncrStatus = $iter['encrypt']; - } else { - $commentEncrStatus = "No"; - } - if (!empty($iter['version'])) { - $encryptVersion = $iter['version']; - } else { - $encryptVersion = 0; - } - - // Decrypt comment data if encrypted - if ($commentEncrStatus == "Yes") { - if ($encryptVersion >= 3) { - // Use new openssl method - if (extension_loaded('openssl')) { - $trans_comments = $cryptoGen->decryptStandard($iter["comments"]); - if ($trans_comments !== false) { - $trans_comments = preg_replace($patterns, $replace, $trans_comments); - } else { - $trans_comments = xl("Unable to decrypt these comments since decryption failed."); + +
+ +
+ +
+ \n"; + echo " \n"; + echo "\n"; } else { - $trans_comments = xl("Unable to decrypt these comments since the PHP openssl module is not installed."); + echo ""; + ?> +
+ + +
+ +
+ + + +
+ +
+ + +
+
+ + + + + + + + + + + + + + + + " /> + aes256Decrypt_mycrypt($iter["comments"])); + + if (($eventname == "") && ($type_event != "")) { + $tevent = $type_event; + } elseif ($type_event == "" && $eventname != "") { + $gev = $eventname; + } elseif ($eventname == "") { + $gev = ""; } else { - $trans_comments = xl("Unable to decrypt these comments since the PHP mycrypt module is not installed."); + $gev = $getevent; } - } - } else { - // base64 decode if applicable (note the $encryptVersion is a misnomer here, we have added in base64 encoding - // of comments in OpenEMR 6.0.0 and greater when the comments are not encrypted since they hold binary (uuid) elements) - if ($encryptVersion >= 4) { - $iter["comments"] = base64_decode($iter["comments"]); - } - $trans_comments = preg_replace($patterns, $replace, $iter["comments"]); - } - ?> - - - - - - - - - - - - - - - - - getEvents(array('sdate' => $start_date, 'edate' => $end_date, 'user' => $form_user, 'patient' => $form_pid, 'sortby' => $_GET['sortby'], 'levent' => $gev, 'tevent' => $tevent, 'direction' => $_GET['direction']))) { + // Set up crypto object (object will increase performance since caches used keys) + $cryptoGen = new CryptoGen(); + + while ($iter = sqlFetchArray($ret)) { + if (empty($iter['id'])) { + //skip empty log items (this means they were deleted and will show up as deleted in the audit log tamper script) + continue; + } + + //translate comments + $patterns = array('/^success/', '/^failure/', '/ encounter/'); + $replace = array(xl('success'), xl('failure'), xl('encounter', '', ' ')); + + if (!empty($iter['encrypt'])) { + $commentEncrStatus = $iter['encrypt']; + } else { + $commentEncrStatus = "No"; + } + if (!empty($iter['version'])) { + $encryptVersion = $iter['version']; + } else { + $encryptVersion = 0; + } + + // Decrypt comment data if encrypted + if ($commentEncrStatus == "Yes") { + if ($encryptVersion >= 3) { + // Use new openssl method + if (extension_loaded('openssl')) { + $trans_comments = $cryptoGen->decryptStandard($iter["comments"]); + if ($trans_comments !== false) { + $trans_comments = preg_replace($patterns, $replace, $trans_comments); + } else { + $trans_comments = xl("Unable to decrypt these comments since decryption failed."); + } + } else { + $trans_comments = xl("Unable to decrypt these comments since the PHP openssl module is not installed."); + } + } elseif ($encryptVersion == 2) { + // Use new openssl method + if (extension_loaded('openssl')) { + $trans_comments = $cryptoGen->aes256DecryptTwo($iter["comments"]); + if ($trans_comments !== false) { + $trans_comments = preg_replace($patterns, $replace, $trans_comments); + } else { + $trans_comments = xl("Unable to decrypt these comments since decryption failed."); + } + } else { + $trans_comments = xl("Unable to decrypt these comments since the PHP openssl module is not installed."); + } + } elseif ($encryptVersion == 1) { + // Use new openssl method + if (extension_loaded('openssl')) { + $trans_comments = preg_replace($patterns, $replace, $cryptoGen->aes256DecryptOne($iter["comments"])); + } else { + $trans_comments = xl("Unable to decrypt these comments since the PHP openssl module is not installed."); + } + } else { //$encryptVersion == 0 + // Use old mcrypt method + if (extension_loaded('mcrypt')) { + $trans_comments = preg_replace($patterns, $replace, $cryptoGen->aes256Decrypt_mycrypt($iter["comments"])); + } else { + $trans_comments = xl("Unable to decrypt these comments since the PHP mycrypt module is not installed."); + } + } + } else { + // base64 decode if applicable (note the $encryptVersion is a misnomer here, we have added in base64 encoding + // of comments in OpenEMR 6.0.0 and greater when the comments are not encrypted since they hold binary (uuid) elements) + if ($encryptVersion >= 4) { + $iter["comments"] = base64_decode($iter["comments"]); + } + $trans_comments = preg_replace($patterns, $replace, $iter["comments"]); + } + ?> + + + + + + + + + + + + + + + + + + getEvents(array('sdate' => $start_date,'edate' => $end_date, 'user' => $form_user, 'patient' => $form_pid, 'sortby' => $_GET['sortby'], 'event' => $eventname))) { - while ($iter = sqlFetchArray($ret)) { - $comments = xl('Recipient Name') . ":" . $iter["recipient"] . ";" . xl('Disclosure Info') . ":" . $iter["description"]; - ?> - - - - - - - - - - - - - -
-
+
+ if (($eventname == "disclosure") || ($gev == "")) { + $eventname = "disclosure"; + if ($ret = EventAuditLogger::instance()->getEvents(array('sdate' => $start_date, 'edate' => $end_date, 'user' => $form_user, 'patient' => $form_pid, 'sortby' => $_GET['sortby'], 'event' => $eventname))) { + while ($iter = sqlFetchArray($ret)) { + $comments = xl('Recipient Name') . ":" . $iter["recipient"] . ";" . xl('Disclosure Info') . ":" . $iter["description"]; + ?> + + + + + + + + + + + + + + +
+ +
- -
-
+
-
-
-
-
-
-
-
-

-
- '> - '> +
+
+
+
+
+

+
+ '> + '> +
-
-
- - +
+ + diff --git a/interface/usergroup/usergroup_admin.php b/interface/usergroup/usergroup_admin.php index 490afe73691..6de22846478 100644 --- a/interface/usergroup/usergroup_admin.php +++ b/interface/usergroup/usergroup_admin.php @@ -34,14 +34,8 @@ use OpenEMR\Events\User\UserUpdatedEvent; use OpenEMR\Events\User\UserCreatedEvent; -if (!empty($_POST)) { - if (!CsrfUtils::verifyCsrfToken($_POST["csrf_token_form"])) { - CsrfUtils::csrfNotVerified(); - } -} - -if (!empty($_GET)) { - if (!CsrfUtils::verifyCsrfToken($_GET["csrf_token_form"])) { +if (!empty($_REQUEST)) { + if (!CsrfUtils::verifyCsrfToken($_REQUEST["csrf_token_form"])) { CsrfUtils::csrfNotVerified(); } } @@ -260,7 +254,7 @@ sqlStatement("UPDATE users SET authorized = ?, active = ?, " . "calendar = ?, portal_user = ?, see_auth = ? WHERE " . "id = ? ", array($tqvar, $actvar, $calvar, $portalvar, $_POST['see_auth'], $_POST["id"])); - //Display message when Emergency Login user was activated + //Display message when Emergency Login user was activated if (is_countable($_POST['access_group'])) { $bg_count = count($_POST['access_group']); for ($i = 0; $i < $bg_count; $i++) { @@ -278,28 +272,28 @@ } } - if ($_POST["comments"]) { + if (isset($_POST["comments"])) { sqlStatement("update users set info = ? where id = ? ", array($_POST["comments"], $_POST["id"])); } - $erxrole = isset($_POST['erxrole']) ? $_POST['erxrole'] : ''; + $erxrole = $_POST['erxrole'] ?? ''; sqlStatement("update users set newcrop_user_role = ? where id = ? ", array($erxrole, $_POST["id"])); - if ($_POST["physician_type"]) { + if (isset($_POST["physician_type"])) { sqlStatement("update users set physician_type = ? where id = ? ", array($_POST["physician_type"], $_POST["id"])); } - if ($_POST["main_menu_role"]) { + if (isset($_POST["main_menu_role"])) { $mainMenuRole = filter_input(INPUT_POST, 'main_menu_role'); sqlStatement("update `users` set `main_menu_role` = ? where `id` = ? ", array($mainMenuRole, $_POST["id"])); } - if ($_POST["patient_menu_role"]) { + if (isset($_POST["patient_menu_role"])) { $patientMenuRole = filter_input(INPUT_POST, 'patient_menu_role'); sqlStatement("update `users` set `patient_menu_role` = ? where `id` = ? ", array($patientMenuRole, $_POST["id"])); } - if ($_POST["erxprid"]) { + if (isset($_POST["erxprid"])) { sqlStatement("update users set weno_prov_id = ? where id = ? ", array($_POST["erxprid"], $_POST["id"])); } @@ -532,13 +526,13 @@ } } } -// added for form submit's from usergroup_admin_add and user_admin.php +// added for form submits from usergroup_admin_add and user_admin.php // sjp 12/29/17 if (isset($_REQUEST["mode"])) { exit(text(trim($alertmsg))); } -$form_inactive = empty($_POST['form_inactive']) ? false : true; +$form_inactive = !empty($_POST['form_inactive']); ?> From 133e721d3b114b7749ae11329b16cc95a01c4c9e Mon Sep 17 00:00:00 2001 From: stephen waite Date: Sat, 17 Feb 2024 10:19:44 -0500 Subject: [PATCH 08/11] fix: bug in service facility logic (#7228) (cherry picked from commit a14b20dd401303a8faeef1c923e6a1d7dc72e594) --- src/Billing/X125010837P.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Billing/X125010837P.php b/src/Billing/X125010837P.php index be0ca7bb29e..62cce65e6ba 100644 --- a/src/Billing/X125010837P.php +++ b/src/Billing/X125010837P.php @@ -986,8 +986,9 @@ public static function genX12837P( } // End of Loop 2310B - // Loop 2310C is omitted in the case of home visits (POS=12). - if ($claim->facilityPOS() != 12 && ($claim->facilityNPI() != $claim->billingFacilityNPI())) { + // Loop 2310C is omitted in the case of home visits (POS=12) + // and when the service facility is the billing facility + if ($claim->facilityPOS() != 12 && ($claim->billing_facility['id'] != $claim->facility['id'])) { ++$edicount; $out .= "NM1" . // Loop 2310C Service Location "*" . "77" . From eee56ac6369e95e9e61107d1099aede4f5f17b93 Mon Sep 17 00:00:00 2001 From: stephen waite Date: Tue, 20 Feb 2024 14:18:21 -0500 Subject: [PATCH 09/11] fix: add space to fix broken LBF sql query (#7240) fixes #7239 (cherry picked from commit dfd3a220cd6da029b941cf57349f65e6bfa916ae) --- interface/forms/LBF/new.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/forms/LBF/new.php b/interface/forms/LBF/new.php index 28bba89b3e9..a80a8045a01 100644 --- a/interface/forms/LBF/new.php +++ b/interface/forms/LBF/new.php @@ -1074,7 +1074,7 @@ function warehouse_changed(sel) { "JOIN form_encounter AS e2 ON " . "e2.pid = e1.pid AND (e2.date < e1.date OR (e2.date = e1.date AND e2.encounter <= e1.encounter)) " . "JOIN shared_attributes AS sa ON " . - "sa.pid = e2.pid AND sa.encounter = e2.encounter AND sa.field_id = ?" . + "sa.pid = e2.pid AND sa.encounter = e2.encounter AND sa.field_id = ? " . "WHERE e1.pid = ? AND e1.encounter = ? " . "ORDER BY e2.date DESC, e2.encounter DESC LIMIT 1", array($field_id, $pid, $visitid) From a12c714a0b7459f4c69298f1fe1498a9ab159a3c Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Thu, 22 Feb 2024 12:43:35 -0500 Subject: [PATCH 10/11] Weno fixes and validations (#7209) * Weno fixes and validations - numerous warnings * - remove Config weno setup. - new service class. - add new Weno Module setup - add logic to prevent module event listeners unless admin credentials are set up. - add logic to show unregister and config icons if not credentials. - add Module Manager call to listener class on pre action events using pre prefix to action i.e. preeneble - using mod_ui_active flag from modules table to qualify some ui actions in module manager - many translations and warnings * - add encrypt and decrypt to globals * - added new manager feature that allows a flag `mod_ui_active` that when set indicates custom styles for buttons. - added a refresh if action listener return an error after alert is closed. - Restyled buttons with font awesome. - Fixed module config container to be responsive and follow themes. - table install fixes - more general code clean up. * - fix sync alert - refactor some BootService methods to static - more general code cleanup. * - change widget title - clean up widget action buttons * - Added an error panel to widget - validations refactors - code cleanup * - new validations for warnings in widget to notify but error level still allows work to proceed. - much error formatting * - Simplfy and refactor checkErrors() method. - Refactor errorWithDie() to echoError() method * - add icon and button to open dialog to render form to fix error item - more restylaes * - add help to setup - fix and restyle Weno Management. * - fix some missteps for url compose for errors - fix vitals eval - refactor cipher - prep to remove Container class * - fix lots of warnings - setup downloads logging - add weno prov id to user settings for back up - restyle choices pharmacy seletions and fix seach for zip - group city looku in UI to be unique - factored away Container class! deleted * - revamped pharmacy search to simplify - fix style color to themes * - add pharmacy download status in widget and choices - test download for fail status the reset anf reattemp - varius warnings * - rename the ModuleManagerAfterActionListener since it now listens for other events othe than after actions. * - add new alerts to widget - replace encounter with auth user to track user to prescription round trip - new age and phone format methods * - send responsible party if under 19 yo * - conditional wrong for guardian * - restyles and minor bug fixes * - add a return to demographics to weno eRx frame. * - add a secondary backup weno admin * - scrape return html errors within downloaded zip and csv files! * - add alerts from scraping weno download files since they don't send say a 401 or 403 status with response holding error. always a 200 regardless. * - move manage modules tab to admins tab currently opens to patient tab which is needed to be in view for editing. * - put back weno enable in globals Config * - logging changes - ensure we have a user id for prescriptions. (cherry picked from commit e670aa3d8961ccaa78e8c1e682db83f9b1c41bfb) --- interface/main/tabs/menu/menus/standard.json | 2 +- .../ModuleManagerActionListener.php | 106 ----- ...Listener.php => ModuleManagerListener.php} | 6 +- ...Listener.php => ModuleManagerListener.php} | 44 +- .../custom_modules/oe-module-weno/info.txt | 2 +- .../oe-module-weno/moduleConfig.php | 17 +- .../oe-module-weno/openemr.bootstrap.php | 2 +- .../oe-module-weno/public/assets/js/synch.js | 115 +++-- .../oe-module-weno/scripts/file_download.php | 146 +++--- .../oe-module-weno/scripts/weno_log_sync.php | 55 ++- .../scripts/weno_pharmacy_search.php | 99 ++-- .../oe-module-weno/sql/table.sql | 8 +- .../oe-module-weno/src/Bootstrap.php | 137 +++--- .../oe-module-weno/src/Services/Container.php | 61 --- .../src/Services/DownloadWenoPharmacies.php | 61 +-- .../src/Services/LogDataInsert.php | 2 - .../src/Services/LogImportBuild.php | 45 +- .../src/Services/LogProperties.php | 63 ++- .../src/Services/ModuleService.php | 179 ++++++++ .../src/Services/TransmitProperties.php | 432 +++++++++++++----- .../src/Services/WenoLogService.php | 62 ++- .../src/Services/WenoPharmaciesImport.php | 73 +-- .../src/Services/WenoPharmaciesJson.php | 28 +- .../oe-module-weno/src/WenoGlobalConfig.php | 118 +++-- .../oe-module-weno/templates/facilities.php | 54 ++- .../oe-module-weno/templates/indexrx.php | 168 ++++--- .../templates/pharmacy_list_display.php | 10 +- .../templates/pharmacy_list_form.php | 213 +++++---- .../oe-module-weno/templates/synch.php | 5 +- .../templates/weno_fragment.php | 89 +++- .../oe-module-weno/templates/weno_setup.php | 201 ++++++++ .../custom_modules/oe-module-weno/version.php | 2 +- .../Controller/InstallerController.php | 11 +- .../src/Installer/Model/InstModuleTable.php | 4 +- .../view/installer/installer/configure.phtml | 14 +- .../view/installer/installer/index.phtml | 64 +-- .../module/Installer/view/layout/layout.phtml | 4 +- .../public/js/installer/action.js | 373 ++++++++------- .../documents/custom_menus/Custom.json | 2 +- 39 files changed, 1869 insertions(+), 1208 deletions(-) delete mode 100644 interface/modules/custom_modules/oe-module-faxsms/ModuleManagerActionListener.php rename interface/modules/custom_modules/oe-module-faxsms/{ModuleManagerAfterActionListener.php => ModuleManagerListener.php} (95%) rename interface/modules/custom_modules/oe-module-weno/{ModuleManagerAfterActionListener.php => ModuleManagerListener.php} (81%) delete mode 100644 interface/modules/custom_modules/oe-module-weno/src/Services/Container.php create mode 100644 interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php create mode 100644 interface/modules/custom_modules/oe-module-weno/templates/weno_setup.php diff --git a/interface/main/tabs/menu/menus/standard.json b/interface/main/tabs/menu/menus/standard.json index ee399152dd8..d426a461096 100644 --- a/interface/main/tabs/menu/menus/standard.json +++ b/interface/main/tabs/menu/menus/standard.json @@ -501,7 +501,7 @@ { "label": "Manage Modules", "menu_id": "adm0", - "target": "pat", + "target": "adm", "url": "/interface/modules/zend_modules/public/Installer", "children": [], "requirement": 0, diff --git a/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerActionListener.php b/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerActionListener.php deleted file mode 100644 index 1f63efbf7d2..00000000000 --- a/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerActionListener.php +++ /dev/null @@ -1,106 +0,0 @@ - - * @copyright Copyright (c) 2024 Jerry Padgett - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -/* - * Currently register isn't supported and support should be a part of install. - * If an error needs to be reported to user, return description of error. - * However, whatever action trapped here has already occurred in Manager. - * Catch any exceptions because chances are they will be overlooked in Laminas module. - * Report them in return value. -*/ - -class ModuleManagerActionListener -{ - // Prevent instantiation - private function __construct() - { - } - - - /** - * @param $methodName - * @param $modId - * @param string $currentActionStatus - * @return string On method success a $currentAction status should be returned or error string. - */ - public static function moduleManagerAction($methodName, $modId, string $currentActionStatus = 'Success'): string - { - // Check if the action method exists - if (method_exists(self::class, $methodName)) { - return self::$methodName($modId, $currentActionStatus); - } else { - // TODO Perhaps this should be an exception! - return "Module cleanup method $methodName does not exist."; - } - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function install($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function enable($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function disable($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function unregister($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function install_sql($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } - - /** - * @param $modId - * @param $currentActionStatus - * @return mixed - */ - private static function upgrade_sql($modId, $currentActionStatus): mixed - { - return $currentActionStatus; - } -} diff --git a/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerAfterActionListener.php b/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerListener.php similarity index 95% rename from interface/modules/custom_modules/oe-module-faxsms/ModuleManagerAfterActionListener.php rename to interface/modules/custom_modules/oe-module-faxsms/ModuleManagerListener.php index 364b08299f4..7033a554240 100644 --- a/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerAfterActionListener.php +++ b/interface/modules/custom_modules/oe-module-faxsms/ModuleManagerListener.php @@ -32,7 +32,7 @@ $classLoader->registerNamespaceIfNotExists("OpenEMR\\Modules\\FaxSMS\\", __DIR__ . DIRECTORY_SEPARATOR . 'src'); */ -class ModuleManagerAfterActionListener extends AbstractModuleActionListener +class ModuleManagerListener extends AbstractModuleActionListener { public $service; private $authUser; @@ -75,9 +75,9 @@ public static function getModuleNamespace(): string * Required method to return this class object, * so it is instantiated in Laminas Manager. * - * @return ModuleManagerAfterActionListener + * @return ModuleManagerListener */ - public static function initListenerSelf(): ModuleManagerAfterActionListener + public static function initListenerSelf(): ModuleManagerListener { return new self(); } diff --git a/interface/modules/custom_modules/oe-module-weno/ModuleManagerAfterActionListener.php b/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php similarity index 81% rename from interface/modules/custom_modules/oe-module-weno/ModuleManagerAfterActionListener.php rename to interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php index 50bbcf62341..ec2cee1275e 100644 --- a/interface/modules/custom_modules/oe-module-weno/ModuleManagerAfterActionListener.php +++ b/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php @@ -31,10 +31,11 @@ */ use OpenEMR\Core\AbstractModuleActionListener; +use OpenEMR\Modules\WenoModule\Services\ModuleService; /* Allows maintenance of background tasks depending on Module Manager action. */ -class ModuleManagerAfterActionListener extends AbstractModuleActionListener +class ModuleManagerListener extends AbstractModuleActionListener { public function __construct() { @@ -73,9 +74,9 @@ public static function getModuleNamespace(): string * Required method to return this class object, * so it is instantiated in Laminas Manager. * - * @return ModuleManagerAfterActionListener + * @return ModuleManagerListener */ - public static function initListenerSelf(): ModuleManagerAfterActionListener + public static function initListenerSelf(): ModuleManagerListener { return new self(); } @@ -95,12 +96,33 @@ private function install($modId, $currentActionStatus): mixed * @param $currentActionStatus * @return mixed */ - private function enable($modId, $currentActionStatus): mixed + private function preenable($modId, $currentActionStatus): mixed { - $rtn = $this->setTaskState('1'); + $modService = new ModuleService(); + if ($modService->isWenoConfigured()) { + $modService::setModuleState($modId, '0', '0'); + return $currentActionStatus; + } + $modService::setModuleState($modId, '0', '1'); return $currentActionStatus; } + /** + * @param $modId + * @param $currentActionStatus + * @return mixed + */ + private function enable($modId, $currentActionStatus): mixed + { + $modService = new ModuleService(); + if ($modService->isWenoConfigured()) { + $modService::setModuleState($modId, '1', '0'); + return $currentActionStatus; + } + $modService::setModuleState($modId, '1', '1'); + return xlt("Weno eRx Service is not configured. Please configure Weno eRx Service in the Weno Module Setup."); + } + /** * @param $modId * @param $currentActionStatus @@ -108,7 +130,7 @@ private function enable($modId, $currentActionStatus): mixed */ private function disable($modId, $currentActionStatus): mixed { - $rtn = $this->setTaskState('0'); + ModuleService::setModuleState($modId, '0', '0'); return $currentActionStatus; } @@ -162,14 +184,4 @@ function getModuleRegistry($modId, $col = '*'): array return $registry; } - - /** - * @param $flag - * @return mixed - */ - private function setTaskState($flag): mixed - { - $sql_next = "UPDATE `background_services` SET `active` = ? WHERE `name` = ? OR `name` = ?"; - return sqlQuery($sql_next, array($flag, 'WenoExchange', 'WenoExchangePharmacies')); - } } diff --git a/interface/modules/custom_modules/oe-module-weno/info.txt b/interface/modules/custom_modules/oe-module-weno/info.txt index 16f17139939..930033b218f 100644 --- a/interface/modules/custom_modules/oe-module-weno/info.txt +++ b/interface/modules/custom_modules/oe-module-weno/info.txt @@ -1 +1 @@ -Weno EZ Integration Module \ No newline at end of file +Weno EZ Integration eRx Module v1.2.0 \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/moduleConfig.php b/interface/modules/custom_modules/oe-module-weno/moduleConfig.php index 6263c658fc8..60deab49f41 100644 --- a/interface/modules/custom_modules/oe-module-weno/moduleConfig.php +++ b/interface/modules/custom_modules/oe-module-weno/moduleConfig.php @@ -1,15 +1,20 @@ - * copyright Copyright (c )2021. Sherwin Gaddis - * license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - * + * @package OpenEMR Module + * @link http://www.open-emr.org + * @author Jerry Padgett + * @copyright Copyright (c) 2023-24 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ require_once dirname(__FILE__, 4) . '/globals.php'; $module_config = 1; +?> + + \ No newline at end of file diff --git a/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php b/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php index 62921dd37ef..96ce417af98 100644 --- a/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php +++ b/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php @@ -25,5 +25,5 @@ * @global EventDispatcher $eventDispatcher Injected by the OpenEMR module loader; */ -$bootstrap = new Bootstrap($eventDispatcher, $GLOBALS['kernel']); +$bootstrap = new Bootstrap($eventDispatcher); $bootstrap->subscribeToEvents(); diff --git a/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js b/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js index acce62f21af..3e6319247c0 100644 --- a/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js +++ b/interface/modules/custom_modules/oe-module-weno/public/assets/js/synch.js @@ -1,55 +1,108 @@ -function sync_weno(){ - var syncIcon = document.getElementById("sync-icon"); - var syncAlert = document.getElementById("sync-alert"); +function sync_weno() { + top.restoreSession(); + const syncIcon = document.getElementById("sync-icon"); + const syncAlert = document.getElementById("sync-alert"); const url = '../../modules/custom_modules/oe-module-weno/templates/synch.php'; - + syncIcon.classList.add("fa-spin"); - + let formData = new FormData(); formData.append("key", "sync"); - + fetch(url, { method: 'POST', body: formData - }) - .then(response => { + }).then(response => { if (!response.ok) { - // If the response status code is not in the 200-299 range, reject the promise - throw new Error('Server responded with an error status: ' + response.status); + // If the response status code is not in the 200-299 range, reject the promise + throw new Error('Server responded with an error status: ' + response.status); } else { - //setting alert details - wenoAlertManager("success",syncAlert,syncIcon); + // setting alert details + wenoAlertManager("success", syncAlert, syncIcon); } - - }).catch(error=> { + }).catch(error => { console.log(error.message) - wenoAlertManager("failed",syncAlert,syncIcon); + wenoAlertManager("failed", syncAlert, syncIcon); }); } - -function wenoAlertManager(option, element, spinElement){ + +function wenoAlertManager(option, element, spinElement) { + top.restoreSession(); spinElement.classList.remove("fa-spin"); - if(option == "success"){ + if (option === "success") { element.classList.remove("d-none"); element.classList.add("alert", "alert-success"); - element.innerHTML = "Successfully updated"; - window.location.reload(); + element.innerHTML = "Successfully updated"; setTimeout( - function(){ + function () { element.classList.add("d-none"); element.classList.remove("alert", "alert-success"); - element.innerHTML = ""; + element.innerHTML = ""; + window.location.reload(); }, 3000 - ); - + ); + } else { - setTimeout(function(){ + setTimeout(function () { element.classList.add("d-none"); element.classList.remove("alert", "alert-danger"); - element.innerHTML = ""; - }, 3000); - element.classList.remove("d-none"); - element.classList.add("alert", "alert-danger"); - element.innerHTML = "An error occurred"; + element.innerHTML = ""; + }, 5000); + element.classList.remove("d-none"); + element.classList.add("alert", "alert-danger"); + element.innerHTML = "An error occurred possibly credentials are wrong. Please check the credentials and try again."; + } +} + +// Reserved for future use. +function renderDialog(action, uid, event) { + event.preventDefault(); + // Trim action URL + action = action.trim(); + // Get CSRF token + const csrf = document.getElementById("csrf_token_form").value || ''; + // Map URLs + const urls = { + 'demographics': '/interface/patient_file/summary/demographics_full.php', + 'user_settings': '/interface/super/edit_globals.php?mode=user', + 'weno_manage': '/interface/modules/custom_modules/oe-module-weno/templates/facilities.php', + 'users': '/interface/usergroup/user_admin.php' + }; + // Construct action URL + const urlPart = urls[action].includes('?') ? '&' : '?'; + const actionUrl = `${urls[action]}${urlPart}id=${encodeURIComponent(uid)}&csrf_token_form=${encodeURIComponent(csrf)}`; + + if (urls[action] === undefined) { + console.error('Invalid action URL'); + alert(action.toUpperCase() + " " + xl('Direct action not implemented yet.')); + return; } -} \ No newline at end of file + // Open modal dialog + dlgopen('', 'dialog-mod', '900', 'full', '', '', { + buttons: [ + /*{ + text: jsText('Click'), + close: false, + id: jsAttr('click-me'), + click: function () { + //tidyUp(); + }, + style: 'primary' + },*/ + { + text: jsText('Return to eRx Widget'), + close: true, + style: 'primary' + } + ], + allowResize: true, + allowDrag: true, + dialogId: 'error-dialog', + type: 'iframe', + resolvePromiseOn: 'close', + url: top.webroot_url + actionUrl + }).then(function (dialog) { + top.restoreSession(); + window.location.reload(); + }); +} diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php index 501c3eaecca..c3bae6ab03f 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/file_download.php @@ -5,12 +5,11 @@ require_once dirname(__DIR__, 4) . "/globals.php"; -use OpenEMR\Common\Logging\EventAuditLogger; - use OpenEMR\Common\Crypto\CryptoGen; -use OpenEMR\Modules\WenoModule\Services\LogDataInsert; -use OpenEMR\Modules\WenoModule\Services\WenoLogService; +use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Modules\WenoModule\Services\PharmacyService; +use OpenEMR\Modules\WenoModule\Services\TransmitProperties; +use OpenEMR\Modules\WenoModule\Services\WenoLogService; $cryptoGen = new CryptoGen(); $weno_username = $GLOBALS['weno_admin_username'] ?? ''; @@ -19,24 +18,18 @@ $baseurl = "https://online.wenoexchange.com/en/EPCS/DownloadPharmacyDirectory"; $data = array( - "UserEmail" => $weno_username, - "MD5Password" => md5($weno_password), - "ExcludeNonWenoTest" => "N", - "Daily" => "N" + "UserEmail" => $weno_username, + "MD5Password" => md5($weno_password), + "ExcludeNonWenoTest" => "N", + "Daily" => "N" ); if (date("l") == "Monday") { //if today is Monday download the weekly file $data["Daily"] = "N"; +} else { + $data["Daily"] = "Y"; } -//check if there is history of download, if not do a weekly file -// $pharmacyService = new PharmacyService(); -// $db_exist = $pharmacyService->checkWenoPharmacyLog(); -// if($db_exist != "empty"){ -// $data["Daily"] = "Y"; -// } - - $json_object = json_encode($data); $method = 'aes-256-cbc'; @@ -66,10 +59,21 @@ function download_zipfile($fileUrl, $zipped_file) fclose($fp); } +$comment = "User Initiated Unscheduled Daily Pharmacy Import"; +if ($data['Daily'] == 'N') { + $comment = "User Initiated Unscheduled Weekly Pharmacy Import"; +} +EventAuditLogger::instance()->newEvent( + "pharmacy_log", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + $comment +); + download_zipfile($fileUrl, $storelocation); $zip = new ZipArchive(); - $wenolog = new WenoLogService(); if ($zip->open($storelocation) === true) { @@ -81,18 +85,26 @@ function download_zipfile($fileUrl, $zipped_file) $filename = basename($csvFile); $csvFilename = $filename; - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "File extracted successfully."); echo 'File extracted successfully.'; echo 'CSV filename: ' . text($csvFilename); $zip->close(); unlink($storelocation); } else { - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "No CSV file found in the zip archive."); + EventAuditLogger::instance()->newEvent("pharmacy_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "No CSV file found in the zip archive."); echo 'No CSV file found in the zip archive.'; } } else { - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Failed to extract the file."); - echo 'Failed to extract the file.'; + $rpt = file_get_contents($storelocation); + $isError = $wenolog->scrapeWenoErrorHtml($rpt); + if ($isError['is_error']) { + error_log('Pharmacy download failed: ' . $isError['messageText']); + $wenolog->insertWenoLog("pharmacy", "loginfail"); + } + EventAuditLogger::instance()->newEvent("pharmacy_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, $isError['messageText']); + $wenolog->insertWenoLog("pharmacy", "Failed"); + // no need to continue + // send error to UI alert + die(js_escape($isError['messageText'])); } $insertPharmacy = new PharmacyService(); @@ -122,46 +134,43 @@ function download_zipfile($fileUrl, $zipped_file) if (!isset($line[1])) { continue; } - if (!isset($line[1])) { - continue; - } if (!empty($line)) { if ($data['Daily'] == 'N') { - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[5]); - $business_name = $line[6]; - $address_line_1 = $line[7]; - $address_line_2 = $line[8]; - $city = $line[9]; - $state = $line[10]; + $ncpdp = str_replace(['[', ']'], '', $line[3] ?? ''); + $npi = str_replace(['[', ']'], '', $line[5] ?? ''); + $business_name = $line[6] ?? ''; + $address_line_1 = $line[7] ?? ''; + $address_line_2 = $line[8] ?? ''; + $city = $line[9] ?? ''; + $state = $line[10] ?? ''; $zipcode = str_replace(['[', ']'], '', $line[11]); - $country = $line[12]; - $international = $line[13]; + $country = $line[12] ?? ''; + $international = $line[13] ?? ''; $pharmacy_phone = str_replace(['[', ']'], '', $line[16]); - $on_weno = $line[21]; - $test_pharmacy = $line[17]; - $state_wide_mail = $line[18]; - $fullDay = $line[22]; + $on_weno = $line[21] ?? ''; + $test_pharmacy = $line[17] ?? ''; + $state_wide_mail = $line[18] ?? ''; + $fullDay = $line[22] ?? ''; } else { - $ncpdp = str_replace(['[', ']'], '', $line[3]); - $npi = str_replace(['[', ']'], '', $line[7]); - $business_name = $line[8]; - $city = $line[11]; - $state = $line[12]; - $zipcode = str_replace(['[', ']'], '', $line[14]); - $country = $line[15]; - $address_line_1 = $line[9]; - $address_line_2 = $line[10]; - $international = $line[16]; - $pharmacy_phone = str_replace(['[', ']'], '', $line[20]); - $county = $line[33]; - $on_weno = $line[37]; - $compounding = $line[41]; - $medicaid_id = $line[45]; - $dea = $line[44]; - $test_pharmacy = $line[29]; - $fullDay = $line[40]; - $state_wide_mail = $line[47]; + $ncpdp = str_replace(['[', ']'], '', $line[3] ?? ''); + $npi = str_replace(['[', ']'], '', $line[7] ?? ''); + $business_name = $line[8] ?? ''; + $city = $line[11] ?? ''; + $state = $line[12] ?? ''; + $zipcode = str_replace(['[', ']'], '', $line[14] ?? ''); + $country = $line[15] ?? ''; + $address_line_1 = $line[9] ?? ''; + $address_line_2 = $line[10] ?? ''; + $international = $line[16] ?? ''; + $pharmacy_phone = str_replace(['[', ']'], '', $line[20] ?? ''); + $county = $line[33] ?? ''; + $on_weno = $line[37] ?? ''; + $compounding = $line[41] ?? ''; + $medicaid_id = $line[45] ?? ''; + $dea = $line[44] ?? ''; + $test_pharmacy = $line[29] ?? ''; + $fullDay = $line[40] ?? ''; + $state_wide_mail = $line[47] ?? ''; } $insertdata['ncpdp'] = $ncpdp; @@ -185,25 +194,42 @@ function download_zipfile($fileUrl, $zipped_file) } else { $insertPharmacy->insertPharmacies($insertdata); } - ++$l; } } } catch (Exception $e) { throw new RuntimeException($e->getMessage(), $e->getCode(), $e); } - $wenolog->insertWenoLog("pharmacy", "Success"); + fclose($records); + // Start the transaction. sqlStatementNoLog('COMMIT'); sqlStatementNoLog('SET autocommit=1'); + // remove the files foreach ($files as $file) { if (is_file($file)) { unlink($file); } } - error_log("Pharmacy Imported"); + // let's brag about it. + EventAuditLogger::instance()->newEvent( + "pharmacy_log", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "User Initiated Pharmacy Download was Imported Successfully." + ); + $wenolog->insertWenoLog("pharmacy", "Success"); + error_log("User Initialed Pharmacy Imported"); } else { + EventAuditLogger::instance()->newEvent( + "pharmacy_log", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 0, + "Pharmacy Import download failed." + ); $wenolog->insertWenoLog("pharmacy", "Failed"); - error_log("file missing"); + error_log("User Initialed Pharmacy Import Failed File Missing"); } diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php index 114c989c577..23033780f45 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php @@ -1,38 +1,61 @@ - * @copyright Copyright (c) 2021 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + * @package OpenEMR + * @link http://www.open-emr.org + * @author Sherwin Gaddis + * @author Jerry Padgett + * @copyright Copyright (c) 2021 Sherwin Gaddis + * @copyright Copyright (c) 2024 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Modules\WenoModule\Services\LogProperties; use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesJson; function downloadWenoPharmacy() { $cryptoGen = new CryptoGen(); - $localPharmacyJson = new WenoPharmaciesJson( - $cryptoGen - ); + $localPharmacyJson = new WenoPharmaciesJson($cryptoGen); - //check if the background service is active and set intervals to once a day - //Weno has decided to not force the import of pharmacies since they are using the iframe - //and the pharmacy can be selected at the time of creating the prescription. + // Check if the background service is active. Intervals are set to once a day + // Weno has decided to not force the import of pharmacies since they are using the iframe + // and the pharmacy can be selected at the time of creating the prescription. $value = $localPharmacyJson->checkBackgroundService(); + + EventAuditLogger::instance()->newEvent( + "pharmacy_background", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "Init Background Pharmacy Download Service Status:" . text(ucfirst($value)) + ); if ($value == 'active' || $value == 'live') { + error_log('Background Initiated Pharmacy Download Started.'); + $status = $localPharmacyJson->storePharmacyDataJson(); - error_log('Weno pharmacies download complete with status:' . text($status)); + + EventAuditLogger::instance()->newEvent( + "pharmacy_background", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "Background Initiated Pharmacy Download Completed with Status:" . text($status) + ); + error_log('Background Initiated Weno Pharmacies download completed with status:' . text($status)); die; } } -function downloadWenoPrescriptionLog() +/** + * @throws Exception + */ +function downloadWenoPrescriptionLog(): void { - $logsync = new LogProperties(); - $logsync->logSync(); - error_log("Background services completed for prescription log"); + $logSync = new LogProperties(); + if (!$logSync->logSync()) { + error_log("Background services failed for prescription log."); + } } diff --git a/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php index ac4490daad1..a5641a68eae 100644 --- a/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php +++ b/interface/modules/custom_modules/oe-module-weno/scripts/weno_pharmacy_search.php @@ -6,14 +6,16 @@ * @package OpenEMR * @link https://www.open-emr.org * @author Kofi Appiah + * @author Jerry Padgett + * @copyright Copyright (c) 2024 Jerry Padgett * @copyright Copyright (c) 2023 Kofi Appiah * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ require_once(dirname(__DIR__, 5) . "/interface/globals.php"); -use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Acl\AclMain; +use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Twig\TwigContainer; if (!AclMain::aclCheckCore('patients', 'med')) { @@ -29,49 +31,53 @@ if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_city') { $return_arr = array(); - $term = filter_input(INPUT_GET, "term"); - $val = '%' . $term . '%'; - + $term = filter_input(INPUT_GET, "term"); + $val = $term . '%'; $params[] = $val; - $sql = "SELECT city, id FROM weno_pharmacy WHERE city LIKE ? LIMIT 10"; + $sql = "SELECT city, id FROM weno_pharmacy WHERE city LIKE ? GROUP BY city LIMIT 10"; $res = sqlStatement($sql, $params); while ($row = sqlFetchArray($res)) { - $return_arr[] = $row['city']; + $return_arr[] = ucwords(strtolower($row['city'])); } - echo text(json_encode($return_arr)); } if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_pharmacy') { - $term = filter_input(INPUT_GET, "term"); + $term = filter_input(INPUT_GET, "term"); $val = '%' . $term . '%'; $params[] = $val; $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . - "FROM weno_pharmacy WHERE Business_Name LIKE ?"; - - $weno_coverage = $_GET['coverage'] ?: ''; - $weno_state = $_GET['weno_state'] ?: ''; - $weno_city = $_GET['weno_city'] ?: ''; - $full_day = $_GET['full_day'] ? 'Yes' : ''; - $weno_only = $_GET['weno_only'] ? 'True' : ''; - $weno_zipcode = $_GET['weno_zipcode'] ?: ''; - $weno_test_pharmacies = $_GET['test_pharmacy'] ? 'True' : ''; + "FROM weno_pharmacy WHERE Business_Name LIKE ?"; + $weno_coverage = $_GET['coverage'] ?? false ?: ''; + $weno_state = $_GET['weno_state'] ?? false ?: ''; + $weno_city = $_GET['weno_city'] ?? false ?: ''; + $full_day = !empty($_GET['full_day']) ? 'Yes' : ''; + $weno_only = !empty($_GET['weno_only']) ? 'True' : ''; + $weno_zipcode = $_GET['weno_zipcode'] ?? false ?: ''; + $weno_test_pharmacies = !empty($_GET['test_pharmacy']) ? 'True' : ''; if (!empty($weno_coverage)) { $sql .= " AND state_wide_mail_order = ?"; $params[] = $weno_coverage; } - if (!empty($weno_state)) { - $sql .= " AND state = ?"; - $params[] = $weno_state; - } - if (!empty($weno_city)) { - $sql .= " AND city = ?"; - $params[] = $weno_city; + + // if a zip, search by it and forget city and state + if (empty($weno_zipcode)) { + if (!empty($weno_city)) { + $sql .= " AND city = ?"; + $params[] = $weno_city; + } + if (!empty($weno_state)) { + $sql .= " AND state = ?"; + $params[] = $weno_state; + } + } else { + $sql .= " AND ZipCode = ?"; + $params[] = $weno_zipcode; } if (!empty($weno_only)) { $sql .= " AND on_weno = ?"; @@ -81,10 +87,6 @@ $sql .= " AND 24HR = ?"; $params[] = $full_day; } - if (!empty($weno_zipcode)) { - $sql .= " AND ZipCode = ?"; - $params[] = $weno_zipcode; - } if (!empty($weno_test_pharmacies)) { $sql .= " AND test_pharmacy = ?"; $params[] = $weno_test_pharmacies; @@ -92,10 +94,11 @@ $sql .= " ORDER BY Business_Name ASC"; + $return_arr = []; $res = sqlStatement($sql, $params); while ($row = sqlFetchArray($res)) { $return_arr[] = array( - "name" => $row['Business_Name'] . "/ " . $row['address_line_1'] . " / " . $row['city'], + "name" => ucwords(strtolower($row['Business_Name'] . " " . $row['address_line_1'] . " " . $row['city'])), "ncpdp" => $row['ncpdp'] ); } @@ -103,32 +106,34 @@ } if (isset($_GET['searchFor']) && $_GET['searchFor'] == 'weno_drop') { - $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . - "FROM weno_pharmacy WHERE 1=1"; + $sql = "SELECT Business_Name, state, ncpdp, city, address_line_1 " . "FROM weno_pharmacy WHERE 1=1"; - $weno_coverage = $_GET['coverage'] ?: ''; - $weno_state = $_GET['weno_state'] ?: ''; - $weno_city = $_GET['weno_city'] ?: ''; - $full_day = $_GET['full_day'] ? 'Yes' : ''; - $weno_zipcode = $_GET['weno_zipcode'] ?: ''; + $weno_coverage = $_GET['coverage'] ?: ''; + $weno_state = $_GET['weno_state'] ?: ''; + $weno_city = $_GET['weno_city'] ?: ''; + $full_day = $_GET['full_day'] ? 'Yes' : ''; + $weno_zipcode = $_GET['weno_zipcode'] ?: ''; $weno_test_pharmacies = $_GET['test_pharmacy'] == 'true' ? 'True' : ''; - if (!empty($weno_state)) { - $sql .= " AND state = ?"; - $params[] = $weno_state; - } - if (!empty($weno_zipcode)) { + // if a zip, search by it and forget city and state + if (empty($weno_zipcode)) { + if (!empty($weno_city)) { + $sql .= " AND city = ?"; + $params[] = $weno_city; + } + if (!empty($weno_state)) { + $sql .= " AND state = ?"; + $params[] = $weno_state; + } + } else { $sql .= " AND ZipCode = ?"; $params[] = $weno_zipcode; } + if (!empty($weno_coverage)) { $sql .= " AND state_wide_mail_order = ?"; $params[] = $weno_coverage; } - if (!empty($weno_city)) { - $sql .= " AND city = ?"; - $params[] = $weno_city; - } if (!empty($full_day)) { $sql .= " AND 24HR = ?"; $params[] = $full_day; @@ -140,11 +145,11 @@ $sql .= " ORDER BY Business_Name ASC"; - $res = sqlStatement($sql, $params); $return_arr = []; + $res = sqlStatement($sql, $params); while ($row = sqlFetchArray($res)) { $return_arr[] = array( - "name" => $row['Business_Name'] . "/ " . $row['address_line_1'] . " / " . $row['city'], + "name" => ucwords(strtolower($row['Business_Name'] . " " . $row['address_line_1'] . " " . $row['city'])), "ncpdp" => $row['ncpdp'] ); } diff --git a/interface/modules/custom_modules/oe-module-weno/sql/table.sql b/interface/modules/custom_modules/oe-module-weno/sql/table.sql index 5e1bf0da3a2..0c9bdf59a8e 100644 --- a/interface/modules/custom_modules/oe-module-weno/sql/table.sql +++ b/interface/modules/custom_modules/oe-module-weno/sql/table.sql @@ -62,9 +62,9 @@ CREATE TABLE `weno_download_log` ( ) ENGINE=InnoDB; #EndIf --- For early adopters of weno, incase they need to upgrade to the next/latest release of openEMR +-- For early adopters of weno, in case they need to upgrade let's delete and add below. #IfRow background_services name WenoExchange -UPDATE `background_services` SET title="Weno Log Sync", `function`="downloadWenoPrescriptionLog", `require_once`="/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php" WHERE `name`="WenoExchange"; +DELETE FROM `background_services` WHERE `name` = 'WenoExchange'; #EndIf #IfNotRow background_services name WenoExchangePharmacies @@ -78,10 +78,10 @@ VALUES ('WenoExchange', 'Weno Log Sync', '0', '0', current_timestamp(), '30', 'd #EndIf #IfRow globals gl_name weno_provider_password -UPDATE `globals` SET gl_name="weno_admin_password" WHERE gl_name="weno_provider_password"; +UPDATE `globals` SET gl_name='weno_admin_password' WHERE gl_name='weno_provider_password'; #EndIf #IfRow globals gl_name weno_provider_username -UPDATE `globals` SET gl_name="weno_admin_username" WHERE gl_name="weno_provider_username"; +UPDATE `globals` SET gl_name='weno_admin_username' WHERE gl_name='weno_provider_username'; #EndIf diff --git a/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php b/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php index f02284bb5aa..86e31b9fefb 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php @@ -1,21 +1,32 @@ + * @author Jerry Padgett + * @copyright Copyright (c) 2023 Omega Systems Group + * @copyright Copyright (c) 2024 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + namespace OpenEMR\Modules\WenoModule; -use OpenEMR\Modules\WenoModule\WenoGlobalConfig; use OpenEMR\Common\Logging\SystemLogger; -use OpenEMR\Core\Kernel; use OpenEMR\Events\Globals\GlobalsInitializedEvent; +use OpenEMR\Events\Patient\PatientBeforeCreatedAuxEvent; +use OpenEMR\Events\Patient\PatientUpdatedEventAux; +use OpenEMR\Events\PatientDemographics\RenderEvent as pRenderEvent; +use OpenEMR\Events\PatientDemographics\RenderPharmacySectionEvent; +use OpenEMR\Menu\MenuEvent; +use OpenEMR\Modules\WenoModule\Services\ModuleService; +use OpenEMR\Modules\WenoModule\Services\SelectedPatientPharmacy; use OpenEMR\Services\Globals\GlobalSetting; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Twig\Environment; -use OpenEMR\Menu\MenuEvent; -use OpenEMR\Events\PatientDemographics\RenderEvent as pRenderEvent; -use OpenEMR\Events\PatientDemographics\RenderPharmacySectionEvent; -use OpenEMR\Events\Patient\PatientBeforeCreatedAuxEvent; -use OpenEMR\Events\Patient\PatientUpdatedEventAux; -use OpenEMR\Modules\WenoModule\Services\SelectedPatientPharmacy; class Bootstrap { @@ -33,6 +44,7 @@ class Bootstrap /** * The OpenEMR Twig Environment + * * @var Environment */ private $twig; @@ -47,18 +59,24 @@ class Bootstrap */ private $logger; - private $modulePath; + private string $modulePath; /** * @var SelectedPatientPharmacy */ - private $selectedPatientPharmacy; + private SelectedPatientPharmacy $selectedPatientPharmacy; /** * @return void */ - public function subscribeToEvents() + public function subscribeToEvents(): void { + $modService = new ModuleService(); + if (!$modService->isWenoConfigured()) { + // let Admin configure Weno if module is not configured. + $this->addGlobalSettings(); + return; + } $this->addGlobalSettings(); $this->registerMenuItems(); $this->registerDemographicsEvents(); @@ -66,16 +84,13 @@ public function subscribeToEvents() $this->demographicsDisplaySelectedEvents(); $this->patientSaveEvents(); $this->patientUpdateEvents(); + $modService::setModuleState('oe-module-weno', '1', '0'); } - public function __construct(EventDispatcher $dispatcher, ?Kernel $kernel = null) + public function __construct(EventDispatcher $dispatcher) { - if (empty($kernel)) { - $kernel = new Kernel(); - } $this->eventDispatcher = $dispatcher; - - $this->globalsConfig = new WenoGlobalConfig($GLOBALS); + $this->globalsConfig = new WenoGlobalConfig(); $this->moduleDirectoryName = basename(dirname(__DIR__)); $this->modulePath = dirname(__DIR__); $this->logger = new SystemLogger(); @@ -85,7 +100,7 @@ public function __construct(EventDispatcher $dispatcher, ?Kernel $kernel = null) /** * @return \Twig\Environment */ - public function getTwig() + public function getTwig(): Environment { return $this->twig; } @@ -94,7 +109,7 @@ public function getTwig() * @param GlobalsInitializedEvent $event * @return void */ - public function addGlobalWenoSettings(GlobalsInitializedEvent $event) + public function addGlobalWenoSettings(GlobalsInitializedEvent $event): void { $settings = $this->globalsConfig->getGlobalSettingSectionConfiguration(); @@ -139,7 +154,7 @@ public function addGlobalWenoSettings(GlobalsInitializedEvent $event) /** * @return void */ - public function registerDemographicsEvents() + public function registerDemographicsEvents(): void { $this->eventDispatcher->addListener(pRenderEvent::EVENT_SECTION_LIST_RENDER_BEFORE, [$this, 'renderWenoSection']); } @@ -148,49 +163,49 @@ public function registerDemographicsEvents() * @param pRenderEvent $event * @return void */ - public function renderWenoSection(pRenderEvent $event) + public function renderWenoSection(pRenderEvent $event): void { $path = __DIR__; $path = str_replace("src", "templates", $path); $pid = $event->getPid(); ?>
- - -
-
+ + +
+ eventDispatcher->addListener(GlobalsInitializedEvent::EVENT_HANDLE, [$this, 'addGlobalWenoSettings']); } @@ -198,7 +213,7 @@ public function addGlobalSettings() /** * @return void */ - public function registerMenuItems() + public function registerMenuItems(): void { $this->eventDispatcher->addListener(MenuEvent::MENU_UPDATE, [$this, 'addCustomMenuItem']); } @@ -207,7 +222,7 @@ public function registerMenuItems() * @param MenuEvent $event * @return MenuEvent */ - public function addCustomMenuItem(MenuEvent $event) + public function addCustomMenuItem(MenuEvent $event): MenuEvent { $menu = $event->getMenu(); //Prescription Log @@ -260,7 +275,7 @@ public function addCustomMenuItem(MenuEvent $event) /** * @return void */ - public function demographicsSelectorEvents() + public function demographicsSelectorEvents(): void { $this->eventDispatcher->addListener(RenderPharmacySectionEvent::RENDER_AFTER_PHARMACY_SECTION, [$this, 'renderWenoPharmacySelector']); } @@ -268,7 +283,7 @@ public function demographicsSelectorEvents() /** * @return void */ - public function renderWenoPharmacySelector() + public function renderWenoPharmacySelector(): void { include_once($this->modulePath) . "/templates/pharmacy_list_form.php"; } @@ -276,7 +291,7 @@ public function renderWenoPharmacySelector() /** * @return void */ - public function demographicsDisplaySelectedEvents() + public function demographicsDisplaySelectedEvents(): void { $this->eventDispatcher->addListener(RenderPharmacySectionEvent::RENDER_AFTER_SELECTED_PHARMACY_SECTION, [$this, 'renderSelectedWenoPharmacies']); } @@ -284,7 +299,7 @@ public function demographicsDisplaySelectedEvents() /** * @return void */ - public function renderSelectedWenoPharmacies() + public function renderSelectedWenoPharmacies(): void { echo "
"; include_once($this->modulePath) . "/templates/pharmacy_list_display.php"; @@ -293,7 +308,7 @@ public function renderSelectedWenoPharmacies() /** * @return void */ - public function patientSaveEvents() + public function patientSaveEvents(): void { $this->eventDispatcher->addListener(PatientBeforeCreatedAuxEvent::EVENT_HANDLE, [$this, 'persistPatientWenoPharmacies']); } @@ -302,7 +317,7 @@ public function patientSaveEvents() * @param PatientBeforeCreatedAuxEvent $event * @return void */ - public function persistPatientWenoPharmacies(PatientBeforeCreatedAuxEvent $event) + public function persistPatientWenoPharmacies(PatientBeforeCreatedAuxEvent $event): void { $patientData = $event->getPatientData(); $this->selectedPatientPharmacy->prepSelectedPharmacy($patientData); @@ -311,7 +326,7 @@ public function persistPatientWenoPharmacies(PatientBeforeCreatedAuxEvent $event /** * @return void */ - public function patientUpdateEvents() + public function patientUpdateEvents(): void { $this->eventDispatcher->addListener(PatientUpdatedEventAux::EVENT_HANDLE, [$this, 'updatePatientWenoPharmacies']); } @@ -320,7 +335,7 @@ public function patientUpdateEvents() * @param PatientUpdatedEventAux $event * @return void */ - public function updatePatientWenoPharmacies(PatientUpdatedEventAux $event) + public function updatePatientWenoPharmacies(PatientUpdatedEventAux $event): void { $updatedPatientData = $event->getUpdatedPatientData(); $this->selectedPatientPharmacy->prepForUpdatePharmacy($updatedPatientData); diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php b/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php deleted file mode 100644 index 1bca4abed7b..00000000000 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/Container.php +++ /dev/null @@ -1,61 +0,0 @@ - - * @copyright Copyright (c) 2021 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 - */ - -namespace OpenEMR\Modules\WenoModule\Services; - -/** - * Class Container - * @package OpenEMR\Rx\Weno - */ -class Container -{ - private $transmitproperties; - private $logproperties; - private $facilityproperties; - private $wenopharmacyimport; - - public function __construct() - { - //do epic stuff here ... - } - - /** - * @return TransmitProperties - */ - public function getTransmitproperties(): TransmitProperties - { - if ($this->transmitproperties === null) { - $this->transmitproperties = new TransmitProperties(); - } - return $this->transmitproperties; - } - - /** - * @return LogProperties - */ - public function getLogproperties(): LogProperties - { - if ($this->logproperties === null) { - $this->logproperties = new LogProperties(); - } - return $this->logproperties; - } - - /** - * @return FacilityProperties - */ - public function getFacilityproperties(): FacilityProperties - { - if ($this->facilityproperties === null) { - $this->facilityproperties = new FacilityProperties(); - } - return $this->facilityproperties; - } -} diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php index 553e50a3099..ba99ffdfd00 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/DownloadWenoPharmacies.php @@ -1,11 +1,13 @@ - * @copyright Copyright (c) 2023 Sherwin Gaddis - * + * @package OpenEMR + * @link http://www.open-emr.org + * @author Sherwin Gaddis + * @author Jerry Padgett + * @copyright Copyright (c) 2023 Sherwin Gaddis + * @copyright Copyright (c) 2024 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ namespace OpenEMR\Modules\WenoModule\Services; @@ -13,10 +15,11 @@ use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Modules\WenoModule\Services\WenoLogService; use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesImport; +use ZipArchive; class DownloadWenoPharmacies { - public function retrieveDataFile($url, $storelocation) + public function retrieveDataFile($url, $storelocation): ?string { $path_to_extract = $storelocation; $storelocation .= "weno_pharmacy.zip"; @@ -26,13 +29,11 @@ public function retrieveDataFile($url, $storelocation) $fp = fopen($storelocation, 'w+'); $ch = curl_init($url); - curl_setopt($ch, CURLOPT_FILE, $fp); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_TIMEOUT, 1000); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0'); curl_exec($ch); - curl_close($ch); fclose($fp); @@ -44,10 +45,10 @@ public function retrieveDataFile($url, $storelocation) } } - public function extractFile($path_to_extract, $storelocation) + public function extractFile($path_to_extract, $storelocation): ?string { - $zip = new \ZipArchive(); - $wenolog = new WenoLogService(); + $zip = new ZipArchive(); + $wenoLog = new WenoLogService(); $import = new WenoPharmaciesImport(); if ($zip->open($storelocation) === true) { @@ -59,13 +60,6 @@ public function extractFile($path_to_extract, $storelocation) $filename = basename($csvFile); $csvFilename = $filename; - EventAuditLogger::instance()->newEvent( - "prescriptions_log", - $_SESSION['authUser'], - $_SESSION['authProvider'], - 1, - "File extracted successfully." - ); echo 'File extracted successfully.'; echo 'CSV filename: ' . text($csvFilename); @@ -73,29 +67,36 @@ public function extractFile($path_to_extract, $storelocation) unlink($storelocation); $result = $import->importPharmacy($csvFile, $files); if ($result == "Imported") { - $wenolog->insertWenoLog("pharmacy", "Success"); - return $result; + $wenoLog->insertWenoLog("pharmacy", "Success"); } else { - return $result; + $wenoLog->insertWenoLog("pharmacy", "Failed"); } - - return "Imported"; + return $result; } else { EventAuditLogger::instance()->newEvent( - "prescriptions_log", + "pharmacy_log", $_SESSION['authUser'], $_SESSION['authProvider'], - 1, + 0, "No CSV file found in the zip archive." ); - $wenolog->insertWenoLog("pharmacy", "Failed"); + $wenoLog->insertWenoLog("pharmacy", "Failed"); return "Failed"; } } else { - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "Failed to extract the file."); - echo 'Failed to extract the file.'; - error_log("Failed to extract the file."); - $wenolog->insertWenoLog("pharmacy", "Failed"); + $scrape = file_get_contents($storelocation); + $wenolog = new WenoLogService(); + $isError = $wenolog->scrapeWenoErrorHtml($scrape); + if ($isError['is_error']) { + EventAuditLogger::instance()->newEvent("pharmacy_background", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "Pharmacy Failed download! Weno error: " . $isError['messageText']); + error_log('Pharmacy download failed: ' . $isError['messageText']); + $wenolog->insertWenoLog("pharmacy", "loginfail"); + } else { + EventAuditLogger::instance()->newEvent("pharmacy_background", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "Pharmacy Failed download! Weno error Other"); + error_log("Pharmacy Failed download! Weno error: Other"); + } + $wenoLog->insertWenoLog("pharmacy", "Failed"); + die; } } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php index 3b21c4ade65..cd3a226a98f 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogDataInsert.php @@ -27,7 +27,6 @@ public function insertPrescriptions($insertdata) $sql .= "patient_id = ?, "; $sql .= "provider_id = ?, "; $sql .= "drug = ?, "; - $sql .= "encounter = ?, "; $sql .= "quantity = ?, "; $sql .= "refills = ?, "; $sql .= "substitute = ?,"; @@ -42,7 +41,6 @@ public function insertPrescriptions($insertdata) $insertdata['patient_id'], $insertdata['user_id'], $insertdata['drug'], - $insertdata['encounter'], $insertdata['quantity'], $insertdata['refills'], $insertdata['substitute'], diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php index 20abc03f089..0339132d9e0 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogImportBuild.php @@ -13,6 +13,11 @@ class LogImportBuild { public $rxsynclog; + private $insertdata; + /** + * @var mixed|null + */ + private mixed $messageid; public function __construct() { @@ -28,7 +33,7 @@ public function getUserIdByWenoId($external_provider_id) return $provider['id']; } else { // logged in user is auth weno user so let's ensure a user is set. - return $_SESSION["authUserID"] ?? null; + return "REQED:{users}" . xlt("Weno Provider Id missing. Select Admin then Users and edit the user to add Weno Provider Id"); } } @@ -54,7 +59,7 @@ public function checkMessageId() return $entry['count']; } - public function buildInsertArray() + public function buildInsertArray(): bool|string { $l = 0; if (file_exists($this->rxsynclog)) { @@ -71,29 +76,29 @@ public function buildInsertArray() continue; } if (isset($line[4])) { - $this->messageid = $line[4] ?? null; + $this->messageid = $line[4] ?? ''; $is_saved = $this->checkMessageId(); if ($is_saved > 0) { continue; } } if (!empty($line)) { - $pr = $line[2] ?? null; + $pr = $line[2] ?? ''; $provider = explode(":", $pr); - $windate = $line[16] ?? null; + $windate = $line[16] ?? ''; $idate = substr(trim($windate), 0, -5); $idate = explode(" ", $idate); $idate = explode("/", $idate[0]); - $year = $idate[2] ?? null; - $month = $idate[0] ?? null; - $day = $idate[1] ?? null; + $year = $idate[2] ?? ''; + $month = $idate[0] ?? ''; + $day = $idate[1] ?? ''; $idate = $year . '-' . $month . '-' . $day; $ida = preg_replace('/T/', ' ', $line[0]); - $p = $line[1] ?? null; + $p = $line[1] ?? ''; $pid_and_encounter = explode(":", $p); $pid = intval($pid_and_encounter[0]); - $encounter = intval($pid_and_encounter[1]); - $r = $line[22] ?? null; + $uid = intval($pid_and_encounter[1]); + $r = $line[22] ?? ''; $refills = filter_var($r, FILTER_SANITIZE_NUMBER_INT); $insertdata = []; @@ -103,28 +108,28 @@ public function buildInsertArray() $insertdata['active'] = $active; $insertdata['date_added'] = $ida; $insertdata['patient_id'] = $pid; - $insertdata['encounter'] = $encounter; + $insertdata['attached_user_id'] = $uid; $drug = isset($line[11]) ? str_replace('"', '', $line[11]) : xlt("Incomplete"); $insertdata['drug'] = $drug; - $insertdata['quantity'] = $line[18] ?? null; + $insertdata['quantity'] = $line[18] ?? ''; $insertdata['refills'] = $refills; $sub = ($line[14] = 'Allowed' ? 1 : 0); - $insertdata['substitute'] = $sub ?? null; - $insertdata['note'] = $line[21] ?? null; - $insertdata['rxnorm_drugcode'] = $line[12] ?? null; + $insertdata['substitute'] = $sub ?? ''; + $insertdata['note'] = $line[21] ?? ''; + $insertdata['rxnorm_drugcode'] = $line[12] ?? ''; $insertdata['provider_id'] = $provider[0]; - $insertdata['user_id'] = $this->getUserIdByWenoId($provider[0]); - $insertdata['prescriptionguid'] = $line[4] ?? null; + $insertdata['user_id'] = ($uid > 0) ? $uid : $this->getUserIdByWenoId($provider[0]); + $insertdata['prescriptionguid'] = $line[4] ?? ''; $insertdata['txDate'] = $ida; $loginsert = new LogDataInsert(); $loginsert->insertPrescriptions($insertdata); - ++$l; } } fclose($records); } else { - echo "File is missing!"; + return xlt("File is missing!"); } + return true; } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php index 8fcd64de1e9..78efe828387 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/LogProperties.php @@ -1,11 +1,13 @@ - * @copyright Copyright (c) 2020 Sherwin Gaddis - * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + * @package OpenEMR + * @link http://www.open-emr.org + * @author Sherwin Gaddis + * @author Jerry Padgett + * @copyright Copyright (c) 2020 Sherwin Gaddis + * @copyright Copyright (c) 2024 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ namespace OpenEMR\Modules\WenoModule\Services; @@ -13,7 +15,6 @@ use Exception; use OpenEMR\Common\Crypto\CryptoGen; use OpenEMR\Common\Logging\EventAuditLogger; -use OpenEMR\Modules\WenoModule\Services\WenoLogService; class LogProperties { @@ -70,11 +71,11 @@ public function __construct() $this->cryptoGen = new CryptoGen(); $this->method = "aes-256-cbc"; $this->rxsynclog = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/logsync.csv"; - $this->enc_key = $this->cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); + $this->enc_key = $this->cryptoGen->decryptStandard($GLOBALS['weno_encryption_key'] ?? ''); $this->key = substr(hash('sha256', $this->enc_key, true), 0, 32); $this->iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0); - $this->weno_admin_email = $GLOBALS['weno_admin_username']; - $this->weno_admin_password = $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); + $this->weno_admin_email = $GLOBALS['weno_admin_username'] ?? ''; + $this->weno_admin_password = $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password'] ?? ''); } /** @@ -83,8 +84,8 @@ public function __construct() public function logEpcs() { $email['email'] = $this->weno_admin_email; - $prov_pass = $this->weno_admin_password; // gets the password stored for the - $md5 = md5($prov_pass); // hash the current password + $prov_pass = $this->weno_admin_password; // gets the password stored for the + $md5 = md5($prov_pass); // hash the current password $workday = date("l"); //Checking Saturday for any prescriptions that were written. if ($workday == 'Monday') { @@ -147,8 +148,7 @@ public function logSync() error_log("Cipher failure check encryption key", time()); exit; } - //**warning** do not add urlencode to $provider_info['email'] per Weno design - $urlOut = $syncLogs . $provider_info['email'] . "&data=" . urlencode($logurlparam); + $urlOut = $syncLogs . urlencode($provider_info['email']) . "&data=" . urlencode($logurlparam); $ch = curl_init($urlOut); curl_setopt($ch, CURLOPT_TIMEOUT, 200); @@ -161,37 +161,50 @@ public function logSync() curl_close($ch); if ($statusCode == 200) { file_put_contents($this->rxsynclog, $rpt); - $logstring = "prescription log import initiated successfully"; - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$logstring"); + $isError = $wenolog->scrapeWenoErrorHtml($rpt); + if ($isError['is_error']) { + $error = $isError['messageText']; + error_log('Prescription download failed: ' . $error); + $wenolog->insertWenoLog("prescription", "loginfail"); + $wenolog->insertWenoLog("prescription", "Failed"); + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, $error); + die(js_escape($error)); + } $wenolog->insertWenoLog("prescription", "Success"); } else { - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 1, "$statusCode"); + // yes record failures. + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "$statusCode"); $wenolog->insertWenoLog("prescription", "Failed"); return false; } if (file_exists($this->rxsynclog)) { $log = new LogImportBuild(); - $log->buildInsertArray(); - return true; + $rtn = $log->buildInsertArray(); + if (!$rtn) { + return false; + } + } else { + return false; } + return true; } /** * @return mixed */ - public function getProviderEmail() + public function getProviderEmail(): mixed { if ($_SESSION['authUser']) { $provider_info = ['email' => $GLOBALS['weno_provider_email']]; - if (!empty($provider_info)) { + if (!empty($provider_info['email'])) { return $provider_info; } else { - $error = xlt("Provider email address is missing. Go to [User settings > Email] to add provider's weno registered email address"); + $error = xlt("Provider email address is missing. Go to User settings Email to add provider's weno registered email address"); error_log($error); - TransmitProperties::errorWithDie($error); + TransmitProperties::echoError($error); } - } else if ($GLOBALS['weno_admin_username']) { + } elseif ($GLOBALS['weno_admin_username'] ?? false) { $provider_info["email"] = $GLOBALS['weno_admin_username']; return $provider_info; } else { @@ -205,7 +218,7 @@ public function getProviderEmail() /** * @return mixed */ - public function getProviderPassword() + public function getProviderPassword(): mixed { if ($_SESSION['authUser']) { if (!empty($GLOBALS['weno_admin_password'])) { @@ -214,7 +227,7 @@ public function getProviderPassword() echo xlt('Provider Password is missing'); die; } - } else if ($GLOBALS['weno_admin_password']) { + } elseif ($GLOBALS['weno_admin_password']) { return $this->cryptoGen->decryptStandard($GLOBALS['weno_admin_password']); } else { error_log("Admin password not set"); diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php new file mode 100644 index 00000000000..bc8281155e4 --- /dev/null +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php @@ -0,0 +1,179 @@ + + * @copyright Copyright (c) 2023-2024 Jerry Padgett + * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 + */ + +namespace OpenEMR\Modules\WenoModule\Services; + +use OpenEMR\Common\Crypto\CryptoGen; + +/** + * Companion to event bootstrapping + */ +class ModuleService +{ + public function __construct() + { + } + + /** + * @param $flag + * @param bool $reset + * @return array|bool|null + */ + public static function setTaskState($flag, bool $reset = false): array|bool|null + { + $sql_next = "UPDATE `background_services` SET `active` = ? WHERE `name` = ? OR `name` = ?"; + if ($reset) { + $sql_next = "UPDATE `background_services` SET `active` = ?, next_run = NOW() WHERE `name` = ? OR `name` = ?"; + } + return sqlQuery($sql_next, array($flag, 'WenoExchange', 'WenoExchangePharmacies')); + } + + /** + * @return array + */ + public function getVendorGlobals($decrypt = true): array + { + $vendors['weno_rx_enable'] = '0'; + $vendors['weno_rx_enable_test'] = '0'; + $vendors['weno_encryption_key'] = ''; + $vendors['weno_admin_username'] = ''; + $vendors['weno_admin_password'] = ''; + $vendors['weno_secondary_encryption_key'] = ''; + $vendors['weno_secondary_admin_username'] = ''; + $vendors['weno_secondary_admin_password'] = ''; + + $gl = sqlStatementNoLog( + "SELECT gl_name, gl_value FROM `globals` WHERE `gl_name` IN(?, ?, ?, ?, ?, ?, ?, ?)", + array("weno_rx_enable", "weno_rx_enable_test", "weno_encryption_key", "weno_admin_username", "weno_admin_password", "weno_secondary_encryption_key", "weno_secondary_admin_username", "weno_secondary_admin_password") + ); + if (empty($gl)) { + $this->saveVendorGlobals($vendors); + return $vendors; + } + while ($row = sqlFetchArray($gl)) { + $vendors[$row['gl_name']] = $row['gl_value']; + } + if ($decrypt) { + $crypt = new CryptoGen(); + $vendors['weno_encryption_key'] = $crypt->decryptStandard($vendors['weno_encryption_key']); + $vendors['weno_admin_password'] = $crypt->decryptStandard($vendors['weno_admin_password']); + $vendors['weno_secondary_encryption_key'] = $crypt->decryptStandard($vendors['weno_secondary_encryption_key']); + $vendors['weno_secondary_admin_password'] = $crypt->decryptStandard($vendors['weno_secondary_admin_password']); + } + + return $vendors; + } + + /** + * @param $vendors + * @return void + */ + public function saveVendorGlobals($items): void + { + $crypt = new CryptoGen(); + $items['weno_encryption_key'] = $crypt->encryptStandard($items['weno_encryption_key']); + $items['weno_admin_password'] = $crypt->encryptStandard($items['weno_admin_password']); + $items['weno_secondary_encryption_key'] = $crypt->encryptStandard($items['weno_secondary_encryption_key']); + $items['weno_secondary_admin_password'] = $crypt->encryptStandard($items['weno_secondary_admin_password']); + $vendors['weno_rx_enable'] = $items['weno_rx_enable'] ?? '0'; + $vendors['weno_rx_enable_test'] = $items['weno_rx_enable_test'] ?? '0'; + $vendors['weno_encryption_key'] = $items['weno_encryption_key']; + $vendors['weno_admin_username'] = $items['weno_admin_username']; + $vendors['weno_admin_password'] = $items['weno_admin_password']; + $vendors['weno_secondary_encryption_key'] = $items['weno_secondary_encryption_key']; + $vendors['weno_secondary_admin_username'] = $items['weno_secondary_admin_username']; + $vendors['weno_secondary_admin_password'] = $items['weno_secondary_admin_password']; + + foreach ($vendors as $key => $vendor) { + sqlQuery( + "INSERT INTO `globals` (`gl_name`,`gl_value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `gl_name` = ?, `gl_value` = ?", + array($key, $vendor, $key, $vendor) + ); + } + } + + /** + * Grab all Laminas Module setup or columns values. + * + * @param $modId + * @param string $col + * @return array + */ + function getModuleRegistry($modId, string $col = '*'): array + { + $registry = []; + $sql = "SELECT $col FROM modules WHERE mod_id = ? OR `mod_directory` = ?"; + $results = sqlQuery($sql, array($modId, $modId)); + foreach ($results as $k => $v) { + $registry[$k] = trim((preg_replace('/\R/', '', $v))); + } + + return $registry; + } + + /** + * @return bool true if all the Admin weno settings have been configured. Otherwise, false. + */ + public function isWenoConfigured(): bool + { + self::statusPharmacyDownloadReset(); // if last failed, reset to active + $config = $this->getVendorGlobals(); + $keys = array_keys($config); + foreach ($keys as $key) { + if ($key === 'weno_rx_enable_test') { + continue; + } + $value = $GLOBALS[$key] ?? null; + + if (empty($value)) { + self::setTaskState('0', false); + return false; + } + } + self::setTaskState('1', false); + return true; + } + + public static function statusPharmacyDownloadReset(): bool + { + $logService = new WenoLogService(); + $log = $logService->getLastPharmacyDownloadStatus(); + if ($log['status'] ?? '' != 'Success') { + if (($log['count'] ?? 0) > 0) { + return true; + } + $sql = "UPDATE `background_services` SET `next_run` = current_timestamp(), `active` = '1' WHERE `name` = ? && `next_run` > current_timestamp()"; + sqlQuery($sql, array('WenoExchangePharmacies')); + return true; + } + return false; + } + + /** + * @param $modId string|int module id or directory name + * @param $flag string|int 1 or 0 to activate or deactivate module. + * @param $flag_ui string|int custom module ui flag to activate or deactivate Manager UI states. + * @return array|bool|null + */ + public static function setModuleState($modId, $flag, $flag_ui): array|bool|null + { + if (($flag_ui == '1') || ($flag == '0')) { + self::setTaskState('0', false); + } else { + // set BG tasks to active if module is active. + self::setTaskState('1', false); + } + // set module state. + $sql = "UPDATE `modules` SET `mod_active` = ?, `mod_ui_active` = ? WHERE `mod_id` = ? OR `mod_directory` = ?"; + return sqlQuery($sql, array($flag, $flag_ui, $modId, $modId)); + } +} diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php index 320ba60befb..03f39a8b166 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/TransmitProperties.php @@ -7,18 +7,22 @@ * @link http://www.open-emr.org * @author Sherwin Gaddis * @author Kofi Appiah + * @author Jerry Padgett * @copyright Copyright (c) 2016-2017 Sherwin Gaddis * @copyright Copyright (c) 2023 omega systems group international + * @copyright Copyright (c) 2024 Jerry Padgett * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3 */ namespace OpenEMR\Modules\WenoModule\Services; use OpenEMR\Common\Crypto\CryptoGen; +use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Services\FacilityService; class TransmitProperties { + public $errors; private $payload; private $patient; private $provider_email; @@ -30,13 +34,19 @@ class TransmitProperties private $cryptoGen; private $pharmacy; private $encounter; + private mixed $wenoProviderID; + private string|false $csrf; + private mixed $responsibleParty; /** * AdminProperties constructor. */ - public function __construct() + public function __construct($returnFlag = false) { + $this->errors = ['errors' => '', 'warnings' => '', 'info' => '', 'string' => '']; + $this->csrf = js_escape(CsrfUtils::collectCsrfToken()); $this->cryptoGen = new CryptoGen(); + $this->wenoProviderID = $this->getWenoProviderID(); $this->ncpdp = $this->getPharmacy(); $this->vitals = $this->getVitals(); $this->patient = $this->getPatientInfo(); @@ -44,15 +54,115 @@ public function __construct() $this->provider_pass = $this->getProviderPassword(); $this->locid = $this->getFacilityInfo(); $this->pharmacy = $this->getPharmacy(); - $this->payload = $this->createJsonObject(); $this->subscriber = $this->getSubscriber(); + // check if patient is under 19 years old + $this->responsibleParty = ''; + if (self::getAge($this->patient['dob']) < 19) { + $this->responsibleParty = $this->getResponsibleParty(); + } $this->encounter = $this->getEncounter(); + // check for errors + $this->errors = $this->checkErrors($this); + if (!empty($this->errors['errors'])) { + // let's not create payload if there are errors. + // nip it here so to speak. + if ($returnFlag) { + return; + } + self::echoError($this->errors); + } elseif ($returnFlag) { + return; + } + // validated so create json object + $this->payload = $this->createJsonObject(); + } + + /** + * @param $value + * @return bool + */ + public function isJson($value): bool + { + return is_string($value) && json_decode($value) !== null && (json_last_error() == JSON_ERROR_NONE); } /** * @return false|string */ - public function createJsonObject() + public function getPayload(): false|string + { + return $this->payload; + } + + /** + * Generate a list of errors, warnings and info messages. + * All messages should be escaped and translated. + * + * @param $obj + * @return string[] + */ + public function checkErrors($obj): array + { + // Initialize the error array + $error = ['errors' => '', 'warnings' => '', 'info' => '', 'string' => '']; + // Check if the input is a valid object + if (!is_object($obj)) { + return $error; // Return empty error array if the input is not an object + } + // Iterate through the object properties + foreach ($obj as $property => $value) { + // Skip 'errors' property and empty values + if ($property === 'errors' || empty($value)) { + continue; + } + // Extract error type and value + $type = ''; + $v = ''; + if (is_string($value)) { + $values = [$value]; + } elseif ($this->isJson($value)) { + $values = json_decode($value, true); + } elseif (is_array($value)) { + $values = $value; + } else { + continue; // Skip non-array and non-string properties + } + // Iterate through the values + foreach ($values as $v) { + if (str_contains($v, "REQED")) { + $type = 'errors'; + } elseif (str_contains($v, "WARNS")) { + $type = 'warnings'; + } elseif (str_contains($v, "INFO")) { + $type = 'info'; + } else { + continue; // Skip if no error type detected + } + // Extract action from value + $action = ''; + if (preg_match('/{([^}]*)}/', $v, $matches)) { + $action = $matches[1]; + $v = str_replace('{' . $matches[1] . '}', '', $v); + } + // Add error to the respective error type if not already present + if (!str_contains($error[$type], $v)) { + // Append error with icon and onclick event + $uid = attr_js($_SESSION['authUserID'] ?? 0); + $action = attr_js($action); + $error[$type] .= "$v
"; + } + } + } + // Combine error messages into a single string + $error['string'] = $error['errors'] . $error['warnings'] . $error['info']; + + return $error; + } + + /** + * @return false|string + */ + public function createJsonObject(): false|string { //default is testing mode $testing = isset($GLOBALS['weno_rx_enable_test']); @@ -62,8 +172,9 @@ public function createJsonObject() $mode = 'N'; } $gender = $this->patient['sex']; - $heighDate = explode(" ", $this->vitals['date']); - $phoneprimary = preg_replace('/\D+/', '', $this->patient['phone_cell']); + $heightDate = explode(" ", $this->vitals['date'] ?? ''); + $phonePrimary = $this->formatPhoneNumber($this->patient['phone_cell']); + $age = self::getAge($this->patient['dob']); //create json array $wenObj = []; $wenObj['UserEmail'] = $this->provider_email['email']; @@ -71,7 +182,7 @@ public function createJsonObject() $wenObj['LocationID'] = $this->locid['weno_id']; $wenObj['TestPatient'] = $mode; $wenObj['PatientType'] = 'Human'; - $wenObj['OrgPatientID'] = $this->patient['pid'] . ":" . $this->getEncounter(); + $wenObj['OrgPatientID'] = $this->patient['pid'] . ":" . $_SESSION['authUserID'] ?? 0; $wenObj['LastName'] = $this->patient['lname']; $wenObj['FirstName'] = $this->patient['fname']; @@ -82,31 +193,102 @@ public function createJsonObject() $wenObj['State'] = $this->patient['state']; $wenObj['PostalCode'] = $this->patient['postal_code']; $wenObj['CountryCode'] = "US"; - $wenObj['PrimaryPhone'] = $phoneprimary; + $wenObj['PrimaryPhone'] = $phonePrimary; $wenObj['SupportsSMS'] = 'Y'; - $wenObj['PatientHeight'] = substr($this->vitals['height'], 0, -3); - $wenObj['PatientWeight'] = substr($this->vitals['weight'], 0, -3); - $wenObj['HeightWeightObservationDate'] = $heighDate[0]; - $wenObj["ResponsiblePartySameAsPatient"] = 'Y'; + $wenObj['PatientHeight'] = substr($this->vitals['height'] ?? '', 0, -3); + $wenObj['PatientWeight'] = substr($this->vitals['weight'] ?? '', 0, -3); + $wenObj['HeightWeightObservationDate'] = $heightDate[0]; + $wenObj["ResponsiblePartySameAsPatient"] = $age < 19 ? 'N' : 'Y'; + if ($age < 19 && !empty($this->responsibleParty)) { + $wenObj['ResponsiblePartyLastName'] = $this->responsibleParty['ResponsiblePartyLastName']; + $wenObj['ResponsiblePartyFirstName'] = $this->responsibleParty['ResponsiblePartyFirstName']; + $wenObj['ResponsiblePartyAddressLine1'] = $this->responsibleParty['ResponsiblePartyAddressLine1']; + if (!empty(($this->responsibleParty['ResponsiblePartyAddressLine2'] ?? ''))) { + $wenObj['ResponsiblePartyAddressLine2'] = $this->responsibleParty['ResponsiblePartyAddressLine2']; + } + $wenObj['ResponsiblePartyCity'] = $this->responsibleParty['ResponsiblePartyCity']; + $wenObj['ResponsiblePartyState'] = $this->responsibleParty['ResponsiblePartyState']; + $wenObj['ResponsiblePartyPostalCode'] = $this->responsibleParty['ResponsiblePartyPostalCode']; + $wenObj['ResponsiblePartyCountryCode'] = 'US'; + $wenObj['ResponsiblePartyPrimaryPhone'] = self::formatPhoneNumber($this->responsibleParty['ResponsiblePartyPrimaryPhone']); + } $wenObj['PatientLocation'] = "Home"; $wenObj['PrimaryPharmacyNCPCP'] = $this->pharmacy['primary']; - $wenObj['AlternativePharmacyNCPCP'] = $this->pharmacy['alternate']; + if (!empty($this->pharmacy['alternate'])) { + $wenObj['AlternativePharmacyNCPCP'] = $this->pharmacy['alternate']; + } - //add insurance return json_encode($wenObj); } /** - * @return array|void + * @return mixed + */ + private function getResponsibleParty(): mixed + { + $guardian = << '' and subscriber_relationship != 'self' and type = 'primary' +insurance; + + $relation = sqlQuery($guardian, [$_SESSION['pid']]); + // if no guardian then check for primary insurance subscriber + if (empty($relation['ResponsiblePartyLastName'])) { + $relation = sqlQuery($insurance, [$_SESSION['pid']]); + } + if (empty($relation)) { + return 'REQED:{demographics}' . xlt("Patient is under 19 years old. A Responsible Party is required. From the Patient Chart select Demographics Primary Insurance or Guardian to add a person."); + } + + return $relation; + } + + /** + * @param $dob + * @param $as_of + * @return string + */ + public static function getAge($dob, $as_of = ''): string + { + if (empty($as_of)) { + $as_of = date('Y-m-d'); + } + $a1 = explode('-', substr($dob, 0, 10)); + $a2 = explode('-', substr($as_of, 0, 10)); + $age = $a2[0] - $a1[0]; + if ($a2[1] < $a1[1] || ($a2[1] == $a1[1] && $a2[2] < $a1[2])) { + --$age; + } + + return (int)$age; + } + + /** + * @param $phone + * @return string + */ + public function formatPhoneNumber($phone): string + { + $phone = preg_replace('/\D+/', '', $phone); + if (strlen($phone) == 11) { + $phone = substr($phone, 1, 10); + } + return $phone; + } + + /** + * @return array|string */ - public function getProviderEmail() + public function getProviderEmail(): array|string { - $provider_info = ['email' => $GLOBALS['weno_provider_email']]; + $provider_info = ['email' => ($GLOBALS['weno_provider_email'] ?? '')]; if (empty($provider_info['email'])) { - echo self::styleErrors(xlt('Provider email address is missing and required. Go to User Settings select Weno Tab and enter your Weno Provider Password')); - exit; + return "REQED:{user_settings}" . (xlt('Provider Email is missing. Go to User Settings Weno Tab and enter your Weno Provider Email')); } else { return $provider_info; } @@ -131,11 +313,9 @@ public function getFacilityInfo(): array|null|false $default_facility = sqlQuery("SELECT name, street, city, state, postal_code, phone, fax, weno_id from facility order by id limit 1"); if (empty($default_facility['weno_id'])) { - echo self::styleErrors(xlt('Facility ID is missing. From Admin select Other then Weno Management. Enter the Weno ID of your facility')); - exit; - } else { - return $default_facility; + $default_facility['error'] = "REQED:{weno_manage}" . xlt('Facility ID is missing. From Admin select Other then Weno Management. Enter the Weno ID of your facility'); } + return $default_facility; } return $locId; } @@ -143,196 +323,208 @@ public function getFacilityInfo(): array|null|false /** * @return mixed */ - private function getPatientInfo() + private function getPatientInfo(): mixed { - //get patient data if in an encounter - //Since the transmitproperties is called in the logproperties - //need to check to see if in an encounter or not. Patient data is not required to view the Weno log - $log = ''; - $missing = 0; - if (empty($_SESSION['encounter'])) { - // removed requirement sjp - } - $patient = sqlQuery("select title, fname, lname, mname, street, state, city, email, phone_cell, postal_code, dob, sex, pid from patient_data where pid=?", [$_SESSION['pid']]); + // Get patient data if in an encounter + // Since the transmitProperties is called in the logproperties + // need to check to see if in an encounter or not. Patient data is not required to view the Weno log + + $patient = sqlQuery("select title, fname, lname, mname, street, state, city, email, phone_cell, phone_home, postal_code, dob, sex, pid from patient_data where pid=?", [$_SESSION['pid']]); if (empty($patient['fname'])) { - $log .= xlt("First Name Missing, From the Patient Chart select Demographics select Who. Save and retry") . ""; - ++$missing; + $patient['lname'] = "REQED:{demographics}" . xlt("Last Name Missing, From the Patient Chart select Demographics select Who."); } if (empty($patient['dob'])) { - $log .= xlt("Date of Birth Missing, From the Patient Chart select Demographics select Who. Save and retry") . "
"; - ++$missing; + $patient['dob'] = "REQED:{demographics}" . xlt("Date of Birth Missing, From the Patient Chart select Demographics select Who."); } if (empty($patient['sex'])) { - $log .= xlt("Gender Missing, From the Patient Chart select Demographics select Who. Save and retry") . "
"; - ++$missing; + $patient['sex'] = "REQED:{demographics}" . xlt("Gender Missing, From the Patient Chart select Demographics select Who."); } if (empty($patient['postal_code'])) { - $log .= xlt("Zip Code Missing, From the Patient Chart select Demographics select Contact select Postal Code. Save and retry") . "
"; - ++$missing; + $patient['postal_code'] = "REQED:{demographics}" . xlt("Zip Code Missing, From the Patient Chart select Demographics select Contact select Postal Code."); } if (empty($patient['street'])) { - $log .= xlt("Street Address incomplete Missing, From the Patient Chart select Demographics select Contact. Save and retry") . "
"; - ++$missing; + $patient['street'] = "REQED:{demographics}" . xlt("Street Address Missing, From the Patient Chart select Demographics select Contact."); + } + if (empty($patient['city'])) { + $patient['city'] = "REQED:{demographics}" . xlt("City Missing, From the Patient Chart select Demographics select Contact."); + } + if (empty($patient['state'])) { + $patient['state'] = "REQED:{demographics}" . xlt("State Missing, From the Patient Chart select Demographics select Contact."); } - if ($missing > 0) { - self::errorWithDie($log); + if (empty($patient['phone_cell'])) { + $patient['phone_cell'] = "REQED:{demographics}" . xlt("Cell or Home Phone Missing, From the Patient Chart select Demographics select Contact."); + if (!empty($patient['phone_home'])) { + $patient['phone_cell'] = $patient['phone_home']; + } } return $patient; } + /** + * @param $error + * @return string + */ public static function styleErrors($error): string { - $log = "

" . + $log = "

" . $error . "
" . xlt('Please address errors and try again!') . - "
" . xlt("Use browser Back button or Click Patient Name from top Patient bar.") . "

"; return $log; } - public static function errorWithDie($error): void + /** + * @param $errors + * @return void + */ + public static function echoError($errors): void { + if (is_array($errors)) { + $error = $errors['errors'] . $errors['warnings'] . $errors['info']; + } else { + $error = $errors; + } $log = self::styleErrors($error); - die($log); + echo($log); } /** * @return string * New Rx */ - public function cipherpayload() + public function cipherPayload(): string { $cipher = "aes-256-cbc"; // AES 256 CBC cipher $enc_key = $this->cryptoGen->decryptStandard($GLOBALS['weno_encryption_key']); - if ($enc_key) { - $key = substr(hash('sha256', $enc_key, true), 0, 32); - $iv = chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0) . chr(0x0); - $ciphertext = base64_encode(openssl_encrypt($this->payload, $cipher, $key, OPENSSL_RAW_DATA, $iv)); - return $ciphertext; - } else { + + if (!$enc_key) { return "error"; } + + $key = substr(hash('sha256', $enc_key, true), 0, 32); + $iv = str_repeat("\0", 16); // Generate an initialization vector + + return base64_encode(openssl_encrypt($this->payload, $cipher, $key, OPENSSL_RAW_DATA, $iv)); } + /** * @return mixed */ - public function getProviderPassword() + public function getProviderPassword(): mixed { if (!empty($GLOBALS['weno_provider_password'])) { return $this->cryptoGen->decryptStandard($GLOBALS['weno_provider_password']); } else { - echo xlt('Provider Password is missing'); - die; + return "REQED:{user_settings}" . xlt('Provider Password is missing. Go to User Settings Weno Tab and enter your Weno Provider Password'); } } /** - * @return mixed + * @return array|false|null */ - public function getVitals() + public function getVitals(): ?array { - $vitals = sqlQuery("select date, height, weight from form_vitals where pid = ? ORDER BY id DESC", [$_SESSION["pid"] ?? null]); + $vitals = sqlQuery("SELECT date, height, weight FROM form_vitals WHERE pid = ? ORDER BY id DESC", [$_SESSION["pid"] ?? null]); + // Check if vitals are empty or missing height and weight + if (empty($vitals) || ($vitals['height'] <= 0) || ($vitals['weight'] <= 0)) { + return [ + "REQED:{vitals}" . xlt("A Vitals Height and Weight are required to transmit a prescription. Create or add Vitals in an encounter.") + ]; + } return $vitals; } - private function getSubscriber() + /** + * @return mixed + */ + private function getSubscriber(): mixed { - $sql = sqlQuery("select subscriber_relationship from insurance_data where pid = ? and type = 'primary'", [$_SESSION['pid']]); - return $sql['subscriber_relationship']; + $relation = sqlQuery("select subscriber_relationship from insurance_data where pid = ? and type = 'primary'", [$_SESSION['pid']]); + $relation = $relation ?? ['subscriber_relationship' => '']; + + return $relation['subscriber_relationship']; } /** - * @return mixed + * @return string|array */ - public function getPharmacy() + public function getPharmacy(): string|array { $data = sqlQuery("SELECT * FROM `weno_assigned_pharmacy` WHERE `pid` = ? ", [$_SESSION["pid"]]); - if (empty($data)) { - $log = xlt("Weno Pharmacies not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Pharmacies"); - self::errorWithDie($log); - } $response = array( - "primary" => $data['primary_ncpdp'], - "alternate" => $data['alternate_ncpdp'] + "primary" => $data['primary_ncpdp'] ?? '', + "alternate" => $data['alternate_ncpdp'] ?? '' ); + if (empty($data)) { + $response['errors'] = true; + // both primary and alternate are empty + } if (empty($response['primary'])) { - $log = xlt("Weno Primary Pharmacy not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); - self::errorWithDie($log); + $response['errors'] = true; + $e = 'REQED:{demographics}' . xlt("Weno Primary Pharmacy not set. From Patient's Demographics Choices assign Primary Pharmacy"); + $response['primary'] = $e; } - if (empty($response['alternate'])) { - $log = xlt("Weno Alternate Pharmacy not set. From Patient's Demographics select Choices then select Weno Pharmacy Selector to Assign Primary Pharmacy"); - self::errorWithDie($log); - } return $response; } - public function wenoChr() - { - return - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0) . - chr(0x0); - } - - public function wenoMethod(): string - { - return "aes-256-cbc"; - } - /** * @return mixed */ - public function getProviderName() + public function getProviderName(): mixed { $provider_info = sqlQuery("select fname, mname, lname from users where username=? ", [$_SESSION["authUser"]]); - + $provider_info = $provider_info ?? ['fname' => '', 'mname' => '', 'lname' => '']; return $provider_info['fname'] . " " . $provider_info['mname'] . " " . $provider_info['lname']; } /** * @return mixed */ - public function getPatientName() + public function getPatientName(): mixed { $patient_info = sqlQuery("select fname, mname, lname from patient_data where pid=? ", [$_SESSION["pid"]]); - + $patient_info = $patient_info ?? ['fname' => '', 'mname' => '', 'lname' => '']; return $patient_info['fname'] . " " . $patient_info['mname'] . " " . $patient_info['lname']; } /** - * @return mixed + * @return int|mixed */ - public function getWenoAltPharmacies() + private function getEncounter(): mixed { - $data = sqlQuery("SELECT * FROM weno_assigned_pharmacy WHERE pid = ? ", [$_SESSION["pid"]]); - $response = array( - "primary" => $data['primary_ncpdp'], - "alternate" => $data['alternate_ncpdp'] - ); - return $response; + return $_SESSION['encounter'] ?? 0; } - private function getEncounter() + /** + * @param $id + * @return mixed|string + */ + public function getWenoProviderId($id = null): mixed { - return $_SESSION['encounter'] ?? 0; + if (empty($id)) { + $id = $_SESSION['authUserID'] ?? ''; + } + // get the weno provider id from the user table (weno_prov_id + $provider = sqlQuery("SELECT weno_prov_id FROM users WHERE id = ?", [$id]); + if (!empty(trim($provider['weno_prov_id'] ?? ''))) { + $doIt = $GLOBALS['weno_provider_uid'] != trim($provider['weno_prov_id']); + if ($doIt) { + $GLOBALS['weno_provider_uid'] = trim($provider['weno_prov_id']); + $sql = "UPDATE `user_settings` SET `setting_value` = ? WHERE `setting_user` = ? AND `setting_label` = 'global:weno_provider_uid'"; + //sqlQuery($sql, [$GLOBALS['weno_provider_uid'], $_SESSION['authUserID']]); + } + return $provider['weno_prov_id']; + } elseif (!empty($GLOBALS['weno_provider_uid'])) { // if not in user table then check globals + // update user table with weno provider id + //sqlQuery("UPDATE `users` SET `weno_prov_id` = ? WHERE `id` = ? OR `weno_prov_id` = ?", [$GLOBALS['weno_provider_uid'], $id, $id]); + return $GLOBALS['weno_provider_uid']; + } else { + return "REQED:{users}" . xlt("Weno Provider Id missing. Select Admin then Users and edit the user to add Weno Provider Id"); + } } } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php index 25a557b72ac..7219807c041 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoLogService.php @@ -20,38 +20,70 @@ public function __construct() { } - public function getLastPrescriptionLogStatus() + public function getLastPrescriptionLogStatus(): bool|array|null { $params = "prescription"; $sql = "SELECT * FROM weno_download_log WHERE "; $sql .= "VALUE = ? ORDER BY created_at DESC LIMIT 1"; - $result = sqlQuery($sql, [$params]); - - return $result; + return sqlQuery($sql, [$params]); } - public function getLastPharmacyDownloadStatus() + public function getLastPharmacyDownloadStatus(): bool|array|null { $params = "pharmacy"; - $sql = "SELECT * FROM weno_download_log WHERE "; - $sql .= "VALUE = ? ORDER BY created_at DESC LIMIT 1"; - - $result = sqlQuery($sql, [$params]); + $v = ['count' => 0, 'created_at' => '', 'status' => '']; + $vsql = sqlQuery("SELECT * FROM `weno_download_log` WHERE `value` = ? ORDER BY `created_at` DESC LIMIT 1", [$params]); + if (!$vsql) { + return $v; + } + $v = $vsql; + $count = sqlQuery("SELECT COUNT(`id`) as count FROM `weno_pharmacy`"); + $v['count'] = $count['count'] ?? 0; - return $result; + return $v; } - public function insertWenoLog($value, $status) + public function insertWenoLog($value, $status): bool|string { - $sql = "INSERT INTO weno_download_log SET "; - $sql .= "value = ?, "; - $sql .= "status = ? "; - + $sql = "INSERT INTO weno_download_log SET value = ?, status = ?"; try { sqlInsert($sql, [$value, $status]); } catch (Exception $e) { return $e->getMessage(); } + return true; + } + + public function scrapeWenoErrorHtml($content) + { + $error = ['is_error' => false, 'type' => 'other', 'messageText' => '', 'messageHtml' => '']; + if (empty($content)) { + return $error; + } + $content = trim(preg_replace("/\r?\n|\r/", '

', $content)); + $content_html = strip_tags($content, '