================================================== 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 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. >>> 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 not possible to change a value after it has been set, even if it is set via an automatic calculation like for the ``planEffort`` field. >>> wi01.setInitData(planEffort=400) Traceback (most recent call last): ... 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.userName 'jim' Change work item states ----------------------- 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' may not be set in state 'assigned'. Jim now really starts to work. The start time is usually set automatically but may also be specified explicitly. >>> wi01.startWork(start=1229958000) >>> wi01 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. >>> wi02 = wi01.stopWork('continue', end=1229958300, planStart=1229960000, ... planDuration=400, planEnd=None, planEffort=None) >>> wi02