1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 from datetime
import date
, datetime
, timedelta
, time
19 from dateutil
.relativedelta
import relativedelta
20 from flask
import request
, session
21 from sqlalchemy
import func
22 from werkzeug
.datastructures
import MultiDict
24 from indico
.core
.errors
import IndicoError
25 from indico
.modules
.rb
.controllers
import RHRoomBookingBase
26 from indico
.modules
.rb
.controllers
.decorators
import requires_location
, requires_room
27 from indico
.modules
.rb
.forms
.rooms
import SearchRoomsForm
28 from indico
.modules
.rb
.models
.locations
import Location
29 from indico
.modules
.rb
.models
.reservation_occurrences
import ReservationOccurrence
30 from indico
.modules
.rb
.models
.reservations
import RepeatMapping
, RepeatFrequency
, Reservation
31 from indico
.modules
.rb
.models
.rooms
import Room
32 from indico
.modules
.rb
.models
.equipment
import EquipmentType
33 from indico
.modules
.rb
.statistics
import calculate_rooms_occupancy
, compose_rooms_stats
34 from indico
.modules
.rb
.views
.user
.rooms
import (WPRoomBookingSearchRooms
, WPRoomBookingMapOfRooms
,
35 WPRoomBookingMapOfRoomsWidget
, WPRoomBookingRoomDetails
,
36 WPRoomBookingRoomStats
, WPRoomBookingSearchRoomsResults
)
37 from indico
.web
.forms
.base
import FormDefaults
38 from MaKaC
.common
.cache
import GenericCache
41 class RHRoomBookingMapOfRooms(RHRoomBookingBase
):
42 def _checkParams(self
):
43 RHRoomBookingBase
._checkParams
(self
, request
.args
)
44 self
._room
_id
= request
.args
.get('roomID')
47 return WPRoomBookingMapOfRooms(self
, roomID
=self
._room
_id
).display()
50 class RHRoomBookingMapOfRoomsWidget(RHRoomBookingBase
):
51 def __init__(self
, *args
, **kwargs
):
52 RHRoomBookingBase
.__init
__(self
, *args
, **kwargs
)
53 self
._cache
= GenericCache('MapOfRooms')
55 def _checkParams(self
):
56 RHRoomBookingBase
._checkParams
(self
, request
.args
)
57 self
._room
_id
= request
.args
.get('roomID')
60 key
= str(sorted(dict(request
.args
, lang
=session
.lang
, user
=session
.user
.id).items()))
61 html
= self
._cache
.get(key
)
63 default_location
= Location
.default_location
64 aspects
= [a
.to_serializable() for a
in default_location
.aspects
]
65 buildings
= default_location
.get_buildings()
66 html
= WPRoomBookingMapOfRoomsWidget(self
,
69 room_id
=self
._room
_id
,
70 default_repeat
='{}|0'.format(int(RepeatFrequency
.NEVER
)),
71 default_start_dt
=datetime
.combine(date
.today(),
72 Location
.working_time_start
),
73 default_end_dt
=datetime
.combine(date
.today(),
74 Location
.working_time_end
),
75 repeat_mapping
=RepeatMapping
.mapping
).display()
76 self
._cache
.set(key
, html
, 3600)
80 class RHRoomBookingSearchRooms(RHRoomBookingBase
):
81 menu_item
= 'roomSearch'
83 def _get_form_data(self
):
86 def _checkParams(self
):
87 defaults
= FormDefaults(location
=Location
.default_location
)
88 self
._form
= SearchRoomsForm(self
._get
_form
_data
(), obj
=defaults
)
89 if (not session
.user
or not Room
.user_owns_rooms(session
.user
)) and not hasattr(self
, 'search_criteria'):
90 # Remove the form element if the user has no rooms and we are not using a shortcut
91 del self
._form
.is_only_my_rooms
93 def _is_submitted(self
):
94 return self
._form
.is_submitted()
98 if self
._is
_submitted
() and form
.validate():
99 rooms
= Room
.find_with_filters(form
.data
, session
.user
)
100 return WPRoomBookingSearchRoomsResults(self
, self
.menu_item
, rooms
=rooms
).display()
101 equipment_locations
= {eq
.id: eq
.location_id
for eq
in EquipmentType
.find()}
102 return WPRoomBookingSearchRooms(self
, form
=form
, errors
=form
.error_list
, rooms
=Room
.find_all(),
103 equipment_locations
=equipment_locations
).display()
106 class RHRoomBookingSearchRoomsShortcutBase(RHRoomBookingSearchRooms
):
107 """Base class for searches with predefined criteria"""
110 def _is_submitted(self
):
113 def _get_form_data(self
):
114 return MultiDict(self
.search_criteria
)
117 class RHRoomBookingSearchMyRooms(RHRoomBookingSearchRoomsShortcutBase
):
118 menu_item
= 'myRoomList'
120 'is_only_my_rooms': True,
125 class RHRoomBookingRoomDetails(RHRoomBookingBase
):
128 def _checkParams(self
):
129 self
._calendar
_start
= datetime
.combine(date
.today(), time())
130 self
._calendar
_end
= datetime
.combine(date
.today(), time(23, 59))
132 preview_months
= int(request
.args
.get('preview_months', '0'))
133 except (TypeError, ValueError):
135 self
._calendar
_end
+= timedelta(days
=31 * preview_months
)
137 def _get_view(self
, **kwargs
):
138 return WPRoomBookingRoomDetails(self
, **kwargs
)
141 occurrences
= ReservationOccurrence
.find_all(
142 Reservation
.room_id
== self
._room
.id,
143 ReservationOccurrence
.start_dt
>= self
._calendar
_start
,
144 ReservationOccurrence
.end_dt
<= self
._calendar
_end
,
145 ReservationOccurrence
.is_valid
,
147 _eager
=ReservationOccurrence
.reservation
150 return self
._get
_view
(room
=self
._room
, start_dt
=self
._calendar
_start
, end_dt
=self
._calendar
_end
,
151 occurrences
=occurrences
).display()
154 class RHRoomBookingRoomStats(RHRoomBookingBase
):
155 def _checkParams(self
):
156 self
._room
= Room
.get(request
.view_args
['roomID'])
157 self
._occupancy
_period
= request
.args
.get('period', 'pastmonth')
158 self
._end
= date
.today()
159 if self
._occupancy
_period
== 'pastmonth':
160 self
._end
= self
._end
- relativedelta(days
=1)
161 self
._start
= self
._end
- relativedelta(days
=29)
162 elif self
._occupancy
_period
== 'thisyear':
163 self
._start
= date(self
._end
.year
, 1, 1)
164 elif self
._occupancy
_period
== 'sinceever':
165 self
._start
= Reservation
.query
.with_entities(func
.min(Reservation
.start_dt
)).one()[0].date()
167 raise IndicoError('Invalid period specified')
170 return WPRoomBookingRoomStats(self
,
172 period
=self
._occupancy
_period
,
173 occupancy
=calculate_rooms_occupancy([self
._room
], self
._start
, self
._end
),
174 stats
=compose_rooms_stats([self
._room
])).display()