state handling for service registrations

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2123 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-10-20 16:01:20 +00:00
parent c701a05d9e
commit 89510875c9
5 changed files with 107 additions and 36 deletions

View file

@ -59,11 +59,13 @@ class Field(Component):
def name(self):
return self.__name__
@property
def defaultValue(self):
def getDefaultValue(self):
if callable(self.default):
return self.default()
return self.default
def setDefaultValue(self, value):
self.default = value
defaultValue = property(getDefaultValue, setDefaultValue)
@property
def fieldRenderer(self):

View file

@ -32,6 +32,7 @@ from cybertools.organize.interfaces import serviceCategories
from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.browser.common import BaseView as SchemaBaseView
from cybertools.composer.schema.interfaces import IClientFactory
from cybertools.stateful.interfaces import IStateful
from cybertools.util.format import formatDate
@ -97,6 +98,7 @@ class ServiceManagerView(BaseView):
first = tpl
return first
#@Lazy - Zope 2.9 compatibility
def registrationUrl(self):
tpl = self.getRegistrationTemplate()
return self.getUrlForObject(tpl)
@ -170,7 +172,8 @@ class CheckoutView(ServiceManagerView):
return True # TODO: error, redirect to overview
regs = IClientRegistrations(client).getRegistrations()
for reg in regs:
pass # set state to submitted,
stateful = IStateful(reg)
stateful.doTransition(('submit', 'change'))
# send mail
# find thank you message and redirect to it
params = '?message=thankyou&id=' + self.clientName
@ -190,6 +193,7 @@ class ServiceView(BaseView):
man = context.getManager()
return ServiceManagerView(man, self.request).getRegistrationTemplate()
#@Lazy - Zope 2.9 compatibility
def registrationUrl(self):
tpl = self.getRegistrationTemplate()
return self.getUrlForObject(tpl)
@ -213,6 +217,12 @@ class ServiceView(BaseView):
instance = IInstance(client)
return instance.applyTemplate()
def getRegistrationInfo(self, reg):
registration = self.getRegistrations()[reg]
state = IStateful(registration).getStateObject()
return dict(number=registration.number,
state=state.name, stateTitle=state.title)
def update(self):
newClient = False
nextUrl = None

View file

@ -33,6 +33,7 @@ from zope.interface import implements, Interface
from cybertools.composer.interfaces import IInstance
from cybertools.composer.rule.base import RuleManager, EventType
from cybertools.composer.schema.interfaces import IClientManager, IClient
from cybertools.stateful.base import StatefulAdapter
from cybertools.stateful.definition import registerStatesDefinition
from cybertools.stateful.definition import StatesDefinition
from cybertools.stateful.definition import State, Transition
@ -97,11 +98,30 @@ class ServiceManager(RuleManager):
return self.rules
class Registration(object):
implements(IRegistration)
number = 1
def __init__(self, client, service, number=1):
self.client = client
self.service = service
self.timeStamp = int(time())
self.number = number
class PersistentRegistration(Registration, Persistent):
pass
class Service(object):
implements(IService)
registrationsFactory = OOBTree
registrationFactory = PersistentRegistration
manager = None
category = None
@ -150,9 +170,9 @@ class Service(object):
reg = self.registrations[clientName]
if number != reg.number:
reg.number = number
self.registrations[clientName] = reg # persistence hack
#self.registrations[clientName] = reg # persistence hack
return reg
reg = Registration(client, self, number)
reg = self.registrationFactory(client, self, number)
self.registrations[clientName] = reg
return reg
#if self.availableCapacity:
@ -184,20 +204,7 @@ class ScheduledService(Service):
return getattr(self.getManager(), 'end', None)
# registration
class Registration(object):
implements(IRegistration)
number = 1
def __init__(self, client, service, number=1):
self.client = client
self.service = service
self.timeStamp = int(time())
self.number = number
# registration stuff
class RegistrationTemplate(object):
@ -253,7 +260,6 @@ class ClientRegistrations(object):
service.unregister(self.context)
def getRegistrations(self):
# TODO: restrict to services on this template
regs = getattr(self.context, self.registrationsAttributeName, [])
if self.template is not None:
svcs = self.template.getServices().values()
@ -261,19 +267,26 @@ class ClientRegistrations(object):
return regs
# registration states definition
# registration states
registrationStates = 'organize.service.registration'
registerStatesDefinition(
StatesDefinition('organize.service.registration',
StatesDefinition(registrationStates,
State('temporary', 'temporary', ('submit', 'cancel',)),
State('submitted', 'submitted', ('retract', 'setwaiting', 'confirm', 'reject',)),
State('submitted', 'submitted',
('change', 'retract', 'setwaiting', 'confirm', 'reject',)),
State('cancelled', 'cancelled', ('submit',)),
State('retracted', 'retracted', ('submit',)),
State('waiting', 'waiting', ('retract', 'confirm', 'reject',)),
State('confirmed', 'confirmed', ('retract', 'reject',)),
State('rejected', 'rejected', ('retract', 'setwaiting', 'confirm',)),
State('waiting', 'waiting',
('change', 'retract', 'confirm', 'reject',)),
State('confirmed', 'confirmed',
('change', 'retract', 'reject',)),
State('rejected', 'rejected',
('change', 'retract', 'setwaiting', 'confirm',)),
Transition('cancel', 'Cancel registration', 'cancelled'),
Transition('submit', 'Submit registration', 'submitted'),
Transition('change', 'Change registration', 'submitted'),
Transition('retract', 'Retract registration', 'retracted'),
Transition('setwaiting', 'Set on waiting list', 'waiting'),
Transition('confirm', 'Confirm registration', 'confirmed'),
@ -282,7 +295,14 @@ registerStatesDefinition(
))
# event types
class StatefulRegistration(StatefulAdapter):
component.adapts(IRegistration)
statesDefinition = registrationStates
# event types for rule-based processing
eventTypes = Jeep((
EventType('service.checkout'),
@ -297,3 +317,11 @@ def clientRemoved(obj, event):
regs = IClientRegistrations(obj)
for r in regs.getRegistrations():
r.service.unregister(obj)
def serviceRemoved(obj, event):
""" Handle removal of a service.
"""
for r in obj.registrations.values():
regs = IClientRegistrations(r.client)
regs.unregister([obj])

View file

@ -47,11 +47,18 @@ class Stateful(object):
state = self.getState()
return self.getStatesDefinition().states[state]
def doTransition(self, transition):
""" execute transition.
"""
def doTransition(self, transition, historyInfo=None):
sd = self.getStatesDefinition()
sd.doTransitionFor(self, transition)
if isinstance(transition, basestring):
sd.doTransitionFor(self, transition)
return
available = [t.name for t in sd.getAvailableTransitionsFor(self)]
for tr in transition:
if tr in available:
sd.doTransitionFor(self, tr)
return
raise ValueError("None of the transitions '%s' is available for state '%s'."
% (repr(transition), self.getState()))
def getAvailableTransitions(self):
sd = self.getStatesDefinition()

View file

@ -50,18 +50,42 @@ class IStateful(Interface):
"""
def getStateObject():
""" Return the state (an IState implementation) of the object.
""" Return the state (an IState implementation) of the context object.
"""
def doTransition(transition):
def doTransition(transition, historyInfo=None):
""" Execute a transition; the transition is specified by its name.
The ``transition`` argument may be an iterable; in this case
its elements will be checked against the available transitions
and the first one that's available will be executed.
The ``historyInfo`` argument is an arbitrary object that will be
used for recording the transition execution in the history
(only if the context object is adaptable to IHistorizable).
"""
def getAvailableTransitions():
""" Return the transitions for this object that are available in
the current state. The implementation of the returned transition
objects is not specified, they may be action dictionaries or
special Transition objects.
the current state. The returned transition objects should
provide the ITransition interface.
"""
class IHistorizable(Interface):
""" An object that may record history information, e.g. when
performing a state transition.
"""
def record(info):
""" Record the information given (typically a mapping) with the
object.
"""
def recordTransition(stateFrom, stateTo, transition, historyInfo=None):
""" Record the state transition characterized by the arguments
(names of the states and the transition), optionally
supplemented by the additional history information given.
"""