source: main/waeup.kofa/trunk/src/waeup/kofa/hostels/batching.py @ 17389

Last change on this file since 17389 was 17313, checked in by Henrik Bettermann, 22 months ago

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

  • Property svn:keywords set to Id
File size: 7.0 KB
RevLine 
[9202]1## $Id: batching.py 17313 2023-01-25 08:52:51Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18"""Batch processing components for hostels.
19
20"""
21import grok
22from zope.interface import Interface
[13432]23from zope.component import getUtility
24from zope.catalog.interfaces import ICatalog
[9202]25from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER
26from waeup.kofa.utils.batching import BatchProcessor
[13432]27from waeup.kofa.hostels.interfaces import IHostel, IBed
28from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
[11891]29from waeup.kofa.interfaces import MessageFactory as _
[9202]30
31class HostelProcessor(BatchProcessor):
[12883]32    """The Hostel Procesor imports hostels, i.e. the container objects of
33    beds. It does not import beds. There is nothing special about this
34    processor.
[9202]35    """
36    grok.implements(IBatchProcessor)
37    grok.provides(IBatchProcessor)
38    grok.context(Interface)
39    util_name = 'hostelprocessor'
40    grok.name(util_name)
41
[11891]42    name = _('Hostel Processor')
[9202]43    iface = IHostel
44
45    location_fields = ['hostel_id',]
46    factory_name = 'waeup.Hostel'
47
48    mode = None
49
50    def parentsExist(self, row, site):
51        return 'hostels' in site.keys()
52
53    def entryExists(self, row, site):
54        return row['hostel_id'] in site['hostels'].keys()
55
56    def getParent(self, row, site):
57        return site['hostels']
58
59    def getEntry(self, row, site):
60        if not self.entryExists(row, site):
61            return None
62        parent = self.getParent(row, site)
63        return parent.get(row['hostel_id'])
64
65    def addEntry(self, obj, row, site):
66        parent = self.getParent(row, site)
67        parent.addHostel(obj)
68        return
69
[9706]70    def updateEntry(self, obj, row, site, filename):
[9202]71        """Update obj to the values given in row.
72        """
[13159]73        items_changed = super(HostelProcessor, self).updateEntry(
74            obj, row, site, filename)
[9202]75        # Log actions...
76        location_field = self.location_fields[0]
[9706]77        grok.getSite()['hostels'].logger.info(
78            '%s - %s - %s - updated: %s'
79            % (self.name, filename, row[location_field], items_changed))
[13432]80        return
81
82
83class BedProcessor(BatchProcessor):
[13434]84    """The Bed Procesor update beds. It allocates students
[17313]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.
[13432]88    """
89    grok.implements(IBatchProcessor)
90    grok.provides(IBatchProcessor)
91    grok.context(Interface)
92    util_name = 'bedupdater'
93    grok.name(util_name)
94
95    name = _('Bed Processor (update only)')
96    iface = IBed
97
98    location_fields = ['hostel_id', 'bed_id']
99    factory_name = None
100
101    mode = None
102
103    @property
104    def available_fields(self):
[17313]105        return self.location_fields + ['reserved', 'blocked', 'owner']
[13432]106
107    def parentsExist(self, row, site):
108        if not 'hostels' in site.keys():
109            return False
110        return row['hostel_id'] in site['hostels']
111
112    def entryExists(self, row, site):
113        if not self.parentsExist(row, site):
114            return False
115        parent = self.getParent(row, site)
116        return row['bed_id'] in parent.keys()
117
118    def getParent(self, row, site):
119        return site['hostels'][row['hostel_id']]
120
121    def getEntry(self, row, site):
122        if not self.entryExists(row, site):
123            return None
124        parent = self.getParent(row, site)
125        return parent.get(row['bed_id'])
126
127    def checkUpdateRequirements(self, obj, row, site):
128        """Checks requirements the bed must fulfill
129        before being updated.
130        """
131        # Check if bed is occupied
132        if row.get('owner') and obj.owner != NOT_OCCUPIED:
133            return 'Bed is occupied.'
[17313]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.'
[13432]139
140    def checkConversion(self, row, mode='ignore'):
141        """Validates all values in row.
142        """
143        inv_errs = ''
144        conv_dict = {}
145        errs = []
146        reserved = row.get('reserved')
147        if reserved not in (None, IGNORE_MARKER, '', '0', '1'):
148            errs.append(('reserved','invalid value'))
[17313]149        blocked = row.get('blocked')
150        if blocked not in (None, IGNORE_MARKER, '', '0', '1'):
151            errs.append(('blocked','invalid value'))
[13432]152        owner = row.get('owner')
153        if owner not in (None, '', IGNORE_MARKER):
154            if owner == NOT_OCCUPIED:
155                errs.append(('owner','bed cannot be released by import'))
156                return errs, inv_errs, conv_dict
157            beds_cat = getUtility(ICatalog, name='beds_catalog')
158            results = list(beds_cat.searchResults(owner=(owner, owner)))
159            if len(results) > 0:
160                errs.append((
161                    'owner','student already resides in %s'
162                    % results[0].bed_id))
163                return errs, inv_errs, conv_dict
164            students_cat = getUtility(ICatalog, name='students_catalog')
165            results = list(students_cat.searchResults(student_id=(owner, owner)))
166            if len(results) != 1:
167                errs.append(('owner','student does not exist'))
168        return errs, inv_errs, conv_dict
169
170    def updateEntry(self, obj, row, site, filename):
171        """Update obj to the values given in row.
172        """
173        changed = []
174        owner = row.get('owner')
175        if owner not in (None, '', IGNORE_MARKER):
176            obj.bookBed(owner)
177            changed.append('owner=%s' % owner)
[17313]178        sh, sex, bt = obj.bed_type.split('_')
[13432]179        reserved = row.get('reserved')
180        if (reserved == '1' and bt != 'reserved') or \
181            (reserved == '0'and bt == 'reserved'):
[17313]182            message = obj.switchBed('reserved')
[13432]183            changed.append(message)
[17313]184        blocked = row.get('blocked')
185        if (blocked == '1' and bt != 'blocked') or \
186            (blocked == '0'and bt == 'blocked'):
187            message = obj.switchBed('blocked')
188            changed.append(message)
[13432]189        # Log actions...
190        if changed:
191            items_changed = ', '.join(changed)
192        else:
193            items_changed = 'nothing'
194        location_field = self.location_fields[1]
195        grok.getSite()['hostels'].logger.info(
196            '%s - %s - %s - updated: %s'
197            % (self.name, filename, row[location_field], items_changed))
[9202]198        return
Note: See TracBrowser for help on using the repository browser.