From d5336c7e2e081c35748229675ed001fceb3ba22c Mon Sep 17 00:00:00 2001 From: matijs de Jong Date: Thu, 17 May 2018 14:23:26 +0200 Subject: [PATCH] Fixed #306 Episode of care is added as a top level object (doesn't start tracks though) --- classes/Gems/Agenda.php | 43 ++++++- classes/Gems/Default/CareEpisodeAction.php | 40 ++++++- classes/Gems/Model/AppointmentModel.php | 37 +++++- .../AppointmentCareEpisodeDependency.php | 113 ++++++++++++++++++ .../Dependency/StaffUserClassDependency.php | 1 + classes/Gems/Model/EpisodeOfCareModel.php | 12 +- .../Agenda/AppointmentFormSnippet.php | 14 --- .../Agenda/AppointmentsTableSnippet.php | 15 ++- .../Snippets/ModelTableSnippetAbstract.php | 1 - 9 files changed, 247 insertions(+), 29 deletions(-) create mode 100644 classes/Gems/Model/Dependency/AppointmentCareEpisodeDependency.php diff --git a/classes/Gems/Agenda.php b/classes/Gems/Agenda.php index 9cdbe30fc..f750d2584 100644 --- a/classes/Gems/Agenda.php +++ b/classes/Gems/Agenda.php @@ -12,6 +12,7 @@ use Gems\Agenda\AppointmentFilterInterface; use Gems\Agenda\AppointmentSelect; +use Gems\Agenda\EpisodeOfCare; /** * @@ -636,15 +637,35 @@ public function getEpisodeStatusCodesInactive() return $codes; } + /** + * Get the options list episodes for episodes + * + * @param array $episodes + * @return array of $epsiodeId => Description + */ + public function getEpisodesAsOptions(array $episodes) + { + $options = []; + + foreach ($episodes as $id => $episode) { + if ($episode instanceof EpisodeOfCare) { + $options[$id] = $episode->getDisplayString(); + } + } + + return $options; + } + /** * Get the episodes for a respondent * * @param \Gems_Tracker_Respondent $respondent + * @param $where mixed Optional extra string or array filter * @return array of $epsiodeId => \Gems\Agenda\EpisodeOfCare */ - public function getEpisodesFor(\Gems_Tracker_Respondent $respondent) + public function getEpisodesFor(\Gems_Tracker_Respondent $respondent, $where = null) { - return $this->getEpisodesForRespId($respondent->getId(), $respondent->getOrganizationId()); + return $this->getEpisodesForRespId($respondent->getId(), $respondent->getOrganizationId(), $where); } /** @@ -652,9 +673,10 @@ public function getEpisodesFor(\Gems_Tracker_Respondent $respondent) * * @param int $respondentId * @param int $orgId + * @param $where mixed Optional extra string or array filter * @return array of $epsiodeId => \Gems\Agenda\EpisodeOfCare */ - public function getEpisodesForRespId($respondentId, $orgId) + public function getEpisodesForRespId($respondentId, $orgId, $where = null) { $select = $this->db->select(); $select->from('gems__episodes_of_care') @@ -662,6 +684,21 @@ public function getEpisodesForRespId($respondentId, $orgId) ->where('gec_id_organization = ?', $orgId) ->order('gec_startdate DESC'); + if ($where) { + if (is_array($where)) { + foreach ($where as $expr => $param) { + if (is_int($expr)) { + $select->where($param); + } else { + $select->where($expr, $param); + } + } + } else { + $select->where($where); + } + } + // \MUtil_Echo::track($select->__toString()); + $episodes = $this->db->fetchAll($select); $output = []; diff --git a/classes/Gems/Default/CareEpisodeAction.php b/classes/Gems/Default/CareEpisodeAction.php index a025226b2..4b7966425 100644 --- a/classes/Gems/Default/CareEpisodeAction.php +++ b/classes/Gems/Default/CareEpisodeAction.php @@ -54,6 +54,28 @@ class Gems_Default_CareEpisodeAction extends \Gems_Default_RespondentChildAction 'contentTitle' => 'getContentTitle', ); + /** + * The parameters used for the show action + * + * When the value is a function name of that object, then that functions is executed + * with the array key as single parameter and the return value is set as the used value + * - unless the key is an integer in which case the code is executed but the return value + * is not stored. + * + * @var array Mixed key => value array for snippet initialization + */ + protected $showParameters = [ + 'bridgeMode' => \MUtil_Model_Bridge_BridgeAbstract::MODE_ROWS, // Prevent lazyness + 'respondent' => 'getRespondent', + ]; + + /** + * The snippets used for the show action + * + * @var mixed String or array of snippets name + */ + protected $showSnippets = ['Generic\\ContentTitleSnippet', 'ModelItemTableSnippetGeneric', 'Agenda_AppointmentsTableSnippet']; + /** * Creates a model for getModel(). Called only for each new $action. * @@ -103,9 +125,9 @@ public function getContentTitle() $patientId = $respondent->getPatientNumber(); if ($patientId) { if ($this->currentUser->areAllFieldsMaskedWhole('grs_first_name', 'grs_surname_prefix', 'grs_last_name')) { - return sprintf($this->_('Episoded of care for respondent number %s'), $patientId); + return sprintf($this->_('Episodes of care for respondent number %s'), $patientId); } - return sprintf($this->_('Episoded of care for respondent number %s: %s'), $patientId, $respondent->getName()); + return sprintf($this->_('Episodes of care for respondent number %s: %s'), $patientId, $respondent->getName()); } return $this->getIndexTitle(); } @@ -154,6 +176,18 @@ protected function getRespondent() */ public function getTopic($count = 1) { - return $this->plural('episode of care', 'episodes of care', $count); + $respondent = $this->getRespondent(); + $patientId = $respondent->getPatientNumber(); + if ($patientId) { + if ($this->currentUser->areAllFieldsMaskedWhole('grs_first_name', 'grs_surname_prefix', 'grs_last_name')) { + $for = sprintf($this->_('for respondent number %s'), $patientId); + } else { + $for = sprintf($this->_('for respondent number %s'), $patientId); + } + $for = ' ' . $for; + } else { + $for = ''; + } + return $this->plural('episode of care', 'episodes of care', $count) . $for; } } diff --git a/classes/Gems/Model/AppointmentModel.php b/classes/Gems/Model/AppointmentModel.php index 4c8001eb8..e4d0f5fb5 100644 --- a/classes/Gems/Model/AppointmentModel.php +++ b/classes/Gems/Model/AppointmentModel.php @@ -7,7 +7,6 @@ * @author Matijs de Jong * @copyright Copyright (c) 2013 Erasmus MC * @license New BSD License - * @version $Id$ */ /** @@ -52,6 +51,12 @@ class Gems_Model_AppointmentModel extends \Gems_Model_JoinModel */ protected $loader; + /** + * + * @var \Gems_Menu + */ + protected $menu; + /** * @var \Gems_Util */ @@ -289,6 +294,10 @@ public function applyEditSettings($orgId) $this->setIfExists('gap_id_procedure', 'multiOptions', $empty + $agenda->getProcedures($orgId)); $this->setIfExists('gap_id_location', 'multiOptions', $empty + $agenda->getLocations($orgId)); + if ($this->currentUser->hasPrivilege('pr.episodes')) { + $this->setIfExists('gap_id_episode', 'multiOptions', $empty); + $this->addDependency('AppointmentCareEpisodeDependency'); + } return $this; } @@ -377,13 +386,29 @@ public function setAutoTrackUpdate($value = true) */ public function showEpisode($episodeId) { - if ($episodeId) { - $episode = $this->loader->getAgenda()->getEpisodeOfCare($episodeId); + if (! $episodeId) { + return null; + } + $episode = $this->loader->getAgenda()->getEpisodeOfCare($episodeId); - if ($episode->exists) { - return $episode->getDisplayString(); - } + if (! $episode->exists) { + return $episodeId; + } + + $episodeItem = $this->menu->findAllowedController('care-episode', 'show'); + if ($episodeItem) { + $href = $episodeItem->toHRefAttribute(['gec_episode_of_care_id' => $episodeId]); + } else { + $href = false; } + + if (! $href) { + return $episode->getDisplayString(); + } + + $onclick = new \MUtil_Html_OnClickArrayAttribute(); + $onclick->addCancelBubble(true); + return \MUtil_Html::create('a', $href, $episode->getDisplayString(), $onclick); } /** diff --git a/classes/Gems/Model/Dependency/AppointmentCareEpisodeDependency.php b/classes/Gems/Model/Dependency/AppointmentCareEpisodeDependency.php new file mode 100644 index 000000000..030bf9d0c --- /dev/null +++ b/classes/Gems/Model/Dependency/AppointmentCareEpisodeDependency.php @@ -0,0 +1,113 @@ + + * @copyright Copyright (c) 2018, Erasmus MC and MagnaFacta B.V. + * @license New BSD License + */ + +namespace Gems\Model\Dependency; + +use MUtil\Model\Dependency\DependencyAbstract; + +/** + * + * @package Gems + * @subpackage Model\Dependency + * @copyright Copyright (c) 2018, Erasmus MC and MagnaFacta B.V. + * @license New BSD License + * @since Class available since version 1.8.3 May 17, 2018 12:02:38 PM + */ +class AppointmentCareEpisodeDependency extends DependencyAbstract +{ + /** + * Array of setting => setting of setting changed by this dependency + * + * The settings array for those effecteds that don't have an effects array + * + * @var array + */ + protected $_defaultEffects = array('multiOptions'); + + /** + * Array of name => name of items dependency depends on. + * + * Can be overriden in sub class, when set to only field names this class will + * change the array to the correct structure. + * + * @var array Of name => name + */ + protected $_dependentOn = array('gap_id_user', 'gap_id_organization', 'gap_admission_time'); + + /** + * Array of name => array(setting => setting) of fields with settings changed by this dependency + * + * Can be overriden in sub class, when set to only field names this class will use _defaultEffects + * to change the array to the correct structure. + * + * @var array of name => array(setting => setting) + */ + protected $_effecteds = array('gap_id_episode'); + + /** + * + * @var \Gems_Loader + */ + protected $loader; + + /** + * + * @var \Gems_Loader + */ + protected $util; + + /** + * Returns the changes that must be made in an array consisting of + * + * + * array( + * field1 => array(setting1 => $value1, setting2 => $value2, ...), + * field2 => array(setting3 => $value3, setting4 => $value4, ...), + * + * + * By using [] array notation in the setting name you can append to existing + * values. + * + * Use the setting 'value' to change a value in the original data. + * + * When a 'model' setting is set, the workings cascade. + * + * @param array $context The current data this object is dependent on + * @param boolean $new True when the item is a new record not yet saved + * @return array name => array(setting => value) + */ + public function getChanges(array $context, $new) + { + $agenda = $this->loader->getAgenda(); + $options = $this->util->getTranslated()->getEmptyDropdownArray(); + + if (isset($context['gap_id_user'], $context['gap_id_organization'])) { + if (isset($context['gap_admission_time'])) { + if ($context['gap_admission_time'] instanceof \MUtil_Date) { + $admission = $context['gap_admission_time']->toString(\Gems_Tracker::DB_DATE_FORMAT); + } elseif ($context['gap_admission_time'] instanceof \DateTimeInterface) { + $admission = $context['gap_admission_time']->format('Y-m-d'); + } else { + $admission = $context['gap_admission_time']; + } + $where['gec_startdate <= ?'] = $admission; + $where['gec_enddate IS NULL OR gec_enddate > ?'] = $admission; + } else { + $where = null; + } + + $options = $options + $agenda->getEpisodesAsOptions( + $agenda->getEpisodesForRespId($context['gap_id_user'], $context['gap_id_organization'], $where) + ); + } + return ['gap_id_episode' => ['multiOptions' => $options]]; + } +} diff --git a/classes/Gems/Model/Dependency/StaffUserClassDependency.php b/classes/Gems/Model/Dependency/StaffUserClassDependency.php index 01137e4be..511cd2b68 100644 --- a/classes/Gems/Model/Dependency/StaffUserClassDependency.php +++ b/classes/Gems/Model/Dependency/StaffUserClassDependency.php @@ -12,6 +12,7 @@ namespace Gems\Model\Dependency; use MUtil\Model\Dependency\DependencyAbstract; + /** * * @package Gems diff --git a/classes/Gems/Model/EpisodeOfCareModel.php b/classes/Gems/Model/EpisodeOfCareModel.php index d799ebd0b..bf251bcfd 100644 --- a/classes/Gems/Model/EpisodeOfCareModel.php +++ b/classes/Gems/Model/EpisodeOfCareModel.php @@ -53,7 +53,13 @@ public function __construct() false ); - $this->addColumn(new \Zend_Db_Expr("'episodes_of_care'"), \Gems_Model::ID_TYPE); + $this->addColumn(new \Zend_Db_Expr("'careepisodes'"), \Gems_Model::ID_TYPE); + $this->addColumn( + new \Zend_Db_Expr( + "(SELECT COUNT(*) FROM gems__appointments WHERE gap_id_episode = gec_episode_of_care_id)" + ), + 'appointment_count'); + $this->setKeys(array(\Gems_Model::EPISODE_ID => 'gec_episode_of_care_id')); } @@ -143,6 +149,8 @@ public function applyBrowseSettings() $this->setIfExists('gec_subject', 'label', $this->_('Subject')); $this->setIfExists('gec_diagnosis', 'label', $this->_('Diagnosis')); + $this->set('appointment_count', 'label', $this->_('Appointments')); + $this->refreshGroupSettings(); return $this; @@ -181,6 +189,7 @@ public function applyDetailSettings() $this->setIfExists('gec_subject', 'label', $this->_('Subject')); $this->setIfExists('gec_comment', 'label', $this->_('Comment')); $this->setIfExists('gec_diagnosis', 'label', $this->_('Diagnosis')); + $this->set('appointment_count', 'label', $this->_('Appointments')); $this->refreshGroupSettings(); @@ -217,6 +226,7 @@ public function applyEditSettings($orgId, $respId) $this->setIfExists('gec_comment', 'elementClass', 'Textarea', 'rows', 5); $this->setIfExists('gec_diagnosis', 'required', true); + $this->set('appointment_count', 'elementClass', 'Exhibitor'); return $this; } diff --git a/classes/Gems/Snippets/Agenda/AppointmentFormSnippet.php b/classes/Gems/Snippets/Agenda/AppointmentFormSnippet.php index a5daecb45..b50f83333 100644 --- a/classes/Gems/Snippets/Agenda/AppointmentFormSnippet.php +++ b/classes/Gems/Snippets/Agenda/AppointmentFormSnippet.php @@ -9,8 +9,6 @@ * @license New BSD License */ -use \Gems\Agenda\EpisodeOfCare; - /** * * @package Gems @@ -84,18 +82,6 @@ protected function createModel() $this->model->set('gap_admission_time', 'formatFunction', array($this, 'displayDate')); $this->model->set('gap_discharge_time', 'formatFunction', array($this, 'displayDate')); - if ($this->currentUser->hasPrivilege('pr.episodes')) { - $options = $this->util->getTranslated()->getEmptyDropdownArray(); - - foreach ($this->loader->getAgenda()->getEpisodesFor($this->respondent) as $id => $episode) { - if ($episode instanceof EpisodeOfCare) { - $options[$id] = $episode->getDisplayString(); - } - } - - $this->model->set('gap_id_episode', 'multiOptions', $options); - } - return $this->model; } } diff --git a/classes/Gems/Snippets/Agenda/AppointmentsTableSnippet.php b/classes/Gems/Snippets/Agenda/AppointmentsTableSnippet.php index e851cc65b..a87144186 100644 --- a/classes/Gems/Snippets/Agenda/AppointmentsTableSnippet.php +++ b/classes/Gems/Snippets/Agenda/AppointmentsTableSnippet.php @@ -7,7 +7,6 @@ * @author Matijs de Jong * @copyright Copyright (c) 2012 Erasmus MC * @license New BSD License - * @version $Id$ */ /** @@ -231,4 +230,18 @@ public function formatTime($value) \MUtil_Date::format($value, 'HH:mm ' . \Zend_Date::WEEKDAY_SHORT, $this->_dateStorageFormat) ); } + /** + * Overrule to implement snippet specific filtering and sorting. + * + * @param \MUtil_Model_ModelAbstract $model + */ + protected function processFilterAndSort(\MUtil_Model_ModelAbstract $model) + { + parent::processFilterAndSort($model); + + $eid = $this->request->getParam(\Gems_Model::EPISODE_ID); + if ($eid) { + $model->addFilter(['gap_id_episode' => $eid]); + } + } } diff --git a/classes/Gems/Snippets/ModelTableSnippetAbstract.php b/classes/Gems/Snippets/ModelTableSnippetAbstract.php index 1d04f583f..34ce3ebf1 100644 --- a/classes/Gems/Snippets/ModelTableSnippetAbstract.php +++ b/classes/Gems/Snippets/ModelTableSnippetAbstract.php @@ -7,7 +7,6 @@ * @author Matijs de Jong * @copyright Copyright (c) 2011 Erasmus MC * @license New BSD License - * @version $Id$ */ /**