source: main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py @ 7925

Last change on this file since 7925 was 7811, checked in by uli, 13 years ago

Rename all non-locales stuff from sirp to kofa.

  • Property svn:keywords set to Id
File size: 6.7 KB
RevLine 
[7192]1## $Id: batching.py 7811 2012-03-08 19:00:51Z uli $
[5321]2##
[7192]3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
[5321]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.
[7192]8##
[5321]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.
[7192]13##
[5321]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 for applicants.
19"""
[7268]20import csv
[5321]21import grok
[7271]22from zope.schema import getFields
[5321]23from zope.interface import Interface
[7268]24from zope.component import queryUtility
25from zope.catalog.interfaces import ICatalog
[7811]26from waeup.kofa.interfaces import (
[7271]27    IBatchProcessor, IObjectConverter, FatalCSVError)
[7811]28from waeup.kofa.utils.batching import BatchProcessor
29from waeup.kofa.applicants.interfaces import (
[7268]30    IApplicantsContainer, IApplicant, IApplicantUpdateByRegNo)
[5321]31
[6251]32class ApplicantsContainerImporter(BatchProcessor):
33    """An importer for applicants containers.
[5321]34    """
[5474]35    grok.implements(IBatchProcessor)
[5321]36    grok.provides(IBatchProcessor)
37    grok.context(Interface)
[6251]38    util_name = 'applicants container importer'
[5321]39    grok.name(util_name)
40
[6251]41    name = u'Applicants Container Importer'
[5475]42    mode = u'create'
[6251]43    iface = IApplicantsContainer
[5321]44
[6251]45    location_fields = ['code',]
[6282]46    factory_name = 'waeup.ApplicantsContainer'
[5321]47
48    def parentsExist(self, row, site):
[6251]49        return 'applicants' in site.keys()
[5321]50
51    def entryExists(self, row, site):
[6251]52        return row['code'] in site['applicants'].keys()
[5321]53
54    def getParent(self, row, site):
[6251]55        return site['applicants']
[5321]56
57    def getEntry(self, row, site):
58        if not self.entryExists(row, site):
59            return None
60        parent = self.getParent(row, site)
[6251]61        return parent.get(row['code'])
[5321]62
63    def addEntry(self, obj, row, site):
64        parent = self.getParent(row, site)
[6251]65        parent[row['code']] = obj
[5321]66        return
67
68    def delEntry(self, row, site):
69        parent = self.getParent(row, site)
[6251]70        del parent[row['code']]
[5321]71        return
[7262]72
[7263]73class ApplicantImporter(BatchProcessor):
[7262]74    """A batch processor for IApplicant objects.
75    """
76    grok.implements(IBatchProcessor)
77    grok.provides(IBatchProcessor)
78    grok.context(Interface)
79    util_name = 'applicantimporter'
80    grok.name(util_name)
81    name = u'Applicant Importer'
82    iface = IApplicant
83    location_fields = []
84    factory_name = 'waeup.Applicant'
[7268]85    location_fields = ['container_code']
[7262]86
87    mode = None
88
89    @property
[7268]90    def available_fields(self):
91        return sorted(list(set(
[7271]92            ['application_number','reg_number','container_code'] + getFields(
[7268]93                self.iface).keys())))
[7262]94
[7268]95    def checkHeaders(self, headerfields, mode='create'):
[7270]96        if not 'reg_number' in headerfields and not 'application_number' \
[7268]97            in headerfields:
98            raise FatalCSVError(
[7270]99                "Need at least columns application_number or reg_number ")
[7268]100        if mode == 'create':
101            for field in self.required_fields:
102                if not field in headerfields:
103                    raise FatalCSVError(
104                        "Need at least columns %s for import!" %
105                        ', '.join(["'%s'" % x for x in self.required_fields]))
106        # Check for fields to be ignored...
107        not_ignored_fields = [x for x in headerfields
108                              if not x.startswith('--')]
109        if len(set(not_ignored_fields)) < len(not_ignored_fields):
110            raise FatalCSVError(
111                "Double headers: each column name may only appear once.")
112        return True
[7262]113
[7268]114    def getLocator(self, row):
115        #if 'application_number' in row.keys() and row['application_number']:
116        if row.get('application_number',None):
117            return 'application_number'
[7270]118        elif 'reg_number' in row.keys() and row['reg_number']:
119            return 'reg_number'
[7268]120        else:
121            return None
[7262]122
123    def getParent(self, row, site):
[7268]124        if not 'applicants' in site.keys():
125            return False
[7262]126        return site['applicants'][row['container_code']]
127
[7268]128    def parentsExist(self, row, site):
129        return self.getParent(row, site) is not None
130
[7262]131    def getEntry(self, row, site):
[7264]132        if not self.parentsExist(row, site):
133            return None
134        parent = self.getParent(row, site)
[7268]135        if self.getLocator(row) == 'application_number':
136            if row['application_number'] in parent:
137                applicant = parent[row['application_number']]
138                return applicant
[7270]139        elif self.getLocator(row) == 'reg_number':
140            reg_number = row['reg_number']
[7268]141            cat = queryUtility(ICatalog, name='applicants_catalog')
142            results = list(
[7270]143                cat.searchResults(reg_number=(reg_number, reg_number)))
[7268]144            if results:
145                return results[0]
146        return None
[7262]147
[7268]148    def entryExists(self, row, site):
149        return self.getEntry(row, site) is not None
150
[7262]151    def addEntry(self, obj, row, site):
152        parent = self.getParent(row, site)
153        parent.addApplicant(obj)
154        return
155
156    def delEntry(self, row, site):
[7268]157        applicant = self.getEntry(row, site)
158        if applicant is not None:
[7262]159            parent = self.getParent(row, site)
[7268]160            del parent[applicant.application_number]
[7262]161        pass
[7268]162
163    def getMapping(self, path, headerfields, mode):
164        """Get a mapping from CSV file headerfields to actually used fieldnames.
165        """
166        result = dict()
167        reader = csv.reader(open(path, 'rb'))
168        raw_header = reader.next()
169        for num, field in enumerate(headerfields):
170            if field not in ['container_code',
[7270]171                'application_number', 'reg_number'] and mode == 'remove':
[7268]172                continue
173            if field == u'--IGNORE--':
174                # Skip ignored columns in failed and finished data files.
175                continue
176            result[raw_header[num]] = field
177        return result
178
179    def checkConversion(self, row, mode='create'):
180        """Validates all values in row.
181        """
182        if mode in ['update', 'remove']:
[7270]183            if self.getLocator(row) == 'reg_number':
[7268]184                iface = IApplicantUpdateByRegNo
185        else:
186            iface = self.iface
187        converter = IObjectConverter(iface)
188        errs, inv_errs, conv_dict =  converter.fromStringDict(
189            row, self.factory_name)
190        return errs, inv_errs, conv_dict
Note: See TracBrowser for help on using the repository browser.