source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/interfaces.py @ 7260

Last change on this file since 7260 was 7260, checked in by Henrik Bettermann, 13 years ago

Let's generate the applicant_id only when the applicant is added to its container to be compliant with the generic batch processor (importer).

  • Property svn:keywords set to Id
File size: 14.0 KB
Line 
1## $Id: interfaces.py 7260 2011-12-04 07:56:39Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Interfaces of the university application package.
19"""
20
21from grokcore.content.interfaces import IContainer
22
23from zope import schema
24from zope.interface import Interface, Attribute
25from zope.component import getUtilitiesFor
26from zc.sourcefactory.basic import BasicSourceFactory
27from waeup.sirp.interfaces import (
28    IWAeUPObject, year_range, validate_email, academic_sessions_vocab)
29from waeup.sirp.university.vocabularies import application_categories
30from waeup.sirp.students.vocabularies import (
31  lgas_vocab, CertificateSource, GenderSource,
32  )
33from waeup.sirp.applicants.vocabularies import (
34  application_types_vocab, application_pins_vocab,
35  AppCatCertificateSource,
36  )
37from waeup.sirp.payments.interfaces import IOnlinePayment
38
39#: Maximum upload size for applicant passport photographs (in bytes)
40MAX_UPLOAD_SIZE = 1024 * 20
41
42class ApplicantContainerProviderSource(BasicSourceFactory):
43    """A source offering all available applicants container types.
44
45    The values returned by this source are names of utilities that can
46    create :class:`ApplicantContainer` instances. So, if you get a
47    name like ``'myactype'`` from this source, then you can do:
48
49      >>> from zope.component import getUtility
50      >>> p = getUtility(IApplicantsContainerProvider, name=myactype)
51      >>> my_applicants_container = p.factory()
52
53    Or you can access class-attributes like
54
55      >>> my_applicants_container.container_title
56      'Pretty'
57
58    """
59    def getValues(self):
60        """Returns a list of ``(<name>, <provider>)`` tuples.
61
62        Here ``<name>`` is the name under which an
63        :class:``ApplicantContainerProvider`` was registered as a
64        utility and ``<provider>`` is the utility itself.
65        """
66        return getUtilitiesFor(IApplicantsContainerProvider)
67
68    def getToken(self, value):
69        """Return the name of the ``(<name>, <provider>)`` tuple.
70        """
71        return value[0]
72
73    def getTitle(self, value):
74        """Get a 'title - description' string for a container type.
75        """
76        factory = value[1].factory
77        return "%s - %s" % (
78            factory.container_title, factory.container_description)
79
80class IApplicantsRoot(IWAeUPObject, IContainer):
81    """A container for university applicants containers.
82    """
83    pass
84
85class IApplicantsContainer(IWAeUPObject):
86    """An applicants container contains university applicants.
87
88    """
89
90    container_title = Attribute(
91        u'classattribute: title for type of container')
92    container_description = Attribute(
93        u'classattribute: description for type of container')
94
95
96    code = schema.TextLine(
97        title = u'Code',
98        default = u'-',
99        required = True,
100        readonly = True,
101        )
102
103    title = schema.TextLine(
104        title = u'Title',
105        required = True,
106        default = u'-',
107        readonly = True,
108        )
109
110    prefix = schema.Choice(
111        title = u'Application target',
112        required = True,
113        default = None,
114        source = application_types_vocab,
115        readonly = True,
116        )
117
118    year = schema.Choice(
119        title = u'Year of entrance',
120        required = True,
121        default = None,
122        values = year_range(),
123        readonly = True,
124        )
125
126    provider = schema.Choice(
127        title = u'Applicants container type',
128        required = True,
129        default = None,
130        source = ApplicantContainerProviderSource(),
131        readonly = True,
132        )
133
134    ac_prefix = schema.Choice(
135        title = u'Access code prefix',
136        required = True,
137        default = None,
138        source = application_pins_vocab,
139        )
140
141    application_category = schema.Choice(
142        title = u'Category for the grouping of certificates',
143        required = True,
144        default = None,
145        source = application_categories,
146        )
147
148    description = schema.Text(
149        title = u'Human readable description in reST format',
150        required = False,
151        default = u'''This text can been seen by anonymous users.
152Here we put information about the study courses provided, the application procedure and deadlines.'''
153        )
154
155    startdate = schema.Date(
156        title = u'Application start date',
157        required = False,
158        default = None,
159        )
160
161    enddate = schema.Date(
162        title = u'Application closing date',
163        required = False,
164        default = None,
165        )
166
167    strict_deadline = schema.Bool(
168        title = u'Forbid additions after deadline (enddate)',
169        required = True,
170        default = True,
171        )
172
173    def archive(id=None):
174        """Create on-dist archive of applicants stored in this term.
175
176        If id is `None`, all applicants are archived.
177
178        If id contains a single id string, only the respective
179        applicants are archived.
180
181        If id contains a list of id strings all of the respective
182        applicants types are saved to disk.
183        """
184
185    def clear(id=None, archive=True):
186        """Remove applicants of type given by 'id'.
187
188        Optionally archive the applicants.
189
190        If id is `None`, all applicants are archived.
191
192        If id contains a single id string, only the respective
193        applicants are archived.
194
195        If id contains a list of id strings all of the respective
196        applicant types are saved to disk.
197
198        If `archive` is ``False`` none of the archive-handling is done
199        and respective applicants are simply removed from the
200        database.
201        """
202
203class IApplicantsContainerAdd(IApplicantsContainer):
204    """An applicants container contains university applicants.
205    """
206    prefix = schema.Choice(
207        title = u'Application target',
208        required = True,
209        default = None,
210        source = application_types_vocab,
211        readonly = False,
212        )
213
214    year = schema.Choice(
215        title = u'Year of entrance',
216        required = True,
217        default = None,
218        values = year_range(),
219        readonly = False,
220        )
221
222    provider = schema.Choice(
223        title = u'Applicants container type',
224        required = True,
225        default = None,
226        source = ApplicantContainerProviderSource(),
227        readonly = False,
228        )
229
230IApplicantsContainerAdd[
231    'prefix'].order =  IApplicantsContainer['prefix'].order
232IApplicantsContainerAdd[
233    'year'].order =  IApplicantsContainer['year'].order
234IApplicantsContainerAdd[
235    'provider'].order =  IApplicantsContainer['provider'].order
236
237class IApplicantBaseData(IWAeUPObject):
238    """The data for an applicant.
239
240    This is a base interface with no field
241    required. For use with importers, forms, etc., please use one of
242    the derived interfaces below, which set more fields to required
243    state, depending on use-case.
244    """
245    history = Attribute('Object history, a list of messages.')
246    state = Attribute('The application state of an applicant')
247    fullname = Attribute('The fullname of an applicant')
248    application_date = Attribute('Date of submission, used for export only')
249    password = Attribute('Encrypted password of a applicant')
250    application_number = Attribute('The key under which the record is stored')
251
252    def loggerInfo(ob_class, comment):
253        """Adds an INFO message to the log file
254        """
255
256    applicant_id = schema.TextLine(
257        title = u'Applicant Id',
258        required = False,
259        readonly = False,
260        )
261
262    reg_no = schema.TextLine(
263        title = u'JAMB Registration Number',
264        readonly = True,
265        required = False,
266        )
267    access_code = schema.TextLine(
268        title = u'Access Code',
269        required = False,
270        readonly = True,
271        )
272    course1 = schema.Choice(
273        title = u'1st Choice Course of Study',
274        source = AppCatCertificateSource(),
275        required = True,
276        )
277    course2 = schema.Choice(
278        title = u'2nd Choice Course of Study',
279        source = AppCatCertificateSource(),
280        required = False,
281        )
282    firstname = schema.TextLine(
283        title = u'First Name',
284        required = True,
285        )
286    middlenames = schema.TextLine(
287        title = u'Middle Names',
288        required = False,
289        )
290    lastname = schema.TextLine(
291        title = u'Last Name (Surname)',
292        required = True,
293        )
294    date_of_birth = schema.Date(
295        title = u'Date of Birth',
296        required = True,
297        )
298    lga = schema.Choice(
299        source = lgas_vocab,
300        title = u'State/LGA',
301        default = 'foreigner',
302        required = True,
303        )
304    sex = schema.Choice(
305        title = u'Sex',
306        source = GenderSource(),
307        default = u'm',
308        required = True,
309        )
310    email = schema.ASCIILine(
311        title = u'Email',
312        required = True,
313        constraint=validate_email,
314        )
315    phone = schema.Int(
316        title = u'Phone',
317        description = u'Enter phone number with country code and without spaces.',
318        required = False,
319        )
320    #passport = ImageFile(
321    #    title = u'Passport Photograph',
322    #    #default = DEFAULT_PASSPORT_IMAGE_MALE,
323    #    defaultFactory = default_passport_image,
324    #    description = u'Maximun file size is 20 kB.',
325    #    required = True,
326    #    max_size = 20480,
327    #    )
328
329    #
330    # Process Data
331    #
332    screening_score = schema.Int(
333        title = u'Screening Score',
334        required = False,
335        )
336    screening_venue = schema.TextLine(
337        title = u'Screening Venue',
338        required = False,
339        )
340    course_admitted = schema.Choice(
341        title = u'Admitted Course of Study',
342        source = CertificateSource(),
343        default = None,
344        required = False,
345        )
346    notice = schema.Text(
347        title = u'Notice',
348        required = False,
349        )
350    student_id = schema.TextLine(
351        title = u'Student Id',
352        required = False,
353        readonly = True,
354        )
355    locked = schema.Bool(
356        title = u'Form locked',
357        default = False,
358        )
359
360class IApplicant(IApplicantBaseData):
361    """An applicant.
362
363    This is basically the applicant base data. Here we repeat the
364    fields from base data if we have to set the `required` attribute
365    to True (which is the default).
366    """
367
368class IApplicantEdit(IApplicantBaseData):
369    """An applicant.
370
371    Here we can repeat the fields from base data and set the
372    `required` and `readonly` attributes to True to further restrict
373    the data access. We cannot omit fields. This has to be done in the
374    respective form page.
375    """
376    screening_score = schema.Int(
377        title = u'Screening Score',
378        required = False,
379        readonly = True,
380        )
381    screening_venue = schema.TextLine(
382        title = u'Screening Venue',
383        required = False,
384        readonly = True,
385        )
386    course_admitted = schema.Choice(
387        title = u'Admitted Course of Study',
388        source = CertificateSource(),
389        default = None,
390        required = False,
391        readonly = True,
392        )
393    notice = schema.Text(
394        title = u'Notice',
395        required = False,
396        readonly = True,
397        )
398
399class IApplicantOnlinePayment(IOnlinePayment):
400    """An applicant payment via payment gateways.
401
402    """
403    p_year = schema.Choice(
404        title = u'Payment Session',
405        source = academic_sessions_vocab,
406        required = False,
407        )
408
409IApplicantOnlinePayment['p_year'].order = IApplicantOnlinePayment[
410    'p_year'].order
411
412class IApplicantsContainerProvider(Interface):
413    """A provider for applicants containers.
414
415    Applicants container providers are meant to be looked up as
416    utilities. This way we can find all applicant container types
417    defined somewhere.
418
419    Each applicants container provider registered as utility provides
420    one container type and one should be able to call the `factory`
421    attribute to create an instance of the requested container type.
422
423    .. THE FOLLOWING SHOULD GO INTO SPHINX DOCS (and be tested)
424
425    Samples:
426
427    Given, you had an IApplicantsContainer implementation somewhere
428    and you would like to make it findable on request, then you would
429    normally create an appropriate provider utility like this::
430
431      import grok
432      from waeup.sirp.applicants.interfaces import IApplicantsContainerProvider
433
434      class MyContainerProvider(grok.GlobalUtility):
435          grok.implements(IApplicantsContainerProvider)
436          grok.name('MyContainerProvider') # Must be unique
437          factory = MyContainer # A class implementing IApplicantsContainer
438                                # or derivations thereof.
439
440    This utility would be registered on startup and could then be used
441    like this:
442
443      >>> from zope.component import getAllUtilitiesRegisteredFor
444      >>> from waeup.sirp.applicants.interfaces import (
445      ...     IApplicantsContainerProvider)
446      >>> all_providers = getAllUtilitiesRegisteredFor(
447      ...     IApplicantsContainerProvider)
448      >>> all_providers
449      [<MyContainerProvider object at 0x...>]
450
451    You could look up this specific provider by name:
452
453      >>> from zope.component import getUtility
454      >>> p = getUtility(IApplicantsContainerProvider, name='MyProvider')
455      >>> p
456      <MyContainerProvider object at 0x...>
457
458    An applicants container would then be created like this:
459
460      >>> provider = all_providers[0]
461      >>> container = provider.factory()
462      >>> container
463      <MyContainer object at 0x...>
464
465    """
466    factory = Attribute("A class that can create instances of the "
467                        "requested container type")
Note: See TracBrowser for help on using the repository browser.