Please see my workflow framework in Lotus Notes, in the end of creating rules, i use graphviz to draw the graph of the workflow..
http://www.youtube.com/watch?v=zMNwqAtiFOw Also i manage centrally all rules and all apps point to my framework like a workflow as a service. Easier to manage. i think. I have about 40 apps with workflow inside. I wish i can do the same in web2py .... 2012/5/2 Ross Peoples <ross.peop...@gmail.com> > Cliff, > > Thanks for the feedback. I added the ability to name / title steps. I also > added the ability to set priorities for workflows. > > It is assumed that when a step is complete, that step is already "done" > and the next step in workflow is "new". Each step has an order_id to show > which order the steps are in. The workflow table stores the "order_id" of > the active workflow step. So in this case if the workflow is on order_id 3, > then anything below 3 is considered done, while everything else is new. Is > this what you mean by states to account for? > > Active workflows can be modified on the fly as well. This has a limitation > that any step that has been completed cannot be modified. All future steps > can be modified. So if the workflow needs to have another step added to it > or if it has been determined that the next destination user_id / group_id > needs to be changed, that can be done (i.e. someone accidentally added the > Engineering group, but it should have been Quality instead). > > I will add another method to WorkflowEngine (I was going to do this > anyways, but forgot to include it in my original post: > workflow = workflow_engine.get_workflow(workflow_id) > > # The contents of the workflow object would contain: > # name: the name of the workflow > # is_template: is this workflow a template > # item_type, item_id: what object is the workflow attached to > # order_id: the current position of the workflow > # priority: the priority of the workflow > # steps: list of step as Row objects > # > # There would be a few helper methods as well: > # current_step(): returns the Row object of the current step or None > # due_date(): returns the current step's due date or None > # ... > > I have not built in any security, as I figured that would be something > more application-specific. For example, a document management system might > want security on folders, just like a regular file system, and > not necessarily on a workflow-by-workflow basis. > > However, I am planning on adding auditing support. I almost used the new > record versioning feature, but decided I wanted to go with delta-based > changes instead of full copies of everything for better timeline support. > > Additional questions, comments, and improvements are welcome! > > On Tuesday, May 1, 2012 4:07:05 PM UTC-4, Cliff wrote: >> >> Ross, >> >> I like the on-the-fly ability. >> >> Each step in your template changes the state of the item. Each one of >> those states should have a title. >> >> There are two other states to account for, new and done. >> >> Workflows sometimes have more than one path to completion. >> >> I see an entity called a workflow_item that has the ability to determine >> its current state and all possible states to which it could transition. It >> also knows who can cause it to transition to one of those states as well as >> which of its attributes should be hidden, visible or editable in any given >> state, and who should be able to see or edit those attributes while in that >> state. >> >> >> On Tuesday, May 1, 2012 12:00:42 PM UTC-4, Ross Peoples wrote: >>> >>> In reference to: >>> https://groups.google.com/forum/#!searchin/web2py/workflow/web2py/osEmmtu9hlg/2MHi_ZCeMBMJ >>> >>> Has anyone done any work on this yet? I was thinking about making a >>> web2py-based workflow engine. >>> >>> I mentioned previously that I built one of these for an application I >>> wrote several years ago, but it was built specifically for that app. This >>> will be my first attempt at making a general-use workflow engine, so let me >>> know if you find any problems with my design: >>> >>> Make a contrib module that is initialized like the Auth module: >>> from gluon.contrib.workflow_engine import WorkflowEngine, Step >>> workflow_engine = WorkflowEngine() >>> workflow_engine.define_tables() >>> >>> >>> I will use the example that I know best, which is passing around a sales >>> order throughout a company's departments. This first example would define a >>> workflow template because every sales order will have the same workflow: >>> workflow_engine.add_template('Sales Order', >>> Step(group_id=2, hours=4), # Engineering gets 4 hours to complete >>> their step >>> Step(user_id=7, hours=0), # The engineering manager (user) has no >>> time limit >>> Step(group_id=3, hours=2), # Quality department gets 2 hours to >>> inspect the order >>> Step(group_id=8, hours=6.5), # Shipping department gets 6.5 hours >>> to ship order >>> ) >>> >>> >>> You would start this workflow like this: >>> workflow_id = workflow_engine.load_template('Sales Order', item_type= >>> 'document', item_id=1) >>> workflow_id = workflow_engine. >>> workflow_engine.start(workflow_id) >>> >>> >>> Optionally, a workflow can be created on the fly (if the workflow will >>> only be used once): >>> workflow_id = workflow_engine.create_workflow('One-time Workflow', >>> 'document', 1 # same as item_type and item_id used in load_template() >>> Step(group_id=2, hours=4) >>> Step(group_id=3, due_date=request.now + datetime.timedelta(days=1)) # >>> set time limit to an exact datetime >>> ) >>> >>> workflow_engine.start(workflow_id) # start the workflow we just created >>> >>> >>> We assume that we are going to associate this workflow with another >>> object. In this case, we will assume there is a table called "document" and >>> that the document we want to pass around has an id of 1. The "item_type" >>> argument allows you to pass around any type of database object. In this >>> case, we will call it the same thing as our table: "document". >>> >>> These are some common operations that could be done: >>> workflow_engine.active_workflows() # returns a list of all active >>> workflows >>> workflow_engine.active_workflows(user_id=1) # all active workflows for >>> the user_id >>> workflow_engine.active_workflows(user_id=1, include_groups=True) # same >>> as above, but includes groups the user is a member of >>> workflow_engine.active_workflows(group_id=2) # all active workflows for >>> the group_id >>> workflow_engine.late_workflows() # returns a list of all late/overdue >>> workflows >>> workflow_engine.step_complete(workflow_id, notes='General info about >>> completed task') # moves workflow to the next step >>> workflow_engine.step_reject(workflow_id, to_step=2, notes='Why step was >>> rejected') # moves workflow back to step 2 incase there was a problem >>> with one of the previously completed steps >>> >>> >>> Workflow triggers: >>> workflow_engine.before_start = function(workflow, step) >>> workflow_engine.after_start = function(workflow, step) >>> workflow_engine.before_step_complete = function(workflow, step) >>> workflow_engine.after_step_complete = function(workflow, step) >>> workflow_engine.before_step_reject = function(workflow, step) >>> workflow_engine.after_step_reject = function(workflow, step) >>> workflow_engine.before_finish = function(workflow, step) >>> workflow_engine.after_finish = function(workflow, step) >>> >>> >>> Finally, (and I MIGHT do this) since we are using time limits in hours, >>> we should set some time ranges where users are available. For example, if >>> the company is only open from 8 AM to 5 PM, you wouldn't want something to >>> be late at 7 PM. You would want to roll over the extra 2 hours so that it >>> becomes late at 10 AM the next business day. A list of time ranges would be >>> created, and a user would be assigned to one of the time ranges. This would >>> accommodate users in different time zones or with different "work" hours. >>> Again, this last part I MIGHT do if I have enough time. I've done it >>> before, but I'm sure you can imagine how complicated this part is. >>> >>> >>> So any questions, comments, improvements? Thanks! >>> >>