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

Last change on this file since 17760 was 17313, checked in by Henrik Bettermann, 2 years 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.