start work on complex services/events (e.g. conferences)

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@4150 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2011-01-16 14:46:43 +00:00
parent 808acafb72
commit 5c6f26e2ec
3 changed files with 153 additions and 34 deletions

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de # Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -174,6 +174,16 @@ class IServiceManager(Interface):
services = Attribute('A collection of services managed by this object.') services = Attribute('A collection of services managed by this object.')
def getServices():
""" Return a collection of all services directly assigned
to this service manager.
"""
def getAllServices():
""" Return a collection of all services belonging
to this service manager.
"""
def isActive(): def isActive():
""" Return True if object is active, e.g. based on effective/expiration """ Return True if object is active, e.g. based on effective/expiration
dates or workflow state. dates or workflow state.
@ -214,11 +224,17 @@ class IService(Interface):
vocabulary=serviceCategories, vocabulary=serviceCategories,
default='event', default='event',
required=False,) required=False,)
bookable = schema.Bool(
title=_(u'May people register for this service'),
description=_(u'When this field is checked participants '
u'may directly register for this service.'),
default=True,
required=False,)
allowRegWithNumber = schema.Bool( allowRegWithNumber = schema.Bool(
title=_(u'Allow registration with number'), title=_(u'Allow registration with number'),
description=_(u'When this field is checked more than one ' description=_(u'When this field is checked more than one '
'object (participant) may be assigned with one ' u'object (participant) may be assigned with one '
'registration by entering a corresponding number.'), u'registration by entering a corresponding number.'),
required=False,) required=False,)
presetRegistrationField = schema.Bool( presetRegistrationField = schema.Bool(
title=_(u'Preset Registration Field'), title=_(u'Preset Registration Field'),
@ -232,9 +248,9 @@ class IService(Interface):
allowDirectRegistration = schema.Bool( allowDirectRegistration = schema.Bool(
title=_(u'Allow direct registration'), title=_(u'Allow direct registration'),
description=_(u'When this field is checked participants ' description=_(u'When this field is checked participants '
'may register themselves directly on the page ' u'may register themselves directly on the page '
'with the service description; otherwise registration ' u'with the service description; otherwise registration '
'is only possible on a registration template.'), u'is only possible on a registration template.'),
required=False,) required=False,)
externalId = schema.TextLine( externalId = schema.TextLine(
title=_(u'External ID'), title=_(u'External ID'),
@ -247,49 +263,49 @@ class IService(Interface):
capacity = schema.Int( capacity = schema.Int(
title=_(u'Capacity'), title=_(u'Capacity'),
description=_(u'The capacity (maximum number of clients) ' description=_(u'The capacity (maximum number of clients) '
'of this service; a negative number means: ' u'of this service; a negative number means: '
'no restriction, i.e. unlimited capacity.'), u'no restriction, i.e. unlimited capacity.'),
required=False,) required=False,)
waitingList = schema.Bool( waitingList = schema.Bool(
title=_(u'Waiting list'), title=_(u'Waiting list'),
description=_(u'Check this field if participants beyond the ' description=_(u'Check this field if participants beyond the '
'capacity of the service should be kept in a ' u'capacity of the service should be kept in a '
'waiting list.'), u'waiting list.'),
required=False,) required=False,)
location = schema.TextLine( location = schema.TextLine(
title=_(u'Location information'), title=_(u'Location information'),
description=_(u'Basic location information or ' description=_(u'Basic location information or '
'start point for transport services.'), u'start point for transport services.'),
required=False,) required=False,)
locationUrl = schema.TextLine( locationUrl = schema.TextLine(
title=_(u'URL for location'), title=_(u'URL for location'),
description=_(u'Web address (URL) with more information ' description=_(u'Web address (URL) with more information '
'about the location.'), u'about the location.'),
required=False,) required=False,)
location2 = schema.TextLine( location2 = schema.TextLine(
title=_(u'Location information (2)'), title=_(u'Location information (2)'),
description=_(u'Additional location information or ' description=_(u'Additional location information or '
'end point for transport services.'), u'end point for transport services.'),
required=False,) required=False,)
location2Url = schema.TextLine( location2Url = schema.TextLine(
title=_(u'URL for location (2)'), title=_(u'URL for location (2)'),
description=_(u'Web address (URL) with more information ' description=_(u'Web address (URL) with more information '
'about the location.'), u'about the location.'),
required=False,) required=False,)
webAddress = schema.TextLine( webAddress = schema.TextLine(
title=_(u'Web address'), title=_(u'Web address'),
description=_(u'Web address (URL) for more information ' description=_(u'Web address (URL) for more information '
'about the service.'), u'about the service.'),
required=False,) required=False,)
info = schema.TextLine( info = schema.TextLine(
title=_(u'Additional information'), title=_(u'Additional information'),
description=_(u'Name/title of a document or web page that ' description=_(u'Name/title of a document or web page that '
'offers additional information.'), u'offers additional information.'),
required=False,) required=False,)
infoUrl = schema.TextLine( infoUrl = schema.TextLine(
title=_(u'URL for additional information'), title=_(u'URL for additional information'),
description=_(u'Web address (URL) of a document or web page that ' description=_(u'Web address (URL) of a document or web page that '
'offers additional information.'), u'offers additional information.'),
required=False,) required=False,)
availableCapacity = Attribute('Available capacity, i.e. number of seats ' availableCapacity = Attribute('Available capacity, i.e. number of seats '
@ -325,6 +341,57 @@ class IService(Interface):
""" Remove the client from this service's registrations. """ Remove the client from this service's registrations.
""" """
def getSubservices():
""" Return a collection of immediate sub-services.
"""
def addSubservice(service):
""" Add the service given as a sub-service to this service.
"""
def removeSubservice(service):
""" Remove the sub-service given.
"""
def getParentService():
""" Return the immediate parent service if present, or None otherwise.
"""
def getServiceCollections():
""" Return a collection of service collection this service is assgned to.
"""
collectionTypes = SimpleVocabulary((
SimpleTerm('day', 'day', u'Day'),
SimpleTerm('track', 'track', u'Track'),
))
class IServiceCollection(IService):
""" A service that provides a substructure element of a compound service,
e.g. a conference track or a conference day.
"""
collectionType = schema.Choice(
title=_(u'Type'),
description=_(u'The type of '
'this service collection, e.g. a day or a track.'),
vocabulary=collectionTypes,
default='day',
required=False,)
def getAssignedServices():
""" Return a collection of services assigned to this collection.
"""
def assignService(service):
""" Assign a service to this collection.
"""
def deassignService(service):
""" Remove a service from this collection.
"""
class IScheduledService(IService): class IScheduledService(IService):
""" A service that starts at a certain date/time and """ A service that starts at a certain date/time and
@ -346,20 +413,6 @@ 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.

View file

@ -1,5 +1,5 @@
# #
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de # Copyright (c) 2011 Helmut Merz helmutm@cy55.de
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@ -45,6 +45,7 @@ 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
from cybertools.organize.interfaces import IService, IScheduledService from cybertools.organize.interfaces import IService, IScheduledService
from cybertools.organize.interfaces import IServiceCollection
from cybertools.organize.interfaces import IRegistration, IRegistrationTemplate from cybertools.organize.interfaces import IRegistration, IRegistrationTemplate
from cybertools.organize.interfaces import IClientRegistrations from cybertools.organize.interfaces import IClientRegistrations
@ -94,8 +95,15 @@ class Service(object):
registrationsFactory = OOBTree registrationsFactory = OOBTree
registrationFactory = PersistentRegistration registrationFactory = PersistentRegistration
subservicesFactory = Jeep
collectionsFactory = set
manager = None manager = None
parent = None
subservices = None
collections = None
bookable = True
category = None category = None
location = locationUrl = externalId = u'' location = locationUrl = externalId = u''
cost = 0.0 cost = 0.0
@ -110,6 +118,10 @@ class Service(object):
self.capacity = capacity self.capacity = capacity
if self.registrationsFactory is not None: if self.registrationsFactory is not None:
self.registrations = self.registrationsFactory() self.registrations = self.registrationsFactory()
if self.subservicesFactory is not None:
self.subservices = self.subservicesFactory()
if self.collectionsFactory is not None:
self.collections = self.collectionsFactory()
self.classification = [] self.classification = []
for k, v in kw.items(): for k, v in kw.items():
setattr(self, k, v) setattr(self, k, v)
@ -120,6 +132,21 @@ class Service(object):
def getManager(self): def getManager(self):
return self.manager return self.manager
def getSubservices(self):
return self.subservices.values()
def addSubservice(self, service):
self.subservices.append(service)
def removeSubservice(self, service):
del self.subservices[service.name]
def getParentService(self):
return self.parent
def getServiceCollections(self):
return self.collections.values()
def getClassification(self): def getClassification(self):
return self.classification return self.classification
@ -220,6 +247,30 @@ class ScheduledService(Service):
return getattr(self.getManager(), 'end', None) return getattr(self.getManager(), 'end', None)
class ServiceCollection(ScheduledService):
implements(IServiceCollection)
assignmentsFactory = set
assignments = None
collectionType = u'day'
def __init__(self, name=None, title=u'', capacity=-1, **kw):
super(ServiceCollection, self).__init__(name, title, capacity, kw)
if self.assignmentsFactory is not None:
self.assignments = self.assignmentsFactory()
def getAssignedServices(self):
return self.assignments
def assignService(self, service):
self.assignments.add(service)
def deassignService(self, service):
self.assignments.remove(service)
# registration stuff # registration stuff
class RegistrationTemplate(object): class RegistrationTemplate(object):

View file

@ -327,8 +327,8 @@ registered for them.
>>> clientNames = [client1Name, client2Name, client3Name] >>> clientNames = [client1Name, client2Name, client3Name]
>>> for service in workshop.getServices(): >>> for svc in workshop.getServices():
... for cn, reg in sorted(service.registrations.items()): ... for cn, reg in sorted(svc.registrations.items()):
... print 'client-%i: ' % (clientNames.index(cn)+1), reg.service.name ... print 'client-%i: ' % (clientNames.index(cn)+1), reg.service.name
client-1: event1 client-1: event1
client-3: event2 client-3: event2
@ -745,6 +745,21 @@ Removal of services and clients
1 1
Compound Services
=================
Let's set up a new service manager with a fairly complicated multi-day
conference that is organized in parallel tracks.
>>> conference = site['conference'] = service.ServiceManager()
>>> conference.__parent__ = site
>>> conference.__name__ = 'conference'
>>> main = service.Service('conf_main', manager=conference,
... title=u'Conference', capacity=5)
>>> conference.services.append(main)
Fin de partie Fin de partie
============= =============