From af3ea308e68d5e0a2479e90dca10143255701cbb Mon Sep 17 00:00:00 2001
From: Tim Steiner <tsteiner2@unl.edu>
Date: Thu, 6 Dec 2012 16:40:06 -0600
Subject: [PATCH] Added a relation router approval action.

---
 .../ApprovalActionRelationRouterModel.php     | 239 ++++++++++++++++++
 .../edit-action/relationRouter.phtml          |  77 ++++++
 2 files changed, 316 insertions(+)
 create mode 100644 application/modules/courses/models/ApprovalActionRelationRouterModel.php
 create mode 100644 application/modules/courses/views/scripts/approval-chain-manager/edit-action/relationRouter.phtml

diff --git a/application/modules/courses/models/ApprovalActionRelationRouterModel.php b/application/modules/courses/models/ApprovalActionRelationRouterModel.php
new file mode 100644
index 00000000..2f4be2ef
--- /dev/null
+++ b/application/modules/courses/models/ApprovalActionRelationRouterModel.php
@@ -0,0 +1,239 @@
+<?php
+
+class Courses_ApprovalActionRelationRouterModel extends Requests_ApprovalActionModel
+{
+    public static function find($id)
+    {
+        $db = Zend_Registry::get('db');
+
+        $select = new Zend_Db_Select($db);
+        $select->from(array('a' => 'creqApprovalActions'));
+        $select->join(array('d' => 'creqApprovalActionsRelationRouter'), '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'] = 'ApprovalActionRelationRouter';
+        
+        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)
+    {
+        $db = Zend_Registry::get('db');
+        
+        $sql = 'CREATE TEMPORARY TABLE creqApprovalActionsRelationRouterUpdate '
+             . 'SELECT * FROM creqApprovalActionsRelationRouter LIMIT 0';
+        $db->query($sql);
+        
+        $sql = 'INSERT INTO creqApprovalActionsRelationRouterUpdate VALUES ';
+        $sqlParts = array();
+        foreach ($models as $model) {
+            $sqlParts[] = $db->quoteInto('(?, ', $model->_data['approvalActionId'])
+                        . $db->quoteInto('?, ',  $model->_data['relationType'])
+                        . $db->quoteInto('?) ',  $model->_data['relationId']);
+        }
+        $sql .= implode(', ', $sqlParts);
+        $db->query($sql);
+        
+        $sql = 'UPDATE creqApprovalActionsRelationRouter AS a, '
+             . '       creqApprovalActionsRelationRouterUpdate AS b '
+             . 'SET a.relationType = b.relationType, '
+             . '    a.relationId   = b.relationId '
+             . 'WHERE a.approvalActionId = b.approvalActionId ';
+        $db->query($sql);
+    }
+
+    static protected function _insert(Unl_Model_Collection $models)
+    {
+        $db = Zend_Registry::get('db');
+
+        $sql = 'INSERT INTO creqApprovalActionsRelationRouter (approvalActionId, relationType, relationId) VALUES ';
+        $sqlParts = array();
+        foreach ($models as $model) {
+            $sqlParts[] = $db->quoteInto('(?, ', $model->_data['approvalActionId'])
+                        . $db->quoteInto('?, ',  $model->_data['relationType'])
+                        . $db->quoteInto('?) ',  $model->_data['relationId']);
+        }
+        $sql .= implode(', ', $sqlParts);
+        $db->query($sql);
+    }
+
+    public function consider($requests)
+    {
+        $requestParentCourses = Courses_CourseModel::findParentOfRequest($requests);
+        $requestCurrentCourses = Courses_CourseModel::findLatestOfRequest($requests);
+        foreach ($requests as $request) {
+            // Set state to No until a match is found.
+            $request->setState('No');
+            
+            $course = $requestParentCourses[$request->getId()];
+            // If there's no previous course, then there's nothing to be related to.
+            if (!$course) {
+                continue;
+            }
+            
+            // Load the related courses for each crosslisting.
+            $relatedCourses = new Unl_Model_Collection('Courses_CourseModel');
+            foreach ($course->getCrosslistings() as $crosslisting) {
+                $relatedCourses->merge(Courses_CourseModel::getRelatedCourses($crosslisting['subject'], $crosslisting['courseNumber'], $crosslisting['courseLetter']));
+            }
+            foreach ($relatedCourses as $relatedCourse) {
+                // Don't worry about courses that are in the same subject/department/college as the requested course.
+                if (
+                    ($this->getRelationType() == 'subject' && $course->getSubject() == $relatedCourse->getSubject()) ||
+                    ($this->getRelationType() == 'department' && $course->getDepartment() == $relatedCourse->getDepartment()) ||
+                    ($this->getRelationType() == 'college' && $course->getCollege() == $relatedCourse->getCollege())
+                ) {
+                    continue;
+                }
+                
+                if ($this->isCourseRelated($relatedCourse)) {
+                    $request->setState('Yes');
+                }
+            }
+        }
+        
+        Requests_RequestModel::save($requests);
+        Requests_ApprovalChainModel::advance($requests);
+        return $requests;
+    }
+
+    public function userMadeDecisions($requests, $requestDecisions)
+    {
+        // Don't do anything here, this is an automated action.
+    }
+
+    public function setExtendedData($in)
+    {
+        if ($in['relationType'] == 'subject') {
+            if (!array_key_exists($in['relationId'], Courses_CourseModel::getSubjects())) {
+                throw new Exception('Invalid subject ID');
+            }
+        } else if ($in['relationType'] == 'department') {
+            if (!array_key_exists($in['relationId'], Courses_CourseModel::getDepartments())) {
+                throw new Exception('Invalid department ID');
+            }
+        } else if ($in['relationType'] == 'college') {
+            if (!array_key_exists($in['relationId'], Courses_CourseModel::getColleges())) {
+                throw new Exception('Invalid college ID');
+            }
+        } else {
+            throw new Exception('Invalid relation type');
+        }
+        
+        $this->_data['relationType'] = $in['relationType'];
+        $this->_data['relationId']   = $in['relationId'];
+        
+    }
+
+    public function getResultStatusStrings()
+    {
+        return array('No' => 'No', 'Yes' => 'Yes');
+    }
+    
+    public function getRelationType()
+    {
+        return $this->_data['relationType'];
+    }
+    
+    public function getRelationId()
+    {
+        return $this->_data['relationId'];
+    }
+    
+    public function getRelationName()
+    {
+        if ($this->getRelationType() == 'subject') {
+            $subjects = Courses_CourseModel::getSubjects();
+            return $subjects[$this->getRelationId()];
+        } else if ($this->getRelationType() == 'department') {
+            $departments = Courses_CourseModel::getDepartments();
+            return $departments[$this->getRelationId()];
+        } else if ($this->getRelationType() == 'college') {
+            $colleges = Courses_CourseModel::getColleges();
+            return $colleges[$this->getRelationId()];
+        } else {
+            return '--Unknown--';
+        }
+    }
+    
+    public function isCourseRelated(Courses_CourseModel $course)
+    {
+        if ($this->getRelationType() == 'subject' && $course->getSubject() == $this->getRelationName()) {
+            return TRUE;
+        }
+        
+        if ($this->getRelationType() == 'department' && $course->getDepartment() == $this->getRelationName()) {
+            return TRUE;
+        }
+        
+        if ($this->getRelationType() == 'college' && $course->getCollege() == $this->getRelationName()) {
+            return TRUE;
+        }
+        
+        return FALSE;
+    }
+}
diff --git a/application/modules/courses/views/scripts/approval-chain-manager/edit-action/relationRouter.phtml b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/relationRouter.phtml
new file mode 100644
index 00000000..2d7de0e1
--- /dev/null
+++ b/application/modules/courses/views/scripts/approval-chain-manager/edit-action/relationRouter.phtml
@@ -0,0 +1,77 @@
+<?php 
+if ($this->approvalAction->getId()) {
+    $prefix = 'edit[' . $this->approvalAction->getId() . '][';
+    $postfix = ']';
+}
+?>
+
+Relation Type:<br />
+<?php echo $this->formSelect(
+    $prefix . 'relationType' . $postfix,
+    $this->approvalAction->getRelationType(),
+    array('class' => 'relationType'),
+    array('' => '--Select--', 'subject' => 'Subject', 'department' => 'Department', 'college' => 'College')
+); ?><br />
+
+Related To<br />
+<?php echo $this->formSelect(
+    $prefix . 'relationId' . $postfix,
+    $this->approvalAction->getRelationId(),
+    array(
+        'class' => 'relationSubject',
+        'disabled' => 'disabled'
+    ),
+    array(-1 => '--Select--') + Courses_CourseModel::getSubjects()
+); ?>
+
+<?php echo $this->formSelect(
+    $prefix . 'relationId' . $postfix,
+    $this->approvalAction->getRelationId(),
+    array(
+        'class' => 'relationDepartment',
+        'disabled' => 'disabled'
+    ),
+    array(-1 => '--Select--') + Courses_CourseModel::getDepartments()
+); ?>
+
+<?php echo $this->formSelect(
+    $prefix . 'relationId' . $postfix,
+    $this->approvalAction->getRelationId(),
+    array(
+        'class' => 'relationCollege',
+        'disabled' => 'disabled'
+    ),
+    array(-1 => '--Select--') + Courses_CourseModel::getColleges()
+); ?>
+<br />
+
+
+<script type="text/javascript">
+(function() {
+    WDN.jQuery('.relationType').change(function() {
+        var subject = WDN.jQuery(this).parent().parent().find('.relationSubject');
+        var department = WDN.jQuery(this).parent().parent().find('.relationDepartment');
+        var college = WDN.jQuery(this).parent().parent().find('.relationCollege');
+    
+        subject.attr('disabled', 'disabled');
+        department.attr('disabled', 'disabled');
+        college.attr('disabled', 'disabled');
+    
+        subject.hide();
+        department.hide();
+        college.hide();
+    
+        if (this.value == 'subject') {
+            subject.removeAttr('disabled');
+            subject.show();
+        } else if (this.value == 'department') {
+            department.removeAttr('disabled');
+            department.show();
+        } else if (this.value == 'college') {
+            college.removeAttr('disabled');
+            college.show();
+        }
+    });
+    WDN.jQuery('.relationType').change();
+})();
+</script>
-- 
GitLab