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

View file

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

View file

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

View file

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

View file

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

View file

@ -96,6 +96,8 @@ class IEvent(Interface):
name = Attribute('The name by which the event will be identified.')
title = Attribute('A human readable title or label.')
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):

View file

@ -37,7 +37,8 @@ class MailActionHandler(ActionHandler):
client = self.context.context
clientData = IInstance(client).applyTemplate()
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])
return data

View file

@ -118,15 +118,15 @@ class ServiceManagerView(BaseView):
result = []
classific = []
category = None
maxLevel = 0
svcs = sorted((svc.getCategory(), idx, svc)
for idx, svc in enumerate(self.context.getServices()))
for cat, idx, svc in svcs:
if includeCategories and cat not in includeCategories:
continue
level = 0
if cat != category:
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,
object=None))
category = cat
@ -141,10 +141,8 @@ class ServiceManagerView(BaseView):
title=element.title,
object=element.object,
view=None))
classific = clsf
if level > maxLevel:
maxLevel = level
result.append(dict(isHeadline=False, level=maxLevel+1,
classific = clsf[:idx+1]
result.append(dict(isHeadline=False, level=level+1,
name=svc.getName(),
title=svc.title or svc.getName(),
fromTo=self.getFromTo(svc),
@ -190,12 +188,27 @@ class CheckoutView(ServiceManagerView):
# send mail
rm = IRuleManager(self.manager)
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
params = '?message=thankyou&id=' + self.clientName
self.request.response.redirect(self.url + '/checkout.html' + params)
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):
@ -215,6 +228,16 @@ class ServiceView(BaseView):
tpl = self.getRegistrationTemplate()
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):
clientName = self.getClientName()
if clientName is None:
@ -271,7 +294,9 @@ class ServiceView(BaseView):
nextUrl = self.getSchemaUrl()
regs = self.state = IClientRegistrations(client)
try:
number = int(form.get('number', 1))
number = int(form.get('number', 0))
if number < 0:
number = 0
except ValueError:
number = 1
regs.validate(clientName, [self.context], [number])
@ -318,6 +343,13 @@ class RegistrationTemplateView(BaseView):
def sortKey(self, svc):
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):
clientName = self.getClientName()
if not clientName:
@ -330,8 +362,11 @@ class RegistrationTemplateView(BaseView):
regs.template = self.context
return regs.getRegistrations()
def getRegisteredServices(self):
return [r.service for r in self.getRegistrations()]
def getRegisteredServicesTokens(self):
return [r.service.token for r in self.getRegistrations()]
return [s.token for s in self.getRegisteredServices()]
def getRegistrationsDict(self):
return dict((r.service.token, r) for r in self.getRegistrations())
@ -377,7 +412,7 @@ class RegistrationTemplateView(BaseView):
try:
value = int(form.get('service.' + token, 0))
except ValueError:
value = 1
value = 0
if value > 0:
newServices.append(svc)
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 StatesDefinition
from cybertools.stateful.definition import State, Transition
from cybertools.stateful.interfaces import IStateful
from cybertools.util.jeep import Jeep
from cybertools.util.randomname import generateName
from cybertools.organize.interfaces import IServiceManager
@ -179,9 +180,11 @@ class Service(object):
if clientName in self.registrations:
del self.registrations[clientName]
def getNumberRegistered(self):
def getNumberRegistered(self, ignoreTemporary=True):
result = 0
for r in self.registrations.values():
if ignoreTemporary and IStateful(r).state == 'temporary':
continue
result += r.number
return result
@ -277,7 +280,11 @@ class ClientRegistrations(object):
for svc, n in zip(services, numbers):
if clientName:
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:
oldN = 0
if svc.capacity and svc.capacity > 0 and svc.availableCapacity < n - oldN: