Ignore:
Timestamp:
10 Nov 2015, 13:06:25 (9 years ago)
Author:
Henrik Bettermann
Message:

Add BedProcessor?.

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

Legend:

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

    r13394 r13432  
    441.3.4.dev0 (unreleased)
    55=======================
     6
     7* Add BedProcessor.
    68
    79* Add portal maintenance mode.
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py

    r13159 r13432  
    2121import grok
    2222from zope.interface import Interface
     23from zope.component import getUtility
     24from zope.catalog.interfaces import ICatalog
    2325from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER
    2426from waeup.kofa.utils.batching import BatchProcessor
    25 from waeup.kofa.hostels.interfaces import IHostel
     27from waeup.kofa.hostels.interfaces import IHostel, IBed
     28from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
    2629from waeup.kofa.interfaces import MessageFactory as _
    2730
     
    7679            % (self.name, filename, row[location_field], items_changed))
    7780        return
     81
     82
     83class BedProcessor(BatchProcessor):
     84    """The Bed Procesor update beds. It does allocate students
     85    to empty beds and switches the reservation status of beds.
     86    """
     87    grok.implements(IBatchProcessor)
     88    grok.provides(IBatchProcessor)
     89    grok.context(Interface)
     90    util_name = 'bedupdater'
     91    grok.name(util_name)
     92
     93    name = _('Bed Processor (update only)')
     94    iface = IBed
     95
     96    location_fields = ['hostel_id', 'bed_id']
     97    factory_name = None
     98
     99    mode = None
     100
     101    @property
     102    def available_fields(self):
     103        return self.location_fields + ['reserved', 'owner']
     104
     105    def parentsExist(self, row, site):
     106        if not 'hostels' in site.keys():
     107            return False
     108        return row['hostel_id'] in site['hostels']
     109
     110    def entryExists(self, row, site):
     111        if not self.parentsExist(row, site):
     112            return False
     113        parent = self.getParent(row, site)
     114        return row['bed_id'] in parent.keys()
     115
     116    def getParent(self, row, site):
     117        return site['hostels'][row['hostel_id']]
     118
     119    def getEntry(self, row, site):
     120        if not self.entryExists(row, site):
     121            return None
     122        parent = self.getParent(row, site)
     123        return parent.get(row['bed_id'])
     124
     125    def checkUpdateRequirements(self, obj, row, site):
     126        """Checks requirements the bed must fulfill
     127        before being updated.
     128        """
     129        # Check if bed is occupied
     130        if row.get('owner') and obj.owner != NOT_OCCUPIED:
     131            return 'Bed is occupied.'
     132
     133    def checkConversion(self, row, mode='ignore'):
     134        """Validates all values in row.
     135        """
     136        inv_errs = ''
     137        conv_dict = {}
     138        errs = []
     139        reserved = row.get('reserved')
     140        if reserved not in (None, IGNORE_MARKER, '', '0', '1'):
     141            errs.append(('reserved','invalid value'))
     142        owner = row.get('owner')
     143        if owner not in (None, '', IGNORE_MARKER):
     144            if owner == NOT_OCCUPIED:
     145                errs.append(('owner','bed cannot be released by import'))
     146                return errs, inv_errs, conv_dict
     147            beds_cat = getUtility(ICatalog, name='beds_catalog')
     148            results = list(beds_cat.searchResults(owner=(owner, owner)))
     149            if len(results) > 0:
     150                errs.append((
     151                    'owner','student already resides in %s'
     152                    % results[0].bed_id))
     153                return errs, inv_errs, conv_dict
     154            students_cat = getUtility(ICatalog, name='students_catalog')
     155            results = list(students_cat.searchResults(student_id=(owner, owner)))
     156            if len(results) != 1:
     157                errs.append(('owner','student does not exist'))
     158        return errs, inv_errs, conv_dict
     159
     160    def updateEntry(self, obj, row, site, filename):
     161        """Update obj to the values given in row.
     162        """
     163        changed = []
     164        owner = row.get('owner')
     165        if owner not in (None, '', IGNORE_MARKER):
     166            obj.bookBed(owner)
     167            changed.append('owner=%s' % owner)
     168        reserved = row.get('reserved')
     169        sh, sex, bt = obj.bed_type.split('_')
     170        if (reserved == '1' and bt != 'reserved') or \
     171            (reserved == '0'and bt == 'reserved'):
     172            message = obj.switchReservation()
     173            changed.append(message)
     174        # Log actions...
     175        if changed:
     176            items_changed = ', '.join(changed)
     177        else:
     178            items_changed = 'nothing'
     179        location_field = self.location_fields[1]
     180        grok.getSite()['hostels'].logger.info(
     181            '%s - %s - %s - updated: %s'
     182            % (self.name, filename, row[location_field], items_changed))
     183        return
  • main/waeup.kofa/trunk/src/waeup/kofa/hostels/tests.py

    r13346 r13432  
    3838from waeup.kofa.hostels.container import HostelsContainer
    3939from waeup.kofa.hostels.hostel import Hostel, Bed
    40 from waeup.kofa.hostels.batching import HostelProcessor
     40from waeup.kofa.hostels.batching import HostelProcessor, BedProcessor
    4141from waeup.kofa.hostels.export import BedExporter, HostelExporter
    4242from waeup.kofa.testing import (FunctionalLayer, FunctionalTestCase)
     
    5050
    5151HOSTEL_HEADER_FIELDS = HOSTEL_SAMPLE_DATA.split(
     52    '\n')[0].split(',')
     53
     54BED_SAMPLE_DATA = open(
     55    os.path.join(os.path.dirname(__file__), 'sample_bed_data.csv'),
     56    'rb').read()
     57
     58BED_HEADER_FIELDS = BED_SAMPLE_DATA.split(
    5259    '\n')[0].split(',')
    5360
     
    523530        shutil.rmtree(os.path.dirname(self.outfile))
    524531
    525 class HostelProcessorTest(HostelsFullSetup):
     532class HostelBedProcessorTest(HostelsFullSetup):
    526533
    527534    layer = FunctionalLayer
     
    561568        return
    562569
    563     def test_import_update(self):
     570    def test_import_update_hostel_and_beds(self):
    564571        self.processor = HostelProcessor()
    565572        self.workdir = tempfile.mkdtemp()
    566         self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
    567         open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
    568573        self.csv_file = os.path.join(self.workdir, 'sample_hostel_data.csv')
    569574        open(self.csv_file, 'wb').write(HOSTEL_SAMPLE_DATA)
     
    586591            "blocks_for_female=['A']"
    587592            in logcontent)
     593        # Update the beds of first hostel
     594        self.app['hostels']['block-a-upper-hostel'].updateBeds()
     595        # Import beds
     596        self.processor = BedProcessor()
     597        self.csv_file = os.path.join(self.workdir, 'sample_bed_data.csv')
     598        open(self.csv_file, 'wb').write(BED_SAMPLE_DATA)
     599        num, num_warns, fin_file, fail_file = self.processor.doImport(
     600            self.csv_file, BED_HEADER_FIELDS, 'update')
     601        self.assertEqual(num_warns,2)
     602        fail_file_content = open(fail_file).read()
     603        logcontent = open(self.logfile).read()
     604        self.assertEqual(
     605            'owner,bed_id,hostel_id,reserved,--ERRORS--\r\n'
     606            '<IGNORE>,block-a-upper-hostel_A_101_C,block-a-upper-hostel,2,'
     607            'reserved: invalid value\r\n'
     608            'K999,block-a-upper-hostel_A_101_E,block-a-upper-hostel,0,'
     609            'owner: student does not exist\r\n',
     610            fail_file_content)
     611        self.assertTrue(
     612            'system - Bed Processor (update only) - sample_bed_data - '
     613            'block-a-upper-hostel_A_101_A - updated: nothing'
     614            in logcontent)
     615        self.assertTrue(
     616            'system - Bed Processor (update only) - sample_bed_data - '
     617            'block-a-upper-hostel_A_101_B - updated: reserved'
     618            in logcontent)
     619        self.assertTrue(
     620            'system - Bed Processor (update only) - sample_bed_data - '
     621            'block-a-upper-hostel_A_101_D - updated: owner=K1000000'
     622            in logcontent)
     623        self.assertEqual(
     624            self.app['hostels']['block-a-upper-hostel']
     625                    ['block-a-upper-hostel_A_101_D'].owner, 'K1000000')
     626        self.assertEqual(
     627            self.app['hostels']['block-a-upper-hostel']
     628                    ['block-a-upper-hostel_A_101_B'].bed_type,
     629                    'regular_female_reserved')
    588630        shutil.rmtree(os.path.dirname(fin_file))
    589631        shutil.rmtree(self.workdir)
Note: See TracChangeset for help on using the changeset viewer.