Hi, Ross,

I think that the entire community is thinking and walking in the RIGHT way.
And your effort is a prove of this. Congratulations.

So, IMHO, I think that workflows are not only linear, but in some cases we
have concurrent tasks to do. If your algorithm is compliant with this, I
think that is a wonderful feature.

Best regards,

José Ricardo Borba
Porto Alegre - RS

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<https://groups.google.com/forum/#%21searchin/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(wo**rkflow_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!
>>>
>>


-- 
José Ricardo Borba

UFRGS - Instituto de Física
L3FNano - 43173 room 101
Lab:    55-51-3308-6457 / Office: 55-51-3308-6530
Mobile:55-51-8184-7649 / Fax:   55-51-3308-7286

Reply via email to