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:
parent
c701a05d9e
commit
89510875c9
5 changed files with 107 additions and 36 deletions
|
@ -59,11 +59,13 @@ class Field(Component):
|
||||||
def name(self):
|
def name(self):
|
||||||
return self.__name__
|
return self.__name__
|
||||||
|
|
||||||
@property
|
def getDefaultValue(self):
|
||||||
def defaultValue(self):
|
|
||||||
if callable(self.default):
|
if callable(self.default):
|
||||||
return self.default()
|
return self.default()
|
||||||
return self.default
|
return self.default
|
||||||
|
def setDefaultValue(self, value):
|
||||||
|
self.default = value
|
||||||
|
defaultValue = property(getDefaultValue, setDefaultValue)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fieldRenderer(self):
|
def fieldRenderer(self):
|
||||||
|
|
|
@ -32,6 +32,7 @@ from cybertools.organize.interfaces import serviceCategories
|
||||||
from cybertools.composer.interfaces import IInstance
|
from cybertools.composer.interfaces import IInstance
|
||||||
from cybertools.composer.schema.browser.common import BaseView as SchemaBaseView
|
from cybertools.composer.schema.browser.common import BaseView as SchemaBaseView
|
||||||
from cybertools.composer.schema.interfaces import IClientFactory
|
from cybertools.composer.schema.interfaces import IClientFactory
|
||||||
|
from cybertools.stateful.interfaces import IStateful
|
||||||
from cybertools.util.format import formatDate
|
from cybertools.util.format import formatDate
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,6 +98,7 @@ class ServiceManagerView(BaseView):
|
||||||
first = tpl
|
first = tpl
|
||||||
return first
|
return first
|
||||||
|
|
||||||
|
#@Lazy - Zope 2.9 compatibility
|
||||||
def registrationUrl(self):
|
def registrationUrl(self):
|
||||||
tpl = self.getRegistrationTemplate()
|
tpl = self.getRegistrationTemplate()
|
||||||
return self.getUrlForObject(tpl)
|
return self.getUrlForObject(tpl)
|
||||||
|
@ -170,7 +172,8 @@ class CheckoutView(ServiceManagerView):
|
||||||
return True # TODO: error, redirect to overview
|
return True # TODO: error, redirect to overview
|
||||||
regs = IClientRegistrations(client).getRegistrations()
|
regs = IClientRegistrations(client).getRegistrations()
|
||||||
for reg in regs:
|
for reg in regs:
|
||||||
pass # set state to submitted,
|
stateful = IStateful(reg)
|
||||||
|
stateful.doTransition(('submit', 'change'))
|
||||||
# send mail
|
# send mail
|
||||||
# find thank you message and redirect to it
|
# find thank you message and redirect to it
|
||||||
params = '?message=thankyou&id=' + self.clientName
|
params = '?message=thankyou&id=' + self.clientName
|
||||||
|
@ -190,6 +193,7 @@ class ServiceView(BaseView):
|
||||||
man = context.getManager()
|
man = context.getManager()
|
||||||
return ServiceManagerView(man, self.request).getRegistrationTemplate()
|
return ServiceManagerView(man, self.request).getRegistrationTemplate()
|
||||||
|
|
||||||
|
#@Lazy - Zope 2.9 compatibility
|
||||||
def registrationUrl(self):
|
def registrationUrl(self):
|
||||||
tpl = self.getRegistrationTemplate()
|
tpl = self.getRegistrationTemplate()
|
||||||
return self.getUrlForObject(tpl)
|
return self.getUrlForObject(tpl)
|
||||||
|
@ -213,6 +217,12 @@ class ServiceView(BaseView):
|
||||||
instance = IInstance(client)
|
instance = IInstance(client)
|
||||||
return instance.applyTemplate()
|
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):
|
def update(self):
|
||||||
newClient = False
|
newClient = False
|
||||||
nextUrl = None
|
nextUrl = None
|
||||||
|
|
|
@ -33,6 +33,7 @@ from zope.interface import implements, Interface
|
||||||
from cybertools.composer.interfaces import IInstance
|
from cybertools.composer.interfaces import IInstance
|
||||||
from cybertools.composer.rule.base import RuleManager, EventType
|
from cybertools.composer.rule.base import RuleManager, EventType
|
||||||
from cybertools.composer.schema.interfaces import IClientManager, IClient
|
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 registerStatesDefinition
|
||||||
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
|
||||||
|
@ -97,11 +98,30 @@ class ServiceManager(RuleManager):
|
||||||
return self.rules
|
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):
|
class Service(object):
|
||||||
|
|
||||||
implements(IService)
|
implements(IService)
|
||||||
|
|
||||||
registrationsFactory = OOBTree
|
registrationsFactory = OOBTree
|
||||||
|
registrationFactory = PersistentRegistration
|
||||||
|
|
||||||
manager = None
|
manager = None
|
||||||
category = None
|
category = None
|
||||||
|
@ -150,9 +170,9 @@ class Service(object):
|
||||||
reg = self.registrations[clientName]
|
reg = self.registrations[clientName]
|
||||||
if number != reg.number:
|
if number != reg.number:
|
||||||
reg.number = number
|
reg.number = number
|
||||||
self.registrations[clientName] = reg # persistence hack
|
#self.registrations[clientName] = reg # persistence hack
|
||||||
return reg
|
return reg
|
||||||
reg = Registration(client, self, number)
|
reg = self.registrationFactory(client, self, number)
|
||||||
self.registrations[clientName] = reg
|
self.registrations[clientName] = reg
|
||||||
return reg
|
return reg
|
||||||
#if self.availableCapacity:
|
#if self.availableCapacity:
|
||||||
|
@ -184,20 +204,7 @@ class ScheduledService(Service):
|
||||||
return getattr(self.getManager(), 'end', None)
|
return getattr(self.getManager(), 'end', None)
|
||||||
|
|
||||||
|
|
||||||
# registration
|
# registration stuff
|
||||||
|
|
||||||
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 RegistrationTemplate(object):
|
class RegistrationTemplate(object):
|
||||||
|
|
||||||
|
@ -253,7 +260,6 @@ class ClientRegistrations(object):
|
||||||
service.unregister(self.context)
|
service.unregister(self.context)
|
||||||
|
|
||||||
def getRegistrations(self):
|
def getRegistrations(self):
|
||||||
# TODO: restrict to services on this template
|
|
||||||
regs = getattr(self.context, self.registrationsAttributeName, [])
|
regs = getattr(self.context, self.registrationsAttributeName, [])
|
||||||
if self.template is not None:
|
if self.template is not None:
|
||||||
svcs = self.template.getServices().values()
|
svcs = self.template.getServices().values()
|
||||||
|
@ -261,19 +267,26 @@ class ClientRegistrations(object):
|
||||||
return regs
|
return regs
|
||||||
|
|
||||||
|
|
||||||
# registration states definition
|
# registration states
|
||||||
|
|
||||||
|
registrationStates = 'organize.service.registration'
|
||||||
|
|
||||||
registerStatesDefinition(
|
registerStatesDefinition(
|
||||||
StatesDefinition('organize.service.registration',
|
StatesDefinition(registrationStates,
|
||||||
State('temporary', 'temporary', ('submit', 'cancel',)),
|
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('cancelled', 'cancelled', ('submit',)),
|
||||||
State('retracted', 'retracted', ('submit',)),
|
State('retracted', 'retracted', ('submit',)),
|
||||||
State('waiting', 'waiting', ('retract', 'confirm', 'reject',)),
|
State('waiting', 'waiting',
|
||||||
State('confirmed', 'confirmed', ('retract', 'reject',)),
|
('change', 'retract', 'confirm', 'reject',)),
|
||||||
State('rejected', 'rejected', ('retract', 'setwaiting', 'confirm',)),
|
State('confirmed', 'confirmed',
|
||||||
|
('change', 'retract', 'reject',)),
|
||||||
|
State('rejected', 'rejected',
|
||||||
|
('change', 'retract', 'setwaiting', 'confirm',)),
|
||||||
Transition('cancel', 'Cancel registration', 'cancelled'),
|
Transition('cancel', 'Cancel registration', 'cancelled'),
|
||||||
Transition('submit', 'Submit registration', 'submitted'),
|
Transition('submit', 'Submit registration', 'submitted'),
|
||||||
|
Transition('change', 'Change registration', 'submitted'),
|
||||||
Transition('retract', 'Retract registration', 'retracted'),
|
Transition('retract', 'Retract registration', 'retracted'),
|
||||||
Transition('setwaiting', 'Set on waiting list', 'waiting'),
|
Transition('setwaiting', 'Set on waiting list', 'waiting'),
|
||||||
Transition('confirm', 'Confirm registration', 'confirmed'),
|
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((
|
eventTypes = Jeep((
|
||||||
EventType('service.checkout'),
|
EventType('service.checkout'),
|
||||||
|
@ -297,3 +317,11 @@ def clientRemoved(obj, event):
|
||||||
regs = IClientRegistrations(obj)
|
regs = IClientRegistrations(obj)
|
||||||
for r in regs.getRegistrations():
|
for r in regs.getRegistrations():
|
||||||
r.service.unregister(obj)
|
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])
|
||||||
|
|
||||||
|
|
|
@ -47,11 +47,18 @@ class Stateful(object):
|
||||||
state = self.getState()
|
state = self.getState()
|
||||||
return self.getStatesDefinition().states[state]
|
return self.getStatesDefinition().states[state]
|
||||||
|
|
||||||
def doTransition(self, transition):
|
def doTransition(self, transition, historyInfo=None):
|
||||||
""" execute transition.
|
|
||||||
"""
|
|
||||||
sd = self.getStatesDefinition()
|
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):
|
def getAvailableTransitions(self):
|
||||||
sd = self.getStatesDefinition()
|
sd = self.getStatesDefinition()
|
||||||
|
|
|
@ -50,18 +50,42 @@ class IStateful(Interface):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def getStateObject():
|
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.
|
""" 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():
|
def getAvailableTransitions():
|
||||||
""" Return the transitions for this object that are available in
|
""" Return the transitions for this object that are available in
|
||||||
the current state. The implementation of the returned transition
|
the current state. The returned transition objects should
|
||||||
objects is not specified, they may be action dictionaries or
|
provide the ITransition interface.
|
||||||
special Transition objects.
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue