view for registrations listing for feedback message; improvements of registration forms

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2176 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-11-14 09:06:27 +00:00
parent be088b1f63
commit 7f184927bd
9 changed files with 77 additions and 26 deletions

View file

@ -11,7 +11,7 @@ Message Management
>>> messageText = '''Dear $person.firstname $person.lastname, >>> messageText = '''Dear $person.firstname $person.lastname,
... You have been registered for the following $services. ... You have been registered for the following $services.
... $@@list_registrations ... $@@list_registrations_text
... $footer ... $footer
... ''' ... '''
@ -27,7 +27,7 @@ Message interpolation
>>> t = MessageTemplate(messageText) >>> t = MessageTemplate(messageText)
>>> print t.safe_substitute({ >>> print t.safe_substitute({
... 'person.firstname': 'John', 'person.lastname': 'Smith', ... 'person.firstname': 'John', 'person.lastname': 'Smith',
... '@@list_registrations': '0815: Python Introduction', ... '@@list_registrations_text': '0815: Python Introduction',
... 'services': 'events', ... 'services': 'events',
... 'footer': 'Regards, $sender'}) ... 'footer': 'Regards, $sender'})
Dear John Smith, Dear John Smith,
@ -43,9 +43,9 @@ Working with message instances
>>> mi = MessageInstance(None, manager.messages['feedback_text'], manager) >>> mi = MessageInstance(None, manager.messages['feedback_text'], manager)
>>> for key, value in mi.applyTemplate().items(): >>> for key, value in mi.applyTemplate().items():
... print key + ':', value ... print key + ':', value
subjectLine:
text: Dear $person.firstname $person.lastname, text: Dear $person.firstname $person.lastname,
You have been registered for the following events. You have been registered for the following events.
$@@list_registrations $@@list_registrations_text
Best regards, Jack Best regards, Jack
<BLANKLINE> <BLANKLINE>
subjectLine:

View file

@ -42,16 +42,20 @@ class MessageInstance(Instance):
self.manager = manager self.manager = manager
def applyTemplate(self, data=None, **kw): def applyTemplate(self, data=None, **kw):
data = DataProvider(self) if data is None:
text = MessageTemplate(self.template.text).safe_substitute(data) data = {}
dp = DataProvider(self, data)
text = MessageTemplate(self.template.text).safe_substitute(dp)
subject = self.template.subjectLine subject = self.template.subjectLine
return Jeep((('subjectLine', subject), ('text', text))) data.update(dict(subjectLine=subject, text=text))
return data
class DataProvider(object): class DataProvider(object):
def __init__(self, context): def __init__(self, context, data):
self.context = context self.context = context
self.data = data
def __getitem__(self, key): def __getitem__(self, key):
client = self.context.client client = self.context.client
@ -61,8 +65,9 @@ class DataProvider(object):
viewName = key[2:] viewName = key[2:]
if client is None: if client is None:
return '$' + key return '$' + key
request = self.data.get('request') or TestRequest()
view = component.queryMultiAdapter( view = component.queryMultiAdapter(
(client.manager, TestRequest()), name=viewName) (client.manager, request), name=viewName)
if view is not None: if view is not None:
return view() return view()
else: else:
@ -72,7 +77,7 @@ class DataProvider(object):
# (client, messageManager.messages[key]), IInstance) # (client, messageManager.messages[key]), IInstance)
mi = MessageInstance(client, messageManager.messages[key], mi = MessageInstance(client, messageManager.messages[key],
messageManager) messageManager)
return mi.applyTemplate().text return mi.applyTemplate()['text']
elif '.' in key: elif '.' in key:
if client is None: if client is None:
return '$' + key return '$' + key

View file

@ -34,4 +34,4 @@ Rule-based Execution of Actions
>>> client = Client() >>> client = Client()
>>> manager.handleEvent(Event(checkoutEvent, client)) >>> manager.handleEvent(Event(checkoutEvent, client))
[{}] [{'request': None}]

View file

@ -99,11 +99,12 @@ class Event(object):
implements(IEvent) implements(IEvent)
def __init__(self, eventType, context=None): def __init__(self, eventType, context=None, request=None):
self.eventType = eventType self.eventType = eventType
self.name = eventType.name self.name = eventType.name
self.title = eventType.title self.title = eventType.title
self.context = context self.context = context
self.request = request
# conditions # conditions

View file

@ -43,7 +43,7 @@ class RuleInstance(Instance):
cond = component.getAdapter(self, ICondition, name=c) cond = component.getAdapter(self, ICondition, name=c)
if not cond(): if not cond():
continue continue
data = {} data = dict(request=self.event.request)
for action in self.template.actions: for action in self.template.actions:
handler = component.getAdapter(self, IActionHandler, handler = component.getAdapter(self, IActionHandler,
name=action.handlerName) name=action.handlerName)

View file

@ -96,6 +96,8 @@ class IEvent(Interface):
name = Attribute('The name by which the event will be identified.') name = Attribute('The name by which the event will be identified.')
title = Attribute('A human readable title or label.') title = Attribute('A human readable title or label.')
context = Attribute('An object that is associated with the event.') context = Attribute('An object that is associated with the event.')
request = Attribute('Optional: the browser request that is associated '
'with the event.')
class ICondition(Interface): class ICondition(Interface):

View file

@ -37,7 +37,8 @@ class MailActionHandler(ActionHandler):
client = self.context.context client = self.context.context
clientData = IInstance(client).applyTemplate() clientData = IInstance(client).applyTemplate()
recipient = clientData['standard.email'] recipient = clientData['standard.email']
msg = self.prepareMessage(data.subjectLine, data.text, sender, recipient) msg = self.prepareMessage(data['subjectLine'], data['text'],
sender, recipient)
data['mailInfo'] = self.sendMail(msg.as_string(), sender, [recipient]) data['mailInfo'] = self.sendMail(msg.as_string(), sender, [recipient])
return data return data

View file

@ -118,15 +118,15 @@ class ServiceManagerView(BaseView):
result = [] result = []
classific = [] classific = []
category = None category = None
maxLevel = 0
svcs = sorted((svc.getCategory(), idx, svc) svcs = sorted((svc.getCategory(), idx, svc)
for idx, svc in enumerate(self.context.getServices())) for idx, svc in enumerate(self.context.getServices()))
for cat, idx, svc in svcs: for cat, idx, svc in svcs:
if includeCategories and cat not in includeCategories: if includeCategories and cat not in includeCategories:
continue continue
level = 0
if cat != category: if cat != category:
term = serviceCategories.getTermByToken(cat) term = serviceCategories.getTermByToken(cat)
result.append(dict(isHeadline=True, level=0, title=term.title, result.append(dict(isHeadline=True, level=level, title=term.title,
name=cat, name=cat,
object=None)) object=None))
category = cat category = cat
@ -141,10 +141,8 @@ class ServiceManagerView(BaseView):
title=element.title, title=element.title,
object=element.object, object=element.object,
view=None)) view=None))
classific = clsf classific = clsf[:idx+1]
if level > maxLevel: result.append(dict(isHeadline=False, level=level+1,
maxLevel = level
result.append(dict(isHeadline=False, level=maxLevel+1,
name=svc.getName(), name=svc.getName(),
title=svc.title or svc.getName(), title=svc.title or svc.getName(),
fromTo=self.getFromTo(svc), fromTo=self.getFromTo(svc),
@ -190,12 +188,27 @@ class CheckoutView(ServiceManagerView):
# send mail # send mail
rm = IRuleManager(self.manager) rm = IRuleManager(self.manager)
rm.addRule(getCheckoutRule(self.manager.senderEmail)) rm.addRule(getCheckoutRule(self.manager.senderEmail))
rm.handleEvent(Event(eventTypes['service.checkout'], client)) rm.handleEvent(Event(eventTypes['service.checkout'], client, self.request))
# 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
self.request.response.redirect(self.url + '/checkout.html' + params) self.request.response.redirect(self.url + '/checkout.html' + params)
return False return False
def listRegistrationsText(self):
client = self.getClient()
if client is None:
return 'Error: no client given.'
result = []
regs = IClientRegistrations(client)
regs = sorted(regs.getRegistrations(), key=self.sortKey)
for reg in regs:
service = reg.service
line = '%-30s %27s' % (service.title, self.getFromTo(service))
if service.allowRegWithNumber:
line += ' %4i' % reg.number
result.append(line)
return '\n'.join(result)
class ServiceView(BaseView): class ServiceView(BaseView):
@ -215,6 +228,16 @@ class ServiceView(BaseView):
tpl = self.getRegistrationTemplate() tpl = self.getRegistrationTemplate()
return self.getUrlForObject(tpl) return self.getUrlForObject(tpl)
def allowRegistration(self):
context = self.context
if not context.allowDirectRegistration:
return False
return (self.capacityAvailable()
or self.getClientName() in context.registrations)
def capacityAvailable(self):
return not self.context.capacity or self.context.availableCapacity
def getClientData(self): def getClientData(self):
clientName = self.getClientName() clientName = self.getClientName()
if clientName is None: if clientName is None:
@ -271,7 +294,9 @@ class ServiceView(BaseView):
nextUrl = self.getSchemaUrl() nextUrl = self.getSchemaUrl()
regs = self.state = IClientRegistrations(client) regs = self.state = IClientRegistrations(client)
try: try:
number = int(form.get('number', 1)) number = int(form.get('number', 0))
if number < 0:
number = 0
except ValueError: except ValueError:
number = 1 number = 1
regs.validate(clientName, [self.context], [number]) regs.validate(clientName, [self.context], [number])
@ -318,6 +343,13 @@ class RegistrationTemplateView(BaseView):
def sortKey(self, svc): def sortKey(self, svc):
return (svc.category, svc.getClassification(), svc.start) return (svc.category, svc.getClassification(), svc.start)
def allowRegistration(self, service):
return (self.capacityAvailable(service)
or service in self.getRegisteredServices())
def capacityAvailable(self, service):
return not service.capacity or service.availableCapacity
def getRegistrations(self): def getRegistrations(self):
clientName = self.getClientName() clientName = self.getClientName()
if not clientName: if not clientName:
@ -330,8 +362,11 @@ class RegistrationTemplateView(BaseView):
regs.template = self.context regs.template = self.context
return regs.getRegistrations() return regs.getRegistrations()
def getRegisteredServices(self):
return [r.service for r in self.getRegistrations()]
def getRegisteredServicesTokens(self): def getRegisteredServicesTokens(self):
return [r.service.token for r in self.getRegistrations()] return [s.token for s in self.getRegisteredServices()]
def getRegistrationsDict(self): def getRegistrationsDict(self):
return dict((r.service.token, r) for r in self.getRegistrations()) return dict((r.service.token, r) for r in self.getRegistrations())
@ -377,7 +412,7 @@ class RegistrationTemplateView(BaseView):
try: try:
value = int(form.get('service.' + token, 0)) value = int(form.get('service.' + token, 0))
except ValueError: except ValueError:
value = 1 value = 0
if value > 0: if value > 0:
newServices.append(svc) newServices.append(svc)
numbers.append(value) numbers.append(value)

View file

@ -39,6 +39,7 @@ 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
from cybertools.stateful.interfaces import IStateful
from cybertools.util.jeep import Jeep from cybertools.util.jeep import Jeep
from cybertools.util.randomname import generateName from cybertools.util.randomname import generateName
from cybertools.organize.interfaces import IServiceManager from cybertools.organize.interfaces import IServiceManager
@ -179,9 +180,11 @@ class Service(object):
if clientName in self.registrations: if clientName in self.registrations:
del self.registrations[clientName] del self.registrations[clientName]
def getNumberRegistered(self): def getNumberRegistered(self, ignoreTemporary=True):
result = 0 result = 0
for r in self.registrations.values(): for r in self.registrations.values():
if ignoreTemporary and IStateful(r).state == 'temporary':
continue
result += r.number result += r.number
return result return result
@ -277,7 +280,11 @@ class ClientRegistrations(object):
for svc, n in zip(services, numbers): for svc, n in zip(services, numbers):
if clientName: if clientName:
oldReg = svc.registrations.get(clientName, None) oldReg = svc.registrations.get(clientName, None)
oldN = oldReg and oldReg.number or 0 if oldReg is None or IStateful(oldReg).state == 'temporary':
# availableCapacity does not consider temporary registrations
oldN = 0
else:
oldN = oldReg.number or 0
else: else:
oldN = 0 oldN = 0
if svc.capacity and svc.capacity > 0 and svc.availableCapacity < n - oldN: if svc.capacity and svc.capacity > 0 and svc.availableCapacity < n - oldN: