source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/interfaces.py @ 17367

Last change on this file since 17367 was 17313, checked in by Henrik Bettermann, 22 months ago

Allow beds to be blocked so that no student can be allocated to such a bed space (in contrast to reserved beds)

  • Property svn:keywords set to Id
File size: 9.2 KB
RevLine 
[7195]1## $Id: interfaces.py 17313 2023-01-25 08:52:51Z henrik $
[6951]2##
[7195]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##
[9414]18from  grok import getSite
[8685]19from datetime import datetime
[9414]20from zope.component import getUtility
21from zope.catalog.interfaces import ICatalog
[13483]22from zope.interface import invariant, Invalid, Attribute, Interface
[6951]23from zope import schema
[8685]24from waeup.kofa.interfaces import (
25    IKofaObject, academic_sessions_vocab, registration_states_vocab)
[7811]26from waeup.kofa.interfaces import MessageFactory as _
27from waeup.kofa.hostels.vocabularies import (
[9414]28    bed_letters, blocks, SpecialHandlingSource,
29    NOT_OCCUPIED)
[17313]30from waeup.kofa.students.interfaces import IStudentsUtils
[6951]31
[13442]32# Define a validation method for sort ids
33class NotASortId(schema.ValidationError):
34    __doc__ = u"Invalid sort_id"
35
36def validate_sort_id(value):
[13475]37    if not value < 1000:
[13442]38        raise NotASortId(value)
39    return True
40
[7819]41class IHostelsContainer(IKofaObject):
[13167]42    """A container for hostel objects.
[6951]43    """
44
[13165]45    expired = Attribute('True if current datetime is in application period.')
[13483]46    statistics = Attribute('Bed category statistics')
[13165]47
[8685]48    startdate = schema.Datetime(
49        title = _(u'Hostel Allocation Start Date'),
50        required = False,
[13280]51        description = _('Example: ') + u'2011-12-01 18:30:00+01:00',
[8685]52        )
53
54    enddate = schema.Datetime(
55        title = _(u'Hostel Allocation Closing Date'),
56        required = False,
[13280]57        description = _('Example: ') + u'2011-12-31 23:59:59+01:00',
[8685]58        )
59
60    accommodation_session = schema.Choice(
61        title = _(u'Booking Session'),
62        source = academic_sessions_vocab,
[13563]63        #default = datetime.now().year,
[8685]64        required = False,
65        readonly = False,
66        )
67
68    accommodation_states = schema.List(
69        title = _(u'Allowed States'),
70        value_type = schema.Choice(
71            vocabulary = registration_states_vocab,
72            ),
[14009]73        defaultFactory=list,
[8685]74        )
75
[15250]76    allocation_expiration = schema.Int(
77        title = _(u'Allocation Expiration Time (days)'),
78        description = _(
79            'Number of days after which allocation is being annulled'),
80        required = False,
81        )
82
[9197]83    def clearAllHostels():
84        """Clear all hostels.
85        """
86
[13165]87    def addHostel(hostel):
88        """Add a hostel.
89        """
90
[13316]91    def releaseExpiredAllocations(n):
92        """Release bed if bed allocation has expired. Allocation expires
93        after `n` days if maintenance fee has not been paid.
94        """
95
[13166]96    def writeLogMessage(view, message):
[13167]97        """Add an INFO message to hostels.log.
[13165]98        """
99
[7819]100class IHostel(IKofaObject):
[13167]101    """Representation of a hostel.
[6951]102    """
[6952]103
[9196]104    bed_statistics = Attribute('Number of booked and total beds')
105
106    def clearHostel():
107        """Remove all beds.
108        """
109
[6970]110    def updateBeds():
111        """Fill hostel with beds or update beds.
112        """
113
[6952]114    hostel_id = schema.TextLine(
[7718]115        title = _(u'Hostel Id'),
[6956]116        )
117
118    sort_id = schema.Int(
[7718]119        title = _(u'Sort Id'),
[6954]120        required = True,
[6956]121        default = 10,
[13442]122        constraint=validate_sort_id,
[6956]123        )
124
125    hostel_name = schema.TextLine(
[7718]126        title = _(u'Hostel Name'),
[6956]127        required = True,
[6959]128        default = u'Hall 1',
[6956]129        )
130
[6959]131    floors_per_block = schema.Int(
[7718]132        title = _(u'Floors per Block'),
[6956]133        required = True,
[6971]134        default = 1,
[6956]135        )
136
137    rooms_per_floor = schema.Int(
[7718]138        title = _(u'Rooms per Floor'),
[6956]139        required = True,
[6971]140        default = 2,
[6956]141        )
142
[6958]143    blocks_for_female = schema.List(
[7718]144        title = _(u'Blocks for Female Students'),
[6958]145        value_type = schema.Choice(
146            vocabulary = blocks
147            ),
[14009]148        defaultFactory=list,
[6958]149        )
150
[6970]151    blocks_for_male = schema.List(
[7718]152        title = _(u'Blocks for Male Students'),
[6970]153        value_type = schema.Choice(
154            vocabulary = blocks
155            ),
[14009]156        defaultFactory=list,
[6970]157        )
158
[9146]159    beds_for_pre= schema.List(
160        title = _(u'Beds for Pre-Study Students'),
161        value_type = schema.Choice(
162            vocabulary = bed_letters
163            ),
[14009]164        defaultFactory=list,
[9146]165        )
166
[6958]167    beds_for_fresh = schema.List(
[7718]168        title = _(u'Beds for Fresh Students'),
[6958]169        value_type = schema.Choice(
170            vocabulary = bed_letters
171            ),
[14009]172        defaultFactory=list,
[6958]173        )
174
[6970]175    beds_for_returning = schema.List(
[7718]176        title = _(u'Beds for Returning Students'),
[6970]177        value_type = schema.Choice(
178            vocabulary = bed_letters
179            ),
[14009]180        defaultFactory=list,
[6970]181        )
182
[6958]183    beds_for_final = schema.List(
[7718]184        title = _(u'Beds for Final Year Students'),
[6958]185        value_type = schema.Choice(
186            vocabulary = bed_letters
187            ),
[14009]188        defaultFactory=list,
[6958]189        )
[6963]190
[6971]191    beds_for_all = schema.List(
[7718]192        title = _(u'Beds without category'),
[6971]193        value_type = schema.Choice(
194            vocabulary = bed_letters
195            ),
[14009]196        defaultFactory=list,
[6971]197        )
198
[6970]199    special_handling = schema.Choice(
[7718]200        title = _(u'Special Handling'),
[9400]201        source = SpecialHandlingSource(),
[6970]202        required = True,
[6973]203        default = u'regular',
[6970]204        )
205
[10680]206    maint_fee = schema.Float(
207        title = _(u'Rent'),
208        default = 0.0,
209        required = False,
210        )
211
[6970]212    @invariant
213    def blocksOverlap(hostel):
214        bfe = hostel.blocks_for_female
215        bma = hostel.blocks_for_male
216        if set(bfe).intersection(set(bma)):
[7718]217            raise Invalid(_('Female and male blocks overlap.'))
[6970]218
219    @invariant
220    def bedsOverlap(hostel):
[6981]221        beds = (hostel.beds_for_fresh +
222                hostel.beds_for_returning +
223                hostel.beds_for_final +
[9146]224                hostel.beds_for_pre +
[6981]225                hostel.beds_for_all)
226        if len(beds) != len(set(beds)):
[7718]227            raise Invalid(_('Bed categories overlap.'))
[6970]228
[13166]229    def writeLogMessage(view, message):
[13167]230        """Add an INFO message to hostels.log.
[13166]231        """
232
[7819]233class IBed(IKofaObject):
[13167]234    """Representation of a bed.
[6963]235    """
236
[13170]237    coordinates = Attribute('Coordinates tuple derived from bed_id')
238    hall = Attribute('Hall id, for exporter only')
239    block = Attribute('Block letter, for exporter only')
240    room = Attribute('Room number, for exporter only')
241    bed = Attribute('Bed letter, for exporter only')
242    special_handling = Attribute('Special handling code, for exporter only')
243    sex = Attribute('Sex, for exporter only')
244    bt = Attribute('Last part of bed type, for exporter only')
[9199]245
[6996]246    def bookBed(student_id):
247        """Book a bed for a student.
248        """
[6963]249
[17313]250    def switchBed(switch_type):
251        """Switches reservation or blockade.
[6974]252        """
253
[13316]254    def releaseBedIfMaintenanceNotPaid():
255        """Release bed if maintenance fee has not been paid on time.
[13533]256        Reserve bed so that it cannot be automatically booked by someone else.
[13316]257        """
258
[6963]259    bed_id = schema.TextLine(
[7718]260        title = _(u'Bed Id'),
[6963]261        required = True,
262        default = u'',
263        )
264
265    bed_type = schema.TextLine(
[7718]266        title = _(u'Bed Type'),
[6963]267        required = True,
268        default = u'',
269        )
270
[6971]271    bed_number = schema.Int(
[7718]272        title = _(u'Bed Number'),
[6963]273        required = True,
274        )
275
276    owner = schema.TextLine(
[7718]277        title = _(u'Owner (Student)'),
[9416]278        description = _('Enter valid student id.'),
[6963]279        required = True,
280        default = u'',
281        )
[7068]282
[9414]283    @invariant
284    def allowed_owners(bed):
285        if bed.owner == NOT_OCCUPIED:
286            return
287        catalog = getUtility(ICatalog, name='students_catalog')
[17176]288        accommodation_span = getUtility(IStudentsUtils).ACCOMMODATION_SPAN
[9414]289        accommodation_session = getSite()['hostels'].accommodation_session
290        students = catalog.searchResults(current_session=(
[17176]291            accommodation_session-accommodation_span,accommodation_session))
[9414]292        student_ids = [student.student_id for student in students]
293        if not bed.owner in student_ids:
294            raise Invalid(_(
[9416]295                "Either student does not exist or student "
[17176]296                "is not eligible to book accommodation."))
[9414]297        catalog = getUtility(ICatalog, name='beds_catalog')
298        beds = catalog.searchResults(owner=(bed.owner,bed.owner))
299        if len(beds):
300            allocated_bed = [bed.bed_id for bed in beds][0]
301            raise Invalid(_(
[13170]302                "This student resides in bed ${a}.",
303                mapping = {'a':allocated_bed}))
[13166]304
305    def writeLogMessage(view, message):
[13167]306        """Add an INFO message to hostels.log.
[13166]307        """
[13483]308
309class IHostelsUtils(Interface):
310    """A collection of methods which are subject to customization.
311    """
312
313    def getBedStatistics():
314        """Return bed statistics.
315        """
Note: See TracBrowser for help on using the repository browser.