- Timestamp:
- 20 Sep 2012, 08:49:37 (12 years ago)
- Location:
- main/waeup.kofa/branches/uli-zc-async
- Files:
-
- 7 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
main/waeup.kofa/branches/uli-zc-async
- Property svn:mergeinfo changed
-
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/browser.py
r9166 r9209 93 93 94 94 def title(self): 95 co = self.context. getBedCoordinates()95 co = self.context.coordinates 96 96 return _('Block ${a}, Room ${b}, Bed ${c}', 97 97 mapping = {'a':co[1], 'b':co[2], 'c':co[3]}) … … 130 130 form_fields = grok.AutoFields(IHostelsContainer) 131 131 taboneactions = [_('Save')] 132 tabtwoactions = [_('Add hostel'), _('Remove selected')] 132 tabtwoactions = [_('Add hostel'), 133 _('Clear all hostels'), 134 _('Remove selected')] 133 135 134 136 def update(self): … … 164 166 return 165 167 168 @jsaction(_('Clear all hostels')) 169 def clearHostels(self, **data): 170 self.context.clearAllHostels() 171 self.flash(_('All hostels cleared.')) 172 write_log_message(self, 'all hostels cleared') 173 self.redirect(self.url(self.context, '@@manage')+'?tab2') 174 return 175 166 176 @action(_('Save'), style='primary') 167 177 def save(self, **data): … … 232 242 tabtwoactions = [_('Update all beds'), 233 243 _('Switch reservation of selected beds'), 234 _('Release selected beds')] 244 _('Release selected beds'), 245 _('Clear hostel')] 235 246 not_occupied = NOT_OCCUPIED 236 247 … … 243 254 tabs.need() 244 255 datatable.need() 256 warning.need() 245 257 self.tab1 = self.tab2 = '' 246 258 qs = self.request.get('QUERY_STRING', '') … … 327 339 return 328 340 341 @jsaction(_('Clear hostel')) 342 def clearHostel(self, **data): 343 self.context.clearHostel() 344 self.flash(_('Hostel cleared.')) 345 write_log_message(self, 'cleared') 346 self.redirect(self.url(self.context, '@@manage')+'?tab2') 347 return 348 329 349 class BedManageFormPage(KofaEditFormPage): 330 350 """ View to edit bed data … … 334 354 grok.require('waeup.manageHostels') 335 355 form_fields = grok.AutoFields(IBedAllocateStudent).omit( 336 'bed_id' ).omit('bed_number').omit('bed_type')356 'bed_id', 'bed_number', 'bed_type') 337 357 label = _('Allocate student') 338 358 pnav = 5 -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/browser_templates/containerpage.pt
r8685 r9209 21 21 <th i18n:translate="">Id</th> 22 22 <th i18n:translate="">Name</th> 23 <th i18n:translate="">Booked Beds</th> 23 24 </tr> 24 25 </thead> 25 26 <tbody> 26 <tr tal:repeat="value context/values"> 27 <td> <a tal:attributes="href value/__name__"> 28 <span tal:content="value/hostel_id">ID</span></a></td> 29 <td tal:content="value/hostel_name">NAME</td> 30 </tr> 27 <tal:tbody repeat="value context/values"> 28 <tr tal:define = "stats value/bed_statistics"> 29 <td> <a tal:attributes="href value/__name__"> 30 <span tal:content="value/hostel_id">ID</span></a></td> 31 <td tal:content="value/hostel_name">NAME</td> 32 <td> 33 <span tal:replace="stats/booked">10</span> of <span tal:replace="stats/total">100</span> 34 </td> 35 </tr> 36 </tal:tbody> 31 37 </tbody> 32 38 </table> -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/container.py
r8686 r9209 51 51 return 52 52 53 def clearAllHostels(self): 54 """Clear all hostels. 55 """ 56 for hostel in self.values(): 57 hostel.clearHostel() 58 return 59 53 60 logger_name = 'waeup.kofa.${sitename}.hostels' 54 61 logger_filename = 'hostels.log' -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/hostel.py
r8685 r9209 22 22 from zope.event import notify 23 23 from zope.component import getUtility 24 from zope.component.interfaces import IFactory 24 25 from datetime import datetime 25 26 from waeup.kofa.utils.helpers import attrs_to_fields … … 40 41 target = self.__name__ 41 42 return grok.getSite()['hostels'].logger_info(ob_class,target,comment) 43 44 @property 45 def bed_statistics(self): 46 total = len(self.keys()) 47 booked = 0 48 for value in self.values(): 49 if value.owner != NOT_OCCUPIED: 50 booked += 1 51 return {'booked':booked, 'total':total} 52 53 def clearHostel(self): 54 """Remove all beds 55 """ 56 keys = [i for i in self.keys()] # create deep copy 57 for bed in keys: 58 del self[bed] 59 return 42 60 43 61 def addBed(self, bed): … … 128 146 grok.provides(IBed) 129 147 130 def getBedCoordinates(self): 148 @property 149 def coordinates(self): 131 150 """Determine the coordinates from the bed_id. 132 151 """ 133 152 return self.bed_id.split('_') 153 154 # The following property attributes are only needed 155 # for the exporter to ease evaluation with Excel. 156 157 @property 158 def hall(self): 159 return self.coordinates[0] 160 161 @property 162 def block(self): 163 return self.coordinates[1] 164 165 @property 166 def room(self): 167 return self.coordinates[2] 168 169 @property 170 def bed(self): 171 return self.coordinates[3] 172 173 @property 174 def special_handling(self): 175 return self.bed_type.split('_')[0] 176 177 @property 178 def sex(self): 179 return self.bed_type.split('_')[1] 180 181 @property 182 def bt(self): 183 return self.bed_type.split('_')[2] 184 134 185 135 186 def bookBed(self, student_id): … … 145 196 """ 146 197 sh, sex, bt = self.bed_type.split('_') 147 hostel_id, block, room_nr, bed = self. getBedCoordinates()198 hostel_id, block, room_nr, bed = self.coordinates 148 199 hostel = self.__parent__ 149 200 beds_for_fresh = getattr(hostel,'beds_for_fresh',[]) … … 221 272 Bed = attrs_to_fields(Bed) 222 273 274 class HostelFactory(grok.GlobalUtility): 275 """A factory for hostels. 276 277 We need this factory for the hostel processor. 278 """ 279 grok.implements(IFactory) 280 grok.name(u'waeup.Hostel') 281 title = u"Create a new hostel.", 282 description = u"This factory instantiates new hostel instances." 283 284 def __call__(self, *args, **kw): 285 return Hostel() 286 287 def getInterfaces(self): 288 return implementedBy(Hostel) 289 290 223 291 @grok.subscribe(IBedTicket, grok.IObjectRemovedEvent) 224 292 def handle_bedticket_removed(bedticket, event): … … 229 297 bedticket.bed.owner = NOT_OCCUPIED 230 298 notify(grok.ObjectModifiedEvent(bedticket.bed)) 299 -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/interfaces.py
r8685 r9209 17 17 ## 18 18 from datetime import datetime 19 from zope.interface import invariant, Invalid 19 from zope.interface import invariant, Invalid, Attribute 20 20 from zope import schema 21 21 from waeup.kofa.interfaces import ( … … 58 58 ) 59 59 60 def clearAllHostels(): 61 """Clear all hostels. 62 """ 63 60 64 class IHostel(IKofaObject): 61 65 """A base representation of hostels. … … 63 67 """ 64 68 69 bed_statistics = Attribute('Number of booked and total beds') 70 65 71 def loggerInfo(ob_class, comment): 66 72 """Adds an INFO message to the log file 73 """ 74 75 def clearHostel(): 76 """Remove all beds. 67 77 """ 68 78 … … 125 135 ) 126 136 137 beds_for_pre= schema.List( 138 title = _(u'Beds for Pre-Study Students'), 139 value_type = schema.Choice( 140 vocabulary = bed_letters 141 ), 142 ) 143 127 144 beds_for_fresh = schema.List( 128 145 title = _(u'Beds for Fresh Students'), … … 172 189 hostel.beds_for_returning + 173 190 hostel.beds_for_final + 191 hostel.beds_for_pre + 174 192 hostel.beds_for_all) 175 193 if len(beds) != len(set(beds)): … … 181 199 """ 182 200 201 coordinates = Attribute('The coordinates of the bed from bed_id') 202 183 203 def loggerInfo(ob_class, comment): 184 204 """Adds an INFO message to the log file 185 205 """ 186 206 187 def getBedCoordinates():188 """Determine the coordinates from bed_id.189 """190 207 def bookBed(student_id): 191 208 """Book a bed for a student. -
main/waeup.kofa/branches/uli-zc-async/src/waeup/kofa/hostels/tests.py
r8686 r9209 19 19 Tests for hostels and their UI components. 20 20 """ 21 import os 21 22 import shutil 22 23 import tempfile … … 36 37 from waeup.kofa.hostels.container import HostelsContainer 37 38 from waeup.kofa.hostels.hostel import Hostel, Bed 39 from waeup.kofa.hostels.batching import HostelProcessor 40 from waeup.kofa.hostels.export import BedExporter, HostelExporter 38 41 from waeup.kofa.testing import (FunctionalLayer, FunctionalTestCase) 39 42 from waeup.kofa.students.student import Student 40 43 from waeup.kofa.students.accommodation import BedTicket 41 44 from waeup.kofa.university.department import Department 45 46 HOSTEL_SAMPLE_DATA = open( 47 os.path.join(os.path.dirname(__file__), 'sample_hostel_data.csv'), 48 'rb').read() 49 50 HOSTEL_HEADER_FIELDS = HOSTEL_SAMPLE_DATA.split( 51 '\n')[0].split(',') 42 52 43 53 class HostelsContainerTestCase(FunctionalTestCase): … … 142 152 # Create a bed 143 153 bed = Bed() 144 bed.bed_id = u' xyz'154 bed.bed_id = u'hall_block_room_bed' 145 155 bed.bed_number = 1 146 bed.bed_type = u'a bc'156 bed.bed_type = u'a_b_c' 147 157 self.app['hostels'][hostel.hostel_id][bed.bed_id] = bed 148 158 … … 157 167 self.browser.handleErrors = False 158 168 169 self.logfile = os.path.join( 170 self.app['datacenter'].storage, 'logs', 'hostels.log') 171 159 172 def tearDown(self): 160 173 super(HostelsFullSetup, self).tearDown() … … 174 187 # We can find a certain bed 175 188 cat = queryUtility(ICatalog, name='beds_catalog') 176 results = cat.searchResults(bed_type=(u'a bc', u'abc'))189 results = cat.searchResults(bed_type=(u'a_b_c', u'a_b_c')) 177 190 results = [x for x in results] # Turn results generator into list 178 191 assert len(results) == 1 179 assert results[0] is self.app['hostels']['hall-x'][' xyz']192 assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed'] 180 193 181 194 def test_search_by_owner(self): 182 195 # We can find a certain bed 183 myobj = self.app['hostels']['hall-x'][' xyz']196 myobj = self.app['hostels']['hall-x']['hall_block_room_bed'] 184 197 myobj.owner = u'abc' 185 198 notify(grok.ObjectModifiedEvent(myobj)) … … 188 201 results = [x for x in results] # Turn results generator into list 189 202 assert len(results) == 1 190 assert results[0] is self.app['hostels']['hall-x'][' xyz']203 assert results[0] is self.app['hostels']['hall-x']['hall_block_room_bed'] 191 204 192 205 class HostelsUITests(HostelsFullSetup): … … 300 313 self.assertMatches( 301 314 '...No allocated bed selected...', self.browser.contents) 302 # Managers can manually allocate studen stafter cancellation315 # Managers can manually allocate students after cancellation 303 316 self.browser.open(self.container_path + '/hall-1/hall-1_A_101_A') 304 317 self.browser.getControl(name="form.owner").value = [self.student_id] … … 334 347 # Also the number of the bed has changed. 335 348 self.assertFalse(new_number == old_number) 349 # The number of occupied bed are displayed on container page. 350 self.browser.open(self.container_path) 351 self.assertTrue('1 of 8' in self.browser.contents) 336 352 # Remove entire hostel 337 353 self.browser.open(self.manage_container_path) … … 346 362 results = [x for x in results] 347 363 assert len(results) == 0 364 365 def test_clear_hostels(self): 366 self.browser.addHeader('Authorization', 'Basic mgr:mgrpw') 367 self.browser.open(self.container_path) 368 self.browser.getLink("Manage accommodation").click() 369 self.browser.getControl("Add hostel").click() 370 self.browser.getControl("Create hostel").click() 371 hall = self.app['hostels']['hall-1'] 372 hall.blocks_for_female = ['A','B'] 373 hall.rooms_per_floor = 1 374 hall.beds_for_fresh = ['A'] 375 hall.beds_for_returning = ['B'] 376 hall.beds_for_final = ['C'] 377 hall.beds_for_all = ['D','E'] 378 self.browser.open(self.container_path + '/hall-1/manage') 379 self.browser.getControl("Update all beds").click() 380 cat = queryUtility(ICatalog, name='beds_catalog') 381 results = cat.searchResults(bed_type=(None, None)) 382 self.assertEqual(len(results), 11) 383 self.browser.getControl("Clear hostel").click() 384 self.assertEqual(len(self.app['hostels']['hall-1']), 0) 385 # Only the bed in hall-x remains in the catalog. 386 results = cat.searchResults(bed_type=(None, None)) 387 self.assertEqual(len(results), 1) 388 # We can clear all hostels at the same time. 389 self.browser.open(self.manage_container_path) 390 self.browser.getControl("Clear all hostels").click() 391 results = cat.searchResults(bed_type=(None, None)) 392 self.assertEqual(len(results), 0) 393 # Both actions have been logged. 394 logcontent = open(self.logfile).read() 395 self.assertTrue('INFO - zope.mgr - hostels.browser.HostelManageFormPage' 396 ' - hall-1 - cleared' in logcontent) 397 self.assertTrue('zope.mgr - hostels.browser.HostelsContainerManagePage' 398 ' - hostels - all hostels cleared' in logcontent) 399 400 class ExportTests(HostelsFullSetup): 401 402 layer = FunctionalLayer 403 404 def setUp(self): 405 super(ExportTests, self).setUp() 406 self.workdir = tempfile.mkdtemp() 407 self.outfile = os.path.join(self.workdir, 'myoutput.csv') 408 return 409 410 def test_export_hostels(self): 411 exporter = HostelExporter() 412 exporter.export_all(self.app, self.outfile) 413 result = open(self.outfile, 'rb').read() 414 self.assertEqual( 415 result, 416 'beds_for_all,beds_for_final,beds_for_fresh,beds_for_pre,' 417 'beds_for_returning,beds_reserved,blocks_for_female,' 418 'blocks_for_male,floors_per_block,hostel_id,hostel_name,' 419 'rooms_per_floor,sort_id,special_handling\r\n,,,,,[],,,1,' 420 'hall-x,Hall 1,2,10,regular\r\n' 421 ) 422 return 423 424 def test_export_beds(self): 425 exporter = BedExporter() 426 exporter.export_all(self.app, self.outfile) 427 result = open(self.outfile, 'rb').read() 428 self.assertEqual( 429 result, 430 'bed_id,bed_number,bed_type,owner,hall,block,room,bed,' 431 'special_handling,sex,bt\r\nhall_block_room_bed,1,a_b_c,,' 432 'hall,block,room,bed,a,b,c\r\n' 433 ) 434 return 435 436 class HostelProcessorTest(HostelsFullSetup): 437 438 layer = FunctionalLayer 439 440 def test_import(self): 441 self.processor = HostelProcessor() 442 self.workdir = tempfile.mkdtemp() 443 self.csv_file = os.path.join(self.workdir, 'sample_student_data.csv') 444 open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA) 445 num, num_warns, fin_file, fail_file = self.processor.doImport( 446 self.csv_file, HOSTEL_HEADER_FIELDS) 447 self.assertEqual(num_warns,0) 448 self.assertEqual(len(self.app['hostels'].keys()), 11) # including hall-x 449 self.assertEqual(self.app['hostels'][ 450 'block-a-upper-hostel'].hostel_id,'block-a-upper-hostel') 451 self.assertEqual(self.app['hostels'][ 452 'block-a-upper-hostel'].beds_for_final, ['A', 'B']) 453 logcontent = open(self.logfile).read() 454 self.assertTrue( 455 "Hostel Processor - block-a-upper-hostel - " 456 "Record updated: beds_for_pre=['G'], floors_per_block=1, " 457 "beds_for_final=['A', 'B'], rooms_per_floor=32, " 458 "blocks_for_male=[], hostel_id=block-a-upper-hostel, " 459 "sort_id=20, beds_for_returning=['C', 'D'], " 460 "hostel_name=Block A Upper Hostel, beds_for_fresh=['E', 'F'], " 461 "blocks_for_female=['A'], beds_for_all=[], beds_reserved=[]" 462 in logcontent) 463 shutil.rmtree(os.path.dirname(fin_file)) 464 return
Note: See TracChangeset for help on using the changeset viewer.