[EXTENSION] simpleWorkflow

Hi Dzsonny,

your solution is very right and I confirm the record should be updated in DB. Now to tell you what may cause this incorrect behavior, I would need more info. Could you please post your Model, action, and workflow so I can help you ?

Thanks

Hi!

I ended up using this solution:


//$model->swNextStatus('deploying');

			$model->del_status='test_report';

			$model->save();

I cant tell, why swNextStatus doesnt work. The project is a bit complex, if i find the problem i will post it.

In the mean time i have another question: Is it possible to have a message tell you, if a constraint is not allowing you to step to the next state.

If a user hasnt fulfilled the requirements to step to the next state, i wolud like to inform him. At this state he wouldnt understand why the button is not working.

Hi [color="#1C2837"][size="2"]Dzsonny,[/size][/color]

[color="#1C2837"][size="2"]I will take a deeper look into the source code to see if I find something strange…[/size][/color]

[color="#1C2837"][size=“2”]Regarding your question, I don’t know what really is the use case, but right now, there is no way to know why a constraint failed (i.e was evaluated to FALSE). However, this is done by design (I mean, no technical reason). The point is that status contraint should not be used as model validators, and basically, if a constraint is not satisfied, no direct user action should change that, when saving the model.[/size][/color]

[color="#1C2837"][size="2"]On the other hand, I have implemented a Workflow Driven Model Validation feature that is dedicated to adding model validation rules inside a workflow (and for a given model)… maybe this could be used ? [/size][/color]

[color="#1C2837"] [/color]

[color="#1C2837"][size=“2”]From your description, I understand that the user doesn’t acutally submit a form, but only clicks on a button right ? Well actually, when the user clicks on the button, its just like he if would :[/size][/color]

[size="2"][color="#1C2837"]

[/color][/size]

[list=1][][size=“2”][color="#1C2837"]change the model status to ‘built’[/color][/size][][size=“2”][color="#1C2837"]save the model[/color][/size][/list]

[size=“2”][color="#1C2837"]So my question is, if the model can’t be built at the time it is displayed to the user, why is the ‘built’ button displayed in the first place ? [/color][/size]

[size="2"][color="#1C2837"]

[/color][/size]

[size=“2”][color="#1C2837"]Please, don’t assume that I’m lazy and don’t want to add this warning constraint message to the extension ;) … it’s just that I want to avoid using constraint like model validation rules; they just have not be designed for this purpose. So, I need to know a little bit more about your scenario and be sure that if there is a really functional need for it, I will add a constraint message.[/color][/size]

[size="2"][color="#1C2837"]

[/color][/size][color="#1C2837"][size="2"]ciao[/size][/color]

[color="#1C2837"][size=“2”]8)[/size][/color]

[color="#1C2837"] [/color]

[size="2"] [/size]

You are absolutly right. I solved the problem, with the button only visible if the constraint is fullfilled. Although with this solution, the whole constraint is kind of in vain, isn’t it?

Ok, I will include the constraint message in the next release. I think you’re right, and a small message won’t hurt ;)

Wow, i made my mark in history :) Your Extension is great, thanks for the great work!

Hi everyone,

First of all, I would like to start by thanking Raoul for this wonderful piece of software, which is about to save me from a lot of development trouble.

Let me describe, first, my situation/scenario: I’m developing a customer management solution for an ISP. A customer will have multiple statuses, such as “new customer contacted by sales”, “signed contract for a new subscription”, “active (new connection installed)” and so on. A customer cannot (or should not) be manually migrated from “new customer” status to “signed contract” status. Instead, the sales rep should enter the data for a new subscription (which is totally different object/model, related to the client by a foreign key). When the subscription has been correctly registered, the client’s status should automatically change to “signed contract”, without user interaction.

Basically, upon successful registration, the Subscription object should order the Client object to whom it belongs to switch to the new status.

And now the question: what is the preferred/recommended way to instruct objects to switch statuses for other objects, without direct user interaction on the "victim" object ?

Regards,

jd

Hi Dan,

and thanks for your comment. I hope this extension will suit your needs.

Let’s see if I understood you well :

  • 2 models : Client and Subscription
  • Relation between Cleint and Subscription (has_one, belong_to)

When a Subscription model is saved, its related Client should be modified : the Client status should be set to "signed contact".

It seems to me that the solution would be to handle the afterSave event on the Subscription model and programatically change the status of the related Client. The simpleWorkflow extension provides a complete API to interact with a model inside its workflow. For instance, you could write someting like :




class Subscription extends CActiveRecord {

 // ....

  public function afterSave(){

 		// assumes the relation name is 'client'  and that the target status is 'client/signed_contact'

        $this->client->swNextStatus('client/signed_contact');

  }

}

Of course, you should consider the case where the Client object (the ‘victim’ ;) ) is currently in a status that can’t reach the ‘client/signed_contact’. In other words, if there is no transition between the current Client status and ‘client/signed_status’ then you have a problem and should decide what to do … but this is more a design issue.

Anyway, I encourage you to take a look to the API Documentation and in particular to the SWActiveRecordBehavior class reference so you can have a better idea about what is possible to do.

I hope my explanation was clear, and if not, don’t hesitate to tell me.

bye

8)

Raoul,

Thank you for your quick and comprehensive reply ! I was, actually, just now toying with the swNextStatus function (and not getting the desired results, since I was trying to send the object in the ‘signed_contract’ status, not in the ‘swClients/signed_contract’ one). May I point out that at least this API function is not very well documented (I had to study the source file to see what it actually does and how it does it).

Anyway, your approach is wonderful, since I was struggling to switch the client status in the controller (which I knew it would be unadvised).

I’ll come back to this thread if any other issues pop up, until then, thank you once again!

Regards,

JD

hi any body

state diagram of my project is like Demo5 in onlinehome.fr

now, i dont know how initialize my Sw.

please help me.

hi Raoul

i need a complete guide to this extension.

you said

but how i can change this folder?

you didnt say how i can have relation between two workflow.

i need a complete refrence.

if this refrence is not available , please tell me to start for implementing a workflow engine by myself.

Hi ehsanjs,

to change the folder where workflows are located, just set the basePath parameter when you initialize the SWPhpWorkflowSource component. Here is an example :


'components'=>array(   

   // adding the simple Workflow source component

   'swSource'=> array(

      'class'=>'application.extensions.simpleWorkflow.SWPhpWorkflowSource',

  	// use a path alias only

      'basePath' => 'application.my_workflows'

   ), 

   // ....

You can may find more information in the API Documentation.

A status can be referenced by its short name (for example ‘ready’, ‘published’, etc…) or by its full name. To jump from a workflow to another, simply use the fullname.

For example, base on demo5, we have workflow1 (‘A’, ‘B’, ‘C’, ‘D’) and workflow2 (‘S1’, ‘S2’, ‘S3’). The definition is :


// definition workflow1

array(

      'initial' => 'A',

      'node' => array(

 		array('id'=>'A',    'transition'=>'B,C'),

 		array('id'=>'B',    'transition'=>'C,D'),

 		// use the fullname workflow2/S1 to jump to another workflow 

 		array('id'=>'C','transition'=>'B,D,workflow2/S1'),

 		array('id'=>'D')

      )

   )

   

// definition workflow2   

array(

      'initial' => 'S1',

      'node' => array(

 		array('id'=>'S1',    'transition'=>'S2,S3,S1'),

 		// use the fullname workflow1/B to jump to another workflow 

 		array('id'=>'S2',    'transition'=>'S1, workflow1/B'),

 		array('id'=>'S3')

      )

   ) 

The reference I provide in the demo site is currently the max I can do because I have not much time right now, but I understand that it may not suit your requirements. If you feel like implementing your own workflow engine, you’ll find a set of intresting links here. I used them as ‘inspiration’ to write this simpleWorkflow extension.

ciao

B)

tanks dear Raoul

i hope that you answer all of my questions in next, too.

Tanks a lot

hi raoul

i have a request.

please release a chm file from documents.

and

i want to know that wat is the way of founding answer of my questions. for example , how i must know that the "basePath" property is the path of workflows?

hi dear raoul.

you said that

so , i suggest that you can release the source of six demos that is available is your demo site and help alot to me and others that are like me.

Hi ehanjs,

ok, if you think the demo source code can help, I will release it 'as it is" … I can’t do that right now, but I will later on today and let you know. Did you notice that in the extension page I also released a Blog Demo source code ? Maybe that can help too …

I’m sorry if the documentation is not complete, and I’ll try to do my best to improve it.

ciao

B)

tanks for your attention.

Hello Dear Raoul

i want to use this extension in a module.

so i placed the extension folder in /protected/modules/site/extensions/

but

in SWActiveRecordBehavior in attach method


$this->_wfs= Yii::app()->{$this->workflowSourceComponent};

point to swSource component in /protected/extensions.

how i can solve this?

hi ehsanjs,

I have prepared a zip file with the demo you can find in the demo site… I hope it will help you.

Now regarding your other question, there should be no problem moving the extension into a module. The SWActiveRecordBehavior uses a component to acces the workflow, so if you move the extensions folder, you just have to initialize the component with the correct path.

For example, if I move extensions to ./modules/test, then in the config file, write :


		'swSource'=> array(

        	// here, just add 'modules'

			'class'=>'application.modules.extensions.simpleWorkflow.SWPhpWorkflowSource',

			'basePath'=> 'application.models.simpleWorkflow.workflows',

		

),



Of course, you can also set the SWSource component when you initialize the behavior :


	public function behaviors()

	{

		return array(

			'swBehavior' => array(

				'class'   		=> 'application.extensions.simpleWorkflow.SWActiveRecordBehavior',

            	// don't forget to declare 'myComponent' in the configuration !

				'workflowSourceComponent' => 'myComponent'

			),

...

Hope this helps

ciao

B)