/** * @expectedException Exception * @expectedExceptionMessage Measurement references cannot reference both an episode and an event */ public function testEpisodeIdAndEventIdSet() { $ref = new MeasurementReference(); $ref->patient_measurement_id = $this->pm('height')->id; $ref->episode_id = 2; $ref->event_id = 2; $ref->save(); }
/** * @expectedException Exception * @expectedExceptionMessage Origin reference already exists */ public function testOriginAlreadyExists() { $ref = new MeasurementReference(); $ref->patient_measurement_id = $this->pm('height')->id; $ref->episode_id = 2; $ref->origin = true; $ref->save(); }
/** * Attach this measurement to an Episode or Event * * @param Episode|Event $entity * @param boolean $origin * @return MeasurementReference */ public function attach($entity, $origin = false) { $ref = new MeasurementReference(); $ref->patient_measurement_id = $this->getPatientMeasurement()->id; $ref->origin = $origin; if ($entity instanceof Episode) { $ref->episode_id = $entity->id; } elseif ($entity instanceof Event) { $ref->event_id = $entity->id; } else { throw new Exception("Can only attach measurements to Episodes or Events, was passed an object of type " . get_class($entity)); } $ref->save(); return $ref; }
private function updateMeasurementReference($measurement_id, $eye_id) { $existing = $this->dbConnection->createCommand()->select(array('fm.id fm_id', 'mr.id mr_id'))->from('ophinvisualfields_field_measurement fm')->join('patient_measurement pm', 'pm.id = fm.patient_measurement_id')->join('measurement_reference mr', 'mr.patient_measurement_id = pm.id and mr.event_id = :event_id')->join('event ev', 'ev.id = mr.event_id')->where('fm.eye_id = :eye_id and mr.event_id = :event_id', array(':eye_id' => $eye_id, ':event_id' => $this->event_id))->queryRow(); if ($existing) { if ($existing['fm_id'] != $measurement_id) { MeasurementReference::model()->deleteByPk($existing['mr_id']); } else { // Nothing to do return; } } if ($measurement_id) { OphInVisualfields_Field_Measurement::model()->findByPk($measurement_id)->attach($this->event); } }
public function run($args) { $event_type_id = EventType::model()->find('class_name = :classname', array(':classname' => 'OphInVisualfields'))->id; $patient_ids = Yii::app()->db->createCommand()->selectDistinct('patient_id')->from('measurement_reference mr')->join('patient_measurement pm', 'pm.id = mr.patient_measurement_id')->queryColumn(); foreach ($patient_ids as $patient_id) { $criteria = new CDbCriteria(); $criteria->condition = 'event_type_id = :event_type_id AND patient_id = :patient_id'; $criteria->join = 'join episode ep on ep.id = t.episode_id'; $criteria->order = 'event_date desc'; $criteria->limit = '3'; $criteria->params = array(':patient_id' => $patient_id, ':event_type_id' => $event_type_id); $events = Event::model()->findAll($criteria); foreach ($events as $event) { echo ' - ' . $event->id . "\n"; MeasurementReference::model()->deleteAll('event_id = ?', array($event->id)); $event->deleted = 1; $event->save(); } echo "{$patient_id}\n"; } }
public function actionImport($importDir, $archiveDir, $errorDir, $dupDir, $interval = 'PT45M', $pasImport = false) { $this->importDir = $this->checkSeparator($importDir); $this->archiveDir = $this->checkSeparator($archiveDir); $this->errorDir = $this->checkSeparator($errorDir); $this->dupDir = $this->checkSeparator($dupDir); $this->interval = $interval; $fhirMarshal = Yii::app()->fhirMarshal; $eventType = EventType::model()->find('class_name=:class_name', array(':class_name' => 'OphInVisualfields')); if (!$eventType) { echo 'Cannot find OphInVisualfields event type, cannot continue' . PHP_EOL; die; } echo 'Processing FMES files...' . PHP_EOL; $filenames = glob($this->importDir . '/*.fmes'); echo count($filenames) . " files to process\n"; foreach ($filenames as $file) { try { $basename = basename($file); echo $basename . PHP_EOL; // First check the file has not already been imported: $field = file_get_contents($file); $fieldObject = $fhirMarshal->parseXml($field); if ($protected_file = ProtectedFile::model()->find('name=:name', array(':name' => $fieldObject->file_reference))) { echo '- ProtectedFile exists (' . $protected_file->id . ')' . PHP_EOL; $this->move($this->dupDir, $file); continue; } // Extract the patient number $matches = array(); preg_match('/__OE_PATIENT_ID_([0-9]*)__/', $field, $matches); if (count($matches) < 2) { echo '- Failed to extract patient ID' . PHP_EOL; $this->move($this->errorDir, $file); continue; } $match = str_pad($matches[1], 7, '0', STR_PAD_LEFT); // Fetch the patient if ($pasImport) { $model = new Patient(null); $model->hos_num = $match; $results = $model->search()->getData(); $patient = reset($results); } else { $patient = Patient::model()->find('hos_num=:hos_num', array(':hos_num' => $match)); } if (!$patient) { echo "- Failed to find patient ({$match})" . PHP_EOL; $this->move($this->errorDir, $file); continue; } $pid = $patient->id; $field = preg_replace('/__OE_PATIENT_ID_([0-9]*)__/', $pid, $field); // Convert to measurement $resource_type = 'MeasurementVisualFieldHumphrey'; $service = Yii::app()->service->getService($resource_type); $fieldObject = $fhirMarshal->parseXml($field); $tx = Yii::app()->db->beginTransaction(); $ref = $service->fhirCreate($fieldObject); $tx->commit(); $refId = $ref->getId(); $measurement = OphInVisualfields_Field_Measurement::model()->findByPk($refId); $study_datetime = $measurement->study_datetime; // Check for existing legacy events if (!($episode = Episode::model()->find('legacy = 1 AND patient_id = :patient_id', array(':patient_id' => $pid)))) { echo '- No legacy episode found, creating...'; $episode = new Episode(); $episode->legacy = 1; $episode->patient_id = $pid; $episode->save(); echo 'done' . PHP_EOL; // As there are no previous legacy events, we can create a new event $this->newEvent($episode, $eventType, $measurement); $this->move($this->archiveDir, $file); } else { // There is a legacy episode, so there may be unmatched legacy field events $criteria = new CdbCriteria(); $criteria->condition = 'event_type_id = :event_type_id and t.deleted = 0 and ep.deleted = 0 and ep.legacy = 1 and ep.patient_id = :patient_id'; $criteria->join = 'join episode ep on ep.id = t.episode_id'; $criteria->order = 't.event_date desc'; $criteria->params = array(':patient_id' => $pid, ':event_type_id' => $eventType->id); if ($this->interval) { // we're looking for all events that are bound to a legacy episode, // for the given patient, looking for the last created test - // this accounts for multiple tests per eye - the implication // being that the newest test overrides the last test for the same eye // (e.g. when a mistake is made and the test is re-ran): // Base time on interval defined by user, a narrow time slot that the test falls within $startCreatedTime = new DateTime($study_datetime); $endCreatedTime = new DateTime($study_datetime); $startCreatedTime->sub(new DateInterval($this->interval)); $endCreatedTime->add(new DateInterval($this->interval)); $criteria->condition .= ' AND t.event_date >= STR_TO_DATE("' . $startCreatedTime->format('Y-m-d H:i:s') . '", "%Y-%m-%d %H:%i:%s") AND t.event_date <= STR_TO_DATE("' . $endCreatedTime->format('Y-m-d H:i:s') . '", "%Y-%m-%d %H:%i:%s")'; } // Of events, there can only be one or none: // FIXME: This can return multiple events, so how do we choose? $events = Event::model()->findAll($criteria); if (count($events) == 1) { echo '- Found existing event (' . $events[0]->id . ')' . PHP_EOL; $element = Element_OphInVisualfields_Image::model()->find('event_id = :event_id', array(':event_id' => $events[0]->id)); $side = strtolower($measurement->eye->name); if ($existing = $element->{"{$side}_field"}) { if ($measurement->study_datetime > $existing->study_datetime) { echo "Newer than existing measurement on {$side}, overwriting\n"; $element->{"{$side}_field_id"} = $measurement->id; $unattached = $existing; } else { echo "Older than existing measurement on {$side}, ignoring\n"; $unattached = $measurement; } // Add dummy reference for the unattached measurement $ref = new MeasurementReference(); $ref->patient_measurement_id = $unattached->getPatientMeasurement()->id; $ref->save(); } else { echo "No existing measurement on {$side}, adding\n"; $element->{"{$side}_field_id"} = $measurement->id; } $element->save(); $this->move($this->archiveDir, $file); } elseif (count($events) > 1) { echo '- Found more than one matching event, cannot attach' . PHP_EOL; $this->move($this->errorDir, $file); } else { // No events in match window, so we create a new one $this->newEvent($episode, $eventType, $measurement); $this->move($this->archiveDir, $file); } } } catch (Exception $ex) { echo $ex . PHP_EOL; if (@$tx && $tx->active) { echo '- rolling back tx' . PHP_EOL; $tx->rollback(); } $this->move($this->errorDir, $file); } } }