diff --git a/application/modules/courses/models/ApprovalActionForkGradModel.php b/application/modules/courses/models/ApprovalActionForkGradModel.php new file mode 100644 index 0000000000000000000000000000000000000000..16db9a73f2664dec7cf1af82d818f92ab7b7a6da --- /dev/null +++ b/application/modules/courses/models/ApprovalActionForkGradModel.php @@ -0,0 +1,255 @@ +<?php + +class Courses_ApprovalActionForkGradModel extends Requests_ApprovalActionModel +{ + static public function find($id) + { + $db = Zend_Registry::get('db'); + + $select = new Zend_Db_Select($db); + $select->from(array('a' => 'creqApprovalActions')); + $select->join(array('d' => 'creqApprovalActionsForkGrad'), 'a.approvalActionId = d.approvalActionId'); + if (Unl_Util::isArray($id)) { + $select->where('a.approvalActionId IN(?)', $id); + } else { + $select->where('a.approvalActionId = ?', $id); + } + + $records = $db->query($select)->fetchAll(); + $objects = new Unl_Model_Collection(__CLASS__); + foreach ($records as $record) { + $object = Unl_Model_Registry::getInstance()->getOrAdd(new self($record)); + $objectId = $object->getId(); + $objects[$objectId] = $object; + } + + if (Unl_Util::isArray($objects)) { + return $objects; + } else { + return array_pop($objects); + } + } + + static public function fetchNew() + { + $data = array( + 'approvalActionId' => NULL, + 'name' => '', + 'approvalChain' => NULL, + 'className' => '', + 'participatingRoles' => array(), + 'editingRoles' => array() + ); + + $new = new self($data); + $new->_setClean(); + + $new->_data['className'] = 'ApprovalActionForkGrad'; + + return $new; + } + + static public function save($models) + { + $modelsToInsert = new Unl_Model_Collection(__CLASS__); + $modelsToUpdate = new Unl_Model_Collection(__CLASS__); + + if (!Unl_Util::isArray($models)) { + $model = $models; + $models = new Unl_Model_Collection(__CLASS__); + $models[$model->getId()] = $model; + } + + foreach ($models as $model) { + if ($model->_cleanData['approvalActionId'] && $model->getId()) { + if ($model->_cleanData != $model->_data) { + $modelsToUpdate[] = $model; + } + } else { + $modelsToInsert[] = $model; + } + } + + if (count($modelsToInsert) > 0) { + self::_insert($modelsToInsert); + } + + if (count($modelsToUpdate) > 0) { + self::_update($modelsToUpdate); + } + } + + static protected function _update(Unl_Model_Collection $models) + { + // Nothing to update + } + + static protected function _insert(Unl_Model_Collection $models) + { + $db = Zend_Registry::get('db'); + + $sql = 'INSERT INTO creqApprovalActionsForkGrad (approvalActionId) VALUES '; + $sqlParts = array(); + foreach ($models as $model) { + $sqlParts[] = $db->quoteInto('(?) ', $model->_data['approvalActionId']); + } + $sql .= implode(', ', $sqlParts); + $db->query($sql); + } + + public function getResultStatusStrings() + { + return array('Grad' => 'Grad'); + } + + public function consider($requests) + { + $courses = Courses_CourseModel::findLatestOfRequest($requests); + $parentCourses = Courses_CourseModel::findParentOfRequest($requests); + + $newCourseRequests = array(); + $newCourses = new Unl_Model_Collection('Courses_CourseModel'); + $newRequests = new Unl_Model_Collection('Requests_RequestModel'); + + $childParentRequestMap = array(); + + foreach ($requests as $request) { + $course = $courses[$request->getId()]; + $parentCourse = $parentCourses[$request->getId()]; + + // If this isn't a Separate Grad request, we don't want to touch it. + if ($request->getType() != 'SeparateGrad') { + continue; + } + + // If the course isn't both grad and undergrad, there's nothing to fork! + if (!$course->isGraduateLevel() || !$course->isUndergraduateLevel()) { + continue; + } + + // create a new generation of the course that will have the grad crosslistings removed + $newGeneration = clone $course; + // create a new generation of the course from the input request to base the new request on. + $gradCourse = clone $course; + + // Grab the home suffix now in case we need to use it later (ie: xx in 4xx/8xx) + $homeSuffix = substr($course->getCourseNumber(), -2); + + // Remove either the grad or the undergrad crosslistings for each course. + foreach ($newGeneration->getCrosslistings() as $crosslistingId => $crosslisting) { + if ($crosslisting['courseNumber'] >= 500) { + $newGeneration->removeCrosslisting($crosslistingId); + } + } + + // Remove all under grad listings, and promote the grad tie-in to the home listing. + $foundGradTieIn = FALSE; + foreach ($gradCourse->getCrosslistings() as $crosslistingId => $crosslisting) { + if ($crosslisting['courseNumber'] < 500) { + $gradCourse->removeCrosslisting($crosslistingId); + } + if ($crosslisting['type'] == 'grad tie-in') { + $gradCourse->editCrosslisting( + $crosslistingId, + 'home listing', + $crosslisting['subject'], + $crosslisting['courseNumber'], + $crosslisting['courseLetter'] + ); + $foundGradTieIn = TRUE; + } + } + + // If no grad tie-in was found, see if a matching suffix can be found instead. + if (!$foundGradTieIn) { + foreach ($gradCourse->getCrosslistings() as $crosslisting) { + if (substr($crosslisting['courseNumber'], -2) != $homeSuffix) { + continue; + } + $gradCourse->editCrosslisting( + $crosslistingId, + 'home listing', + $crosslisting['subject'], + $crosslisting['courseNumber'], + $crosslisting['courseLetter'] + ); + $foundGradTieIn = TRUE; + break; + } + } + + // If we still haven't found the primary grad tie-in, just use the first one. + if (!$foundGradTieIn) { + foreach ($gradCourse->getCrosslistings() as $crosslisting) { + $gradCourse->editCrosslisting( + $crosslistingId, + 'home listing', + $crosslisting['subject'], + $crosslisting['courseNumber'], + $crosslisting['courseLetter'] + ); + $foundGradTieIn = TRUE; + break; + } + } + + // set the existing request to change course. + $request->setType('ChangeCourse'); + + // create the new request to contain only the grad data. + $newRequest = clone $request; + $childParentRequestMap[] = array('child' => $newRequest, 'parent' => $request); + $newRequest->setType('NewCourse'); + $newRequest->setState('Grad'); + + $newRequests[] = $newRequest; + $newCourses[] = $newGeneration; + $newCourses[] = $gradCourse; + $newCourseRequests[] = array( + 'request' => $newRequest, + 'course' => $gradCourse + ); + } + Courses_CourseModel::save($courses); + Requests_RequestModel::save($requests); + Requests_RequestModel::save($newRequests); + + foreach ($newCourseRequests as $newCourseRequest) { + $request = $newCourseRequest['request']; + $course = $newCourseRequest['course']; + + $course->setRequest($request); + } + + Courses_CourseModel::save($newCourses); + + // Copy the watchers from the parent requests to the child requests + $db = Zend_Registry::get('db'); + foreach ($childParentRequestMap as $childParentRequests) { + $parent = $childParentRequests['parent']; + $child = $childParentRequests['child']; + $sql = 'INSERT INTO creqRequestWatchers (request, watchingApprovalRole) ' + . $db->quoteInto('SELECT ?, watchingApprovalRole ', $child->getId()) + . 'FROM creqRequestWatchers AS w ' + . $db->quoteInto('WHERE w.request=? ', $parent->getId()); + ; + $db->query($sql); + } + + // all done... advance all requests and return them for consideration + $allRequests = $requests->merge($newRequests); + Requests_ApprovalChainModel::advance($requests); + return $requests; + } + + public function setExtendedData($in) + { + // No extended data + } + + public function userMadeDecisions($requests, $requestDecisions) + { + // Don't do anything here, this is an automated action. + } + +} diff --git a/application/modules/courses/models/CourseModel.php b/application/modules/courses/models/CourseModel.php index 9d7a83112b95715fa41826ee26ce9700687be9c6..8cd6e957571ffe7dca0e91a440d428664340ed91 100644 --- a/application/modules/courses/models/CourseModel.php +++ b/application/modules/courses/models/CourseModel.php @@ -897,8 +897,8 @@ class Courses_CourseModel extends Unl_Model if (is_array($model->_cleanData['crosslistings'])) { $keysToDelete = array_diff_key($model->_cleanData['crosslistings'], $model->_data['crosslistings']); - foreach ($keysToDelete as $keyToDelete) { - $activitiesToDelete[] = $model->_cleanData['crosslistings'][$keyToDelete]['courseCrosslistingId']; + foreach (array_keys($keysToDelete) as $keyToDelete) { + $crosslistingsToDelete[] = $model->_cleanData['crosslistings'][$keyToDelete]['courseCrosslistingId']; } } } @@ -1689,7 +1689,7 @@ class Courses_CourseModel extends Unl_Model $db = Zend_Registry::get('db'); - $sql = $db->quoteInto('DELETE FROM creqCourseCrosslistings WHERE creqCourseCrosslistingId IN (?)', $models); + $sql = $db->quoteInto('DELETE FROM creqCourseCrosslistings WHERE courseCrosslistingId IN (?)', $models); $db->query($sql); } diff --git a/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml new file mode 100644 index 0000000000000000000000000000000000000000..b3d9bbc7f3711e882119cd6b3af051245d859d04 --- /dev/null +++ b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/forkGrad.phtml @@ -0,0 +1 @@ +<?php