/**
  * @see BaseJob::run()
  */
 public function run()
 {
     $workflowsWithInvalidActions = WorkflowActionsUtil::getWorkflowsMissingRequiredActionAttributes();
     if (count($workflowsWithInvalidActions) > 0) {
         $commonMessage = Zurmo::t('WorkflowsModule', 'As a result of a field or fields recently ' . 'becoming required, at least 1 workflow action rule will no longer work properly:');
         $message = new NotificationMessage();
         $message = $this->updateNotificationMessage($workflowsWithInvalidActions, $message, $commonMessage);
     }
     $workflowsWithInvalidTriggers = WorkflowTriggersUtil::getWorkflowsWithInvalidTriggerCustomFieldValue();
     if (count($workflowsWithInvalidTriggers) > 0) {
         if (!isset($message)) {
             $message = new NotificationMessage();
         }
         $commonMessage = Zurmo::t('WorkflowsModule', 'As a result of modifying picklist data recently, ' . 'at least 1 workflow trigger rule will no longer work properly:');
         $message = $this->updateNotificationMessage($workflowsWithInvalidTriggers, $message, $commonMessage);
     }
     if (count($workflowsWithInvalidActions) > 0 || count($workflowsWithInvalidTriggers) > 0) {
         $rules = new WorkflowValidityCheckNotificationRules();
         NotificationsUtil::submit($message, $rules);
     }
     return true;
 }
 /**
  * @depends testTriggerBeforeSaveIsEmpty
  */
 public function testTriggerBeforeSaveIsNotEmpty()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('multiDropDown', 'isNotEmpty', null);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $value = new CustomFieldValue();
     $value->value = 'd';
     $model->multiDropDown->values->add($value);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->multiDropDown->values->removeAll();
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @depends testTriggerBeforeSaveIsEmpty
  */
 public function testTriggerBeforeSaveIsNotEmpty()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerForDateOrDateTime('dateTime', 'Is Not Empty', null);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someString';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dateTime = '2007-06-03 00:02:00';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dateTime = null;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dateTime = '';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @depends testTriggerBeforeSaveHasManyNotOwnedEquals
  */
 public function testTriggerBeforeSaveManyManyNotOwnedEquals()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('hasMany1___boolean', 'equals', '1', 'WorkflowsTestModule', 'WorkflowModelTestItem3');
     $model = new WorkflowModelTestItem3();
     $relatedModel = new WorkflowModelTestItem();
     $relatedModel->lastName = 'someLastName';
     $relatedModel->string = 'someString';
     $this->assertTrue($relatedModel->save());
     $model->hasMany1->add($relatedModel);
     $model->hasMany1[0]->boolean = '1';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->hasMany1[0]->boolean = '0';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->hasMany1[0]->boolean = '1';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @param Workflow $workflow
  * @param RedBeanModel $model
  * @return bool|void
  */
 protected static function resolveTriggersAreTrueBeforeSave(Workflow $workflow, RedBeanModel $model)
 {
     if (count($workflow->getTriggers()) == 0) {
         return true;
     }
     $structureAsPHPString = WorkflowTriggersUtil::resolveStructureToPHPString($workflow->getTriggersStructure());
     $dataToEvaluate = array();
     $count = 0;
     foreach ($workflow->getTriggers() as $trigger) {
         $dataToEvaluate[$count + 1] = self::isTriggerTrueByModel($workflow, $trigger, $model);
         $count++;
     }
     $phpStringReadyToEvaluate = WorkflowTriggersUtil::resolveBooleansDataToPHPString($structureAsPHPString, $dataToEvaluate);
     return WorkflowTriggersUtil::evaluatePHPString($phpStringReadyToEvaluate);
 }
 /**
  * @depends testTriggerBeforeSaveLessThanOrEqualTo
  */
 public function testTriggerBeforeSaveBetween()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('float', 'between', '54.78', 'WorkflowsTestModule', 'WorkflowModelTestItem', '97');
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someValue';
     $model->float = '65.12';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->float = '32.12';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->float = '76.12';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->float = 55.12;
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->float = 54.78;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->float = 97.12;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 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);
 }
 /**
  * @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();
             }
         }
     }
 }
 /**
  * @depends testTriggerBeforeSaveIsEmpty
  */
 public function testTriggerBeforeSaveIsNotEmpty()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('dropDown', 'isNotEmpty', null);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dropDown->value = 'bValue';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dropDown->value = null;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->dropDown->value = '';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @depends testTriggerBeforeSaveIsEmpty
  */
 public function testTriggerBeforeSaveIsNotEmpty()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('user__User', 'isNotEmpty', null);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->user = User::getByUsername('bobby');
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->user = null;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @depends testTriggerBeforeSaveIsEmpty
  */
 public function testTriggerBeforeSaveIsNotEmpty()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('status', OperatorRules::TYPE_IS_NOT_EMPTY, null);
     $model = new WorkflowModelTestItem();
     $model->lastName = 'someLastName';
     $model->string = 'someValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->status = 2;
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->status = null;
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->status = '';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * 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 testTriggerBeforeSaveHasManyNotOwnedEquals
  */
 public function testTriggerBeforeSaveManyManyNotOwnedEquals()
 {
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType('hasMany3___name', 'equals', 'aValue', 'WorkflowsTestModule', 'WorkflowModelTestItem2');
     $model = new WorkflowModelTestItem2();
     $relatedModel = new WorkflowModelTestItem3();
     $this->assertTrue($relatedModel->save());
     $model->hasMany3->add($relatedModel);
     $model->hasMany3[0]->name = 'aValue';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->hasMany3[0]->name = 'bValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model = self::saveAndReloadModel($model);
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->hasMany3[0]->name = 'aValue';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     //should be case-insensitive
     $model->hasMany3[0]->name = 'aVAlUe';
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * @see testTriggerOnAnInferredModelsOwnedModelWithAMultipleModelsRelated. Saving Note first, then retrieving. This
  * means the activityItems are 'Item' model and need to be casted down.
  */
 public function testTriggerOnAnAlreadySavedInferredModelsOwnedModelWithAMultipleModelsRelated()
 {
     $attributeIndexOrDerivedType = 'Account__activityItems__Inferred___billingAddress___street1';
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType($attributeIndexOrDerivedType, 'equals', 'cValue', 'NotesModule', 'Note');
     $model = new Note();
     $model->description = 'description';
     $relatedModel = new Account();
     $relatedModel->name = 'dValue';
     $relatedModel->billingAddress->street1 = 'cValue';
     $this->assertTrue($relatedModel->save());
     $model->activityItems->add($relatedModel);
     $currencies = Currency::getAll();
     $currencyValue = new CurrencyValue();
     $currencyValue->value = 100;
     $currencyValue->currency = $currencies[0];
     $relatedModel2 = new Opportunity();
     $relatedModel2->name = 'someName';
     $relatedModel2->amount = $currencyValue;
     $relatedModel2->closeDate = '2011-01-01';
     $relatedModel2->stage->value = 'Verbal';
     $this->assertTrue($relatedModel2->save());
     $model->activityItems->add($relatedModel2);
     $saved = $model->save();
     $this->assertTrue($saved);
     $modelId = $model->id;
     $model->forget();
     unset($model);
     $model = Note::getById($modelId);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     //Just testing that since nothing changed on the related model, it should still evaluate as true
     $relatedModel2->name = 'someLastName2';
     $this->assertTrue($relatedModel->save());
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $relatedModel->billingAddress->street1 = 'bValue';
     $this->assertTrue($relatedModel->save());
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }
 /**
  * Testing that when you have a relation with another owned relation before the attribute, that it works correctly.
  */
 public function testAreTriggersTrueBeforeSaveWithRelationAndAnotherRelationBeforeAttribute()
 {
     $attributeIndexOrDerivedType = 'hasMany2___primaryAddress___street1';
     $workflow = self::makeOnSaveWorkflowAndTriggerWithoutValueType($attributeIndexOrDerivedType, 'equals', 'cValue', 'WorkflowsTestModule', 'WorkflowModelTestItem2');
     $model = new WorkflowModelTestItem2();
     $relatedModel = new WorkflowModelTestItem();
     $address = new Address();
     $relatedModel->primaryAddress = $address;
     $relatedModel->primaryAddress->street1 = 'cValue';
     $model->hasMany2->add($relatedModel);
     $this->assertTrue(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
     $model->hasMany2[0]->primaryAddress->street1 = 'bValue';
     $this->assertFalse(WorkflowTriggersUtil::areTriggersTrueBeforeSave($workflow, $model));
 }