Fixes #7219 email validate allow empty strings. (#7220)
[openemr.git] / src / Services / DrugService.php
blobee72ba86132085296fa9baaa8e0d9f347b4668ca
1 <?php
3 /**
4 * DrugService
6 * @package OpenEMR
7 * @link http://www.open-emr.org
8 * @author Yash Bothra <yashrajbothra786gmail.com>
9 * @copyright Copyright (c) 2020 Yash Bothra <yashrajbothra786gmail.com>
10 * @license https://github.com/openemr/openemr/blob/master/LICENSE GNU General Public License 3
13 namespace OpenEMR\Services;
15 use OpenEMR\Common\Database\QueryUtils;
16 use OpenEMR\Common\Database\SqlQueryException;
17 use OpenEMR\Common\Logging\SystemLogger;
18 use OpenEMR\Common\Uuid\UuidRegistry;
19 use OpenEMR\Services\Search\FhirSearchWhereClauseBuilder;
20 use OpenEMR\Services\Search\ISearchField;
21 use OpenEMR\Services\Search\ReferenceSearchField;
22 use OpenEMR\Services\Search\ReferenceSearchValue;
23 use OpenEMR\Services\Search\SearchFieldException;
24 use OpenEMR\Services\Search\SearchModifier;
25 use OpenEMR\Services\Search\StringSearchField;
26 use OpenEMR\Services\Search\TokenSearchField;
27 use OpenEMR\Services\Search\TokenSearchValue;
28 use OpenEMR\Validators\ProcessingResult;
30 class DrugService extends BaseService
32 private const DRUG_TABLE = "drugs";
34 /**
35 * Default constructor.
37 public function __construct()
39 parent::__construct(self::DRUG_TABLE);
40 UuidRegistry::createMissingUuidsForTables([self::DRUG_TABLE]);
43 public function getUuidFields(): array
45 return ['uuid'];
48 /**
49 * Returns a list of drugs matching optional search criteria.
50 * Search criteria is conveyed by array where key = field/column name, value = field value.
51 * If no search criteria is provided, all records are returned.
53 * @param $search search array parameters
54 * @param $isAndCondition specifies if AND condition is used for multiple criteria. Defaults to true.
55 * @param $puuidBind - Patient uuid to return drug resources that are only visible to the current patient
56 * @return ProcessingResult which contains validation messages, internal error messages, and the data
57 * payload.
59 public function getAll($search = array(), $isAndCondition = true, $puuidBind = null)
61 $newSearch = [];
62 foreach ($search as $key => $value) {
63 if (!$value instanceof ISearchField) {
64 $newSearch[] = new StringSearchField($key, [$value], SearchModifier::EXACT);
65 } else {
66 $newSearch[$key] = $value;
69 // so if we have a puuid we need to make sure we only return drugs that are connected to the current patient.
70 if (isset($puuidBind)) {
71 $newSearch['puuid'] = new TokenSearchField('puuid', $puuidBind, true);
74 return $this->search($newSearch, $isAndCondition);
77 /**
78 * Returns a single drug record by id.
79 * @param $uuid - The drug uuid identifier in string format.
80 * @return ProcessingResult which contains validation messages, internal error messages, and the data
81 * payload.
83 public function getOne($uuid)
85 $search = [
86 'uuid' => new TokenSearchField('uuid', [new TokenSearchValue($uuid, null, false)])
88 // so if we have a puuid we need to make sure we only return drugs that are connected to the current patient.
89 if (isset($puuid)) {
90 $search['puuid'] = new ReferenceSearchField('puuid', [new ReferenceSearchValue($puuid, 'Patient', true)]);
92 return $this->search($search);
95 public function search($search, $isAndCondition = true)
97 $sql = "SELECT drugs.drug_id,
98 uuid,
99 name,
100 ndc_number,
101 form,
102 size,
103 unit,
104 route,
105 related_code,
106 active,
107 drug_code,
108 IF(drug_prescriptions.rxnorm_drugcode!=''
109 ,drug_prescriptions.rxnorm_drugcode
110 ,IF(drug_code IS NULL, '', concat('RXCUI:',drug_code))
111 ) AS 'rxnorm_drugcode',
112 drug_inventory.manufacturer,
113 drug_inventory.lot_number,
114 drug_inventory.expiration
115 FROM drugs
116 LEFT JOIN drug_inventory
117 ON drugs.drug_id = drug_inventory.drug_id
118 LEFT JOIN (
119 select
120 uuid AS prescription_uuid
121 ,rxnorm_drugcode
122 ,drug_id
123 ,patient_id as prescription_patient_id
124 FROM
125 prescriptions
126 ) drug_prescriptions
127 ON drug_prescriptions.drug_id = drugs.drug_id
128 LEFT JOIN (
129 select uuid AS puuid
130 ,pid
131 FROM patient_data
132 ) patient
133 ON patient.pid = drug_prescriptions.prescription_patient_id";
135 $processingResult = new ProcessingResult();
136 try {
137 $whereClause = FhirSearchWhereClauseBuilder::build($search, $isAndCondition);
139 $sql .= $whereClause->getFragment();
140 $sqlBindArray = $whereClause->getBoundValues();
141 $statementResults = QueryUtils::sqlStatementThrowException($sql, $sqlBindArray);
143 while ($row = sqlFetchArray($statementResults)) {
144 $resultRecord = $this->createResultRecordFromDatabaseResult($row);
145 $processingResult->addData($resultRecord);
147 } catch (SqlQueryException $exception) {
148 // we shouldn't hit a query exception
149 (new SystemLogger())->error($exception->getMessage(), ['trace' => $exception->getTraceAsString()]);
150 $processingResult->addInternalError("Error selecting data from database");
151 } catch (SearchFieldException $exception) {
152 (new SystemLogger())->error($exception->getMessage(), ['trace' => $exception->getTraceAsString(), 'field' => $exception->getField()]);
153 $processingResult->setValidationMessages([$exception->getField() => $exception->getMessage()]);
156 return $processingResult;
159 protected function createResultRecordFromDatabaseResult($row)
161 $record = parent::createResultRecordFromDatabaseResult($row);
163 if ($record['rxnorm_drugcode'] != "") {
164 $codes = $this->addCoding($row['rxnorm_drugcode']);
165 $updatedCodes = [];
166 foreach ($codes as $code => $codeValues) {
167 if (empty($codeValues['description'])) {
168 // use the drug name if for some reason we have no rxnorm description from the lookup
169 $codeValues['description'] = $row['drug'];
171 $updatedCodes[$code] = $codeValues;
173 $record['drug_code'] = $updatedCodes;
176 if ($row['rxnorm_drugcode'] != "") {
177 $row['drug_code'] = $this->addCoding($row['drug_code']);
179 return $record;