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
Line 
1## $Id: batching.py 7268 2011-12-04 17:40:41Z 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 for applicants.
19"""
20import csv
21import grok
22from zope.interface import Interface
23from zope.component import queryUtility
24from zope.catalog.interfaces import ICatalog
25from waeup.sirp.interfaces import IBatchProcessor, IObjectConverter
26from waeup.sirp.utils.batching import BatchProcessor
27from waeup.sirp.applicants.interfaces import (
28    IApplicantsContainer, IApplicant, IApplicantUpdateByRegNo)
29
30class ApplicantsContainerImporter(BatchProcessor):
31    """An importer for applicants containers.
32    """
33    grok.implements(IBatchProcessor)
34    grok.provides(IBatchProcessor)
35    grok.context(Interface)
36    util_name = 'applicants container importer'
37    grok.name(util_name)
38
39    name = u'Applicants Container Importer'
40    mode = u'create'
41    iface = IApplicantsContainer
42
43    location_fields = ['code',]
44    factory_name = 'waeup.ApplicantsContainer'
45
46    def parentsExist(self, row, site):
47        return 'applicants' in site.keys()
48
49    def entryExists(self, row, site):
50        return row['code'] in site['applicants'].keys()
51
52    def getParent(self, row, site):
53        return site['applicants']
54
55    def getEntry(self, row, site):
56        if not self.entryExists(row, site):
57            return None
58        parent = self.getParent(row, site)
59        return parent.get(row['code'])
60
61    def addEntry(self, obj, row, site):
62        parent = self.getParent(row, site)
63        parent[row['code']] = obj
64        return
65
66    def delEntry(self, row, site):
67        parent = self.getParent(row, site)
68        del parent[row['code']]
69        return
70
71class ApplicantImporter(BatchProcessor):
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'
83    location_fields = ['container_code']
84
85    mode = None
86
87    @property
88    def available_fields(self):
89        return sorted(list(set(
90            ['application_number','reg_no'] + getFields(
91                self.iface).keys())))
92
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
111
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
120
121    def getParent(self, row, site):
122        if not 'applicants' in site.keys():
123            return False
124        return site['applicants'][row['container_code']]
125
126    def parentsExist(self, row, site):
127        return self.getParent(row, site) is not None
128
129    def getEntry(self, row, site):
130        if not self.parentsExist(row, site):
131            return None
132        parent = self.getParent(row, site)
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
145
146    def entryExists(self, row, site):
147        return self.getEntry(row, site) is not None
148
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):
155        applicant = self.getEntry(row, site)
156        if applicant is not None:
157            parent = self.getParent(row, site)
158            del parent[applicant.application_number]
159        pass
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.