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
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
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
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):
82 self
.activated
= False
83 self
.title
= "Registration Form"
84 self
.announcement
= ""
87 self
.setStartRegistrationDate(nowutc())
88 self
.setEndRegistrationDate(nowutc())
89 self
.setModificationEndDate(None)
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()
111 self
._statusesGenerator
= Counter()
113 if not skipPersonalData
:
114 self
.personalData
= PersonalDataForm(self
)
116 self
.sessionsForm
= SessionsForm()
117 self
.accommodationForm
= AccommodationForm(self
)
118 self
.reasonParticipationForm
= ReasonParticipationForm()
119 self
.furtherInformation
= FurtherInformationForm()
120 self
.socialEventForm
= SocialEventForm(self
)
122 self
._generalSectionGenerator
= Counter()
123 self
.generalSectionForms
= {}
124 if not skipPersonalData
:
125 self
.addGeneralSectionForm(self
.personalData
, True)
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()
166 form
.accommodationForm
= acf
.clone(form
)
167 fif
= self
.getFurtherInformationForm()
169 form
.furtherInformation
= fif
.clone()
170 rpf
= self
.getReasonParticipationForm()
172 form
.reasonParticipationForm
= rpf
.clone()
173 form
.setAllSessions()
174 ses
= self
.getSessionsForm()
176 form
.sessionsForm
= ses
.clone(form
.sessionsForm
.getSessionList())
177 sef
= self
.getSocialEventForm()
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
)
191 def getCurrency(self
):
192 return payment_event_settings
.get(self
._conf
, 'currency')
194 def getConference(self
):
196 getOwner
= getConference
198 def getTimezone(self
):
199 return self
.getConference().getTimezone()
201 def setConference(self
, 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
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
):
224 if self
._mandatoryAccount
:
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
):
239 if self
._notificationSender
:
240 sender
= self
._notificationSender
241 except AttributeError, e
:
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
):
256 if self
._sendPaidEmail
:
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()
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() == "":
284 self
.usersLimit
= int(newLimit
.strip())
285 if self
.usersLimit
< 0:
288 def getUsersLimit(self
):
289 return self
.usersLimit
292 if self
.usersLimit
!= 0:
293 return len(self
.getConference().getRegistrants()) >= self
.usersLimit
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())
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
):
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
):
330 return self
._endExtraTimeUnit
331 except AttributeError:
332 self
._endExtraTimeUnit
= 'days'
333 return self
._endExtraTimeUnit
335 def setModificationEndDate(self
, ed
):
337 self
.modificationEndDate
= datetime(ed
.year
, ed
.month
, ed
.day
, 23, 59, 59)
339 self
.modificationEndDate
= None
341 def getModificationEndDate(self
):
343 if self
.modificationEndDate
:
344 return timezone(self
.getTimezone()).localize(self
.modificationEndDate
)
345 except AttributeError, e
:
349 def inModificationPeriod(self
):
350 if self
.getModificationEndDate() is None:
353 sd
= self
.getStartRegistrationDate()
354 ed
= self
.getModificationEndDate()
355 return date
<= ed
and date
>= sd
357 def inRegistrationPeriod(self
, date
=None):
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
):
374 except AttributeError, e
:
376 return self
._statuses
378 def _generateStatusId(self
):
380 if self
._statusesGenerator
:
382 except AttributeError, e
:
383 self
._statusesGenerator
= Counter()
384 return self
._statusesGenerator
386 def getStatusesList(self
, sort
=True):
387 v
= self
.getStatuses().values()
389 v
.sort(Status
._cmpCaption
)
392 def getStatusById(self
, id):
393 if self
.getStatuses().has_key(id):
394 return self
.getStatuses()[id]
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
):
409 if self
.notification
:
412 self
.notification
= Notification()
413 return self
.notification
415 def _convertPersonalData(self
):
416 if isinstance(self
.personalData
, PersonalDataForm
):
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":
431 val
= str(TitlesRegistry
._items
.index(val
))
433 # can happen for older events with obsolete titles
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()
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
):
474 if self
._generalSectionGenerator
:
476 except AttributeError, e
:
477 self
._generalSectionGenerator
= Counter()
478 return self
._generalSectionGenerator
480 def getGeneralSectionForms(self
):
482 if self
.generalSectionForms
:
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())
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
):
516 if self
._sortedForms
:
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):
531 i
= len(self
.getSortedForms())
533 self
.getSortedForms().remove(form
)
534 except ValueError, e
:
536 self
.getSortedForms().insert(i
, form
)
537 self
.notifyModification()
540 def removeFromSortedForms(self
, form
):
542 self
.getSortedForms().remove(form
)
543 except ValueError, e
:
545 self
.notifyModification()
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:
553 lconf
= self
.getConference().getLocator()
556 def notifyRegistrantRemoval(self
, reg
):
557 acco
= reg
.getAccommodation()
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
)
571 self
.getSessionsForm().clearSessionList()
572 TrashCanManager().add(self
)
575 TrashCanManager().remove(self
)
577 def notifyModification(self
):
579 self
._conf
.notifyModification()
581 def getETicket(self
):
584 except AttributeError:
585 self
._eTicket
= eticket
.ETicket()
589 class Notification(Persistent
):
591 self
._toList
= PersistentList()
592 self
._ccList
= PersistentList()
596 for t
in self
.getToList():
598 for c
in self
.getCCList():
605 def setToList(self
, tl
):
608 def addToList(self
, to
):
609 self
._toList
.append(to
)
611 def clearToList(self
):
612 self
._toList
= PersistentList()
617 def setCCList(self
, 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
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
):
654 except AttributeError, e
:
659 return getattr(self
, self
._iterableContainer
).__iter
__();
661 def __getitem__(self
, key
):
662 return getattr(self
, self
._iterableContainer
)[key
]
665 class FieldInputType(Persistent
):
670 def __init__(self
, field
):
676 def setValues(self
, data
):
684 setId
= classmethod(setId
)
688 getId
= classmethod(getId
)
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
:
703 return self
._parent
.getCaption()
705 def useWholeRow(self
):
706 return self
._wholeRow
708 def getMandatoryCol(self
, item
):
710 if (item
is not None and item
.isMandatory()) or self
.getParent().isMandatory():
711 mandatory
= """<span class="regFormMandatoryField">*</span>"""
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.
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.
734 item
= MiscellaneousInfoSimpleItem(mg
, self
.getParent())
735 mg
.addResponseItem(item
)
736 self
._beforeValueChange
(item
, True)
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.
759 def _getSpecialOptionsHTML(self
):
760 price
= self
._parent
.getPrice()
761 billable
= self
._parent
.isBillable()
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)")
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>
778 """) % (checked
, price
)
781 def _getDescriptionHTML(self
, description
):
782 return """<span class="inputDescription">%s</span>""" % description
785 fi
= FieldInputs().getAvailableInputKlassById(self
.getId())(gf
)
789 class TextInput(FieldInputType
, Fossilizable
):
791 fossilizes(IRegFormTextInputFieldFossil
)
797 getName
= classmethod(getName
)
799 def __init__(self
, field
):
800 FieldInputType
.__init
__(self
, field
)
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()
812 price
= item
.getPrice()
813 billable
= item
.isBillable()
814 currency
= item
.getCurrency()
815 htmlName
= item
.getHTMLName()
817 if (registrant
is not None and billable
and registrant
.getPayed()):
818 disable
= "disabled=\"true\""
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
827 length
= 'size="%s"' % self
.getLength()
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
833 tmp
= """%s %s %s</td> """ % (tmp
, price
, currency
)
835 tmp
= """%s </td> """ % tmp
837 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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
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())
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("""
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" />
865 </tr>""" % self
.getLength())
868 ti
= FieldInputType
.clone(self
, gf
)
869 ti
.setLength(self
.getLength())
874 d
["length"] = self
.getLength()
877 def setValues(self
, data
):
878 if data
.has_key("length"):
879 self
.setLength(data
.get("length"))
883 if self
._length
: pass
884 except AttributeError:
888 def setLength(self
, value
):
892 class TelephoneInput(FieldInputType
, Fossilizable
):
894 fossilizes(IRegFormTelephoneInputFieldFossil
)
897 _REGEX
= r
'^(\(\+\d*\)|\+)?\s*(\d(\s*|\-))+$'
898 _PATTERN
= re
.compile(_REGEX
)
902 getName
= classmethod(getName
)
904 def __init__(self
, field
):
905 FieldInputType
.__init
__(self
, field
)
908 def _getModifHTML(self
, item
, registrant
, default
=""):
909 description
= self
._parent
.getDescription()
910 htmlName
= self
.getHTMLName()
915 htmlName
= item
.getHTMLName()
918 if self
._parent
.isMandatory():
920 addParam($E('%s'), 'text', false, function(value) {
921 if (!/%s/.test(value)) {
922 return "Invalid phone number format";
925 </script>""" % (htmlName
, TelephoneInput
._REGEX
)
929 length
= 'size="%s"' % self
.getLength()
932 format
= """ <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
936 tmp
= """%s</tr><tr><td>%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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
)
952 item
.setMandatory(self
.getParent().isMandatory())
953 item
.setHTMLName(self
.getHTMLName())
955 def _getSpecialOptionsHTML(self
):
956 return i18nformat("""
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" />
962 </tr>""" % self
.getLength())
965 ti
= FieldInputType
.clone(self
, gf
)
966 ti
.setLength(self
.getLength())
971 d
["length"] = self
.getLength()
974 def setValues(self
, data
):
975 if data
.has_key("length"):
976 self
.setLength(data
.get("length"))
982 except AttributeError:
986 def setLength(self
, value
):
990 class TextareaInput(FieldInputType
, Fossilizable
):
992 fossilizes(IRegFormTextareaInputFieldFossil
)
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()
1012 if item
is not None:
1014 price
= item
.getPrice()
1015 billable
= item
.isBillable()
1016 currency
= item
.getCurrency()
1017 htmlName
= item
.getHTMLName()
1019 if (registrant
is not None and billable
and registrant
.getPayed()):
1020 disable
= "disabled=\"true\""
1024 desc
= """%s<br/>""" % self
._getDescriptionHTML
(description
)
1028 if self
._parent
.isMandatory():
1029 param
= """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
1032 cols
= self
.getNumberOfColumns()
1035 rows
= self
.getNumberOfRows()
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
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
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())
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("""
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" />
1069 </tr>""") % self
.getNumberOfRows()]
1071 html
.append(i18nformat("""
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" />
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())
1086 def getValues(self
):
1088 d
["numberOfRows"] = self
.getNumberOfRows()
1089 d
["numberOfColumns"] = self
.getNumberOfColumns()
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
):
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
):
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
)
1124 _useLabelCol
= False
1128 getName
= classmethod(getName
)
1130 def __init__(self
, field
):
1131 FieldInputType
.__init
__(self
, field
)
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:
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()
1153 extra_check
= "function(){}"
1154 param
= """<script>addParam($E('%s'), 'non_negative_int', %s, %s);</script>""" % (htmlName
, mandat
, extra_check
)
1157 if (registrant
is not None and billable
and registrant
.getPayed()):
1158 disable
= "disabled=\"true\""
1160 if self
.getLength():
1161 length
= 'size="%s"' % self
.getLength()
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
1173 subTotal
= (float(price
) * int(v
) or 0)
1174 tmp
= """%s<td align="right" align="bottom"> <span>%s %s</span><span class="regFormSubtotal">Total: <span id="subtotal-%s">%s</span> %s</span></td> """ % (tmp
, price
, currency
, htmlName
, subTotal
, currency
)
1176 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
1179 def _setResponseValue(self
, item
, params
, registrant
, override
=False, validate
=True):
1180 v
= params
.get(self
.getHTMLName(), "")
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
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:
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()
1210 checked
= "checked=\"checked\""
1212 return i18nformat("""
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" />
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" />
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)")
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>
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())
1244 def getValues(self
):
1246 d
["length"] = self
.getLength()
1247 d
["minValue"] = self
.getMinValue()
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
):
1258 if self
._length
: pass
1259 except AttributeError:
1263 def setLength(self
, value
):
1264 self
._length
= value
1266 def getMinValue(self
):
1268 if self
._minValue
: pass
1269 except AttributeError:
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
)
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()
1297 if item
is not None:
1299 price
= item
.getPrice()
1300 billable
= item
.isBillable()
1301 currency
= item
.getCurrency()
1303 tmp
= """ <td align="right" valign="bottom">"""
1305 tmp
= """%s %s %s</td> """ % (tmp
, price
, currency
)
1307 tmp
= """%s </td> """ % tmp
1309 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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
1318 #item.setQuantity(0)
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())
1333 class CheckboxInput(FieldInputType
, Fossilizable
):
1335 fossilizes(IRegFormCheckboxInputFieldFossil
)
1338 _useLabelCol
= False
1341 return "Multiple choices/checkbox"
1342 getName
= classmethod(getName
)
1344 def _getModifHTML(self
, item
, registrant
, default
=""):
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()
1356 if item
is not None:
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\""
1367 checked
= "checked=\"checked\""
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
1374 tmp
= """%s %s %s """ % (tmp
, price
, currency
)
1375 if self
.getParent().getPlacesLimit():
1376 tmp
+= """ <span class='placesLeft'>[%s place(s) left]</span>""" % (self
.getParent().getNoPlacesLeft())
1379 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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
1388 if params
.has_key(self
.getHTMLName()):
1389 item
.setValue("yes")
1391 elif not override
and self
.getParent().isMandatory():
1392 raise FormValuesError(_('The checkbox "%s" is mandatory. Please enable it.') % self
.getParent().getCaption())
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>
1409 </tr>""") % (self
._parent
.getPlacesLimit())
1413 class YesNoInput(FieldInputType
, Fossilizable
):
1415 fossilizes(IRegFormYesNoInputFieldFossil
)
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()
1430 if item
is not None:
1432 price
= item
.getPrice()
1433 billable
= item
.isBillable()
1434 currency
= item
.getCurrency()
1435 htmlName
= item
.getHTMLName()
1438 if self
._parent
.isMandatory():
1439 param
= """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
1445 if (registrant
is not None and billable
and registrant
.getPayed()):
1446 disable
= "disabled=\"true\""
1449 checkedYes
= "selected"
1451 checkedNo
= "selected"
1454 if self
.getParent().getPlacesLimit():
1455 placesInfo
= """ [%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
1461 tmp
= """%s %s %s</td> """ % (tmp
, price
, currency
)
1463 tmp
= """%s </td> """ % tmp
1465 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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()):
1472 #######################
1473 # if the registrant has already payed, Indico blocks all the modifications about new/removed items
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())
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>
1498 </tr>""") % (self
._parent
.getPlacesLimit())
1502 class FileInput(FieldInputType
, Fossilizable
):
1504 fossilizes(IRegFormFileInputFieldFossil
)
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
)
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
)
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):
1542 registrant
.deleteFile(item
.getValue().getId())
1545 if not newValueEmpty
:
1546 f
= registrant
.saveFile(v
)
1549 def _getSpecialOptionsHTML(self
):
1552 def clone(self
, gf
):
1553 ti
= FieldInputType
.clone(self
, gf
)
1557 class RadioItem(Persistent
, Fossilizable
):
1559 fossilizes(IRegFormRadioItemFossil
)
1561 def __init__(self
, parent
):
1562 self
._parent
= parent
1565 self
._billable
= False
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"])
1586 def setId(self
, id):
1589 def getCaption(self
):
1590 return self
._caption
1592 def setCaption(self
, cap
):
1593 if self
._caption
!= cap
:
1594 self
.updateRegistrantSelection(cap
)
1597 def setEnabled(self
, en
=True):
1600 def isEnabled(self
):
1602 return self
._enabled
1605 return self
._enabled
1607 def isBillable(self
):
1609 return self
._billable
1611 self
._billable
= False
1612 return self
._billable
1614 def setBillable(self
, v
):
1621 self
.setPrice(False)
1624 def setPrice(self
, price
):
1626 match
= PRICE_PATTERN
.match(price
)
1628 price
= match
.group(1)
1630 raise MaKaCError(_('The price is in incorrect format!'))
1633 def getPlacesLimit(self
):
1635 if self
._placesLimit
:
1637 except AttributeError, e
:
1638 self
._placesLimit
= 0
1639 return self
._placesLimit
1641 def setPlacesLimit(self
, limit
):
1647 raise FormValuesError(_("Please enter a number for the limit of places"))
1648 self
._placesLimit
= l
1649 self
.updateCurrentNoPlaces()
1651 def getCurrentNoPlaces(self
):
1653 if self
._currentNoPlaces
:
1655 except AttributeError:
1656 self
._currentNoPlaces
= 0
1657 return self
._currentNoPlaces
1659 def hasAvailablePlaces(self
):
1660 if not self
.getPlacesLimit():
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
1682 regform
= gsf
.getRegistrationForm()
1683 for reg
in regform
.getConference().getRegistrantsList():
1684 mg
= reg
.getMiscellaneousGroupById(gsf
.getId())
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
1696 regform
= gsf
.getRegistrationForm()
1697 for reg
in regform
.getConference().getRegistrantsList():
1698 mg
= reg
.getMiscellaneousGroupById(gsf
.getId())
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())
1715 def _cmpCaption(r1
, r2
):
1716 return cmp(r1
.getCaption(), r2
.getCaption())
1717 _cmpCaption
= staticmethod(_cmpCaption
)
1720 class RadioGroupInput(FieldInputType
, Fossilizable
):
1722 fossilizes(IRegFormRadioGroupInputFieldFossil
)
1727 return "Multiple options/One choice"
1728 getName
= classmethod(getName
)
1730 def __init__(self
, field
):
1731 FieldInputType
.__init
__(self
, field
)
1733 self
._radioItemGenerator
= Counter()
1734 self
._defaultItem
= None
1735 self
._inputType
= "radiogroup"
1736 self
._emptyCaption
= '-- Choose a value --'
1738 def getValues(self
):
1740 d
["radioitems"] = []
1741 for i
in self
.getItemsList():
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()
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'))
1760 self
.createItem(itemValues
, i
)
1762 # remove else set and move
1763 if 'remove' in itemValues
:
1764 self
.removeItem(item
)
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
)
1786 selected
.increaseNoPlaces()
1788 def getSelectedItem(self
, item
):
1789 for val
in self
.getItemsList():
1790 if val
.getCaption() == item
.getValue():
1794 def getDefaultItem(self
):
1796 if self
._defaultItem
:
1798 except AttributeError, e
:
1799 self
._defaultItem
= None
1800 return self
._defaultItem
1802 def setDefaultItem(self
, caption
):
1804 self
._defaultItem
= None
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():
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)
1830 def setInputType(self
, inputType
):
1831 self
._inputType
= inputType
1833 def getInputType(self
):
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()
1846 def addItem(self
, item
, i
=None):
1848 i
= len(self
.getItemsList())
1849 if item
in self
.getItemsList():
1850 self
.removeItem(item
)
1852 item
.setId(str(self
._getRadioItemGenerator
().newCount()))
1854 self
.getItemsList().insert(i
, item
)
1855 self
.notifyModification()
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():
1883 def notifyModification(self
):
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())
1894 def _getRadioItemGenerator(self
):
1895 return self
._radioItemGenerator
1897 def getEmptyCaption(self
):
1899 return self
._emptyCaption
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()
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>"""]
1918 for val
in self
.getItemsList():
1920 itemId
= "%s_%s" % (self
.getHTMLName(), counter
)
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\""
1929 if val
.getCaption() == value
:
1931 elif not value
and val
.getCaption() == self
.getDefaultItem():
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(""" %s %s""" % (val
.getPrice(), currency
))
1936 tmp
.append("""</td><td align="right" style="vertical-align: bottom;" >""")
1937 if val
.getPlacesLimit():
1938 tmp
.append(""" <span class='placesLeft'>[%s place(s) left]</span>""" % (val
.getNoPlacesLeft()))
1939 tmp
.append(""" </td></tr> """)
1942 tmp
.append("""<tr><td></td><td colspan="2">%s</td></tr>""" % (self
._getDescriptionHTML
(description
)))
1944 if self
._parent
.isMandatory():
1946 for (var i=1; i<=%s; i++) {
1947 var item = $E('%s_' + i);
1948 if (item.dom.checked) {
1952 new AlertPopup($T("Warning"), $T('You must select option for "%s"!')).open();
1954 """ % (counter
, self
.getHTMLName(), caption
)
1955 script
= """<script>addValidator(function() {%s});</script>""" % validator
1960 def _getDropDownModifHTML(self
, item
, registrant
, default
=""):
1961 description
= self
._parent
.getDescription()
1962 billable
= self
._parent
.isBillable()
1963 currency
= self
._parent
.getParent().getRegistrationForm().getCurrency()
1965 if item
is not None:
1966 billable
= item
.isBillable()
1967 currency
= item
.getCurrency()
1968 value
= item
.getValue()
1971 value
= self
.getDefaultItem()
1973 if self
._parent
.isMandatory():
1974 param
= """<script>addParam($E('%s'), 'text', false);</script>""" % self
.getHTMLName()
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()):
1987 if radioItem
.getPlacesLimit():
1988 placesInfo
= """ [%s place(s) left]""" % (radioItem
.getNoPlacesLeft())
1991 if (not radioItem
.hasAvailablePlaces() and radioItem
.getCaption() != value
):
1992 disabled
= " disabled='disabled'"
1995 if radioItem
.getCaption() == value
:
1996 selected
= " selected='selected'"
2000 if radioItem
.isBillable():
2001 price
= """ %s %s """ % (radioItem
.getPrice(), currency
)
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
)
2010 tmp
.append("""<tr><td colspan="2">%s</td></tr>""" % (self
._getDescriptionHTML
(description
)))
2014 def _getModifHTML(self
, item
, registrant
, default
=""):
2015 if self
.getInputType() == 'radiogroup':
2016 return self
._getRadioGroupModifHTML
(item
, registrant
, default
)
2018 return self
._getDropDownModifHTML
(item
, registrant
, default
)
2020 def _setResponseValue(self
, item
, params
, registrant
, override
=False, validate
=True):
2021 radioitemid
= params
.get(self
.getHTMLName(), "")
2023 for val
in self
.getItemsList():
2024 if val
.isBillable():
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
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())
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()
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
= ''
2058 dropdownSelected
= ' selected="selected"'
2059 if self
.getParent().isLocked('input'):
2060 typeDisabled
= ' disabled="disabled"'
2063 html
= [i18nformat("""
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>
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">
2081 <td class="blacktext"><span class="titleCellFormat"> _("Caption")</span></td>
2082 <td bgcolor="white" class="blacktext" width="100%%">
2083 <input type="text" name="newradioitem">
2087 <td class="blacktext"><span class="titleCellFormat"> _("Billable")</span></td>
2088 <td bgcolor="white" class="blacktext" width="100%%">
2089 <input type="checkbox" name="newbillable" >
2093 <td class="blacktext"><span class="titleCellFormat"> _("Price")</span></td>
2094 <td bgcolor="white" class="blacktext" width="100%%">
2095 <input type="text" name="newprice">
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
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>
2115 """) % inlineContextHelp(_('Use 0 for unlimited places')))
2116 html
.append("""<tr><td valign="top" align="left"><table>""")
2118 for v
in self
.getItemsList():
2120 if v
.getPlacesLimit():
2121 placesInfo
= " (%s places)" % (v
.getPlacesLimit())
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
))
2129 html
.append(i18nformat("""<span class="titleCellFormat"> _("Price"):%s</span>""") % (v
.getPrice()))
2130 if not v
.isEnabled():
2131 html
.append("""<span><font color="red"> (""" + _("disabled") + """)</font></span>""")
2132 if v
.getCaption() == self
.getDefaultItem():
2133 html
.append("""<span><font color="green"> (""" + _("default") + """)</font></span>""")
2138 html
.append("""</table></td></tr>""")
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
)
2153 getName
= classmethod(getName
)
2155 def getValueDisplay(self
, value
):
2156 return CountryHolder().getCountryById(value
)
2158 def getCountriesList(self
):
2160 for countryKey
in CountryHolder().getCountrySortedKeys():
2162 country
["countryKey"] = countryKey
2163 country
["caption"] = CountryHolder().getCountryById(countryKey
)
2164 countryList
.append(country
)
2167 def _getModifHTML(self
, item
, registrant
, default
=""):
2168 description
= self
._parent
.getDescription()
2169 htmlName
= self
.getHTMLName()
2171 if item
is not None:
2172 value
= item
.getValue()
2173 htmlName
= item
.getHTMLName()
2176 if self
._parent
.isMandatory():
2177 param
= """<script>addParam($E('%s'), 'text', false);</script>""" % htmlName
2181 inputHTML
= i18nformat("""<option value="">-- _("Select a country") --</option>""")
2182 for countryKey
in CountryHolder().getCountrySortedKeys():
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
2191 tmp
= """%s</tr><tr><td colspan="2">%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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())
2201 item
.setMandatory(self
.getParent().isMandatory())
2202 item
.setHTMLName(self
.getHTMLName())
2204 def _getSpecialOptionsHTML(self
):
2208 class DateInput(FieldInputType
, Fossilizable
):
2210 fossilizes(IRegFormDateInputFieldFossil
)
2214 def __init__(self
, field
):
2215 FieldInputType
.__init
__(self
, field
)
2216 self
.dateFormat
= ''
2220 getName
= classmethod(getName
)
2222 def getValues(self
):
2224 d
["dateFormat"] = self
.getDateFormat()
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()
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'),
2261 def getValueDisplay(self
, value
):
2262 if type(value
) == datetime
:
2263 return value
.strftime(self
.getDateFormat())
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()
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
= """ <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
2294 tmp
= """%s</tr><tr><td>%s</td>""" % (tmp
, self
._getDescriptionHTML
(description
))
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
2306 date
= datetime(int(year
), int(month
), int(day
), int(hour
), int(minute
))
2308 elif not self
._parent
.isMandatory():
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("""
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"'
2330 html
.append("""<option value="%s"%s>%s</option>""" % (format
, selected
, display
))
2332 html
.append(_("""</select>
2335 return "".join(html
)
2337 def _getFormatDisplayText(self
):
2338 formats
= self
.getDisplayFormats()
2341 for dateFormat
, display
in formats
:
2342 if self
.getDateFormat() == dateFormat
:
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
2384 self
._caption
= "General Field"
2385 self
._input
= FieldInputs
.getAvailableInputKlassById("text")(self
)
2386 self
._input
.setValues(data
)
2387 self
._mandatory
= False
2389 self
._description
= ""
2390 self
._billable
= False
2392 self
._placesLimit
= 0
2393 self
._currentNoPlaces
= 0
2394 self
._disabled
= True
2395 self
._pdField
= None
2397 self
._mandatory
= False
2398 self
.setValues(data
, True)
2400 def clone(self
, newsection
):
2401 field
= GeneralField(newsection
, self
.getValues())
2404 def setValues(self
, data
, firstTime
=False):
2405 caption
= data
.get("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
))
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"])
2419 self
._input
.setValues(data
)
2421 self
.setLocked(data
.get("lock", ()))
2422 if self
.isMandatory() and self
.isLocked('mandatory'):
2423 self
.setMandatory(True)
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", ""))
2435 self
.setPDField(data
.get("pd"))
2437 def getValues(self
):
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()
2452 def isTemporary(self
):
2455 def setPDField(self
, v
):
2458 def getPDField(self
):
2460 return self
._pdField
2462 self
._pdField
= None
2463 return self
._pdField
2465 def isBillable(self
):
2467 return self
._billable
2469 self
._billable
= False
2470 return self
._billable
2472 def setBillable(self
, v
):
2482 def setPrice(self
, price
):
2484 match
= PRICE_PATTERN
.match(price
)
2486 price
= match
.group(1)
2488 raise MaKaCError(_('The price is in incorrect format!'))
2491 def getPlacesLimit(self
):
2493 if self
._placesLimit
:
2495 except AttributeError, e
:
2496 self
._placesLimit
= 0
2497 return self
._placesLimit
2499 def setPlacesLimit(self
, limit
):
2505 raise FormValuesError(_("Please enter a number for the limit of places"))
2506 self
._placesLimit
= l
2507 self
.updateCurrentNoPlaces()
2509 def getCurrentNoPlaces(self
):
2511 if self
._currentNoPlaces
:
2513 except AttributeError:
2514 self
._currentNoPlaces
= 0
2515 return self
._currentNoPlaces
2517 def hasAvailablePlaces(self
):
2518 if not self
.getPlacesLimit():
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
2542 for reg
in self
._parent
.getRegistrationForm().getConference().getRegistrantsList():
2543 mg
= reg
.getMiscellaneousGroupById(self
._parent
.getId())
2545 item
= mg
.getResponseItemById(self
.getId())
2546 if item
is not None and item
.getQuantity():
2547 self
.increaseNoPlaces()
2552 def setId(self
, id):
2555 def getCaption(self
):
2556 return self
._caption
2558 def setCaption(self
, caption
):
2559 self
._caption
= caption
2561 def getDescription(self
):
2563 if self
._description
:
2565 except AttributeError:
2566 self
._description
= ''
2567 return self
._description
2569 def setDescription(self
, description
):
2570 self
._description
= description
2575 def setInput(self
, input):
2578 def isMandatory(self
):
2579 return self
._mandatory
2581 def setMandatory(self
, v
):
2584 def getLocked(self
):
2591 def isLocked(self
, what
):
2592 return what
in self
.getLocked()
2594 def setLocked(self
, v
):
2597 def isDisabled(self
):
2599 return self
._disabled
2601 self
._disabled
= False
2602 return self
._disabled
2604 def setDisabled(self
, v
):
2607 def getParent(self
):
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:
2615 lconf
= self
.getParent().getLocator()
2616 lconf
["sectionFieldId"] = self
.getId()
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
2628 self
._title
= _("Miscellaneous information")
2629 self
._description
= ""
2630 self
._required
= required
2633 #Mods to support sorting 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()
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
):
2654 values
["title"] = self
.getTitle()
2655 values
["description"] = self
.getDescription()
2656 values
["enabled"] = self
.isEnabled()
2657 values
["required"] = self
.isRequired()
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
))
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
2685 def setId(self
, id):
2691 def setTitle(self
, title
):
2694 def getDescription(self
):
2695 return self
._description
2697 def setDescription(self
, description
):
2698 self
._description
= description
2700 def isRequired(self
):
2702 return self
._required
2704 self
._required
= False
2707 def setRequired(self
, required
):
2708 self
._required
= required
2710 def getSortedFields(self
):
2712 returnFields
= self
._sortedFields
2713 except AttributeError:
2714 self
._sortedFields
= self
._fields
2715 returnFields
= self
._sortedFields
2718 def addToSortedFields(self
, f
, i
=None):
2720 i
= len(self
.getSortedFields())
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()
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():
2740 def getFieldPosById(self
, id):
2741 for ind
, f
in enumerate(self
.getSortedFields()):
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:
2754 lconf
= self
.getRegistrationForm().getLocator()
2755 lconf
["sectionFormId"] = self
.getId()
2758 def notifyModification(self
):
2762 class PersonalDataForm(GeneralSectionForm
):
2763 def __init__(self
, regForm
, createFields
=True):
2764 GeneralSectionForm
.__init
__(self
, regForm
, {'title': 'Personal Data'}, True)
2771 'inputType':'dropdown',
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') },
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():
2805 pf
.addToSortedFields(f
)
2807 pf
._pdMap
[f
.getPDField()] = f
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'])
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()
2833 def getFormValuesFromAvatar(self
, av
):
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()
2848 class PersonalDataFormItem(Persistent
): # old
2850 def __init__(self
, data
=None):
2855 self
._mandatory
= False
2856 self
._enabled
= True
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)
2867 def setId(self
, id):
2873 def setName(self
, name
):
2876 def isEnabled(self
):
2878 return self
._enabled
2881 return self
._enabled
2883 def setEnabled(self
, enabled
=True):
2884 self
._enabled
= enabled
2890 def setInput(self
, input):
2893 def isMandatory(self
):
2894 return self
._mandatory
2896 def setMandatory(self
, v
):
2901 class PersonalData(Persistent
):
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())
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())
2957 def getSortedKeys(self
):
2958 return self
._sortedKeys
2960 def getMandatoryItems(self
):
2962 for i
in self
.getSortedKeys():
2963 if self
.getData()[i
].isMandatory() and self
.getData()[i
].isEnabled():
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"
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"
2988 except AttributeError, e
:
2989 self
._id
= "furtherInformation"
2992 def setValues(self
, data
):
2993 self
.setTitle(data
.get("title", "Further Information"))
2994 self
.setContent(data
.get("content", ""))
2996 def getValues(self
):
2998 values
["title"] = self
.getTitle()
2999 values
["content"] = self
.getContent()
3000 values
["enabled"] = self
.isEnabled()
3004 fif
= FurtherInformationForm()
3005 fif
.setValues(self
.getValues())
3006 fif
.setEnabled(self
.isEnabled())
3012 def setTitle(self
, 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
3028 class AccommodationType(Persistent
, Fossilizable
):
3030 fossilizes(IRegFormAccommodationTypeItemFossil
)
3032 def __init__(self
, rf
, data
=None):
3036 self
._cancelled
= False
3037 self
._placesLimit
= 0
3038 self
._currentNoPlaces
= 0
3039 self
._billable
= False
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
):
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()
3062 def clone(self
, registrationForm
):
3063 act
= AccommodationType(registrationForm
)
3064 act
.setValues(self
.getValues())
3070 def setId(self
, id):
3073 def getCaption(self
):
3074 return self
._caption
3076 def setCaption(self
, c
):
3079 def getPlacesLimit(self
):
3081 if self
._placesLimit
:
3083 except AttributeError, e
:
3084 self
._placesLimit
= 0
3085 return self
._placesLimit
3087 def setPlacesLimit(self
, 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
):
3099 if self
._currentNoPlaces
:
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
3108 if self
.getCurrentNoPlaces() >= self
.getPlacesLimit():
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
):
3140 def isCancelled(self
):
3144 except AttributeError, e
:
3145 self
._cancelled
= False
3146 return self
._cancelled
3148 def setCancelled(self
, v
):
3151 def isBillable(self
):
3153 return self
._billable
3155 self
._billable
= False
3156 return self
._billable
3158 def setBillable(self
, v
):
3168 def setPrice(self
, price
):
3170 match
= PRICE_PATTERN
.match(price
)
3172 price
= match
.group(1)
3174 raise MaKaCError(_('The price is in incorrect format!'))
3177 def getCurrency(self
):
3178 return self
._regForm
.getCurrency()
3181 self
.setCancelled(True)
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:
3197 lconf
= self
.getRegistrationForm().getLocator()
3198 lconf
["accoTypeId"] = self
.getId()
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]
3227 except AttributeError, e
:
3228 self
._id
= "accommodation"
3231 def getConference(self
):
3232 return self
._regForm
.getConference()
3234 def getArrivalOffsetDates(self
):
3236 return self
._arrivalOffsetDates
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()
3248 curDate
= startDate
= conf
.getStartDate() + timedelta(days
=offsets
[0])
3249 endDate
= conf
.getEndDate() + timedelta(days
=offsets
[1])
3250 if startDate
.date() > endDate
.date():
3252 while curDate
.date() <= endDate
.date():
3253 dates
.append(curDate
)
3254 curDate
+= timedelta(days
=1)
3257 def setArrivalOffsetDates(self
, dates
):
3258 self
._arrivalOffsetDates
= dates
3260 def getDepartureOffsetDates(self
):
3262 return self
._departureOffsetDates
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()
3274 curDate
= startDate
= conf
.getStartDate() + timedelta(days
=offsets
[0])
3275 endDate
= conf
.getEndDate() + timedelta(days
=offsets
[1])
3276 if startDate
> endDate
:
3278 while curDate
<= endDate
:
3279 dates
.append(curDate
)
3280 curDate
+= timedelta(days
=1)
3283 def setDepartureOffsetDates(self
, dates
):
3284 self
._departureOffsetDates
= dates
3286 def _setDefaultAccommodationTypes(self
):
3287 a
= AccommodationType(self
._regForm
)
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
):
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]
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
))
3329 def setTitle(self
, 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
3345 return str(self
._accoTypeGenerator
.newCount())
3347 self
._accoTypeGenerator
= Counter()
3348 return str(self
._accoTypeGenerator
.newCount())
3350 def addAccommodationType(self
, accom
):
3353 id = self
._generateNewAccoTypeId
()
3355 self
._accommodationTypes
[id] = accom
3357 def removeAccommodationType(self
, accom
):
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]
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"
3396 except AttributeError, e
:
3397 self
._id
= "reasonParticipation"
3400 def setValues(self
, data
):
3401 self
.setTitle(data
.get("title", "Reason for participation"))
3402 self
.setDescription(data
.get("description", ""))
3404 def getValues(self
):
3406 values
["title"] = self
.getTitle()
3407 values
["description"] = self
.getDescription()
3411 rpf
= ReasonParticipationForm()
3412 rpf
.setValues(self
.getValues())
3413 rpf
.setEnabled(self
.isEnabled())
3419 def setTitle(self
, title
):
3422 def getDescription(self
):
3423 return self
._description
3425 def setDescription(self
, description
):
3426 self
._description
= description
3429 #No items for this form
3433 class RegistrationSession(Persistent
, Fossilizable
):
3435 fossilizes(IRegFormRegistrationSessionItemFossil
)
3437 def __init__(self
, ses
, regForm
=None):
3439 self
._session
.setRegistrationSession(self
)
3440 self
._regForm
= regForm
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
):
3451 if self
.isBillable():
3452 data
["billable"] = True
3453 data
["price"] = self
.getPrice()
3456 def getSession(self
):
3457 return self
._session
3459 def setSession(self
, ses
):
3461 self
._billable
= ses
.isBillable()
3462 self
._price
= ses
.getPrice()
3464 def getRegistrationForm(self
):
3465 return self
._regForm
3467 def setRegistrationForm(self
, 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()
3476 def getConference(self
):
3477 if self
._regForm
is not None:
3478 return self
._regForm
.getConference()
3482 #self._session.setRegistrationSession(None)
3483 self
.setRegistrationForm(None)
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()
3492 return self
._session
.getId()
3495 return self
._session
.getTitle()
3497 # for compatibility with other fields
3498 getCaption
= getTitle
3500 def getStartDate(self
):
3501 return self
._session
.getStartDate()
3504 return self
._session
.getCode()
3513 def setPrice(self
, price
):
3515 match
= PRICE_PATTERN
.match(price
)
3517 price
= match
.group(1)
3519 raise MaKaCError(_('The price is in incorrect format!'))
3522 def isBillable(self
):
3524 return self
._billable
3526 self
._billable
= False
3527 return self
._billable
3529 def setBillable(self
, 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)
3536 self
._currency
= self
._regForm
.getCurrency()
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:
3546 lconf
= self
.getRegistrationForm().getLocator()
3547 lconf
["sessionId"] = self
.getId()
3551 def _cmpTitle(s1
, s2
):
3552 if s1
is None and s2
is not None:
3554 elif s1
is not None and s2
is None:
3556 elif s1
is None and s2
is None:
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"
3583 except AttributeError, e
:
3584 self
._id
= "sessions"
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())
3596 s
.setValues(ses
.getValues())
3601 def getValues(self
):
3603 data
["title"] = self
.getTitle()
3604 data
["description"] = self
.getDescription()
3605 data
["enabled"] = self
.isEnabled()
3606 data
["type"] = self
.getType()
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"))
3617 def setTitle(self
, title
):
3620 def getDescription(self
):
3621 return self
._description
3623 def setDescription(self
, description
):
3624 self
._description
= description
3630 except AttributeError, e
:
3631 self
._type
= "2priorities"
3634 def setType(self
, type):
3637 def getSessionsFromParams(self
, params
):
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:
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
)
3662 lv
.sort(RegistrationSession
._cmpTitle
)
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):
3698 self
._caption
= "--no caption--"
3700 self
._cancelled
= False
3701 self
._cancelledReason
= ""
3702 self
._maxPlacePerRegistrant
= 10
3703 self
._placesLimit
= 0
3704 self
._currentNoPlaces
= 0
3705 self
._billable
= False
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
:
3718 maxPlace
= int(data
["maxPlace"])
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"])
3731 self
.setPrice(data
["price"])
3733 def getValues(self
):
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()
3748 def clone(self
, regForm
):
3749 newSEI
= SocialEventItem(regForm
)
3750 newSEI
.setValues(self
.getValues())
3756 def setId(self
, id):
3759 def getCaption(self
):
3760 return self
._caption
3762 def setCaption(self
, c
):
3765 def getPlacesLimit(self
):
3767 if self
._placesLimit
:
3769 except AttributeError, e
:
3770 self
._placesLimit
= 0
3771 return self
._placesLimit
3773 def setPlacesLimit(self
, 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
):
3785 if self
._currentNoPlaces
:
3787 except AttributeError, e
:
3788 self
._currentNoPlaces
= 0
3789 return self
._currentNoPlaces
3791 def hasAvailablePlaces(self
):
3792 if self
.getCurrentNoPlaces() >= self
.getPlacesLimit():
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
):
3826 def isCancelled(self
):
3830 except AttributeError, e
:
3831 self
._cancelled
= False
3832 return self
._cancelled
3834 def setCancelled(self
, v
):
3837 def getCancelledReason(self
):
3839 if self
._cancelledReason
:
3841 except AttributeError:
3842 self
._cancelledReason
= ""
3843 return self
._cancelledReason
3845 def setCancelledReason(self
, cr
):
3846 self
._cancelledReason
= cr
3848 def getMaxPlacePerRegistrant(self
):
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
):
3860 return self
._billable
3862 self
._billable
= False
3863 return self
._billable
3865 def setBillable(self
, v
):
3868 def isPricePerPlace(self
):
3870 return self
._pricePerPlace
3872 self
._pricePerPlace
= False
3873 return self
._pricePerPlace
3875 def setPricePerPlace(self
, v
):
3876 self
._pricePerPlace
= v
3885 def setPrice(self
, price
):
3887 match
= PRICE_PATTERN
.match(price
)
3889 price
= match
.group(1)
3891 raise MaKaCError(_('The price is in incorrect format!'))
3894 def getCurrency(self
):
3895 return self
._regForm
.getCurrency()
3898 self
.setCancelled(True)
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:
3914 lconf
= self
.getRegistrationForm().getLocator()
3915 lconf
["socialEventId"] = self
.getId()
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"
3949 except AttributeError, e
:
3950 self
._id
= "socialEvents"
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
):
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()
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
))
3981 def setTitle(self
, title
):
3984 def getDescription(self
):
3985 return self
._description
3987 def setDescription(self
, description
):
3988 self
._description
= description
3990 def getMandatory(self
):
3992 return self
._mandatory
3993 except AttributeError:
3994 self
._mandatory
= False
3997 def setMandatory(self
, value
):
3998 self
._mandatory
= value
4000 def getRegistrationForm(self
):
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()
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
):
4018 if self
._introSentence
:
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
):
4029 if self
._selectionTypeList
:
4031 except AttributeError, e
:
4032 self
._selectionTypeList
= {"multiple": "Multiple choice",
4033 "unique": "Unique choice"}
4034 return self
._selectionTypeList
4036 def _getSelectionType(self
):
4038 if self
._selectionType
:
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
4057 return str(self
._socialEventItemGenerator
.newCount())
4059 self
._socialEventItemGenerator
= Counter()
4060 return str(self
._socialEventItemGenerator
.newCount())
4062 def addSocialEvent(self
, se
):
4065 id = self
._generateNewSocialEventItemId
()
4067 self
._socialEvents
[id] = se
4069 def removeSocialEvent(self
, se
):
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]
4083 def getSocialEventList(self
, sort
=False):
4084 v
= self
._socialEvents
.values()
4086 v
.sort(SocialEventItem
._cmpCaption
)
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:
4098 lconf
= self
.getConference().getLocator()
4099 lconf
["sectionFieldId"] = self
.getId()
4103 class StatusValue(Persistent
):
4105 def __init__(self
, st
, data
=None):
4109 if data
is not None:
4110 self
.setValues(data
)
4112 def getValues(self
):
4114 d
["caption"] = self
.getCaption()
4117 def setValues(self
, d
):
4118 self
.setCaption(d
.get("caption", "-- no caption --"))
4123 def setId(self
, id):
4126 def getCaption(self
):
4127 return self
._caption
4129 def setCaption(self
, cp
):
4132 def clone(self
, st
):
4133 sv
= StatusValue(st
)
4134 sv
.setCaption(self
.getCaption())
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()
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", ""))
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)
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
):
4181 d
["caption"] = self
.getCaption()
4184 def getConference(self
):
4185 return self
._regForm
.getConference()
4193 def getCaption(self
):
4194 return self
._caption
4196 def setCaption(self
, 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
4209 return str(self
._valuesGenerator
.newCount())
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()
4220 r
.sort(StatusValue
._cmpCaption
)
4223 def hasStatusValue(self
, v
):
4224 if v
is not None and self
.getStatusValues().has_key(v
.getId()):
4228 def getStatusValueById(self
, id):
4229 if self
.getStatusValues().has_key(id):
4230 return self
.getStatusValues()[id]
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:
4252 lconf
= self
.getConference().getLocator()
4253 lconf
["statusId"] = self
.getId()
4256 def notifyModification(self
):
4257 """Method called to notify that the registration form has been modified.
4262 # Users --------- FINAL INFORMATION STORED FROM THE REGISTRATION FORM
4264 class Registrant(Persistent
, Fossilizable
):
4266 fossilizes(IRegFormRegistrantFossil
, IRegFormRegistrantBasicFossil
, IRegFormRegistrantFullFossil
)
4272 self
._complete
= False
4273 self
._registrationDate
= nowutc()
4274 self
._checkedIn
= False
4275 self
._checkInDate
= None
4276 self
._checkInUUID
= str(uuid4())
4279 self
._firstName
= ""
4282 self
._institution
= ""
4289 self
._personalHomepage
= ""
4292 self
._socialEvents
= []
4293 self
._accommodation
= Accommodation(self
)
4294 self
._reasonParticipation
= ""
4296 self
._miscellaneous
= {}
4297 self
._parmasReturn
= {}
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
):
4321 elif not self
.doPay():
4326 return "c%sr%s" % (self
._conf
.getId(), self
.getId())
4328 def setTotal(self
, total
):
4338 def getCurrency(self
):
4340 return self
._currency
4341 except AttributeError:
4342 self
._currency
= self
.getRegistrationForm().getCurrency()
4343 return self
._currency
4345 def updateTotal(self
):
4347 for gs
in self
.getRegistrationForm().getGeneralSectionFormsList():
4349 mg
= self
.getMiscellaneousGroupById(gs
.getId())
4351 for miscItem
in mg
.getResponseItemList():
4352 if miscItem
.isBillable():
4353 price
= float(miscItem
.getPrice() or 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
)
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
):
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
)
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
)
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)
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])
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():
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'))
4456 for seItem
in self
.getSocialEvents()[:]:
4457 self
.removeSocialEventById(seItem
.getId())
4458 #if not self.getPayed():
4459 # self._miscellaneous = {}
4461 for gs
in self
.getRegistrationForm().getGeneralSectionFormsList():
4463 mg
= self
.getMiscellaneousGroupById(gs
.getId())
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)
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
):
4491 except AttributeError, e
:
4492 self
._complete
= False
4493 return self
._complete
4495 def isCheckedIn(self
):
4499 except AttributeError:
4500 self
._checkedIn
= False
4501 return self
._checkedIn
4503 def setCheckedIn(self
, checkedIn
):
4505 self
._checkInDate
= nowutc()
4507 self
._checkInDate
= None
4508 self
._checkedIn
= checkedIn
4510 def getCheckInUUID(self
):
4512 if self
._checkInUUID
:
4514 except AttributeError:
4515 self
._checkInUUID
= str(uuid4())
4516 return self
._checkInUUID
4518 def getCheckInDate(self
):
4520 if self
._checkInDate
:
4522 except AttributeError:
4523 self
._checkInDate
= None
4524 return self
._checkInDate
4526 def getAdjustedCheckInDate(self
,tz
=None):
4528 tz
= self
.getConference().getTimezone()
4529 if tz
not in all_timezones
:
4531 checkInDate
= self
.getCheckInDate()
4533 return checkInDate
.astimezone(timezone(tz
))
4537 def payment_status(self
):
4538 transaction
= PaymentTransaction
.find_latest_for_registrant(self
)
4539 return transaction
.status
if transaction
else None
4542 return self
.payment_status
== TransactionStatus
.successful
4544 def _generateRandomId(self
):
4546 return md5(str(random
.random() + time
.mktime(n
.timetuple()))).hexdigest()
4548 def getRandomId(self
):
4552 except AttributeError, e
:
4553 self
._randomId
= self
._generateRandomId
()
4554 return self
._randomId
4559 def setId(self
, id):
4560 self
._id
= str(id).strip()
4562 def getConference(self
):
4565 def setConference(self
, c
):
4569 return self
.getConference()
4571 def setOwner(self
, o
):
4572 self
.setConference(o
)
4574 def getAvatar(self
):
4577 def setAvatar(self
, a
):
4578 if isinstance(self
._avatar
, AvatarUserWrapper
):
4579 self
._avatar
.unlinkTo(self
, "registrant")
4581 a
.linkTo(self
, "registrant")
4583 def getRegistrationForm(self
):
4584 return self
.getConference().getRegistrationForm()
4586 def getRegistrationDate(self
):
4588 if self
._registrationDate
:
4590 except AttributeError, e
:
4591 self
._registrationDate
= None
4592 return self
._registrationDate
4594 def getAdjustedRegistrationDate(self
, tz
=None):
4596 tz
= self
.getConference().getTimezone()
4597 if tz
not in all_timezones
:
4599 return self
.getRegistrationDate().astimezone(timezone(tz
))
4604 def setTitle(self
, v
):
4607 def getFirstName(self
):
4608 return self
._firstName
4610 def setFirstName(self
, v
):
4613 def getSurName(self
):
4614 return self
._surname
4615 getFamilyName
= getSurName
4617 def setSurName(self
, v
):
4619 setFamilyName
= setSurName
4621 def getFullName(self
, title
=True, firstNameFirst
=False):
4623 res
= "%s %s" % (self
.getFirstName(), self
.getFamilyName())
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
)
4633 def getPosition(self
):
4634 return self
._position
4636 def setPosition(self
, 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
):
4654 def setCity(self
, v
):
4657 def getCountry(self
):
4658 return self
._country
4660 def setCountry(self
, v
):
4666 def setPhone(self
, v
):
4672 def setFax(self
, v
):
4678 def setEmail(self
, 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
):
4718 if self
._socialEvents
:
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():
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)
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:
4750 lconf
= self
.getConference().getLocator()
4751 lconf
["registrantId"] = self
.getId()
4754 def notifyModification(self
):
4755 """Method called to notify the current registered participant has been modified.
4759 def _cmpFamilyName(r1
, r2
):
4760 if r1
is None and r2
is None:
4766 return cmp(r1
.getFamilyName().lower(), r2
.getFamilyName().lower())
4767 _cmpFamilyName
= staticmethod(_cmpFamilyName
)
4769 def getMiscellaneousGroups(self
):
4771 if self
._miscellaneous
:
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]
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
):
4795 return self
._sessionBillingEnabled
4797 self
.setSessionBillingEnabled(False)
4798 return self
._sessionBillingEnabled
4800 def getBilledForms(self
):
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
))
4813 def getStatuses(self
):
4817 except AttributeError, e
:
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)
4836 st
= self
._conf
.getRegistrationForm().getStatusById(id)
4837 v
= RegistrantStatus(self
, st
)
4838 if st
.getDefaultValue() is not None:
4839 v
.setStatusValue(st
.getDefaultValue())
4843 def setModificationDate(self
):
4846 def getAttachments(self
):
4848 if self
._attachments
:
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
):
4862 if self
._attachmentsCounter
:
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())
4882 file.setFileName(fileUploaded
.filename
)
4883 file.setFilePath(tempFileName
)
4885 file.setId(self
._getAttachmentsCounter
())
4886 self
.__addFile
(file)
4889 def deleteFile(self
, fileId
):
4890 file = self
.getAttachments()[fileId
]
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.
4901 def canUserModify(self
, user
):
4902 return self
.getConference().canUserModify(user
) or (user
is not None and user
== self
.getAvatar())
4904 def getCheckoutAttemptDt(self
):
4906 return self
._checkout
_attempt
_dt
4907 except AttributeError:
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
)
4918 class BilledItemsWrapper(object):
4920 def __init__(self
, 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
4932 self
._quantity
= quantity
4933 self
._currency
= currency
4935 def getCaption(self
):
4936 return self
._caption
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
4956 self
._billable
= False
4959 def isCancelled(self
):
4960 return self
._accommodationType
.isCancelled()
4962 def getRegistrant(self
):
4964 return self
._registrant
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
4992 def isBillable(self
):
4994 return self
._billable
4998 def getCurrency(self
):
5000 return self
._currency
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()
5016 at
.increaseNoPlaces()
5017 self
._price
= at
.getPrice()
5018 self
._billable
= at
.isBillable()
5019 self
._currency
= at
.getCurrency()
5022 self
._billable
= False
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 ''
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
):
5053 return self
._registrant
5057 def setRegistrant(self
, reg
):
5058 self
._registrant
= reg
5060 def getNoPlaces(self
):
5061 return self
._noPlaces
5063 def getCurrency(self
):
5065 return self
._currency
5067 self
._currency
= self
._socialEventItem
.getCurrency()
5068 return self
._currency
5076 def isBillable(self
):
5078 return self
._billable
5082 def isPricePerPlace(self
):
5084 return self
._pricePerPlace
5088 def getBilledItem(self
):
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
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()
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
5142 def isBillable(self
):
5144 return self
._billable
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()
5158 return self
._regSession
.getId()
5160 def getCaption(self
):
5161 return self
._regSession
.getCaption()
5162 getTitle
= getCaption
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
= {}
5184 def getGeneralSection(self
):
5185 return self
._generalSection
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]
5213 def clearResponses(self
, gs
=None):
5215 self
._responseItems
= {}
5216 self
.notifyModification()
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()
5230 def notifyModification(self
):
5234 class MiscellaneousInfoSimpleItem(Persistent
):
5236 def __init__(self
, group
, field
):
5238 self
._generalField
= field
5239 self
._id
= field
.getId()
5241 self
._billable
= False
5245 self
._mandatory
= False
5246 # TODO: When migrate to new database, take into account that HTMLName cannot be empty string
5249 def getHTMLName(self
):
5251 if self
._HTMLName
== "":
5252 self
._HTMLName
= self
.getGeneralField().getInput().getHTMLName()
5255 return self
._HTMLName
5257 def setHTMLName(self
, HTMLName
):
5258 self
._HTMLName
= HTMLName
5260 def isMandatory(self
):
5262 return self
._mandatory
5264 self
._mandatory
= False
5265 return self
._mandatory
5267 def setMandatory(self
, mandatory
):
5268 self
._mandatory
= mandatory
5270 def getCurrency(self
):
5272 return self
._currency
5274 self
.setCurrency("")
5275 return self
._currency
5277 def setCurrency(self
, currency
):
5278 self
._currency
= currency
5280 def getQuantity(self
):
5282 return self
._quantity
5285 return self
._quantity
5287 def setQuantity(self
, quantity
):
5288 self
._quantity
= quantity
5290 def isBillable(self
):
5292 return self
._billable
5294 self
.setBillable(False)
5295 return self
._billable
5297 def setBillable(self
, v
):
5307 def setPrice(self
, price
):
5313 def getGeneralField(self
):
5314 return self
._generalField
5316 def getCaption(self
):
5317 return self
._generalField
.getCaption()
5326 def setValue(self
, v
):
5330 class RegistrantStatus(Persistent
):
5332 def __init__(self
, reg
, st
, data
=None):
5334 self
._registrant
= reg
5336 if data
is not None:
5339 def setValues(self
, d
):
5340 self
.setStatusValue(d
.get("statusvalue", ""))
5342 def getValues(self
):
5344 d
["statusvalue"] = self
.getStatusValue()
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()
5358 def setStatusValue(self
, v
):
5362 class RegistrantMapping(object):
5364 def __init__(self
, registrant
):
5365 self
._registrant
= registrant
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:])
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()
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
)
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
)
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
)
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()
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()
5463 def _formatValue(self
, fieldInput
, value
):
5465 value
= fieldInput
.getValueDisplay(value
)
5467 value
= str(value
).strip()
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())
5478 def _getCheckedIn(self
):
5479 conf
= self
._registrant
.getConference()
5480 if not conf
.getRegistrationForm().getETicket().isEnabled():
5482 elif self
._registrant
.isCheckedIn():
5487 def _getCheckInDate(self
):
5488 checkInDate
= self
._registrant
.getAdjustedCheckInDate()
5490 return format_datetime(checkInDate
)