From f9d749656d2e8dcd2dbc365466a9f22523badb9a Mon Sep 17 00:00:00 2001 From: Stephen Nielson Date: Tue, 24 May 2022 21:47:59 -0600 Subject: [PATCH] Openemr fix 5377 (#5378) * Fix the code lookup for immunization negation * Fix negationRationale missing obj propert error * Change immunization refusal reason code Changed the order of the immunization refusal codes so that patient refusal comes before parent refusal. Since they map to the same SNOMED-CT code we want patient refusal to be the default for ccda/qrda imports. * Add debugging methods for qrda * Fix styles --- sql/6_1_0-to-7_0_0_upgrade.sql | 5 ++++ src/Services/Cda/CdaTemplateImportDispose.php | 5 +++- src/Services/Qdm/CqmCalculator.php | 2 +- src/Services/Qdm/IndividualResult.php | 5 ++++ src/Services/Qrda/ExportCat3Service.php | 38 +++++++++++++++++++++++++++ 5 files changed, 53 insertions(+), 2 deletions(-) diff --git a/sql/6_1_0-to-7_0_0_upgrade.sql b/sql/6_1_0-to-7_0_0_upgrade.sql index 0a73afda9..a3fb9f3a4 100644 --- a/sql/6_1_0-to-7_0_0_upgrade.sql +++ b/sql/6_1_0-to-7_0_0_upgrade.sql @@ -708,4 +708,9 @@ INSERT INTO list_options (list_id,option_id,title,seq,is_default,activity, codes #IfNotRow2D list_options list_id drug_interval option_id WK INSERT INTO list_options (list_id,option_id,title,seq,is_default,activity) VALUES ('drug_interval','WK','Weekly',19,0,1); INSERT INTO list_options (list_id,option_id,title,seq,is_default,activity) VALUES ('drug_interval','MO','Monthly',20,0,1); +#EndIf + +#IfRow3D list_options list_id immunization_refusal_reason option_id parental_decision seq 10 +UPDATE list_options SET seq=40 WHERE list_id="immunization_refusal_reason" AND option_id="parental_decision"; +UPDATE list_options SET seq=10 WHERE list_id="immunization_refusal_reason" AND option_id="patient_decision"; #EndIf \ No newline at end of file diff --git a/src/Services/Cda/CdaTemplateImportDispose.php b/src/Services/Cda/CdaTemplateImportDispose.php index e184ac635..0ffb07b85 100644 --- a/src/Services/Cda/CdaTemplateImportDispose.php +++ b/src/Services/Cda/CdaTemplateImportDispose.php @@ -797,8 +797,11 @@ class CdaTemplateImportDispose } $option = ''; if (!empty($value['reason_code'])) { + // TODO: check with @sjpadgett why the codes are "SNOMED CT:" instead of "SNOMED-CT" for the immunization reason code + $reason_code = str_replace("SNOMED CT", "SNOMED-CT", $value['reason_code']); + $listService = new ListService(); - $option = $listService->getOptionsByListName('immunization_refusal_reason', ['codes' => $value['reason_code']])[0]; + $option = $listService->getOptionsByListName('immunization_refusal_reason', ['codes' => $reason_code])[0]; } if (!empty($value['extension'])) { diff --git a/src/Services/Qdm/CqmCalculator.php b/src/Services/Qdm/CqmCalculator.php index 47b927533..c02a5374a 100644 --- a/src/Services/Qdm/CqmCalculator.php +++ b/src/Services/Qdm/CqmCalculator.php @@ -73,7 +73,7 @@ class CqmCalculator foreach ($patient->dataElements as $dataElement) { // We need to look up OIDs and add the first code concept from the value set. // We do this first in case it's in a dataElement that we need to clone for the calculator below - if ($dataElement->negationRationale !== null) { + if (isset($dataElement->negationRationale) && $dataElement->negationRationale !== null) { $to_add = []; foreach ($dataElement->dataElementCodes as $dataElementCode) { if (empty($dataElementCode->system)) { diff --git a/src/Services/Qdm/IndividualResult.php b/src/Services/Qdm/IndividualResult.php index 5e20bb0b2..b8e5a7506 100644 --- a/src/Services/Qdm/IndividualResult.php +++ b/src/Services/Qdm/IndividualResult.php @@ -48,6 +48,11 @@ class IndividualResult extends AbstractType $this->measure = $measure; } + public function getInnerResult() + { + return $this->_result; + } + public function observed_values() { /* diff --git a/src/Services/Qrda/ExportCat3Service.php b/src/Services/Qrda/ExportCat3Service.php index 703133b2b..47c646828 100644 --- a/src/Services/Qrda/ExportCat3Service.php +++ b/src/Services/Qrda/ExportCat3Service.php @@ -10,6 +10,8 @@ namespace OpenEMR\Services\Qrda; +use OpenEMR\Common\Logging\SystemLogger; +use OpenEMR\Cqm\Qdm\Patient; use OpenEMR\Services\Qdm\CqmCalculator; use OpenEMR\Services\Qdm\IndividualResult; use OpenEMR\Services\Qdm\Interfaces\QdmRequestInterface; @@ -28,6 +30,8 @@ class ExportCat3Service protected $effectiveDate; protected $effectiveDateEnd; + const DEBUG = false; + /** * ExportCat3Service constructor. * @@ -58,6 +62,10 @@ class ExportCat3Service $patients = $this->builder->build($this->request); $calculationResults = $this->do_calculation($patients, $measureObjs); + if (self::DEBUG) { + $this->logCalculationResults($patients, $calculationResults); + } + if ($resultOnly) { return $calculationResults; } @@ -209,4 +217,34 @@ class ExportCat3Service end */ } + + /** + * Used for logging out the IPP, DENOM, NUMER, DENEXCEP commands to the error log if debug logging is turned on + * This can be quickly seen in a grid format by running the following command from inside a docker container + * tail -f /var/log/apache2/error.log | cut -c 100- + * + * Future debugging could store these in a database file or something else for easier debugging. + * @param $patients + * @param $results + * @throws \Exception + */ + private function logCalculationResults($patients, $results) + { + $logger = new SystemLogger(); + $patientsById = []; + foreach ($patients as $patient) { + $patientsById[$patient->id->value] = $patient; + } + foreach ($results as $key => $result) { + $resultPatient = $patientsById[$result[0]->patient_id->value] ?? new Patient(); + $innerResult = $result[0]->getInnerResult(); + + $resultString = [str_pad("Patient: " . implode(" ", $resultPatient->patientName), 30)]; + $resultString[] = str_pad("IPP: " . ($innerResult['IPP'] ?? 0), 10); + $resultString[] = str_pad("DENOM: " . ($innerResult['DENOM'] ?? 0), 10); + $resultString[] = str_pad("NUMER: " . ($innerResult['NUMER'] ?? 0), 10); + $resultString[] = str_pad("DENEXCEP: " . ($innerResult['DENEXCEP'] ?? 0), 10); + $logger->debug(implode(" ", $resultString)); + } + } } -- 2.11.4.GIT