Implement ONC CareTeam, Fixed PractitionerRole, Fix critical bug in lookup_code_infor...
[openemr.git] / src / Services / ConditionService.php
blob48cc7bf7a3794e581589810348962901b239a1f4
1 <?php
3 /**
4 * ConditionService
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\Uuid\UuidRegistry;
17 use OpenEMR\Services\Search\FhirSearchWhereClauseBuilder;
18 use OpenEMR\Services\Search\ISearchField;
19 use OpenEMR\Services\Search\SearchModifier;
20 use OpenEMR\Services\Search\StringSearchField;
21 use OpenEMR\Services\Search\TokenSearchField;
22 use OpenEMR\Validators\ConditionValidator;
23 use OpenEMR\Validators\ProcessingResult;
25 class ConditionService extends BaseService
27 private const CONDITION_TABLE = "lists";
28 private const PATIENT_TABLE = "patient_data";
29 private const ENCOUNTER_TABLE = "form_encounter";
30 private $uuidRegistry;
31 private $conditionValidator;
33 /**
34 * Default constructor.
36 public function __construct()
38 parent::__construct('lists');
39 $this->uuidRegistry = new UuidRegistry(['table_name' => self::CONDITION_TABLE]);
40 $this->uuidRegistry->createMissingUuids();
41 (new UuidRegistry(['table_name' => self::PATIENT_TABLE]))->createMissingUuids();
42 (new UuidRegistry(['table_name' => self::ENCOUNTER_TABLE]))->createMissingUuids();
43 $this->conditionValidator = new ConditionValidator();
46 public function search($search, $isAndCondition = true)
48 $sql = "SELECT lists.*,
49 lists.pid AS patient_id,
50 lists.title,
51 encounter.uuid as encounter_uuid,
52 patient.puuid,
53 patient.patient_uuid,
54 condition_ids.condition_uuid,
55 verification.title as verification_title
56 FROM lists
57 INNER JOIN (
58 SELECT lists.uuid AS condition_uuid FROM lists
59 ) condition_ids ON lists.uuid = condition_ids.condition_uuid
60 LEFT JOIN list_options as verification ON verification.option_id = lists.verification and verification.list_id = 'condition-verification'
61 RIGHT JOIN (
62 SELECT
63 patient_data.uuid AS puuid
64 ,patient_data.pid
65 ,patient_data.uuid AS patient_uuid
66 FROM patient_data
67 ) patient ON patient.pid = lists.pid
68 LEFT JOIN issue_encounter as issue ON issue.list_id =lists.id
69 LEFT JOIN form_encounter as encounter ON encounter.encounter =issue.encounter";
71 $search['type'] = new StringSearchField('type', ['medical_problem'], SearchModifier::EXACT);
72 $whereClause = FhirSearchWhereClauseBuilder::build($search, $isAndCondition);
74 $sql .= $whereClause->getFragment();
75 $sqlBindArray = $whereClause->getBoundValues();
76 $statementResults = QueryUtils::sqlStatementThrowException($sql, $sqlBindArray);
79 $processingResult = new ProcessingResult();
80 while ($row = sqlFetchArray($statementResults)) {
81 $resultRecord = $this->createResultRecordFromDatabaseResult($row);
82 $processingResult->addData($resultRecord);
84 return $processingResult;
87 public function getUuidFields(): array
89 return ['condition_uuid', 'puuid', 'encounter_uuid', 'uuid', 'patient_uuid'];
92 public function createResultRecordFromDatabaseResult($row)
94 $row = parent::createResultRecordFromDatabaseResult($row);
95 if ($row['diagnosis'] != "") {
96 $row['diagnosis'] = $this->addCoding($row['diagnosis']);
98 return $row;
102 * Returns a list of condition matching optional search criteria.
103 * Search criteria is conveyed by array where key = field/column name, value = field value.
104 * If no search criteria is provided, all records are returned.
106 * @param $search search array parameters
107 * @param $isAndCondition specifies if AND condition is used for multiple criteria. Defaults to true.
108 * @param $puuidBind - Optional variable to only allow visibility of the patient with this puuid.
109 * @return ProcessingResult which contains validation messages, internal error messages, and the data
110 * payload.
112 public function getAll($search = array(), $isAndCondition = true, $puuidBind = null)
114 $newSearch = [];
115 foreach ($search as $key => $value) {
116 if (!$value instanceof ISearchField) {
117 $newSearch[] = new StringSearchField($key, [$value], SearchModifier::EXACT);
118 } else {
119 $newSearch[$key] = $value;
123 // override puuid, this replaces anything in search if it is already specified.
124 if (isset($puuidBind)) {
125 $search['puuid'] = new TokenSearchField('puuid', $puuidBind, true);
128 return $this->search($search, $isAndCondition);
132 * Returns a single condition record by uuid.
133 * @param $uuid - The condition uuid identifier in string format.
134 * @param $puuidBind - Optional variable to only allow visibility of the patient with this puuid.
135 * @return ProcessingResult which contains validation messages, internal error messages, and the data
136 * payload.
138 public function getOne($uuid, $puuidBind = null)
140 $search['condition_uuid'] = new TokenSearchField('condition_uuid', $uuid, true);
141 if (isset($puuidBind)) {
142 $search['puuid'] = new TokenSearchField('puuid', $puuidBind, true);
144 return $this->search($search);
149 * Inserts a new condition record.
151 * @param $data The condition fields (array) to insert.
152 * @return ProcessingResult which contains validation messages, internal error messages, and the data
153 * payload.
155 public function insert($data)
157 $processingResult = $this->conditionValidator->validate(
158 $data,
159 ConditionValidator::DATABASE_INSERT_CONTEXT
162 if (!$processingResult->isValid()) {
163 return $processingResult;
166 $puuidBytes = UuidRegistry::uuidToBytes($data['puuid']);
167 $data['pid'] = $this->getIdByUuid($puuidBytes, self::PATIENT_TABLE, "pid");
168 $data['uuid'] = (new UuidRegistry(['table_name' => self::CONDITION_TABLE]))->createUuid();
170 $query = $this->buildInsertColumns($data);
171 $sql = " INSERT INTO lists SET";
172 $sql .= " date=NOW(),";
173 $sql .= " activity=1,";
174 $sql .= " type='medical_problem',";
175 $sql .= $query['set'];
176 $results = sqlInsert(
177 $sql,
178 $query['bind']
181 if ($results) {
182 $processingResult->addData(array(
183 'id' => $results,
184 'uuid' => UuidRegistry::uuidToString($data['uuid'])
186 } else {
187 $processingResult->addInternalError("error processing SQL Insert");
190 return $processingResult;
194 * Updates an existing condition record.
196 * @param $uuid - The condition uuid identifier in string format used for update.
197 * @param $data - The updated condition data fields
198 * @return ProcessingResult which contains validation messages, internal error messages, and the data
199 * payload.
201 public function update($uuid, $data)
203 if (empty($data)) {
204 $processingResult = new ProcessingResult();
205 $processingResult->setValidationMessages("Invalid Data");
206 return $processingResult;
209 $data["uuid"] = $uuid;
210 $processingResult = $this->conditionValidator->validate(
211 $data,
212 ConditionValidator::DATABASE_UPDATE_CONTEXT
214 if (!$processingResult->isValid()) {
215 return $processingResult;
218 $query = $this->buildUpdateColumns($data);
219 $sql = " UPDATE lists SET ";
220 $sql .= $query['set'];
221 $sql .= " WHERE `uuid` = ?";
222 $sql .= " AND `type` = 'medical_problem'";
224 $uuidBinary = UuidRegistry::uuidToBytes($uuid);
225 array_push($query['bind'], $uuidBinary);
226 $sqlResult = sqlStatement($sql, $query['bind']);
228 if (!$sqlResult) {
229 $processingResult->addErrorMessage("error processing SQL Update");
230 } else {
231 $processingResult = $this->getOne($uuid);
233 return $processingResult;
237 * Deletes an existing condition record.
239 * @param $puuid - The patient uuid identifier in string format used for update.
240 * @param $uuid - The condition uuid identifier in string format used for update.
241 * @return ProcessingResult which contains validation messages, internal error messages, and the data
242 * payload.
244 public function delete($puuid, $uuid)
246 $processingResult = new ProcessingResult();
248 $isValid = $this->conditionValidator->validateId("uuid", "lists", $uuid, true);
249 $isPatientValid = $this->conditionValidator->validateId("uuid", "patient_data", $puuid, true);
251 if ($isValid !== true || $isPatientValid !== true) {
252 $validationMessages = [
253 'UUID' => ["invalid or nonexisting value"]
255 $processingResult->setValidationMessages($validationMessages);
256 return $processingResult;
259 $puuidBytes = UuidRegistry::uuidToBytes($puuid);
260 $auuid = UuidRegistry::uuidToBytes($uuid);
261 $pid = $this->getIdByUuid($puuidBytes, self::PATIENT_TABLE, "pid");
262 $sql = "DELETE FROM lists WHERE pid=? AND uuid=? AND type='medical_problem'";
264 $results = sqlStatement($sql, array($pid, $auuid));
266 if ($results) {
267 $processingResult->addData(array(
268 'uuid' => $uuid
270 } else {
271 $processingResult->addInternalError("error processing SQL Insert");
274 return $processingResult;