VC: Fix error on clone page for legacy-ID events
[cds-indico.git] / indico / MaKaC / registration.py
blob0ecc95baf01b92f9dbc646fea26100a49e1c99f8
1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from babel.numbers import format_currency
18 from flask import request, session
20 import random, time
21 from uuid import uuid4
22 from hashlib import md5
23 from datetime import datetime, timedelta
25 from pytz import timezone
26 from pytz import all_timezones
27 from MaKaC.common.timezoneUtils import nowutc
28 from persistent import Persistent
29 from persistent.mapping import PersistentMapping
30 from persistent.list import PersistentList
31 import MaKaC
32 from indico.core.db import eticket
33 from MaKaC.common.Counter import Counter
34 from MaKaC.errors import FormValuesError, MaKaCError
35 from MaKaC.common.Locators import Locator
36 from indico.core.config import Config
37 from MaKaC.common.TemplateExec import inlineContextHelp
38 import MaKaC.webinterface.urlHandlers as urlHandlers
39 from MaKaC.webinterface.common.tools import strip_ml_tags
40 from MaKaC.trashCan import TrashCanManager
41 from MaKaC.webinterface.mail import GenericMailer, GenericNotification
42 from MaKaC.i18n import _
43 from indico.util.caching import memoize_request
44 from indico.util.i18n import i18nformat
45 from indico.util.date_time import format_datetime, format_date
46 from indico.util.string import safe_upper
47 from MaKaC.webinterface.common.countries import CountryHolder
48 import re
49 import tempfile
50 import string
51 from MaKaC.webinterface.common.person_titles import TitlesRegistry
52 from indico.modules.payment import event_settings as payment_event_settings
53 from indico.modules.payment import settings as payment_settings
54 from indico.modules.payment.models.transactions import PaymentTransaction, TransactionStatus
55 from indico.modules.users.legacy import AvatarUserWrapper
56 from indico.util.fossilize import Fossilizable, fossilizes
57 from indico.core.fossils.registration import IRegFormTextInputFieldFossil, IRegFormTelephoneInputFieldFossil, \
58 IRegFormTextareaInputFieldFossil, IRegFormNumberInputFieldFossil, IRegFormLabelInputFieldFossil, \
59 IRegFormCheckboxInputFieldFossil, IRegFormYesNoInputFieldFossil, IRegFormFileInputFieldFossil, \
60 IRegFormRadioItemFossil, IRegFormRadioGroupInputFieldFossil, IRegFormCountryInputFieldFossil, \
61 IRegFormDateInputFieldFossil, IRegFormGeneralFieldFossil, IRegFormGeneralSectionFossil, \
62 IRegFormFurtherInformationSectionFossil, IRegFormAccommodationTypeItemFossil, IRegFormAccommodationSectionFossil, \
63 IRegFormReasonParticipationSectionFossil, IRegFormRegistrationSessionItemFossil, IRegFormSessionSectionFossil, \
64 IRegFormSocialEventItemFossil, IRegFormSocialEventSectionFossil, IRegFormRegistrantFossil, \
65 IRegFormRegistrantBasicFossil, IRegFormRegistrantFullFossil, IRegFormSocialEventFossil, IRegFormMiscellaneousInfoGroupFossil
67 PRICE_PATTERN = re.compile(r'^(\d+(?:[\.,]\d+)?)$')
70 def stringToDate(str):
71 months = {"January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
72 "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12}
73 [day, month, year] = str.split("-")
74 return datetime(int(year), months[month], int(day))
77 class RegistrationForm(Persistent):
79 def __init__(self, conf, groupData=None, skipPersonalData=False):
80 self._conf = conf
81 if groupData is None:
82 self.activated = False
83 self.title = "Registration Form"
84 self.announcement = ""
85 self.usersLimit = 0
86 self.contactInfo = ""
87 self.setStartRegistrationDate(nowutc())
88 self.setEndRegistrationDate(nowutc())
89 self.setModificationEndDate(None)
90 else:
91 self.activated = groupData.get("activated", False)
92 self.title = groupData.get("name", "")
93 self.announcement = groupData.get("announcement", "")
94 self.usersLimit = groupData.get("limit", "")
95 self.startRegistrationDate = groupData.get("startRegistrationDate", None)
96 if self.startRegistrationDate is None:
97 self.setStartRegistrationDate(nowutc())
98 self.endRegistrationDate = groupData.get("endRegistrationDate", None)
99 if self.endRegistrationDate is None:
100 self.setEndRegistrationDate(nowutc())
101 self._endExtraTimeAmount = 0
102 self._endExtraTimeUnit = 'days'
103 self.modificationEndDate = groupData.get("modificationEndDate", None)
104 #if self.modificationEndDate is None:
105 # self.setModificationEndDate(nowutc())
106 self.contactInfo = groupData.get("contactInfo", "")
107 self.notification = Notification()
108 self._eTicket = eticket.ETicket()
109 # Status definition
110 self._statuses = {}
111 self._statusesGenerator = Counter()
112 #Multiple-Subforms
113 if not skipPersonalData:
114 self.personalData = PersonalDataForm(self)
115 #Simple-SubForms
116 self.sessionsForm = SessionsForm()
117 self.accommodationForm = AccommodationForm(self)
118 self.reasonParticipationForm = ReasonParticipationForm()
119 self.furtherInformation = FurtherInformationForm()
120 self.socialEventForm = SocialEventForm(self)
121 #General-SubForms
122 self._generalSectionGenerator = Counter()
123 self.generalSectionForms = {}
124 if not skipPersonalData:
125 self.addGeneralSectionForm(self.personalData, True)
126 #All SortedForms
127 self._sortedForms = []
128 if not skipPersonalData:
129 self.addToSortedForms(self.personalData)
130 self.addToSortedForms(self.reasonParticipationForm)
131 self.addToSortedForms(self.sessionsForm)
132 self.addToSortedForms(self.accommodationForm)
133 self.addToSortedForms(self.socialEventForm)
134 self.addToSortedForms(self.furtherInformation)
136 self.setAllSessions()
138 def clone(self, conference):
139 form = RegistrationForm(conference, skipPersonalData=True)
140 form.setConference(conference)
141 form.setAnnouncement(self.getAnnouncement())
142 form.setContactInfo(self.getContactInfo())
143 registrationPeriodEnd = self.getConference().getStartDate() - self.getEndRegistrationDate()
144 registrationPeriodStart = self.getConference().getStartDate() - self.getStartRegistrationDate()
145 form.setEndRegistrationDate(conference.getStartDate() - registrationPeriodEnd)
146 form.setEndExtraTimeAmount(self.getEndExtraTimeAmount())
147 form.setEndExtraTimeUnit(self.getEndExtraTimeUnit())
148 form.setStartRegistrationDate(conference.getStartDate() - registrationPeriodStart)
149 if self.getModificationEndDate():
150 registrationPeriodModifEndDate = self.getConference().getStartDate() - self.getModificationEndDate()
151 form.setModificationEndDate(conference.getStartDate() - registrationPeriodModifEndDate)
152 form.setTitle(self.getTitle())
153 form.setUsersLimit(self.getUsersLimit())
154 form.setActivated(self.isActivated())
155 form.setMandatoryAccount(self.isMandatoryAccount())
156 form.setNotificationSender(self.getNotificationSender())
157 form.setSendRegEmail(self.isSendRegEmail())
158 form.setSendPaidEmail(self.isSendPaidEmail())
159 form.setAllSessions()
160 form.notification = self.getNotification().clone()
161 form._eTicket = self.getETicket().clone()
162 form.personalData = self.getPersonalData().clone(form)
163 form.generalSectionForms[form.personalData.getId()] = form.personalData
164 acf = self.getAccommodationForm()
165 if acf is not None:
166 form.accommodationForm = acf.clone(form)
167 fif = self.getFurtherInformationForm()
168 if fif is not None:
169 form.furtherInformation = fif.clone()
170 rpf = self.getReasonParticipationForm()
171 if rpf is not None:
172 form.reasonParticipationForm = rpf.clone()
173 form.setAllSessions()
174 ses = self.getSessionsForm()
175 if ses is not None:
176 form.sessionsForm = ses.clone(form.sessionsForm.getSessionList())
177 sef = self.getSocialEventForm()
178 if sef is not None:
179 form.socialEventForm = sef.clone(form)
180 form._sortedForms = []
181 for item in self.getSortedForms():
182 clonedItem = form.getSectionById(item.getId())
183 if clonedItem is None: # General Section, not cloned yet
184 clonedItem = item.clone(form)
185 form.generalSectionForms[clonedItem.getId()] = clonedItem
186 form.addToSortedForms(clonedItem)
188 return form
190 @memoize_request
191 def getCurrency(self):
192 return payment_event_settings.get(self._conf, 'currency')
194 def getConference(self):
195 return self._conf
196 getOwner = getConference
198 def getTimezone(self):
199 return self.getConference().getTimezone()
201 def setConference(self, conf):
202 self._conf = conf
203 setOwner = setConference
205 def setAllSessions(self):
206 for ses in self._conf.getSessionList():
207 rs = RegistrationSession(ses, self)
208 self.sessionsForm.addSession(rs)
210 def isActivated(self):
211 return self.activated
213 def activate(self):
214 self.activated = True
216 def deactivate(self):
217 self.activated = False
219 def setActivated(self, value):
220 self.activated = value
222 def isMandatoryAccount(self):
223 try:
224 if self._mandatoryAccount:
225 pass
226 except AttributeError, e:
227 self._mandatoryAccount = True
228 return self._mandatoryAccount
230 def setMandatoryAccount(self, v=True):
231 self._mandatoryAccount = v
233 def setNotificationSender(self, sender):
234 self._notificationSender = sender
236 def getNotificationSender(self):
237 sender = None
238 try:
239 if self._notificationSender:
240 sender = self._notificationSender
241 except AttributeError, e:
242 pass
243 if not sender:
244 self._notificationSender = self._conf.getSupportInfo().getEmail(returnNoReply=True).split(',', 1)[0]
245 return self._notificationSender
247 def isSendRegEmail(self):
248 return getattr(self, '_sendRegEmail', True) or getattr(self, '_sendReceiptEmail', False)
250 def setSendRegEmail(self, v=True):
251 self._sendRegEmail = v
252 self._sendReceiptEmail = v
254 def isSendPaidEmail(self):
255 try:
256 if self._sendPaidEmail:
257 pass
258 except AttributeError, e:
259 self._sendPaidEmail = False
260 return self._sendPaidEmail
262 def setSendPaidEmail(self, v=True):
263 self._sendPaidEmail = v
265 def setTitle(self, newName):
266 self.title = newName.strip()
268 def getTitle(self):
269 return self.title
271 def setAnnouncement(self, newDesc):
272 self.announcement = newDesc.strip()
274 def getAnnouncement(self):
275 return self.announcement
277 def setUsersLimit(self, newLimit):
278 if isinstance(newLimit, int):
279 self.usersLimit = newLimit
280 elif isinstance(newLimit, str):
281 if newLimit.strip() == "":
282 self.usersLimit = 0
283 else:
284 self.usersLimit = int(newLimit.strip())
285 if self.usersLimit < 0:
286 self.usersLimit = 0
288 def getUsersLimit(self):
289 return self.usersLimit
291 def isFull(self):
292 if self.usersLimit != 0:
293 return len(self.getConference().getRegistrants()) >= self.usersLimit
294 return False
296 def setStartRegistrationDate(self, sd):
297 self.startRegistrationDate = datetime(sd.year, sd.month, sd.day, 0, 0, 0)
299 def getStartRegistrationDate(self):
300 return timezone(self.getTimezone()).localize(self.startRegistrationDate)
302 def setEndRegistrationDate(self, ed):
303 self.endRegistrationDate = datetime(ed.year, ed.month, ed.day, 23, 59, 59)
305 def getEndRegistrationDate(self):
306 return timezone(self.getTimezone()).localize(self.endRegistrationDate)
308 def getAllowedEndRegistrationDate(self):
309 if self.getEndExtraTimeUnit() == 'days':
310 delta = timedelta(days=self.getEndExtraTimeAmount())
311 else:
312 delta = timedelta(weeks=self.getEndExtraTimeAmount())
313 return timezone(self.getTimezone()).localize(self.endRegistrationDate + delta)
315 def setEndExtraTimeAmount(self, value):
316 self._endExtraTimeAmount = value
318 def getEndExtraTimeAmount(self):
319 try:
320 return self._endExtraTimeAmount
321 except AttributeError:
322 self._endExtraTimeAmount = 0
323 return self._endExtraTimeAmount
325 def setEndExtraTimeUnit(self, value):
326 self._endExtraTimeUnit = value
328 def getEndExtraTimeUnit(self):
329 try:
330 return self._endExtraTimeUnit
331 except AttributeError:
332 self._endExtraTimeUnit = 'days'
333 return self._endExtraTimeUnit
335 def setModificationEndDate(self, ed):
336 if ed:
337 self.modificationEndDate = datetime(ed.year, ed.month, ed.day, 23, 59, 59)
338 else:
339 self.modificationEndDate = None
341 def getModificationEndDate(self):
342 try:
343 if self.modificationEndDate:
344 return timezone(self.getTimezone()).localize(self.modificationEndDate)
345 except AttributeError, e:
346 pass
347 return None
349 def inModificationPeriod(self):
350 if self.getModificationEndDate() is None:
351 return True
352 date = nowutc()
353 sd = self.getStartRegistrationDate()
354 ed = self.getModificationEndDate()
355 return date <= ed and date >= sd
357 def inRegistrationPeriod(self, date=None):
358 if date is None:
359 date = nowutc()
360 sd = self.getStartRegistrationDate()
361 ed = self.getAllowedEndRegistrationDate()
362 return date <= ed and date >= sd
364 def setContactInfo(self, ci):
365 self.contactInfo = ci
367 def getContactInfo(self):
368 return self.contactInfo
370 def getStatuses(self):
371 try:
372 if self._statuses:
373 pass
374 except AttributeError, e:
375 self._statuses = {}
376 return self._statuses
378 def _generateStatusId(self):
379 try:
380 if self._statusesGenerator:
381 pass
382 except AttributeError, e:
383 self._statusesGenerator = Counter()
384 return self._statusesGenerator
386 def getStatusesList(self, sort=True):
387 v = self.getStatuses().values()
388 if sort:
389 v.sort(Status._cmpCaption)
390 return v
392 def getStatusById(self, id):
393 if self.getStatuses().has_key(id):
394 return self.getStatuses()[id]
395 return None
397 def addStatus(self, st):
398 st.setId(str(self._generateStatusId().newCount()))
399 self.getStatuses()[st.getId()] = st
400 self.notifyModification()
402 def removeStatus(self, st):
403 if self.getStatuses().has_key(st.getId()):
404 del self.getStatuses()[st.getId()]
405 self.notifyModification()
407 def getNotification(self):
408 try:
409 if self.notification:
410 pass
411 except:
412 self.notification = Notification()
413 return self.notification
415 def _convertPersonalData(self):
416 if isinstance(self.personalData, PersonalDataForm):
417 return
418 pd = PersonalDataForm(self)
419 self.addGeneralSectionForm(pd, True, 0)
420 for f in pd.getSortedFields():
421 f.setDisabled(not self.personalData.getDataItem(f.getPDField()).isEnabled())
422 f.setMandatory(self.personalData.getDataItem(f.getPDField()).isMandatory())
423 for registrant in self.getConference().getRegistrants().itervalues():
424 mg = MiscellaneousInfoGroup(registrant, pd)
425 registrant.addMiscellaneousGroup(mg)
426 for f in pd.getSortedFields():
427 val = getattr(registrant, '_' + f.getPDField())
428 # radiobuttons are numerically indexed
429 if f.getCaption() == "Title":
430 try:
431 val = str(TitlesRegistry._items.index(val))
432 except ValueError:
433 # can happen for older events with obsolete titles
434 val = "0"
436 fakeParams = {f.getInput().getHTMLName(): val}
437 f.getInput().setResponseValue(mg.getResponseItemById(f.getId()), fakeParams, registrant, mg, override=True, validate=False)
438 self.personalData = pd
440 def getPersonalData(self):
441 self._convertPersonalData()
442 return self.personalData
444 def getFurtherInformationForm(self):
445 return self.furtherInformation
447 def getSessionsForm(self):
448 return self.sessionsForm
450 def getAccommodationForm(self):
451 return self.accommodationForm
453 def getSocialEventForm(self):
454 return self.socialEventForm
456 def getReasonParticipationForm(self):
457 return self.reasonParticipationForm
459 def getSectionById(self, id):
460 if id == "reasonParticipation":
461 return self.getReasonParticipationForm()
462 if id == "sessions":
463 return self.getSessionsForm()
464 if id == "accommodation":
465 return self.getAccommodationForm()
466 if id == "socialEvents":
467 return self.getSocialEventForm()
468 if id == "furtherInformation":
469 return self.getFurtherInformationForm()
470 return self.getGeneralSectionFormById(id)
472 def _getGeneralSectionGenerator(self):
473 try:
474 if self._generalSectionGenerator:
475 pass
476 except AttributeError, e:
477 self._generalSectionGenerator = Counter()
478 return self._generalSectionGenerator
480 def getGeneralSectionForms(self):
481 try:
482 if self.generalSectionForms:
483 pass
484 except AttributeError, e:
485 self.generalSectionForms = {}
486 return self.generalSectionForms
488 def getGeneralSectionFormById(self, id):
489 return self.getGeneralSectionForms().get(id, None)
491 def getGeneralSectionFormsList(self):
492 return self.getGeneralSectionForms().values()
494 def addGeneralSectionForm(self, gsf, preserveTitle=False, pos=None):
495 id = str(self._getGeneralSectionGenerator().newCount())
496 while self.getGeneralSectionFormById(id) is not None:
497 id = str(self._getGeneralSectionGenerator().newCount())
498 gsf.setId(id)
499 if not preserveTitle:
500 gsf.setTitle("Miscellaneous information %s" % gsf.getId())
501 self.generalSectionForms[gsf.getId()] = gsf
502 self.addToSortedForms(gsf, pos)
503 self.notifyModification()
505 def removeGeneralSectionForm(self, gsf):
506 if self.hasGeneralSectionForm(gsf):
507 del self.generalSectionForms[gsf.getId()]
508 self.removeFromSortedForms(gsf)
509 self.notifyModification()
511 def hasGeneralSectionForm(self, gsf):
512 return self.getGeneralSectionForms().has_key(gsf.getId())
514 def getSortedForms(self):
515 try:
516 if self._sortedForms:
517 pass
518 except AttributeError, e:
519 self._sortedForms = []
520 self.addToSortedForms(self.reasonParticipationForm)
521 self.addToSortedForms(self.sessionsForm)
522 self.addToSortedForms(self.accommodationForm)
523 self.addToSortedForms(self.socialEventForm)
524 self.addToSortedForms(self.furtherInformation)
525 for gs in self.getGeneralSectionFormsList():
526 self.addToSortedForms(gs)
527 return self._sortedForms
529 def addToSortedForms(self, form, i=None):
530 if i is None:
531 i = len(self.getSortedForms())
532 try:
533 self.getSortedForms().remove(form)
534 except ValueError, e:
535 pass
536 self.getSortedForms().insert(i, form)
537 self.notifyModification()
538 return True
540 def removeFromSortedForms(self, form):
541 try:
542 self.getSortedForms().remove(form)
543 except ValueError, e:
544 return False
545 self.notifyModification()
546 return True
548 def getLocator(self):
549 """Gives back (Locator) a globaly unique identification encapsulated in
550 a Locator object for the RegistrationForm instance """
551 if self.getConference() is None:
552 return Locator()
553 lconf = self.getConference().getLocator()
554 return lconf
556 def notifyRegistrantRemoval(self, reg):
557 acco = reg.getAccommodation()
558 if acco is not None:
559 accoType = acco.getAccommodationType()
560 if accoType is not None:
561 accoType.decreaseNoPlaces()
562 for se in reg.getSocialEvents():
563 se.delete() # It'll decrease the no of places
564 for mg in reg.getMiscellaneousGroupList():
565 for item in mg.getResponseItemList():
566 item.getGeneralField().getInput()._beforeValueChange(item, False)
567 for attachment in reg.getAttachments().keys():
568 reg.deleteFile(attachment)
570 def delete(self):
571 self.getSessionsForm().clearSessionList()
572 TrashCanManager().add(self)
574 def recover(self):
575 TrashCanManager().remove(self)
577 def notifyModification(self):
578 self._p_changed = 1
579 self._conf.notifyModification()
581 def getETicket(self):
582 try:
583 return self._eTicket
584 except AttributeError:
585 self._eTicket = eticket.ETicket()
586 return self._eTicket
589 class Notification(Persistent):
590 def __init__(self):
591 self._toList = PersistentList()
592 self._ccList = PersistentList()
594 def clone(self):
595 n = Notification()
596 for t in self.getToList():
597 n.addToList(t)
598 for c in self.getCCList():
599 n.addCCList(c)
600 return n
602 def getToList(self):
603 return self._toList
605 def setToList(self, tl):
606 self._toList = tl
608 def addToList(self, to):
609 self._toList.append(to)
611 def clearToList(self):
612 self._toList = PersistentList()
614 def getCCList(self):
615 return self._ccList
617 def setCCList(self, cl):
618 self._ccList = cl
620 def addCCList(self, cc):
621 self._ccList.append(cc)
623 def clearCCList(self):
624 self._ccList = PersistentList()
627 class BaseForm(Persistent):
630 Base class for registration forms
632 It includes iterators/getters, provided if the class attribute
633 _iterableContainer is present. _iterableContainer is a simple workaround for
634 the problem of having a generic iterator interface over all the forms, even
635 if the initial design didn't unify the form container into a BaseForm
636 attribute. Since it is too late now for redesigning the DB schema, this
637 attribute kind of fixes it.
641 # should be overloaded if iteration is to be provided
642 _iterableContainer = None
644 def __init__(self):
645 self._enabled = True # it means that the form cannot be used either in the registration display or in the management area.
647 def setEnabled(self, v):
648 self._enabled = v
650 def isEnabled(self):
651 try:
652 if self._enabled:
653 pass
654 except AttributeError, e:
655 self._enabled = True
656 return self._enabled
658 def __iter__(self):
659 return getattr(self, self._iterableContainer).__iter__();
661 def __getitem__(self, key):
662 return getattr(self, self._iterableContainer)[key]
665 class FieldInputType(Persistent):
666 _id = ""
667 _useLabelCol = True
668 _wholeRow = False
670 def __init__(self, field):
671 self._parent = field
673 def getValues(self):
674 return {}
676 def setValues(self, data):
677 pass
679 def getParent(self):
680 return self._parent
682 def setId(cls, id):
683 cls._id = id
684 setId = classmethod(setId)
686 def getId(cls):
687 return cls._id
688 getId = classmethod(getId)
690 def getName(cls):
691 return cls._id
692 getName = classmethod(getName)
694 def getHTMLName(self):
696 This method returns the indentifier of the field item in the web form.
698 return "*genfield*%s-%s" % (self.getParent().getParent().getId(), self.getParent().getId())
700 def getModifLabelCol(self):
701 if not self._useLabelCol:
702 return ""
703 return self._parent.getCaption()
705 def useWholeRow(self):
706 return self._wholeRow
708 def getMandatoryCol(self, item):
709 mandatory = ""
710 if (item is not None and item.isMandatory()) or self.getParent().isMandatory():
711 mandatory = """<span class="regFormMandatoryField">*</span>"""
712 return mandatory
714 def getModifHTML(self, item, registrant, default=""):
716 Method that display the form web which represents this object.
718 return "<table><tr>%s</tr></table>" % (self._getModifHTML(item, registrant, default))
720 def _getModifHTML(self, item, registrant, default=""):
722 Method that should be overwritten by the classes inheriting from this one in order to display
723 the form web which represents this object.
725 return ""
727 def setResponseValue(self, item, params, registrant, mg=None, override=False, validate=True):
729 This method shouldn't be called from the classes inheriting from this one (FieldInputType).
730 This method fills the attribute "item" (MiscellaneousInfoSimpleItem) with the value the user wrote
731 in the registration form.
733 if item is None:
734 item = MiscellaneousInfoSimpleItem(mg, self.getParent())
735 mg.addResponseItem(item)
736 self._beforeValueChange(item, True)
737 else:
738 self._beforeValueChange(item, False)
740 self._setResponseValue(item, params, registrant, override=override, validate=validate)
741 self._afterValueChange(item)
743 def _beforeValueChange(self, item, newItem):
744 # if the item had a quantity, make the place available again
745 if not newItem and item.getQuantity():
746 self.getParent().decreaseNoPlaces()
748 def _afterValueChange(self, item):
749 # if the item has a quantity now, make the place unavailable
750 if item.getQuantity():
751 self.getParent().increaseNoPlaces()
753 def _setResponseValue(self, item, registrant, params, override=False, validate=True):
755 Method that should be overwritten by the classes inheriting from this one in order to get the value written in the form.
757 pass
759 def _getSpecialOptionsHTML(self):
760 price = self._parent.getPrice()
761 billable = self._parent.isBillable()
762 checked = ""
763 if billable:
764 checked = "checked=\"checked\""
766 html = i18nformat(""" <tr>
767 <td class="titleCellTD"><span class="titleCellFormat">Is Billable</span></td>
768 <td bgcolor="white" class="blacktext" width="100%%">
769 <input type="checkbox" name="billable" size="60" %s> _("(uncheck if it is not billable)")
770 </td>
771 </tr>
772 <tr>
773 <td class="titleCellTD"><span class="titleCellFormat"> _("Price")</span></td>
774 <td bgcolor="white" class="blacktext" width="100%%">
775 <input type="text" name="price" size="60" value=%s>
776 </td>
777 </tr>
778 """) % (checked, price)
779 return "".join(html)
781 def _getDescriptionHTML(self, description):
782 return """<span class="inputDescription">%s</span>""" % description
784 def clone(self, gf):
785 fi = FieldInputs().getAvailableInputKlassById(self.getId())(gf)
786 return fi
789 class TextInput(FieldInputType, Fossilizable):
791 fossilizes(IRegFormTextInputFieldFossil)
793 _id = "text"
795 def getName(cls):
796 return "Text"
797 getName = classmethod(getName)
799 def __init__(self, field):
800 FieldInputType.__init__(self, field)
801 self._length = ''
803 def _getModifHTML(self, item, registrant, default=""):
804 description = self._parent.getDescription()
805 price = self._parent.getPrice()
806 billable = self._parent.isBillable()
807 currency = self._parent.getParent().getRegistrationForm().getCurrency()
808 htmlName = self.getHTMLName()
809 v = default
810 if item is not None:
811 v = item.getValue()
812 price = item.getPrice()
813 billable = item.isBillable()
814 currency = item.getCurrency()
815 htmlName = item.getHTMLName()
816 disable = ""
817 if (registrant is not None and billable and registrant.getPayed()):
818 disable = "disabled=\"true\""
819 #pass
820 if self._parent.getPDField() == 'email':
821 param = """<script>addParam($E('%s'), 'email', %s);</script>""" % (htmlName, 'false' if self._parent.isMandatory() else 'true')
822 elif self._parent.isMandatory():
823 param = """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
824 else:
825 param = ''
826 if self.getLength():
827 length = 'size="%s"' % self.getLength()
828 else:
829 length = 'size="60"'
830 tmp = """<input type="text" id="%s" name="%s" value="%s" %s %s >%s""" % (htmlName, htmlName, v , disable, length, param)
831 tmp = """ <td>%s</td><td align="right" align="bottom">""" % tmp
832 if billable:
833 tmp = """%s&nbsp;&nbsp;%s&nbsp;&nbsp;%s</td> """ % (tmp, price, currency)
834 else:
835 tmp = """%s </td> """ % tmp
836 if description:
837 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
838 return tmp
840 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
841 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
842 #if ( item is not None and item.isBillable()):
843 #######################
844 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
845 return
846 v = params.get(self.getHTMLName(), "")
847 if not override and self.getParent().isMandatory() and v.strip() == "":
848 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
850 item.setQuantity(0)
851 item.setValue(v)
852 #item.setBillable(self._parent.isBillable())
853 #item.setPrice(self._parent.getPrice())
854 #item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
855 item.setMandatory(self.getParent().isMandatory())
856 item.setHTMLName(self.getHTMLName())
858 def _getSpecialOptionsHTML(self):
859 return i18nformat("""
860 <tr>
861 <td class="titleCellTD"><span class="titleCellFormat">_("Size in chars")</span></td>
862 <td bgcolor="white" class="blacktext" width="100%%">
863 <input type="text" name="length" value="%s" />
864 </td>
865 </tr>""" % self.getLength())
867 def clone(self, gf):
868 ti = FieldInputType.clone(self, gf)
869 ti.setLength(self.getLength())
870 return ti
872 def getValues(self):
873 d = {}
874 d["length"] = self.getLength()
875 return d
877 def setValues(self, data):
878 if data.has_key("length"):
879 self.setLength(data.get("length"))
881 def getLength(self):
882 try:
883 if self._length: pass
884 except AttributeError:
885 self._length = ''
886 return self._length
888 def setLength(self, value):
889 self._length = value
892 class TelephoneInput(FieldInputType, Fossilizable):
894 fossilizes(IRegFormTelephoneInputFieldFossil)
896 _id = "telephone"
897 _REGEX = r'^(\(\+\d*\)|\+)?\s*(\d(\s*|\-))+$'
898 _PATTERN = re.compile(_REGEX)
900 def getName(cls):
901 return "Telephone"
902 getName = classmethod(getName)
904 def __init__(self, field):
905 FieldInputType.__init__(self, field)
906 self._length = ''
908 def _getModifHTML(self, item, registrant, default=""):
909 description = self._parent.getDescription()
910 htmlName = self.getHTMLName()
912 v = default
913 if item is not None:
914 v = item.getValue()
915 htmlName = item.getHTMLName()
917 disable = ""
918 if self._parent.isMandatory():
919 param = """<script>
920 addParam($E('%s'), 'text', false, function(value) {
921 if (!/%s/.test(value)) {
922 return "Invalid phone number format";
925 </script>""" % (htmlName, TelephoneInput._REGEX)
926 else:
927 param = ''
928 if self.getLength():
929 length = 'size="%s"' % self.getLength()
930 else:
931 length = 'size="30"'
932 format = """&nbsp;<span class="inputDescription">(+) 999 99 99 99</span>"""
933 tmp = """<input type="text" id="%s" name="%s" value="%s" %s %s>%s%s""" % (htmlName, htmlName, v , disable, length, format, param)
934 tmp = """ <td>%s</td>""" % tmp
935 if description:
936 tmp = """%s</tr><tr><td>%s</td>""" % (tmp, self._getDescriptionHTML(description))
937 return tmp
939 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
940 v = params.get(self.getHTMLName(), "")
942 if not override and self.getParent().isMandatory() and v.strip() == "":
943 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
945 if validate and v.strip() != '' and not TelephoneInput._PATTERN.match(v):
946 raise FormValuesError(_("The field \"%s\" is in wrong format. Please fill it in the correct format: (+) 999 99 99 99") % self.getParent().getCaption())
948 v = re.sub(r'\s+|\-+', '', v)
950 item.setQuantity(0)
951 item.setValue(v)
952 item.setMandatory(self.getParent().isMandatory())
953 item.setHTMLName(self.getHTMLName())
955 def _getSpecialOptionsHTML(self):
956 return i18nformat("""
957 <tr>
958 <td class="titleCellTD"><span class="titleCellFormat">_("Size in chars")</span></td>
959 <td bgcolor="white" class="blacktext" width="100%%">
960 <input type="text" name="length" value="%s" />
961 </td>
962 </tr>""" % self.getLength())
964 def clone(self, gf):
965 ti = FieldInputType.clone(self, gf)
966 ti.setLength(self.getLength())
967 return ti
969 def getValues(self):
970 d = {}
971 d["length"] = self.getLength()
972 return d
974 def setValues(self, data):
975 if data.has_key("length"):
976 self.setLength(data.get("length"))
978 def getLength(self):
979 try:
980 if self._length:
981 pass
982 except AttributeError:
983 self._length = ''
984 return self._length
986 def setLength(self, value):
987 self._length = value
990 class TextareaInput(FieldInputType, Fossilizable):
992 fossilizes(IRegFormTextareaInputFieldFossil)
994 _id = "textarea"
996 def getName(cls):
997 return "Textarea"
998 getName = classmethod(getName)
1000 def __init__(self, field):
1001 FieldInputType.__init__(self, field)
1002 self._numberOfRows = ''
1003 self._numberOfColumns = ''
1005 def _getModifHTML(self, item, registrant, default=""):
1006 description = self._parent.getDescription()
1007 price = self._parent.getPrice()
1008 billable = self._parent.isBillable()
1009 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1010 htmlName = self.getHTMLName()
1011 v = default
1012 if item is not None:
1013 v = item.getValue()
1014 price = item.getPrice()
1015 billable = item.isBillable()
1016 currency = item.getCurrency()
1017 htmlName = item.getHTMLName()
1018 disable = ""
1019 if (registrant is not None and billable and registrant.getPayed()):
1020 disable = "disabled=\"true\""
1021 #pass
1023 if description:
1024 desc = """%s<br/>""" % self._getDescriptionHTML(description)
1025 else:
1026 desc = ''
1028 if self._parent.isMandatory():
1029 param = """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
1030 else:
1031 param = ''
1032 cols = self.getNumberOfColumns()
1033 if not cols:
1034 cols = 60
1035 rows = self.getNumberOfRows()
1036 if not rows:
1037 rows = 4
1039 tmp = """%s<textarea id="%s" name="%s" cols="%s" rows="%s" %s >%s</textarea>%s""" % (desc, htmlName, htmlName, cols, rows, disable, v, param)
1040 tmp = """ <td>%s</td><td align="right" align="bottom">""" % tmp
1041 tmp = """%s </td> """ % tmp
1043 return tmp
1045 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1046 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
1047 #if ( item is not None and item.isBillable()):
1048 #######################
1049 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
1050 return
1051 v = params.get(self.getHTMLName(), "")
1052 if not override and self.getParent().isMandatory() and v.strip() == "":
1053 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
1054 item.setQuantity(0)
1055 item.setValue(v)
1056 #item.setBillable(self._parent.isBillable())
1057 #item.setPrice(self._parent.getPrice())
1058 #item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
1059 item.setMandatory(self.getParent().isMandatory())
1060 item.setHTMLName(self.getHTMLName())
1062 def _getSpecialOptionsHTML(self):
1063 html = [i18nformat("""
1064 <tr>
1065 <td class="titleCellTD"><span class="titleCellFormat">_("Number of rows")</span></td>
1066 <td bgcolor="white" class="blacktext" width="100%%">
1067 <input type="text" name="numberOfRows" value="%s" />
1068 </td>
1069 </tr>""") % self.getNumberOfRows()]
1071 html.append(i18nformat("""
1072 <tr>
1073 <td class="titleCellTD"><span class="titleCellFormat">_("Row length")</span></td>
1074 <td bgcolor="white" class="blacktext" width="100%%">
1075 <input type="text" name="numberOfColumns" value="%s" />
1076 </td>
1077 </tr>""") % self.getNumberOfColumns())
1078 return "".join(html)
1080 def clone(self, gf):
1081 ti = FieldInputType.clone(self, gf)
1082 ti.setNumberOfRows(self.getNumberOfRows())
1083 ti.setNumberOfColumns(self.getNumberOfColumns())
1084 return ti
1086 def getValues(self):
1087 d = {}
1088 d["numberOfRows"] = self.getNumberOfRows()
1089 d["numberOfColumns"] = self.getNumberOfColumns()
1090 return d
1092 def setValues(self, data):
1093 if data.has_key("numberOfRows"):
1094 self.setNumberOfRows(data.get("numberOfRows"))
1095 if data.has_key("numberOfColumns"):
1096 self.setNumberOfColumns(data.get("numberOfColumns"))
1098 def getNumberOfRows(self):
1099 try:
1100 if self._numberOfRows: pass
1101 except AttributeError:
1102 self._numberOfRows = ''
1103 return self._numberOfRows
1105 def setNumberOfRows(self, value):
1106 self._numberOfRows = value
1108 def getNumberOfColumns(self):
1109 try:
1110 if self._numberOfColumns: pass
1111 except AttributeError:
1112 self._numberOfColumns = ''
1113 return self._numberOfColumns
1115 def setNumberOfColumns(self, value):
1116 self._numberOfColumns = value
1119 class NumberInput(FieldInputType, Fossilizable):
1121 fossilizes(IRegFormNumberInputFieldFossil)
1123 _id = "number"
1124 _useLabelCol = False
1126 def getName(cls):
1127 return "Number"
1128 getName = classmethod(getName)
1130 def __init__(self, field):
1131 FieldInputType.__init__(self, field)
1132 self._length = ''
1133 self._minValue = 0
1135 def _getModifHTML(self, item, registrant, default=""):
1136 description = self._parent.getDescription()
1137 price = self._parent.getPrice()
1138 billable = self._parent.isBillable()
1139 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1140 htmlName = self.getHTMLName()
1141 v = default or self.getMinValue()
1142 if item is not None:
1143 v = item.getValue()
1144 price = item.getPrice()
1145 billable = item.isBillable()
1146 currency = item.getCurrency()
1147 htmlName = item.getHTMLName()
1149 mandat = "false" if self._parent.isMandatory() else "true"
1150 if self.getMinValue() != 0:
1151 extra_check = "IndicoUtil.validate_number({minimum:%s})" % self.getMinValue()
1152 else:
1153 extra_check = "function(){}"
1154 param = """<script>addParam($E('%s'), 'non_negative_int', %s, %s);</script>""" % (htmlName, mandat, extra_check)
1156 disable = ""
1157 if (registrant is not None and billable and registrant.getPayed()):
1158 disable = "disabled=\"true\""
1159 #pass
1160 if self.getLength():
1161 length = 'size="%s"' % self.getLength()
1162 else:
1163 length = 'size="6"'
1164 onkeyup = ""
1165 if billable:
1166 onkeyup = """onkeyup="
1167 var value = ((isNaN(parseInt(this.value, 10)) || parseInt(this.value, 10) < 0) ? 0 : parseInt(this.value, 10)) * %s;
1168 $E('subtotal-%s').dom.innerHTML = parseInt(value) === parseFloat(value) ? value : value.toFixed(2);"
1169 """ % (price, htmlName)
1170 tmp = """<input type="text" id="%s" name="%s" value="%s" %s %s %s /> %s""" % (htmlName, htmlName, v, onkeyup, disable, length, param)
1171 tmp = """ <td>%s</td>""" % tmp
1172 if billable:
1173 subTotal = (float(price) * int(v) or 0)
1174 tmp = """%s<td align="right" align="bottom">&nbsp;&nbsp;<span>%s&nbsp;%s</span><span class="regFormSubtotal">Total: <span id="subtotal-%s">%s</span>&nbsp;%s</span></td> """ % (tmp, price, currency, htmlName, subTotal, currency)
1175 if description:
1176 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
1177 return tmp
1179 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1180 v = params.get(self.getHTMLName(), "")
1181 quantity = 0
1182 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
1183 #if ( item is not None and item.isBillable() ):
1184 #######################
1185 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
1186 return
1187 if not override and self.getParent().isMandatory() and v.strip() == "":
1188 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
1189 if not override and self.getParent().isMandatory() and (not v.isalnum() or int(v) < 0):
1190 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it with a number.") % self.getParent().getCaption())
1191 if not v.isalnum() or int(v) < 1:
1192 quantity = 0
1193 else:
1194 quantity = int(v)
1195 if v.strip() != '' and quantity < self.getMinValue():
1196 raise FormValuesError(_("The field \"%s\" needs to be filled with a number greater than or equal to %d.") % (self.getParent().getCaption(), self.getMinValue()))
1197 item.setQuantity(quantity)
1198 item.setValue(quantity)
1199 item.setBillable(self._parent.isBillable())
1200 item.setPrice(self._parent.getPrice())
1201 item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
1202 item.setMandatory(self.getParent().isMandatory())
1203 item.setHTMLName(self.getHTMLName())
1205 def _getSpecialOptionsHTML(self):
1206 price = self._parent.getPrice()
1207 billable = self._parent.isBillable()
1208 checked = ""
1209 if billable:
1210 checked = "checked=\"checked\""
1212 return i18nformat("""
1213 <tr>
1214 <td class="titleCellTD"><span class="titleCellFormat">_("Min. value")</span></td>
1215 <td bgcolor="white" class="blacktext" width="100%%">
1216 <input type="text" name="minValue" value="%s" />
1217 </td>
1218 </tr>
1219 <tr>
1220 <td class="titleCellTD"><span class="titleCellFormat">_("Size in chars")</span></td>
1221 <td bgcolor="white" class="blacktext" width="100%%">
1222 <input type="text" name="length" value="%s" />
1223 </td>
1224 </tr>
1225 <tr>
1226 <td class="titleCellTD"><span class="titleCellFormat">Is Billable</span></td>
1227 <td bgcolor="white" class="blacktext" width="100%%">
1228 <input type="checkbox" name="billable" size="60" %s> _("(uncheck if it is not billable)")
1229 </td>
1230 </tr>
1231 <tr>
1232 <td class="titleCellTD"><span class="titleCellFormat"> _("Price (multiplied with entered number)")</span></td>
1233 <td bgcolor="white" class="blacktext" width="100%%">
1234 <input type="text" name="price" size="60" value=%s>
1235 </td>
1236 </tr>""" % (self.getMinValue(), self.getLength(), checked, price))
1238 def clone(self, gf):
1239 ni = FieldInputType.clone(self, gf)
1240 ni.setLength(self.getLength())
1241 ni.setMinValue(self.getMinValue())
1242 return ni
1244 def getValues(self):
1245 d = {}
1246 d["length"] = self.getLength()
1247 d["minValue"] = self.getMinValue()
1248 return d
1250 def setValues(self, data):
1251 if data.has_key("length"):
1252 self.setLength(data.get("length"))
1253 if data.has_key("minValue"):
1254 self.setMinValue(int(data.get("minValue") or 0))
1256 def getLength(self):
1257 try:
1258 if self._length: pass
1259 except AttributeError:
1260 self._length = ''
1261 return self._length
1263 def setLength(self, value):
1264 self._length = value
1266 def getMinValue(self):
1267 try:
1268 if self._minValue: pass
1269 except AttributeError:
1270 self._minValue = 0
1271 return self._minValue
1273 def setMinValue(self, value):
1274 self._minValue = value
1276 def getModifLabelCol(self):
1277 return self._parent.getCaption()
1280 class LabelInput(FieldInputType, Fossilizable):
1282 fossilizes(IRegFormLabelInputFieldFossil)
1284 _id = "label"
1285 _wholeRow = True
1287 def getName(cls):
1288 return "Label"
1289 getName = classmethod(getName)
1291 def _getModifHTML(self, item, registrant, default=""):
1292 description = self._parent.getDescription()
1293 price = self._parent.getPrice()
1294 billable = self._parent.isBillable()
1295 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1296 v = default
1297 if item is not None:
1298 v = item.getValue()
1299 price = item.getPrice()
1300 billable = item.isBillable()
1301 currency = item.getCurrency()
1302 #pass
1303 tmp = """ <td align="right" valign="bottom">"""
1304 if billable:
1305 tmp = """%s&nbsp;&nbsp;%s&nbsp;%s</td> """ % (tmp, price, currency)
1306 else:
1307 tmp = """%s </td> """ % tmp
1308 if description:
1309 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
1310 return tmp
1312 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1313 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
1314 #if ( item is not None and item.isBillable()):
1315 #######################
1316 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
1317 return
1318 #item.setQuantity(0)
1319 #else:
1320 item.setQuantity(1)
1321 item.setValue("")
1322 item.setBillable(self._parent.isBillable())
1323 item.setPrice(self._parent.getPrice())
1324 item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
1325 item.setMandatory(self.getParent().isMandatory())
1326 item.setHTMLName(self.getHTMLName())
1327 #v=params.get(self.getHTMLName(),"")
1328 #if self.getParent().isMandatory() and v.strip()=="":
1329 # raise FormValuesError("The field \"%s\" is mandatory. Please fill it."%self.getParent().getCaption())
1330 #item.setValue(v)
1333 class CheckboxInput(FieldInputType, Fossilizable):
1335 fossilizes(IRegFormCheckboxInputFieldFossil)
1337 _id = "checkbox"
1338 _useLabelCol = False
1340 def getName(cls):
1341 return "Multiple choices/checkbox"
1342 getName = classmethod(getName)
1344 def _getModifHTML(self, item, registrant, default=""):
1345 disable = ""
1346 checked = ""
1347 mandatory = ""
1348 caption = self._parent.getCaption()
1349 description = self._parent.getDescription()
1350 price = self._parent.getPrice()
1351 billable = self._parent.isBillable()
1352 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1353 htmlName = self.getHTMLName()
1354 v = default
1355 quantity = 0
1356 if item is not None:
1357 v = item.getValue()
1358 price = item.getPrice()
1359 billable = item.isBillable()
1360 currency = item.getCurrency()
1361 htmlName = item.getHTMLName()
1362 quantity = item.getQuantity()
1363 mandatory = """<span class="regFormMandatoryField">*</span>""" if self._parent.isMandatory() else ""
1364 if (registrant is not None and billable and registrant.getPayed()) or (not self.getParent().hasAvailablePlaces() and not quantity):
1365 disable = "disabled=\"disabled\""
1366 if v == "yes":
1367 checked = "checked=\"checked\""
1368 pm = ''
1369 if self._parent.isMandatory():
1370 pm = """<script>addParam($E('%s'), 'checkBox', false);</script>""" % htmlName
1371 tmp = """<input type="checkbox" id="%s" name="%s" %s %s> %s %s%s""" % (htmlName, htmlName, checked, disable, caption, mandatory, pm)
1372 tmp = """ <td>%s</td><td align="right" align="bottom">""" % tmp
1373 if billable:
1374 tmp = """%s&nbsp;&nbsp;%s&nbsp;%s """ % (tmp, price, currency)
1375 if self.getParent().getPlacesLimit():
1376 tmp += """&nbsp;<span class='placesLeft'>[%s place(s) left]</span>""" % (self.getParent().getNoPlacesLeft())
1377 tmp += """</td>"""
1378 if description:
1379 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
1380 return tmp
1382 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1383 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
1384 #if ( item is not None and item.isBillable()):
1385 #######################
1386 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
1387 return
1388 if params.has_key(self.getHTMLName()):
1389 item.setValue("yes")
1390 item.setQuantity(1)
1391 elif not override and self.getParent().isMandatory():
1392 raise FormValuesError(_('The checkbox "%s" is mandatory. Please enable it.') % self.getParent().getCaption())
1393 else:
1394 item.setValue("no")
1395 item.setQuantity(0)
1396 item.setBillable(self._parent.isBillable())
1397 item.setPrice(self._parent.getPrice())
1398 item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
1399 item.setMandatory(self.getParent().isMandatory())
1400 item.setHTMLName(self.getHTMLName())
1402 def _getSpecialOptionsHTML(self):
1403 html = FieldInputType._getSpecialOptionsHTML(self)
1404 html += i18nformat("""<tr>
1405 <td class="titleCellTD"><span class="titleCellFormat"> _("Places (0 for unlimited)")</span></td>
1406 <td bgcolor="white" class="blacktext" width="100%%">
1407 <input type="text" name="placesLimit" size="60" value=%s>
1408 </td>
1409 </tr>""") % (self._parent.getPlacesLimit())
1410 return html
1413 class YesNoInput(FieldInputType, Fossilizable):
1415 fossilizes(IRegFormYesNoInputFieldFossil)
1417 _id = "yes/no"
1419 def getName(cls):
1420 return "Yes/No"
1421 getName = classmethod(getName)
1423 def _getModifHTML(self, item, registrant, default=""):
1424 description = self._parent.getDescription()
1425 price = self._parent.getPrice()
1426 billable = self._parent.isBillable()
1427 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1428 htmlName = self.getHTMLName()
1429 v = default
1430 if item is not None:
1431 v = item.getValue()
1432 price = item.getPrice()
1433 billable = item.isBillable()
1434 currency = item.getCurrency()
1435 htmlName = item.getHTMLName()
1436 disable = ""
1438 if self._parent.isMandatory():
1439 param = """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
1440 else:
1441 param = ''
1443 checkedYes = ""
1444 checkedNo = ""
1445 if (registrant is not None and billable and registrant.getPayed()):
1446 disable = "disabled=\"true\""
1447 #pass
1448 if v == "yes":
1449 checkedYes = "selected"
1450 elif v == "no":
1451 checkedNo = "selected"
1453 placesInfo = ""
1454 if self.getParent().getPlacesLimit():
1455 placesInfo = """&nbsp;[%s place(s) left]""" % (self.getParent().getNoPlacesLeft())
1456 if v != "yes" and not self.getParent().hasAvailablePlaces():
1457 checkedYes += " disabled"
1458 tmp = """<select id="%s" name="%s" %s><option value="">-- Choose a value --</option><option value="yes" %s>yes%s</option><option value="no" %s>no</option></select>%s""" % (htmlName, htmlName, disable, checkedYes, placesInfo, checkedNo, param)
1459 tmp = """ <td>%s</td><td align="right" align="bottom">""" % tmp
1460 if billable:
1461 tmp = """%s&nbsp;&nbsp;%s&nbsp;%s</td> """ % (tmp, price, currency)
1462 else:
1463 tmp = """%s </td> """ % tmp
1464 if description:
1465 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
1466 return tmp
1468 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1469 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
1470 #if ( item is not None and item.isBillable()):
1471 # return
1472 #######################
1473 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
1474 return
1475 v = params.get(self.getHTMLName())
1477 if not override and self.getParent().isMandatory() and v.strip() == "":
1478 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
1480 if v == "yes":
1481 item.setQuantity(1)
1482 else:
1483 item.setQuantity(0)
1484 item.setValue(v)
1485 item.setBillable(self._parent.isBillable())
1486 item.setPrice(self._parent.getPrice())
1487 item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
1488 item.setMandatory(self.getParent().isMandatory())
1489 item.setHTMLName(self.getHTMLName())
1491 def _getSpecialOptionsHTML(self):
1492 html = FieldInputType._getSpecialOptionsHTML(self)
1493 html += i18nformat("""<tr>
1494 <td class="titleCellTD"><span class="titleCellFormat"> _("Places (0 for unlimited)")</span></td>
1495 <td bgcolor="white" class="blacktext" width="100%%">
1496 <input type="text" name="placesLimit" size="60" value=%s>
1497 </td>
1498 </tr>""") % (self._parent.getPlacesLimit())
1499 return html
1502 class FileInput(FieldInputType, Fossilizable):
1504 fossilizes(IRegFormFileInputFieldFossil)
1506 _id = "file"
1508 def getName(cls):
1509 return "File"
1510 getName = classmethod(getName)
1512 def getValueDisplay(self, value):
1513 uh = (urlHandlers.UHRegistrantAttachmentFileAccess if request.blueprint == 'event_mgmt' else
1514 urlHandlers.UHFileAccess)
1515 return """<a href="%s">%s</a>""" % (uh.getURL(value), value.getFileName())
1517 def _getModifHTML(self, item, registrant, default=None):
1518 from MaKaC.webinterface.pages.registrationForm import WFileInputField
1520 wc = WFileInputField(self, item, default)
1521 return wc.getHTML()
1523 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
1524 v = params.get(self.getHTMLName(), "")
1525 newValueEmpty = v.strip() == "" if isinstance(v, str) else v.filename == ""
1526 if not override and self.getParent().isMandatory() and newValueEmpty:
1527 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
1529 item.setMandatory(self.getParent().isMandatory())
1530 item.setHTMLName(self.getHTMLName())
1531 # There was no file saved on DB
1532 if item.getValue() is None:
1533 if not newValueEmpty: # user submits a new file
1534 f = registrant.saveFile(v)
1535 item.setValue(f)
1536 # There was already a file on DB
1537 # if 'str': it means that we are receiving the name of the already existing file. Do not modify.
1538 # if file descriptor: replace previous file with new one
1539 # if 'empty' value: just remove
1540 elif not isinstance(v, str):
1541 # delete
1542 registrant.deleteFile(item.getValue().getId())
1543 item.setValue(None)
1544 # new file
1545 if not newValueEmpty:
1546 f = registrant.saveFile(v)
1547 item.setValue(f)
1549 def _getSpecialOptionsHTML(self):
1550 return ""
1552 def clone(self, gf):
1553 ti = FieldInputType.clone(self, gf)
1554 return ti
1557 class RadioItem(Persistent, Fossilizable):
1559 fossilizes(IRegFormRadioItemFossil)
1561 def __init__(self, parent):
1562 self._parent = parent
1563 self._id = ""
1564 self._caption = ""
1565 self._billable = False
1566 self._price = ""
1567 self._enabled = True
1568 self._placesLimit = 0
1569 self._currentNoPlaces = 0
1571 def setValues(self, data):
1572 if data.has_key("caption"):
1573 self.setCaption(data["caption"])
1574 if data.has_key("isBillable"):
1575 self.setBillable(data["isBillable"])
1576 if data.has_key("price"):
1577 self.setPrice(data["price"])
1578 if data.has_key("isEnabled"):
1579 self.setEnabled(data["isEnabled"])
1580 if data.has_key("placesLimit"):
1581 self.setPlacesLimit(data["placesLimit"])
1583 def getId(self):
1584 return self._id
1586 def setId(self, id):
1587 self._id = id
1589 def getCaption(self):
1590 return self._caption
1592 def setCaption(self, cap):
1593 if self._caption != cap:
1594 self.updateRegistrantSelection(cap)
1595 self._caption = cap
1597 def setEnabled(self, en=True):
1598 self._enabled = en
1600 def isEnabled(self):
1601 try:
1602 return self._enabled
1603 except:
1604 self.setEnabled()
1605 return self._enabled
1607 def isBillable(self):
1608 try:
1609 return self._billable
1610 except:
1611 self._billable = False
1612 return self._billable
1614 def setBillable(self, v):
1615 self._billable = v
1617 def getPrice(self):
1618 try:
1619 return self._price
1620 except:
1621 self.setPrice(False)
1622 return self._price
1624 def setPrice(self, price):
1625 if price:
1626 match = PRICE_PATTERN.match(price)
1627 if match:
1628 price = match.group(1)
1629 else:
1630 raise MaKaCError(_('The price is in incorrect format!'))
1631 self._price = price
1633 def getPlacesLimit(self):
1634 try:
1635 if self._placesLimit:
1636 pass
1637 except AttributeError, e:
1638 self._placesLimit = 0
1639 return self._placesLimit
1641 def setPlacesLimit(self, limit):
1642 if limit == "":
1643 limit = "0"
1644 try:
1645 l = int(limit)
1646 except ValueError:
1647 raise FormValuesError(_("Please enter a number for the limit of places"))
1648 self._placesLimit = l
1649 self.updateCurrentNoPlaces()
1651 def getCurrentNoPlaces(self):
1652 try:
1653 if self._currentNoPlaces:
1654 pass
1655 except AttributeError:
1656 self._currentNoPlaces = 0
1657 return self._currentNoPlaces
1659 def hasAvailablePlaces(self):
1660 if not self.getPlacesLimit():
1661 return True
1662 return (self.getCurrentNoPlaces() < self.getPlacesLimit())
1664 def getNoPlacesLeft(self):
1665 return self.getPlacesLimit() - self.getCurrentNoPlaces()
1667 def increaseNoPlaces(self):
1668 if self.getPlacesLimit() > 0 :
1669 if self.getCurrentNoPlaces() >= self.getPlacesLimit():
1670 raise FormValuesError(_("""The place limit has been exceeded."""))
1671 self._currentNoPlaces += 1
1673 def decreaseNoPlaces(self):
1674 if self.getPlacesLimit() > 0 and self.getCurrentNoPlaces() > 0:
1675 self._currentNoPlaces -= 1
1677 def updateCurrentNoPlaces(self):
1678 # self -> RadioGroupInput -> GeneralField -> GeneralSectionForm
1679 gf = self._parent._parent
1680 self._currentNoPlaces = 0
1681 gsf = gf._parent
1682 regform = gsf.getRegistrationForm()
1683 for reg in regform.getConference().getRegistrantsList():
1684 mg = reg.getMiscellaneousGroupById(gsf.getId())
1685 if not mg:
1686 continue
1687 gf.getId() # for some reason it's empty when calling it for the first time
1688 item = mg.getResponseItemById(gf.getId())
1689 if item is not None and item.getQuantity() and item.getValue() == self.getCaption():
1690 self.increaseNoPlaces()
1692 def updateRegistrantSelection(self, caption):
1693 gf = self._parent._parent
1694 self._currentNoPlaces = 0
1695 gsf = gf._parent
1696 regform = gsf.getRegistrationForm()
1697 for reg in regform.getConference().getRegistrantsList():
1698 mg = reg.getMiscellaneousGroupById(gsf.getId())
1699 if not mg:
1700 continue
1701 item = mg.getResponseItemById(gf.getId())
1702 if item is not None and item.getQuantity() and item.getValue() == self.getCaption():
1703 item.setValue(caption)
1704 self.increaseNoPlaces()
1706 def clone(self, parent):
1707 ri = RadioItem(parent)
1708 ri.setCaption(self.getCaption())
1709 ri.setBillable(self.isBillable())
1710 ri.setPrice(self.getPrice())
1711 ri.setEnabled(self.isEnabled())
1712 ri.setPlacesLimit(self.getPlacesLimit())
1713 return ri
1715 def _cmpCaption(r1, r2):
1716 return cmp(r1.getCaption(), r2.getCaption())
1717 _cmpCaption = staticmethod(_cmpCaption)
1720 class RadioGroupInput(FieldInputType, Fossilizable):
1722 fossilizes(IRegFormRadioGroupInputFieldFossil)
1724 _id = "radio"
1726 def getName(cls):
1727 return "Multiple options/One choice"
1728 getName = classmethod(getName)
1730 def __init__(self, field):
1731 FieldInputType.__init__(self, field)
1732 self._items = []
1733 self._radioItemGenerator = Counter()
1734 self._defaultItem = None
1735 self._inputType = "radiogroup"
1736 self._emptyCaption = '-- Choose a value --'
1738 def getValues(self):
1739 d = {}
1740 d["radioitems"] = []
1741 for i in self.getItemsList():
1742 tmp = {}
1743 tmp["caption"] = i.getCaption()
1744 tmp["billable"] = i.isBillable()
1745 tmp["price"] = i.getPrice()
1746 tmp["isEnabled"] = i.isEnabled()
1747 tmp["placesLimit"] = i.getPlacesLimit()
1748 tmp["id"] = i.getId()
1749 d["radioitems"].append(tmp)
1750 d["defaultItem"] = self.getDefaultItem()
1751 d["inputType"] = self.getInputType()
1752 d["emptyCaption"] = self.getEmptyCaption()
1753 return d
1755 def setValues(self, data):
1756 if "radioitems" in data:
1757 for i, itemValues in enumerate(data.get("radioitems", [])):
1758 item = self.getItemById(itemValues.get('id'))
1759 if item is None:
1760 self.createItem(itemValues, i)
1761 else:
1762 # remove else set and move
1763 if 'remove' in itemValues:
1764 self.removeItem(item)
1765 else:
1766 item.setValues(itemValues)
1767 self.addItem(item, i)
1769 if "defaultItem" in data:
1770 self.setDefaultItem(data.get("defaultItem", None))
1771 if "inputType" in data:
1772 self._inputType = data.get("inputType")
1773 if "emptyCaption" in data:
1774 self._emptyCaption = data["emptyCaption"]
1776 def _beforeValueChange(self, item, newItem):
1777 # if the item had a quantity, make the place available again
1778 selected = self.getSelectedItem(item)
1779 if not newItem and selected:
1780 selected.decreaseNoPlaces()
1782 def _afterValueChange(self, item):
1783 # if the item has a quantity now, make the place unavailable
1784 selected = self.getSelectedItem(item)
1785 if selected:
1786 selected.increaseNoPlaces()
1788 def getSelectedItem(self, item):
1789 for val in self.getItemsList():
1790 if val.getCaption() == item.getValue():
1791 return val
1792 return None
1794 def getDefaultItem(self):
1795 try:
1796 if self._defaultItem:
1797 pass
1798 except AttributeError, e:
1799 self._defaultItem = None
1800 return self._defaultItem
1802 def setDefaultItem(self, caption):
1803 if caption == "":
1804 self._defaultItem = None
1805 else:
1806 self._defaultItem = caption
1808 def setDefaultItemById(self, id):
1809 item = self.getItemById(id)
1810 if item in self.getItemsList():
1811 self.setDefaultItem(item.getCaption())
1813 def changeItemById(self, id, caption=None, billable=None, price=None, places=None):
1814 item = self.getItemById(id)
1815 if item in self.getItemsList():
1816 if caption:
1817 item.setCaption(caption)
1818 if billable and price:
1819 item.setBillable(billable)
1820 item.setPrice(price)
1821 if places or places == 0: # empty string doesn't change it, 0 does
1822 item.setPlacesLimit(places)
1824 def removePriceById(self, id):
1825 item = self.getItemById(id)
1826 if item in self.getItemsList():
1827 item.setBillable(False)
1828 item.setPrice("")
1830 def setInputType(self, inputType):
1831 self._inputType = inputType
1833 def getInputType(self):
1834 try:
1835 if self._inputType:
1836 pass
1837 except AttributeError:
1838 self._inputType = "radiogroup"
1839 return self._inputType
1841 def getItemsList(self):
1842 if type(self._items) == dict:
1843 self._items = self._items.values()
1844 return self._items
1846 def addItem(self, item, i=None):
1847 if i is None:
1848 i = len(self.getItemsList())
1849 if item in self.getItemsList():
1850 self.removeItem(item)
1851 else:
1852 item.setId(str(self._getRadioItemGenerator().newCount()))
1854 self.getItemsList().insert(i, item)
1855 self.notifyModification()
1856 return True
1858 def createItem(self, itemValues, i=None):
1859 item = RadioItem(self)
1860 item.setValues(itemValues)
1861 self.addItem(item, i)
1863 def removeItem(self, item):
1864 if item in self.getItemsList():
1865 self.getItemsList().remove(item)
1866 self.notifyModification()
1868 def removeItemById(self, id):
1869 return self.removeItem(self.getItemById(id))
1871 def disableItemById(self, id):
1872 item = self.getItemById(id)
1873 if item in self.getItemsList():
1874 item.setEnabled(not item.isEnabled())
1875 self.notifyModification()
1877 def getItemById(self, id):
1878 for f in self.getItemsList():
1879 if f.getId() == id:
1880 return f
1881 return None
1883 def notifyModification(self):
1884 self._p_changed = 1
1886 def clone(self, gf):
1887 rgi = FieldInputType.clone(self, gf)
1888 for item in self.getItemsList():
1889 rgi.addItem(item.clone(rgi))
1890 rgi.setDefaultItem(self.getDefaultItem())
1891 rgi.setInputType(self.getInputType())
1892 return rgi
1894 def _getRadioItemGenerator(self):
1895 return self._radioItemGenerator
1897 def getEmptyCaption(self):
1898 try:
1899 return self._emptyCaption
1900 except:
1901 self._emptyCaption = '-- Choose a value --'
1902 return self._emptyCaption
1904 def _getRadioGroupModifHTML(self, item, registrant, default=""):
1905 description = self._parent.getDescription()
1906 caption = self._parent.getCaption()
1907 billable = self._parent.isBillable()
1908 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1909 value = default
1910 if item is not None:
1911 billable = item.isBillable()
1912 currency = item.getCurrency()
1913 value = item.getValue()
1915 tmp = ["""<td align="right" align="bottom" colspan="2"></td>"""]
1917 counter = 0
1918 for val in self.getItemsList():
1919 counter += 1
1920 itemId = "%s_%s" % (self.getHTMLName(), counter)
1921 disable = ""
1922 if not val.isEnabled():
1923 disable = "disabled=\"disabled\""
1924 if (registrant is not None and (val.isBillable() or billable) and registrant.getPayed()):
1925 disable = "disabled=\"disabled\""
1926 elif (not val.hasAvailablePlaces() and val.getCaption() != value):
1927 disable = "disabled=\"disabled\""
1928 checked = ""
1929 if val.getCaption() == value:
1930 checked = "checked"
1931 elif not value and val.getCaption() == self.getDefaultItem():
1932 checked = "checked"
1933 tmp.append("""<tr><td></td><td><input type="radio" id="%s" name="%s" value="%s" %s %s> %s</td><td align="right" style="vertical-align: bottom;" >""" % (itemId, self.getHTMLName(), val.getId(), checked, disable, val.getCaption()))
1934 if val.isBillable():
1935 tmp.append("""&nbsp;&nbsp;%s&nbsp;%s""" % (val.getPrice(), currency))
1936 tmp.append("""</td><td align="right" style="vertical-align: bottom;" >""")
1937 if val.getPlacesLimit():
1938 tmp.append("""&nbsp;<span class='placesLeft'>[%s place(s) left]</span>""" % (val.getNoPlacesLeft()))
1939 tmp.append(""" </td></tr> """)
1941 if description:
1942 tmp.append("""<tr><td></td><td colspan="2">%s</td></tr>""" % (self._getDescriptionHTML(description)))
1944 if self._parent.isMandatory():
1945 validator = """
1946 for (var i=1; i<=%s; i++) {
1947 var item = $E('%s_' + i);
1948 if (item.dom.checked) {
1949 return true;
1952 new AlertPopup($T("Warning"), $T('You must select option for "%s"!')).open();
1953 return false;
1954 """ % (counter, self.getHTMLName(), caption)
1955 script = """<script>addValidator(function() {%s});</script>""" % validator
1956 tmp.append(script)
1958 return "".join(tmp)
1960 def _getDropDownModifHTML(self, item, registrant, default=""):
1961 description = self._parent.getDescription()
1962 billable = self._parent.isBillable()
1963 currency = self._parent.getParent().getRegistrationForm().getCurrency()
1964 value = default
1965 if item is not None:
1966 billable = item.isBillable()
1967 currency = item.getCurrency()
1968 value = item.getValue()
1970 if not value:
1971 value = self.getDefaultItem()
1973 if self._parent.isMandatory():
1974 param = """<script>addParam($E('%s'), 'text', false);</script>""" % self.getHTMLName()
1975 else:
1976 param = ''
1978 tmp = []
1979 tmp.append("""<td><select id="%s" name="%s">""" % (self.getHTMLName(), self.getHTMLName()))
1981 tmp.append("""<option value="">%s</option>""" % self.getEmptyCaption())
1983 for radioItem in self.getItemsList():
1984 if radioItem.isEnabled() and not (registrant is not None and (radioItem.isBillable() or billable) and registrant.getPayed()):
1986 placesInfo = ""
1987 if radioItem.getPlacesLimit():
1988 placesInfo = """&nbsp;[%s place(s) left]""" % (radioItem.getNoPlacesLeft())
1990 disabled = ""
1991 if (not radioItem.hasAvailablePlaces() and radioItem.getCaption() != value):
1992 disabled = " disabled='disabled'"
1994 selected = ""
1995 if radioItem.getCaption() == value:
1996 selected = " selected='selected'"
1997 else:
1998 selected = ''
2000 if radioItem.isBillable():
2001 price = """&nbsp;&nbsp;%s&nbsp;%s """ % (radioItem.getPrice(), currency)
2002 else:
2003 price = ''
2005 tmp.append("""<option value="%s"%s%s>%s%s%s</option>""" % (radioItem.getId(), selected, disabled, radioItem.getCaption(), price, placesInfo))
2007 tmp.append("""</select>%s</td>""" % param)
2009 if description:
2010 tmp.append("""<tr><td colspan="2">%s</td></tr>""" % (self._getDescriptionHTML(description)))
2012 return "".join(tmp)
2014 def _getModifHTML(self, item, registrant, default=""):
2015 if self.getInputType() == 'radiogroup':
2016 return self._getRadioGroupModifHTML(item, registrant, default)
2017 else:
2018 return self._getDropDownModifHTML(item, registrant, default)
2020 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
2021 radioitemid = params.get(self.getHTMLName(), "")
2022 billable = False
2023 for val in self.getItemsList():
2024 if val.isBillable():
2025 billable = True
2026 if (registrant is not None and self._parent.isBillable() and registrant.getPayed()):
2027 #if (item is not None and billable):
2028 #######################
2029 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
2030 return
2031 if not override and self.getParent().isMandatory() and radioitemid.strip() == "":
2032 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
2033 price = 0
2034 quantity = 0
2035 caption = ""
2036 if radioitemid.strip() != "":
2037 radioitem = self.getItemById(radioitemid)
2038 if radioitem is not None:
2039 caption = radioitem.getCaption()
2040 billable = radioitem.isBillable()
2041 price = radioitem.getPrice()
2042 quantity = 1
2044 item.setCurrency(self._parent.getParent().getRegistrationForm().getCurrency())
2045 item.setMandatory(self.getParent().isMandatory())
2046 item.setValue(caption)
2047 item.setBillable(billable)
2048 item.setPrice(price)
2049 item.setQuantity(quantity)
2050 item.setHTMLName(self.getHTMLName())
2052 def _getSpecialOptionsHTML(self):
2053 if self.getInputType() == 'radiogroup':
2054 radioSelected = ' selected="selected"'
2055 dropdownSelected = ''
2056 else:
2057 radioSelected = ''
2058 dropdownSelected = ' selected="selected"'
2059 if self.getParent().isLocked('input'):
2060 typeDisabled = ' disabled="disabled"'
2061 else:
2062 typeDisabled = ''
2063 html = [i18nformat("""
2064 <tr>
2065 <td class="titleCellTD"><span class="titleCellFormat">_("Type of input")</span></td>
2066 <td bgcolor="white" class="blacktext" width="100%%">
2067 <select name="inputtype"%(typeDisabled)s>
2068 <option value="radiogroup"%(radioSelected)s>Radio group</option>
2069 <option value="dropdown"%(dropdownSelected)s>Drop-down menu</option>
2070 </select>
2071 </td>
2072 </tr>
2073 <tr>
2074 <td class="titleCellTD"><span class="titleCellFormat">Items</span></td>
2075 <td bgcolor="white" class="blacktext" width="100%%">
2076 <table>""") % dict(radioSelected=radioSelected, dropdownSelected=dropdownSelected, typeDisabled=typeDisabled)]
2077 html.append(i18nformat("""<tr>
2078 <td valign="top" align="left">
2079 <table>
2080 <tr>
2081 <td class="blacktext"><span class="titleCellFormat"> _("Caption")</span></td>
2082 <td bgcolor="white" class="blacktext" width="100%%">
2083 <input type="text" name="newradioitem">
2084 </td>
2085 </tr>
2086 <tr>
2087 <td class="blacktext"><span class="titleCellFormat"> _("Billable")</span></td>
2088 <td bgcolor="white" class="blacktext" width="100%%">
2089 <input type="checkbox" name="newbillable" >
2090 </td>
2091 </tr>
2092 <tr>
2093 <td class="blacktext"><span class="titleCellFormat"> _("Price")</span></td>
2094 <td bgcolor="white" class="blacktext" width="100%%">
2095 <input type="text" name="newprice">
2096 </td>
2097 </tr>
2098 <tr>
2099 <td class="blacktext"><span class="titleCellFormat"> _("Places")</span></td>
2100 <td bgcolor="white" class="blacktext" width="100%%">
2101 <input type="text" name="newplaces">%s
2102 </td>
2103 </tr>
2104 </table>
2105 </td>
2106 <td rowspan="2" valign="top" align="left">
2107 <input type="submit" class="btn" name="addradioitem" value="_("add")" onfocus="addIsFocused = true;" onblur="addIsFocused = false;"><br>
2108 <input type="submit" class="btn" name="removeradioitem" value="_("remove")"><br>
2109 <input type="submit" class="btn" name="disableradioitem" value="_("enable/disable")"><br>
2110 <input type="submit" class="btn" name="defaultradioitem" value="_("set as default")"><br>
2111 <input type="submit" class="btn" name="changeradioitem" value="_("change")"><br>
2112 <input type="submit" class="btn" name="removeradioitemprice" value="_("remove price")"><br>
2113 </td>
2114 </tr>
2115 """) % inlineContextHelp(_('Use 0 for unlimited places')))
2116 html.append("""<tr><td valign="top" align="left"><table>""")
2117 billable = False
2118 for v in self.getItemsList():
2119 placesInfo = ""
2120 if v.getPlacesLimit():
2121 placesInfo = " (%s places)" % (v.getPlacesLimit())
2122 html.append("""
2123 <tr>
2124 <td bgcolor="white" class="blacktext" ><input type="checkbox" name="radioitems" value="%s">%s%s</td>
2125 <td bgcolor="white" class="blacktext" >
2126 """ % (v.getId(), v.getCaption(), placesInfo))
2127 if v.isBillable():
2128 billable = True
2129 html.append(i18nformat("""<span class="titleCellFormat">&nbsp;&nbsp; _("Price"):%s</span>""") % (v.getPrice()))
2130 if not v.isEnabled():
2131 html.append("""<span><font color="red">&nbsp;&nbsp;(""" + _("disabled") + """)</font></span>""")
2132 if v.getCaption() == self.getDefaultItem():
2133 html.append("""<span><font color="green">&nbsp;&nbsp;(""" + _("default") + """)</font></span>""")
2134 html.append("""
2135 </td>
2136 </tr>
2137 """)
2138 html.append("""</table></td></tr>""")
2139 if billable:
2140 html.append("""<input type="hidden" name="billable" value="">""")
2141 html.append("""</table></td></tr>""")
2142 return "".join(html)
2145 class CountryInput(FieldInputType, Fossilizable):
2147 fossilizes(IRegFormCountryInputFieldFossil)
2149 _id = "country"
2151 def getName(cls):
2152 return "Country"
2153 getName = classmethod(getName)
2155 def getValueDisplay(self, value):
2156 return CountryHolder().getCountryById(value)
2158 def getCountriesList(self):
2159 countryList = []
2160 for countryKey in CountryHolder().getCountrySortedKeys():
2161 country = {}
2162 country["countryKey"] = countryKey
2163 country["caption"] = CountryHolder().getCountryById(countryKey)
2164 countryList.append(country)
2165 return countryList
2167 def _getModifHTML(self, item, registrant, default=""):
2168 description = self._parent.getDescription()
2169 htmlName = self.getHTMLName()
2170 value = default
2171 if item is not None:
2172 value = item.getValue()
2173 htmlName = item.getHTMLName()
2174 disable = ""
2176 if self._parent.isMandatory():
2177 param = """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
2178 else:
2179 param = ''
2181 inputHTML = i18nformat("""<option value="">-- _("Select a country") --</option>""")
2182 for countryKey in CountryHolder().getCountrySortedKeys():
2183 selected = ""
2184 if value == countryKey:
2185 selected = "selected"
2186 inputHTML += """<option value="%s" %s>%s</option>""" % (countryKey, selected, CountryHolder().getCountryById(countryKey))
2187 inputHTML = """<select id="%s" name="%s" %s>%s</select>%s""" % (htmlName, htmlName, disable, inputHTML, param)
2189 tmp = """ <td>%s</td>""" % inputHTML
2190 if description:
2191 tmp = """%s</tr><tr><td colspan="2">%s</td>""" % (tmp, self._getDescriptionHTML(description))
2192 return tmp
2194 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
2195 v = params.get(self.getHTMLName(), "")
2196 if not override and self.getParent().isMandatory() and v.strip() == "":
2197 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
2199 item.setQuantity(0)
2200 item.setValue(v)
2201 item.setMandatory(self.getParent().isMandatory())
2202 item.setHTMLName(self.getHTMLName())
2204 def _getSpecialOptionsHTML(self):
2205 return ""
2208 class DateInput(FieldInputType, Fossilizable):
2210 fossilizes(IRegFormDateInputFieldFossil)
2212 _id = "date"
2214 def __init__(self, field):
2215 FieldInputType.__init__(self, field)
2216 self.dateFormat = ''
2218 def getName(cls):
2219 return "Date"
2220 getName = classmethod(getName)
2222 def getValues(self):
2223 d = {}
2224 d["dateFormat"] = self.getDateFormat()
2225 return d
2227 def setValues(self, data):
2228 if data.has_key("dateFormat"):
2229 self.setDateFormat(data.get("dateFormat"))
2231 def clone(self, gf):
2232 di = FieldInputType.clone(self, gf)
2233 di.dateFormat = self.getDateFormat()
2234 return di
2236 def getDateFormat(self):
2237 if self.dateFormat == '':
2238 self.dateFormat = self.getDisplayFormats()[0][0]
2239 return self.dateFormat
2241 def setDateFormat(self, dateFormat):
2242 self.dateFormat = dateFormat
2244 def getDisplayFormats(self):
2245 return [('%d/%m/%Y %H:%M', 'DD/MM/YYYY hh:mm'),
2246 ('%d.%m.%Y %H:%M', 'DD.MM.YYYY hh:mm'),
2247 ('%m/%d/%Y %H:%M', 'MM/DD/YYYY hh:mm'),
2248 ('%m.%d.%Y %H:%M', 'MM.DD.YYYY hh:mm'),
2249 ('%Y/%m/%d %H:%M', 'YYYY/MM/DD hh:mm'),
2250 ('%Y.%m.%d %H:%M', 'YYYY.MM.DD hh:mm'),
2251 ('%d/%m/%Y', 'DD/MM/YYYY'),
2252 ('%d.%m.%Y', 'DD.MM.YYYY'),
2253 ('%m/%d/%Y', 'MM/DD/YYYY'),
2254 ('%m.%d.%Y', 'MM.DD.YYYY'),
2255 ('%Y/%m/%d', 'YYYY/MM/DD'),
2256 ('%Y.%m.%d', 'YYYY.MM.DD'),
2257 ('%m/%Y', 'MM/YYYY'),
2258 ('%m.%Y', 'MM.YYYY'),
2259 ('%Y', 'YYYY')]
2261 def getValueDisplay(self, value):
2262 if type(value) == datetime:
2263 return value.strftime(self.getDateFormat())
2264 else:
2265 return value
2267 def getHTMLName(self):
2268 return "_genfield_%s_%s_" % (self.getParent().getParent().getId(), self.getParent().getId())
2270 def _getModifHTML(self, item, registrant, default=""):
2271 description = self._parent.getDescription()
2272 if item is not None:
2273 date = item.getValue()
2274 htmlName = item.getHTMLName()
2275 else:
2276 date = default or None
2277 htmlName = self.getHTMLName()
2279 from MaKaC.webinterface.wcomponents import WDateField
2280 inputHTML = WDateField(htmlName, date, self.getDateFormat(), True, self._parent.isMandatory()).getHTML()
2282 dateFormat = self.getDateFormat()
2283 dateFormat = re.sub('%d', 'DD', dateFormat)
2284 dateFormat = re.sub('%m', 'MM', dateFormat)
2285 dateFormat = re.sub('%Y', 'YYYY', dateFormat)
2286 dateFormat = re.sub('%H', 'hh', dateFormat)
2287 dateFormat = re.sub('%M', 'mm', dateFormat)
2289 dformat = """&nbsp;<span class="inputDescription">%s</span>""" % dateFormat
2290 tmp = "%s %s" % (inputHTML, dformat)
2291 tmp = """ <td>%s</td><td align="right" align="bottom">""" % tmp
2292 tmp = """%s </td> """ % tmp
2293 if description:
2294 tmp = """%s</tr><tr><td>%s</td>""" % (tmp, self._getDescriptionHTML(description))
2295 return tmp
2297 def _setResponseValue(self, item, params, registrant, override=False, validate=True):
2298 day = params.get('%sDay' % self.getHTMLName(), 1) or 1
2299 month = params.get('%sMonth' % self.getHTMLName(), 1) or 1
2300 year = params.get('%sYear' % self.getHTMLName())
2302 hour = params.get('%sHour' % self.getHTMLName(), 0) or 0
2303 minute = params.get('%sMin' % self.getHTMLName(), 0) or 0
2305 if year:
2306 date = datetime(int(year), int(month), int(day), int(hour), int(minute))
2307 item.setValue(date)
2308 elif not self._parent.isMandatory():
2309 item.setValue(None)
2310 elif not override:
2311 raise FormValuesError(_("The field \"%s\" is mandatory. Please fill it.") % self.getParent().getCaption())
2313 item.setMandatory(self.getParent().isMandatory())
2314 item.setHTMLName(self.getHTMLName())
2316 def _getSpecialOptionsHTML(self):
2317 formats = self.getDisplayFormats()
2319 html = [i18nformat("""
2320 <tr>
2321 <td class="titleCellTD"><span class="titleCellFormat">_("Date format")</span></td>
2322 <td bgcolor="white" class="blacktext" width="100%%">
2323 <select name="dateFormat">""")]
2325 for format, display in formats:
2326 if self.getDateFormat() == format:
2327 selected = ' selected="selected"'
2328 else:
2329 selected = ''
2330 html.append("""<option value="%s"%s>%s</option>""" % (format, selected, display))
2332 html.append(_("""</select>
2333 </td>
2334 </tr>"""))
2335 return "".join(html)
2337 def _getFormatDisplayText(self):
2338 formats = self.getDisplayFormats()
2340 value = ""
2341 for dateFormat, display in formats:
2342 if self.getDateFormat() == dateFormat:
2343 value = display
2344 break
2345 return value
2348 class FieldInputs:
2350 _availableInputs = {TextInput.getId():TextInput, \
2351 TextareaInput.getId(): TextareaInput, \
2352 LabelInput.getId():LabelInput, \
2353 NumberInput.getId():NumberInput, \
2354 RadioGroupInput.getId():RadioGroupInput, \
2355 CheckboxInput.getId():CheckboxInput, \
2356 YesNoInput.getId(): YesNoInput, \
2357 CountryInput.getId(): CountryInput, \
2358 DateInput.getId(): DateInput, \
2359 TelephoneInput.getId(): TelephoneInput, \
2360 FileInput.getId(): FileInput
2363 def getAvailableInputs(cls):
2364 return cls._availableInputs
2365 getAvailableInputs = classmethod(getAvailableInputs)
2367 def getAvailableInputKlassById(cls, id):
2368 return cls._availableInputs.get(id, None)
2369 getAvailableInputKlassById = classmethod(getAvailableInputKlassById)
2371 def getAvailableInputKeys(cls):
2372 return cls._availableInputs.keys()
2373 getAvailableInputKeys = classmethod(getAvailableInputKeys)
2376 class GeneralField(Persistent, Fossilizable):
2378 fossilizes(IRegFormGeneralFieldFossil)
2380 def __init__(self, parent, data=None):
2381 self._parent = parent
2382 self._id = ""
2383 if data is None:
2384 self._caption = "General Field"
2385 self._input = FieldInputs.getAvailableInputKlassById("text")(self)
2386 self._input.setValues(data)
2387 self._mandatory = False
2388 self._locked = ()
2389 self._description = ""
2390 self._billable = False
2391 self._price = "0"
2392 self._placesLimit = 0
2393 self._currentNoPlaces = 0
2394 self._disabled = True
2395 self._pdField = None
2396 else:
2397 self._mandatory = False
2398 self.setValues(data, True)
2400 def clone(self, newsection):
2401 field = GeneralField(newsection, self.getValues())
2402 return field
2404 def setValues(self, data, firstTime=False):
2405 caption = data.get("caption", "")
2406 if caption == "":
2407 caption = _("General Field")
2408 self.setCaption(caption)
2409 ## The following commented lines were removed, but it is unclear if they are not needed anymore.
2410 if firstTime: # or not self.isLocked('input'):
2411 self.setInput(FieldInputs.getAvailableInputKlassById(data.get("input", "text"))(self))
2412 #else:
2413 # self.setInput(FieldInputs.getAvailableInputKlassById(self.getInput().getId())(self))
2414 if data.has_key("inputObj"):
2415 self._input.setValues(data["inputObj"].getValues())
2416 elif data.has_key('inputValues'):
2417 self._input.setValues(data["inputValues"])
2418 else:
2419 self._input.setValues(data)
2420 if firstTime:
2421 self.setLocked(data.get("lock", ()))
2422 if self.isMandatory() and self.isLocked('mandatory'):
2423 self.setMandatory(True)
2424 else:
2425 self.setMandatory(data['mandatory'] if 'mandatory' in data else False)
2426 if self.isLocked('disable'):
2427 self.setDisabled(False)
2428 elif 'disabled' in data:
2429 self.setDisabled(data.get("disabled", False))
2430 self.setBillable(data.get("billable", False))
2431 self.setPrice(str(data.get("price", "")))
2432 self.setPlacesLimit(data.get("placesLimit", "0"))
2433 self.setDescription(data.get("description", ""))
2434 if firstTime:
2435 self.setPDField(data.get("pd"))
2437 def getValues(self):
2438 values = {}
2439 values["caption"] = self.getCaption()
2440 values["input"] = self.getInput().getId()
2441 values["inputObj"] = self.getInput()
2442 values["lock"] = self.getLocked()
2443 values["mandatory"] = self.isMandatory()
2444 values["disabled"] = self.isDisabled()
2445 values["billable"] = self.isBillable()
2446 values["price"] = self.getPrice()
2447 values["placesLimit"] = self.getPlacesLimit()
2448 values["description"] = self.getDescription()
2449 values["pd"] = self.getPDField()
2450 return values
2452 def isTemporary(self):
2453 return False
2455 def setPDField(self, v):
2456 self._pdField = v
2458 def getPDField(self):
2459 try:
2460 return self._pdField
2461 except:
2462 self._pdField = None
2463 return self._pdField
2465 def isBillable(self):
2466 try:
2467 return self._billable
2468 except:
2469 self._billable = False
2470 return self._billable
2472 def setBillable(self, v):
2473 self._billable = v
2475 def getPrice(self):
2476 try:
2477 return self._price
2478 except:
2479 self._price = 0
2480 return self._price
2482 def setPrice(self, price):
2483 if price:
2484 match = PRICE_PATTERN.match(price)
2485 if match:
2486 price = match.group(1)
2487 else:
2488 raise MaKaCError(_('The price is in incorrect format!'))
2489 self._price = price
2491 def getPlacesLimit(self):
2492 try:
2493 if self._placesLimit:
2494 pass
2495 except AttributeError, e:
2496 self._placesLimit = 0
2497 return self._placesLimit
2499 def setPlacesLimit(self, limit):
2500 if limit == "":
2501 limit = "0"
2502 try:
2503 l = int(limit)
2504 except ValueError:
2505 raise FormValuesError(_("Please enter a number for the limit of places"))
2506 self._placesLimit = l
2507 self.updateCurrentNoPlaces()
2509 def getCurrentNoPlaces(self):
2510 try:
2511 if self._currentNoPlaces:
2512 pass
2513 except AttributeError:
2514 self._currentNoPlaces = 0
2515 return self._currentNoPlaces
2517 def hasAvailablePlaces(self):
2518 if not self.getPlacesLimit():
2519 return True
2520 return (self.getCurrentNoPlaces() < self.getPlacesLimit())
2522 def getNoPlacesLeft(self):
2523 return self.getPlacesLimit() - self.getCurrentNoPlaces()
2525 def increaseNoPlaces(self):
2526 if self.getPlacesLimit() > 0:
2527 if self.getCurrentNoPlaces() >= self.getPlacesLimit():
2528 raise FormValuesError(_("""The limit for the number of places is smaller than the current amount registered for this item."""))
2529 self._currentNoPlaces += 1
2531 def decreaseNoPlaces(self):
2532 if self.getPlacesLimit() > 0 and self.getCurrentNoPlaces() > 0:
2533 self._currentNoPlaces -= 1
2535 def updateCurrentNoPlaces(self):
2536 self._currentNoPlaces = 0
2538 if self._parent.getId() == '':
2539 # parent is not yet in the form
2540 return
2542 for reg in self._parent.getRegistrationForm().getConference().getRegistrantsList():
2543 mg = reg.getMiscellaneousGroupById(self._parent.getId())
2544 if mg:
2545 item = mg.getResponseItemById(self.getId())
2546 if item is not None and item.getQuantity():
2547 self.increaseNoPlaces()
2549 def getId(self):
2550 return self._id
2552 def setId(self, id):
2553 self._id = id
2555 def getCaption(self):
2556 return self._caption
2558 def setCaption(self, caption):
2559 self._caption = caption
2561 def getDescription(self):
2562 try:
2563 if self._description:
2564 pass
2565 except AttributeError:
2566 self._description = ''
2567 return self._description
2569 def setDescription(self, description):
2570 self._description = description
2572 def getInput(self):
2573 return self._input
2575 def setInput(self, input):
2576 self._input = input
2578 def isMandatory(self):
2579 return self._mandatory
2581 def setMandatory(self, v):
2582 self._mandatory = v
2584 def getLocked(self):
2585 try:
2586 return self._locked
2587 except:
2588 self._locked = ()
2589 return self._locked
2591 def isLocked(self, what):
2592 return what in self.getLocked()
2594 def setLocked(self, v):
2595 self._locked = v
2597 def isDisabled(self):
2598 try:
2599 return self._disabled
2600 except:
2601 self._disabled = False
2602 return self._disabled
2604 def setDisabled(self, v):
2605 self._disabled = v
2607 def getParent(self):
2608 return self._parent
2610 def getLocator(self):
2611 """Gives back (Locator) a globaly unique identification encapsulated in
2612 a Locator object for the GeneralField instance """
2613 if self.getParent() == None:
2614 return Locator()
2615 lconf = self.getParent().getLocator()
2616 lconf["sectionFieldId"] = self.getId()
2617 return lconf
2620 class GeneralSectionForm(BaseForm, Fossilizable):
2622 fossilizes(IRegFormGeneralSectionFossil)
2624 def __init__(self, regForm, data=None, required=False):
2625 BaseForm.__init__(self)
2626 self._regForm = regForm
2627 self._id = ""
2628 self._title = _("Miscellaneous information")
2629 self._description = ""
2630 self._required = required
2632 #####
2633 #Mods to support sorting fields
2634 #self._fields=[]
2636 self._sortedFields = []
2638 if data is not None:
2639 self._title = data.get("title", self._title)
2640 self._description = data.get("description", self._description)
2641 self._generalFieldGenerator = Counter()
2643 def setValues(self, data):
2644 title = data.get("title", "").strip()
2645 if title == "":
2646 title = _("Miscellaneous information %s") % self.getId()
2647 self.setTitle(title)
2648 self.setDescription(data.get("description", ""))
2649 if 'required' in data:
2650 self.setRequired(data['required'])
2652 def getValues(self):
2653 values = {}
2654 values["title"] = self.getTitle()
2655 values["description"] = self.getDescription()
2656 values["enabled"] = self.isEnabled()
2657 values["required"] = self.isRequired()
2658 return values
2660 def clone(self, regForm):
2661 gsf = GeneralSectionForm(regForm)
2662 gsf.setId(self.getId())
2663 gsf.setValues(self.getValues())
2664 gsf.setEnabled(self.isEnabled())
2665 gsf.setRequired(self.isRequired())
2667 #Mods to support sorting fields
2668 #for field in self.getFields():
2669 for field in self.getSortedFields():
2670 gsf.addToSortedFields(field.clone(gsf))
2671 return gsf
2673 def getRegistrationForm(self):
2674 return self._regForm
2676 def getConference(self):
2677 return self._regForm.getConference()
2679 def _getGeneralFieldGenerator(self):
2680 return self._generalFieldGenerator
2682 def getId(self):
2683 return self._id
2685 def setId(self, id):
2686 self._id = id
2688 def getTitle(self):
2689 return self._title
2691 def setTitle(self, title):
2692 self._title = title
2694 def getDescription(self):
2695 return self._description
2697 def setDescription(self, description):
2698 self._description = description
2700 def isRequired(self):
2701 try:
2702 return self._required
2703 except:
2704 self._required = False
2705 return False
2707 def setRequired(self, required):
2708 self._required = required
2710 def getSortedFields(self):
2711 try:
2712 returnFields = self._sortedFields
2713 except AttributeError:
2714 self._sortedFields = self._fields
2715 returnFields = self._sortedFields
2716 return returnFields
2718 def addToSortedFields(self, f, i=None):
2719 if i is None:
2720 i = len(self.getSortedFields())
2721 try:
2722 self.getSortedFields().remove(f)
2723 except ValueError, e:
2724 f.setId(str(self._getGeneralFieldGenerator().newCount()))
2725 self.getSortedFields().insert(i, f)
2726 self.notifyModification()
2727 return True
2729 def removeField(self, f):
2730 if f in self.getSortedFields():
2731 self.getSortedFields().remove(f)
2732 self.notifyModification()
2734 def getFieldById(self, id):
2735 for f in self.getSortedFields():
2736 if f.getId() == id:
2737 return f
2738 return None
2740 def getFieldPosById(self, id):
2741 for ind, f in enumerate(self.getSortedFields()):
2742 if f.getId() == id:
2743 return ind
2744 return None
2746 #end mods
2747 ##########
2749 def getLocator(self):
2750 """Gives back (Locator) a globaly unique identification encapsulated in
2751 a Locator object for the GeneralSectionForm instance """
2752 if self.getRegistrationForm().getConference() == None:
2753 return Locator()
2754 lconf = self.getRegistrationForm().getLocator()
2755 lconf["sectionFormId"] = self.getId()
2756 return lconf
2758 def notifyModification(self):
2759 self._p_changed = 1
2762 class PersonalDataForm(GeneralSectionForm):
2763 def __init__(self, regForm, createFields=True):
2764 GeneralSectionForm.__init__(self, regForm, {'title': 'Personal Data'}, True)
2766 fields = (
2767 { 'pd': 'title',
2768 'caption': 'Title',
2769 'input': 'radio',
2770 'inputValues': {
2771 'inputType':'dropdown',
2772 'emptyCaption': '',
2773 'radioitems': [{'caption':title} for title in TitlesRegistry.getList()]
2775 'lock': ('input', 'delete')
2777 { 'pd':'firstName', 'caption':'First Name', 'mandatory':True, 'lock':('mandatory', 'input', 'delete', 'disable') },
2778 { 'pd':'surname', 'caption':'Surname', 'mandatory':True, 'lock':('mandatory', 'input', 'delete', 'disable') },
2779 { 'pd':'position', 'caption':'Position', 'lock':('input', 'delete') },
2780 { 'pd':'institution', 'caption':'Institution', 'mandatory':True, 'lock':('input', 'delete') },
2781 { 'pd':'address', 'caption':'Address', 'lock':('input', 'delete') },
2782 { 'pd':'city', 'caption':'City', 'mandatory':True, 'lock':('input', 'delete') },
2783 { 'pd':'country', 'caption':'Country', 'input':'country', 'mandatory':True, 'lock':('input', 'delete') },
2784 { 'pd':'phone', 'caption':'Phone', 'input':'telephone', 'lock':('input', 'delete') },
2785 { 'pd':'fax', 'caption':'Fax', 'input':'telephone', 'lock':('input', 'delete') },
2786 { 'pd':'email', 'caption':'Email', 'mandatory':True, 'lock':('mandatory', 'input', 'delete', 'disable') },
2787 { 'pd':'personalHomepage', 'caption':'Personal homepage', 'lock':('input', 'delete') },
2790 self._pdMap = {}
2791 if createFields:
2792 for fieldInfo in fields:
2793 field = GeneralField(self, fieldInfo)
2794 self._pdMap[fieldInfo['pd']] = field
2795 self.addToSortedFields(field)
2797 def clone(self, regForm):
2798 pf = PersonalDataForm(regForm, False)
2799 pf.setId(self.getId())
2800 pf.setValues(self.getValues())
2801 pf.setEnabled(self.isEnabled())
2802 pf.setRequired(self.isRequired())
2803 for field in self.getSortedFields():
2804 f = field.clone(pf)
2805 pf.addToSortedFields(f)
2806 if f.getPDField():
2807 pf._pdMap[f.getPDField()] = f
2808 return pf
2810 def getValueFromParams(self, params, field):
2811 return params.get(self._pdMap[field].getInput().getHTMLName())
2813 def getField(self, field):
2814 return self._pdMap[field]
2816 def getRegistrantValues(self, registrant):
2817 mg = registrant.getMiscellaneousGroupById(self.getId())
2818 return dict((name, mg.getResponseItemById(field.getId()).getValue()) for name, field in self._pdMap.iteritems() if not field.isDisabled())
2820 def getValuesFromAvatar(self, av):
2821 r = dict((k, '') for k in ['title', 'firstName', 'surname', 'institution',
2822 'email', 'address', 'phone', 'fax'])
2823 if av is not None:
2824 r['title'] = av.getTitle()
2825 r['firstName'] = av.getFirstName()
2826 r['surname'] = av.getFamilyName()
2827 r['institution'] = av.getOrganisation()
2828 r['email'] = av.getEmail()
2829 r['address'] = av.getAddress()
2830 r['phone'] = av.getTelephone()
2831 return r
2833 def getFormValuesFromAvatar(self, av):
2834 r = {}
2836 if av is not None:
2837 r[self._pdMap['title'].getInput().getHTMLName()] = av.getTitle()
2838 r[self._pdMap['firstName'].getInput().getHTMLName()] = av.getFirstName()
2839 r[self._pdMap['surname'].getInput().getHTMLName()] = av.getFamilyName()
2840 r[self._pdMap['institution'].getInput().getHTMLName()] = av.getOrganisation()
2841 r[self._pdMap['email'].getInput().getHTMLName()] = av.getEmail()
2842 r[self._pdMap['address'].getInput().getHTMLName()] = av.getAddress()
2843 r[self._pdMap['phone'].getInput().getHTMLName()] = av.getTelephone()
2844 return r
2848 class PersonalDataFormItem(Persistent): # old
2850 def __init__(self, data=None):
2851 if data is None:
2852 self._id = ""
2853 self._name = ""
2854 self._input = ""
2855 self._mandatory = False
2856 self._enabled = True
2857 else:
2858 self._id = data.get("id", "")
2859 self._name = data.get("name", "")
2860 self._input = data.get("input", "")
2861 self._mandatory = data.get("mandatory", False)
2862 self._enabled = data.get("enabled", True)
2864 def getId(self):
2865 return self._id
2867 def setId(self, id):
2868 self._id = id
2870 def getName(self):
2871 return self._name
2873 def setName(self, name):
2874 self._name = name
2876 def isEnabled(self):
2877 try:
2878 return self._enabled
2879 except:
2880 self.setEnabled()
2881 return self._enabled
2883 def setEnabled(self, enabled=True):
2884 self._enabled = enabled
2885 self._p_changed = 1
2887 def getInput(self):
2888 return self._input
2890 def setInput(self, input):
2891 self._input = input
2893 def isMandatory(self):
2894 return self._mandatory
2896 def setMandatory(self, v):
2897 self._mandatory = v
2898 self._p_changed = 1
2901 class PersonalData(Persistent):
2903 def __init__(self):
2904 self._initStandardPersonalData()
2906 def _initStandardPersonalData(self):
2907 self._data = PersistentMapping()
2908 self._sortedKeys = PersistentList()
2909 p = PersonalDataFormItem({'id':'title', 'name': "Title", 'input':'list', 'mandatory':False})
2910 self._data[p.getId()] = p
2911 self._sortedKeys.append(p.getId())
2912 p = PersonalDataFormItem({'id':'firstName', 'name': "First Name", 'input':'text', 'mandatory':True})
2913 self._data[p.getId()] = p
2914 self._sortedKeys.append(p.getId())
2915 p = PersonalDataFormItem({'id':'surname', 'name': "Surname", 'input':'text', 'mandatory':True})
2916 self._data[p.getId()] = p
2917 self._sortedKeys.append(p.getId())
2918 p = PersonalDataFormItem({'id':'position', 'name': "Position", 'input':'text', 'mandatory':False})
2919 self._data[p.getId()] = p
2920 self._sortedKeys.append(p.getId())
2921 p = PersonalDataFormItem({'id':'institution', 'name': "Institution", 'input':'text', 'mandatory':True})
2922 self._data[p.getId()] = p
2923 self._sortedKeys.append(p.getId())
2924 p = PersonalDataFormItem({'id':'address', 'name': "Address", 'input':'text', 'mandatory':False})
2925 self._data[p.getId()] = p
2926 self._sortedKeys.append(p.getId())
2927 p = PersonalDataFormItem({'id':'city', 'name': "City", 'input':'text', 'mandatory':True})
2928 self._data[p.getId()] = p
2929 self._sortedKeys.append(p.getId())
2930 p = PersonalDataFormItem({'id':'country', 'name': "Country/Region", 'input':'list', 'mandatory':True})
2931 self._data[p.getId()] = p
2932 self._sortedKeys.append(p.getId())
2933 p = PersonalDataFormItem({'id':'phone', 'name': "Phone", 'input':'text', 'mandatory':False})
2934 self._data[p.getId()] = p
2935 self._sortedKeys.append(p.getId())
2936 p = PersonalDataFormItem({'id':'fax', 'name': "Fax", 'input':'text', 'mandatory':False})
2937 self._data[p.getId()] = p
2938 self._sortedKeys.append(p.getId())
2939 p = PersonalDataFormItem({'id':'email', 'name': "Email", 'input':'hidden', 'mandatory':True})
2940 self._data[p.getId()] = p
2941 self._sortedKeys.append(p.getId())
2942 p = PersonalDataFormItem({'id':'personalHomepage', 'name': "Personal homepage", 'input':'text', 'mandatory':False})
2943 self._data[p.getId()] = p
2944 self._sortedKeys.append(p.getId())
2946 def clone(self):
2947 form = PersonalData()
2948 for key, item in self._data.iteritems():
2949 newItem = form.getDataItem(key)
2950 newItem.setEnabled(item.isEnabled())
2951 newItem.setMandatory(item.isMandatory())
2952 return form
2954 def getData(self):
2955 return self._data
2957 def getSortedKeys(self):
2958 return self._sortedKeys
2960 def getMandatoryItems(self):
2961 r = []
2962 for i in self.getSortedKeys():
2963 if self.getData()[i].isMandatory() and self.getData()[i].isEnabled():
2964 r.append(i)
2965 return r
2967 def getDataItem(self, key):
2968 return self._data.get(key, None)
2971 class FurtherInformationForm(BaseForm, Fossilizable):
2973 fossilizes(IRegFormFurtherInformationSectionFossil)
2975 def __init__(self, data=None):
2976 BaseForm.__init__(self)
2977 self._title = "Further information"
2978 self._content = ""
2979 if data is not None:
2980 self._title = data.get("title", self._title)
2981 self._content = data.get("content", self._content)
2982 self._id = "furtherInformation"
2984 def getId(self):
2985 try:
2986 if self._id:
2987 pass
2988 except AttributeError, e:
2989 self._id = "furtherInformation"
2990 return self._id
2992 def setValues(self, data):
2993 self.setTitle(data.get("title", "Further Information"))
2994 self.setContent(data.get("content", ""))
2996 def getValues(self):
2997 values = {}
2998 values["title"] = self.getTitle()
2999 values["content"] = self.getContent()
3000 values["enabled"] = self.isEnabled()
3001 return values
3003 def clone(self):
3004 fif = FurtherInformationForm()
3005 fif.setValues(self.getValues())
3006 fif.setEnabled(self.isEnabled())
3007 return fif
3009 def getTitle(self):
3010 return self._title
3012 def setTitle(self, title):
3013 self._title = title
3015 def getContent(self):
3016 return self._content
3018 def setContent(self, content):
3019 self._content = content
3021 # Fallback for setDescription
3022 setDescription = setContent
3024 def getItems(self):
3025 return ""
3028 class AccommodationType(Persistent, Fossilizable):
3030 fossilizes(IRegFormAccommodationTypeItemFossil)
3032 def __init__(self, rf, data=None):
3033 self._id = ""
3034 self._caption = ""
3035 self._regForm = rf
3036 self._cancelled = False
3037 self._placesLimit = 0
3038 self._currentNoPlaces = 0
3039 self._billable = False
3040 self._price = 0
3042 def setValues(self, data):
3043 self.setCaption(data.get("caption", "--no caption--"))
3044 self.setCancelled(data.has_key("cancelled") and data["cancelled"])
3045 self.setPlacesLimit(data.get("placesLimit", "0"))
3046 self.setBillable(data.has_key("billable") and data["billable"])
3047 self.setPrice(data.get("price"))
3048 self._regForm.notifyModification()
3050 def getValues(self):
3051 values = {}
3052 values["caption"] = self.getCaption()
3053 if self.isCancelled():
3054 values["cancelled"] = self.isCancelled()
3055 values["placesLimit"] = self.getPlacesLimit()
3056 if self.isBillable():
3057 values["billable"] = True
3058 values["price"] = self.getPrice()
3060 return values
3062 def clone(self, registrationForm):
3063 act = AccommodationType(registrationForm)
3064 act.setValues(self.getValues())
3065 return act
3067 def getId(self):
3068 return self._id
3070 def setId(self, id):
3071 self._id = id
3073 def getCaption(self):
3074 return self._caption
3076 def setCaption(self, c):
3077 self._caption = c
3079 def getPlacesLimit(self):
3080 try:
3081 if self._placesLimit:
3082 pass
3083 except AttributeError, e:
3084 self._placesLimit = 0
3085 return self._placesLimit
3087 def setPlacesLimit(self, limit):
3088 if limit == "":
3089 limit = "0"
3090 try:
3091 l = int(limit)
3092 except ValueError, e:
3093 raise FormValuesError(_("Please introduce a number for the limit of places"))
3094 self._placesLimit = l
3095 self.updateCurrentNoPlaces()
3097 def getCurrentNoPlaces(self):
3098 try:
3099 if self._currentNoPlaces:
3100 pass
3101 except AttributeError, e:
3102 self._currentNoPlaces = 0
3103 return self._currentNoPlaces
3105 def hasAvailablePlaces(self):
3106 if self.getPlacesLimit() == 0: #zero means no limit
3107 return True
3108 if self.getCurrentNoPlaces() >= self.getPlacesLimit():
3109 return False
3110 return True
3112 def getNoPlacesLeft(self):
3113 return self.getPlacesLimit() - self.getCurrentNoPlaces()
3115 def increaseNoPlaces(self):
3116 if self.getPlacesLimit() > 0 :
3117 if self.getCurrentNoPlaces() >= self.getPlacesLimit():
3118 raise FormValuesError(_("""The limit for the number of places is smaller than the current amount registered for this accommodation. Please, set a higher limit."""))
3119 self._currentNoPlaces += 1
3121 def decreaseNoPlaces(self):
3122 if self.getPlacesLimit() > 0 and self.getCurrentNoPlaces() > 0:
3123 self._currentNoPlaces -= 1
3125 def updateCurrentNoPlaces(self):
3126 self._currentNoPlaces = 0
3127 for reg in self._regForm.getConference().getRegistrantsList():
3128 acco = reg.getAccommodation()
3129 if acco is not None:
3130 accoType = acco.getAccommodationType()
3131 if accoType is not None and accoType == self:
3132 self.increaseNoPlaces()
3134 def getRegistrationForm(self):
3135 return self._regForm
3137 def setRegistrationForm(self, rf):
3138 self._regForm = rf
3140 def isCancelled(self):
3141 try:
3142 if self._cancelled:
3143 pass
3144 except AttributeError, e:
3145 self._cancelled = False
3146 return self._cancelled
3148 def setCancelled(self, v):
3149 self._cancelled = v
3151 def isBillable(self):
3152 try:
3153 return self._billable
3154 except:
3155 self._billable = False
3156 return self._billable
3158 def setBillable(self, v):
3159 self._billable = v
3161 def getPrice(self):
3162 try:
3163 return self._price
3164 except:
3165 self.setPrice(0)
3166 return self._price
3168 def setPrice(self, price):
3169 if price:
3170 match = PRICE_PATTERN.match(price)
3171 if match:
3172 price = match.group(1)
3173 else:
3174 raise MaKaCError(_('The price is in incorrect format!'))
3175 self._price = price
3177 def getCurrency(self):
3178 return self._regForm.getCurrency()
3180 def remove(self):
3181 self.setCancelled(True)
3182 self.delete()
3184 def delete(self):
3185 self.setRegistrationForm(None)
3186 TrashCanManager().add(self)
3188 def recover(self, rf):
3189 self.setRegistrationForm(rf)
3190 TrashCanManager().remove(self)
3192 def getLocator(self):
3193 """Gives back (Locator) a globaly unique identification encapsulated in
3194 a Locator object for the AccommodationType instance """
3195 if self.getRegistrationForm().getConference() is None:
3196 return Locator()
3197 lconf = self.getRegistrationForm().getLocator()
3198 lconf["accoTypeId"] = self.getId()
3199 return lconf
3202 class AccommodationForm(BaseForm, Fossilizable):
3204 fossilizes(IRegFormAccommodationSectionFossil)
3206 _iterableContainer = '_accommodationTypes'
3208 def __init__(self, regForm, data=None):
3209 BaseForm.__init__(self)
3210 self._accoTypeGenerator = Counter()
3211 self._regForm = regForm
3212 self._title = "Accommodation"
3213 self._description = ""
3214 self._accommodationTypes = PersistentMapping()
3215 if data is not None:
3216 self._title = data.get("title", self._title)
3217 self._description = data.get("description", self._description)
3218 self._setDefaultAccommodationTypes()
3219 self._id = "accommodation"
3220 self._arrivalOffsetDates = [-2, 0]
3221 self._departureOffsetDates = [1, 3]
3223 def getId(self):
3224 try:
3225 if self._id:
3226 pass
3227 except AttributeError, e:
3228 self._id = "accommodation"
3229 return self._id
3231 def getConference(self):
3232 return self._regForm.getConference()
3234 def getArrivalOffsetDates(self):
3235 try:
3236 return self._arrivalOffsetDates
3237 except:
3238 self.setDefaultArrivalOffsetDates()
3239 return self._arrivalOffsetDates
3241 def setDefaultArrivalOffsetDates(self):
3242 self._arrivalOffsetDates = [-2, 0]
3244 def getArrivalDates(self):
3245 offsets = self.getArrivalOffsetDates()
3246 conf = self.getConference()
3247 dates = []
3248 curDate = startDate = conf.getStartDate() + timedelta(days=offsets[0])
3249 endDate = conf.getEndDate() + timedelta(days=offsets[1])
3250 if startDate.date() > endDate.date():
3251 endDate = startDate
3252 while curDate.date() <= endDate.date():
3253 dates.append(curDate)
3254 curDate += timedelta(days=1)
3255 return dates
3257 def setArrivalOffsetDates(self, dates):
3258 self._arrivalOffsetDates = dates
3260 def getDepartureOffsetDates(self):
3261 try:
3262 return self._departureOffsetDates
3263 except:
3264 self.setDefaultDepartureOffsetDates()
3265 return self._departureOffsetDates
3267 def setDefaultDepartureOffsetDates(self):
3268 self._departureOffsetDates = [1, 3]
3270 def getDepartureDates(self):
3271 offsets = self.getDepartureOffsetDates()
3272 conf = self.getConference()
3273 dates = []
3274 curDate = startDate = conf.getStartDate() + timedelta(days=offsets[0])
3275 endDate = conf.getEndDate() + timedelta(days=offsets[1])
3276 if startDate > endDate:
3277 endDate = startDate
3278 while curDate <= endDate:
3279 dates.append(curDate)
3280 curDate += timedelta(days=1)
3281 return dates
3283 def setDepartureOffsetDates(self, dates):
3284 self._departureOffsetDates = dates
3286 def _setDefaultAccommodationTypes(self):
3287 a = AccommodationType(self._regForm)
3288 a.setId("cern")
3289 a.setCaption("CERN Hostel")
3290 self._accommodationTypes[a.getId()] = a
3291 a = AccommodationType(self._regForm)
3292 a.setId("own-accommodation")
3293 a.setCaption("I will arrange my own accommodation")
3294 self._accommodationTypes[a.getId()] = a
3295 a = AccommodationType(self._regForm)
3296 a.setId("geneva-hotel")
3297 a.setCaption("I prefer to book a room in a Geneva hotel")
3298 self._accommodationTypes[a.getId()] = a
3300 def setValues(self, data):
3301 self.setTitle(data.get("title", "Accommodation"))
3302 self.setDescription(data.get("description", ""))
3303 self.setArrivalOffsetDates([int(data.get("aoffset1", -2)), int(data.get("aoffset2", 0))])
3304 self.setDepartureOffsetDates([int(data.get("doffset1", 1)), int(data.get("doffset2", 3))])
3306 def getValues(self):
3307 values = {}
3308 values["title"] = self.getTitle()
3309 values["description"] = self.getDescription()
3310 values["enabled"] = self.isEnabled()
3311 values["aoffset1"] = self.getArrivalOffsetDates()[0]
3312 values["aoffset2"] = self.getArrivalOffsetDates()[1]
3313 values["doffset1"] = self.getDepartureOffsetDates()[0]
3314 values["doffset2"] = self.getDepartureOffsetDates()[1]
3315 return values
3317 def clone(self, registrationForm):
3318 acf = AccommodationForm(registrationForm)
3319 acf.setValues(self.getValues())
3320 acf.setEnabled(self.isEnabled())
3321 acf._accommodationTypes = PersistentMapping()
3322 for at in self.getAccommodationTypesList() :
3323 acf.addAccommodationType(at.clone(registrationForm))
3324 return acf
3326 def getTitle(self):
3327 return self._title
3329 def setTitle(self, title):
3330 self._title = title
3332 def getDescription(self):
3333 return self._description
3335 def setDescription(self, description):
3336 self._description = description
3338 def getRegistrationForm(self):
3339 return self._regForm
3341 def _generateNewAccoTypeId(self):
3342 """Returns a new unique identifier for the current registration form
3344 try:
3345 return str(self._accoTypeGenerator.newCount())
3346 except:
3347 self._accoTypeGenerator = Counter()
3348 return str(self._accoTypeGenerator.newCount())
3350 def addAccommodationType(self, accom):
3351 id = accom.getId()
3352 if id == "":
3353 id = self._generateNewAccoTypeId()
3354 accom.setId(id)
3355 self._accommodationTypes[id] = accom
3357 def removeAccommodationType(self, accom):
3358 accom.remove()
3359 if self._accommodationTypes.has_key(accom.getId().strip()):
3360 del(self._accommodationTypes[accom.getId().strip()])
3362 def recoverAccommodationType(self, accom):
3363 self.addAccommodationType(accom)
3364 accom.recover(self.getRegistrationForm())
3366 def getAccommodationTypeById(self, id):
3367 if self._accommodationTypes.has_key(id.strip()):
3368 return self._accommodationTypes[id]
3369 return None
3371 def getAccommodationTypesList(self):
3372 return self._accommodationTypes.values()
3374 def clearAccommodationTypesList(self):
3375 for at in self.getAccommodationTypesList():
3376 self.removeAccommodationType(at)
3379 class ReasonParticipationForm(BaseForm, Fossilizable):
3381 fossilizes(IRegFormReasonParticipationSectionFossil)
3383 def __init__(self, data=None):
3384 BaseForm.__init__(self)
3385 self._title = "Reason for participation"
3386 self._description = "Please, let us know why you are interested to participate in our event:"
3387 if data is not None:
3388 self._title = data.get("title", self._title)
3389 self._description = data.get("description", self._description)
3390 self._id = "reasonParticipation"
3392 def getId(self):
3393 try:
3394 if self._id:
3395 pass
3396 except AttributeError, e:
3397 self._id = "reasonParticipation"
3398 return self._id
3400 def setValues(self, data):
3401 self.setTitle(data.get("title", "Reason for participation"))
3402 self.setDescription(data.get("description", ""))
3404 def getValues(self):
3405 values = {}
3406 values["title"] = self.getTitle()
3407 values["description"] = self.getDescription()
3408 return values
3410 def clone(self):
3411 rpf = ReasonParticipationForm()
3412 rpf.setValues(self.getValues())
3413 rpf.setEnabled(self.isEnabled())
3414 return rpf
3416 def getTitle(self):
3417 return self._title
3419 def setTitle(self, title):
3420 self._title = title
3422 def getDescription(self):
3423 return self._description
3425 def setDescription(self, description):
3426 self._description = description
3428 def getItems(self):
3429 #No items for this form
3430 return ""
3433 class RegistrationSession(Persistent, Fossilizable):
3435 fossilizes(IRegFormRegistrationSessionItemFossil)
3437 def __init__(self, ses, regForm=None):
3438 self._session = ses
3439 self._session.setRegistrationSession(self)
3440 self._regForm = regForm
3441 self._price = 0
3442 self._billable = False
3443 self._currency = regForm.getCurrency()
3445 def setValues(self, data):
3446 self.setBillable(data.has_key("billable") and data["billable"])
3447 self.setPrice(data.get("price"))
3449 def getValues(self):
3450 data = {}
3451 if self.isBillable():
3452 data["billable"] = True
3453 data["price"] = self.getPrice()
3454 return data
3456 def getSession(self):
3457 return self._session
3459 def setSession(self, ses):
3460 self._session = ses
3461 self._billable = ses.isBillable()
3462 self._price = ses.getPrice()
3464 def getRegistrationForm(self):
3465 return self._regForm
3467 def setRegistrationForm(self, rf):
3468 self._regForm = rf
3470 def getParent(self):
3471 # The parent of registration session is "session form"
3472 if self._regForm is not None:
3473 return self._regForm.getSessionsForm()
3474 return None
3476 def getConference(self):
3477 if self._regForm is not None:
3478 return self._regForm.getConference()
3479 return None
3481 def remove(self):
3482 #self._session.setRegistrationSession(None)
3483 self.setRegistrationForm(None)
3484 pass
3486 def isCancelled(self):
3487 ## return self._session is None or not self.getParent().hasSession(self.getId())
3488 ## return not self.getParent().hasSession(self.getId())
3489 return not self.getRegistrationForm()
3491 def getId(self):
3492 return self._session.getId()
3494 def getTitle(self):
3495 return self._session.getTitle()
3497 # for compatibility with other fields
3498 getCaption = getTitle
3500 def getStartDate(self):
3501 return self._session.getStartDate()
3503 def getCode(self):
3504 return self._session.getCode()
3506 def getPrice(self):
3507 try:
3508 return self._price
3509 except:
3510 self.setPrice(0)
3511 return self._price
3513 def setPrice(self, price):
3514 if price:
3515 match = PRICE_PATTERN.match(price)
3516 if match:
3517 price = match.group(1)
3518 else:
3519 raise MaKaCError(_('The price is in incorrect format!'))
3520 self._price = price
3522 def isBillable(self):
3523 try:
3524 return self._billable
3525 except:
3526 self._billable = False
3527 return self._billable
3529 def setBillable(self, v):
3530 self._billable = v
3532 def getCurrency(self):
3533 if not hasattr(self, "_currency") or not self._currency:
3534 # it may happen that _regForm doesn't exist (session was removed from it)
3535 if self._regForm:
3536 self._currency = self._regForm.getCurrency()
3537 else:
3538 self._currency = None
3539 return self._currency
3541 def getLocator(self):
3542 """Gives back (Locator) a globaly unique identification encapsulated in
3543 a Locator object for the RegistrationSession instance """
3544 if self.getRegistrationForm().getConference() == None:
3545 return Locator()
3546 lconf = self.getRegistrationForm().getLocator()
3547 lconf["sessionId"] = self.getId()
3548 return lconf
3550 @staticmethod
3551 def _cmpTitle(s1, s2):
3552 if s1 is None and s2 is not None:
3553 return -1
3554 elif s1 is not None and s2 is None:
3555 return 1
3556 elif s1 is None and s2 is None:
3557 return 0
3558 return cmp(s1.getTitle(), s2.getTitle())
3561 class SessionsForm(BaseForm, Fossilizable):
3563 fossilizes(IRegFormSessionSectionFossil)
3565 _iterableContainer = '_sessions'
3567 def __init__(self, data=None):
3568 BaseForm.__init__(self)
3569 self._title = "Sessions"
3570 self._type = "2priorities"
3571 self._description = ""
3572 self._sessions = PersistentMapping()
3573 if data is not None:
3574 self._title = data.get("title", self._title)
3575 self._description = data.get("description", self._description)
3576 self._sessions = data.get("sessions", self._sessions)
3577 self._id = "sessions"
3579 def getId(self):
3580 try:
3581 if self._id:
3582 pass
3583 except AttributeError, e:
3584 self._id = "sessions"
3585 return self._id
3587 def clone(self, newSessions):
3588 sesf = SessionsForm()
3589 sesf.setTitle(self.getTitle())
3590 sesf.setType(self.getType())
3591 sesf.setDescription(self.getDescription())
3592 sesf.setEnabled(self.isEnabled())
3593 for s in newSessions:
3594 ses = self.getSessionById(s.getId())
3595 if ses:
3596 s.setValues(ses.getValues())
3597 sesf.addSession(s)
3599 return sesf
3601 def getValues(self):
3602 data = {}
3603 data["title"] = self.getTitle()
3604 data["description"] = self.getDescription()
3605 data["enabled"] = self.isEnabled()
3606 data["type"] = self.getType()
3607 return data
3609 def setValues(self, data):
3610 self.setTitle(data.get("title", "Sessions"))
3611 self.setDescription(data.get("description", ""))
3612 self.setType(data.get("sessionFormType", "2priorities"))
3614 def getTitle(self):
3615 return self._title
3617 def setTitle(self, title):
3618 self._title = title
3620 def getDescription(self):
3621 return self._description
3623 def setDescription(self, description):
3624 self._description = description
3626 def getType(self):
3627 try:
3628 if self._type:
3629 pass
3630 except AttributeError, e:
3631 self._type = "2priorities"
3632 return self._type
3634 def setType(self, type):
3635 self._type = type
3637 def getSessionsFromParams(self, params):
3638 sessions = []
3639 if self.isEnabled():
3640 if self.getType() == "2priorities":
3641 if params.get("session1", "nosession") == "nosession":
3642 raise FormValuesError(_("Please, choose at least one session in order to register"))
3643 if params.get("session1", "") == params.get("session2", "nosession"):
3644 raise FormValuesError(_("You cannot choose the same session twice"))
3645 sessions.append(self.getSessionById(params.get("session1")))
3646 ses2 = self.getSessionById(params.get("session2", "nosession"))
3647 if ses2 is not None:
3648 sessions.append(ses2)
3649 elif self.getType() == "all":
3650 sess = params.get("sessions", [])
3651 if type(sess) != list:
3652 sess = [sess]
3653 for ses in sess:
3654 if self.hasSession(ses):
3655 sessions.append(self.getSessionById(ses))
3656 return [RegistrantSession(ses) for ses in sessions]
3658 def getSessionList(self, doSort=False):
3659 lv = self._sessions.values()
3660 lv.sort(sortByStartDate)
3661 if doSort:
3662 lv.sort(RegistrationSession._cmpTitle)
3663 return lv
3665 def getSessions(self):
3666 return self._sessions
3668 def addSession(self, ses):
3669 if not self._sessions.has_key(ses.getId()):
3670 self._sessions[ses.getId()] = ses
3672 def removeSession(self, sesId):
3673 if self._sessions.has_key(sesId):
3674 self._sessions[sesId].remove()
3675 del self._sessions[sesId]
3677 def clearSessionList(self):
3678 for s in self.getSessionList():
3679 self.removeSession(s)
3681 def hasSession(self, key):
3682 return self._sessions.has_key(key)
3684 def getSessionById(self, id):
3685 return self._sessions.get(id, None)
3688 def sortByStartDate(x, y):
3689 return cmp(x.getSession().getStartDate(), y.getSession().getStartDate())
3692 class SocialEventItem(Persistent, Fossilizable):
3694 fossilizes(IRegFormSocialEventItemFossil)
3696 def __init__(self, rf, data=None):
3697 self._id = ""
3698 self._caption = "--no caption--"
3699 self._regForm = rf
3700 self._cancelled = False
3701 self._cancelledReason = ""
3702 self._maxPlacePerRegistrant = 10
3703 self._placesLimit = 0
3704 self._currentNoPlaces = 0
3705 self._billable = False
3706 self._price = 0
3707 self._pricePerPlace = False
3709 def setValues(self, data):
3710 if "caption" in data:
3711 self.setCaption(data["caption"])
3712 if "cancelled" in data:
3713 self.setCancelled(data["cancelled"])
3714 if "cancelledReason" in data:
3715 self.setCancelledReason(data["cancelledReason"])
3716 if "maxPlace" in data:
3717 try:
3718 maxPlace = int(data["maxPlace"])
3719 except ValueError:
3720 maxPlace = 0
3721 if maxPlace < 0:
3722 maxPlace = 0
3723 self.setMaxPlacePerRegistrant(maxPlace)
3724 if "placesLimit" in data:
3725 self.setPlacesLimit(data["placesLimit"])
3726 if "billable" in data:
3727 self.setBillable(data["billable"])
3728 if "billable" in data:
3729 self.setPricePerPlace(data["pricePerPlace"])
3730 if "price" in data:
3731 self.setPrice(data["price"])
3733 def getValues(self):
3734 data = {}
3735 data["caption"] = self.getCaption()
3736 if self.isCancelled():
3737 data["cancelled"] = self.isCancelled()
3738 data["cancelledReason"] = self.getCancelledReason()
3739 data["maxPlace"] = self.getMaxPlacePerRegistrant()
3740 data["placesLimit"] = self.getPlacesLimit()
3741 if self.isBillable():
3742 data["billable"] = True
3743 if self.isPricePerPlace():
3744 data["pricePerPlace"] = True
3745 data["price"] = self.getPrice()
3746 return data
3748 def clone(self, regForm):
3749 newSEI = SocialEventItem(regForm)
3750 newSEI.setValues(self.getValues())
3751 return newSEI
3753 def getId(self):
3754 return self._id
3756 def setId(self, id):
3757 self._id = id
3759 def getCaption(self):
3760 return self._caption
3762 def setCaption(self, c):
3763 self._caption = c
3765 def getPlacesLimit(self):
3766 try:
3767 if self._placesLimit:
3768 pass
3769 except AttributeError, e:
3770 self._placesLimit = 0
3771 return self._placesLimit
3773 def setPlacesLimit(self, limit):
3774 if limit == "":
3775 limit = "0"
3776 try:
3777 l = int(limit)
3778 except ValueError, e:
3779 raise FormValuesError(_("Please introduce a number for the limit of places"))
3780 self._placesLimit = l
3781 self.updateCurrentNoPlaces()
3783 def getCurrentNoPlaces(self):
3784 try:
3785 if self._currentNoPlaces:
3786 pass
3787 except AttributeError, e:
3788 self._currentNoPlaces = 0
3789 return self._currentNoPlaces
3791 def hasAvailablePlaces(self):
3792 if self.getCurrentNoPlaces() >= self.getPlacesLimit():
3793 return False
3794 return True
3796 def getNoPlacesLeft(self):
3797 return self.getPlacesLimit() - self.getCurrentNoPlaces()
3799 def increaseNoPlaces(self, n):
3800 if self.getPlacesLimit() > 0 :
3801 if (self.getCurrentNoPlaces() + n) > self.getPlacesLimit():
3802 raise FormValuesError(_("We are sorry but there are not enough places for the social event \"%s\". \
3803 ") % (self.getCaption()))
3804 self._currentNoPlaces += n
3806 def decreaseNoPlaces(self, n):
3807 if self.getPlacesLimit() > 0 and self.getCurrentNoPlaces() > 0:
3808 if (self._currentNoPlaces - n) < 0:
3809 raise FormValuesError(_("Impossible to decrease %s places for \"%s\" because the current number of \
3810 places would be less than zero") % (n, self.getCaption()))
3811 self._currentNoPlaces -= n
3813 def updateCurrentNoPlaces(self):
3814 self._currentNoPlaces = 0
3815 for reg in self._regForm.getConference().getRegistrantsList():
3816 for se in reg.getSocialEvents():
3817 if se.getSocialEventItem() == self:
3818 self.increaseNoPlaces(se.getNoPlaces())
3820 def getRegistrationForm(self):
3821 return self._regForm
3823 def setRegistrationForm(self, rf):
3824 self._regForm = rf
3826 def isCancelled(self):
3827 try:
3828 if self._cancelled:
3829 pass
3830 except AttributeError, e:
3831 self._cancelled = False
3832 return self._cancelled
3834 def setCancelled(self, v):
3835 self._cancelled = v
3837 def getCancelledReason(self):
3838 try:
3839 if self._cancelledReason:
3840 pass
3841 except AttributeError:
3842 self._cancelledReason = ""
3843 return self._cancelledReason
3845 def setCancelledReason(self, cr):
3846 self._cancelledReason = cr
3848 def getMaxPlacePerRegistrant(self):
3849 try:
3850 return self._maxPlacePerRegistrant
3851 except AttributeError:
3852 self._maxPlacePerRegistrant = 9
3853 return self._maxPlacePerRegistrant
3855 def setMaxPlacePerRegistrant(self, numPlace):
3856 self._maxPlacePerRegistrant = numPlace
3858 def isBillable(self):
3859 try:
3860 return self._billable
3861 except:
3862 self._billable = False
3863 return self._billable
3865 def setBillable(self, v):
3866 self._billable = v
3868 def isPricePerPlace(self):
3869 try:
3870 return self._pricePerPlace
3871 except:
3872 self._pricePerPlace = False
3873 return self._pricePerPlace
3875 def setPricePerPlace(self, v):
3876 self._pricePerPlace = v
3878 def getPrice(self):
3879 try:
3880 return self._price
3881 except:
3882 self.setPrice(0)
3883 return self._price
3885 def setPrice(self, price):
3886 if price:
3887 match = PRICE_PATTERN.match(price)
3888 if match:
3889 price = match.group(1)
3890 else:
3891 raise MaKaCError(_('The price is in incorrect format!'))
3892 self._price = price
3894 def getCurrency(self):
3895 return self._regForm.getCurrency()
3897 def remove(self):
3898 self.setCancelled(True)
3899 self.delete()
3901 def delete(self):
3902 self.setRegistrationForm(None)
3903 TrashCanManager().add(self)
3905 def recover(self, rf):
3906 self.setRegistrationForm(rf)
3907 TrashCanManager().remove(self)
3909 def getLocator(self):
3910 """Gives back (Locator) a globaly unique identification encapsulated in
3911 a Locator object for the SocialEventItem instance """
3912 if self.getRegistrationForm().getConference() == None:
3913 return Locator()
3914 lconf = self.getRegistrationForm().getLocator()
3915 lconf["socialEventId"] = self.getId()
3916 return lconf
3918 @staticmethod
3919 def _cmpCaption(se1, se2):
3920 return cmp(se1.getCaption().lower(), se2.getCaption().lower())
3923 class SocialEventForm(BaseForm, Fossilizable):
3925 fossilizes(IRegFormSocialEventSectionFossil)
3927 _iterableContainer = '_socialEvents'
3929 def __init__(self, regForm, data=None):
3930 BaseForm.__init__(self)
3931 self._socialEventItemGenerator = Counter()
3932 self._regForm = regForm
3933 self._title = "Social Events"
3934 self._description = ""
3935 self._introSentence = self._getDefaultIntroValue()
3936 self._mandatory = False
3937 self._selectionType = "multiple"
3938 self._socialEvents = PersistentMapping()
3939 if data is not None:
3940 self._title = data.get("title", self._title)
3941 self._description = data.get("description", self._description)
3942 self._mandatory = data.get('mandatory', False)
3943 self._id = "socialEvents"
3945 def getId(self):
3946 try:
3947 if self._id:
3948 pass
3949 except AttributeError, e:
3950 self._id = "socialEvents"
3951 return self._id
3953 def setValues(self, data):
3954 self.setTitle(data.get("title", "Sessions"))
3955 self.setDescription(data.get("description", ""))
3956 self.setIntroSentence(data.get("intro", ""))
3957 self.setSelectionType(data.get("selectionType", "multiple"))
3958 self.setMandatory(data.get('mandatory', False))
3960 def getValues(self):
3961 values = {}
3962 values["title"] = self.getTitle()
3963 values["description"] = self.getDescription()
3964 values["intro"] = self.getIntroSentence()
3965 values["selectionType"] = self.getSelectionTypeId()
3966 values["mandatory"] = self.getMandatory()
3967 return values
3969 def clone(self, registrationForm):
3970 sef = SocialEventForm(registrationForm)
3971 sef.setValues(self.getValues())
3972 sef.setEnabled(self.isEnabled())
3974 for se in self.getSocialEventList():
3975 sef.addSocialEvent(se.clone(registrationForm))
3976 return sef
3978 def getTitle(self):
3979 return self._title
3981 def setTitle(self, title):
3982 self._title = title
3984 def getDescription(self):
3985 return self._description
3987 def setDescription(self, description):
3988 self._description = description
3990 def getMandatory(self):
3991 try:
3992 return self._mandatory
3993 except AttributeError:
3994 self._mandatory = False
3995 return False
3997 def setMandatory(self, value):
3998 self._mandatory = value
4000 def getRegistrationForm(self):
4001 try:
4002 if self._regForm:
4003 pass
4004 except AttributeError, e:
4005 self._regForm = None
4006 return self._regForm
4008 def getConference(self):
4009 if self.getRegistrationForm() is not None:
4010 return self.getRegistrationForm().getConference()
4011 return None
4013 def _getDefaultIntroValue(self):
4014 return "Select the social events you would like to attend and how many places you will need"
4016 def getIntroSentence(self):
4017 try:
4018 if self._introSentence:
4019 pass
4020 except AttributeError, e:
4021 self._introSentence = self._getDefaultIntroValue()
4022 return self._introSentence
4024 def setIntroSentence(self, intro):
4025 self._introSentence = intro
4027 def getSelectionTypeList(self):
4028 try:
4029 if self._selectionTypeList:
4030 pass
4031 except AttributeError, e:
4032 self._selectionTypeList = {"multiple": "Multiple choice",
4033 "unique": "Unique choice"}
4034 return self._selectionTypeList
4036 def _getSelectionType(self):
4037 try:
4038 if self._selectionType:
4039 pass
4040 except AttributeError, e:
4041 self._selectionType = "multiple"
4042 return self._selectionType
4044 def getSelectionTypeId(self):
4045 return self._getSelectionType()
4047 def getSelectionTypeCaption(self):
4048 return self.getSelectionTypeList()[self._getSelectionType()]
4050 def setSelectionType(self, id):
4051 self._selectionType = id
4053 def _generateNewSocialEventItemId(self):
4054 """Returns a new unique identifier for the current registration form
4056 try:
4057 return str(self._socialEventItemGenerator.newCount())
4058 except:
4059 self._socialEventItemGenerator = Counter()
4060 return str(self._socialEventItemGenerator.newCount())
4062 def addSocialEvent(self, se):
4063 id = se.getId()
4064 if id == "":
4065 id = self._generateNewSocialEventItemId()
4066 se.setId(id)
4067 self._socialEvents[id] = se
4069 def removeSocialEvent(self, se):
4070 se.remove()
4071 if self._socialEvents.has_key(se.getId().strip()):
4072 del(self._socialEvents[se.getId().strip()])
4074 def recoverSocialEvent(self, se):
4075 self.addSocialEvent(se)
4076 se.recover(self.getRegistrationForm())
4078 def getSocialEventById(self, id):
4079 if self._socialEvents.has_key(id.strip()):
4080 return self._socialEvents[id]
4081 return None
4083 def getSocialEventList(self, sort=False):
4084 v = self._socialEvents.values()
4085 if sort:
4086 v.sort(SocialEventItem._cmpCaption)
4087 return v
4089 def clearSocialEventList(self):
4090 for se in self.getSocialEventList():
4091 self.removeSocialEvent(se)
4093 def getLocator(self):
4094 """Gives back (Locator) a globaly unique identification encapsulated in
4095 a Locator object for the GeneralField instance """
4096 if self.getConference() == None:
4097 return Locator()
4098 lconf = self.getConference().getLocator()
4099 lconf["sectionFieldId"] = self.getId()
4100 return lconf
4103 class StatusValue(Persistent):
4105 def __init__(self, st, data=None):
4106 self._status = st
4107 self._id = ""
4108 self._caption = ""
4109 if data is not None:
4110 self.setValues(data)
4112 def getValues(self):
4113 d = {}
4114 d["caption"] = self.getCaption()
4115 return d
4117 def setValues(self, d):
4118 self.setCaption(d.get("caption", "-- no caption --"))
4120 def getId(self):
4121 return self._id
4123 def setId(self, id):
4124 self._id = id
4126 def getCaption(self):
4127 return self._caption
4129 def setCaption(self, cp):
4130 self._caption = cp
4132 def clone(self, st):
4133 sv = StatusValue(st)
4134 sv.setCaption(self.getCaption())
4135 return sv
4137 def _cmpCaption(sv1, sv2):
4138 return cmp(sv1.getCaption().strip().lower(), sv2.getCaption().strip().lower())
4139 _cmpCaption = staticmethod(_cmpCaption)
4142 class Status(Persistent):
4144 def __init__(self, regForm, data=None):
4145 self._regForm = regForm
4146 self._statusValues = {}
4147 self._valuesGenerator = Counter()
4148 self._id = ""
4149 self._caption = ""
4150 self._defaultValue = None
4151 if data is not None:
4152 self.setValues(data)
4153 self.addStatusValue(StatusValue(self, {"caption":"Yes"}))
4154 self.addStatusValue(StatusValue(self, {"caption":"No"}))
4156 def setValues(self, d):
4157 self.setCaption(d.get("caption", ""))
4158 ids = []
4159 defaultValueSet = False
4160 if d.has_key("values") and type(d.get("values", [])) == list:
4161 for vd in d.get("values", []):
4162 id = vd.get("id", "")
4163 if self.getStatusValueById(id) is not None:
4164 v = self.getStatusValueById(id)
4165 v.setValues(vd)
4166 else:
4167 v = StatusValue(self, vd)
4168 self.addStatusValue(v)
4169 if d.get("defaultvalue", "").strip() == id:
4170 defaultValueSet = True
4171 self.setDefaultValue(v)
4172 ids.append(v.getId())
4173 if not defaultValueSet:
4174 self.setDefaultValue(None)
4175 for v in self.getStatusValuesList()[:]:
4176 if v.getId() not in ids:
4177 self.removeStatusValue(v)
4179 def getValues(self):
4180 d = {}
4181 d["caption"] = self.getCaption()
4182 return d
4184 def getConference(self):
4185 return self._regForm.getConference()
4187 def getId(self):
4188 return self._id
4190 def setId(self, i):
4191 self._id = i
4193 def getCaption(self):
4194 return self._caption
4196 def setCaption(self, c):
4197 self._caption = c
4199 def setDefaultValue(self, stval):
4200 self._defaultValue = stval
4202 def getDefaultValue(self):
4203 return self._defaultValue
4205 def _generateValueId(self):
4206 """Returns a new unique identifier for the current registration form
4208 try:
4209 return str(self._valuesGenerator.newCount())
4210 except:
4211 self._valuesGenerator = Counter()
4212 return str(self._valuesGenerator.newCount())
4214 def getStatusValues(self):
4215 return self._statusValues
4217 def getStatusValuesList(self, sort=False):
4218 r = self._statusValues.values()
4219 if sort:
4220 r.sort(StatusValue._cmpCaption)
4221 return r
4223 def hasStatusValue(self, v):
4224 if v is not None and self.getStatusValues().has_key(v.getId()):
4225 return True
4226 return False
4228 def getStatusValueById(self, id):
4229 if self.getStatusValues().has_key(id):
4230 return self.getStatusValues()[id]
4231 return None
4233 def addStatusValue(self, v):
4234 v.setId(self._generateValueId())
4235 self.getStatusValues()[v.getId()] = v
4236 self.notifyModification()
4238 def removeStatusValue(self, v):
4239 if self.getStatusValues().has_key(v.getId()):
4240 del self.getStatusValues()[v.getId()]
4241 self.notifyModification()
4243 def _cmpCaption(s1, s2):
4244 return cmp(s1.getCaption().lower().strip(), s2.getCaption().lower().strip())
4245 _cmpCaption = staticmethod(_cmpCaption)
4247 def getLocator(self):
4248 """Gives back (Locator) a globaly unique identification encapsulated in
4249 a Locator object for the Status instance """
4250 if self.getConference() == None:
4251 return Locator()
4252 lconf = self.getConference().getLocator()
4253 lconf["statusId"] = self.getId()
4254 return lconf
4256 def notifyModification(self):
4257 """Method called to notify that the registration form has been modified.
4259 self._p_changed = 1
4262 # Users --------- FINAL INFORMATION STORED FROM THE REGISTRATION FORM
4264 class Registrant(Persistent, Fossilizable):
4266 fossilizes(IRegFormRegistrantFossil, IRegFormRegistrantBasicFossil, IRegFormRegistrantFullFossil)
4268 def __init__(self):
4269 self._conf = None
4270 self._avatar = None
4271 self._id = ""
4272 self._complete = False
4273 self._registrationDate = nowutc()
4274 self._checkedIn = False
4275 self._checkInDate = None
4276 self._checkInUUID = str(uuid4())
4278 self._title = ""
4279 self._firstName = ""
4280 self._surname = ""
4281 self._position = ""
4282 self._institution = ""
4283 self._address = ""
4284 self._city = ""
4285 self._country = ""
4286 self._phone = ""
4287 self._fax = ""
4288 self._email = ""
4289 self._personalHomepage = ""
4291 self._sessions = []
4292 self._socialEvents = []
4293 self._accommodation = Accommodation(self)
4294 self._reasonParticipation = ""
4296 self._miscellaneous = {}
4297 self._parmasReturn = {}
4298 self._statuses = {}
4299 self._total = 0
4300 self._currency = ''
4301 self._transactionInfo = None
4302 self._checkout_attempt_dt = None
4304 self._randomId = self._generateRandomId()
4305 self._attachmentsCounter = Counter()
4307 def __cmp__(self, other):
4308 if type(self) is not type(other):
4309 # This is actually dangerous and the ZODB manual says not to do this
4310 # because it relies on memory order. However, this branch should never
4311 # be taken anyway since we do not store different types in the same set
4312 # or use them as keys.
4313 return cmp(hash(self), hash(other))
4314 if self.getConference() == other.getConference():
4315 return cmp(self.getId(), other.getId())
4316 return cmp(self.getConference(), other.getConference())
4318 def isPayedText(self):
4319 if self.getPayed():
4320 return "Yes"
4321 elif not self.doPay():
4322 return "-"
4323 return "No"
4325 def getIdPay(self):
4326 return "c%sr%s" % (self._conf.getId(), self.getId())
4328 def setTotal(self, total):
4329 self._total = total
4331 def getTotal(self):
4332 try:
4333 return self._total
4334 except:
4335 self.setTotal(0)
4336 return self._total
4338 def getCurrency(self):
4339 try:
4340 return self._currency
4341 except AttributeError:
4342 self._currency = self.getRegistrationForm().getCurrency()
4343 return self._currency
4345 def updateTotal(self):
4346 total = 0
4347 for gs in self.getRegistrationForm().getGeneralSectionFormsList():
4348 if gs.isEnabled():
4349 mg = self.getMiscellaneousGroupById(gs.getId())
4350 if mg != None:
4351 for miscItem in mg.getResponseItemList():
4352 if miscItem.isBillable():
4353 price = float(miscItem.getPrice() or 0)
4354 else:
4355 price = 0
4356 quantity = miscItem.getQuantity()
4357 total += price * quantity
4358 for bf in self.getBilledForms():
4359 for item in bf.getBilledItems():
4360 total += item.getPrice() * item.getQuantity()
4361 self.setTotal(total)
4363 def doPay(self):
4364 return (self.getTotal() > 0 and self.payment_status not in {TransactionStatus.successful,
4365 TransactionStatus.pending})
4367 def setPersonalData(self, data):
4369 self.getConference().updateRegistrantIndexByEmail(self, data.get("email", ""))
4371 self.setTitle(data.get("title", ""))
4372 self.setFirstName(data.get("firstName", ""))
4373 self.setSurName(data.get("surname", ""))
4374 self.setPosition(data.get("position", ""))
4375 self.setInstitution(data.get("institution", ""))
4376 self.setAddress(data.get("address", ""))
4377 self.setCity(data.get("city", ""))
4378 self.setCountry(data.get("country", ""))
4379 self.setPhone(data.get("phone", ""))
4380 self.setFax(data.get("fax", ""))
4381 self.setEmail(data.get("email", ""))
4382 self.setPersonalHomepage(data.get("personalHomepage", ""))
4384 def setValues(self, data, av):
4385 self._avatar = av
4386 self._currency = self.getRegistrationForm().getCurrency()
4388 if self.getRegistrationForm().getReasonParticipationForm().isEnabled():
4389 self.setReasonParticipation(data.get("reason", ""))
4391 if self.getRegistrationForm().getSessionsForm().isEnabled():
4392 sessions = data.get("sessions", [])
4393 if not isinstance(sessions, list):
4394 sessions = [sessions]
4395 if not self.getPayed():
4396 self.setSessions(sessions)
4397 else:
4398 # First keep all sessions which are billable (they are not submitted anymore)
4399 newSessions = [session for session in self.getSessionList() if session.isBillable()]
4400 # Then take all chosen sessions which are not billable
4401 newSessions += [session for session in sessions if not session.isBillable()]
4402 self.setSessions(newSessions)
4403 else:
4404 self.setSessions([])
4406 self.setSessionBillingEnabled(self.getRegistrationForm().getSessionsForm().getType() != "2priorities")
4408 if self.getRegistrationForm().getAccommodationForm().isEnabled():
4409 ad = data.get("arrivalDate", None)
4410 dd = data.get("departureDate", None)
4411 if ad == "nodate":
4412 raise FormValuesError(_("Arrival date cannot be empty."))
4413 elif dd == "nodate":
4414 raise FormValuesError(_("Departure date cannot be empty."))
4415 if ad is not None and dd is not None:
4416 ad = map(lambda x: int(x), ad.split("-"))
4417 ad = datetime(ad[2], ad[1], ad[0])
4418 dd = map(lambda x: int(x), dd.split("-"))
4419 dd = datetime(dd[2], dd[1], dd[0])
4420 if ad > dd:
4421 raise FormValuesError(_("Arrival date has to be earlier than departure date"))
4422 # Allow changing of the dates only if the current accomodation is not billable or the user hasn't paid yet
4423 currentAccoType = self._accommodation.getAccommodationType()
4424 if not self.getPayed() or currentAccoType is None or not currentAccoType.isBillable():
4425 self._accommodation.setArrivalDate(ad)
4426 self._accommodation.setDepartureDate(dd)
4427 accoType = data.get("accommodationType", None)
4428 if accoType is not None and accoType.isCancelled():
4429 accoType = None
4430 if self.getRegistrationForm().getAccommodationForm().getAccommodationTypesList() != []:
4431 # Only change the accommodation type if:
4432 # - the registrant hasn't paid yet OR
4433 # - neither the current nor the new accommodation is billable
4434 if not self.getPayed() or \
4435 ((currentAccoType is None or not currentAccoType.isBillable()) and \
4436 (accoType is None or not accoType.isBillable())):
4437 if self.getRegistrationForm().getAccommodationForm().getAccommodationTypesList() != [] and data.get("accommodation_type", None) is None:
4438 raise FormValuesError(_("It is mandatory to choose an accommodation in order to register"))
4439 self._accommodation.setAccommodationType(accoType)
4440 else: # AccommodationForm disabled
4441 self._accommodation.setAccommodationType(None)
4443 if self.getRegistrationForm().getSocialEventForm().isEnabled():
4444 for seItem in self.getSocialEvents()[:]:
4445 # Remove all items which can be added back (i.e. if paid only non-billable ones)
4446 if not (self.getPayed() and seItem.isBillable()):
4447 self.removeSocialEventById(seItem.getId())
4448 for seItem in data.get("socialEvents", []):
4449 # Only add item if the registrant hasn't paid yet or the item is not billable
4450 if seItem and (not self.getPayed() or not seItem.isBillable()):
4451 newSE = SocialEvent(seItem, int(data.get("places-%s" % seItem.getId(), "1")))
4452 self.addSocialEvent(newSE)
4453 if self.getRegistrationForm().getSocialEventForm().getMandatory() and not self.getSocialEvents():
4454 raise FormValuesError(_('You have to select at least one social event'))
4455 else:
4456 for seItem in self.getSocialEvents()[:]:
4457 self.removeSocialEventById(seItem.getId())
4458 #if not self.getPayed():
4459 # self._miscellaneous = {}
4460 total = 0
4461 for gs in self.getRegistrationForm().getGeneralSectionFormsList():
4462 if gs.isEnabled():
4463 mg = self.getMiscellaneousGroupById(gs.getId())
4464 if mg == None:
4465 mg = MiscellaneousInfoGroup(self, gs)
4466 self.addMiscellaneousGroup(mg)
4467 #Mods to support sorting fields
4468 #for f in gs.getFields():
4469 for f in gs.getSortedFields():
4470 if not f.isDisabled():
4471 f.getInput().setResponseValue(mg.getResponseItemById(f.getId()), data, self, mg)
4472 for miscItem in mg.getResponseItemList():
4473 if miscItem.isBillable():
4474 price = float(miscItem.getPrice() or 0)
4475 else:
4476 price = 0
4477 quantity = miscItem.getQuantity()
4478 total += price * quantity
4479 for bf in self.getBilledForms():
4480 for item in bf.getBilledItems():
4481 total += item.getPrice() * item.getQuantity()
4482 if not self.getPayed():
4483 self.setTotal(total)
4484 self.setPersonalData(self.getRegistrationForm().getPersonalData().getRegistrantValues(self))
4485 self._complete = True
4487 def isComplete(self):
4488 try:
4489 if self._complete:
4490 pass
4491 except AttributeError, e:
4492 self._complete = False
4493 return self._complete
4495 def isCheckedIn(self):
4496 try:
4497 if self._checkedIn:
4498 pass
4499 except AttributeError:
4500 self._checkedIn = False
4501 return self._checkedIn
4503 def setCheckedIn(self, checkedIn):
4504 if checkedIn:
4505 self._checkInDate = nowutc()
4506 else:
4507 self._checkInDate = None
4508 self._checkedIn = checkedIn
4510 def getCheckInUUID(self):
4511 try:
4512 if self._checkInUUID:
4513 pass
4514 except AttributeError:
4515 self._checkInUUID = str(uuid4())
4516 return self._checkInUUID
4518 def getCheckInDate(self):
4519 try:
4520 if self._checkInDate:
4521 pass
4522 except AttributeError:
4523 self._checkInDate = None
4524 return self._checkInDate
4526 def getAdjustedCheckInDate(self,tz=None):
4527 if not tz:
4528 tz = self.getConference().getTimezone()
4529 if tz not in all_timezones:
4530 tz = 'UTC'
4531 checkInDate = self.getCheckInDate()
4532 if checkInDate:
4533 return checkInDate.astimezone(timezone(tz))
4535 @property
4536 @memoize_request
4537 def payment_status(self):
4538 transaction = PaymentTransaction.find_latest_for_registrant(self)
4539 return transaction.status if transaction else None
4541 def getPayed(self):
4542 return self.payment_status == TransactionStatus.successful
4544 def _generateRandomId(self):
4545 n = datetime.now()
4546 return md5(str(random.random() + time.mktime(n.timetuple()))).hexdigest()
4548 def getRandomId(self):
4549 try:
4550 if self._randomId:
4551 pass
4552 except AttributeError, e:
4553 self._randomId = self._generateRandomId()
4554 return self._randomId
4556 def getId(self):
4557 return self._id
4559 def setId(self, id):
4560 self._id = str(id).strip()
4562 def getConference(self):
4563 return self._conf
4565 def setConference(self, c):
4566 self._conf = c
4568 def getOwner(self):
4569 return self.getConference()
4571 def setOwner(self, o):
4572 self.setConference(o)
4574 def getAvatar(self):
4575 return self._avatar
4577 def setAvatar(self, a):
4578 if isinstance(self._avatar, AvatarUserWrapper):
4579 self._avatar.unlinkTo(self, "registrant")
4580 self._avatar = a
4581 a.linkTo(self, "registrant")
4583 def getRegistrationForm(self):
4584 return self.getConference().getRegistrationForm()
4586 def getRegistrationDate(self):
4587 try:
4588 if self._registrationDate:
4589 pass
4590 except AttributeError, e:
4591 self._registrationDate = None
4592 return self._registrationDate
4594 def getAdjustedRegistrationDate(self, tz=None):
4595 if not tz:
4596 tz = self.getConference().getTimezone()
4597 if tz not in all_timezones:
4598 tz = 'UTC'
4599 return self.getRegistrationDate().astimezone(timezone(tz))
4601 def getTitle(self):
4602 return self._title
4604 def setTitle(self, v):
4605 self._title = v
4607 def getFirstName(self):
4608 return self._firstName
4610 def setFirstName(self, v):
4611 self._firstName = v
4613 def getSurName(self):
4614 return self._surname
4615 getFamilyName = getSurName
4617 def setSurName(self, v):
4618 self._surname = v
4619 setFamilyName = setSurName
4621 def getFullName(self, title=True, firstNameFirst=False):
4622 if firstNameFirst:
4623 res = "%s %s" % (self.getFirstName(), self.getFamilyName())
4624 res = res.strip()
4625 else:
4626 res = safe_upper(self.getFamilyName())
4627 if self.getFirstName():
4628 res = "%s, %s" % (res, self.getFirstName())
4629 if title and self.getTitle():
4630 res = "%s %s" % (self.getTitle(), res)
4631 return res
4633 def getPosition(self):
4634 return self._position
4636 def setPosition(self, v):
4637 self._position = v
4639 def getInstitution(self):
4640 return self._institution
4642 def setInstitution(self, v):
4643 self._institution = v
4645 def getAddress(self):
4646 return self._address
4648 def setAddress(self, v):
4649 self._address = v
4651 def getCity(self):
4652 return self._city
4654 def setCity(self, v):
4655 self._city = v
4657 def getCountry(self):
4658 return self._country
4660 def setCountry(self, v):
4661 self._country = v
4663 def getPhone(self):
4664 return self._phone
4666 def setPhone(self, v):
4667 self._phone = v
4669 def getFax(self):
4670 return self._fax
4672 def setFax(self, v):
4673 self._fax = v
4675 def getEmail(self):
4676 return self._email
4678 def setEmail(self, v):
4679 self._email = v
4681 def getPersonalHomepage(self):
4682 return self._personalHomepage
4684 def setPersonalHomepage(self, v):
4685 self._personalHomepage = v
4687 def getSessionList(self):
4688 return self._sessions
4690 def addSession(self, ses):
4691 self._sessions.append(ses)
4692 self.notifyModification()
4694 def removeSession(self, ses):
4695 self._sessions.remove(ses)
4696 self.notifyModification()
4698 def setSessions(self, sesList):
4699 self._sessions = sesList
4700 for ses in self._sessions:
4701 ses.setRegistrant(self)
4702 self.notifyModification()
4704 def setAccommodation(self, a):
4705 self._accommodation = a
4707 def getAccommodation(self):
4708 return self._accommodation
4710 def setReasonParticipation(self, a):
4711 self._reasonParticipation = a
4713 def getReasonParticipation(self):
4714 return self._reasonParticipation
4716 def getSocialEvents(self):
4717 try:
4718 if self._socialEvents:
4719 pass
4720 except AttributeError, e:
4721 self._socialEvents = []
4722 return self._socialEvents
4724 def getSocialEventById(self, id):
4725 for se in self.getSocialEvents():
4726 if id == se.getId():
4727 return se
4728 return None
4730 def setSocialEvents(self, se):
4731 self._socialEvents = se
4732 self.notifyModification()
4734 def addSocialEvent(self, se):
4735 se.setRegistrant(self)
4736 self.getSocialEvents().append(se)
4737 self.notifyModification()
4739 def removeSocialEventById(self, id):
4740 se = self.getSocialEventById(id)
4741 se.delete()
4742 self.getSocialEvents().remove(se)
4743 self.notifyModification()
4745 def getLocator(self):
4746 """Gives back (Locator) a globaly unique identification encapsulated in
4747 a Locator object for the registrant instance """
4748 if self.getConference() == None:
4749 return Locator()
4750 lconf = self.getConference().getLocator()
4751 lconf["registrantId"] = self.getId()
4752 return lconf
4754 def notifyModification(self):
4755 """Method called to notify the current registered participant has been modified.
4757 self._p_changed = 1
4759 def _cmpFamilyName(r1, r2):
4760 if r1 is None and r2 is None:
4761 return 0
4762 if r1 is None:
4763 return -1
4764 if r2 is None:
4765 return 1
4766 return cmp(r1.getFamilyName().lower(), r2.getFamilyName().lower())
4767 _cmpFamilyName = staticmethod(_cmpFamilyName)
4769 def getMiscellaneousGroups(self):
4770 try:
4771 if self._miscellaneous:
4772 pass
4773 except AttributeError, e:
4774 self._miscellaneous = {}
4775 return self._miscellaneous
4777 def getMiscellaneousGroupList(self):
4778 return self.getMiscellaneousGroups().values()
4780 def getMiscellaneousGroupById(self, id):
4781 if self.getMiscellaneousGroups().has_key(id):
4782 return self.getMiscellaneousGroups()[id]
4783 return None
4785 def addMiscellaneousGroup(self, g):
4786 if not self.getMiscellaneousGroups().has_key(g.getId()):
4787 self.getMiscellaneousGroups()[g.getId()] = g
4788 self.notifyModification()
4790 def setSessionBillingEnabled(self, v):
4791 self._sessionBillingEnabled = v
4793 def isSessionBillingEnabled(self):
4794 try:
4795 return self._sessionBillingEnabled
4796 except:
4797 self.setSessionBillingEnabled(False)
4798 return self._sessionBillingEnabled
4800 def getBilledForms(self):
4804 forms = []
4805 if self._accommodation:
4806 forms.append(BilledItemsWrapper([self._accommodation]))
4807 if self._socialEvents:
4808 forms.append(BilledItemsWrapper(self._socialEvents))
4809 if self._sessions and self.isSessionBillingEnabled():
4810 forms.append(BilledItemsWrapper(self._sessions))
4811 return forms
4813 def getStatuses(self):
4814 try:
4815 if self._statuses:
4816 pass
4817 except AttributeError, e:
4818 self._statuses = {}
4819 return self._statuses
4821 def getStatusesList(self):
4822 return self.getStatuses().values()
4824 def addStatus(self, s):
4825 self.getStatuses()[s.getId()] = s
4826 self.notifyModification()
4828 def removeStatus(self, s):
4829 if self.getStatuses().has_key(s.getId()):
4830 del self.getStatuses()[s.getId()]
4831 self.notifyModification()
4833 def getStatusById(self, id):
4834 v = self.getStatuses().get(id, None)
4835 if v is None:
4836 st = self._conf.getRegistrationForm().getStatusById(id)
4837 v = RegistrantStatus(self, st)
4838 if st.getDefaultValue() is not None:
4839 v.setStatusValue(st.getDefaultValue())
4840 self.addStatus(v)
4841 return v
4843 def setModificationDate(self):
4844 pass
4846 def getAttachments(self):
4847 try:
4848 if self._attachments:
4849 pass
4850 except AttributeError:
4851 self._attachments = {}
4852 return self._attachments
4854 def getAttachmentList(self):
4855 return self.getAttachments().values()
4857 def getAttachmentById(self, id):
4858 return self.getAttachments().get(id, None)
4860 def _getAttachmentsCounter(self):
4861 try:
4862 if self._attachmentsCounter:
4863 pass
4864 except AttributeError:
4865 self._attachmentsCounter = Counter()
4866 return self._attachmentsCounter.newCount()
4868 def __addFile(self, file):
4869 file.archive(self.getConference()._getRepository())
4870 self.getAttachments()[file.getId()] = file
4871 self.notifyModification()
4873 def saveFile(self, fileUploaded):
4874 from MaKaC.conference import LocalFile
4875 cfg = Config.getInstance()
4876 tempPath = cfg.getUploadedFilesTempDir()
4877 tempFileName = tempfile.mkstemp(suffix="IndicoRegistrant.tmp", dir=tempPath)[1]
4878 f = open(tempFileName, "wb")
4879 f.write(fileUploaded.file.read())
4880 f.close()
4881 file = LocalFile()
4882 file.setFileName(fileUploaded.filename)
4883 file.setFilePath(tempFileName)
4884 file.setOwner(self)
4885 file.setId(self._getAttachmentsCounter())
4886 self.__addFile(file)
4887 return file
4889 def deleteFile(self, fileId):
4890 file = self.getAttachments()[fileId]
4891 file.delete()
4892 del self.getAttachments()[fileId]
4893 self.notifyModification()
4895 def removeResource(self, res):
4896 """Necessary because LocalFile.delete (see _deleteFile) is calling this method.
4897 In our case, nothing to do.
4899 pass
4901 def canUserModify(self, user):
4902 return self.getConference().canUserModify(user) or (user is not None and user == self.getAvatar())
4904 def getCheckoutAttemptDt(self):
4905 try:
4906 return self._checkout_attempt_dt
4907 except AttributeError:
4908 return None
4910 def isCheckoutSessionAlive(self):
4911 checkout_attempt_dt = self.getCheckoutAttemptDt()
4912 if checkout_attempt_dt:
4913 checkout_session_timeout = payment_settings.get('checkout_session_timeout')
4914 return datetime.now() - checkout_attempt_dt < timedelta(minutes=checkout_session_timeout)
4915 return False
4918 class BilledItemsWrapper(object):
4920 def __init__(self, items):
4921 self._items = items
4923 def getBilledItems(self):
4924 return [item.getBilledItem() for item in self._items if item.isBillable() and not item.isCancelled()]
4927 class BilledItem(object):
4929 def __init__(self, caption, price, quantity, currency):
4930 self._caption = caption
4931 self._price = price
4932 self._quantity = quantity
4933 self._currency = currency
4935 def getCaption(self):
4936 return self._caption
4938 def getPrice(self):
4939 return float(self._price)
4941 def getQuantity(self):
4942 return self._quantity
4944 def getCurrency(self):
4945 return self._currency
4948 class Accommodation(Persistent):
4950 def __init__(self, reg=None):
4951 self._registrant = reg
4952 self._arrivalDate = None
4953 self._departureDate = None
4954 self._accommodationType = None
4955 self._price = 0
4956 self._billable = False
4957 self._currency = ""
4959 def isCancelled(self):
4960 return self._accommodationType.isCancelled()
4962 def getRegistrant(self):
4963 try:
4964 return self._registrant
4965 except:
4966 return None
4968 def setRegistrant(self, reg):
4969 self._registrant = reg
4971 def getArrivalDate(self):
4972 return self._arrivalDate
4974 def setArrivalDate(self, ad):
4975 self._arrivalDate = ad
4977 def getDepartureDate(self):
4978 return self._departureDate
4980 def setDepartureDate(self, dd):
4981 self._departureDate = dd
4983 def getNights(self):
4984 return (self._departureDate - self._arrivalDate).days
4986 def getPrice(self):
4987 try:
4988 return self._price
4989 except:
4990 return 0
4992 def isBillable(self):
4993 try:
4994 return self._billable
4995 except:
4996 return False
4998 def getCurrency(self):
4999 try:
5000 return self._currency
5001 except:
5002 self._currency = self._regForm.getCurrency()
5003 return self._currency
5005 def getBilledItem(self):
5006 return BilledItem(self._accommodationType.getCaption(), self.getPrice(), self.getNights(), self.getCurrency())
5008 def getAccommodationType(self):
5009 return self._accommodationType
5011 def setAccommodationType(self, at):
5012 if self.getAccommodationType() != at:
5013 if self.getAccommodationType() is not None:
5014 self.getAccommodationType().decreaseNoPlaces()
5015 if at is not None:
5016 at.increaseNoPlaces()
5017 self._price = at.getPrice()
5018 self._billable = at.isBillable()
5019 self._currency = at.getCurrency()
5020 else:
5021 self._price = 0
5022 self._billable = False
5023 self._currency = ""
5024 self._accommodationType = at
5026 def getCaption(self):
5027 acc_type = self.getAccommodationType()
5028 return acc_type.getCaption() if acc_type is not None else ''
5030 def getId(self):
5031 return self.getAccommodationType().getId() if self.getAccommodationType() is not None else ''
5034 class SocialEvent(Persistent, Fossilizable):
5036 fossilizes(IRegFormSocialEventFossil)
5038 def __init__(self, se, noPlaces, reg=None):
5039 self._registrant = None
5040 self.addSEItem(se, noPlaces)
5042 def addSEItem(self, se, noPlaces):
5043 self._socialEventItem = se
5044 self._noPlaces = noPlaces
5045 self._socialEventItem.increaseNoPlaces(noPlaces)
5046 self._price = self._socialEventItem.getPrice()
5047 self._pricePerPlace = self._socialEventItem.isPricePerPlace()
5048 self._billable = self._socialEventItem.isBillable()
5049 self._currency = self._socialEventItem.getCurrency()
5051 def getRegistrant(self):
5052 try:
5053 return self._registrant
5054 except:
5055 return None
5057 def setRegistrant(self, reg):
5058 self._registrant = reg
5060 def getNoPlaces(self):
5061 return self._noPlaces
5063 def getCurrency(self):
5064 try:
5065 return self._currency
5066 except:
5067 self._currency = self._socialEventItem.getCurrency()
5068 return self._currency
5070 def getPrice(self):
5071 try:
5072 return self._price
5073 except:
5074 return 0
5076 def isBillable(self):
5077 try:
5078 return self._billable
5079 except:
5080 return False
5082 def isPricePerPlace(self):
5083 try:
5084 return self._pricePerPlace
5085 except:
5086 return False
5088 def getBilledItem(self):
5089 quantity = 1
5090 if self._pricePerPlace:
5091 quantity = self.getNoPlaces()
5092 return BilledItem(self.getCaption(), self.getPrice(), quantity, self.getCurrency())
5094 def getSocialEventItem(self):
5095 return self._socialEventItem
5097 def getId(self):
5098 return self._socialEventItem.getId()
5100 def isCancelled(self):
5101 return self._socialEventItem.isCancelled()
5103 def getCancelledReason(self):
5104 return self._socialEventItem.getCancelledReason()
5106 def getCaption(self):
5107 return self._socialEventItem.getCaption()
5109 def getMaxPlacePerRegistrant(self):
5110 return self._socialEventItem.getMaxPlacePerRegistrant()
5112 def delete(self):
5113 self._socialEventItem.decreaseNoPlaces(self._noPlaces)
5116 class RegistrantSession(Persistent):
5118 def __init__(self, ses, reg=None):
5119 self._regSession = ses
5120 self._registrant = reg
5121 self._price = self._regSession.getPrice()
5122 self._billable = self._regSession.isBillable()
5123 self._currency = self._regSession.getCurrency()
5125 def getRegistrant(self):
5126 return self._registrant
5128 def setRegistrant(self, reg):
5129 self._registrant = reg
5131 def getCurrency(self):
5132 if not hasattr(self, "_currency") or not self._currency:
5133 self._currency = self._regSession.getCurrency()
5134 return self._currency
5136 def getPrice(self):
5137 try:
5138 return self._price
5139 except:
5140 return 0
5142 def isBillable(self):
5143 try:
5144 return self._billable
5145 except:
5146 return False
5148 def getBilledItem(self):
5149 return BilledItem(self.getCaption(), self.getPrice(), 1, self.getCurrency())
5151 def getRegSession(self):
5152 return self._regSession
5154 def getSession(self):
5155 return self._regSession.getSession()
5157 def getId(self):
5158 return self._regSession.getId()
5160 def getCaption(self):
5161 return self._regSession.getCaption()
5162 getTitle = getCaption
5164 def getCode(self):
5165 return self._regSession.getCode()
5167 def isCancelled(self):
5168 return self._regSession.isCancelled()
5171 class MiscellaneousInfoGroup(Persistent, Fossilizable):
5173 fossilizes(IRegFormMiscellaneousInfoGroupFossil)
5175 def __init__(self, reg, gs):
5176 self._registrant = reg
5177 self._generalSection = gs
5178 self._id = gs.getId()
5179 self._responseItems = {}
5181 def getId(self):
5182 return self._id
5184 def getGeneralSection(self):
5185 return self._generalSection
5187 def getTitle(self):
5188 return self.getGeneralSection().getTitle()
5190 def getRegistrant(self):
5191 return self._registrant
5193 def getResponseItems(self):
5194 return self._responseItems
5196 def getResponseItemList(self):
5197 return self._responseItems.values()
5199 def addResponseItem(self, r):
5200 self._responseItems[r.getId()] = r
5201 self.notifyModification()
5203 def removeResponseItem(self, i):
5204 if self.getResponseItems().has_key(i.getId()):
5205 del self._responseItems[i.getId()]
5206 self.notifyModification()
5208 def getResponseItemById(self, id):
5209 if self._responseItems.has_key(id):
5210 return self._responseItems[id]
5211 return None
5213 def clearResponses(self, gs=None):
5214 if gs is None:
5215 self._responseItems = {}
5216 self.notifyModification()
5217 else:
5218 #Mods to support sorting fields
5219 #for f in gs.getFields():
5220 for f in gs.getSortedFields():
5221 self.removeResponseItem(f)
5223 def getLocator(self):
5224 """Gives back (Locator) a globaly unique identification encapsulated in
5225 a Locator object for the MiscellaneousInfoGroup instance """
5226 lconf = self.getRegistrant().getLocator()
5227 lconf["miscInfoId"] = self.getId()
5228 return lconf
5230 def notifyModification(self):
5231 self._p_changed = 1
5234 class MiscellaneousInfoSimpleItem(Persistent):
5236 def __init__(self, group, field):
5237 self._group = group
5238 self._generalField = field
5239 self._id = field.getId()
5240 self._value = None
5241 self._billable = False
5242 self._price = 0.0
5243 self._quantity = 0
5244 self._currency = ""
5245 self._mandatory = False
5246 # TODO: When migrate to new database, take into account that HTMLName cannot be empty string
5247 self._HTMLName = ""
5249 def getHTMLName(self):
5250 try:
5251 if self._HTMLName == "":
5252 self._HTMLName = self.getGeneralField().getInput().getHTMLName()
5253 except:
5254 self._HTMLName = ""
5255 return self._HTMLName
5257 def setHTMLName(self, HTMLName):
5258 self._HTMLName = HTMLName
5260 def isMandatory(self):
5261 try:
5262 return self._mandatory
5263 except:
5264 self._mandatory = False
5265 return self._mandatory
5267 def setMandatory(self, mandatory):
5268 self._mandatory = mandatory
5270 def getCurrency(self):
5271 try:
5272 return self._currency
5273 except:
5274 self.setCurrency("")
5275 return self._currency
5277 def setCurrency(self, currency):
5278 self._currency = currency
5280 def getQuantity(self):
5281 try:
5282 return self._quantity
5283 except:
5284 self.setQuantity(0)
5285 return self._quantity
5287 def setQuantity(self, quantity):
5288 self._quantity = quantity
5290 def isBillable(self):
5291 try:
5292 return self._billable
5293 except:
5294 self.setBillable(False)
5295 return self._billable
5297 def setBillable(self, v):
5298 self._billable = v
5300 def getPrice(self):
5301 try:
5302 return self._price
5303 except:
5304 self.setPrice(0)
5305 return self._price
5307 def setPrice(self, price):
5308 self._price = price
5310 def getId(self):
5311 return self._id
5313 def getGeneralField(self):
5314 return self._generalField
5316 def getCaption(self):
5317 return self._generalField.getCaption()
5319 def getOwner(self):
5320 return self._group
5321 getGroup = getOwner
5323 def getValue(self):
5324 return self._value
5326 def setValue(self, v):
5327 self._value = v
5330 class RegistrantStatus(Persistent):
5332 def __init__(self, reg, st, data=None):
5333 self._status = st
5334 self._registrant = reg
5335 self._value = None
5336 if data is not None:
5337 self.setValues()
5339 def setValues(self, d):
5340 self.setStatusValue(d.get("statusvalue", ""))
5342 def getValues(self):
5343 d = {}
5344 d["statusvalue"] = self.getStatusValue()
5345 return d
5347 def getId(self):
5348 return self._status.getId()
5350 def getCaption(self):
5351 return self._status.getCaption()
5353 def getStatusValue(self):
5354 if not self._status.hasStatusValue(self._value):
5355 self._value = self._status.getDefaultValue()
5356 return self._value
5358 def setStatusValue(self, v):
5359 self._value = v
5362 class RegistrantMapping(object):
5364 def __init__(self, registrant):
5365 self._registrant = registrant
5366 self._regDict = {
5367 "FirstName": self._registrant.getFirstName,
5368 "LastName": self._registrant.getSurName,
5369 "Institution": self._registrant.getInstitution,
5370 "Position": self._registrant.getPosition,
5371 "Phone": self._registrant.getPhone,
5372 "City": self._registrant.getCity,
5373 "Address": self._registrant.getAddress,
5374 "Email": self._registrant.getEmail,
5375 "isPayed": self._registrant.isPayedText,
5376 "idpayment": self._registrant.getIdPay,
5377 "Country": self._getCountry,
5378 "amountToPay": self._getAmountToPay,
5379 "Accommodation": self._getAccomodation,
5380 "SocialEvents": self._getSocialEvents,
5381 "ReasonParticipation": self._getReasonParticipation,
5382 "RegistrationDate": self._getRegistrationDate,
5383 "Sessions": self._getSessions,
5384 "DepartureDate": self._getDepartureDate,
5385 "ArrivalDate": self._getArrivalDate,
5386 "checkedIn": self._getCheckedIn,
5387 "checkInDate": self._getCheckInDate
5390 def __getitem__(self, key):
5391 if self._regDict.has_key(key):
5392 return self._regDict[key]()
5393 elif re.match("s-[0-9]+$", key):
5394 return self._getStatus(key[2:])
5395 elif re.match("[0-9]+$", key):
5396 return self._getGroup(key)
5397 elif re.match("[0-9]+-[0-9]+$", key):
5398 dashPos = key.find('-')
5399 return self._getItem(key[:dashPos], key[dashPos + 1:])
5400 else:
5401 return "&nbsp;"
5403 def _getCountry(self):
5404 return CountryHolder().getCountryById(self._registrant.getCountry())
5406 def _getAmountToPay(self):
5407 return "%.2f %s" % (self._registrant.getTotal(), self._registrant.getConference().getRegistrationForm().getCurrency())
5409 def _getAccomodation(self):
5410 if self._registrant.getAccommodation() is not None:
5411 if self._registrant.getAccommodation().getAccommodationType() is not None:
5412 return self._registrant.getAccommodation().getAccommodationType().getCaption()
5413 return ""
5415 def _getDepartureDate(self):
5416 accomodation = self._registrant.getAccommodation()
5417 if accomodation is not None:
5418 departure_date = accomodation.getDepartureDate()
5419 if departure_date is not None:
5420 return format_date(departure_date)
5421 return ""
5423 def _getArrivalDate(self):
5424 accomodation = self._registrant.getAccommodation()
5425 if accomodation is not None:
5426 arrival_date = accomodation.getArrivalDate()
5427 if arrival_date is not None:
5428 return format_date(arrival_date)
5429 return ""
5431 def _getSocialEvents(self):
5432 events = self._registrant.getSocialEvents()
5433 items = ["%s (%s)" % (item.getCaption(), item.getNoPlaces()) for item in events ]
5434 return "<br>".join(items)
5436 def _getReasonParticipation(self):
5437 return self._registrant.getReasonParticipation() or ""
5439 def _getRegistrationDate(self):
5440 registration_date = self._registrant.getAdjustedRegistrationDate()
5441 if registration_date is not None:
5442 return format_datetime(registration_date)
5443 else:
5444 return i18nformat("""-- _("date unknown")--""")
5446 def _getSessions(self):
5447 sessions = self._registrant.getSessionList()
5448 return "<br>".join([sess.getTitle() for sess in sessions])
5450 def _getStatus(self, id):
5451 st = self._registrant.getStatusById(id)
5452 if st.getStatusValue() is not None:
5453 return st.getStatusValue().getCaption()
5454 else:
5455 return i18nformat("""<span style="white-space:nowrap">-- _("not set") --</span>""")
5457 def _getGroup(self, groupId):
5458 if self._registrant.getMiscellaneousGroupById(groupId):
5459 return self._registrant.getMiscellaneousGroupById(groupId).getTitle()
5460 else:
5461 return ""
5463 def _formatValue(self, fieldInput, value):
5464 try:
5465 value = fieldInput.getValueDisplay(value)
5466 except:
5467 value = str(value).strip()
5468 return value
5470 def _getItem(self, groupId, itemId):
5471 if self._registrant.getMiscellaneousGroupById(groupId) and \
5472 self._registrant.getMiscellaneousGroupById(groupId).getResponseItemById(itemId):
5473 item = self._registrant.getMiscellaneousGroupById(groupId).getResponseItemById(itemId)
5474 return self._formatValue(item.getGeneralField().getInput(), item.getValue())
5475 else:
5476 return ""
5478 def _getCheckedIn(self):
5479 conf = self._registrant.getConference()
5480 if not conf.getRegistrationForm().getETicket().isEnabled():
5481 return "-"
5482 elif self._registrant.isCheckedIn():
5483 return _("Yes")
5484 else:
5485 return _("No")
5487 def _getCheckInDate(self):
5488 checkInDate = self._registrant.getAdjustedCheckInDate()
5489 if checkInDate:
5490 return format_datetime(checkInDate)
5491 else:
5492 return "-"