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

Last change on this file since 17902 was 17787, checked in by Henrik Bettermann, 7 months ago

Add SessionConfigurationProcessor.
Add ConfigurationContainerProcessor.
Add ConfigurationContainerExporter.

  • Property svn:keywords set to Id
File size: 7.0 KB
Line 
1## $Id: batching.py 17787 2024-05-15 06:42:58Z 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
23from zope.component import getUtility
24from zope.catalog.interfaces import ICatalog
25from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER
26from waeup.kofa.utils.batching import BatchProcessor
27from waeup.kofa.hostels.interfaces import IHostel, IBed
28from waeup.kofa.hostels.vocabularies import NOT_OCCUPIED
29from waeup.kofa.interfaces import MessageFactory as _
30
31class HostelProcessor(BatchProcessor):
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.
35    """
36    grok.implements(IBatchProcessor)
37    grok.provides(IBatchProcessor)
38    grok.context(Interface)
39    util_name = 'hostelprocessor'
40    grok.name(util_name)
41
42    name = _('Hostel Processor')
43    iface = IHostel
44
45    location_fields = ['hostel_id',]
46    factory_name = 'waeup.Hostel'
47
48    def parentsExist(self, row, site):
49        return 'hostels' in site.keys()
50
51    def entryExists(self, row, site):
52        return row['hostel_id'] in site['hostels'].keys()
53
54    def getParent(self, row, site):
55        return site['hostels']
56
57    def getEntry(self, row, site):
58        if not self.entryExists(row, site):
59            return None
60        parent = self.getParent(row, site)
61        return parent.get(row['hostel_id'])
62
63    def addEntry(self, obj, row, site):
64        parent = self.getParent(row, site)
65        parent.addHostel(obj)
66        return
67
68    def updateEntry(self, obj, row, site, filename):
69        """Update obj to the values given in row.
70        """
71        items_changed = super(HostelProcessor, self).updateEntry(
72            obj, row, site, filename)
73        # Log actions...
74        location_field = self.location_fields[0]
75        grok.getSite()['hostels'].logger.info(
76            '%s - %s - %s - updated: %s'
77            % (self.name, filename, row[location_field], items_changed))
78        return
79
80
81class BedProcessor(BatchProcessor):
82    """The Bed Procesor update beds. It allocates students
83    to empty beds and switches the reservation or blockade status of beds. ``1``
84    means reserved (or blocked) and ``0`` unreserved (or unblocked).
85    Beds cannot be released by import.
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    @property
100    def available_fields(self):
101        return self.location_fields + ['reserved', 'blocked', 'owner']
102
103    def parentsExist(self, row, site):
104        if not 'hostels' in site.keys():
105            return False
106        return row['hostel_id'] in site['hostels']
107
108    def entryExists(self, row, site):
109        if not self.parentsExist(row, site):
110            return False
111        parent = self.getParent(row, site)
112        return row['bed_id'] in parent.keys()
113
114    def getParent(self, row, site):
115        return site['hostels'][row['hostel_id']]
116
117    def getEntry(self, row, site):
118        if not self.entryExists(row, site):
119            return None
120        parent = self.getParent(row, site)
121        return parent.get(row['bed_id'])
122
123    def checkUpdateRequirements(self, obj, row, site):
124        """Checks requirements the bed must fulfill
125        before being updated.
126        """
127        # Check if bed is occupied
128        if row.get('owner') and obj.owner != NOT_OCCUPIED:
129            return 'Bed is occupied.'
130        # Check if bed is blocked and not unblocked by the importer
131        if obj.bed_type.endswith('blocked') and \
132            row.get('owner') not in (None, '', IGNORE_MARKER) and \
133            row.get('blocked') != '0':
134            return 'Bed is blocked.'
135
136    def checkConversion(self, row, mode='ignore'):
137        """Validates all values in row.
138        """
139        inv_errs = ''
140        conv_dict = {}
141        errs = []
142        reserved = row.get('reserved')
143        if reserved not in (None, IGNORE_MARKER, '', '0', '1'):
144            errs.append(('reserved','invalid value'))
145        blocked = row.get('blocked')
146        if blocked not in (None, IGNORE_MARKER, '', '0', '1'):
147            errs.append(('blocked','invalid value'))
148        owner = row.get('owner')
149        if owner not in (None, '', IGNORE_MARKER):
150            if owner == NOT_OCCUPIED:
151                errs.append(('owner','bed cannot be released by import'))
152                return errs, inv_errs, conv_dict
153            beds_cat = getUtility(ICatalog, name='beds_catalog')
154            results = list(beds_cat.searchResults(owner=(owner, owner)))
155            if len(results) > 0:
156                errs.append((
157                    'owner','student already resides in %s'
158                    % results[0].bed_id))
159                return errs, inv_errs, conv_dict
160            students_cat = getUtility(ICatalog, name='students_catalog')
161            results = list(students_cat.searchResults(student_id=(owner, owner)))
162            if len(results) != 1:
163                errs.append(('owner','student does not exist'))
164        return errs, inv_errs, conv_dict
165
166    def updateEntry(self, obj, row, site, filename):
167        """Update obj to the values given in row.
168        """
169        changed = []
170        owner = row.get('owner')
171        if owner not in (None, '', IGNORE_MARKER):
172            obj.bookBed(owner)
173            changed.append('owner=%s' % owner)
174        sh, sex, bt = obj.bed_type.split('_')
175        reserved = row.get('reserved')
176        if (reserved == '1' and bt != 'reserved') or \
177            (reserved == '0'and bt == 'reserved'):
178            message = obj.switchBed('reserved')
179            changed.append(message)
180        blocked = row.get('blocked')
181        if (blocked == '1' and bt != 'blocked') or \
182            (blocked == '0'and bt == 'blocked'):
183            message = obj.switchBed('blocked')
184            changed.append(message)
185        # Log actions...
186        if changed:
187            items_changed = ', '.join(changed)
188        else:
189            items_changed = 'nothing'
190        location_field = self.location_fields[1]
191        grok.getSite()['hostels'].logger.info(
192            '%s - %s - %s - updated: %s'
193            % (self.name, filename, row[location_field], items_changed))
194        return
Note: See TracBrowser for help on using the repository browser.