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:
parent
be088b1f63
commit
7f184927bd
9 changed files with 77 additions and 26 deletions
|
@ -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:
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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}]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Reference in a new issue