move doctests from cyberapps.tum to cybertools.organize
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@4147 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
		
							parent
							
								
									7e2150f81c
								
							
						
					
					
						commit
						42565dc685
					
				
					 5 changed files with 823 additions and 5 deletions
				
			
		| 
						 | 
					@ -57,10 +57,8 @@ Tasks
 | 
				
			||||||
  >>> from cybertools.organize.task import Task
 | 
					  >>> from cybertools.organize.task import Task
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Service Management
 | 
					Service and Form Management
 | 
				
			||||||
==================
 | 
					===========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  >>> from cybertools.organize.service import Service
 | 
					See servicemanager.txt and formmanager.txt.
 | 
				
			||||||
 | 
					 | 
				
			||||||
(See cyberapps.tumsm for comprehensive description and tests.)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										38
									
								
								organize/formmanager.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								organize/formmanager.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					Form Manager
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ($Id$)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This package does not provide functionality on its own but shows only
 | 
				
			||||||
 | 
					how to integrate other packages into an application package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
 | 
				
			||||||
 | 
					  >>> site = placefulSetUp(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.tests import setUp
 | 
				
			||||||
 | 
					  >>> setUp(site)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope import component
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer import schema
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.schema import client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Setting up a Form Manager
 | 
				
			||||||
 | 
					=========================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> fm = client.ClientManager()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Form Manager Views
 | 
				
			||||||
 | 
					==================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.schema.browser.schema import FormManagerView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fin de partie
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> placefulTearDown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,6 +346,20 @@ class IScheduledService(IService):
 | 
				
			||||||
    duration = Attribute('Time delta between start and end date/time.')
 | 
					    duration = Attribute('Time delta between start and end date/time.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ICompoundService(IService):
 | 
				
			||||||
 | 
					    """ A service that consists of a set of sub-services, e.g. a conference,
 | 
				
			||||||
 | 
					        a course or a multi-day seminar.
 | 
				
			||||||
 | 
					        Sub-services may be other compound services or simple services; 
 | 
				
			||||||
 | 
					        in addition there may be service parts additional strucure elements.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class IServicePart(IService):
 | 
				
			||||||
 | 
					    """ A service that provides a substructure element of a compound service,
 | 
				
			||||||
 | 
					        e.g. a conference track or a conference day.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IClient(Interface):
 | 
					class IClient(Interface):
 | 
				
			||||||
    """ An fairly abstract interface for objects to be used as clients
 | 
					    """ An fairly abstract interface for objects to be used as clients
 | 
				
			||||||
        for services.
 | 
					        for services.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										752
									
								
								organize/servicemanager.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										752
									
								
								organize/servicemanager.txt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,752 @@
 | 
				
			||||||
 | 
					===============
 | 
				
			||||||
 | 
					Service Manager
 | 
				
			||||||
 | 
					================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ($Id$)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This package does not provide functionality on its own but shows only
 | 
				
			||||||
 | 
					how to integrate other packages into an application package.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
 | 
				
			||||||
 | 
					  >>> site = placefulSetUp(True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.tests import setUp
 | 
				
			||||||
 | 
					  >>> setUp(site)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope import component
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer import schema
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.interfaces import IInstance
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.schema.interfaces import IClientFactory
 | 
				
			||||||
 | 
					  >>> from cybertools.organize import service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Setting up a Service Manager
 | 
				
			||||||
 | 
					============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A service manager is a collection of individual services; in our
 | 
				
			||||||
 | 
					example the service manager represents a workshop with two
 | 
				
			||||||
 | 
					parts (events, lectures, ...).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> workshop = site['workshop'] = service.ServiceManager()
 | 
				
			||||||
 | 
					  >>> workshop.__parent__ = site
 | 
				
			||||||
 | 
					  >>> workshop.__name__ = 'workshop'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> event1 = service.ScheduledService('event1', category='event', manager=workshop,
 | 
				
			||||||
 | 
					  ...                                   title=u'Event 1', capacity=5)
 | 
				
			||||||
 | 
					  >>> event2 = service.ScheduledService('event2', category='event', manager=workshop,
 | 
				
			||||||
 | 
					  ...                                   title=u'Event 2')
 | 
				
			||||||
 | 
					  >>> workshop.services.append(event1)
 | 
				
			||||||
 | 
					  >>> workshop.services.append(event2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In order to be able to registrate participants for the workshop we
 | 
				
			||||||
 | 
					have to provide data structures for the participants (the service
 | 
				
			||||||
 | 
					clients. This is done via to form descriptions (schemas), one for the
 | 
				
			||||||
 | 
					personal data (first name, last name), and one for the address.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> workshop.clientSchemas.append(schema.Schema(
 | 
				
			||||||
 | 
					  ...               schema.Field('lastName', u'Last Name', required=True,
 | 
				
			||||||
 | 
					  ...                            standardFieldName='lastName'),
 | 
				
			||||||
 | 
					  ...               schema.Field('firstName', u'First Name'),
 | 
				
			||||||
 | 
					  ...               schema.Field('email', u'Email Address', required=True,
 | 
				
			||||||
 | 
					  ...                            fieldType='email', standardFieldName='email'),
 | 
				
			||||||
 | 
					  ...               schema.Field('age', u'Age', fieldType='number'),
 | 
				
			||||||
 | 
					  ...               schema.Field('addr', u'Personal Address', required=True,
 | 
				
			||||||
 | 
					  ...                            fieldtype='radiobuttons',
 | 
				
			||||||
 | 
					  ...                            vocabulary=u'Mrs\nMr'),
 | 
				
			||||||
 | 
					  ...               schema.Field('acadTitles', u'Academic Titles',
 | 
				
			||||||
 | 
					  ...                            fieldtype='checkboxes',
 | 
				
			||||||
 | 
					  ...                            vocabulary=u'Prof.\nDr.'),
 | 
				
			||||||
 | 
					  ...               name='person',
 | 
				
			||||||
 | 
					  ...               manager=workshop,
 | 
				
			||||||
 | 
					  ... ))
 | 
				
			||||||
 | 
					  >>> workshop.clientSchemas.append(schema.Schema(
 | 
				
			||||||
 | 
					  ...               schema.Field('street', u'Street'),
 | 
				
			||||||
 | 
					  ...               schema.Field('city', u'City', required=True),
 | 
				
			||||||
 | 
					  ...               schema.Field('country', u'Country', required=True,
 | 
				
			||||||
 | 
					  ...                            fieldType='dropdown', vocabulary=u'USA\nGermany'),
 | 
				
			||||||
 | 
					  ...               name='address',
 | 
				
			||||||
 | 
					  ...               manager=workshop,
 | 
				
			||||||
 | 
					  ... ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Registration of Clients
 | 
				
			||||||
 | 
					=======================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					So we are now ready to register participants.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> client1 = IClientFactory(workshop)()
 | 
				
			||||||
 | 
					  >>> client1Name = workshop.addClient(client1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> data = dict(addr=u'Mr', lastName=u'Skywalker', email='luke@skywalker.universe')
 | 
				
			||||||
 | 
					  >>> inst = component.getAdapter(client1, IInstance, name='editor')
 | 
				
			||||||
 | 
					  >>> inst.template = workshop.clientSchemas['person']
 | 
				
			||||||
 | 
					  >>> state = inst.applyTemplate(data=data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> list(client1.__schema_attributes__)
 | 
				
			||||||
 | 
					  ['schema.client.__standard__', 'schema.client.person']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> client1.__schema_attributes__['schema.client.person']['lastName']
 | 
				
			||||||
 | 
					  u'Skywalker'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Instead of directly peeking into the attributes we can also use a
 | 
				
			||||||
 | 
					suitable instance adapter.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> inst = IInstance(client1)
 | 
				
			||||||
 | 
					  >>> inst.template = workshop.clientSchemas['person']
 | 
				
			||||||
 | 
					  >>> inst.applyTemplate()
 | 
				
			||||||
 | 
					  {'acadTitles': u'', 'standard.lastName': u'Skywalker', 'addr': u'Mr',
 | 
				
			||||||
 | 
					   'firstName': u'', 'lastName': u'Skywalker', 'age': '', '__name__': '...',
 | 
				
			||||||
 | 
					   'email': u'luke@skywalker.universe',
 | 
				
			||||||
 | 
					   'standard.email': u'luke@skywalker.universe'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Note that the ``standardFieldName`` setting for the ``lastName`` field
 | 
				
			||||||
 | 
					results in a 'standard.lastName' entry; this technique may be used to
 | 
				
			||||||
 | 
					retrieve certain standard informations from a client without having to
 | 
				
			||||||
 | 
					use a template.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using schema views for displaying and editing data
 | 
				
			||||||
 | 
					--------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We need some additional setup for working with schema views - so we have to
 | 
				
			||||||
 | 
					supply some session handling stuff in order to work with client names.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope.interface import implements
 | 
				
			||||||
 | 
					  >>> from zope.app.session.interfaces import IClientIdManager, ISessionDataContainer
 | 
				
			||||||
 | 
					  >>> from zope.app.session import session
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(session.ClientId)
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(session.Session)
 | 
				
			||||||
 | 
					  >>> component.provideUtility(session.RAMSessionDataContainer(), ISessionDataContainer)
 | 
				
			||||||
 | 
					  >>> class ClientIdManager(object):
 | 
				
			||||||
 | 
					  ...     implements(IClientIdManager)
 | 
				
			||||||
 | 
					  ...     def getClientId(self, request): return 'dummy'
 | 
				
			||||||
 | 
					  >>> component.provideUtility(ClientIdManager())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from zope.publisher.browser import TestRequest
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.schema.browser.schema import SchemaView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> request = TestRequest()
 | 
				
			||||||
 | 
					  >>> schema = workshop.clientSchemas['person']
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's have a closer look at some of the view's attributes.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> [f.name for f in view.fields]
 | 
				
			||||||
 | 
					  ['lastName', 'firstName', 'email', 'age', 'addr', 'acadTitles']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> view.data
 | 
				
			||||||
 | 
					  {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Providing an id will enable the view to return the data of
 | 
				
			||||||
 | 
					the corresponding client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client1Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.data
 | 
				
			||||||
 | 
					  {'acadTitles': u'', 'standard.lastName': u'Skywalker', 'addr': u'Mr',
 | 
				
			||||||
 | 
					   'firstName': u'', 'lastName': u'Skywalker', 'age': '', '__name__': '...',
 | 
				
			||||||
 | 
					   'email': u'luke@skywalker.universe',
 | 
				
			||||||
 | 
					   'standard.email': u'luke@skywalker.universe'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When we provide data and an 'update' action a new client object will
 | 
				
			||||||
 | 
					be created - if we clear the client name in the session first via
 | 
				
			||||||
 | 
					``view.setClientName('')``.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(lastName='Solo', firstName='Han', email='han.solo@space.net',
 | 
				
			||||||
 | 
					  ...              addr=u'Mr', action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.setClientName('')
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> client2Name = view.clientName
 | 
				
			||||||
 | 
					  >>> client2Name != client1Name
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client2Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.data
 | 
				
			||||||
 | 
					  {'acadTitles': u'', 'standard.lastName': u'Solo', 'addr': u'Mr',
 | 
				
			||||||
 | 
					   'firstName': u'Han', 'lastName': u'Solo',
 | 
				
			||||||
 | 
					   'age': '', '__name__': '...', 'email': u'han.solo@space.net',
 | 
				
			||||||
 | 
					   'standard.email': u'han.solo@space.net'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If we provide an id parameter we may also change an existing client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(lastName=u'Skywalker', firstName=u'Luke', id=client1Name,
 | 
				
			||||||
 | 
					  ...              email='luke@skywalker.universe', addr=u'Mr', action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client1Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.data
 | 
				
			||||||
 | 
					  {'acadTitles': u'', 'standard.lastName': u'Skywalker', 'addr': u'Mr',
 | 
				
			||||||
 | 
					   'firstName': u'Luke', 'lastName': u'Skywalker', 'age': '', '__name__': '...',
 | 
				
			||||||
 | 
					   'email': u'luke@skywalker.universe',
 | 
				
			||||||
 | 
					   'standard.email': u'luke@skywalker.universe'}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If we do not provide a value for a required attribute we get a validation
 | 
				
			||||||
 | 
					error and the form will be displayed again.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(firstName=u'Anakin', action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The same happens if we provide a number field with a string that cannot
 | 
				
			||||||
 | 
					be converted to an integer.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(firstName=u'Anakin', lastName=u'Skywalker', age='foo',
 | 
				
			||||||
 | 
					  ...             action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More on special field types
 | 
				
			||||||
 | 
					---------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> schema2 = workshop.clientSchemas['address']
 | 
				
			||||||
 | 
					  >>> countryField = schema2.fields.country
 | 
				
			||||||
 | 
					  >>> countryField.getVocabularyItems()
 | 
				
			||||||
 | 
					  [{'token': u'USA', 'title': u'USA'}, {'token': u'Germany', 'title': u'Germany'}]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Registering for Services Using a Registration Template
 | 
				
			||||||
 | 
					======================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import RegistrationTemplate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> workshop.clientSchemas.append(RegistrationTemplate(
 | 
				
			||||||
 | 
					  ...               name='regform',
 | 
				
			||||||
 | 
					  ...               manager=workshop))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regForm = workshop.clientSchemas['regform']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> list(regForm.services)
 | 
				
			||||||
 | 
					  [<...ScheduledService object...>, <...ScheduledService object...>]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The registration action itself is performed using an IClientRegistrations
 | 
				
			||||||
 | 
					adapter for a client object.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.interfaces import IClientRegistrations
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import ClientRegistrations
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(ClientRegistrations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regs = IClientRegistrations(client1)
 | 
				
			||||||
 | 
					  >>> regs.template = regForm
 | 
				
			||||||
 | 
					  >>> regs.register([regForm.services[0]])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regs = list(regs.getRegistrations())
 | 
				
			||||||
 | 
					  >>> regs
 | 
				
			||||||
 | 
					  [<...Registration object...>]
 | 
				
			||||||
 | 
					  >>> regs[0].client is client1
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Using a registration template view for displaying and editing registration data
 | 
				
			||||||
 | 
					-------------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(Note: after creating a view we usually clear the client name in the session
 | 
				
			||||||
 | 
					using ``view.setClientName('')`` in order to create a new client object.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.browser.service import RegistrationTemplateView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> request = TestRequest()
 | 
				
			||||||
 | 
					  >>> regForm = workshop.clientSchemas['regform']
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> view.setClientName('')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> len(view.services)
 | 
				
			||||||
 | 
					  2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> view.getRegistrations()
 | 
				
			||||||
 | 
					  []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Providing an id will enable the view to return the data of
 | 
				
			||||||
 | 
					the corresponding client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client1Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> regs = list(view.getRegistrations())
 | 
				
			||||||
 | 
					  >>> regs
 | 
				
			||||||
 | 
					  [<...Registration object...>]
 | 
				
			||||||
 | 
					  >>> regs[0].client is client1
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When we provide registration data and an 'update' action a new client object will
 | 
				
			||||||
 | 
					be created.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(service_tokens=['event2'], action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> view.setClientName('')
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> client3Name = view.clientName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client3Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> regs = list(view.getRegistrations())
 | 
				
			||||||
 | 
					  >>> regs
 | 
				
			||||||
 | 
					  [<...Registration object...>]
 | 
				
			||||||
 | 
					  >>> regs[0].client.__name__ == client3Name
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					  >>> regs[0].service.token
 | 
				
			||||||
 | 
					  'event2'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If we provide an id parameter we may also change an existing client.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(service_tokens=['event1'], id=client1Name, action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(id=client1Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> view = RegistrationTemplateView(regForm, request)
 | 
				
			||||||
 | 
					  >>> regs = list(view.getRegistrations())
 | 
				
			||||||
 | 
					  >>> len(regs)
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					  >>> regs[0].service.token
 | 
				
			||||||
 | 
					  'event1'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's finally look at the services and what they know about the clients
 | 
				
			||||||
 | 
					registered for them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> clientNames = [client1Name, client2Name, client3Name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> for service in workshop.getServices():
 | 
				
			||||||
 | 
					  ...     for cn, reg in sorted(service.registrations.items()):
 | 
				
			||||||
 | 
					  ...         print 'client-%i: ' % (clientNames.index(cn)+1), reg.service.name
 | 
				
			||||||
 | 
					  client-1: event1
 | 
				
			||||||
 | 
					  client-3: event2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More on Schema-based Forms and Template Views
 | 
				
			||||||
 | 
					=============================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Navigation
 | 
				
			||||||
 | 
					----------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If a service provides more than one template (schema or registration
 | 
				
			||||||
 | 
					template) the form may show buttons to navigate to the next or previous
 | 
				
			||||||
 | 
					template together with saving the data entered.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> schema = workshop.clientSchemas['person']
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, TestRequest())
 | 
				
			||||||
 | 
					  >>> view.getPreviousTemplate()
 | 
				
			||||||
 | 
					  ''
 | 
				
			||||||
 | 
					  >>> view.getNextTemplate()
 | 
				
			||||||
 | 
					  'http://127.0.0.1/workshop/address'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> schema = workshop.clientSchemas['address']
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, TestRequest())
 | 
				
			||||||
 | 
					  >>> view.getPreviousTemplate()
 | 
				
			||||||
 | 
					  'http://127.0.0.1/workshop/person'
 | 
				
			||||||
 | 
					  >>> view.getNextTemplate()
 | 
				
			||||||
 | 
					  'http://127.0.0.1/workshop/regform'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> schema = workshop.clientSchemas['regform']
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, TestRequest())
 | 
				
			||||||
 | 
					  >>> view.previousTemplate
 | 
				
			||||||
 | 
					  'http://127.0.0.1/workshop/address'
 | 
				
			||||||
 | 
					  >>> view.getNextTemplate()
 | 
				
			||||||
 | 
					  ''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> view.getCheckoutView()
 | 
				
			||||||
 | 
					  'http://127.0.0.1/workshop/checkout.html'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Message Definition and Rule Handling
 | 
				
			||||||
 | 
					====================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Setting up a message manager with messages
 | 
				
			||||||
 | 
					------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> messageText = '''Dear $person.firstName $person.lastName,
 | 
				
			||||||
 | 
					  ... You have been registered for the following $services.
 | 
				
			||||||
 | 
					  ... $@@list_registrations_text
 | 
				
			||||||
 | 
					  ... $footer
 | 
				
			||||||
 | 
					  ... '''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.message.interfaces import IMessageManager
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import MessageManagerAdapter
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(MessageManagerAdapter)
 | 
				
			||||||
 | 
					  >>> messageManager = IMessageManager(workshop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> messageManager.addMessage('feedback_text', messageText,
 | 
				
			||||||
 | 
					  ...                           subjectLine='Workshop Registration')
 | 
				
			||||||
 | 
					  >>> messageManager.addMessage('footer', 'Best regards, $sender')
 | 
				
			||||||
 | 
					  >>> messageManager.addMessage('sender', 'Jack')
 | 
				
			||||||
 | 
					  >>> messageManager.addMessage('services', text='events')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Controlling actions with rules
 | 
				
			||||||
 | 
					------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's first set up a rule with two actions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.base import Rule, Action, Event
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import eventTypes
 | 
				
			||||||
 | 
					  >>> checkoutEvent = eventTypes['service.checkout']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> checkoutRule = Rule('checkout')
 | 
				
			||||||
 | 
					  >>> checkoutRule.events.append(checkoutEvent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> checkoutRule.actions.append(Action('sendmail',
 | 
				
			||||||
 | 
					  ...                   parameters=dict(sender='manager@workshops.com',
 | 
				
			||||||
 | 
					  ...                                   messageName='feedback_text')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We also have to provide rule instance and action handler adapters that
 | 
				
			||||||
 | 
					will do the real work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.instance import RuleInstance
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.interfaces import IRuleInstance
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(RuleInstance, provides=IRuleInstance)
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.mail import MailActionHandler
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.message import MessageActionHandler
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(MessageActionHandler, name='message')
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(MailActionHandler, name='sendmail')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We can now get a rule manager for our workshop and add the rule to it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.interfaces import IRuleManager
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import RuleManagerAdapter
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(RuleManagerAdapter)
 | 
				
			||||||
 | 
					  >>> ruleManager = IRuleManager(workshop)
 | 
				
			||||||
 | 
					  >>> ruleManager.addRule(checkoutRule)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For testing purposes we also have to register a TestMailer that
 | 
				
			||||||
 | 
					just prints the message and other parameters.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.tests import TestMailer
 | 
				
			||||||
 | 
					  >>> from zope.sendmail.interfaces import IMailDelivery
 | 
				
			||||||
 | 
					  >>> component.provideUtility(TestMailer(), provides=IMailDelivery, name='Mail')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We are now ready to trigger a registration checkout.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> result = ruleManager.handleEvent(Event(checkoutEvent, client1))
 | 
				
			||||||
 | 
					  sender: manager@workshops.com
 | 
				
			||||||
 | 
					  recipients: [u'luke@skywalker.universe']
 | 
				
			||||||
 | 
					  subject: Workshop Registration
 | 
				
			||||||
 | 
					  message:
 | 
				
			||||||
 | 
					  Dear Luke Skywalker,
 | 
				
			||||||
 | 
					  You have been registered for the following events.
 | 
				
			||||||
 | 
					  @@list_registrations_text
 | 
				
			||||||
 | 
					  Best regards, Jack
 | 
				
			||||||
 | 
					  <BLANKLINE>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In addition to sending mails we can also control the redirection to a
 | 
				
			||||||
 | 
					feedback or thankyou page with a rule.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> messageHtml = '''<p>Dear $person.firstName $person.lastName,</p>
 | 
				
			||||||
 | 
					  ... <p>You have been registered for the following $services.</p>
 | 
				
			||||||
 | 
					  ... <div>$@@list_registrations_html</div>
 | 
				
			||||||
 | 
					  ... <div>$footer</div>
 | 
				
			||||||
 | 
					  ... '''
 | 
				
			||||||
 | 
					  >>> messageManager.addMessage('feedback_html', messageHtml)
 | 
				
			||||||
 | 
					  >>> checkoutRule.actions.append(Action('redirect',
 | 
				
			||||||
 | 
					  ...                   parameters=dict(viewName='message_view.html',
 | 
				
			||||||
 | 
					  ...                                   messageName='feedback_html')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.web import RedirectActionHandler
 | 
				
			||||||
 | 
					  >>> component.provideAdapter(RedirectActionHandler, name='redirect')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> request = TestRequest()
 | 
				
			||||||
 | 
					  >>> request._app_names = ['workshop', 'checkout.html']
 | 
				
			||||||
 | 
					  >>> result = ruleManager.handleEvent(Event(checkoutEvent, client1, request))
 | 
				
			||||||
 | 
					  sender: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This redirects to a special message view that will deliver the
 | 
				
			||||||
 | 
					rendered message.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.composer.rule.web import MessageView
 | 
				
			||||||
 | 
					  >>> input = dict(message='feedback_html')
 | 
				
			||||||
 | 
					  >>> view = MessageView(workshop, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> view.getMessage()
 | 
				
			||||||
 | 
					  u'<p>Dear Luke Skywalker...'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Service Manager and Service Views
 | 
				
			||||||
 | 
					=================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.browser.service import ServiceManagerView
 | 
				
			||||||
 | 
					  >>> wsView = ServiceManagerView(workshop, TestRequest())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Service manager view
 | 
				
			||||||
 | 
					--------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The service manager view provides an ``overview()`` method that
 | 
				
			||||||
 | 
					allows a hierarchical presentation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> overview = wsView.overview()
 | 
				
			||||||
 | 
					  >>> for line in overview:
 | 
				
			||||||
 | 
					  ...     print line['title'], line['isHeadline'], line['level']
 | 
				
			||||||
 | 
					  Event True 0
 | 
				
			||||||
 | 
					  Event 1 False 1
 | 
				
			||||||
 | 
					  Event 2 False 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Service view
 | 
				
			||||||
 | 
					------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.browser.service import ServiceView
 | 
				
			||||||
 | 
					  >>> srvView = ServiceView(event1, TestRequest(form=dict(with_temporary='yes')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The service view allows us to retrieve the registrations of a service, e.g.
 | 
				
			||||||
 | 
					to list them on a page template.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regs = srvView.listRegistrations()
 | 
				
			||||||
 | 
					  >>> len(list(regs))
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					  >>> reg = regs.keys()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					There are also convenience methods for retrieving and formatting client
 | 
				
			||||||
 | 
					and registration data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regInfo = srvView.getRegistrationInfo(reg)
 | 
				
			||||||
 | 
					  >>> clientInfo = srvView.getDataForClient(reg)
 | 
				
			||||||
 | 
					  >>> print srvView.formatClientInfo(clientInfo)
 | 
				
			||||||
 | 
					  Skywalker
 | 
				
			||||||
 | 
					  >>> print regInfo['number'], regInfo['stateTitle']
 | 
				
			||||||
 | 
					  1 temporary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The service view also provides fields that sum up the numbers of all
 | 
				
			||||||
 | 
					(non-temporary) registrations. (The number of waiting participants is empty
 | 
				
			||||||
 | 
					because the ``waitingList`` flag has not been set.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> srvView.registeredTotalSubmitted
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					  >>> srvView.registeredTotalsSubmitted
 | 
				
			||||||
 | 
					  {'numberWaiting': '', 'number': 0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Checkout
 | 
				
			||||||
 | 
					--------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After finishing registrating for services the user may check out (submit)
 | 
				
			||||||
 | 
					her registrations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.browser.service import CheckoutView
 | 
				
			||||||
 | 
					  >>> checkout = CheckoutView(workshop, TestRequest())
 | 
				
			||||||
 | 
					  >>> data = checkout.getClientData()
 | 
				
			||||||
 | 
					  >>> list(sorted(data))
 | 
				
			||||||
 | 
					  ['__name__', 'errors', 'info_messages', 'service_registrations',
 | 
				
			||||||
 | 
					   'standard.email', 'standard.lastName']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> checkout.getRegistrationsInfo()
 | 
				
			||||||
 | 
					  [...]
 | 
				
			||||||
 | 
					  >>> checkout.listRegistrationsText()
 | 
				
			||||||
 | 
					  u'Event 1\nDatum: -\nUhrzeit: -\n\n'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					When the user clicks the "Confirm Registration" button the corresponding
 | 
				
			||||||
 | 
					actions will be carried out.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> request._app_names = ['workshop', 'checkout.html']
 | 
				
			||||||
 | 
					  >>> checkout = CheckoutView(workshop, request)
 | 
				
			||||||
 | 
					  >>> checkout.update()
 | 
				
			||||||
 | 
					  sender: unknown@sender.com
 | 
				
			||||||
 | 
					  recipients: [u'luke@skywalker.universe']
 | 
				
			||||||
 | 
					  subject: Workshop Registration
 | 
				
			||||||
 | 
					  message: ...
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The checkout procedure has set the registrations' state to 'submitted'.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> srvView = ServiceView(event1, TestRequest())
 | 
				
			||||||
 | 
					  >>> srvView.getRegistrationInfo(reg)['state']
 | 
				
			||||||
 | 
					  'submitted'
 | 
				
			||||||
 | 
					  >>> srvView.registeredTotalSubmitted
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					What happens if we submit a registration again?
 | 
				
			||||||
 | 
					(We supply the clientName because this may have been cleared on checkout
 | 
				
			||||||
 | 
					for security reasons.)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(action='update', id=client1Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> request._app_names = ['workshop', 'checkout.html']
 | 
				
			||||||
 | 
					  >>> checkout = CheckoutView(workshop, request)
 | 
				
			||||||
 | 
					  >>> checkout.update()
 | 
				
			||||||
 | 
					  sender: unknown@sender.com
 | 
				
			||||||
 | 
					  recipients: [u'luke@skywalker.universe']
 | 
				
			||||||
 | 
					  subject: Workshop Registration
 | 
				
			||||||
 | 
					  message: ...
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> srvView.getRegistrationInfo(reg)['state']
 | 
				
			||||||
 | 
					  'submitted'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Waiting List
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The use of the waiting list is controlled by the ``waitingList`` flag.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> event1.waitingList
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> len(event1.registrations)
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					  >>> event1.availableCapacity
 | 
				
			||||||
 | 
					  4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We now limit the capacity of the event to 1 so that there is no place available
 | 
				
			||||||
 | 
					any more.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> event1.capacity = 1
 | 
				
			||||||
 | 
					  >>> event1.availableCapacity
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regView = RegistrationTemplateView(regForm, TestRequest())
 | 
				
			||||||
 | 
					  >>> regView.setClientName('')
 | 
				
			||||||
 | 
					  >>> regView.allowRegistration(event1)
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If we now set the ``waitingList`` flag to True further registration is
 | 
				
			||||||
 | 
					possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> event1.waitingList = True
 | 
				
			||||||
 | 
					  >>> regView.allowRegistration(event1)
 | 
				
			||||||
 | 
					  True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(lastName='Walker', firstName='John', email='john@walker.tv',
 | 
				
			||||||
 | 
					  ...              addr=u'Mr', action='update')
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> schema = workshop.clientSchemas['person']
 | 
				
			||||||
 | 
					  >>> view = SchemaView(schema, request)
 | 
				
			||||||
 | 
					  >>> view.setClientName('')
 | 
				
			||||||
 | 
					  >>> view.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					  >>> client4Name = view.clientName
 | 
				
			||||||
 | 
					  >>> input = {'action': 'update', 'service.event1': 3, 'id': client4Name}
 | 
				
			||||||
 | 
					  >>> regView = RegistrationTemplateView(regForm, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> regView.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> for reg in sorted(event1.registrations.values(), key=lambda x: x.number):
 | 
				
			||||||
 | 
					  ...     print reg.number, reg.numberWaiting
 | 
				
			||||||
 | 
					  0 3
 | 
				
			||||||
 | 
					  1 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's fix the last registration by running the checkout process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(action='update', id=client4Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> request._app_names = ['workshop', 'checkout.html']
 | 
				
			||||||
 | 
					  >>> checkout = CheckoutView(workshop, request)
 | 
				
			||||||
 | 
					  >>> checkout.update()
 | 
				
			||||||
 | 
					  sender: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Taking over free places
 | 
				
			||||||
 | 
					-----------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					What happens if one of the participants cancels her registration?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = {'action': 'update', 'service.event1': 0, 'id': client1Name}
 | 
				
			||||||
 | 
					  >>> regView = RegistrationTemplateView(regForm, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> regView.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					  >>> for reg in sorted(event1.registrations.values(), key=lambda x: x.number):
 | 
				
			||||||
 | 
					  ...     print reg.number, reg.numberWaiting
 | 
				
			||||||
 | 
					  0 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As the participants on the waiting list get priority over newly registering
 | 
				
			||||||
 | 
					participants the available capacity will still be 0 as long as there are
 | 
				
			||||||
 | 
					people on the waiting list.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> event1.availableCapacity
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					  >>> input = {'action': 'update', 'service.event1': 2}
 | 
				
			||||||
 | 
					  >>> regView = RegistrationTemplateView(regForm, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> regView.setClientName('')
 | 
				
			||||||
 | 
					  >>> regView.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					  >>> for reg in sorted(event1.registrations.values(), key=lambda x: x.numberWaiting):
 | 
				
			||||||
 | 
					  ...     print reg.number, reg.numberWaiting
 | 
				
			||||||
 | 
					  0 2
 | 
				
			||||||
 | 
					  0 3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Now the participant on the waiting list registers again - and gets the
 | 
				
			||||||
 | 
					free place.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = {'action': 'update', 'service.event1': 3, 'id': client4Name}
 | 
				
			||||||
 | 
					  >>> regView = RegistrationTemplateView(regForm, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> regView.update()
 | 
				
			||||||
 | 
					  False
 | 
				
			||||||
 | 
					  >>> for reg in sorted(event1.registrations.values(), key=lambda x: x.number):
 | 
				
			||||||
 | 
					  ...     print reg.number, reg.numberWaiting
 | 
				
			||||||
 | 
					  0 2
 | 
				
			||||||
 | 
					  1 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's finally fix this registration by running the checkout process.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(action='update', id=client4Name)
 | 
				
			||||||
 | 
					  >>> request = TestRequest(form=input)
 | 
				
			||||||
 | 
					  >>> request._app_names = ['workshop', 'checkout.html']
 | 
				
			||||||
 | 
					  >>> checkout = CheckoutView(workshop, request)
 | 
				
			||||||
 | 
					  >>> checkout.update()
 | 
				
			||||||
 | 
					  sender: ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Excel Export
 | 
				
			||||||
 | 
					============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.browser.report import RegistrationsExportCsv
 | 
				
			||||||
 | 
					  >>> input = dict(get_data_method='getData')
 | 
				
			||||||
 | 
					  >>> csv = RegistrationsExportCsv(workshop, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> print csv.render()
 | 
				
			||||||
 | 
					  "Service","Client ID","Organization","First Name","Last Name","E-Mail","Number","State"
 | 
				
			||||||
 | 
					  "Event 1","...","","Walker","","john@walker.tv",1,"submitted"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> input = dict(get_data_method='getAllDataInColumns')
 | 
				
			||||||
 | 
					  >>> csv = RegistrationsExportCsv(workshop, TestRequest(form=input))
 | 
				
			||||||
 | 
					  >>> result = csv.render().splitlines()
 | 
				
			||||||
 | 
					  >>> print result[0]
 | 
				
			||||||
 | 
					  "Client ID","Time Stamp","Last Name","First Name","Email Address","Age","Personal Address","Academic Titles","Street","City","Country","Event 1","WL Event 1","Event 2","WL Event 2"
 | 
				
			||||||
 | 
					  >>> len(result)
 | 
				
			||||||
 | 
					  2
 | 
				
			||||||
 | 
					  >>> print [f.strip('"') for f in result[1].split(',')[1:]]
 | 
				
			||||||
 | 
					  ['...', 'Walker', 'John', 'john@walker.tv', '', 'Mr', '', '', '', '', '1', '2', '0', '0']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Removal of services and clients
 | 
				
			||||||
 | 
					===============================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> from cybertools.organize.service import serviceRemoved, clientRemoved
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> client4 = workshop.clients[client4Name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regs = IClientRegistrations(client4)
 | 
				
			||||||
 | 
					  >>> regs.template = regForm
 | 
				
			||||||
 | 
					  >>> len(regs.getRegistrations())
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> serviceRemoved(event1, None)
 | 
				
			||||||
 | 
					  >>> len(regs.getRegistrations())
 | 
				
			||||||
 | 
					  0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> regs.register([event2])
 | 
				
			||||||
 | 
					  >>> len(event2.registrations)
 | 
				
			||||||
 | 
					  2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> clientRemoved(client4, None)
 | 
				
			||||||
 | 
					  >>> len(event2.registrations)
 | 
				
			||||||
 | 
					  1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Fin de partie
 | 
				
			||||||
 | 
					=============
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  >>> placefulTearDown()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,12 @@ $Id$
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import unittest, doctest
 | 
					import unittest, doctest
 | 
				
			||||||
 | 
					from zope import component
 | 
				
			||||||
from zope.testing.doctestunit import DocFileSuite
 | 
					from zope.testing.doctestunit import DocFileSuite
 | 
				
			||||||
 | 
					from cybertools.composer.schema import client, field, instance
 | 
				
			||||||
from cybertools.organize.party import Person
 | 
					from cybertools.organize.party import Person
 | 
				
			||||||
 | 
					from cybertools.organize import service
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestParty(unittest.TestCase):
 | 
					class TestParty(unittest.TestCase):
 | 
				
			||||||
    "Basic tests for the party module."
 | 
					    "Basic tests for the party module."
 | 
				
			||||||
| 
						 | 
					@ -19,11 +23,23 @@ class TestParty(unittest.TestCase):
 | 
				
			||||||
        self.assertEqual('Meier', p.lastName)
 | 
					        self.assertEqual('Meier', p.lastName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setUp(site):
 | 
				
			||||||
 | 
					    component.provideAdapter(client.ClientFactory)
 | 
				
			||||||
 | 
					    component.provideAdapter(instance.ClientInstance)
 | 
				
			||||||
 | 
					    component.provideAdapter(instance.ClientInstanceEditor, name='editor')
 | 
				
			||||||
 | 
					    component.provideAdapter(field.FieldInstance)
 | 
				
			||||||
 | 
					    component.provideAdapter(field.NumberFieldInstance, name='number')
 | 
				
			||||||
 | 
					    component.provideAdapter(field.EmailFieldInstance, name='email')
 | 
				
			||||||
 | 
					    component.provideAdapter(service.StatefulRegistration)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_suite():
 | 
					def test_suite():
 | 
				
			||||||
    flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
 | 
					    flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
 | 
				
			||||||
    return unittest.TestSuite((
 | 
					    return unittest.TestSuite((
 | 
				
			||||||
        unittest.makeSuite(TestParty),
 | 
					        unittest.makeSuite(TestParty),
 | 
				
			||||||
        DocFileSuite('README.txt', optionflags=flags),
 | 
					        DocFileSuite('README.txt', optionflags=flags),
 | 
				
			||||||
 | 
					        DocFileSuite('formmanager.txt', optionflags=flags),
 | 
				
			||||||
 | 
					        DocFileSuite('servicemanager.txt', optionflags=flags),
 | 
				
			||||||
        DocFileSuite('work.txt', optionflags=flags),
 | 
					        DocFileSuite('work.txt', optionflags=flags),
 | 
				
			||||||
        ))
 | 
					        ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue