source: main/waeup.sirp/trunk/src/waeup/sirp/hostels/hostel.py @ 9961

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

Internationalize hostels package.

Remove exception catcher in switchReservations and corresponding test.

When testing the hostel configuration manually I found out that the beds_reserved list attribute of halls
only changed during the lifetime of a running instance. After restarting the portal all changes were gone.
Also "hostel._p_changed = True" didn't help. The only solution was to reassign the attribute to ensure persistance.

Unfortunately, the current tests don't catch such a malfunction. This has to be improved.

  • Property svn:keywords set to Id
File size: 8.8 KB
Line 
1## $Id: hostel.py 7718 2012-02-28 19:34:51Z 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"""
19These are the hostels.
20"""
21import grok
22from zope.event import notify
23from datetime import datetime
24from waeup.sirp.utils.helpers import attrs_to_fields
25from waeup.sirp.hostels.vocabularies import NOT_OCCUPIED
26from waeup.sirp.hostels.interfaces import IHostel, IBed, IBedAllocateStudent
27from waeup.sirp.students.interfaces import IBedTicket
28from waeup.sirp.interfaces import MessageFactory as _
29
30class Hostel(grok.Container):
31    """This is a hostel.
32    """
33    grok.implements(IHostel)
34    grok.provides(IHostel)
35
36    def loggerInfo(self, ob_class, comment=None):
37        target = self.__name__
38        return grok.getSite()['hostels'].logger_info(ob_class,target,comment)
39
40    def addBed(self, bed):
41        """Add a bed.
42        """
43        if not IBed.providedBy(bed):
44            raise TypeError(
45                'Hostels contain only IBed instances')
46        self[bed.bed_id] = bed
47        return
48
49    def updateBeds(self):
50        """Fill hostel with beds or update beds.
51        """
52        added_counter = 0
53        modified_counter = 0
54        removed_counter = 0
55        modified_beds = u''
56
57        # Remove all empty beds. Occupied beds remain in hostel!
58        keys = list(self.keys()) # create list copy
59        for key in keys:
60            if self[key].owner == NOT_OCCUPIED:
61                del self[key]
62                self._p_changed = True
63                removed_counter += 1
64            else:
65                self[key].bed_number = 9999
66        remaining = len(keys) - removed_counter
67
68        blocks_for_female = getattr(self,'blocks_for_female',[])
69        blocks_for_male = getattr(self,'blocks_for_male',[])
70        beds_for_fresh = getattr(self,'beds_for_fresh',[])
71        beds_for_pre = getattr(self,'beds_for_pre',[])
72        beds_for_returning = getattr(self,'beds_for_returning',[])
73        beds_for_final = getattr(self,'beds_for_final',[])
74        beds_for_all = getattr(self,'beds_for_all',[])
75        beds_reserved = getattr(self,'beds_reserved',[])
76        all_blocks = blocks_for_female + blocks_for_male
77        all_beds = (beds_for_pre + beds_for_fresh +
78            beds_for_returning + beds_for_final + beds_for_all)
79        for block in all_blocks:
80            sex = 'male'
81            if block in blocks_for_female:
82                sex = 'female'
83            for floor in range(1,int(self.floors_per_block)+1):
84                for room in range(1,int(self.rooms_per_floor)+1):
85                    for bed in all_beds:
86                        room_nr = floor*100 + room
87                        bt = 'all'
88                        if '%s_%s_%s' % (block,room_nr,bed) in beds_reserved:
89                            bt = "reserved"
90                        elif bed in beds_for_fresh:
91                            bt = 'fr'
92                        elif bed in beds_for_pre:
93                            bt = 'pr'
94                        elif bed in beds_for_final:
95                            bt = 'fi'
96                        elif bed in beds_for_returning:
97                            bt = 're'
98                        bt = u'%s_%s_%s' % (self.special_handling,sex,bt)
99                        uid = u'%s_%s_%d_%s' % (self.hostel_id,block,room_nr,bed)
100                        if self.has_key(uid):
101                            bed = self[uid]
102                            # Renumber remaining beds
103                            bed.bed_number = len(self) + 1 - remaining
104                            remaining -= 1
105                            if bed.bed_type != bt:
106                                bed.bed_type = bt
107                                modified_counter += 1
108                                modified_beds += '%s ' % uid
109                        else:
110                            bed = Bed()
111                            bed.bed_id = uid
112                            bed.bed_type = bt
113                            bed.bed_number = len(self) + 1 - remaining
114                            bed.owner = NOT_OCCUPIED
115                            self.addBed(bed)
116                            added_counter +=1
117        return removed_counter, added_counter, modified_counter, modified_beds
118
119Hostel = attrs_to_fields(Hostel)
120
121class Bed(grok.Container):
122    """This is a bed.
123    """
124    grok.implements(IBed, IBedAllocateStudent)
125    grok.provides(IBed)
126
127    def getBedCoordinates(self):
128        """Determine the coordinates from the bed_id.
129        """
130        return self.bed_id.split('_')
131
132    def bookBed(self, student_id):
133        if self.owner == NOT_OCCUPIED:
134            self.owner = student_id
135            notify(grok.ObjectModifiedEvent(self))
136            return None
137        else:
138            return self.owner
139
140    def switchReservation(self):
141        """Reserves or unreserve bed respectively.
142        """
143        sh, sex, bt = self.bed_type.split('_')
144        hostel_id, block, room_nr, bed = self.getBedCoordinates()
145        hostel = self.__parent__
146        beds_for_fresh = getattr(hostel,'beds_for_fresh',[])
147        beds_for_pre = getattr(hostel,'beds_for_pre',[])
148        beds_for_returning = getattr(hostel,'beds_for_returning',[])
149        beds_for_final = getattr(hostel,'beds_for_final',[])
150        bed_string = u'%s_%s_%s' % (block, room_nr, bed)
151        if bt == 'reserved':
152            bt = 'all'
153            if bed in beds_for_fresh:
154                bt = 'fr'
155            elif bed in beds_for_pre:
156                bt = 'pr'
157            elif bed in beds_for_final:
158                bt = 'fi'
159            elif bed in beds_for_returning:
160                bt = 're'
161            bt = u'%s_%s_%s' % (sh, sex, bt)
162
163            # Comment of Martijn:
164            # If you have a non-Persistent subobject (like a list) and you change it,
165            # you need to manually flag the persistence machinery on the object that
166            # its subobject changed, with _p_changed. This is only necessary if some
167            # of the objects are not sublclasses of Persistent. For common built-in
168            # collections in Python such as list and dictionary there are replacements
169            # (PersistentList, PersistentMapping), and more advanced building blocks
170            # for indexes (BTrees), that don't have this issue.
171            #hostel._p_changed = True
172
173            # Henrik: Unfortunately, this doesn't work in our case.
174            # After restarting the portal,
175            # added or removed list items are gone. The only way to ensure
176            # persistance is to reassign the list attribute.
177            br = hostel.beds_reserved
178            br.remove(bed_string)
179            hostel.beds_reserved = br
180            message = _(u'unreserved')
181        else:
182            bt = u'%s_%s_reserved' % (sh, sex)
183            # See comment above
184            br = hostel.beds_reserved
185            br.append(bed_string)
186            hostel.beds_reserved = br
187            message = _(u'reserved')
188        self.bed_type = bt
189        return message
190
191    def releaseBed(self):
192        if self.owner == NOT_OCCUPIED:
193            return
194        else:
195            old_owner = self.owner
196            self.owner = NOT_OCCUPIED
197            notify(grok.ObjectModifiedEvent(self))
198            accommodation_session = grok.getSite()[
199                'configuration'].accommodation_session
200            try:
201                bedticket = grok.getSite()['students'][old_owner][
202                              'accommodation'][str(accommodation_session)]
203            except KeyError:
204                return '%s without bed ticket' % old_owner
205            bedticket.bed = None
206            timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
207            bedticket.bed_coordinates = u'-- booking cancelled on %s --' % timestamp
208            return old_owner
209
210    def loggerInfo(self, ob_class, comment=None):
211        target = self.__name__
212        return grok.getSite()['hostels'].logger_info(ob_class,target,comment)
213
214Bed = attrs_to_fields(Bed)
215
216@grok.subscribe(IBedTicket, grok.IObjectRemovedEvent)
217def handle_bedticket_removed(bedticket, event):
218    """If a bed ticket is deleted, we make sure that also the owner attribute
219    of the bed is cleared (set to NOT_OCCUPIED).
220    """
221    if bedticket.bed != None:
222        bedticket.bed.owner = NOT_OCCUPIED
223        notify(grok.ObjectModifiedEvent(bedticket.bed))
Note: See TracBrowser for help on using the repository browser.