work in progress: work item (task) management
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@3079 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
0356cdf85c
commit
ee49d66e0d
5 changed files with 112 additions and 9 deletions
|
@ -4,6 +4,9 @@ Organizations: Persons, Institutions, Addresses...
|
||||||
|
|
||||||
($Id$)
|
($Id$)
|
||||||
|
|
||||||
|
>>> from zope import component
|
||||||
|
|
||||||
|
|
||||||
Persons and Addresses
|
Persons and Addresses
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
@ -48,6 +51,12 @@ Let's create an address and assign it to a person:
|
||||||
u'Broadway 1'
|
u'Broadway 1'
|
||||||
|
|
||||||
|
|
||||||
|
Tasks
|
||||||
|
=====
|
||||||
|
|
||||||
|
>>> from cybertools.organize.task import Task
|
||||||
|
|
||||||
|
|
||||||
Service Management
|
Service Management
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
@ -59,5 +68,28 @@ Service Management
|
||||||
Work
|
Work
|
||||||
====
|
====
|
||||||
|
|
||||||
>>> from cybertools.organize.work import WorkItem
|
Work items are stored in a tracking storage; in order to conveniently access
|
||||||
|
the work items we have to provide an adapter to the tracking storage.
|
||||||
|
|
||||||
|
>>> from cybertools.tracking.btree import TrackingStorage
|
||||||
|
>>> from cybertools.organize.interfaces import IWorkItems
|
||||||
|
>>> from cybertools.organize.work import WorkItemTrack, WorkItems
|
||||||
|
>>> component.provideAdapter(WorkItems)
|
||||||
|
|
||||||
|
The individual work item (a track) is carrying a state attribute that is
|
||||||
|
governed by a special states definition. We have to register this states
|
||||||
|
definition as a utility.
|
||||||
|
|
||||||
|
>>> from cybertools.organize.work import workItemStates
|
||||||
|
>>> component.provideUtility(workItemStates(), name='organize.workItemStates')
|
||||||
|
|
||||||
|
We are now ready to set up the tracking storage.
|
||||||
|
|
||||||
|
>>> tracks = TrackingStorage(trackFactory=WorkItemTrack)
|
||||||
|
>>> workItems = component.getAdapter(tracks, IWorkItems)
|
||||||
|
|
||||||
|
The work management only deals with the IDs or names of tasks and persons,
|
||||||
|
so we do not have to set up real objects.
|
||||||
|
|
||||||
|
>>> workItems.add('001', 'john')
|
||||||
|
<WorkItem ['001', 1, 'john', '2008-12-22 12:07', 'created']: {}>
|
||||||
|
|
|
@ -3,8 +3,16 @@
|
||||||
<configure
|
<configure
|
||||||
xmlns="http://namespaces.zope.org/zope"
|
xmlns="http://namespaces.zope.org/zope"
|
||||||
xmlns:i18n="http://namespaces.zope.org/i18n"
|
xmlns:i18n="http://namespaces.zope.org/i18n"
|
||||||
i18n_domain="zope">
|
i18n_domain="cybertools.organize">
|
||||||
|
|
||||||
<i18n:registerTranslations directory="locales" />
|
<i18n:registerTranslations directory="locales" />
|
||||||
|
|
||||||
|
<!-- work -->
|
||||||
|
|
||||||
|
<adapter factory="cybertools.organize.work.WorkItems" />
|
||||||
|
|
||||||
|
<utility component="cybertools.organize.work.workItemStates"
|
||||||
|
provides="cybertools.stateful.interfaces.IStatesDefinition"
|
||||||
|
name="organize.workItemStates" />
|
||||||
|
|
||||||
</configure>
|
</configure>
|
||||||
|
|
|
@ -425,19 +425,24 @@ class IWorkItem(Interface):
|
||||||
done by exactly one party (usually a person).
|
done by exactly one party (usually a person).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
task = Attribute('The task this work item belongs to.')
|
task = Attribute('The task this work item belongs to, identified by '
|
||||||
runId = Attribute('Used for recurring tasks: identifies the run '
|
'its name or ID.')
|
||||||
|
run = Attribute('Used for recurring tasks: identifies the run '
|
||||||
'(execution instance) of the task the work item belongs to.')
|
'(execution instance) of the task the work item belongs to.')
|
||||||
party = Attribute('Whoever does the work, usually a person.')
|
party = Attribute('Whoever does the work, usually a person, identified '
|
||||||
|
'by its name or ID.')
|
||||||
state = Attribute('The current state the work item is in.')
|
state = Attribute('The current state the work item is in.')
|
||||||
|
description = Attribute('A note about what has to be done, and why...')
|
||||||
comment = Attribute('A note about what has been done, and why...')
|
comment = Attribute('A note about what has been done, and why...')
|
||||||
# optional plan fields; duration (and effort) may be derived from start and end
|
# optional plan fields; duration (and effort) may be derived from start and end
|
||||||
|
# all date/time fields are timeStamp values, all duration and effort
|
||||||
|
# fields are in seconds
|
||||||
planStart = Attribute('When the work should start.')
|
planStart = Attribute('When the work should start.')
|
||||||
planEnd = Attribute('When the work should be finished.')
|
planEnd = Attribute('When the work should be finished.')
|
||||||
planDuration = Attribute('How long it may take to finish the work.')
|
planDuration = Attribute('How long it may take to finish the work.')
|
||||||
planEffort = Attribute('How much effort (time units) it might take '
|
planEffort = Attribute('How much effort (time units) it might take '
|
||||||
'to finish the work.')
|
'to finish the work.')
|
||||||
# real stuff; duration (and effort) may be derived from start and end
|
# real stuff
|
||||||
start = Attribute('When the work was started.')
|
start = Attribute('When the work was started.')
|
||||||
end = Attribute('When the work was finished.')
|
end = Attribute('When the work was finished.')
|
||||||
duration = Attribute('How long it took to finish the work.')
|
duration = Attribute('How long it took to finish the work.')
|
||||||
|
@ -450,3 +455,12 @@ class IWorkItem(Interface):
|
||||||
newTask = Attribute('Optional: a new task that has been created based '
|
newTask = Attribute('Optional: a new task that has been created based '
|
||||||
'on this work item.')
|
'on this work item.')
|
||||||
|
|
||||||
|
|
||||||
|
class IWorkItems(Interface):
|
||||||
|
""" A collection (manager, container) of work items.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def add(task, party, run=0, **kw):
|
||||||
|
""" Create and register a work item; return it. Additional properties
|
||||||
|
may be specified via keyword arguments.
|
||||||
|
"""
|
||||||
|
|
|
@ -22,14 +22,17 @@ Planning and recording activities (work items).
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from zope import component
|
||||||
from zope.component import adapts
|
from zope.component import adapts
|
||||||
from zope.interface import implementer, implements
|
from zope.interface import implementer, implements
|
||||||
|
|
||||||
from cybertools.organize.interfaces import IWorkItem
|
from cybertools.organize.interfaces import IWorkItem, IWorkItems
|
||||||
from cybertools.stateful.base import Stateful
|
from cybertools.stateful.base import Stateful
|
||||||
from cybertools.stateful.definition import StatesDefinition
|
from cybertools.stateful.definition import StatesDefinition
|
||||||
from cybertools.stateful.definition import State, Transition
|
from cybertools.stateful.definition import State, Transition
|
||||||
from cybertools.stateful.interfaces import IStatesDefinition
|
from cybertools.stateful.interfaces import IStatesDefinition
|
||||||
|
from cybertools.tracking.btree import Track
|
||||||
|
from cybertools.tracking.interfaces import ITrackingStorage
|
||||||
|
|
||||||
|
|
||||||
@implementer(IStatesDefinition)
|
@implementer(IStatesDefinition)
|
||||||
|
@ -56,3 +59,50 @@ class WorkItem(Stateful):
|
||||||
|
|
||||||
statesDefinition = 'organize.workItemStates'
|
statesDefinition = 'organize.workItemStates'
|
||||||
|
|
||||||
|
def getStatesDefinition(self):
|
||||||
|
return component.getUtility(IStatesDefinition, name=self.statesDefinition)
|
||||||
|
|
||||||
|
# work item attributes (except state that is provided by stateful
|
||||||
|
|
||||||
|
|
||||||
|
class WorkItemTrack(WorkItem, Track):
|
||||||
|
""" A work item that may be stored as a track in a tracking storage.
|
||||||
|
"""
|
||||||
|
|
||||||
|
metadata_attributes = Track.metadata_attributes + ('state',)
|
||||||
|
index_attributes = metadata_attributes
|
||||||
|
typeName = 'WorkItem'
|
||||||
|
|
||||||
|
initAttributes = set(['description', 'predecessor',
|
||||||
|
'planStart', 'planEnd', 'planDuration', 'planEffort'])
|
||||||
|
|
||||||
|
def __init__(self, taskId, runId, userName, data={}):
|
||||||
|
for k in data:
|
||||||
|
if k not in initAttributes:
|
||||||
|
raise ValueError("Illegal initial attribute: '%s'." % k)
|
||||||
|
super(WorkItemTrack, self).__init__(taskId, runId, userName, data)
|
||||||
|
self.state = self.getState() # make initial state persistent
|
||||||
|
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
value = self.data.get(attr, _not_found)
|
||||||
|
if value is _not_found:
|
||||||
|
raise AttributeError(attr)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
class WorkItems(object):
|
||||||
|
""" A tracking storage adapter managing work items.
|
||||||
|
"""
|
||||||
|
|
||||||
|
implements(IWorkItems)
|
||||||
|
adapts(ITrackingStorage)
|
||||||
|
|
||||||
|
def __init__(self, context):
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.context[key]
|
||||||
|
|
||||||
|
def add(self, task, party, run=0, **kw):
|
||||||
|
trackId = self.context.saveUserTrack(task, run, party, kw)
|
||||||
|
return self[trackId]
|
||||||
|
|
|
@ -92,14 +92,13 @@ class TrackingStorage(BTreeContainer):
|
||||||
implements(ITrackingStorage)
|
implements(ITrackingStorage)
|
||||||
|
|
||||||
trackFactory = Track
|
trackFactory = Track
|
||||||
|
indexAttributes = trackFactory.index_attributes
|
||||||
|
|
||||||
trackNum = runId = 0
|
trackNum = runId = 0
|
||||||
runs = None # currently active runs
|
runs = None # currently active runs
|
||||||
finishedRuns = None # finished runs
|
finishedRuns = None # finished runs
|
||||||
currentRuns = None # the currently active run for each task
|
currentRuns = None # the currently active run for each task
|
||||||
|
|
||||||
indexAttributes = Track.index_attributes
|
|
||||||
|
|
||||||
def __init__(self, *args, **kw):
|
def __init__(self, *args, **kw):
|
||||||
trackFactory = kw.pop('trackFactory', None)
|
trackFactory = kw.pop('trackFactory', None)
|
||||||
if trackFactory is not None:
|
if trackFactory is not None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue