public function testRun()
 {
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('WorkflowsTest2Module');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     //Add action that is missing required owner
     $action = new ActionForWorkflowForm('WorkflowModelTestItem2', Workflow::TYPE_ON_SAVE);
     $action->type = ActionForWorkflowForm::TYPE_CREATE;
     $action->relation = 'hasMany2';
     $attributes = array('string' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'jason'), 'lastName' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'jason'));
     $action->setAttributes(array(ActionForWorkflowForm::ACTION_ATTRIBUTES => $attributes));
     $workflow->addAction($action);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $this->assertEquals(0, count(Notification::getAll()));
     $job = new WorkflowValidityCheckJob();
     $this->assertTrue($job->run());
     $notifications = Notification::getAll();
     $this->assertEquals(1, count($notifications));
 }
 /**
  * @param WorkflowMessageInQueue $workflowMessageInQueue
  * @param RedBeanModel $model
  */
 protected function processWorkflowMessageInQueue(WorkflowMessageInQueue $workflowMessageInQueue, RedBeanModel $model)
 {
     $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($workflowMessageInQueue->savedWorkflow);
     if (!$workflow->getIsActive()) {
         return;
     }
     WorkflowEmailMessagesUtil::processOnWorkflowMessageInQueueJob($workflow, $model, self::resolveTriggeredByUser($workflowMessageInQueue));
 }
    protected function makeSampleOnSaveWorkflow()
    {
        Yii::app()->user->userModel = User::getByUsername('super');
        $emailTemplate = new EmailTemplate();
        $emailTemplate->type = EmailTemplate::TYPE_WORKFLOW;
        $emailTemplate->builtType = EmailTemplate::BUILT_TYPE_BUILDER_TEMPLATE;
        $emailTemplate->subject = 'We closed a deal';
        $emailTemplate->name = 'We closed a deal - Sample Email Template';
        $emailTemplate->textContent = 'Hello!!!
We just closed new deal, please check details: [[MODEL^URL]]
Thanks!';
        $emailTemplate->htmlContent = '<p>Hello!!!</p>
<p>We just closed new deal, please check details: [[MODEL^URL]]</p>
<p>Thanks!</p>';
        $emailTemplate->modelClassName = 'Opportunity';
        $emailTemplate->isDraft = false;
        $emailTemplate->save();
        $trigger = new TriggerForWorkflowForm('OpportunitiesModule', 'Opportunity', Workflow::TYPE_ON_SAVE);
        $trigger->attributeIndexOrDerivedType = 'stage';
        $trigger->value = 'Closed Won';
        $trigger->operator = OperatorRules::TYPE_BECOMES;
        $trigger->relationFilter = TriggerForWorkflowForm::RELATION_FILTER_ANY;
        $message = new EmailMessageForWorkflowForm('Opportunity', Workflow::TYPE_ON_SAVE);
        $message->sendAfterDurationInterval = 0;
        $message->sendAfterDurationType = TimeDurationUtil::DURATION_TYPE_MINUTE;
        $message->emailTemplateId = $emailTemplate->id;
        $message->sendFromType = EmailMessageForWorkflowForm::SEND_FROM_TYPE_DEFAULT;
        $recipients = array(array('type' => WorkflowEmailMessageRecipientForm::TYPE_STATIC_ADDRESS, 'audienceType' => EmailMessageRecipient::TYPE_TO, 'toName' => 'The Sales Team', 'toAddress' => '*****@*****.**'));
        $message->setAttributes(array(EmailMessageForWorkflowForm::EMAIL_MESSAGE_RECIPIENTS => $recipients));
        $workflow = new Workflow();
        $workflow->setDescription('This will send an email to recipients that you choose when you close a deal!');
        $workflow->setIsActive(false);
        $workflow->setOrder(2);
        $workflow->setModuleClassName('OpportunitiesModule');
        $workflow->setName('Closed won Opportunity alert');
        $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
        $workflow->setType(Workflow::TYPE_ON_SAVE);
        $workflow->setTriggersStructure('1');
        $workflow->addTrigger($trigger);
        $workflow->addEmailMessage($message);
        $savedWorkflow = new SavedWorkflow();
        SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
        $savedWorkflow->save();
    }
 /**
  * A test to show that the modifiedByUser works ok as a trigger with 'equals' on a newly created model.
  * @see testProcessBeforeSaveOnCreatedByUserEquals
  */
 public function testProcessBeforeSaveOnModifiedByUserEquals()
 {
     Yii::app()->user->userModel = User::getByUsername('super');
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('AccountsModule');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     //Add trigger
     $trigger = new TriggerForWorkflowForm('AccountsTestModule', 'Account', $workflow->getType());
     $trigger->attributeIndexOrDerivedType = 'modifiedByUser';
     $trigger->value = Yii::app()->user->userModel->id;
     $trigger->operator = 'equals';
     $workflow->addTrigger($trigger);
     //Add action
     $action = new ActionForWorkflowForm('Account', Workflow::TYPE_ON_SAVE);
     $action->type = ActionForWorkflowForm::TYPE_UPDATE_SELF;
     $attributes = array('name' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'jason'));
     $action->setAttributes(array(ActionForWorkflowForm::ACTION_ATTRIBUTES => $attributes));
     $workflow->addAction($action);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     //Confirm that the workflow processes and the attribute gets updated
     $model = new Account();
     $model->name = 'aValue';
     $this->assertTrue($model->save());
     $this->assertEquals('jason', $model->name);
 }
 /**
  * @param ByTimeWorkflowInQueue $byTimeWorkflowInQueue
  * @param RedBeanModel $model
  * @throws FailedToSaveModelException
  */
 protected function processByTimeWorkflowInQueue(ByTimeWorkflowInQueue $byTimeWorkflowInQueue, RedBeanModel $model)
 {
     $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($byTimeWorkflowInQueue->savedWorkflow);
     if (!$workflow->getIsActive()) {
         return;
     }
     $workflow->setTimeTriggerRequireChangeToProcessToFalse();
     if (WorkflowTriggersUtil::areTriggersTrueOnByTimeWorkflowQueueJob($workflow, $model)) {
         WorkflowActionsUtil::processOnByTimeWorkflowInQueueJob($workflow, $model, Yii::app()->user->userModel);
         WorkflowEmailMessagesUtil::processAfterSave($workflow, $model, Yii::app()->user->userModel);
         if ($model->isModified()) {
             $saved = $model->save();
             if (!$saved) {
                 throw new FailedToSaveModelException();
             }
         }
     }
 }
 protected function resolveSavedWorkflowAndWorkflowByPostData(array $postData, &$savedWorkflow, &$workflow, $type, $id = null, $isBeingCopied = false)
 {
     if ($id == null) {
         $this->resolveCanCurrentUserAccessWorkflows();
         $savedWorkflow = new SavedWorkflow();
         $workflow = new Workflow();
         $workflow->setType($type);
     } elseif ($isBeingCopied) {
         $savedWorkflow = new SavedWorkflow();
         $oldWorkflow = SavedWorkflow::getById(intval($id));
         ControllerSecurityUtil::resolveAccessCanCurrentUserReadModel($oldWorkflow);
         ZurmoCopyModelUtil::copy($oldWorkflow, $savedWorkflow);
         $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
     } else {
         $savedWorkflow = SavedWorkflow::getById(intval($id));
         ControllerSecurityUtil::resolveAccessCanCurrentUserWriteModel($savedWorkflow);
         $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
     }
     DataToWorkflowUtil::resolveWorkflowByWizardPostData($workflow, $postData, WorkflowToWizardFormAdapter::getFormClassNameByType($type));
 }
 /**
  * @depends testResolveAfterSaveByModel
  */
 public function testResolveAfterSaveByModelForByTime()
 {
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('WorkflowsTestModule');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_BY_TIME);
     $workflow->setTriggersStructure('1');
     $workflow->setIsActive(true);
     //Add time trigger
     $trigger = new TimeTriggerForWorkflowForm('WorkflowsTestModule', 'WorkflowModelTestItem', $workflow->getType());
     $trigger->attributeIndexOrDerivedType = 'date';
     $trigger->durationSeconds = '500';
     $trigger->valueType = 'Is Time For';
     $workflow->setTimeTrigger($trigger);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $workflow->setId($savedWorkflow->id);
     //set Id back.
     $model = new WorkflowModelTestItem();
     $model->lastName = 'something';
     $model->string = 'aValue';
     $model->date = '2013-03-03';
     $saved = $model->save();
     $this->assertTrue($saved);
     $model->addWorkflowToProcessAfterSave($workflow);
     $this->assertEquals(0, count(ByTimeWorkflowInQueue::getAll()));
     SavedWorkflowsUtil::resolveAfterSaveByModel($model, Yii::app()->user->userModel);
     $this->assertEquals(1, count(ByTimeWorkflowInQueue::getAll()));
 }
 public function testWorkflowDoesLinkRelatedModelWhenPermissionsIsSetToOwner()
 {
     $super = $this->logoutCurrentUserLoginNewUserAndGetByUsername('super');
     $contactStates = ContactState::getAll();
     $this->assertEquals(0, Contact::getCount());
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('AccountsModule');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     //Add action
     $action = new ActionForWorkflowForm('Account', Workflow::TYPE_ON_SAVE);
     $action->type = ActionForWorkflowForm::TYPE_CREATE;
     $action->relation = 'contacts';
     $attributes = array('lastName' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'smith'), 'firstName' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'john'), 'owner__User' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => Yii::app()->user->userModel->id), 'state' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => $contactStates[0]->id));
     $action->setAttributes(array(ActionForWorkflowForm::ACTION_ATTRIBUTES => $attributes));
     $workflow->addAction($action);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $account = new Account();
     $account->name = 'myTestAccount';
     $account->owner = $super;
     $account->save();
     RedBeanModel::forgetAll();
     $contacts = Contact::getAll();
     $this->assertCount(1, $contacts);
     $this->assertEquals('myTestAccount', $contacts[0]->account->name);
     $this->assertEquals('john smith', strval($account->contacts[0]));
     $this->assertTrue($account->contacts[0]->id > 0);
 }
 public function testProcessAfterSaveWhenSendIsInFuture()
 {
     $this->assertEquals(0, count(WorkflowMessageInQueue::getAll()));
     $workflow = new Workflow();
     $workflow->setId(self::$savedWorkflow->id);
     $workflow->type = Workflow::TYPE_ON_SAVE;
     $emailMessageForm = new EmailMessageForWorkflowForm('WorkflowModelTestItem', Workflow::TYPE_ON_SAVE);
     $emailMessageForm->sendAfterDurationSeconds = 86400;
     $recipients = array(array('type' => WorkflowEmailMessageRecipientForm::TYPE_DYNAMIC_TRIGGERED_MODEL_USER, 'audienceType' => EmailMessageRecipient::TYPE_TO, 'dynamicUserType' => DynamicTriggeredModelUserWorkflowEmailMessageRecipientForm::DYNAMIC_USER_TYPE_CREATED_BY_USER));
     $emailMessageForm->setAttributes(array(EmailMessageForWorkflowForm::EMAIL_MESSAGE_RECIPIENTS => $recipients));
     $workflow->addEmailMessage($emailMessageForm);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'lastName';
     $model->string = 'string';
     $this->assertTrue($model->save());
     $compareDateTime = DateTimeUtil::convertTimestampToDbFormatDateTime(time() + 86400);
     WorkflowEmailMessagesUtil::processAfterSave($workflow, $model, Yii::app()->user->userModel);
     $workflowMessageInQueues = WorkflowMessageInQueue::getAll();
     $this->assertEquals(1, count($workflowMessageInQueues));
     $this->assertTrue($workflowMessageInQueues[0]->savedWorkflow->isSame(self::$savedWorkflow));
     $this->assertTrue($workflowMessageInQueues[0]->triggeredByUser->isSame(Yii::app()->user->userModel));
     $this->assertEquals($model->getClassId('Item'), $workflowMessageInQueues[0]->modelItem->getClassId('Item'));
     $this->assertEquals('WorkflowModelTestItem', $workflowMessageInQueues[0]->modelClassName);
     $this->assertEquals($compareDateTime, $workflowMessageInQueues[0]->processDateTime);
     $emailMessageData = SavedWorkflowToWorkflowAdapter::makeArrayFromEmailMessageForWorkflowFormAttributesData(array($emailMessageForm));
     $this->assertEquals(serialize($emailMessageData), $workflowMessageInQueues[0]->serializedData);
     $this->assertTrue($workflowMessageInQueues[0]->delete());
 }
 /**
  * @depends testProcessBeforeSave
  */
 public function testProcessAfterSave()
 {
     //Save everyone group
     $group = Group::getByName(Group::EVERYONE_GROUP_NAME);
     $this->assertTrue($group->save());
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('WorkflowsTestModule');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     $workflow->setIsActive(true);
     //Add trigger
     $trigger = new TriggerForWorkflowForm('WorkflowsTestModule', 'WorkflowModelTestItem', $workflow->getType());
     $trigger->attributeIndexOrDerivedType = 'string';
     $trigger->value = 'aValue';
     $trigger->operator = 'equals';
     $workflow->addTrigger($trigger);
     //Add action
     $action = new ActionForWorkflowForm('WorkflowModelTestItem', Workflow::TYPE_ON_SAVE);
     $action->type = ActionForWorkflowForm::TYPE_CREATE;
     $action->relation = 'hasOne';
     $attributes = array('name' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'jason'), 'permissions' => array('shouldSetValue' => '1', 'type' => ExplicitReadWriteModelPermissionsWorkflowActionAttributeForm::TYPE_DYNAMIC_EVERYONE_GROUP));
     $action->setAttributes(array(ActionForWorkflowForm::ACTION_ATTRIBUTES => $attributes));
     $workflow->addAction($action);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $model = new WorkflowModelTestItem();
     $model->string = 'aValue';
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $this->assertEquals(0, WorkflowModelTestItem2::getCount());
     WorkflowActionsUtil::processAfterSave($workflow, $model, Yii::app()->user->userModel);
     $workflowModelTestItem2s = WorkflowModelTestItem2::getAll();
     $this->assertEquals(1, count($workflowModelTestItem2s));
     //Confirm permissions are on the everyone group
     $explicitReadWriteModelPermissions = ExplicitReadWriteModelPermissionsUtil::makeBySecurableItem($workflowModelTestItem2s[0]);
     $this->assertEquals(1, $explicitReadWriteModelPermissions->getReadWritePermitablesCount());
     $readWritePermitables = $explicitReadWriteModelPermissions->getReadWritePermitables();
     $everyoneGroup = Group::getByName(Group::EVERYONE_GROUP_NAME);
     $this->assertTrue(isset($readWritePermitables[$everyoneGroup->getClassId('Permitable')]));
 }
 /**
  * Given a RedBeanModel, query workflow rules and process any beforeSave triggers for either on-save or
  * by-time workflows.  Called from @see WokflowsObserver->processWorkflowBeforeSave
  * @param Item $model
  * @param User $triggeredByUser
  * @throws NotSupportedException if the workflow type is not valid
  */
 public static function resolveBeforeSaveByModel(Item $model, User $triggeredByUser)
 {
     $savedWorkflows = SavedWorkflow::getActiveByModuleClassNameAndIsNewModel($model::getModuleClassName(), $model->getIsNewModel());
     foreach ($savedWorkflows as $savedWorkflow) {
         $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
         if (WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model)) {
             if ($workflow->getType() == Workflow::TYPE_BY_TIME) {
                 $model->addWorkflowToProcessAfterSave($workflow);
             } elseif ($workflow->getType() == Workflow::TYPE_ON_SAVE) {
                 WorkflowActionsUtil::processBeforeSave($workflow, $model, $triggeredByUser);
                 $model->addWorkflowToProcessAfterSave($workflow);
             } else {
                 throw new NotSupportedException();
             }
         }
     }
 }
 /**
  * @depends testResolveWorkflowToSavedWorkflow
  */
 public function testMakeWorkflowBySavedWorkflow()
 {
     $savedWorkflows = SavedWorkflow::getAll();
     $this->assertEquals(1, count($savedWorkflows));
     $savedWorkflow = $savedWorkflows[0];
     $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
     $triggers = $workflow->getTriggers();
     $this->assertEquals('WorkflowsTestModule', $workflow->getModuleClassName());
     $this->assertEquals('myFirstWorkflow', $workflow->getName());
     $this->assertEquals('aDescription', $workflow->getDescription());
     $this->assertTrue($workflow->getIsActive());
     $this->assertEquals(5, $workflow->getOrder());
     $this->assertEquals(Workflow::TRIGGER_ON_NEW, $workflow->getTriggerOn());
     $this->assertEquals(Workflow::TYPE_ON_SAVE, $workflow->getType());
     $this->assertEquals('1 and 2 or 3 or 4', $workflow->getTriggersStructure());
     $this->assertCount(4, $triggers);
 }
 /**
  * Tests that a bug involving creating a required custom picklist on projects causes the workflow
  * to break when creating a task
  */
 public function testProcessWorkflowForTaskWhenProjectAsARequiredCustomPicklist()
 {
     Yii::app()->user->userModel = User::getByUsername('super');
     //Create a required picklist for projects
     ModulesSearchWithDataProviderTestHelper::createDropDownAttribute(new Project(), 'pick', true);
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('TasksModule');
     $workflow->setName('myFirstWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_BY_TIME);
     $workflow->setTriggersStructure('1');
     //Add trigger
     $trigger = new TimeTriggerForWorkflowForm('TasksModule', 'Task', $workflow->getType());
     $trigger->attributeIndexOrDerivedType = 'dueDateTime';
     $trigger->valueType = MixedDateTypesSearchFormAttributeMappingRules::TYPE_IS_TIME_FOR;
     $trigger->durationInterval = 5;
     $trigger->durationType = TimeDurationUtil::DURATION_TYPE_MONTH;
     $trigger->durationSign = TimeDurationUtil::DURATION_SIGN_NEGATIVE;
     $workflow->setTimeTrigger($trigger);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     //Confirm that the workflow processes
     $model = new Task();
     $model->name = 'aTask';
     $model->dueDateTime = DateTimeUtil::convertTimestampToDbFormatDateTime(time());
     $this->assertTrue($model->save());
 }
 public static function getWorkflowsMissingRequiredActionAttributes()
 {
     $savedWorkflows = SavedWorkflow::getAll();
     $workflows = array();
     foreach ($savedWorkflows as $savedWorkflow) {
         $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
         $missingRequired = false;
         foreach ($workflow->getActions() as $action) {
             if ($action->isModelActionVariant() && !$action->isTypeAnUpdateVariant() && $action->isMissingRequiredActionAttributes()) {
                 $missingRequired = true;
                 break;
             }
         }
         if ($missingRequired) {
             $workflows[] = $workflow;
         }
     }
     return $workflows;
 }
 public function testRunWithMissingTriggerMultiselectPicklistValue()
 {
     $this->clearNotificationsWorkflowsAndEmailMessages();
     $this->createStageValues();
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('bDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('OpportunitiesModule');
     $workflow->setName('mySecondWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     $trigger = new TriggerForWorkflowForm('OpportunitiesModule', 'Opportunity', Workflow::TYPE_ON_SAVE);
     $trigger->attributeIndexOrDerivedType = 'stage';
     $trigger->value = 'Closed Won,Negotiating';
     $trigger->operator = OperatorRules::TYPE_ONE_OF;
     $trigger->relationFilter = TriggerForWorkflowForm::RELATION_FILTER_ANY;
     $workflow->addTrigger($trigger);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $this->assertEquals(0, Notification::getCount());
     $this->assertEquals(0, EmailMessage::getCount());
     $job = new WorkflowValidityCheckJob();
     $this->assertTrue($job->run());
     $this->assertEquals(0, Notification::getCount());
     $this->assertEquals(0, EmailMessage::getCount());
     $this->clearNotificationsWorkflowsAndEmailMessages();
     $workflow = new Workflow();
     $workflow->setDescription('cDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(5);
     $workflow->setModuleClassName('OpportunitiesModule');
     $workflow->setName('mySecondWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     $trigger = new TriggerForWorkflowForm('OpportunitiesModule', 'Opportunity', Workflow::TYPE_ON_SAVE);
     $trigger->attributeIndexOrDerivedType = 'stage';
     $trigger->value = 'Closed Won,Unexisting state';
     $trigger->operator = OperatorRules::TYPE_BECOMES;
     $trigger->relationFilter = TriggerForWorkflowForm::RELATION_FILTER_ANY;
     $workflow->addTrigger($trigger);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $this->assertEquals(0, Notification::getCount());
     $this->assertEquals(0, EmailMessage::getCount());
     $job = new WorkflowValidityCheckJob();
     $this->assertTrue($job->run());
     $this->assertEquals(1, Notification::getCount());
     $this->assertEquals(1, EmailMessage::getCount());
 }
 /**
  * Check if picklist modification caused some issues with workflow triggers and if yes notify users
  * @return array
  * @throws NotSupportedException
  */
 public static function getWorkflowsWithInvalidTriggerCustomFieldValue()
 {
     $savedWorkflows = SavedWorkflow::getAll();
     $workflows = array();
     foreach ($savedWorkflows as $savedWorkflow) {
         $workflow = SavedWorkflowToWorkflowAdapter::makeWorkflowBySavedWorkflow($savedWorkflow);
         $hasInvalidCustomFieldValue = false;
         foreach ($workflow->getTriggers() as $trigger) {
             $modelClassName = $trigger->getModelClassName();
             $customFieldAttributeNames = CustomFieldUtil::getCustomFieldAttributeNames($modelClassName);
             $triggerAttributeName = $trigger->getAttribute();
             if (in_array($triggerAttributeName, $customFieldAttributeNames)) {
                 $customFieldData = CustomFieldDataModelUtil::getDataByModelClassNameAndAttributeName($modelClassName, $triggerAttributeName);
                 $allCustomFieldValues = unserialize($customFieldData->serializedData);
                 // Check with triggers that allow single value
                 if (in_array($trigger->getOperator(), array(OperatorRules::TYPE_EQUALS, OperatorRules::TYPE_DOES_NOT_EQUAL, OperatorRules::TYPE_BECOMES, OperatorRules::TYPE_WAS))) {
                     if (!in_array($trigger->value, $allCustomFieldValues)) {
                         $hasInvalidCustomFieldValue = true;
                         break;
                     }
                 } elseif (in_array($trigger->getOperator(), array(OperatorRules::TYPE_BECOMES_ONE_OF, OperatorRules::TYPE_WAS_ONE_OF, OperatorRules::TYPE_ONE_OF))) {
                     $triggerSelectedCustomFieldValues = MultiSelectDropDownSanitizerUtil::getCustomFieldValuesFromValueString($trigger->value);
                     foreach ($triggerSelectedCustomFieldValues as $triggerValue) {
                         if (!in_array($triggerValue, $allCustomFieldValues)) {
                             $hasInvalidCustomFieldValue = true;
                             break 2;
                         }
                     }
                 }
             }
         }
         if ($hasInvalidCustomFieldValue) {
             $workflows[] = $workflow;
         }
     }
     return $workflows;
 }
 /**
  * @param Workflow $workflow
  * @param EmailMessageForWorkflowForm $emailMessage
  * @param RedBeanModel $model
  * @param User $triggeredByUser
  * @throws FailedToSaveModelException
  */
 protected static function processEmailMessageAfterSave(Workflow $workflow, EmailMessageForWorkflowForm $emailMessage, RedBeanModel $model, User $triggeredByUser)
 {
     if ($emailMessage->sendAfterDurationInterval == 0) {
         $helper = new WorkflowEmailMessageProcessingHelper($emailMessage, $model, $triggeredByUser);
         $helper->process();
     } else {
         $emailMessageData = SavedWorkflowToWorkflowAdapter::makeArrayFromEmailMessageForWorkflowFormAttributesData(array($emailMessage));
         $workflowMessageInQueue = new WorkflowMessageInQueue();
         $workflowMessageInQueue->processDateTime = DateTimeUtil::convertTimestampToDbFormatDateTime($emailMessage->resolveNewTimeStampForDuration(time()));
         $workflowMessageInQueue->savedWorkflow = SavedWorkflow::getById((int) $workflow->getId());
         $workflowMessageInQueue->modelClassName = get_class($model);
         $workflowMessageInQueue->modelItem = $model;
         $workflowMessageInQueue->serializedData = serialize($emailMessageData);
         $workflowMessageInQueue->triggeredByUser = $triggeredByUser;
         $saved = $workflowMessageInQueue->save();
         if (!$saved) {
             throw new FailedToSaveModelException();
         }
     }
 }
 public function testUpdateRelatedCatalogItemOnAProductBySellPriceCriteria()
 {
     $super = User::getByUsername('super');
     $contactStates = ContactState::getAll();
     //Create workflow
     $workflow = new Workflow();
     $workflow->setDescription('aDescription');
     $workflow->setIsActive(true);
     $workflow->setOrder(1);
     $workflow->setModuleClassName('ProductsModule');
     $workflow->setName('myFirstProductWorkflow');
     $workflow->setTriggerOn(Workflow::TRIGGER_ON_NEW_AND_EXISTING);
     $workflow->setType(Workflow::TYPE_ON_SAVE);
     $workflow->setTriggersStructure('1');
     //Add Trigger
     $trigger = new TriggerForWorkflowForm('ProductsModule', 'Product', Workflow::TYPE_ON_SAVE);
     $trigger->attributeIndexOrDerivedType = 'sellPrice';
     $trigger->value = 600;
     $trigger->operator = 'greaterThanOrEqualTo';
     $workflow->addTrigger($trigger);
     //Add action
     $currencies = Currency::getAll();
     $action = new ActionForWorkflowForm('Product', Workflow::TYPE_ON_SAVE);
     $action->type = ActionForWorkflowForm::TYPE_UPDATE_RELATED;
     $action->relation = 'productTemplate';
     $attributes = array('description' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 'Set Price'), 'priceFrequency' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 2), 'listPrice' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 800, 'currencyId' => $currencies[0]->id), 'cost' => array('shouldSetValue' => '1', 'type' => WorkflowActionAttributeForm::TYPE_STATIC, 'value' => 700, 'currencyId' => $currencies[0]->id));
     $action->setAttributes(array(ActionForWorkflowForm::ACTION_ATTRIBUTES => $attributes));
     $workflow->addAction($action);
     //Create the saved Workflow
     $savedWorkflow = new SavedWorkflow();
     SavedWorkflowToWorkflowAdapter::resolveWorkflowToSavedWorkflow($workflow, $savedWorkflow);
     $saved = $savedWorkflow->save();
     $this->assertTrue($saved);
     $productTemplate = ProductTemplateTestHelper::createProductTemplateByName('superProductTemplate');
     $productTemplates = ProductTemplate::getByName('superProductTemplate');
     $product = ProductTestHelper::createProductByNameForOwner('Test Product', $super);
     $this->assertTrue($product->id > 0);
     $product->productTemplate = $productTemplates[0];
     //Change product sell price
     $product->sellPrice->value = 650;
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $product));
     $saved = $product->save();
     $this->assertTrue($saved);
     $productId = $product->id;
     $product->forget();
     $product = Product::getById($productId);
     $this->assertEquals('Set Price', $product->productTemplate->description);
     $this->assertEquals(2, $product->productTemplate->priceFrequency);
     $this->assertEquals(700, $product->productTemplate->cost->value);
     $this->assertEquals(800, $product->productTemplate->listPrice->value);
 }