public function execute(&$params) { $workflowId = $this->parseOption('workflowId', $params); $stageNumber = $this->parseOption('stageNumber', $params); $model = $params['model']; $type = lcfirst(X2Model::getModuleName(get_class($model))); $modelId = $model->id; $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); $message = ''; if (Workflow::validateAction('start', $workflowStatus, $stageNumber, '', $message)) { list($started, $workflowStatus) = Workflow::startStage($workflowId, $stageNumber, $model, $workflowStatus); assert($started); return array(true, Yii::t('studio', 'Stage "{stageName}" started for {recordName}', array('{stageName}' => $workflowStatus['stages'][$stageNumber]['name'], '{recordName}' => $model->getLink()))); } else { return array(false, $message); } }
echo Yii::t('workflow', 'Workflow'); ?> </td> <td colspan="3" id="workflow"> <div class="detail-field" style="width:170px; text-align:center;margin-bottom:5px;" onclick="showField($('#workflow').get(),false);"><?php echo $workflowList[$currentWorkflow]; ?> </div> <div class="detail-form" style="width:170px; text-align:center;margin-bottom:5px;"> <?php echo CHtml::dropDownList('workflowId', $currentWorkflow, $workflowList, array('ajax' => array('type' => 'GET', 'url' => CHtml::normalizeUrl(array('workflow/getWorkflow', 'modelId' => $model->id, 'type' => 'quotes')), 'update' => '#workflow-diagram'))); ?> </div> <div id="workflow-diagram"> <?php $workflowStatus = Workflow::getWorkflowStatus($currentWorkflow, $model->id, 'quotes'); // true = include dropdowns echo Workflow::renderWorkflow($workflowStatus); ?> </div></td> </tr> <tr> <td class="label"> <?php echo $model->getAttributeLabel('description'); ?> </td> <td colspan="3" class="text-field" id="description" onclick="showField(this,true)"><div class="spacer"></div> <div class="detail-field"><?php echo $this->convertUrls($model->description); // replace any CR or LF characters with <br />, maximum of 2 in a row
/** * Used to check workflow status condition * @param Array $condition * @param Array $params * @return bool true for success, false otherwise */ public static function checkWorkflowStatusCondition($condition, &$params) { if (!isset($params['model']) || !isset($condition['workflowId']) || !isset($condition['stageNumber']) || !isset($condition['stageState'])) { return false; } $model = $params['model']; $workflowId = $condition['workflowId']; $stageNumber = $condition['stageNumber']; $stageState = $condition['stageState']; $modelId = $model->id; $type = lcfirst(X2Model::getModuleName(get_class($model))); $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); $stages = $workflowStatus['stages']; if (!isset($workflowStatus['stages'][$stageNumber])) { return false; } $stage = $workflowStatus['stages'][$stageNumber]; $passed = false; switch ($stageState) { case 'completed': $passed = Workflow::isCompleted($workflowStatus, $stageNumber); break; case 'started': $passed = Workflow::isStarted($workflowStatus, $stageNumber); break; case 'notCompleted': $passed = !Workflow::isCompleted($workflowStatus, $stageNumber); break; case 'notStarted': $passed = !Workflow::isStarted($workflowStatus, $stageNumber); break; default: return false; } return $passed; }
private function getDragAndDropViewParams($id, $users = '') { $model = $this->loadModel($id); $modelType = isset($_GET['modelType']) ? self::parseModelType($_GET['modelType']) : ''; $dateRange = self::getDateRange(); $expectedCloseDateDateRange = self::getDateRange('expectedCloseDateStart', 'expectedCloseDateEnd', 'expectedCloseDateRange'); $memberListContainerSelectors = array(); $stageValues = Workflow::getStageValues($model, $users, $modelType, $dateRange, $expectedCloseDateDateRange); $stageCount = count($model->stages); for ($i = 1; $i <= $stageCount; $i++) { $memberListContainerSelectors[] = '#workflow-stage-' . $i . ' .items'; } $workflowStatus = Workflow::getWorkflowStatus($id); $stagePermissions = Workflow::getStagePermissions($workflowStatus); $stagesWhichRequireComments = Workflow::getStageCommentRequirements($workflowStatus); $stageNames = Workflow::getStageNames($workflowStatus); $colors = $model->getWorkflowStageColors($stageCount, true); return array('model' => $model, 'modelType' => $modelType, 'dateRange' => $dateRange, 'expectedCloseDateDateRange' => $expectedCloseDateDateRange, 'users' => $users, 'colors' => $colors, 'listItemColors' => Workflow::getPipelineListItemColors($colors), 'memberListContainerSelectors' => $memberListContainerSelectors, 'stagePermissions' => $stagePermissions, 'stagesWhichRequireComments' => $stagesWhichRequireComments, 'stageNames' => $stageNames, 'stageValues' => $stageValues); }
/** * Uncompletes a stage (if completed) or unstarts it (if started). * @param $unstarts bool If false, will not attempt to unstart an ongoing stage */ public static function revertStage($workflowId, $stageNumber, $model, $unstart = true, $workflowStatus = null) { //AuxLib::debugLogR ('reverting stage '.$stageNumber); $modelId = $model->id; $type = lcfirst(X2Model::getModuleName(get_class($model))); if (!$workflowStatus) { $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); } $stageCount = count($workflowStatus['stages']); $reverted = false; // if stage has been started or completed if ($model !== null && self::isStarted($workflowStatus, $stageNumber)) { // find selected stage (and duplicates) $actions = X2Model::model('Actions')->findAllByAttributes(array('associationId' => $modelId, 'associationType' => $type, 'type' => 'workflow', 'workflowId' => $workflowId, 'stageNumber' => $stageNumber), new CDbCriteria(array('order' => 'createDate DESC'))); // if there is more than 1 action for this stage, if (count($actions) > 1) { // delete all but the most recent one for ($i = 1; $i < count($actions); $i++) { $actions[$i]->delete(); } } // the stage is complete, so just set it to 'started' if (self::isCompleted($workflowStatus, $stageNumber) && self::canUncomplete($workflowStatus, $stageNumber)) { //AuxLib::debugLogR ('uncompleting stage '.$stageNumber); $actions[0]->setScenario('workflow'); // don't genererate normal action changelog/triggers/events $actions[0]->disableBehavior('changelog'); $actions[0]->disableBehavior('tags'); // no tags up in here $actions[0]->complete = 'No'; $actions[0]->completeDate = null; $actions[0]->completedBy = ''; // original completion note no longer applies $actions[0]->actionDescription = ''; $actions[0]->save(); self::updateWorkflowChangelog($actions[0], 'revert', $model); X2Flow::trigger('WorkflowRevertStageTrigger', array('workflow' => $actions[0]->workflow, 'model' => $model, 'workflowId' => $actions[0]->workflow->id, 'stageNumber' => $stageNumber)); // delete all incomplete stages after this one // X2Model::model('Actions')->deleteAll(new CDbCriteria( // array('condition'=>"associationId=$modelId AND associationType='$type' AND type='workflow' AND workflowId=$workflowId AND stageNumber > $stageNumber AND (completeDate IS NULL OR completeDate=0)") // )); } else { if ($unstart) { // the stage is already incomplete, so delete it and all subsequent stages $subsequentActions = X2Model::model('Actions')->findAll(new CDbCriteria(array('condition' => "associationId={$modelId} AND associationType='{$type}' " . "AND type='workflow' AND workflowId={$workflowId} " . "AND stageNumber >= {$stageNumber}"))); foreach ($subsequentActions as &$action) { self::updateWorkflowChangelog($action, 'revert', $model); X2Flow::trigger('WorkflowRevertStageTrigger', array('workflow' => $action->workflow, 'model' => $model, 'workflowId' => $action->workflow->id, 'stageNumber' => $action->stageNumber)); $action->delete(); } } } $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); $reverted = true; } //AuxLib::debugLogR ((int) $reverted); return array($reverted, $workflowStatus); }
********************************************************************************/ Yii::app()->clientScript->registerScript('getWorkflowStage', "\n\nfunction getStageMembers(stage) {\n\t\$.ajax({\n\t\turl: '" . CHtml::normalizeUrl(array('/workflow/default/getStageMembers')) . "',\n\t\ttype: 'GET',\n\t\tdata: 'workflowId=" . $model->id . "&stage='+stage+'&modelId=" . $model->id . "&type=contacts',\n\t\tsuccess: function(response) {\n\t\t\tif(response!='')\n\t\t\t\t\$('#workflow-gridview').html(response);\n\t\t}\n\t});\n}\n", CClientScript::POS_HEAD); $isAdmin = Yii::app()->user->getName() == 'admin'; $this->menu = array(array('label' => Yii::t('workflow', 'All Workflows'), 'url' => array('index')), array('label' => Yii::t('app', 'Create'), 'url' => array('create'), 'visible' => $isAdmin), array('label' => Yii::t('app', 'View')), array('label' => Yii::t('app', 'Update'), 'url' => array('update', 'id' => $model->id), 'visible' => $isAdmin), array('label' => Yii::t('app', 'Delete'), 'url' => '#', 'linkOptions' => array('submit' => array('delete', 'id' => $model->id), 'confirm' => Yii::t('app', 'Are you sure you want to delete this item?')), 'visible' => $isAdmin)); ?> <h2><?php echo Yii::t('workflow', 'Workflow:'); ?> <b><?php echo $model->name; ?> </b></h2> <div style="clear:both;overflow:auto;margin-bottom:10px;"> <?php $workflowStatus = Workflow::getWorkflowStatus($model->id); // true = include dropdowns echo Workflow::renderWorkflowStats($workflowStatus); ?> </div> <div id="workflow-gridview"> <?php if (isset($viewStage)) { echo Yii::app()->controller->actionGetStageMembers($model->id, $viewStage); } else { $this->widget('zii.widgets.grid.CGridView', array('baseScriptUrl' => Yii::app()->request->baseUrl . '/themes/' . Yii::app()->theme->name . '/css/gridview', 'template' => '{items}{pager}', 'dataProvider' => CActiveRecord::model('WorkflowStage')->search($model->id), 'columns' => array(array('name' => 'stageNumber', 'header' => '#', 'headerHtmlOptions' => array('style' => 'width:8%;')), array('name' => 'name', 'type' => 'raw'), array('name' => 'requirePrevious', 'value' => 'Yii::t("app",($data->requirePrevious? "Yes" : "No"))', 'type' => 'raw', 'headerHtmlOptions' => array('style' => 'width:15%;')), array('name' => 'requireComment', 'value' => 'Yii::t("app",($data->requireComment? "Yes" : "No"))', 'type' => 'raw', 'headerHtmlOptions' => array('style' => 'width:15%;')), array('name' => 'conversionRate', 'headerHtmlOptions' => array('style' => 'width:15%;')), array('name' => 'value', 'headerHtmlOptions' => array('style' => 'width:15%;'))))); } ?> </div>
/** * Tests a method in WorkflowController which belongs in the Workflow model class */ public function testGetStageMemberDataProvider() { $workflow = $this->workflows('workflow2'); $workflowStatus = Workflow::getWorkflowStatus($workflow->id); $this->assertDataProviderCountMatchesStageCount($workflow, $workflowStatus, 1); $this->assertDataProviderCountMatchesStageCount($workflow, $workflowStatus, 4); // make record invisible $action = Actions::model()->findByAttributes(array('workflowId' => $workflow->id, 'complete' => 'No', 'stageNumber' => 8)); $record = X2Model::getModelOfTypeWithId($action->associationType, $action->associationId); $record->visibility = 0; $record->assignedTo = 'admin'; $this->assertSaves($record); $counts = $this->assertDataProviderCountMatchesStageCount($workflow, $workflowStatus, 4); $this->assertEquals(1, $counts[3]); TestingAuxLib::suLogin('testuser'); $counts = $this->assertDataProviderCountMatchesStageCount($workflow, $workflowStatus, 4); $this->assertEquals(0, $counts[3]); $record->assignedTo = 'testuser'; $this->assertSaves($record); $counts = $this->assertDataProviderCountMatchesStageCount($workflow, $workflowStatus, 4); $this->assertEquals(1, $counts[3]); }
</form> <?php $this->endWidget('zii.widgets.jui.CJuiDialog'); ?> <?php // dialog to contain Workflow Stage Details $this->widget('zii.widgets.jui.CJuiDialog', array('id' => 'workflowStageDetails', 'options' => array('title' => Yii::t('workflow', 'Comment Required'), 'autoOpen' => false, 'resizable' => false, 'modal' => false, 'show' => 'fade', 'hide' => 'fade'))); // $this->endWidget('zii.widgets.jui.CJuiDialog'); $workflowList = Workflow::getList(); ?> <div class="form"> <div class="row" style="text-align:center;"><b><?php echo Yii::t('workflow', 'Workflow'); ?> </b> <?php echo CHtml::dropDownList('workflowId', $currentWorkflow, $workflowList, array('ajax' => array('type' => 'GET', 'url' => CHtml::normalizeUrl(array('/workflow/default/getWorkflow', 'modelId' => $model->id, 'type' => $modelName)), 'update' => '#workflow-diagram', 'data' => array('workflowId' => 'js:$(this).val()')), 'id' => 'workflowSelector')); ?> </div> <div class="row"> <div id="workflow-diagram"> <?php $workflowStatus = Workflow::getWorkflowStatus($currentWorkflow, $model->id, $modelName); // true = include dropdowns echo Workflow::renderWorkflow($workflowStatus); ?> </div> </div> </div>
public function actionRevertStage($workflowId, $stageNumber, $modelId, $type) { if (is_numeric($workflowId) && is_numeric($stageNumber) && is_numeric($modelId) && ctype_alpha($type)) { $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); $stageCount = count($workflowStatus) - 1; if (isset($workflowStatus[$stageNumber]['createDate'])) { // find selected stage (and duplicates) $actions = CActiveRecord::model('Actions')->findAllByAttributes(array('associationId' => $modelId, 'associationType' => $type, 'type' => 'workflow', 'workflowId' => $workflowId, 'stageNumber' => $stageNumber), new CDbCriteria(array('order' => 'createDate DESC'))); if (count($actions) > 1) { // if there is more than 1 action for this stage, for ($i = 1; $i < count($actions); $i++) { // delete all but the most recent one $actions[$i]->delete(); } } if ($workflowStatus[$stageNumber]['complete']) { // the stage is complete, so just set it to 'started' $actions[0]->setScenario('workflow'); $actions[0]->complete = 'No'; $actions[0]->completeDate = null; $actions[0]->completedBy = ''; $actions[0]->actionDescription = ''; // original completion note no longer applies $actions[0]->save(); $this->updateWorkflowChangelog($actions[0], 'revert'); // delete all incomplete stages after this one // CActiveRecord::model('Actions')->deleteAll(new CDbCriteria( // array('condition'=>"associationId=$modelId AND associationType='$type' AND type='workflow' AND workflowId=$workflowId AND stageNumber > $stageNumber AND (completeDate IS NULL OR completeDate=0)") // )); } else { // the stage is already incomplete, so delete it and all subsequent stages $subsequentActions = CActiveRecord::model('Actions')->findAll(new CDbCriteria(array('condition' => "associationId={$modelId} AND associationType='{$type}' AND type='workflow' AND workflowId={$workflowId} AND stageNumber >= {$stageNumber}"))); foreach ($subsequentActions as &$action) { $this->updateWorkflowChangelog($action, 'revert'); $action->delete(); } } $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); } echo Workflow::renderWorkflow($workflowStatus); } }
echo Yii::t('workflow', 'Please summarize how this stage was completed.'); ?> </div> <div class="row"> <?php echo CHtml::textArea('workflowComment', '', array('style' => 'width:260px;height:80px;')); echo CHtml::hiddenField('workflowCommentWorkflowId', '', array('id' => 'workflowCommentWorkflowId')); echo CHtml::hiddenField('workflowCommentStageNumber', '', array('id' => 'workflowCommentStageNumber')); ?> </div> </form> </div> <!-- dialog to contain Workflow Stage Details--> <div id="workflowStageDetails"></div> <div class="row"> <div id="workflow-diagram"> <?php // true = include dropdowns $workflowStatus = Workflow::getWorkflowStatus($currentWorkflow, $model->id, X2Model::getAssociationType(get_class($model))); //echo Workflow::renderWorkflow($workflowStatus); if (sizeof($workflowStatus['stages']) > 1) { $workflow = Workflow::model()->findByPk($workflowStatus['id']); $colors = $workflow->getWorkflowStageColors(sizeof($workflowStatus['stages'])); Yii::app()->controller->renderPartial('application.modules.workflow.views.workflow._inlineFunnel', array('workflowStatus' => $workflowStatus, 'stageCount' => sizeof($workflowStatus['stages']), 'colors' => $colors)); } ?> </div> </div>
public function actionTempImportWorkflow() { $file = "workflowData.csv"; $fp = fopen($file, 'r+'); $meta = fgetcsv($fp); $workflowList = array('1' => 'Contacted', '2' => 'Appointment Set', '3' => 'Interview Conducted', '4' => 'Essay/Assessment Completed', '5' => 'Transcript Request Form', '6' => 'Unofficial Transcript', '7' => 'Application Completed', '8' => 'Recommendation', '9' => 'Notify FA/Prelim', '10' => 'FAFSA Completed', '11' => 'Transcribe Application', '12' => 'Enrolled', '13' => 'FA Complete', '14' => 'Official Transcript', '15' => 'Started', '16' => '3 2 1 Checklist', '17' => 'Services Lead Card', '18' => 'Q Drive'); while ($arr = fgetcsv($fp)) { $attributes = array_combine($meta, $arr); $record = Contacts::model()->findByPk($attributes['id']); if (isset($record)) { $modelId = $record->id; $type = "contacts"; $workflowId = 1; foreach ($workflowList as $stageNumber => $stage) { if (isset($attributes[$stage]) && $attributes[$stage] != "") { if (is_numeric($workflowId) && is_numeric($stageNumber) && is_numeric($modelId) && ctype_alpha($type)) { $workflowStatus = Workflow::getWorkflowStatus($workflowId, $modelId, $type); if ((!isset($workflowStatus[$stageNumber]['createDate']) || $workflowStatus[$stageNumber]['createDate'] == 0) && (!isset($workflowStatus[$stageNumber]['completeDate']) || $workflowStatus[$stageNumber]['completeDate'] == 0)) { $action = new Actions('workflow'); $action->associationId = $modelId; $action->associationType = $type; $action->assignedTo = 'Anyone'; $action->updatedBy = 'admin'; $action->complete = 'Yes'; $action->completeDate = strtotime($attributes[$stage]); $action->completedBy = 'admin'; $action->type = 'workflow'; $action->visibility = 1; $action->createDate = strtotime($attributes[$stage]); $action->lastUpdated = time(); $action->workflowId = (int) $workflowId; $action->stageNumber = (int) $stageNumber; // $action->actionDescription = ''; $action->save(); // echo var_dump($action->getErrors()); // echo var_dump($action->attributes); // echo var_dump($action->save()); // echo'derp'; } } } } } } }
private function getDragAndDropViewParams($id, $users = '') { $model = $this->loadModel($id); if (isset($_GET['modelType'])) { $modelType = $_GET['modelType']; } elseif (!empty($model->financialModel)) { if (X2Model::getModelName($model->financialModel)) { $modelType = $model->financialModel; } else { $modelType = 'contacts'; } } else { $modelType = 'contacts'; } $dateRange = self::getDateRange(); $memberListContainerSelectors = array(); $stageCount = count($model->stages); for ($i = 1; $i <= $stageCount; $i++) { $memberListContainerSelectors[] = '#workflow-stage-' . $i . ' .items'; } $workflowStatus = Workflow::getWorkflowStatus($id); $stagePermissions = Workflow::getStagePermissions($workflowStatus); $stagesWhichRequireComments = Workflow::getStageCommentRequirements($workflowStatus); $stageNames = Workflow::getStageNames($workflowStatus); $colors = $model->getWorkflowStageColors($stageCount, true); $stageCounts = Workflow::getStageCounts($workflowStatus, $dateRange, $users, $modelType); $stageValues = Workflow::getStageValues($workflowStatus, $dateRange, $users, $modelType); return array('model' => $model, 'modelType' => $modelType, 'dateRange' => $dateRange, 'users' => $users, 'colors' => $colors, 'listItemColors' => Workflow::getPipelineListItemColors($colors), 'memberListContainerSelectors' => $memberListContainerSelectors, 'stagePermissions' => $stagePermissions, 'stagesWhichRequireComments' => $stagesWhichRequireComments, 'stageNames' => $stageNames, 'stageCounts' => $stageCounts, 'stageValues' => $stageValues); }