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

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

Implement bed booking algorithm (work in progress!).

  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
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
19import sys
20from time import time
21from datetime import date, datetime
22from zope.component import createObject
23from waeup.sirp.browser import (
24    WAeUPPage, WAeUPEditFormPage, WAeUPAddFormPage, WAeUPDisplayFormPage,
25    NullValidator)
26from waeup.sirp.browser.breadcrumbs import Breadcrumb
27from waeup.sirp.browser.resources import datepicker, datatable, tabs, toggleall
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)
34from waeup.sirp.browser.pages import delSubobjects
35from waeup.sirp.authentication import get_principal_role_manager
36from waeup.sirp.hostels.container import HostelsContainer
37from waeup.sirp.hostels.hostel import Hostel, NOT_OCCUPIED
38from waeup.sirp.hostels.interfaces import IHostelsContainer, IHostel
39
40def write_log_message(view, message):
41    ob_class = view.__implemented__.__name__.replace('waeup.sirp.','')
42    view.context.loggerInfo(ob_class, message)
43    return
44
45# Save function used for save methods in manager pages
46def msave(view, **data):
47    form = view.request.form
48    changed_fields = view.applyData(view.context, **data)
49    # Turn list of lists into single list
50    if changed_fields:
51        changed_fields = reduce(lambda x,y: x+y, changed_fields.values())
52    fields_string = ' + '.join(changed_fields)
53    view.context._p_changed = True
54    view.flash('Form has been saved.')
55    if fields_string:
56        write_log_message(view, 'saved: % s' % fields_string)
57    return
58
59class HostelsTab(PrimaryNavTab):
60    """Hostels tab in primary navigation.
61    """
62
63    grok.context(IWAeUPObject)
64    grok.order(5)
65    grok.require('waeup.viewHostels')
66    grok.template('primarynavtab')
67
68    pnav = 5
69    tab_title = u'Hostels'
70
71    @property
72    def link_target(self):
73        return self.view.application_url('hostels')
74
75class HostelsBreadcrumb(Breadcrumb):
76    """A breadcrumb for the hostels container.
77    """
78    grok.context(IHostelsContainer)
79    title = u'Hostels'
80
81class HostelBreadcrumb(Breadcrumb):
82    """A breadcrumb for the hostel container.
83    """
84    grok.context(IHostel)
85
86    def title(self):
87        return self.context.hostel_name
88
89class HostelsContainerPage(WAeUPDisplayFormPage):
90    """The standard view for hostels containers.
91    """
92    grok.context(IHostelsContainer)
93    grok.name('index')
94    grok.require('waeup.viewHostels')
95    grok.template('containerpage')
96    label = 'Accommodation Section'
97    title = 'Hostels'
98    pnav = 5
99
100class HostelsContainerManageActionButton(ManageActionButton):
101    grok.order(1)
102    grok.context(IHostelsContainer)
103    grok.view(HostelsContainerPage)
104    grok.require('waeup.manageHostels')
105    text = 'Manage accommodation section'
106
107class HostelsContainerManagePage(WAeUPDisplayFormPage):
108    """The manage page for hostel containers.
109    """
110    grok.context(IHostelsContainer)
111    grok.name('manage')
112    grok.require('waeup.manageHostels')
113    grok.template('containermanagepage')
114    pnav = 5
115    title = 'Hostels'
116    label = 'Manage accommodation section'
117
118    # It's quite dangerous to remove entire hostels with its content (beds).
119    # Thus, this remove method should be combined with an archiving function.
120    @grok.action('Remove selected')
121    def delHostels(self, **data):
122        form = self.request.form
123        if form.has_key('val_id'):
124            deleted = []
125            child_id = form['val_id']
126            if not isinstance(child_id, list):
127                child_id = [child_id]
128            for id in child_id:
129                deleted.append(id)
130            write_log_message(self, 'deleted: % s' % ', '.join(deleted))
131        delSubobjects(self, redirect='@@manage', tab='2')
132        return
133
134    @grok.action('Add hostel', validator=NullValidator)
135    def addSubunit(self, **data):
136        self.redirect(self.url(self.context, 'addhostel'))
137        return
138
139class HostelAddFormPage(WAeUPAddFormPage):
140    """Add-form to add a hostel.
141    """
142    grok.context(IHostelsContainer)
143    grok.require('waeup.manageHostels')
144    grok.name('addhostel')
145    #grok.template('hosteladdpage')
146    form_fields = grok.AutoFields(IHostel)
147    title = 'Hostels'
148    label = 'Add hostel'
149    pnav = 5
150
151    @grok.action('Create hostel')
152    def addHostel(self, **data):
153        hostel = Hostel()
154        self.applyData(hostel, **data)
155        hostel.hostel_id = data[
156            'hostel_name'].lower().replace(' ','-').replace('_','-')
157        try:
158            self.context.addHostel(hostel)
159        except KeyError:
160            self.flash('The hostel already exists.')
161            return
162        self.flash('Hostel created.')
163        write_log_message(self, 'added: % s' % data['hostel_name'])
164        self.redirect(self.url(self.context[hostel.hostel_id], 'index'))
165        return
166
167class HostelDisplayFormPage(WAeUPDisplayFormPage):
168    """ Page to display hostel data
169    """
170    grok.context(IHostel)
171    grok.name('index')
172    grok.require('waeup.viewHostels')
173    #grok.template('hostelpage')
174    pnav = 5
175
176    @property
177    def label(self):
178        return self.context.hostel_name
179
180    @property
181    def title(self):
182        return self.context.hostel_name
183
184class HostelManageActionButton(ManageActionButton):
185    grok.order(1)
186    grok.context(IHostel)
187    grok.view(HostelDisplayFormPage)
188    grok.require('waeup.manageHostels')
189    text = 'Manage'
190    target = 'manage'
191
192class HostelManageFormPage(WAeUPEditFormPage):
193    """ View to edit hostel data
194    """
195    grok.context(IHostel)
196    grok.name('manage')
197    grok.require('waeup.manageHostels')
198    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
199    grok.template('hostelmanagepage')
200    label = 'Manage hostel'
201    pnav = 5
202    taboneactions = ['Save']
203    tabtwoactions = ['Update all beds',
204        'Switch reservation of selected beds',
205        'Release selected beds']
206    not_occupied = NOT_OCCUPIED
207
208    @property
209    def title(self):
210        return self.context.hostel_name
211
212    @property
213    def students_url(self):
214        return self.url(grok.getSite(),'students')
215
216    def update(self):
217        datepicker.need() # Enable jQuery datepicker in date fields.
218        tabs.need()
219        datatable.need()
220        super(HostelManageFormPage, self).update()
221        return
222
223    @grok.action('Save')
224    def save(self, **data):
225        msave(self, **data)
226        return
227
228    @grok.action('Update all beds')
229    def updateBeds(self, **data):
230        removed, added, modified, modified_beds = self.context.updateBeds()
231        message = '%d empty beds removed, %d beds added, %d occupied beds modified (%s)' % (
232            removed, added, modified, modified_beds)
233        self.flash(message)
234        write_log_message(self, message)
235        self.redirect(self.url(self.context, '@@manage')+'#tab-2')
236        return
237
238    @grok.action('Switch reservation of selected beds')
239    def switchReservations(self, **data):
240        form = self.request.form
241        if form.has_key('val_id'):
242            child_id = form['val_id']
243        else:
244            self.flash('No item selected.')
245            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
246            return
247        if not isinstance(child_id, list):
248            child_id = [child_id]
249        switched = []
250        for bed_id in child_id:
251            try:
252                message = self.context[bed_id].switchReservation()
253                switched.append('%s (%s)' % (bed_id,message))
254            except:
255                self.flash('Could not switch %s: %s: %s' % (
256                        id, sys.exc_info()[0], sys.exc_info()[1]))
257                self.redirect(self.url(self.context, '@@manage')+'#tab-2')
258                return
259        if len(switched):
260            message = ', '.join(switched)
261            self.flash('Successfully switched beds: %s' % message)
262            write_log_message(self, 'switched: % s' % message)
263            self.redirect(self.url(self.context, '@@manage')+'#tab-2')
264        return
265
266    # Needed for removing students from beds
267    #@grok.action('Release selected beds')
268    #def releaseBeds(self, **data):
269    #    #self.flash('%d released' % released)
270    #    self.redirect(self.url(self.context, '@@manage')+'#tab-2')
271    #    return
Note: See TracBrowser for help on using the repository browser.