source: main/waeup.sirp/trunk/src/waeup/sirp/applicants/batching.py @ 7268

Last change on this file since 7268 was 7268, checked in by Henrik Bettermann, 14 years ago

Use reg_no as locator to find applicants for updating and removal.

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