work in progress: task management with work items
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@3092 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
5344a8bb85
commit
7db5c8df68
3 changed files with 53 additions and 24 deletions
|
@ -93,7 +93,7 @@ so we do not have to set up real objects.
|
||||||
|
|
||||||
>>> wi01 = workItems.add('001', 'john')
|
>>> wi01 = workItems.add('001', 'john')
|
||||||
>>> wi01
|
>>> wi01
|
||||||
<WorkItem ['001', 1, 'john', '...', 'created']:
|
<WorkItem ['001', 1, 'john', '...', 'new']:
|
||||||
{'created': ..., 'creator': 'john'}>
|
{'created': ..., 'creator': 'john'}>
|
||||||
|
|
||||||
Properties that have not been set explicitly have a default of None; properties
|
Properties that have not been set explicitly have a default of None; properties
|
||||||
|
@ -110,20 +110,16 @@ Certain (not all) properties may be set after creation.
|
||||||
|
|
||||||
>>> wi01.setInitData(planStart=1229955772, planDuration=600, party='annie')
|
>>> wi01.setInitData(planStart=1229955772, planDuration=600, party='annie')
|
||||||
>>> wi01
|
>>> wi01
|
||||||
<WorkItem ['001', 1, 'annie', '2008-12-22 14:22', 'created']:
|
<WorkItem ['001', 1, 'annie', '2008-12-22 14:22', 'new']:
|
||||||
{'created': ..., 'planEnd': 1229956372, 'planDuration': 600,
|
{'created': ..., 'planEnd': 1229956372, 'planDuration': 600,
|
||||||
'planStart': 1229955772, 'creator': 'john', 'planEffort': 600}>
|
'planStart': 1229955772, 'creator': 'john', 'planEffort': 600}>
|
||||||
|
|
||||||
It's not possible to change a value after it has been set, even if it is
|
It's possible to change a value after it has been set as long as the work
|
||||||
set via an automatic calculation like for the ``planEffort`` field.
|
item is in state 'new'.
|
||||||
|
|
||||||
>>> wi01.setInitData(planEffort=400)
|
>>> wi01.setInitData(planEffort=700)
|
||||||
Traceback (most recent call last):
|
>>> wi01.planEffort
|
||||||
...
|
700
|
||||||
ValueError: Attribute 'planEffort' already set to '600'.
|
|
||||||
|
|
||||||
There is one exception to this rule: The party may be changed as long as
|
|
||||||
the work item is not in the ``assigned`` state.
|
|
||||||
|
|
||||||
>>> wi01.setInitData(party='jim')
|
>>> wi01.setInitData(party='jim')
|
||||||
>>> wi01.userName
|
>>> wi01.userName
|
||||||
|
@ -141,7 +137,7 @@ that the work item is assigned to may not be changed any more.
|
||||||
>>> wi01.setInitData(party='annie')
|
>>> wi01.setInitData(party='annie')
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
...
|
...
|
||||||
ValueError: Attribute 'party' may not be set in state 'assigned'.
|
ValueError: Attribute 'party' already set to 'jim'.
|
||||||
|
|
||||||
Jim now really starts to work. The start time is usually set automatically
|
Jim now really starts to work. The start time is usually set automatically
|
||||||
but may also be specified explicitly.
|
but may also be specified explicitly.
|
||||||
|
@ -151,7 +147,7 @@ but may also be specified explicitly.
|
||||||
<WorkItem ['001', 1, 'jim', '2008-12-22 15:00', 'running']:
|
<WorkItem ['001', 1, 'jim', '2008-12-22 15:00', 'running']:
|
||||||
{'created': ..., 'planEnd': 1229956372, 'start': 1229958000,
|
{'created': ..., 'planEnd': 1229956372, 'start': 1229958000,
|
||||||
'assigned': ..., 'planDuration': 600, 'planStart': 1229955772,
|
'assigned': ..., 'planDuration': 600, 'planStart': 1229955772,
|
||||||
'creator': 'john', 'planEffort': 600}>
|
'creator': 'john', 'planEffort': 700}>
|
||||||
|
|
||||||
Stopping work
|
Stopping work
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -476,6 +476,17 @@ class IWorkItem(Interface):
|
||||||
as keyword arguments.
|
as keyword arguments.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def doAction(action, **kw):
|
||||||
|
""" Execute an action.
|
||||||
|
|
||||||
|
Actions are usually a sequence of transitions together with
|
||||||
|
setting some properties depending on the action and
|
||||||
|
the starting state.
|
||||||
|
|
||||||
|
Available actions are: plan, delegate, accept, start, finish,
|
||||||
|
cancel, continue, transfer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
class IWorkItems(Interface):
|
class IWorkItems(Interface):
|
||||||
""" A collection (manager, container) of work items.
|
""" A collection (manager, container) of work items.
|
||||||
|
|
|
@ -41,7 +41,7 @@ _not_found = object()
|
||||||
@implementer(IStatesDefinition)
|
@implementer(IStatesDefinition)
|
||||||
def workItemStates():
|
def workItemStates():
|
||||||
return StatesDefinition('workItemStates',
|
return StatesDefinition('workItemStates',
|
||||||
State('created', 'created', ('assign', 'cancel',), color='red'),
|
State('new', 'new', ('assign', 'cancel',), color='red'),
|
||||||
State('assigned', 'assigned', ('start', 'finish', 'cancel', 'transfer'),
|
State('assigned', 'assigned', ('start', 'finish', 'cancel', 'transfer'),
|
||||||
color='yellow'),
|
color='yellow'),
|
||||||
State('running', 'running', ('finish', 'continue', 'cancel', 'transfer'),
|
State('running', 'running', ('finish', 'continue', 'cancel', 'transfer'),
|
||||||
|
@ -57,7 +57,7 @@ def workItemStates():
|
||||||
Transition('continue', 'continue', 'continued'),
|
Transition('continue', 'continue', 'continued'),
|
||||||
Transition('transfer', 'transfer', 'transferred'),
|
Transition('transfer', 'transfer', 'transferred'),
|
||||||
Transition('cancel', 'cancel', 'cancelled'),
|
Transition('cancel', 'cancel', 'cancelled'),
|
||||||
initialState='created')
|
initialState='new')
|
||||||
|
|
||||||
|
|
||||||
class WorkItem(Stateful):
|
class WorkItem(Stateful):
|
||||||
|
@ -99,20 +99,16 @@ class WorkItemTrack(WorkItem, Track):
|
||||||
return self.userName
|
return self.userName
|
||||||
|
|
||||||
def setInitData(self, **kw):
|
def setInitData(self, **kw):
|
||||||
|
indexChanged = False
|
||||||
|
updatePlanData = False
|
||||||
for k in kw:
|
for k in kw:
|
||||||
if k not in self.initAttributes:
|
if k not in self.initAttributes:
|
||||||
raise ValueError("Illegal initial attribute: '%s'." % k)
|
raise ValueError("Illegal initial attribute: '%s'." % k)
|
||||||
|
self.checkOverwrite(kw)
|
||||||
party = kw.pop('party', None)
|
party = kw.pop('party', None)
|
||||||
if party is not None:
|
if party is not None:
|
||||||
if self.state != 'created':
|
self.userName = party
|
||||||
raise ValueError("Attribute 'party' may not be set in state '%s'." %
|
indexChanged = True
|
||||||
self.state)
|
|
||||||
else:
|
|
||||||
self.userName = party
|
|
||||||
indexChanged = True
|
|
||||||
self.checkOverwrite(kw)
|
|
||||||
updatePlanData = False
|
|
||||||
indexChanged = False
|
|
||||||
data = self.data
|
data = self.data
|
||||||
for k, v in kw.items():
|
for k, v in kw.items():
|
||||||
data[k] = v
|
data[k] = v
|
||||||
|
@ -174,10 +170,36 @@ class WorkItemTrack(WorkItem, Track):
|
||||||
self.data['successor'] = getName(new)
|
self.data['successor'] = getName(new)
|
||||||
return new
|
return new
|
||||||
|
|
||||||
|
# actions
|
||||||
|
|
||||||
|
def doAction(self, action, **kw):
|
||||||
|
# TODO: check if action is allowed
|
||||||
|
m = getattr(self, 'action_' + action)
|
||||||
|
m(**kw)
|
||||||
|
|
||||||
|
def action_start(self, **kw):
|
||||||
|
if self.state == 'new':
|
||||||
|
self.assign(kw.pop('party', None))
|
||||||
|
self.startWork(**kw)
|
||||||
|
|
||||||
|
def action_finish(self, **kw):
|
||||||
|
if self.state == 'new':
|
||||||
|
self.assign(kw.pop('party', None))
|
||||||
|
self.stopWork(**kw)
|
||||||
|
#pred = self.predecessor # better to finish predecessors manually?
|
||||||
|
#while pred is not None:
|
||||||
|
# wi = getParent(self)[pred]
|
||||||
|
# wi.doTransition('finish')
|
||||||
|
# pred = wi.pred
|
||||||
|
|
||||||
|
# auxiliary methods
|
||||||
|
|
||||||
def reindex(self):
|
def reindex(self):
|
||||||
getParent(self).updateTrack(self, {}) # force reindex
|
getParent(self).updateTrack(self, {}) # force reindex
|
||||||
|
|
||||||
def checkOverwrite(self, kw):
|
def checkOverwrite(self, kw):
|
||||||
|
if self.state == 'new':
|
||||||
|
return
|
||||||
for k, v in kw.items():
|
for k, v in kw.items():
|
||||||
old = getattr(self, k, None)
|
old = getattr(self, k, None)
|
||||||
if old is not None and old != v:
|
if old is not None and old != v:
|
||||||
|
|
Loading…
Add table
Reference in a new issue