From 5c5001f8f7fba8e883edc70617acaab85f016ef4 Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Tue, 16 Apr 2024 11:25:32 -0400 Subject: [PATCH] Some finishing touches (#7306) * Weno fixup and credential API - change fa font size - prevent old styles loading * - add acl to setup - validate vitals for under age - fix popup error for invalid action - add validation and default to change events - better validate setting requirements * - New WenoValidate class to verift keys and user credentials - verify and reset encryption key if needed for phamacy downloads. - temporally chang testing URL to weno dev server until new api goes online. - setup weno module for using upgrade in pre for auto upgrade feature. * - update code stamdards and do a little cleanup of our utility.js - numerous validation additions. - add all weno required settings (weno user id, facility location id and admin credentials validation) to module setup page. * - moved the custom modules to top of managers list. appears I have a bias! - add a simple but useful help panel to top of list table. - color coded module name for clarity if laminas or custom. * - had to create a separate setup_facilities script for setup so can use when module isn't enabled. - add a help button to MM and help_requested event listener - refactor controller for readability - add some security * - fix pathing problems - refactor reloads to replace page with new version * - too full of myself. utility Cleanup failed. - add new dowdlog log viewer - fix download create directory * - fix download won't break on duplicate key - auto save weno id in facilities section. - some setup refactor * - prevent resave of demographics on dialog close * - prevent demos from throwing warning in upgrade for old weno table population. v5.0.1 I believe. - files clean out - remove a chance for a race condition in background tasks * - change and move help - refactor to use the online api from dev api * - refactor and consoladate weno menu from Other to Weno eRx Tools - add Module setup and new Dowmload log viewer for admin to manage - add traps for internet off line. - remove unused class methods and cleanup WenoValidate class for readability. * - combine the download facility download viewer page * Some finishing touches - don't expose sensitive data - change datepicker option. though it would work in US not so muct Europe's day/m/Y * - refactor weno_log_sync for better readability and separation of concerns. This script was driving me crazy! - reformat various errors - ensure we have valid credentials and encryp key for downloads. If not reset so we can complete the important initial downloads at least. - added new info to download manager - I don't know take a look... * Remove unused code Add link to modules wiki * a couple log errors * review * module manager help method * Fix log escaping * Add exception to decryptStandard so we can tell where the heck error occurs * no message * Resubmit for missing yag that is not missing! * missing return in format function. Things are disappearing in my local! * add test pharmacies finish coredecrypt exceptions error messages refactors * Main fix here is adding logic for weno test pahramcies refactors of phamacy search and bud fix add logic to keep weno provider ids upto date and validated. escaping and xlating some js * Trying out updated linting - more global management for the module - escaping - pharmacy search alerts - add additional ease of setup options to setup. User Setting for logged in admin - had to refactor provider username to provider_email for weno legacy - add Brady's fix in core encryption service for dynamic properties. One less thing to worry about!. clean up comments * - more clean up. This is a very nice class. * - move validate actions up in form. - more fiddling around. * - add new action for listener reset_module active when the register icon is clicked. I used to remove all DB. - contiueing project messages and search fine tuning. - crypto updates * - fix edit_globals magins and padding - more runtime safety - review note * Update ModuleService.php * - reset back to dev server for testing - format messages * - refactor to online production API domain. - Add new items for setup and a complete module reset - refactore MM to separate cust and laminas section lists. --- .../oe-module-weno/ModuleManagerListener.php | 49 ++++- .../oe-module-weno/openemr.bootstrap.php | 6 +- .../oe-module-weno/public/assets/js/synch.js | 9 +- .../oe-module-weno/scripts/file_download.php | 25 ++- .../oe-module-weno/scripts/weno_log_sync.php | 111 +++++++--- .../scripts/weno_pharmacy_search.php | 9 +- .../oe-module-weno/src/Bootstrap.php | 11 + .../src/Services/DownloadWenoPharmacies.php | 24 ++- .../src/Services/LogProperties.php | 28 ++- .../src/Services/ModuleService.php | 109 +++++++--- .../src/Services/PharmacyService.php | 2 +- .../src/Services/TransmitProperties.php | 69 ++++--- .../src/Services/WenoLogService.php | 16 +- .../src/Services/WenoValidate.php | 19 +- .../oe-module-weno/src/WenoGlobalConfig.php | 14 +- .../custom_modules/oe-module-weno/table.sql | 112 +++++----- .../templates/download_log_viewer.php | 30 ++- .../oe-module-weno/templates/indexrx.php | 6 +- .../templates/pharmacy_list_form.php | 192 +++++++++-------- .../templates/setup_facilities.php | 14 +- .../oe-module-weno/templates/synch.php | 9 +- .../templates/weno_fragment.php | 14 +- .../oe-module-weno/templates/weno_setup.php | 194 +++++++++++------- .../oe-module-weno/templates/weno_users.php | 23 ++- .../Controller/InstallerController.php | 5 +- .../view/installer/installer/index.phtml | 97 ++++----- .../public/js/installer/action.js | 10 +- interface/super/edit_globals.php | 11 +- src/Common/Crypto/CryptoGen.php | 133 ++++++++---- 29 files changed, 847 insertions(+), 504 deletions(-) diff --git a/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php b/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php index 707a342f5b6..eba6dfedbcf 100644 --- a/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php +++ b/interface/modules/custom_modules/oe-module-weno/ModuleManagerListener.php @@ -60,7 +60,7 @@ public function moduleManagerAction($methodName, $modId, string $currentActionSt /** * Required method to return namespace - * If namespace isn't provided return empty + * If namespace isn't provided return empty string * and register namespace at top of this script.. * * @return string @@ -107,11 +107,9 @@ private function install($modId, $currentActionStatus): mixed private function help_requested($modId, $currentActionStatus): mixed { // must call a script that implements a dialog to show help. - // I can't find a way to override the Laminas UI except using a dialog. - try { - include 'show_help.php'; - } catch (Exception $e) { - return $e->getMessage(); + // I can't find a way to override the Lamina's UI except using a dialog. + if (file_exists(__DIR__ . '/show_help.php')) { + include __DIR__ . '/show_help.php'; } return $currentActionStatus; } @@ -166,6 +164,45 @@ private function unregister($modId, $currentActionStatus): mixed return $currentActionStatus; } + /** + * @param $modId + * @param $currentActionStatus + * @return mixed + */ + private function reset_module($modId, $currentActionStatus): mixed + { + $rtn = true; + $modService = new ModuleService(); + $logMessage = ''; // Initialize an empty string to store log messages + + if (!$modService::getModuleState($modId)) { + $sql = "DELETE FROM `user_settings` WHERE `setting_label` LIKE 'global:weno%'"; + $rtn = sqlQuery($sql); + $logMessage .= "DELETE FROM `user_settings`: " . (empty($rtn) ? "Success" : "Failed") . "\n"; + + $sql = "DELETE FROM `globals` WHERE `gl_name` LIKE 'weno%'"; + $rtn = sqlQuery($sql); + $logMessage .= "DELETE FROM `globals`: " . (empty($rtn) ? "Success" : "Failed") . "\n"; + + $sql = "DROP TABLE IF EXISTS `weno_pharmacy`"; + $rtn = sqlQuery($sql); + $logMessage .= "DROP TABLE `weno_pharmacy`: " . (empty($rtn) ? "Success" : "Failed") . "\n"; + + $sql = "DROP TABLE IF EXISTS `weno_assigned_pharmacy`"; + $rtn = sqlQuery($sql); + $logMessage .= "DROP TABLE `weno_assigned_pharmacy`: " . (empty($rtn) ? "Success" : "Failed") . "\n"; + + $sql = "DROP TABLE IF EXISTS `weno_download_log`"; + $rtn = sqlQuery($sql); + $logMessage .= "DROP TABLE `weno_download_log`: " . (empty($rtn) ? "Success" : "Failed") . "\n"; + + error_log(text($logMessage)); + } + + // return log messages to the MM to show user. + return text($logMessage); + } + /** * @param $modId * @param $currentActionStatus 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 96ce417af98..b076ebf86dd 100644 --- a/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php +++ b/interface/modules/custom_modules/oe-module-weno/openemr.bootstrap.php @@ -3,18 +3,16 @@ /** * * @package OpenEMR Weno Module - * @link https://online.wenoexchange.com * + * @author Jerry Padgett * @author Kofi Appiah - * Copyright (c) 2023 Omega Systems Group Corp + * Copyright (c) 2023 Omega Systems Group Corp * @license GNU General Public License 3 * */ namespace OpenEMR\Modules\WenoModule; -use OpenEMR\Core\ModulesClassLoader; - /** * @global OpenEMR\Core\ModulesClassLoader $classLoader */ 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 fa78f25eacf..b23af6548d3 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 @@ -77,12 +77,12 @@ function renderDialog(action, uid, event) { const actionUrl = `${urls[action]}${urlPart}id=${encodeURIComponent(uid)}&csrf_token_form=${encodeURIComponent(csrf)}`; // Open modal dialog - dlgopen('', 'dialog-mod', '900', 'full', '', '', { + dlgopen('', 'dialog-mod', 'modal-lg', 'full', '', '', { buttons: [ { - text: jsText('Return to eRx Widget'), - close: true, - style: 'primary' + text: jsText('Return to eRx Widget'), + close: true, + style: 'primary' } ], allowResize: true, @@ -91,6 +91,7 @@ function renderDialog(action, uid, event) { dialogId: 'error-dialog', type: 'iframe', resolvePromiseOn: 'close', + sizeHeight: 'full', url: top.webroot_url + actionUrl }).then(function (dialog) { top.restoreSession(); 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 70c16c95501..60208a183d1 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 @@ -8,7 +8,6 @@ use OpenEMR\Common\Crypto\CryptoGen; 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(); @@ -44,7 +43,7 @@ $path_to_extract = $GLOBALS['OE_SITE_DIR'] . "/documents/logs_and_misc/weno/"; // takes URL of image and Path for the image as parameter -function download_zipfile($fileUrl, $zipped_file) +function download_zipfile($fileUrl, $zipped_file): void { $fp = fopen($zipped_file, 'w+'); @@ -74,8 +73,8 @@ function download_zipfile($fileUrl, $zipped_file) download_zipfile($fileUrl, $storelocation); $zip = new ZipArchive(); -$wenolog = new WenoLogService(); - +$wenoLog = new WenoLogService(); +$csvFile = ''; if ($zip->open($storelocation) === true) { $zip->extractTo($path_to_extract); @@ -95,13 +94,13 @@ function download_zipfile($fileUrl, $zipped_file) } } else { $rpt = file_get_contents($storelocation); - $isError = $wenolog->scrapeWenoErrorHtml($rpt); + $isError = $wenoLog->scrapeWenoErrorHtml($rpt); if ($isError['is_error']) { - error_log('Pharmacy download failed: ' . $isError['messageText']); - $wenolog->insertWenoLog("pharmacy", "Exceeded_download_limits"); + error_log('Pharmacy download failed: ' . errorLogEscape($isError['messageText'])); + $wenoLog->insertWenoLog("pharmacy", "Exceeded download limits"); } - EventAuditLogger::instance()->newEvent("pharmacy_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, $isError['messageText']); - $wenolog->insertWenoLog("pharmacy", "Failed"); + 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'])); @@ -221,7 +220,7 @@ function download_zipfile($fileUrl, $zipped_file) 0, "Pharmacy Import download failed SQL Insert error." ); - $wenolog->insertWenoLog("pharmacy", "Failed"); + $wenoLog->insertWenoLog("pharmacy", "Failed"); error_log("User Initialed Pharmacy Import Failed Insert error"); } // let's brag about it. @@ -232,8 +231,8 @@ function download_zipfile($fileUrl, $zipped_file) 1, "User Initiated Pharmacy Download was Imported Successfully." ); - $wenolog->insertWenoLog("pharmacy", "Success"); - error_log("User Initialed Pharmacy Imported"); + $wenoLog->insertWenoLog("pharmacy", "Success"); + error_log("User Initiated Pharmacy Imported"); } else { EventAuditLogger::instance()->newEvent( "pharmacy_log", @@ -242,6 +241,6 @@ function download_zipfile($fileUrl, $zipped_file) 0, "Pharmacy Import download failed." ); - $wenolog->insertWenoLog("pharmacy", "Failed"); + $wenoLog->insertWenoLog("pharmacy", "Failed"); 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 ee238b7d81f..11523089816 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 @@ -13,55 +13,110 @@ use OpenEMR\Common\Crypto\CryptoGen; use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Modules\WenoModule\Services\LogProperties; +use OpenEMR\Modules\WenoModule\Services\WenoLogService; use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesJson; use OpenEMR\Modules\WenoModule\Services\WenoValidate; +/** + * Download Weno Pharmacy data. + */ function downloadWenoPharmacy() { - // Check if the encryption key is valid. If not, request a new key and then set it. $wenoValidate = new WenoValidate(); - $isKey = $wenoValidate->validateAdminCredentials(true); // auto reset on invalid. + $isKey = $wenoValidate->validateAdminCredentials(true, "pharmacy"); + if ((int)$isKey >= 998) { - EventAuditLogger::instance()->newEvent( - "pharmacy_background", - $_SESSION['authUser'], - $_SESSION['authProvider'], - 1, - text("Background Initiated Pharmacy download attempt failed. Internet problem!") - ); - error_log('Background Initiated Pharmacy Download not ran. Internet problem: ' . text($isKey)); - die; + handleDownloadError("Background Initiated Pharmacy download attempt failed. Internet problem!"); + } + + if ($isKey === false) { + requireGlobals(); } - error_log('Background Initiated Encryption Verify returned: ' . text($isKey == '1' ? 'Verified key is valid.' : 'Invalid Key')); - $cryptoGen = new CryptoGen(); - $localPharmacyJson = new WenoPharmaciesJson($cryptoGen); - // Check if the background service is active. Intervals are set to once a day + $localPharmacyJson = new WenoPharmaciesJson(new CryptoGen()); $value = $localPharmacyJson->checkBackgroundService(); + if ($value == 'active' || $value == 'live') { - error_log('Background Initiated Pharmacy Download Started.'); - - $status = $localPharmacyJson->storePharmacyDataJson(); - - 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; + $wenoLog = new WenoLogService(); + $wenoLog->insertWenoLog("pharmacy", "Download started"); + + performPharmacyDownload($localPharmacyJson); } } /** + * Perform the pharmacy data download. + * + * @param WenoPharmaciesJson $localPharmacyJson + */ +function performPharmacyDownload(WenoPharmaciesJson $localPharmacyJson) +{ + error_log('Background Initiated Pharmacy Download Started.'); + + $status = $localPharmacyJson->storePharmacyDataJson(); + + EventAuditLogger::instance()->newEvent( + "pharmacy_background", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + "Background Initiated Pharmacy Download Completed with Status:" . ($status) + ); + + error_log('Background Initiated Weno Pharmacies download completed with status:' . text($status)); +} + +/** + * Download Weno Prescription log. + * * @throws Exception */ function downloadWenoPrescriptionLog(): void { + $wenoValidate = new WenoValidate(); + $isKey = $wenoValidate->validateAdminCredentials(true); + + if ((int)$isKey >= 998) { + handleDownloadError("Prescription download attempt failed. Internet problem!"); + } + + if ($isKey === false) { + requireGlobals(); + } + $logSync = new LogProperties(); if (!$logSync->logSync()) { error_log("Background services failed for prescription log."); } } + +/** + * Handle download errors. + * + * @param string $errorMessage + */ +function handleDownloadError(string $errorMessage) +{ + EventAuditLogger::instance()->newEvent( + "pharmacy_background", + $_SESSION['authUser'], + $_SESSION['authProvider'], + 1, + ($errorMessage) + ); + + error_log(errorLogEscape($errorMessage)); + die; +} + +/** + * Require global variables. + */ +function requireGlobals(): void +{ + // Key has been reset, reload globals + // This is the problem when using globals for anything in a function. + // They need to be reloaded when dynamically changed or JIT global values. + // TODO: We need to address this in the future. + require_once dirname(__DIR__, 4) . "/globals.php"; +} 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 a5641a68eae..bcd593709ac 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 @@ -55,10 +55,10 @@ $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' : ''; + $weno_only = $_GET['weno_only'] == 'true' ? 'True' : ''; + $full_day = $_GET['full_day'] == 'true' ? 'Yes' : ''; + $weno_test_pharmacies = $_GET['test_pharmacy'] == 'true' ? 'True' : ''; if (!empty($weno_coverage)) { $sql .= " AND state_wide_mail_order = ?"; @@ -111,8 +111,9 @@ $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_only = $_GET['weno_only'] == 'true' ? 'True' : ''; + $full_day = $_GET['full_day'] == 'true' ? 'Yes' : ''; $weno_test_pharmacies = $_GET['test_pharmacy'] == 'true' ? 'True' : ''; // if a zip, search by it and forget city and state 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 1fb811bf2f8..bff303fa63c 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Bootstrap.php @@ -263,6 +263,16 @@ public function addCustomMenuItem(MenuEvent $event): MenuEvent $setupMenu->children = []; $setupMenu->acl_req = ["admin", "super"]; $setupMenu->global_req = ["weno_rx_enable"]; + // Background Services + $serviceMenu = new \stdClass(); + $serviceMenu->requirement = 0; + $serviceMenu->target = 'rpt0'; + $serviceMenu->menu_id = 'rep'; + $serviceMenu->label = xlt("Background Services (Convenience)"); + $serviceMenu->url = "/interface/reports/background_services.php"; + $serviceMenu->children = []; + $serviceMenu->acl_req = ["admin", "super"]; + $serviceMenu->global_req = ["weno_rx_enable"]; // Write the menu items to the menu foreach ($menu as $item) { if ($item->menu_id == 'admimg') { @@ -271,6 +281,7 @@ public function addCustomMenuItem(MenuEvent $event): MenuEvent if ($other->label == 'Weno eRx Tools') { $other->children[] = $dlMenu; $other->children[] = $setupMenu; + $other->children[] = $serviceMenu; break; } } 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 2681657eeb0..eae39b6fdfd 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,10 +1,10 @@ - * @author Jerry Padgett + * @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 @@ -13,8 +13,6 @@ namespace OpenEMR\Modules\WenoModule\Services; use OpenEMR\Common\Logging\EventAuditLogger; -use OpenEMR\Modules\WenoModule\Services\WenoLogService; -use OpenEMR\Modules\WenoModule\Services\WenoPharmaciesImport; use ZipArchive; class DownloadWenoPharmacies @@ -47,10 +45,14 @@ public function retrieveDataFile($url, $storelocation): ?string public function extractFile($path_to_extract, $storelocation): ?string { - $zip = new ZipArchive(); + try { + $zip = new ZipArchive(); + } catch (\Exception $e) { + error_log('Error extracting zip file: ' . errorLogEscape($e->getMessage())); + return "PHPError_install_zip_archive"; + } $wenoLog = new WenoLogService(); $import = new WenoPharmaciesImport(); - if ($zip->open($storelocation) === true) { $zip->extractTo($path_to_extract); @@ -89,13 +91,13 @@ public function extractFile($path_to_extract, $storelocation): ?string $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", "Exceeded_download_limits"); + error_log('Pharmacy download failed: ' . errorLogEscape($isError['messageText'])); + $wenolog->insertWenoLog("pharmacy", "Exceeded download limits"); } 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"); } - $wenoLog->insertWenoLog("pharmacy", "Failed"); die; } } 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 e27cfe27b96..755937823e2 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 @@ -107,7 +107,7 @@ public function logEpcs() "ToDate" => $today, "ResponseFormat" => "CSV" ]; - $plaintext = json_encode($p); //json encode email and password + $plaintext = json_encode($p); //json encode email and password if ($this->enc_key && $md5) { return base64_encode(openssl_encrypt($plaintext, $this->method, $this->key, OPENSSL_RAW_DATA, $this->iv)); } else { @@ -141,10 +141,8 @@ public function logReview() */ public function logSync() { + $wenoLog = new WenoLogService(); $provider_info['email'] = $this->weno_admin_email; - - $wenolog = new WenoLogService(); - $logurlparam = $this->logEpcs(); $syncLogs = "https://online.wenoexchange.com/en/EPCS/DownloadNewRxSyncDataVal?useremail="; if ($logurlparam == 'error') { @@ -152,8 +150,8 @@ public function logSync() error_log("Cipher failure check encryption key", time()); exit; } - $urlOut = $syncLogs . urlencode($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); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @@ -165,22 +163,20 @@ public function logSync() curl_close($ch); if ($statusCode == 200) { file_put_contents($this->rxsynclog, $rpt); - $isError = $wenolog->scrapeWenoErrorHtml($rpt); + $isError = $wenoLog->scrapeWenoErrorHtml($rpt); if ($isError['is_error']) { $error = $isError['messageText']; - error_log('Prescription download failed: ' . $error); - $wenolog->insertWenoLog("prescription", "possible_invalid_credentials"); - $wenolog->insertWenoLog("prescription", "Failed"); - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, $error); + error_log('Prescription download failed: ' . errorLogEscape($error)); + $wenoLog->insertWenoLog("prescription", "Invalid Prescriber Credentials Hint:see previous errors."); + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, ($error)); die(js_escape($error)); } - $wenolog->insertWenoLog("prescription", "Success"); + $wenoLog->insertWenoLog("prescription", "Success"); } else { // yes record failures. - EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, "$statusCode"); - error_log("Prescription download failed: $statusCode"); - $wenolog->insertWenoLog("prescription", "http_error_$statusCode"); - $wenolog->insertWenoLog("prescription", "Failed"); + EventAuditLogger::instance()->newEvent("prescriptions_log", $_SESSION['authUser'], $_SESSION['authProvider'], 0, ("$statusCode")); + error_log("Prescription download failed: errorLogEscape($statusCode)"); + $wenoLog->insertWenoLog("prescription", "http_error_$statusCode"); return false; } @@ -207,7 +203,7 @@ public function getProviderEmail(): string|array 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_log($error); + error_log(errorLogEscape($error)); TransmitProperties::echoError($error); } } elseif ($GLOBALS['weno_admin_username'] ?? false) { 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 index 3fea679b6c5..7575ecadbea 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/ModuleService.php @@ -24,7 +24,7 @@ public function __construct() } /** - * @param $flag + * @param $flag * @param bool $reset * @return array|bool|null */ @@ -47,58 +47,93 @@ public function getVendorGlobals($decrypt = true): array $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'] = ''; + $vendors['weno_provider_email'] = ''; + $vendors['weno_provider_password'] = ''; + + $us = $gl = []; $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") + "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") ); - if (empty($gl)) { - $this->saveVendorGlobals($vendors); - return $vendors; + if (!empty($_SESSION['authUserID'] ?? '')) { + $us = sqlStatementNoLog( + "SELECT `setting_label`, `setting_value`, `setting_user` FROM `user_settings` WHERE `setting_label` IN(?, ?) AND `setting_user` = ?", + array("global:weno_provider_email", "global:weno_provider_password", $_SESSION['authUserID'] ?? '') + ); } + + $flag = false; while ($row = sqlFetchArray($gl)) { + $flag = true; $vendors[$row['gl_name']] = $row['gl_value']; } + if (!$flag) { + $this->saveVendorGlobals($vendors, 'global'); + } + $flag = false; + while ($row = sqlFetchArray($us)) { + $flag = true; + $key = substr($row['setting_label'], 7); + $vendors[$key] = $row['setting_value']; + } + if (!$flag && !empty($_SESSION['authUserID'] ?? '')) { + $this->saveVendorGlobals($vendors, 'user'); + } 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']); + $vendors['weno_provider_password'] = $crypt->decryptStandard($vendors['weno_provider_password']); } return $vendors; } /** - * @param $vendors + * @param $items * @return void */ - public function saveVendorGlobals($items): void + public function saveVendorGlobals($items, $which = null): 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']); + if (!empty($items['weno_encryption_key'])) { + $items['weno_encryption_key'] = $crypt->encryptStandard($items['weno_encryption_key']); + } + if (!empty($items['weno_admin_password'])) { + $items['weno_admin_password'] = $crypt->encryptStandard($items['weno_admin_password']); + } + if (!empty($items['weno_provider_password'])) { + $items['weno_provider_password'] = $crypt->encryptStandard($items['weno_provider_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) { - $GLOBALS[$key] = $vendor; - sqlQuery( - "INSERT INTO `globals` (`gl_name`,`gl_value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `gl_name` = ?, `gl_value` = ?", - array($key, $vendor, $key, $vendor) - ); + $userSettings['weno_provider_email'] = $items['weno_provider_email']; + $userSettings['weno_provider_password'] = $items['weno_provider_password']; + + $GLOBALS['weno_encryption_key'] = $items['weno_encryption_key']; + $GLOBALS['weno_admin_password'] = $items['weno_admin_password']; + + if ($which != 'user') { + foreach ($vendors as $key => $vendor) { + $GLOBALS[$key] = $vendor; + sqlQuery( + "INSERT INTO `globals` (`gl_name`,`gl_value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `gl_name` = ?, `gl_value` = ?", + array($key, $vendor, $key, $vendor) + ); + } + } + if ($which != 'global' && !empty($_SESSION['authUserID'] ?? '')) { + foreach ($userSettings as $key => $vendor) { + $GLOBALS[$key] = $vendor; + sqlQuery( + "INSERT INTO `user_settings` (`setting_label`,`setting_value`, `setting_user`) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE `setting_value` = ?, `setting_user` = ?", + array('global:' . $key, $vendor, $_SESSION['authUserID'], $vendor, $_SESSION['authUserID'] ?? '') + ); + } } } @@ -126,7 +161,7 @@ function getModuleRegistry($modId, string $col = '*'): array */ public function isWenoConfigured(): bool { - self::statusPharmacyDownloadReset(); // if last failed, reset to active + // self::statusPharmacyDownloadReset(); // if last failed, reset to active TODO: this may cause a race condition! Check. $config = $this->getVendorGlobals(); $keys = array_keys($config); foreach ($keys as $key) { @@ -182,4 +217,22 @@ public static function setModuleState($modId, $flag, $flag_ui): array|bool|null $sql = "UPDATE `modules` SET `mod_active` = ?, `mod_ui_active` = ? WHERE `mod_id` = ? OR `mod_directory` = ?"; return sqlQuery($sql, array($flag, $flag_ui, $modId, $modId)); } + + public static function getModuleState($modId): bool + { + $sql = "SELECT `mod_active` FROM `modules` WHERE `mod_id` = ? OR `mod_directory` = ?"; + $flag = sqlQuery($sql, array($modId, $modId)); + + return !empty($flag['mod_active']); + } + + /** + * @return string + */ + public function getProviderName(): string + { + $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']; + } } 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 50f80ec5734..f7dde667706 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 @@ -115,7 +115,7 @@ public function getWenoAlternatePharm($pid) public function checkWenoPharmacyLog() { - $db_exist = sqlStatement("SELECT * FROM weno_download_log LIMIT 1"); + $db_exist = sqlStatement("SELECT * FROM weno_download_log ORDER BY `created_at` DESC, `id` DESC LIMIT 1"); if (empty($db_exist)) { return "empty"; } else { 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 3708daa007a..55c2f7d9c86 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 @@ -200,6 +200,10 @@ public function createJsonObject(): false|string $wenObj['PatientHeight'] = substr($this->vitals['height'] ?? '', 0, -3); $wenObj['PatientWeight'] = substr($this->vitals['weight'] ?? '', 0, -3); $wenObj['HeightWeightObservationDate'] = $heightDate[0]; + } elseif (!empty($this->vitals['height'] ?? '') && !empty($this->vitals['weight'] ?? '')) { // may as well send + $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)) { @@ -307,7 +311,7 @@ public function getFacilityInfo(): array|null|false } else { // from users facility $facilityService = new FacilityService(); - $locId = $facilityService->getFacilityForUser($_SESSION['authUserID']); + $locId = $facilityService->getFacilityForUser($_SESSION['authUserID'] ?? ''); } if (empty($locId['weno_id'] ?? '')) { @@ -379,10 +383,7 @@ private function getPatientInfo(): mixed */ public static function styleErrors($error): string { - $log = "

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

"; - return $log; + return "

" . text($error) . "

"; } /** @@ -426,14 +427,18 @@ public function cipherPayload(): string public function getProviderPassword(): mixed { if (!empty($GLOBALS['weno_provider_password'])) { - return $this->cryptoGen->decryptStandard($GLOBALS['weno_provider_password']); + $ret = $this->cryptoGen->decryptStandard($GLOBALS['weno_provider_password']); + if (!$ret) { + return ("REQED:{user_settings}" . xlt('Your Provider Password fails decryption. Go to User Settings Weno Tab and reenter your Weno Provider Password')); + } + return $ret; } else { - return "REQED:{user_settings}" . xlt('Provider Password is missing. Go to User Settings Weno Tab and enter your Weno Provider Password'); + return "REQED:{user_settings}" . xlt('Your Provider Password is missing. Go to User Settings Weno Tab and enter your Weno Provider Password'); } } /** - * @return array|false|null + * @return array|null */ public function getVitals(): ?array { @@ -448,9 +453,9 @@ public function getVitals(): ?array } } elseif (empty($vitals)) { $vitals = [ - "date" => date('Y-m-d H:i:s'), - "height" => 0, - "weight" => 0 + "date" => date('Y-m-d H:i:s'), + "height" => 0, + "weight" => 0 ]; } return $vitals; @@ -492,9 +497,9 @@ public function getPharmacy(): string|array } /** - * @return mixed + * @return string */ - public function getProviderName(): mixed + public function getProviderName(): string { $provider_info = sqlQuery("select fname, mname, lname from users where username=? ", [$_SESSION["authUser"]]); $provider_info = $provider_info ?? ['fname' => '', 'mname' => '', 'lname' => '']; @@ -502,9 +507,9 @@ public function getProviderName(): mixed } /** - * @return mixed + * @return string */ - public function getPatientName(): mixed + public function getPatientName(): string { $patient_info = sqlQuery("select fname, mname, lname from patient_data where pid=? ", [$_SESSION["pid"]]); $patient_info = $patient_info ?? ['fname' => '', 'mname' => '', 'lname' => '']; @@ -530,18 +535,34 @@ public function getWenoProviderId($id = null): mixed } // 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 ((!empty($GLOBALS['weno_provider_uid'])) && !empty($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']]); + $GLOBALS['weno_provider_uid'] = $provider['weno_prov_id']; + $sql = "INSERT INTO `user_settings` (`setting_value`, `setting_user`, `setting_label`) + VALUES (?, ?, 'global:weno_provider_uid') + ON DUPLICATE KEY UPDATE `setting_value` = ?"; + sqlQuery($sql, [$provider['weno_prov_id'], $id, $provider['weno_prov_id']]); } + + $GLOBALS['weno_provider_uid'] = $GLOBALS['weno_prov_id'] = $provider['weno_prov_id']; // update globals + return $provider['weno_prov_id']; + } elseif (!empty($provider['weno_prov_id'] ?? '') && empty($GLOBALS['weno_provider_uid'])) { + $sql = "INSERT INTO `user_settings` (`setting_value`, `setting_user`, `setting_label`) + VALUES (?, ?, 'global:weno_provider_uid') + ON DUPLICATE KEY UPDATE `setting_value` = ?"; + sqlQuery($sql, [$provider['weno_prov_id'], $id, $provider['weno_prov_id']]); + + $GLOBALS['weno_provider_uid'] = $GLOBALS['weno_prov_id'] = $provider['weno_prov_id']; + return $provider['weno_prov_id']; + } elseif (empty($provider['weno_prov_id'] ?? '') && !empty($GLOBALS['weno_provider_uid'])) { + $sql = "INSERT INTO `users` (`weno_prov_id`, `id`) VALUES (?, ?) + ON DUPLICATE KEY UPDATE `weno_prov_id` = ?"; + sqlQuery($sql, [$GLOBALS['weno_provider_uid'], $id, $GLOBALS['weno_provider_uid']]); + + $provider['weno_prov_id'] = $GLOBALS['weno_prov_id'] = $GLOBALS['weno_provider_uid']; 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 e0be198ee5e..ef926151bf5 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 @@ -23,17 +23,16 @@ public function __construct() public function getLastPrescriptionLogStatus(): bool|array|null { $params = "prescription"; - $sql = "SELECT * FROM weno_download_log WHERE "; - $sql .= "VALUE = ? ORDER BY created_at DESC LIMIT 1"; + $sql = "SELECT * FROM weno_download_log WHERE VALUE = ? ORDER BY `created_at` DESC, `id` DESC LIMIT 1"; return sqlQuery($sql, [$params]); } - public function getLastPharmacyDownloadStatus(): bool|array|null + public function getLastPharmacyDownloadStatus($lastStatus = ''): bool|array|null { $params = "pharmacy"; - $v = ['count' => 0, 'created_at' => '', 'status' => 'Unknown']; - $vsql = sqlQuery("SELECT * FROM `weno_download_log` WHERE `value` = ? ORDER BY `created_at` DESC LIMIT 1", [$params]); + $v = ['count' => 0, 'created_at' => 'Never', 'status' => 'Possibly download is in progress.']; + $vsql = sqlQuery("SELECT * FROM `weno_download_log` WHERE `value` = ? ORDER BY `created_at` DESC, `id` DESC LIMIT 1", [$params]); if (!$vsql) { return $v; } @@ -41,6 +40,13 @@ public function getLastPharmacyDownloadStatus(): bool|array|null $count = sqlQuery("SELECT COUNT(`id`) as count FROM `weno_pharmacy`"); $v['count'] = $count['count'] ?? 0; + if (!empty($lastStatus)) { + $vsql = sqlQuery("SELECT `created_at` FROM `weno_download_log` WHERE `value` = ? AND `status` = ? ORDER BY `created_at` DESC, `id` DESC LIMIT 1", [$params, $lastStatus]); + if ($vsql) { + $v['created_at'] = $vsql['created_at']; + } + } + return $v; } diff --git a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoValidate.php b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoValidate.php index d5fca95c54b..3fbaed3fa9b 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/Services/WenoValidate.php +++ b/interface/modules/custom_modules/oe-module-weno/src/Services/WenoValidate.php @@ -51,12 +51,11 @@ public function setNewEncryptionKey($key): void { $gbl = $this->getVendorGlobals(); $gbl['weno_encryption_key'] = $key; + $GLOBALS['weno_encryption_key'] = $key; // save the new key to the database. // save will also set the global to stay current. $this->saveVendorGlobals($gbl); - error_log('A new encryption key ' . $key . ' was created and saved: ' . date('Y-d-m H:i:s', time())); - $wenoLog = new WenoLogService(); - $wenoLog->insertWenoLog("new_encryption_key", "saved new key value " . $key); + error_log('A new encryption key was created and saved: ' . date('Y-m-d H:i:s', time())); } /** @@ -160,8 +159,8 @@ public function requestEncryptionKeyReset(): false|int|string $newKey = $response['Body']['Success']['NewEncryptionKey'] ?? ''; return ($response !== false && !empty($newKey)) ? trim($newKey) : false; - } catch (GuzzleException $e) { - // Handle Guzzle Exception + } catch (\Exception $e) { + // Handle Exception return false; } } @@ -231,11 +230,11 @@ private function sendRequest($payload): false|array|string $result = json_decode(json_encode($result), true); // make associative array. return $result ?: []; } else { - error_log("invalid_http_status_$httpCode"); + error_log(text("invalid_http_status_$httpCode")); return "connection_problem_$httpCode"; } } catch (GuzzleException $e) { - error_log($e->getMessage()); + error_log(errorLogEscape($e->getMessage())); return 'connection_problem_notconnected'; } } @@ -244,7 +243,7 @@ private function sendRequest($payload): false|array|string * @param $resetOnInvalid * @return bool */ - public function validateAdminCredentials($resetOnInvalid = false): bool + public function validateAdminCredentials($resetOnInvalid = false, $where = "prescription"): bool { $newKey = ''; $isKeyValid = $this->verifyEncryptionKey(); @@ -256,7 +255,11 @@ public function validateAdminCredentials($resetOnInvalid = false): bool if (!empty($newKey)) { // save new admin production key. $this->setNewEncryptionKey($newKey); + error_log(errorLogEscape("$where Encryption Verify returned Invalid Key. Attempted to reset key.")); + $wenoLog = new WenoLogService(); + $wenoLog->insertWenoLog(text("$where"), "reset_encryption_key"); } + return false; } // return new key or encrypted key status (default). return !empty($newKey) ? trim($newKey) : $isKeyValid; diff --git a/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php b/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php index 565b2d83c44..281d18c392b 100644 --- a/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php +++ b/interface/modules/custom_modules/oe-module-weno/src/WenoGlobalConfig.php @@ -43,8 +43,8 @@ public function __construct() } /** - * @deprecated Left for legacy purposes and replaced by installation set up. * @return array[] + * @deprecated Left for legacy purposes and replaced by installation set up. */ public function getGlobalSettingSectionConfiguration(): array { @@ -84,27 +84,27 @@ public function getGlobalSettingSectionConfiguration(): array , 'default' => '' , 'user_setting' => false ]*/ - self::WENO_PROVIDER_EMAIL => [ + self::WENO_PROVIDER_EMAIL => [ 'title' => xl('Weno Provider Email') , 'description' => xl('') , 'type' => GlobalSetting::DATA_TYPE_TEXT , 'default' => '' , 'user_setting' => true - ] - , self::WENO_PROVIDER_PASSWORD => [ + ] + , self::WENO_PROVIDER_PASSWORD => [ 'title' => xl('Weno Provider Password') , 'description' => xl('') , 'type' => GlobalSetting::DATA_TYPE_ENCRYPTED , 'default' => '' , 'user_setting' => true - ] - , self::WENO_PROVIDER_UID => [ + ] + , self::WENO_PROVIDER_UID => [ 'title' => xl('Weno Provider ID') , 'description' => xl('When a Weno eRx provider, please enter your Weno provider ID here or in your Users setting. If you are not a Weno provider, please leave this field blank.') , 'type' => GlobalSetting::DATA_TYPE_TEXT , 'default' => '' , 'user_setting' => true - ] + ] ]; } } diff --git a/interface/modules/custom_modules/oe-module-weno/table.sql b/interface/modules/custom_modules/oe-module-weno/table.sql index 6106b63d6d9..d76f73ac68b 100644 --- a/interface/modules/custom_modules/oe-module-weno/table.sql +++ b/interface/modules/custom_modules/oe-module-weno/table.sql @@ -1,65 +1,71 @@ +# -- DELETE FROM `user_settings` WHERE `setting_label` LIKE 'global:weno%'; +# -- DELETE FROM `globals` WHERE `gl_name` LIKE 'weno%'; +# -- DROP TABLE IF EXISTS `weno_pharmacy`; +# -- DROP TABLE IF EXISTS `weno_assigned_pharmacy`; +# -- DROP TABLE IF EXISTS `weno_download_log`; + #IfNotTable weno_pharmacy CREATE TABLE `weno_pharmacy` ( - `id` int(20) NOT NULL AUTO_INCREMENT, - `App` varchar(8) DEFAULT NULL, - `NCPDP` varchar(8) DEFAULT NULL, - `NCPDP_safe` varchar(7) DEFAULT NULL, - `Mutually_Defined_ID` varchar(10) DEFAULT NULL, - `Mutually_Defined_ID_safe` varchar(10) DEFAULT NULL, - `NPI` varchar(10) DEFAULT NULL, - `NPI_safe` varchar(10) DEFAULT NULL, - `Business_Name` varchar(255) DEFAULT NULL, - `Address_Line_1` varchar(255) DEFAULT NULL, - `Address_Line_2` varchar(255) DEFAULT NULL, - `City` varchar(20) DEFAULT NULL, - `State` varchar(20) DEFAULT NULL, - `ZipCode` varchar(5) DEFAULT NULL, - `ZipCode_safe` varchar(10) DEFAULT NULL, - `Country_Code` varchar(255) DEFAULT NULL, - `International` tinyint(1) DEFAULT NULL, - `Latitude` varchar(255) DEFAULT NULL, - `Longitude` varchar(255) DEFAULT NULL, - `Pharmacy_Phone` varchar(255) DEFAULT NULL, - `Pharmacy_Phone_safe` varchar(255) DEFAULT NULL, - `Pharmacy_Fax` varchar(255) DEFAULT NULL, - `Types` varchar(255) DEFAULT NULL, - `Script_Msg_Accepted` varchar(255) DEFAULT NULL, - `Specialized_Msg_Accepted` varchar(255) DEFAULT NULL, - `Connectivity_Status` varchar(255) DEFAULT NULL, - `Accept_TSO` varchar(255) DEFAULT NULL, - `DEA_Audit_Exp` varchar(255) DEFAULT NULL, - `Test_Pharmacy` varchar(5) DEFAULT NULL, - `State_Wide_Mail_Order` varchar(6) NOT NULL, - `Created` datetime DEFAULT NULL, - `Modified` datetime DEFAULT NULL, - `Deleted` datetime DEFAULT NULL, - `24HR` varchar(3) DEFAULT NULL, - `on_weno` tinytext, - PRIMARY KEY (`id`), - UNIQUE KEY `ncpdp` (`NCPDP`) -) ENGINE=InnoDB; + `id` int(20) NOT NULL AUTO_INCREMENT, + `App` varchar(8) DEFAULT NULL, + `NCPDP` varchar(8) DEFAULT NULL, + `NCPDP_safe` varchar(7) DEFAULT NULL, + `Mutually_Defined_ID` varchar(10) DEFAULT NULL, + `Mutually_Defined_ID_safe` varchar(10) DEFAULT NULL, + `NPI` varchar(10) DEFAULT NULL, + `NPI_safe` varchar(10) DEFAULT NULL, + `Business_Name` varchar(255) DEFAULT NULL, + `Address_Line_1` varchar(255) DEFAULT NULL, + `Address_Line_2` varchar(255) DEFAULT NULL, + `City` varchar(20) DEFAULT NULL, + `State` varchar(20) DEFAULT NULL, + `ZipCode` varchar(5) DEFAULT NULL, + `ZipCode_safe` varchar(10) DEFAULT NULL, + `Country_Code` varchar(255) DEFAULT NULL, + `International` tinyint(1) DEFAULT NULL, + `Latitude` varchar(255) DEFAULT NULL, + `Longitude` varchar(255) DEFAULT NULL, + `Pharmacy_Phone` varchar(255) DEFAULT NULL, + `Pharmacy_Phone_safe` varchar(255) DEFAULT NULL, + `Pharmacy_Fax` varchar(255) DEFAULT NULL, + `Types` varchar(255) DEFAULT NULL, + `Script_Msg_Accepted` varchar(255) DEFAULT NULL, + `Specialized_Msg_Accepted` varchar(255) DEFAULT NULL, + `Connectivity_Status` varchar(255) DEFAULT NULL, + `Accept_TSO` varchar(255) DEFAULT NULL, + `DEA_Audit_Exp` varchar(255) DEFAULT NULL, + `Test_Pharmacy` varchar(5) DEFAULT NULL, + `State_Wide_Mail_Order` varchar(6) NOT NULL, + `Created` datetime DEFAULT NULL, + `Modified` datetime DEFAULT NULL, + `Deleted` datetime DEFAULT NULL, + `24HR` varchar(3) DEFAULT NULL, + `on_weno` tinytext, + PRIMARY KEY (`id`), + UNIQUE KEY `ncpdp` (`NCPDP`) +) ENGINE = InnoDB; #EndIf #IfNotTable weno_assigned_pharmacy CREATE TABLE `weno_assigned_pharmacy` ( - `id` INT(10) NOT NULL AUTO_INCREMENT, - `pid` BIGINT(20) NOT NULL, - `primary_ncpdp` VARCHAR(8) NOT NULL, + `id` INT(10) NOT NULL AUTO_INCREMENT, + `pid` BIGINT(20) NOT NULL, + `primary_ncpdp` VARCHAR(8) NOT NULL, `alternate_ncpdp` VARCHAR(8) NOT NULL, KEY (`pid`), - PRIMARY KEY(`id`) -) ENGINE=InnoDB; + PRIMARY KEY (`id`) +) ENGINE = InnoDB; #EndIf #IfNotTable weno_download_log CREATE TABLE `weno_download_log` ( - `id` BIGINT(20) NOT NULL AUTO_INCREMENT, - `value` VARCHAR(63) NOT NULL, - `status` VARCHAR(255) NOT NULL, - `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `id` BIGINT(20) NOT NULL AUTO_INCREMENT, + `value` VARCHAR(63) NOT NULL, + `status` VARCHAR(255) NOT NULL, + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `value` (`value`) -) ENGINE=InnoDB; +) ENGINE = InnoDB; #EndIf -- For early adopters of weno, in case they need to upgrade let's delete and add below. @@ -68,21 +74,19 @@ DELETE FROM `background_services` WHERE `name` = 'WenoExchange'; #EndIf #IfNotRow background_services name WenoExchangePharmacies -INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) -VALUES ('WenoExchangePharmacies', 'Weno Exchange Pharmacy', '0', '0', current_timestamp(), '1440', 'downloadWenoPharmacy', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); +INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) VALUES ('WenoExchangePharmacies', 'Weno Exchange Pharmacy', '0', '0', current_timestamp(), '1440', 'downloadWenoPharmacy', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); #EndIf #IfNotRow background_services name WenoExchange -INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) -VALUES ('WenoExchange', 'Weno Log Sync', '0', '0', current_timestamp(), '30', 'downloadWenoPrescriptionLog', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); +INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) VALUES ('WenoExchange', 'Weno Log Sync', '0', '0', current_timestamp(), '30', 'downloadWenoPrescriptionLog', '/interface/modules/custom_modules/oe-module-weno/scripts/weno_log_sync.php', '100'); #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 #IfNotColumnType weno_download_log status varchar(255) diff --git a/interface/modules/custom_modules/oe-module-weno/templates/download_log_viewer.php b/interface/modules/custom_modules/oe-module-weno/templates/download_log_viewer.php index 5da04279f24..a3c0d83b8c5 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/download_log_viewer.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/download_log_viewer.php @@ -37,7 +37,7 @@ $('.datepicker').datetimepicker({ - + }); }); @@ -120,6 +120,19 @@ function downloadPresLog(){

+ '; + while ($task = sqlFetchArray($backGroundTask)) { + $title = $task['title']; + $nextRun = $task['next_run']; + echo '' . text($title) . ' ' . xlt("next run") . ': ' . text($nextRun) . ''; + } + echo ''; + } + ?>

@@ -129,10 +142,9 @@ function downloadPresLog(){
- +
- @@ -141,10 +153,9 @@ function downloadPresLog(){ - - - + + - @@ -174,7 +184,7 @@ function downloadPresLog(){ - +
@@ -224,12 +234,12 @@ function downloadPresLog(){ echo $message; } if (isset($_GET['search']) || isset($_GET['delete'])) { - $sql = "SELECT `id`, `value`, `status`, `created_at` FROM `weno_download_log` WHERE `created_at` BETWEEN ? AND ? ORDER BY `created_at` DESC"; + $sql = "SELECT `id`, `value`, `status`, `created_at` FROM `weno_download_log` WHERE `created_at` BETWEEN ? AND ? ORDER BY `created_at` DESC, `id` DESC"; $result = sqlStatement($sql, [$fmtStartDate . ' 00:00:00', $fmtEndDate . ' 23:59:59']); // Display logs in a table if ($result ?? false) { echo '
'; - echo '
#
1
2
'; + echo '
'; echo ''; echo ''; echo ''; 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 df28c0c3e86..6b10c6d2076 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/indexrx.php @@ -112,7 +112,7 @@ $(function () { const warnMsg = ""; syncAlertMsg(warnMsg, 8000, 'danger', 'lg').then(() => { - window.location.href = "/interface/patient_file/summary/demographics.php?set_pid="; + window.location.href = "/interface/patient_file/summary/demographics.php?set_pid="; }); }); @@ -139,10 +139,10 @@
-
+

"> - +

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 768e297ce38..91e9edacb33 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 @@ -40,7 +40,7 @@ $pid = ($frow['blank_form'] ?? null) ? 0 : $pid; $logService = new WenoLogService(); -$pharmacy_log = $logService->getLastPharmacyDownloadStatus(); +$pharmacy_log = $logService->getLastPharmacyDownloadStatus('Success'); $activeStatus = sqlQuery("SELECT `active` FROM background_services WHERE `name` = 'WenoExchangePharmacies'"); @@ -73,16 +73,16 @@ -
+
- + $error = false; ?> +
-
-
- - - - - - +
+
+ + + + +
+
+
+ + + +
+ +
+ +
+
+ + + + +
-
- - - -
-
- -
- - - - -
-
-
-
- -
-
- - - -
+
+ +
+
+ + + +
-
- +
+
+
- - + +
- - + +
@@ -201,21 +211,13 @@ function init(prevPrimPharmacy, prevAltPharmacy) { let jsPrim = JSON.parse(prevPrimPharmacy); let jsAlt = JSON.parse(prevAltPharmacy); - // may or may not want this! - /*if (jsPrim != false) { - var html = (''); - $("#weno_pharmacy").html(html); - //setting the form value for Weno Primary Pharmacy and Display Text respectively - $('#weno_primary').text(" " + jsPrim.business_name); - }*/ - if (jsPrim !== false) { - $('#weno_primary').text(jsAttr(" " + (jsPrim.business_name) + ' - ' + (jsPrim.address_line_1))); + + if (jsPrim !== false && jsPrim !== null && jsPrim.business_name !== '') { + $('#weno_primary').text(jsText((jsPrim.business_name) + ' - ' + (jsPrim.address_line_1))); $('#primary_pharmacy').val(jsAttr(jsPrim.primary_ncpdp)); } - if (jsAlt !== false) { - $('#weno_alt').text(jsAttr(" " + (jsAlt.business_name) + ' - ' + (jsAlt.address_line_1))); + if (jsAlt !== false && jsAlt !== null && jsAlt.business_name !== '') { + $('#weno_alt').text(jsText((jsAlt.business_name) + ' - ' + (jsAlt.address_line_1))); $('#alternate_pharmacy').val(jsAttr(jsAlt.alternate_ncpdp)); } } @@ -258,13 +260,20 @@ function fullDayChanged(cb) { } function testPharmaciesChanged(cb) { + let test = $('#weno_pharmacy'); this.testPharmacies = cb ? cb.checked : false; + $(".test-hide").toggleClass('d-none'); + if (cb.checked) { + if (test.hasClass('select2-hidden-accessible')) { + test.select2('destroy').off('select2:open'); + } + makeRequest(); + } } function doAjax() { - var state = document.getElementById('form_weno_state').selectedOptions[0].value; - var coverage = document.getElementById('weno_coverage').selectedOptions[0].value; - + const state = document.getElementById('form_weno_state').selectedOptions[0].value; + const coverage = document.getElementById('weno_coverage').selectedOptions[0].value; $.ajax({ url: url, cache: false, @@ -314,7 +323,7 @@ function createWenoPharmacySelect2() { }, minimumInputLength: 3, cache: true, - placeholder: 'Enter desired Pharmacy', + placeholder: 'Default Pharmacies', allowClear: true }); } @@ -347,7 +356,7 @@ function createWenoCitySelect2() { }, minimumInputLength: 3, cache: true, - placeholder: 'Enter City' + placeholder: 'Select a City' }); } @@ -374,7 +383,7 @@ function search() { if (!wenoCity && !wenoZipcode) { $('#weno_city').addClass("is-invalid"); - $('.warn').text(requiredField); + $('.warn').text(jsText(requiredField)); } if (!wenoState && !wenoZipcode) { @@ -388,12 +397,19 @@ function search() { } function makeRequest() { + // clear main search fields + if (testPharmacies) { + wenoState = ''; + wenoCity = ''; + wenoZipcode = ''; + coverage = ''; + } let data = { searchFor: 'weno_drop', weno_state: wenoState, weno_city: wenoCity, - coverage: coverage, weno_zipcode: wenoZipcode, + coverage: coverage, full_day: fullDay, test_pharmacy: testPharmacies, csrf_token_form: csrf @@ -403,37 +419,45 @@ function makeRequest() { type: "GET", data: data, success: function (data) { - var html = ''; + let html = ''; data = JSON.parse(data); - if (data == null) { - html += (''); + if (data === null || data.length === 0) { // Check for no data or empty array + html += ''; + let msg = jsText(xl('No results found.')); + syncAlertMsg(msg, 2000, 'warning'); // Display warning message } else { - html += (''); + if (testPharmacies) { + html += ''; + } else { + html += ''; + } $.each(data, function (i, value) { - html += (''); + html += ''; }); + let msg = (testPharmacies ? (jsText(xl('Test')) + ' ') : '') + jsText(xl('Pharmacy search completed')) + ': ' + data.length + ' ' + jsText(xl('result(s) found.')); + syncAlertMsg(msg, 2000, 'warning', 'lg'); // Display success message } - - $("#weno_pharmacy").html(html); + $("#weno_pharmacy").html(html); // Write HTML options to the select element }, // Error handling error: function (error) { + let msg = jsText(xl('Something went wrong. Try again!')) + ' ' + jsAttr(error); + syncAlertMsg(msg, 5000, 'danger', 'lg'); // Display error message } }); - } function assignPrimaryPharmacy() { weno_pharm = $('#weno_pharmacy').val(); weno_pharm_text = $('#weno_pharmacy').text(); - $('#weno_primary').text(" " + wenoPrimPharm); + $('#weno_primary').text(jsText(wenoPrimPharm)); $('#primary_pharmacy').val(weno_pharm); } function assignAlternatePharmacy() { weno_alt = $('#weno_pharmacy').val(); weno_alt_text = $('#weno_pharmacy').text(); - $('#weno_alt').text(" " + wenoPrimPharm); + $('#weno_alt').text(jsText(wenoPrimPharm)); $('#alternate_pharmacy').val(weno_alt); } diff --git a/interface/modules/custom_modules/oe-module-weno/templates/setup_facilities.php b/interface/modules/custom_modules/oe-module-weno/templates/setup_facilities.php index bf3f52c3a75..b7cd45b1914 100644 --- a/interface/modules/custom_modules/oe-module-weno/templates/setup_facilities.php +++ b/interface/modules/custom_modules/oe-module-weno/templates/setup_facilities.php @@ -48,9 +48,17 @@ -
-
- - +
+ +
@@ -75,9 +73,9 @@ function getProviderByWenoId($external_id, $provider_id = ''): string
' . xlt("ID") . '
+ +
+ @@ -157,10 +150,10 @@ $help_items = [ 0) { foreach ($InstallersAll as $moduleResult) { @@ -175,6 +168,7 @@ $help_items = [ + +
z_xlt('ID'); ?> z_xlt('Module'); ?>z_xlt('Release'); ?> z_xlt('Status'); ?> z_xlt('Menu Text'); ?> z_xlt('Nick Name'); ?>
escapeHtml($count); ?> escapeHtml($moduleResult->modName); ?>escapeHtml($moduleResult->sql_version ?: '0.0.0'); ?> sqlRun == 0) { @@ -236,11 +230,11 @@ $help_items = [ sqlRun == 0 && $moduleResult->modActive == 0) { ?> - + modActive == 1) { ?> modUiActive == 1 && $moduleResult->type == 0) { ?> - + modActive == 0 && $moduleResult->type == 0) { ?> modUiActive == 1) { @@ -263,8 +257,29 @@ $help_items = [ +
+ +
z_xlt("Lamina's Module Listings"); ?>
+ + + + + + + + + + + + + + + + + + 0) { foreach ($InstallersAll as $moduleResult) { @@ -279,6 +294,7 @@ $help_items = [ +
z_xlt('ID'); ?>z_xlt('Module'); ?>z_xlt('Release'); ?>z_xlt('Status'); ?>z_xlt('Menu Text'); ?>z_xlt('Nick Name'); ?>z_xlt('Type'); ?> z_xlt('Dependency Modules'); ?>z_xlt('Action'); ?>z_xlt('Configuration'); ?>
escapeHtml($count); ?> escapeHtml($moduleResult->modName); ?>escapeHtml($moduleResult->sql_version ?: '0.0.0'); ?> sqlRun == 0) { @@ -362,38 +378,7 @@ $help_items = [ ?>
+
- - - 0) { - */ ?> diff --git a/interface/modules/zend_modules/public/js/installer/action.js b/interface/modules/zend_modules/public/js/installer/action.js index bff38c80f32..fd1247102bc 100644 --- a/interface/modules/zend_modules/public/js/installer/action.js +++ b/interface/modules/zend_modules/public/js/installer/action.js @@ -1,4 +1,3 @@ - /** * interface/modules/zend_modules/public/js/installer/action.js * @@ -27,12 +26,17 @@ function register(status, title, name, method, type) { } function manage(id, action) { - if (action == 'unregister') { + if (action === 'unregister') { if (!confirm("Please Confirm with OK to Unregister this Module.")) { return false; } } - install_upgrade_log = $("#install_upgrade_log"); + if (action === 'reset_module') { + if (!confirm("Please Confirm with OK to Reset Module!\nThis action may possibly remove database dependencies that are only related to this module.")) { + return false; + } + } + let install_upgrade_log = $("#install_upgrade_log"); install_upgrade_log.empty(); if (document.getElementById('mod_enc_menu')) diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index 968bd7d3850..e61a5476519 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -29,7 +29,6 @@ use OpenEMR\Common\Csrf\CsrfUtils; use OpenEMR\Common\Logging\EventAuditLogger; use OpenEMR\Common\Twig\TwigContainer; -use OpenEMR\Common\Logging\SystemLogger; use OpenEMR\Core\Header; use OpenEMR\FHIR\Config\ServerConfig; use OpenEMR\OeUI\OemrUI; @@ -341,7 +340,7 @@ function checkBackgroundServices() $title = ($userMode) ? xlt("User Settings") : xlt("Configuration"); ?> -<?php echo $title; ?> +<?php echo $title; ?>