source: main/waeup.sirp/trunk/src/waeup/sirp/hostels/browser.py @ 7125

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

Add more tests and increase test coverage.

  • Property svn:keywords set to Id
File size: 11.1 KB
RevLine 
[6953]1## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
2## This program is free software; you can redistribute it and/or modify
3## it under the terms of the GNU General Public License as published by
4## the Free Software Foundation; either version 2 of the License, or
5## (at your option) any later version.
6##
7## This program is distributed in the hope that it will be useful,
8## but WITHOUT ANY WARRANTY; without even the implied warranty of
9## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10## GNU General Public License for more details.
11##
12## You should have received a copy of the GNU General Public License
13## along with this program; if not, write to the Free Software
14## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15##
16"""UI components for hostels and related components.
17"""
18import grok
[6973]19import sys
[6953]20from time import time
21from datetime import date, datetime
22from zope.component import createObject
23from waeup.sirp.browser import (
[6959]24    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage, WAeUPDisplayFormPage,
25    NullValidator)
[6953]26from waeup.sirp.browser.breadcrumbs import Breadcrumb
[6959]27from waeup.sirp.browser.resources import datepicker, datatable, tabs, toggleall
[6953]28from waeup.sirp.browser.viewlets import (
29    ManageActionButton, PrimaryNavTab, AddActionButton)
30from waeup.sirp.interfaces import IWAeUPObject, IUserAccount
31from waeup.sirp.widgets.datewidget import (
32    FriendlyDateWidget, FriendlyDateDisplayWidget,
33    FriendlyDatetimeDisplayWidget)
[6959]34from waeup.sirp.browser.pages import delSubobjects
[6953]35from waeup.sirp.authentication import get_principal_role_manager
36from waeup.sirp.hostels.container import HostelsContainer
[7068]37from waeup.sirp.hostels.vocabularies import NOT_OCCUPIED
38from waeup.sirp.hostels.hostel import Hostel
39from waeup.sirp.hostels.interfaces import (
40    IHostelsContainer, IHostel, IBed, IBedAllocateStudent)
[6953]41
[6956]42def write_log_message(view, message):
43    ob_class = view.__implemented__.__name__.replace('waeup.sirp.','')
44    view.context.loggerInfo(ob_class, message)
45    return
[6953]46
[6956]47# Save function used for save methods in manager pages
48def msave(view, **data):
49    form = view.request.form
50    changed_fields = view.applyData(view.context, **data)
51    # Turn list of lists into single list
52    if changed_fields:
53        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
54    fields_string = ' + '.join(changed_fields)
55    view.context._p_changed = True
56    view.flash('Form has been saved.')
57    if fields_string:
58        write_log_message(view, 'saved: % s' % fields_string)
59    return
60
[6953]61class HostelsTab(PrimaryNavTab):
62    """Hostels tab in primary navigation.
63    """
64
65    grok.context(IWAeUPObject)
66    grok.order(5)
67    grok.require('waeup.viewHostels')
68    grok.template('primarynavtab')
69
70    pnav = 5
71    tab_title = u'Hostels'
72
73    @property
74    def link_target(self):
75        return self.view.application_url('hostels')
76
77class HostelsBreadcrumb(Breadcrumb):
78    """A breadcrumb for the hostels container.
79    """
80    grok.context(IHostelsContainer)
81    title = u'Hostels'
82
83class HostelBreadcrumb(Breadcrumb):
84    """A breadcrumb for the hostel container.
85    """
86    grok.context(IHostel)
87
[6959]88    def title(self):
89        return self.context.hostel_name
90
[7068]91class BedBreadcrumb(Breadcrumb):
92    """A breadcrumb for the hostel container.
93    """
94    grok.context(IBed)
95
96    def title(self):
97        co = self.context.getBedCoordinates()
98        return 'Block %s, Room %s, Bed %s' % (co[1], co[2], co[3])
99
[6953]100class HostelsContainerPage(WAeUPDisplayFormPage):
101    """The standard view for hostels containers.
102    """
103    grok.context(IHostelsContainer)
104    grok.name('index')
105    grok.require('waeup.viewHostels')
[6959]106    grok.template('containerpage')
[6953]107    label = 'Accommodation Section'
[6959]108    title = 'Hostels'
[6953]109    pnav = 5
110
111class HostelsContainerManageActionButton(ManageActionButton):
112    grok.order(1)
113    grok.context(IHostelsContainer)
114    grok.view(HostelsContainerPage)
115    grok.require('waeup.manageHostels')
116    text = 'Manage accommodation section'
117
118class HostelsContainerManagePage(WAeUPDisplayFormPage):
119    """The manage page for hostel containers.
120    """
121    grok.context(IHostelsContainer)
122    grok.name('manage')
123    grok.require('waeup.manageHostels')
[6959]124    grok.template('containermanagepage')
[6953]125    pnav = 5
[6959]126    title = 'Hostels'
[6953]127    label = 'Manage accommodation section'
128
[6959]129    # It's quite dangerous to remove entire hostels with its content (beds).
[6966]130    # Thus, this remove method should be combined with an archiving function.
[6959]131    @grok.action('Remove selected')
132    def delHostels(self, **data):
133        form = self.request.form
134        if form.has_key('val_id'):
135            deleted = []
136            child_id = form['val_id']
[6966]137            if not isinstance(child_id, list):
138                child_id = [child_id]
[6959]139            for id in child_id:
140                deleted.append(id)
141            write_log_message(self, 'deleted: % s' % ', '.join(deleted))
142        delSubobjects(self, redirect='@@manage', tab='2')
143        return
[6953]144
[6959]145    @grok.action('Add hostel', validator=NullValidator)
146    def addSubunit(self, **data):
147        self.redirect(self.url(self.context, 'addhostel'))
148        return
149
[6953]150class HostelAddFormPage(WAeUPAddFormPage):
151    """Add-form to add a hostel.
152    """
153    grok.context(IHostelsContainer)
154    grok.require('waeup.manageHostels')
155    grok.name('addhostel')
[6970]156    #grok.template('hosteladdpage')
[6953]157    form_fields = grok.AutoFields(IHostel)
[6959]158    title = 'Hostels'
[6953]159    label = 'Add hostel'
160    pnav = 5
161
162    @grok.action('Create hostel')
163    def addHostel(self, **data):
[6954]164        hostel = Hostel()
165        self.applyData(hostel, **data)
[6973]166        hostel.hostel_id = data[
167            'hostel_name'].lower().replace(' ','-').replace('_','-')
[6966]168        try:
169            self.context.addHostel(hostel)
170        except KeyError:
171            self.flash('The hostel already exists.')
172            return
[6953]173        self.flash('Hostel created.')
[6959]174        write_log_message(self, 'added: % s' % data['hostel_name'])
[6953]175        self.redirect(self.url(self.context[hostel.hostel_id], 'index'))
176        return
177
178class HostelDisplayFormPage(WAeUPDisplayFormPage):
179    """ Page to display hostel data
180    """
181    grok.context(IHostel)
182    grok.name('index')
183    grok.require('waeup.viewHostels')
184    #grok.template('hostelpage')
185    pnav = 5
186
[6956]187    @property
188    def label(self):
189        return self.context.hostel_name
[6953]190
[6956]191    @property
192    def title(self):
193        return self.context.hostel_name
[6953]194
195class HostelManageActionButton(ManageActionButton):
196    grok.order(1)
197    grok.context(IHostel)
198    grok.view(HostelDisplayFormPage)
199    grok.require('waeup.manageHostels')
200    text = 'Manage'
[6970]201    target = 'manage'
[6953]202
203class HostelManageFormPage(WAeUPEditFormPage):
204    """ View to edit hostel data
205    """
206    grok.context(IHostel)
[6970]207    grok.name('manage')
[6953]208    grok.require('waeup.manageHostels')
209    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
[6970]210    grok.template('hostelmanagepage')
[6959]211    label = 'Manage hostel'
[6953]212    pnav = 5
[6970]213    taboneactions = ['Save']
[6973]214    tabtwoactions = ['Update all beds',
215        'Switch reservation of selected beds',
216        'Release selected beds']
[6996]217    not_occupied = NOT_OCCUPIED
[6953]218
[6956]219    @property
220    def title(self):
221        return self.context.hostel_name
[6953]222
[6996]223    @property
224    def students_url(self):
225        return self.url(grok.getSite(),'students')
226
[6953]227    def update(self):
228        datepicker.need() # Enable jQuery datepicker in date fields.
[6970]229        tabs.need()
230        datatable.need()
[6953]231        super(HostelManageFormPage, self).update()
232        return
233
234    @grok.action('Save')
235    def save(self, **data):
236        msave(self, **data)
237        return
[6970]238
[6973]239    @grok.action('Update all beds')
[6970]240    def updateBeds(self, **data):
[6988]241        removed, added, modified, modified_beds = self.context.updateBeds()
242        message = '%d empty beds removed, %d beds added, %d occupied beds modified (%s)' % (
243            removed, added, modified, modified_beds)
244        self.flash(message)
245        write_log_message(self, message)
[6970]246        self.redirect(self.url(self.context, '@@manage')+'#tab-2')
247        return
[6973]248
249    @grok.action('Switch reservation of selected beds')
[6974]250    def switchReservations(self, **data):
[6973]251        form = self.request.form
252        if form.has_key('val_id'):
253            child_id = form['val_id']
254        else:
255            self.flash('No item selected.')
256            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
257            return
258        if not isinstance(child_id, list):
259            child_id = [child_id]
260        switched = []
261        for bed_id in child_id:
262            try:
[6988]263                message = self.context[bed_id].switchReservation()
264                switched.append('%s (%s)' % (bed_id,message))
[6973]265            except:
266                self.flash('Could not switch %s: %s: %s' % (
267                        id, sys.exc_info()[0], sys.exc_info()[1]))
268                self.redirect(self.url(self.context, '@@manage')+'#tab-2')
269                return
270        if len(switched):
[6988]271            message = ', '.join(switched)
272            self.flash('Successfully switched beds: %s' % message)
[7042]273            write_log_message(self, 'switched: %s' % message)
[6973]274            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
275        return
276
[7042]277    @grok.action('Release selected beds')
278    def releaseBeds(self, **data):
279        form = self.request.form
280        if form.has_key('val_id'):
281            child_id = form['val_id']
282        else:
283            self.flash('No item selected.')
284            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
285            return
286        if not isinstance(child_id, list):
287            child_id = [child_id]
288        released = []
289        for bed_id in child_id:
[7068]290            message = self.context[bed_id].releaseBed()
[7070]291            if message:
292                released.append('%s (%s)' % (bed_id,message))
[7042]293        if len(released):
294            message = ', '.join(released)
295            self.flash('Successfully released beds: %s' % message)
296            write_log_message(self, 'released: %s' % message)
297            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
[7070]298        else:
299            self.flash('No allocated bed selected.')
300            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
[7042]301        return
[7068]302
303class BedManageFormPage(WAeUPEditFormPage):
304    """ View to edit bed data
305    """
306    grok.context(IBedAllocateStudent)
307    grok.name('index')
308    grok.require('waeup.manageHostels')
309    form_fields = grok.AutoFields(IBedAllocateStudent).omit(
310        'bed_id').omit('bed_number').omit('bed_type')
311    label = 'Allocate student'
312    pnav = 5
313
314    @property
315    def title(self):
316        co = self.context.getBedCoordinates()
317        return '%s, Block %s, Room %s, Bed %s' % (
318            self.context.__parent__.hostel_name, co[1], co[2], co[3])
319
320    @grok.action('Save')
321    def save(self, **data):
322        msave(self, **data)
323        self.redirect(self.url(self.context.__parent__, '@@manage')+'#tab-2')
324        return
325
326    def update(self):
327        if self.context.owner != NOT_OCCUPIED:
328            # Don't use this form for exchanging students.
329            # Beds must be released first before they can be allocated to
330            # other students.
331            self.redirect(self.url(self.context.__parent__, '@@manage')+'#tab-2')
332        return
Note: See TracBrowser for help on using the repository browser.