diff --git a/application/controllers/ApprovalbodyadminController.php b/application/controllers/ApprovalbodyadminController.php
index 8f8b895103291bf420585e7fb89929c421a4b56a..51d9a0712055cc40296cc008c6dd79f64ec0b7f2 100644
--- a/application/controllers/ApprovalbodyadminController.php
+++ b/application/controllers/ApprovalbodyadminController.php
@@ -20,6 +20,7 @@ class ApprovalBodyAdminController extends Nmc_Controller_Action
         $out = new Nmc_View();
         $out->page = 'approval_body_admin';
 
+        $out->groups = Groups::getInstance()->fetchAll();
         $out->approvalBody = ApprovalBodies::getInstance()->find($approvalBodyId);
         $out->approvalBodies = ApprovalBodies::getInstance()->fetchAll();
 
@@ -70,6 +71,7 @@ class ApprovalBodyAdminController extends Nmc_Controller_Action
 
         $body->name = $in->getPost('name');
         $body->description = $in->getPost('description');
+        $body->adminGroup = $in->getPost('adminGroup');
         $body->save();
 
         $out = new Nmc_View();
diff --git a/application/controllers/ApprovalbodymanagerController.php b/application/controllers/ApprovalbodymanagerController.php
new file mode 100644
index 0000000000000000000000000000000000000000..74cf1ae4164cc0898aa2b8dc688c6082c62f85f0
--- /dev/null
+++ b/application/controllers/ApprovalbodymanagerController.php
@@ -0,0 +1,34 @@
+<?php
+
+class ApprovalBodyManagerController extends Nmc_Controller_Action
+{
+    public function indexAction()
+    {
+        return $this->listAction();
+    }
+
+    public function listAction()
+    {
+        $usersBodies = ApprovalBodies::getInstance()->fetchApprovalBodiesUserCanAdminister(Nmc_User::getInstance()->getUser());
+
+        $out = new Nmc_View();
+        $out->page = 'approval_body_manager';
+        $out->usersBodies = $usersBodies;
+        echo $out->render('index.xhtml');
+    }
+
+    public function editBodyAction()
+    {
+        $in = $this->getRequest();
+        $approvalBodyId = Zend_Filter::getInt($in->getParam(0));
+
+        $usersBodies = ApprovalBodies::getInstance()->fetchApprovalBodiesUserCanAdminister(Nmc_User::getInstance()->getUser());
+        $currentBody = ApprovalBodies::getInstance()->find($approvalBodyId);
+
+        $out = new Nmc_View();
+        $out->page = 'approval_body_manager';
+        $out->usersBodies = $usersBodies;
+        $out->currentBody = $currentBody;
+        echo $out->render('index.xhtml');
+    }
+}
\ No newline at end of file
diff --git a/application/controllers/ApprovalchainmanagerController.php b/application/controllers/ApprovalchainmanagerController.php
new file mode 100644
index 0000000000000000000000000000000000000000..1121acc1d770de38371421017da8f60ed9f12037
--- /dev/null
+++ b/application/controllers/ApprovalchainmanagerController.php
@@ -0,0 +1,88 @@
+<?php
+
+class ApprovalChainManagerController extends Nmc_Controller_Action
+{
+    public function indexAction()
+    {
+        return $this->listAction();
+    }
+
+    public function listAction()
+    {
+        $approvalChains = ApprovalChains::getInstance()->fetchAll();
+
+        $out = new Nmc_View();
+        $out->page = 'approval_chain_manager';
+        $out->approvalChains = $approvalChains;
+        echo $out->render('index.xhtml');
+    }
+
+    public function editChainAction()
+    {
+        $in = $this->getRequest();
+        $chainId = Zend_Filter::getInt($in->getParam(0));
+        $chain = ApprovalChains::getInstance()->find($chainId);
+
+        $approvalChains = ApprovalChains::getInstance()->fetchAll();
+
+        $approvalActions = ApprovalActions::getInstance()->getAvailableActions();
+        $approvalActionList = array();
+        foreach ($approvalActions as $approvalAction) {
+            $approvalActionList[get_class($approvalAction)] = $approvalAction->getActionName();
+        }
+
+        $out = new Nmc_View();
+        $out->page = 'approval_chain_manager';
+        $out->chain = $chain;
+        $out->approvalChains = $approvalChains;
+        $out->approvalActions = $approvalActionList;
+        $out->approvalChain = $chain;
+        echo $out->render('index.xhtml');
+    }
+
+    public function addLinkPostAction()
+    {
+        /*
+        $in = $this->getRequest()->getPost();
+        $chainId = Zend_Filter::getInt($in['chainId']);
+        $chain = ApprovalChains::getInstance()->find($chainId);
+
+        $newLink = ApprovalLinks::getInstance()->fetchNew();
+        $newLink->currentAction = $in['currentAction'];
+        $newLink->currentState = $in['currentState'];
+        $newLink->nextAction = $in['nextAction'];
+        */
+    }
+
+    public function getActionListAction()
+    {
+        $approvalActions = ApprovalActions::getInstance()->getAvailableActions();
+
+        $out = new DOMDocument();
+        foreach ($approvalActions as $approvalAction) {
+            $element = $out->createElement('action');
+            $element->setAttribute('name', $approvalAction->getActionName());
+            $element->setAttribute('className', get_class($approvalAction));
+            foreach($approvalAction->getResultStatusStrings() as $actionResult)
+            {
+                $resultElement = $out->createElement('result');
+                $resultElement->setAttribute('name', $actionResult);
+                $element->appendChild($resultElement);
+            }
+            $out->appendChild($element);
+        }
+        $this->getResponse()->setHeader('Content-type', 'application/xml');
+        $this->getResponse()->setBody($out->saveXML());
+    }
+
+    public function getActionEditXhtmlAction()
+    {
+        $in = $this->getRequest();
+        $actionName = $in->getParam(0);
+        $className = 'ApprovalActions' . $actionName;
+        $action = call_user_method('getInstance', $className);
+        $template = $action->getEditTemplate();
+        $out = new Nmc_View();
+        echo $out->render($template);
+    }
+}
\ No newline at end of file
diff --git a/application/controllers/TestController.php b/application/controllers/TestController.php
index 0701d103f2d6f3e4c8bd53adc5b67757bb984d48..2197b245a1b2e199d3626b901cf98e3962ed195d 100644
--- a/application/controllers/TestController.php
+++ b/application/controllers/TestController.php
@@ -11,11 +11,14 @@ class TestController extends Nmc_Controller_Action
 
     public function indexAction()
     {
-        $out = $this->getResponse();
-        $view = new Nmc_View();
-        $out->setBody($view->render('index.xhtml'));
-        //$out->renderExceptions(true);
-        throw new Exception("this is bad!");
+        $a = ApprovalChains::getInstance()->find(1);
+
+        foreach ($a->approvalActions as $b) {}
+
+        $a->save();
+
+        header('Content-type: text/plain');
+        print_r($a);
     }
 }
 
diff --git a/application/library/ApprovalAction/AutoApprove.php b/application/library/ApprovalAction/AutoApprove.php
new file mode 100644
index 0000000000000000000000000000000000000000..4a0502b2fe92a65cdff4125bd16ed98cb6ba7848
--- /dev/null
+++ b/application/library/ApprovalAction/AutoApprove.php
@@ -0,0 +1,8 @@
+<?php
+
+require_once 'ApprovalAction/Interface.php';
+
+class Application_ApprovalAction_AutoApprove implements Application_ApprovalAction_Interface
+{
+
+}
\ No newline at end of file
diff --git a/application/library/ApprovalAction/Interface.php b/application/library/ApprovalAction/Interface.php
new file mode 100644
index 0000000000000000000000000000000000000000..6eab2037273fdcfe012e89de1516bb0dcb0b74c0
--- /dev/null
+++ b/application/library/ApprovalAction/Interface.php
@@ -0,0 +1,21 @@
+<?php
+
+interface Application_ApprovalAction_Interface
+{
+    /**
+     * Reutrns an array of strings, corresponding to the possible
+     * results of performing this action.
+     *
+     * @return array
+     */
+    public function getResultStatusStrings();
+
+    /**
+     * Initiates the action, causing it to begin processing the given request.
+     * When consideration finishes, the parent chain will be called again.
+     *
+     * @param Request $request
+     * @param ApprovalChain $parentChain
+     */
+    public function consider(Request $request, ApprovalChain $parentChain);
+}
diff --git a/application/models/rows/ApprovalAction.php b/application/models/rows/ApprovalAction.php
new file mode 100644
index 0000000000000000000000000000000000000000..3c086a6e07217517f659742b4035375149555124
--- /dev/null
+++ b/application/models/rows/ApprovalAction.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @tableClass ApprovalActions
+ *
+ */
+class ApprovalAction extends Nmc_Db_Table_Row
+{
+    public function getPrimaryKey()
+    {
+        return $this->approvalActionId;
+    }
+
+    public function getPrimaryKeyName($camelized = false)
+    {
+        if ($camelized) {
+            return 'approvalActionId';
+        } else {
+            return 'approval_action_id';
+        }
+    }
+}
\ No newline at end of file
diff --git a/application/models/rows/ApprovalActionAuto.php b/application/models/rows/ApprovalActionAuto.php
new file mode 100644
index 0000000000000000000000000000000000000000..3fb020639d8e2b63358c271f12410e909e391e8b
--- /dev/null
+++ b/application/models/rows/ApprovalActionAuto.php
@@ -0,0 +1,23 @@
+<?php
+
+require_once 'ApprovalAction/Interface.php';
+
+/**
+ * @foreignKey approvalActionId
+ * @tableClass ApprovalActionsAuto
+ *
+ */
+class ApprovalActionAuto extends ApprovalAction
+                         implements Application_ApprovalAction_Interface
+{
+
+    public function getResultStatusStrings()
+    {
+        return $this->getTable()->getResultStatusStrings();
+    }
+
+    public function consider(Request $request, ApprovalChain $parentChain)
+    {
+        //
+    }
+}
\ No newline at end of file
diff --git a/application/models/rows/ApprovalBody.php b/application/models/rows/ApprovalBody.php
index 51e36af406e896ddd00aaa2ff61a8eda7cd48bd2..59bcd410e8520610cd5ec0519c9a0bd27c760e6e 100644
--- a/application/models/rows/ApprovalBody.php
+++ b/application/models/rows/ApprovalBody.php
@@ -2,10 +2,8 @@
 
 class ApprovalBody extends Nmc_Db_Table_Row
 {
-    function __construct($config = array())
+    function __init()
     {
-        parent::__construct($config);
-
         $this->_registerRelation(
             new Nmc_Db_Table_Relation_HasMany(
                 ApprovalBodyRoles::getInstance(),
diff --git a/application/models/rows/ApprovalChain.php b/application/models/rows/ApprovalChain.php
index 88b3b9c307641cb6077bfced1460cb5d8350ac58..2dbd20c122c75430f96ae57019a9543fc8e744f3 100644
--- a/application/models/rows/ApprovalChain.php
+++ b/application/models/rows/ApprovalChain.php
@@ -3,6 +3,33 @@
 class ApprovalChain extends Nmc_Db_Table_Row
 {
 
+    protected function _init()
+    {
+        $linksRelation = new Nmc_Db_Table_Relation_HasMany(ApprovalLinks::getInstance(), $this, 'chain', 'approvalLinks');
+        $this->_registerRelation($linksRelation);
+
+        $actionsRelation = new Nmc_Db_Table_Relation_HasMany(ApprovalActionsAbstract::getInstance(), $this, 'approval_chain', 'approvalActions');
+        $this->_registerRelation($actionsRelation);
+    }
+
+    protected function _preSave()
+    {
+        $foo = 1;
+        parent::_preSave();
+    }
+
+    protected function _save()
+    {
+        $foo = 1;
+        parent::_save();
+    }
+
+    protected function _postSave()
+    {
+        $foo = 1;
+        parent::_postSave();
+    }
+
     /**
      * This function is called by ApprovalActions when a decision has been reached.
      * When called, the next ApprovalAction in the chain will be called
diff --git a/application/models/rows/ApprovalLink.php b/application/models/rows/ApprovalLink.php
new file mode 100644
index 0000000000000000000000000000000000000000..f37a68d3ae6a2a1a980183d1e46dcdf060c2eace
--- /dev/null
+++ b/application/models/rows/ApprovalLink.php
@@ -0,0 +1,14 @@
+<?php
+
+class ApprovalLink extends Nmc_Db_Table_Row {
+
+    protected function _init()
+    {
+        $currentActionRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalActionsAbstract::getInstance(), $this, 'current_action', 'currentAction', true);
+        $currentActionRelation->setOverrideLocal(true);
+        $this->_registerRelation($currentActionRelation);
+        $nextActionRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalActionsAbstract::getInstance(), $this, 'next_action', 'nextAction', true);
+        $this->_registerRelation($nextActionRelation);
+    }
+
+}
\ No newline at end of file
diff --git a/application/models/rows/CourseDetail.php b/application/models/rows/CourseDetail.php
index 7cbaedc4e01ed2f9778f065d1936e4d16545c750..ed1b98a0b29ea9e73f34e163876583b635b02b73 100644
--- a/application/models/rows/CourseDetail.php
+++ b/application/models/rows/CourseDetail.php
@@ -3,9 +3,8 @@
 class CourseDetail extends Nmc_Db_Table_Row
 {
 
-    public function __construct($config = array())
+    public function _init()
     {
-        parent::__construct($config);
         $this->_humanize();
     }
 
diff --git a/application/models/rows/CourseGeneration.php b/application/models/rows/CourseGeneration.php
index c97ac7ab62418c7c6bada47df07c1fcea4d8de6b..f03164099a40a6f5223416a60fe8e0a71049bbf5 100644
--- a/application/models/rows/CourseGeneration.php
+++ b/application/models/rows/CourseGeneration.php
@@ -13,7 +13,7 @@ class CourseGeneration extends Asset
     public function _init()
     {
         $this->_registerRelation(
-            new Nmc_Db_Table_Relation_HasOne(CourseDetails::getInstance(), $this, 'generation'));
+            new Nmc_Db_Table_Relation_HasSubset(CourseDetails::getInstance(), $this, 'generation'));
         $this->_registerRelation(
             new Nmc_Db_Table_Relation_HasMany(CourseActivities::getInstance(), $this, 'generation', 'activities'));
         $this->_registerRelation(
diff --git a/application/models/rows/Request.php b/application/models/rows/Request.php
index 9c6d55cc7dc48a5db92aaea25a188c410f8da721..f4bc1b8269bec0886843e3f7bdeb59cd19c6d684 100644
--- a/application/models/rows/Request.php
+++ b/application/models/rows/Request.php
@@ -7,28 +7,16 @@ class Request extends Nmc_Db_Table_Row
         $requestRelation = new Nmc_Db_Table_Relation_HasMany(RequestFiles::getInstance(), $this, 'request', 'files');
         $this->_registerRelation($requestRelation);
 
-        $ownerRelation = new Nmc_Db_Table_Relation_HasOne(Users::getInstance(), $this, 'owner');
-        $ownerRelation->setForeignKeyInLocalTable(true);
-        $ownerRelation->setAttributeName('owner');
-        $ownerRelation->setOverrideLocal(true);
+        $ownerRelation = new Nmc_Db_Table_Relation_HasOne(Users::getInstance(), $this, 'owner', 'owner', true);
         $this->_registerRelation($ownerRelation);
 
-        $stackRelation = new Nmc_Db_Table_Relation_HasOne(RequestStacks::getInstance(), $this, 'stack_pointer');
-        $stackRelation->setForeignKeyInLocalTable(true);
-        $stackRelation->setAttributeName('stackPointer');
-        $stackRelation->setOverrideLocal(true);
+        $stackRelation = new Nmc_Db_Table_Relation_HasOne(RequestStacks::getInstance(), $this, 'stack_pointer', 'stackPointer', true);
         $this->_registerRelation($stackRelation);
 
-        $stateRelation = new Nmc_Db_Table_Relation_HasOne(RequestStates::getInstance(), $this, 'state');
-        $stateRelation->setForeignKeyInLocalTable(true);
-        $stateRelation->setAttributeName('state');
-        $stateRelation->setOverrideLocal(true);
+        $stateRelation = new Nmc_Db_Table_Relation_HasOne(RequestStates::getInstance(), $this, 'state', 'state', true);
         $this->_registerRelation($stateRelation);
 
-        $typeRelation = new Nmc_Db_Table_Relation_HasOne(RequestTypes::getInstance(), $this, 'type');
-        $typeRelation->setForeignKeyInLocalTable(true);
-        $typeRelation->setAttributeName('type');
-        $typeRelation->setOverrideLocal(true);
+        $typeRelation = new Nmc_Db_Table_Relation_HasOne(RequestTypes::getInstance(), $this, 'type', 'type', true);
         $this->_registerRelation($typeRelation);
     }
 
@@ -115,7 +103,7 @@ class Request extends Nmc_Db_Table_Row
 
         $stack = RequestStacks::getInstance()->fetchNew();
         $stack->chain = $this->type->approvalChain;
-        $stack->body = $approvalBody;
+        $stack->action = null;
         $stack->save();
 
         $this->stackPointer = $stack;
diff --git a/application/models/rows/RequestStack.php b/application/models/rows/RequestStack.php
index bd6b08e220c15e49bcf1b70827b8bb4ab23311b9..dde1429e5632426d64304db494a85619291421af 100644
--- a/application/models/rows/RequestStack.php
+++ b/application/models/rows/RequestStack.php
@@ -4,17 +4,10 @@ class RequestStack extends Nmc_Db_Table_Row
 {
     public function _init()
     {
-        $bodyRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalBodies::getInstance(), $this, 'body');
-        $bodyRelation->setForeignKeyInLocalTable(true);
-        $bodyRelation->setOverrideLocal(true);
-        $bodyRelation->setAttributeName('body');
+        $bodyRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalActionsAbstract::getInstance(), $this, 'action', 'action', true);
         $this->_registerRelation($bodyRelation);
 
-
-        $chainRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalChains::getInstance(), $this, 'chain');
-        $chainRelation->setForeignKeyInLocalTable(true);
-        $chainRelation->setOverrideLocal(true);
-        $chainRelation->setAttributeName('chain');
+        $chainRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalChains::getInstance(), $this, 'chain', 'chain', true);
         $this->_registerRelation($chainRelation);
     }
 }
\ No newline at end of file
diff --git a/application/models/rows/RequestType.php b/application/models/rows/RequestType.php
index fceb0d37b58f6a650850de6516208ef2a609ba86..3fa9495fc931e1941729eef68cce2561ff4fc343 100644
--- a/application/models/rows/RequestType.php
+++ b/application/models/rows/RequestType.php
@@ -5,7 +5,6 @@ class RequestType extends Nmc_Db_Table_Row
     protected function _init()
     {
         $chainRelation = new Nmc_Db_Table_Relation_HasOne(ApprovalChains::getInstance(), $this, 'approval_chain', 'approvalChain', true);
-        $chainRelation->setOverrideLocal(true);
         $this->_registerRelation($chainRelation);
     }
 }
\ No newline at end of file
diff --git a/application/models/tables/ApprovalActions.php b/application/models/tables/ApprovalActions.php
new file mode 100644
index 0000000000000000000000000000000000000000..05bb60ef04b7f2368058b693b7674a841ad02f79
--- /dev/null
+++ b/application/models/tables/ApprovalActions.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @rowClass ApprovalAction
+ * @primary approval_action_id
+ *
+ */
+class ApprovalActions extends Nmc_Db_Table
+{
+    /**
+     * The one true instance
+     *
+     * @var ApprovalActions
+     */
+    static protected $_instance;
+
+    /**
+     * Return the one true instance
+     *
+     * @return ApprovalActions
+     */
+    static public function getInstance($config = array())
+    {
+        if (!self::$_instance) {
+            self::$_instance = new ApprovalActions($config);
+        }
+        return self::$_instance;
+    }
+
+    public function getAvailableActions()
+    {
+        $actions = array();
+        $currentPath = dirname(__FILE__);
+        $tablesDir = scandir($currentPath);
+        foreach ($tablesDir as $fullPath) {
+            $file = basename($fullPath);
+
+            if (substr($file, 0, strlen('ApprovalActions')) != 'ApprovalActions') {
+                continue;
+            }
+            if (substr($file, -1 * strlen('.php')) != '.php') {
+                continue;
+            }
+            if ($file == 'ApprovalActions.php') {
+                continue;
+            }
+
+            $className = substr($file, 0, -1 * strlen('.php'));
+            $class = call_user_func(array($className, 'getInstance'));
+
+            $actions[] = $class;
+        }
+        return $actions;
+    }
+}
\ No newline at end of file
diff --git a/application/models/tables/ApprovalActionsAbstract.php b/application/models/tables/ApprovalActionsAbstract.php
new file mode 100644
index 0000000000000000000000000000000000000000..090b08a0d9e36f9f175379020176b0cab68705b8
--- /dev/null
+++ b/application/models/tables/ApprovalActionsAbstract.php
@@ -0,0 +1,81 @@
+<?php
+
+/**
+ * @rowClass ApprovalAction
+ * @primary approval_action_id
+ *
+ */
+class ApprovalActionsAbstract extends Nmc_Db_Table
+{
+    /**
+     * The one true instance
+     *
+     * @var ApprovalActions
+     */
+    static protected $_instance;
+
+    /**
+     * Return the one true instance
+     *
+     * @return ApprovalActionsAbstract
+     */
+    static public function getInstance($config = array())
+    {
+        if (!self::$_instance) {
+            self::$_instance = new ApprovalActionsAbstract($config);
+        }
+        return self::$_instance;
+    }
+
+    public function _setup()
+    {
+        $this->_name = ApprovalActions::getInstance()->getTableName();
+        return parent::_setup();
+    }
+
+    public function find($val)
+    {
+        $db = $this->getAdapter();
+
+        $parentTable = ApprovalActions::getInstance();
+        $parentRow = $parentTable->find($val);
+        $rowClass = $parentRow->className;
+
+        // find out what the parent table is supposed to be (in the case of an extended row)
+        $introspect = new ReflectionClass($rowClass);
+        $docBlock = Nmc_DocBlock::createFromString($introspect->getDocComment());
+        $tableClass = $docBlock->tableClass;
+        $table = call_user_method('getInstance', $tableClass);
+
+        $whereString = $parentRow->getPrimaryKeyName() . ' = ?';
+        $where = $db->quoteInto($whereString, $parentRow->getPrimaryKey());
+
+        return $table->fetchRow($where);
+    }
+
+    public function fetchRow($where = null, $order = null)
+    {
+        $db = $this->getAdapter();
+        $parentTable = ApprovalActions::getInstance();
+        $parentRow = $parentTable->fetchRow($where, $order);
+        if ($parentRow) {
+            return $this->find($parentRow->getPrimaryKey());
+        } else {
+            return null;
+        }
+    }
+
+    public function fetchAll($where = null, $order = null, $count = null, $offset = null)
+    {
+        $db = $this->getAdapter();
+        $parentTable = ApprovalActions::getInstance();
+        $parentRowset = $parentTable->fetchAll($where, $order, $count, $offset);
+
+        foreach($parentRowset as $key => $row)
+        {
+            $parentRowset[$key] = $this->find($row->getPrimaryKey());
+        }
+
+        return $parentRowset;
+    }
+}
\ No newline at end of file
diff --git a/application/models/tables/ApprovalActionsAuto.php b/application/models/tables/ApprovalActionsAuto.php
new file mode 100644
index 0000000000000000000000000000000000000000..467ebc5ff87c583e61b324675f4b996f0a8112d7
--- /dev/null
+++ b/application/models/tables/ApprovalActionsAuto.php
@@ -0,0 +1,45 @@
+<?php
+
+/**
+ * @rowClass ApprovalActionAuto
+ * @primary approval_action_auto_id
+ *
+ */
+class ApprovalActionsAuto extends Nmc_Db_Table
+{
+    /**
+     * The one true instance
+     *
+     * @var ApprovalActionsAuto
+     */
+    static protected $_instance;
+
+    /**
+     * Return the one true instance
+     *
+     * @return ApprovalActionsAuto
+     */
+    static public function getInstance($config = array())
+    {
+        if (!self::$_instance) {
+            self::$_instance = new ApprovalActionsAuto($config);
+        }
+        return self::$_instance;
+    }
+
+    public function getActionName()
+    {
+        return 'Automatic';
+    }
+
+    public function getResultStatusStrings()
+    {
+        return array('Approved' => 'Approved',
+                     'Denied' => 'Denied');
+    }
+
+    public function getEditTemplate()
+    {
+        return 'approval_actions/ApprovalActionAuto.xhtml';
+    }
+}
\ No newline at end of file
diff --git a/application/models/tables/ApprovalBodies.php b/application/models/tables/ApprovalBodies.php
index 10628de216f934f007c5aa9e486b670d4f9dcfb7..91e08c8f067ca9c359d43ebcdcff76004a160e03 100644
--- a/application/models/tables/ApprovalBodies.php
+++ b/application/models/tables/ApprovalBodies.php
@@ -40,6 +40,18 @@ class ApprovalBodies extends Nmc_Db_Table
     {
         return $this->find(1);
     }
+
+    public function fetchApprovalBodiesUserCanAdminister(User $user)
+    {
+        $groups = GroupImpliedMemberships::getInstance()->fetchGroupsByUser($user);
+        $groupIds = array();
+        foreach ($groups as $group) {
+            $groupIds [] = $group->getPrimaryKey();
+        }
+
+        $where = $this->_db->quoteInto('admin_group IN (?)', $groupIds);
+        return $this->fetchAll($where);
+    }
 }
 
 ?>
\ No newline at end of file
diff --git a/application/models/tables/ApprovalLinks.php b/application/models/tables/ApprovalLinks.php
index d58c522a89626aa94418e1053aa4ca351253051b..618bd257b41bc49d90cbac6d0676bd17f1daf113 100644
--- a/application/models/tables/ApprovalLinks.php
+++ b/application/models/tables/ApprovalLinks.php
@@ -2,9 +2,31 @@
 
 /**
  *
+ * @rowClass ApprovalLink
  * @primary approval_link_id
  *
  */
-class ApprovalLinks extends Nmc_Db_Table {}
+class ApprovalLinks extends Nmc_Db_Table
+{
+    /**
+     * The one true instance
+     *
+     * @var ApprovalLinks
+     */
+    static protected $_instance;
+
+    /**
+     * Return the one true instance
+     *
+     * @return ApprovalLinks
+     */
+    static public function getInstance($config = array())
+    {
+        if (!self::$_instance) {
+            self::$_instance = new ApprovalLinks($config);
+        }
+        return self::$_instance;
+    }
+}
 
 ?>
\ No newline at end of file
diff --git a/application/views/approval_actions/ApprovalActionAuto.xhtml b/application/views/approval_actions/ApprovalActionAuto.xhtml
new file mode 100644
index 0000000000000000000000000000000000000000..13b62044494557c652c512ccbd49cdac0a6a18f4
--- /dev/null
+++ b/application/views/approval_actions/ApprovalActionAuto.xhtml
@@ -0,0 +1,17 @@
+<?php
+
+$currentSave = $current;
+
+$current['id'] = '';
+$current['value'] = null;
+if ($approvalAction) {
+    $current['id'] = '[' . $approvalAction->getPrimaryKey() . ']';
+    $current['value'] = $approvalAction->result;
+}
+
+echo $this->formSelect('result' . $current['id'],
+                       $current['value'],
+                       null,
+                       ApprovalActionsAuto::getInstance()->getResultStatusStrings());
+
+$current = $currentSave;
\ No newline at end of file
diff --git a/application/views/approval_body_admin.xhtml b/application/views/approval_body_admin.xhtml
index 72a8ec195995e2cdba26cb11b5fbdb4d05fc96b3..1d1480f36927ddce3993bdaf578647eeda7f3d68 100644
--- a/application/views/approval_body_admin.xhtml
+++ b/application/views/approval_body_admin.xhtml
@@ -37,6 +37,11 @@
         <?php echo $this->formText('description',
                                    $this->approvalBody->description,
                                    array('size' => 32)); ?>
+        <label for="adminGroup">Admin User/Group:</label>
+        <?php echo $this->formSelect('adminGroup',
+                                     $this->approvalBody->adminGroup,
+                                     null,
+                                     $this->groups->columnToArray('name', Groups::getInstance()->getPrimaryKeyName(true))); ?>
         <?php echo $this->formSubmit('Submit', 'Submit'); ?>
     </form>
 </div>
diff --git a/application/views/approval_body_manager.xhtml b/application/views/approval_body_manager.xhtml
new file mode 100644
index 0000000000000000000000000000000000000000..504eba241537343eab893e5dc5c19b14466bcf9a
--- /dev/null
+++ b/application/views/approval_body_manager.xhtml
@@ -0,0 +1,22 @@
+<h2>Select an Approval Body:</h2>
+
+<ul>
+<?php foreach ($this->usersBodies as $approvalBody) { ?>
+<li>
+    <a href="/ApprovalBodyManager/EditBody/<?php echo $approvalBody->getPrimaryKey(); ?>">
+        <?php echo $approvalBody->name; ?>
+    </a>
+</li>
+<?php } ?>
+</ul>
+
+<?php if($this->currentBody) { ?>
+<h1>Editing <?php echo $this->currentBody->name; ?></h1>
+<form method="post" action="/ApprovalBodyManager/EditBodyPost">
+<?php foreach (RequestTypes::getInstance()->fetchAll() as $requestType) { ?>
+<h2><?php echo $requestType->name; ?></h2>
+<?php } ?>
+
+</form>
+
+<?php } ?>
\ No newline at end of file
diff --git a/application/views/approval_chain_manager.xhtml b/application/views/approval_chain_manager.xhtml
new file mode 100644
index 0000000000000000000000000000000000000000..55d33f70ba11fa4000e434a9560811382554a596
--- /dev/null
+++ b/application/views/approval_chain_manager.xhtml
@@ -0,0 +1,101 @@
+<div id="select_chain">
+    <h2>Select an Approval Chain</h2>
+    <ul>
+    <?php foreach ($this->approvalChains as $approvalChain) { ?>
+        <li>
+            <a href="/ApprovalChainManager/EditChain/<?php echo $approvalChain->getPrimaryKey(); ?>">
+                <?php echo $approvalChain->name; ?>
+            </a>
+        </li>
+    <?php } ?>
+    </ul>
+</div>
+
+
+<?php if ($this->approvalChain) { ?>
+
+<div id="edit_pane">
+    <h1>Editing Approval Chain <?php echo $this->approvalChain->name; ?></h1>
+    <div id="select_links_or_actions">
+        <a href="#" id="select_manage_links">Links</a>
+        |
+        <a href="#" id="select_manage_actions">Actions</a>
+    </div>
+
+    <div id="manage_links">
+        <form method="post" action="/ApprovalChainManager/AddLinkPost">
+            <?php echo $this->formHidden('chainId', $this->approvalChain->getPrimaryKey()); ?>
+            <h2>Add Link to Approval Chain</h2>
+
+            <table>
+                <tr>
+                    <th>Previous Action</th>
+                    <th>Resulted In</th>
+                    <th>Next Action</th>
+                </tr>
+                <?php foreach ($this->approvalChain->approvalLinks as $approvalLink) { ?>
+                <tr>
+                    <td>
+                        <?php echo $this->formSelect('currentAction',
+                                                     null,
+                                                     array('class' => 'actionSelectElement'),
+                                                     array_merge(array('_null' => '--Just Entered Chain--'),
+                                                                 $this->approvalActions)); ?>
+                    </td>
+                    <td>
+                        <?php echo $this->formSelect('currentState', null, null, array('_null' => '--N/A--')); ?>
+                    </td>
+                    <td>
+                        <?php echo $this->formSelect('nextAction', null, null,
+                                                     array_merge(array('_null' => '--Exit Chain--'),
+                                                                 $this->approvalActions)); ?>
+                    </td>
+                </tr>
+                <?php } ?>
+            </table>
+
+            <?php echo $this->formSubmit('submit', 'Add Link', null); ?>
+        </form>
+
+        <form method="post" action="/ApprovalChainManager/EditChainPost">
+            <h2>Edit current Chains</h2>
+            <table>
+                <tr>
+                    <th>Previous Action</th>
+                    <th>Resulted In</th>
+                    <th>Next Action</th>
+                </tr>
+                <?php foreach ($this->approvalChain->approvalLinks as $approvalLink) { ?>
+                <tr>
+                    <td>
+                        <?php echo $this->formSelect('currentAction['. $approvalLink->getPrimaryKey() .']',
+                                                     $approvalLink->currentAction->className,
+                                                     array('class' => 'actionSelectElement'),
+                                                     array_merge(array('_null' => '--Just Entered Chain--'),
+                                                                 $this->approvalActions)); ?>
+                    </td>
+                    <td>
+                        <?php echo $this->formSelect('currentState', null, null, array('_null' => '--N/A--')); ?>
+                    </td>
+                    <td>
+                        <?php echo $this->formSelect('nextAction', $approvalLink->nextAction->className, null,
+                                                     array_merge(array('_null' => '--Exit Chain--'),
+                                                                 $this->approvalActions)); ?>
+                    </td>
+                </tr>
+                <?php } ?>
+            </table>
+        </form>
+    </div>
+
+    <div id="manage_actions" style="display:none;">
+        <form>
+            <?php foreach ($this->approvalChain->approvalActions as $approvalAction) { ?>
+            <label>Name: <?php echo $this->formText('name[' . $approvalAction->getPrimaryKey() . ']', $approvalAction->name); ?></label>
+            <label>Type: <?php echo $this->formSelect('type[' . $approvalAction->getPrimaryKey() . ']', $approvalAction->className, null, $this->approvalActions); ?></label>
+            <?php include $approvalAction->getTable()->getEditTemplate(); ?>
+            <?php } ?>
+        </form>
+    </div>
+</div>
+<?php } ?>
diff --git a/application/views/my_home.xhtml b/application/views/my_home.xhtml
index 75b66de9ba3f736de67bbdcbe2cbf499682b3b44..98adceba11cf3c4f8a223c445c56374842b20df1 100644
--- a/application/views/my_home.xhtml
+++ b/application/views/my_home.xhtml
@@ -106,6 +106,6 @@
     <?php } ?>
 </div>
 
-
+<?php print_r(array_keys($_SESSION['default'])); ?>
 
 <?php echo nl2br(Nmc_Registry_Session::getInstance()->loginError); ?>
\ No newline at end of file
diff --git a/document_root/css/approval_chain_manager.css b/document_root/css/approval_chain_manager.css
new file mode 100644
index 0000000000000000000000000000000000000000..95d7d0710a2c022ff5d7109d1bb7dea8ed316b01
--- /dev/null
+++ b/document_root/css/approval_chain_manager.css
@@ -0,0 +1,11 @@
+div#select_chain {
+    float: left;
+}
+
+div#select_chain ul {
+    list-style: none;
+}
+
+div#index_content div#edit_pane {
+    margin-left: 150px;
+}
\ No newline at end of file
diff --git a/document_root/javascript/approval_chain_manager.js b/document_root/javascript/approval_chain_manager.js
new file mode 100644
index 0000000000000000000000000000000000000000..218faa2c97adf8f64e838f6f7a0dd655966df190
--- /dev/null
+++ b/document_root/javascript/approval_chain_manager.js
@@ -0,0 +1,86 @@
+function loadApprovalChainManager()
+{
+    loadXMLDoc('/ApprovalChainManager/GetActionList', saveActionList)
+
+
+    var actionSelectElements = getElementsByClass('actionSelectElement');
+    for(var i = 0; i < actionSelectElements.length; i++) {
+        var actionSelectElement = actionSelectElements[i];
+        actionSelectElement.onchange = function() {updateActionResults(this);};
+    }
+
+    document.getElementById('select_manage_links').onclick = selectLinksOrActions;
+    document.getElementById('select_manage_actions').onclick = selectLinksOrActions;
+}
+
+addLoadEvent(loadApprovalChainManager);
+
+
+
+function selectLinksOrActions()
+{
+    if(this.id == 'select_manage_links') {
+        document.getElementById('manage_links').style.display = '';
+        document.getElementById('manage_actions').style.display = 'none';
+    } else {
+        document.getElementById('manage_links').style.display = 'none';
+        document.getElementById('manage_actions').style.display = '';
+    }
+}
+
+
+
+
+var _serverActionList = new Array();
+
+function saveActionList(response)
+{
+    if (req.readyState != 4) {
+        return;
+    }
+    if (req.status != 200) {
+        return;
+    }
+
+    _serverActionList = new Array();
+
+    actionXML = req.responseXML;
+    for (var i = 0; i < actionXML.childNodes.length; i++) {
+        var currentActionNode = actionXML.childNodes[i];
+        var currentAction = new Object();
+        currentAction.name = currentActionNode.getAttribute('name');
+        currentAction.className = currentActionNode.getAttribute('className');
+        currentAction.results = new Array();
+        for (var j = 0; j < currentActionNode.childNodes.length; j++) {
+            currentAction.results[j] = currentActionNode.childNodes[j].getAttribute('name');
+        }
+        _serverActionList[i] = currentAction;
+    }
+}
+
+
+function updateActionResults(actionSelectElement)
+{
+    var actionResultElement = actionSelectElement.parentNode;
+    for(actionResultElement = actionResultElement.nextSibling;
+        actionResultElement.nodeName != 'td';
+        actionResultElement = actionResultElement.nextSibling);
+
+    actionResultElement = actionResultElement.getElementsByTagName('select').item(0);
+    actionResultElement.options.length = 0;
+
+    if (actionSelectElement.value == '_null') {
+        actionResultElement.add(new Option('--N/A--', '_null', false, false), null);
+        return;
+    }
+
+    for (var i = 0; i < _serverActionList.length; i++) {
+        if (_serverActionList[i].className == actionSelectElement.value) {
+            for (var j = 0; j < _serverActionList[i].results.length; j++) {
+                var resultName = _serverActionList[i].results[j];
+                actionResultElement.add(new Option(resultName, resultName, false, false), null);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/document_root/javascript/index.js b/document_root/javascript/index.js
index e0c48b7823f229998927e87cdd3b7c7a855144d5..15cabed1f6951885f9448684d8bdac0fd994d7bf 100644
--- a/document_root/javascript/index.js
+++ b/document_root/javascript/index.js
@@ -45,3 +45,23 @@ function getElementsByClass(searchClass,node,tag) {
         return classElements;
 }
 //end borrowed code
+
+
+function loadXMLDoc(url, handler_function)
+{
+    // branch for native XMLHttpRequest object
+    if (window.XMLHttpRequest) {
+        req = new XMLHttpRequest();
+        eval( 'req.onreadystatechange = ' + handler_function + ';' );
+        req.open("GET", url, true);
+        req.send(null);
+    // branch for IE/Windows ActiveX version
+    } else if (window.ActiveXObject) {
+        req = new ActiveXObject("Microsoft.XMLHTTP");
+        if (req) {
+            eval( 'req.onreadystatechange = ' + handler_function +';' );
+            req.open("GET", url, true);
+            req.send();
+        }
+    }
+}
\ No newline at end of file