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

Last change on this file since 17782 was 17313, checked in by Henrik Bettermann, 2 years 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.