Ignore:
Timestamp:
25 Jan 2023, 08:52:51 (2 years ago)
Author:
Henrik Bettermann
Message:

Allow beds to be blocked so that no student can be allocated to such a bed space (in contrast to reserved beds)

Location:
main/waeup.kofa/trunk
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/CHANGES.txt

    r17307 r17313  
    441.8.2.dev0 (unreleased)
    55=======================
     6
     7* Allow beds to be blocked so that no student can be allocated to such a bed space
     8  (in contrast to reserved beds)
    69
    710* Upgrade packages for helper tools to Python3-compatible versions. Requires
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/__init__.py

    r7811 r17313  
    1 """This package contains everything regarding hostels.
    2 """
    31# Make this a package.
    4 from waeup.kofa.hostels.container import HostelsContainer
    5 from waeup.kofa.hostels.hostel import Hostel, Bed
    6 
    7 __all__ = [
    8     'HostelsContainer',
    9     'Hostel',
    10     'Bed',
    11     ]
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py

    r13434 r17313  
    8383class BedProcessor(BatchProcessor):
    8484    """The Bed Procesor update beds. It allocates students
    85     to empty beds and switches the reservation status of beds. ``1``
    86     means reserved and ``0`` unreserved. Beds cannot be released
    87     by import.
     85    to empty beds and switches the reservation or blockade status of beds. ``1``
     86    means reserved (or blocked) and ``0`` unreserved (or unblocked).
     87    Beds cannot be released by import.
    8888    """
    8989    grok.implements(IBatchProcessor)
     
    103103    @property
    104104    def available_fields(self):
    105         return self.location_fields + ['reserved', 'owner']
     105        return self.location_fields + ['reserved', 'blocked', 'owner']
    106106
    107107    def parentsExist(self, row, site):
     
    132132        if row.get('owner') and obj.owner != NOT_OCCUPIED:
    133133            return 'Bed is occupied.'
     134        # Check if bed is blocked and not unblocked by the importer
     135        if obj.bed_type.endswith('blocked') and \
     136            row.get('owner') not in (None, '', IGNORE_MARKER) and \
     137            row.get('blocked') != '0':
     138            return 'Bed is blocked.'
    134139
    135140    def checkConversion(self, row, mode='ignore'):
     
    142147        if reserved not in (None, IGNORE_MARKER, '', '0', '1'):
    143148            errs.append(('reserved','invalid value'))
     149        blocked = row.get('blocked')
     150        if blocked not in (None, IGNORE_MARKER, '', '0', '1'):
     151            errs.append(('blocked','invalid value'))
    144152        owner = row.get('owner')
    145153        if owner not in (None, '', IGNORE_MARKER):
     
    168176            obj.bookBed(owner)
    169177            changed.append('owner=%s' % owner)
     178        sh, sex, bt = obj.bed_type.split('_')
    170179        reserved = row.get('reserved')
    171         sh, sex, bt = obj.bed_type.split('_')
    172180        if (reserved == '1' and bt != 'reserved') or \
    173181            (reserved == '0'and bt == 'reserved'):
    174             message = obj.switchReservation()
     182            message = obj.switchBed('reserved')
     183            changed.append(message)
     184        blocked = row.get('blocked')
     185        if (blocked == '1' and bt != 'blocked') or \
     186            (blocked == '0'and bt == 'blocked'):
     187            message = obj.switchBed('blocked')
    175188            changed.append(message)
    176189        # Log actions...
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser.py

    r15633 r17313  
    266266    grok.name('addhostel')
    267267    #grok.template('hosteladdpage')
    268     form_fields = grok.AutoFields(IHostel).omit('beds_reserved', 'hostel_id')
     268    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
    269269    label = _('Add hostel')
    270270    pnav = 5
     
    294294    grok.require('waeup.viewHostels')
    295295    grok.template('hostelpage')
    296     form_fields = grok.AutoFields(IHostel).omit('beds_reserved')
     296    form_fields = grok.AutoFields(IHostel)
    297297    pnav = 5
    298298
     
    315315    grok.name('manage')
    316316    grok.require('waeup.manageHostels')
    317     form_fields = grok.AutoFields(IHostel).omit('hostel_id', 'beds_reserved')
     317    form_fields = grok.AutoFields(IHostel).omit('hostel_id')
    318318    grok.template('hostelmanagepage')
    319319    label = _('Manage hostel')
     
    322322    tabtwoactions = [_('Update all beds'),
    323323        _('Switch reservation of selected beds'),
     324        _('Switch blockade of selected beds'),
    324325        _('Release selected beds'),
    325326        _('Clear hostel')]
     
    337338
    338339    @action(_('Update all beds'), style='primary',
    339             warning=_('Attention: The updater removes all reservation flags of existing beds.'
    340                         ' You really want to update?'))
     340            warning=_('Attention: The updater removes all reservation and '
     341                        'blockade flags of existing beds. '
     342                        'You really want to update?'))
    341343    def updateBeds(self, **data):
    342344        if not grok.getSite()['configuration'].maintmode_enabled_by:
     
    364366        return
    365367
    366     @action(_('Switch reservation of selected beds'))
    367     def switchReservations(self, **data):
     368    def _switchBeds(self, switch_type):
    368369        form = self.request.form
    369370        if 'val_id' in form:
     
    380381        preferred_language = self.request.cookies.get('kofa.language')
    381382        for bed_id in child_id:
    382             message = self.context[bed_id].switchReservation()
     383            message = self.context[bed_id].switchBed(switch_type)
    383384            switched.append('%s (%s)' % (bed_id,message))
    384385            m_translated = translate(message, 'waeup.kofa',
     
    396397            self.context.writeLogMessage(self, 'switched: %s' % message)
    397398            self.redirect(self.url(self.context, '@@manage')+'#tab2')
     399            return
     400
     401
     402    @action(_('Switch reservation of selected beds'))
     403    def switchReservations(self, **data):
     404        self._switchBeds('reserved')
     405        return
     406
     407    @action(_('Switch blockade of selected beds'))
     408    def switchBockade(self, **data):
     409        self._switchBeds('blocked')
    398410        return
    399411
     
    456468
    457469    def update(self):
     470        if self.context.bed_type.endswith('blocked'):
     471            # No student can reside in a blocked bed.
     472            self.redirect(self.url(self.context.__parent__, '@@manage')+'#tab2')
    458473        if self.context.owner != NOT_OCCUPIED:
    459474            # Don't use this form for exchanging students.
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/browser_templates/hostelmanagepage.pt

    r13346 r17313  
    5959                <span tal:content="value/owner">OWNER</span>
    6060              </a>
    61               <a tal:condition="python: value.owner == view.not_occupied"
     61              <a tal:condition="python: value.owner == view.not_occupied and not value.bed_type.endswith('blocked')"
    6262                 tal:attributes="href python: view.url(value)"
    6363                 i18n:translate="">
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/hostel.py

    r15944 r17313  
    198198            return self.owner
    199199
    200     def switchReservation(self):
    201         """Reserves or unreserve bed respectively.
     200    def switchBed(self, switch_type):
     201        """Switches bed. `switch_type` is either `reserved` or `blocked`.
    202202        """
    203203        sh, sex, bt = self.bed_type.split('_')
     
    209209        beds_for_final = getattr(hostel,'beds_for_final',[])
    210210        bed_string = u'%s_%s_%s' % (block, room_nr, bed)
    211         if bt == 'reserved':
     211        if bt == switch_type:
    212212            bt = 'all'
    213213            if bed in beds_for_fresh:
     
    220220                bt = 're'
    221221            bt = u'%s_%s_%s' % (sh, sex, bt)
    222             message = _(u'unreserved')
     222            message = _(u'un' + switch_type)
    223223        else:
    224             bt = u'%s_%s_reserved' % (sh, sex)
    225             message = _(u'reserved')
     224            bt = u'%s_%s_%s' % (sh, sex, switch_type)
     225            message = switch_type
    226226        self.bed_type = bt
    227227        notify(grok.ObjectModifiedEvent(self))
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/interfaces.py

    r17176 r17313  
    2828    bed_letters, blocks, SpecialHandlingSource,
    2929    NOT_OCCUPIED)
    30 from waeup.kofa.students.interfaces import (IStudentsUtils)
     30from waeup.kofa.students.interfaces import IStudentsUtils
    3131
    3232# Define a validation method for sort ids
     
    248248        """
    249249
    250     def switchReservation():
    251         """Reserves bed or relases reserved bed respectively.
     250    def switchBed(switch_type):
     251        """Switches reservation or blockade.
    252252        """
    253253
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/sample_bed_data.csv

    r13432 r17313  
    1 hostel_id,bed_id,owner,reserved
    2 block-a-upper-hostel,block-a-upper-hostel_A_101_A,,0
    3 block-a-upper-hostel,block-a-upper-hostel_A_101_B,,1
    4 block-a-upper-hostel,block-a-upper-hostel_A_101_C,,2
    5 block-a-upper-hostel,block-a-upper-hostel_A_101_D,K1000000,0
    6 block-a-upper-hostel,block-a-upper-hostel_A_101_E,K999,0
     1hostel_id,bed_id,owner,reserved,blocked
     2block-a-upper-hostel,block-a-upper-hostel_A_101_A,,0,1
     3block-a-upper-hostel,block-a-upper-hostel_A_101_B,,1,0
     4block-a-upper-hostel,block-a-upper-hostel_A_101_C,,2,0
     5block-a-upper-hostel,block-a-upper-hostel_A_101_D,K1000000,0,0
     6block-a-upper-hostel,block-a-upper-hostel_A_101_E,K999,0,0
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py

    r17176 r17313  
    3131from zope.security.interfaces import Unauthorized
    3232from zope.catalog.interfaces import ICatalog
    33 from zope.component import queryUtility, getUtility
     33from zope.component import queryUtility, getUtility, createObject
    3434from waeup.kofa.app import University
    3535from waeup.kofa.hostels.interfaces import (
     
    5454BED_SAMPLE_DATA = open(
    5555    os.path.join(os.path.dirname(__file__), 'sample_bed_data.csv'),
     56    'rb').read()
     57
     58BED_SAMPLE_DATA_2 = open(
     59    os.path.join(os.path.dirname(__file__), 'sample_bed_data_2.csv'),
    5660    'rb').read()
    5761
     
    396400             (u'hall-1_A_101_C', u'regular_female_reserved'),
    397401             (u'hall-1_A_101_D', u'regular_female_reserved')])
     402        # Block beds.
     403        self.browser.getControl("Switch blockade", index=0).click()
     404        self.assertTrue('No item selected' in self.browser.contents)
     405        ctrl = self.browser.getControl(name='val_id')
     406        ctrl.getControl(value='hall-1_A_101_A').selected = True
     407        ctrl.getControl(value='hall-1_A_101_B').selected = True
     408        ctrl.getControl(value='hall-1_A_101_C').selected = True
     409        ctrl.getControl(value='hall-1_A_101_D').selected = True
     410        self.browser.getControl("Switch blockade", index=0).click()
     411        self.assertTrue('Successfully switched beds: hall-1_A_101_A (blocked)'
     412            in self.browser.contents)
     413        self.assertEqual(self.app['hostels']['hall-1'][
     414            'hall-1_A_101_D'].bed_type, 'regular_female_blocked')
     415        # The catalog has been updated.
     416        results = cat.searchResults(
     417            bed_type=('regular_female_all', 'regular_female_all'))
     418        results = [(x.bed_id, x.bed_type) for x in results]
     419        self.assertEqual(results,
     420            [(u'hall-1_A_101_E', u'regular_female_all'),
     421             (u'hall-1_B_101_D', u'regular_female_all'),
     422             (u'hall-1_B_101_E', u'regular_female_all')])
     423        results = cat.searchResults(
     424            bed_type=('regular_female_blocked', 'regular_female_blocked'))
     425        results = [(x.bed_id, x.bed_type) for x in results]
     426        self.assertEqual(results,
     427            [(u'hall-1_A_101_A', u'regular_female_blocked'),
     428             (u'hall-1_A_101_B', u'regular_female_blocked'),
     429             (u'hall-1_A_101_C', u'regular_female_blocked'),
     430             (u'hall-1_A_101_D', u'regular_female_blocked')])
    398431        # Change hostel configuration with one bed booked.
    399432        hall['hall-1_A_101_E'].owner = u'anyid'
     
    672705        logcontent = open(self.logfile).read()
    673706        self.assertEqual(
    674             'owner,bed_id,hostel_id,reserved,--ERRORS--\r\n'
    675             '<IGNORE>,block-a-upper-hostel_A_101_C,block-a-upper-hostel,2,'
     707            'owner,bed_id,hostel_id,reserved,blocked,--ERRORS--\r\n'
     708            '<IGNORE>,block-a-upper-hostel_A_101_C,block-a-upper-hostel,2,0,'
    676709            'reserved: invalid value\r\n'
    677             'K999,block-a-upper-hostel_A_101_E,block-a-upper-hostel,0,'
     710            'K999,block-a-upper-hostel_A_101_E,block-a-upper-hostel,0,0,'
    678711            'owner: student does not exist\r\n',
    679712            fail_file_content)
    680713        self.assertTrue(
    681714            'system - Bed Processor (update only) - sample_bed_data - '
    682             'block-a-upper-hostel_A_101_A - updated: nothing'
     715            'block-a-upper-hostel_A_101_A - updated: blocked'
    683716            in logcontent)
    684717        self.assertTrue(
     
    697730                    ['block-a-upper-hostel_A_101_B'].bed_type,
    698731                    'regular_female_reserved')
     732        # Add another student K1000001
     733        student = createObject('waeup.Student')
     734        student.firstname = u'Claus'
     735        student.lastname = u'Tester'
     736        self.app['students'].addStudent(student)
     737        # Try to allocate this student to a blocked bed
     738
     739        open(self.csv_file, 'wb').write(BED_SAMPLE_DATA_2)
     740        num, num_warns, fin_file, fail_file = self.processor.doImport(
     741            self.csv_file, BED_HEADER_FIELDS, 'update')
     742        fail_file_content = open(fail_file).read()
     743        self.assertEqual(
     744            'owner,bed_id,hostel_id,reserved,blocked,--ERRORS--\r\n'
     745            'K1000001,block-a-upper-hostel_A_101_A,block-a-upper-hostel,'
     746            '<IGNORE>,<IGNORE>,Bed is blocked.\r\n',
     747            fail_file_content)
    699748        shutil.rmtree(os.path.dirname(fin_file))
    700749        shutil.rmtree(self.workdir)
  • main/waeup.kofa/trunk/src/waeup/kofa/students/__init__.py

    r7811 r17313  
    1 """This package contains everything regarding students.
    2 """
    31# Make this a package.
    4 from waeup.kofa.students.student import (
    5     Student, StudentFactory
    6     )
    7 from waeup.kofa.students.container import StudentsContainer
    8 from waeup.kofa.students.studycourse import StudentStudyCourse
    9 from waeup.kofa.students.payments import StudentPaymentsContainer
    10 from waeup.kofa.students.accommodation import StudentAccommodation
    11 from waeup.kofa.students.dynamicroles import StudentPrincipalRoleManager
    12 
    13 
    14 __all__ = [
    15     'Student',
    16     'StudentFactory',
    17     'StudentsContainer',
    18     'StudentStudyCourse',
    19     'StudentPaymentsContainer',
    20     'StudentAccommodation',
    21     'StudentPrincipalRoleManager',
    22     ]
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_dynamicroles.py

    r10639 r17313  
    2727from waeup.kofa.app import University
    2828from waeup.kofa.students.tests.test_browser import StudentsFullSetup
    29 from waeup.kofa.students import Student, StudentPrincipalRoleManager
     29from waeup.kofa.students.student import Student
     30from waeup.kofa.students.dynamicroles import StudentPrincipalRoleManager
    3031
    3132class StudentPrincipalRoleManagerTests(APRMTest):
Note: See TracChangeset for help on using the changeset viewer.