From a758a759509cea920ff095c2844b0502f0390a63 Mon Sep 17 00:00:00 2001 From: Jerry Padgett Date: Thu, 2 May 2024 08:20:44 -0400 Subject: [PATCH] Bring into patch 1 2420E #7405 (#7418) * Bring into patch 1 2420E #7405 * database update I think is needed for tests to run! --- interface/forms/newpatient/common.php | 9 +++ interface/forms/newpatient/save.php | 6 +- library/globals.inc.php | 6 ++ sql/database.sql | 43 +-------------- sql/patch.sql | 4 ++ src/Billing/Claim.php | 79 ++++++++++++++++++++++++++- src/Billing/MiscBillingOptions.php | 24 ++++++++ src/Billing/X125010837P.php | 17 +++++- src/Services/EncounterService.php | 18 ++++++ 9 files changed, 162 insertions(+), 44 deletions(-) diff --git a/interface/forms/newpatient/common.php b/interface/forms/newpatient/common.php index 6367bb747c9..5a3b87037a2 100644 --- a/interface/forms/newpatient/common.php +++ b/interface/forms/newpatient/common.php @@ -553,6 +553,15 @@ function cancelClickedOld() { +
+
+ + genOrderingProviderSelect('ordering_provider_id', '-- ' . xl("Please Select") . ' --', $result["ordering_provider_id"] ?? ''); + ?> + +
+
diff --git a/interface/forms/newpatient/save.php b/interface/forms/newpatient/save.php index 2b247b8f219..40ac2a875ec 100644 --- a/interface/forms/newpatient/save.php +++ b/interface/forms/newpatient/save.php @@ -57,6 +57,7 @@ $referring_provider_id = $_POST['referring_provider_id'] ?? null; //save therapy group if exist in external_id column $external_id = isset($_POST['form_gid']) ? $_POST['form_gid'] : ''; +$ordering_provider_id = $_POST['ordering_provider_id'] ?? null; $discharge_disposition = $_POST['discharge_disposition'] ?? null; $discharge_disposition = $discharge_disposition != '_blank' ? $discharge_disposition : null; @@ -113,6 +114,7 @@ 'encounter_type_code' => $encounter_type_code, 'encounter_type_description' => $encounter_type_description, 'in_collection' => $in_collection, + 'ordering_provider_id' => $ordering_provider_id, ]; $col_string = implode(" = ?, ", array_keys($data)) . " = ?"; @@ -153,6 +155,7 @@ $encounter_type_code, $encounter_type_description, $in_collection, + $ordering_provider_id, $id ); $col_string = implode(" = ?, ", [ @@ -171,7 +174,8 @@ 'referring_provider_id', 'encounter_type_code', 'encounter_type_description', - 'in_collection' + 'in_collection', + 'ordering_provider_id', ]) . " =?"; sqlStatement("UPDATE form_encounter SET $datepart $col_string WHERE id = ?", $sqlBindArray); } else { diff --git a/library/globals.inc.php b/library/globals.inc.php index b0f09dde389..725a55a4524 100644 --- a/library/globals.inc.php +++ b/library/globals.inc.php @@ -4308,6 +4308,12 @@ function gblTimeZones() xl('Show Encounter Class option on Encounters'), ], + 'enc_enable_ordering_provider' => [ + xl('Show Ordering Provider option on Encounters'), + getDefaultRenderListOptions(), + RenderFormFieldHelper::HIDE_ALL, + xl('Display the Ordering Provider option on Encounters'), + ], ], ); diff --git a/sql/database.sql b/sql/database.sql index 9c74ef79252..102febd74b8 100644 --- a/sql/database.sql +++ b/sql/database.sql @@ -208,8 +208,6 @@ INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_r INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) VALUES ('X12_SFTP', 'SFTP Claims to X12 Partner Service', 0, 0, '2021-01-18 11:25:10', 1, 'start_X12_SFTP', '/library/billing_sftp_service.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, '2021-01-18 11:25:10', 0, 'start_weno', '/library/weno_log_sync.php', 100); -INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) VALUES ('UUID_Service', 'Automated UUID Creation Service', 1, 0, '2021-01-18 11:25:10', 240, 'autoPopulateAllMissingUuids', '/library/uuid.php', 100); INSERT INTO `background_services` (`name`, `title`, `active`, `running`, `next_run`, `execute_interval`, `function`, `require_once`, `sort_order`) VALUES ('Email_Service', 'Email Service', 1, 0, '2021-01-18 11:25:10', 2, 'emailServiceRun', '/library/email_service_run.php', 100); @@ -1643,44 +1641,6 @@ CREATE TABLE `erx_ttl_touch` ( -- -------------------------------------------------------- --- --- Table structure for table `erx_weno_drugs` --- - -DROP TABLE IF EXISTS `erx_weno_drugs`; -CREATE TABLE `erx_weno_drugs` ( - `drug_id` int(11) NOT NULL AUTO_INCREMENT, - `rxcui_drug_coded` int(11) DEFAULT NULL, - `generic_rxcui` int(11) DEFAULT NULL, - `drug_db_code_qualifier` text, - `full_name` varchar(250) NOT NULL, - `rxn_dose_form` text, - `full_generic_name` varchar(250) NOT NULL, - `brand_name` varchar(250) NOT NULL, - `display_name` varchar(250) NOT NULL, - `route` text, - `new_dose_form` varchar(100) DEFAULT NULL, - `strength` varchar(15) DEFAULT NULL, - `supress_for` text, - `display_name_synonym` text, - `is_retired` text, - `sxdg_rxcui` varchar(10) DEFAULT NULL, - `sxdg_tty` text, - `sxdg_name` varchar(100) DEFAULT NULL, - `psn_drugdescription` varchar(100) DEFAULT NULL, - `ncpdp_quantity_term` text, - `potency_unit_code` varchar(10) DEFAULT NULL, - `dea_schedule_no` int(2) DEFAULT NULL, - `dea_schedule` varchar(7) DEFAULT NULL, - `ingredients` varchar(100) DEFAULT NULL, - `drug_interaction` varchar(100) DEFAULT NULL, - `unit_source_code` varchar(3) DEFAULT NULL, - `code_list_qualifier` int(3) DEFAULT NULL, - PRIMARY KEY (`drug_id`) -) ENGINE=InnoDB; - --- -------------------------------------------------------- - -- -- Table structure for table `erx_rx_log` -- @@ -1945,6 +1905,7 @@ CREATE TABLE `form_encounter` ( `date_end` DATETIME DEFAULT NULL, `in_collection` tinyint(1) default NULL, `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `ordering_provider_id` INT(11) DEFAULT '0' COMMENT 'referring provider, if any, for this visit', PRIMARY KEY (`id`), UNIQUE KEY `uuid` (`uuid`), KEY `pid_encounter` (`pid`, `encounter`), @@ -8053,7 +8014,7 @@ DROP TABLE IF EXISTS `rule_filter`; CREATE TABLE `rule_filter` ( `id` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to the id column in the clinical_rules table', `include_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is exclude and 1 is include', - `required_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is required and 1 is optional', + `required_flag` tinyint(1) NOT NULL default 0 COMMENT '0 is optional and 1 is required', `method` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options list rule_filters', `method_detail` varchar(31) NOT NULL DEFAULT '' COMMENT 'Maps to list_options lists rule__intervals', `value` varchar(255) NOT NULL DEFAULT '', diff --git a/sql/patch.sql b/sql/patch.sql index 53ebca71edf..b23efb63e91 100644 --- a/sql/patch.sql +++ b/sql/patch.sql @@ -55,3 +55,7 @@ UPDATE list_options SET option_id='DOB' WHERE list_id='recent_patient_columns' A #IfMissingColumn form_encounter last_update ALTER TABLE `form_encounter` ADD `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; #EndIf + +#IfMissingColumn form_encounter ordering_provider_id +ALTER TABLE `form_encounter` ADD `ordering_provider_id` INT(11) DEFAULT '0' COMMENT 'ordering provider, if any, for this visit'; +#EndIf diff --git a/src/Billing/Claim.php b/src/Billing/Claim.php index b79dbf5dd0d..61741321f35 100644 --- a/src/Billing/Claim.php +++ b/src/Billing/Claim.php @@ -37,6 +37,7 @@ class Claim public $provider; // row from users table (rendering provider) public $referrer; // row from users table (referring provider) public $supervisor; // row from users table (supervising provider) + public $orderer; // row from users table (ordering provider) public $insurance_numbers; // row from insurance_numbers table for current payer public $supervisor_numbers;// row from insurance_numbers table for current payer public $patient_data; // row from patient_data table @@ -81,6 +82,7 @@ public function __construct($pid, $encounter_id, $x12_partner_id) $this->procs[0]['payer_id'], $this->encounter['supervisor_id'] ); + $this->orderer = (new UserService())->getUser($this->getOrdererId()); } public function getProcsAndDiags($pid, $encounter_id) @@ -190,6 +192,17 @@ public function getReferrerId() return $referrer_id; } + public function getOrdererId(): string|int|null + { + if ($this->billing_options['provider_id'] ?? '') { + $orderer_id = $this->billing_options['provider_id']; + } elseif ($this->encounterService->getOrderingProviderID($this->pid, $this->encounter_id) ?? '') { + $orderer_id = $this->encounterService->getOrderingProviderID($this->pid, $this->encounter_id); + } + + return $orderer_id ?? ''; + } + // This enforces the X12 Basic Character Set. Page A2. public function x12Clean($str) { @@ -1253,7 +1266,7 @@ public function cptUnits($prockey) public function cptNDCID($prockey) { $ndcinfo = $this->procs[$prockey]['ndc_info']; - if (preg_match('/^N4(\S+)\s+(\S\S)(.*)/', $ndcinfo, $tmp)) { + if (preg_match('/^N4(\S+)\s+(\S\S)(.*)/', $ndcinfo ?? '', $tmp)) { $ndc = $tmp[1]; if (preg_match('/^(\d+)-(\d+)-(\d+)$/', $ndc, $tmp)) { return sprintf('%05d%04d%02d', $tmp[1], $tmp[2], $tmp[3]); @@ -1831,4 +1844,68 @@ public function getLineItemAdjustments($aarr) return $this->line_item_adjs; } + + public function ordererLastName() + { + return $this->x12Clean(trim($this->orderer['lname'] ?? '')); + } + + public function ordererFirstName() + { + return $this->x12Clean(trim($this->orderer['fname'])); + } + + public function ordererMiddleName() + { + return $this->x12Clean(trim($this->orderer['mname'])); + } + + public function ordererNPI() + { + return $this->x12Clean(trim($this->orderer['npi'])); + } + + public function ordererUPIN() + { + return $this->x12Clean(trim($this->orderer['upin'])); + } + + public function ordererSSN() + { + return $this->x12Clean(trim(str_replace('-', '', $this->orderer['federaltaxid']))); + } + + public function ordererTaxonomy() + { + if (empty($this->orderer['taxonomy'])) { + return '207Q00000X'; + } + + return $this->x12Clean(trim($this->orderer['taxonomy'])); + } + + public function ordererStreet() + { + return $this->x12Clean(trim($this->orderer['street'])); + } + + public function ordererStreetB() + { + return $this->x12Clean(trim($this->orderer['streetb'])); + } + + public function ordererCity() + { + return $this->x12Clean(trim($this->orderer['city'])); + } + + public function ordererState() + { + return $this->x12Clean(trim($this->orderer['state'])); + } + + public function ordererZip() + { + return $this->x12Clean(trim($this->orderer['zip'])); + } } diff --git a/src/Billing/MiscBillingOptions.php b/src/Billing/MiscBillingOptions.php index ddf93940969..e02abd29692 100644 --- a/src/Billing/MiscBillingOptions.php +++ b/src/Billing/MiscBillingOptions.php @@ -88,6 +88,30 @@ public function genReferringProviderSelect($selname, $toptext, $default = 0, $di echo "\n"; } + public function genOrderingProviderSelect($selname, $toptext, $default = 0, $disabled = false) + { + $query = "SELECT id, lname, fname FROM users WHERE npi != '' ORDER BY lname, fname"; + $res = sqlStatement($query); + echo "\n"; + } + public function qual_id_to_description($qual_type, $value) { $options = $this->hcfa_date_quals[$qual_type]; diff --git a/src/Billing/X125010837P.php b/src/Billing/X125010837P.php index 62cce65e6ba..951650326c3 100644 --- a/src/Billing/X125010837P.php +++ b/src/Billing/X125010837P.php @@ -1509,7 +1509,22 @@ public static function genX12837P( // Segment NM1 (Loop 2420D Supervising Provider Name) omitted. // Segment REF (Loop 2420D Supervising Provider Secondary Identification) omitted. - // Loop 2420E, Ordering Provider omitted. + // Loop 2420E, Ordering Provider + if ($claim->orderer ?? null) { + ++$edicount; + $out .= "NM1" . + "*" . "DK" . + "*" . "1" . + "*" . $claim->ordererLastName() . '*' . $claim->ordererFirstName() . + "*" . + "*" . + "*" . + "*" . "XX" . + "*" . $claim->ordererNPI() . "~\n"; + $out .= "N3" . "*" . $claim->ordererStreet() . "~\n"; + $out .= "N4" . "*" . $claim->ordererCity() . "*" . + $claim->ordererState() . "*" . $claim->ordererZip() . "~\n"; + } // Segment NM1 (Referring Provider Name) omitted. // Segment REF (Referring Provider Secondary Identification) omitted. diff --git a/src/Services/EncounterService.php b/src/Services/EncounterService.php index 1cc0f068d99..4cd76c2f023 100644 --- a/src/Services/EncounterService.php +++ b/src/Services/EncounterService.php @@ -215,6 +215,7 @@ class.notes as class_title, fe.provider_id, fe.referring_provider_id, + fe.ordering_provider_id, providers.provider_uuid, providers.provider_username, referrers.referrer_uuid, @@ -249,6 +250,7 @@ class_code, discharge_disposition, pid as encounter_pid, referring_provider_id, + ordering_provider_id, last_update FROM form_encounter ) fe @@ -710,6 +712,22 @@ public function getReferringProviderID($pid, $encounter_id) return []; } + /** + * Returns the ordering provider for the encounter matching the patient and encounter identifier. + * + * @param $pid The legacy identifier of particular patient + * @param $encounter_id The identifier of a particular encounter + * @return string ordering provider of first row of encounter data (it's an id from the users table) + */ + public function getOrderingProviderID($pid, $encounter_id) + { + $encounterResult = $this->search(['pid' => $pid, 'eid' => $encounter_id], $options = ['limit' => '1']); + if ($encounterResult->hasData()) { + return $encounterResult->getData()[0]['ordering_provider_id'] ?? ''; + } + return []; + } + /** * Return an array of encounters within a date range *