================================================== Organizations: Persons, Institutions, Addresses... ================================================== ($Id$) >>> from zope import component Persons and Addresses ===================== Let's start with a Person: >>> from cybertools.organize.party import Person >>> john = Person(u'Smith') >>> john.lastName u'Smith' >>> john.firstName u'' >>> john.birthDate is None True >>> john.addresses {} A Person object knows the age of the person: >>> john.age is None True >>> from datetime import date >>> john.birthDate = date(1980, 3, 25) >>> now = date(2006, 5, 12) >>> john.ageAt(now) 26 >>> john.age >= 26 True >>> john.firstName = u'John' >>> john.firstName u'John' Addresses --------- Let's create an address and assign it to a person: >>> from cybertools.organize.party import Address >>> addr = Address(u'New York', u'Broadway 1') >>> john.addresses['standard'] = addr >>> john.addresses['standard'].street u'Broadway 1' Tasks ===== >>> from cybertools.organize.task import Task Service Management ================== >>> from cybertools.organize.service import Service (See cyberapps.tumsm for comprehensive description and tests.) Work ==== 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 WorkItem, 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=WorkItem) >>> 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. >>> wi01 = workItems.add('001', 'john') >>> wi01 Properties that have not been set explicitly have a default of None; properties not specified in the IWorkItem interface will lead to an AttributeError. >>> wi01.description is None True >>> wi01.something Traceback (most recent call last): ... AttributeError: something Certain (not all) properties may be set after creation. >>> wi01.setInitData(planStart=1229955772, planDuration=600, party='annie') >>> wi01 It's possible to change a value after it has been set as long as the work item is in state 'new'. >>> wi01.setInitData(planEffort=700) >>> wi01.planEffort 700 >>> wi01.setInitData(party='jim') >>> wi01.userName 'jim' Change work item state ---------------------- Now Jim accepts the work item, i.e. he wants to work on it. Now the party that the work item is assigned to may not be changed any more. >>> wi01.assign() >>> wi01.state 'assigned' >>> wi01.setInitData(party='annie') Traceback (most recent call last): ... ValueError: Attribute 'party' already set to 'jim'. Jim now really starts to work. The start time is usually set automatically but may also be specified explicitly. >>> wi01.startWork(start=1229958000) >>> wi01 Stopping work ------------- After five minutes of work Jim decides to stop working; but he will continue work later, so he executes a ``continue`` transition that will set up a copy of the work item. He also specifies a new plan start and duration for the new work item. Plan end and plan effort are given explicitly as None values so that they won't be taken from the old work item but recalculated. Note that the work item has already been set to assigned as Jim has committed himself to continue working on it by selecting the ``continue`` transition. >>> wi02 = wi01.stopWork('continue', end=1229958300, planStart=1229960000, ... planDuration=400, planEnd=None, planEffort=None) >>> wi02