Ignore:
Timestamp:
3 May 2012, 07:28:57 (12 years ago)
Author:
Henrik Bettermann
Message:

Let's do the applicant importer do what it's supposed to do.

Some catalog searches are performed twice during import of a row. This can only be improved by modifying doImport in the base class.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/applicants
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/applicants/batching.py

    r8290 r8331  
    7777class ApplicantProcessor(BatchProcessor):
    7878    """A batch processor for IApplicant objects.
     79
     80    In create mode container_code is required. If application_number is given
     81    an applicant with this number is created in the designated container.
     82    If application_number is not given a random application_number is assigned.
     83    applicant_id is being determined by the system and can't be imported.
     84
     85    In update or remove mode container_code and application_number columns
     86    must not exist. The applicant object is solely searched by its applicant_id
     87    or reg_number.
    7988    """
    8089    grok.implements(IBatchProcessor)
     
    8594    name = u'Applicant Processor'
    8695    iface = IApplicant
    87     location_fields = ['container_code']
     96    location_fields = ['']
    8897    factory_name = 'waeup.Applicant'
    8998
     
    93102    def available_fields(self):
    94103        return sorted(list(set(
    95             ['application_number','reg_number',
     104            ['application_number',
    96105            'container_code','state','password'] + getFields(
    97106                self.iface).keys())))
    98107
    99108    def checkHeaders(self, headerfields, mode='create'):
    100         if not 'reg_number' in headerfields and not 'application_number' \
    101             in headerfields:
    102             raise FatalCSVError(
    103                 "Need at least columns application_number or reg_number ")
     109        cond1 = 'container_code' in headerfields
     110        cond2 = 'application_number' in headerfields
     111        cond3 = 'applicant_id' in headerfields
     112        cond4 = 'reg_number' in headerfields
    104113        if mode == 'create':
     114            if not cond1:
     115                raise FatalCSVError(
     116                    "Need at least container_code column!")
     117            if cond3:
     118                raise FatalCSVError(
     119                    "applicant_id can't be imported in create mode!")
    105120            for field in self.required_fields:
    106121                if not field in headerfields:
     
    108123                        "Need at least columns %s for import!" %
    109124                        ', '.join(["'%s'" % x for x in self.required_fields]))
     125        if mode in ('update', 'remove'):
     126            if not cond3 and not cond4:
     127                raise FatalCSVError(
     128                    "Need at least column reg_number or applicant_id!")
     129            if cond1 or cond2:
     130                raise FatalCSVError(
     131                    "container_code or application_number can't be imported " +
     132                    "in update or remove mode!")
    110133        # Check for fields to be ignored...
    111134        not_ignored_fields = [x for x in headerfields
     
    117140
    118141    def getLocator(self, row):
    119         if row.get('application_number', None) not in (IGNORE_MARKER, None):
    120             return 'application_number'
     142        if row.get('container_code', None) not in (IGNORE_MARKER, None):
     143            # create, update or remove
     144            return 'container_code'
     145        elif row.get('applicant_id', None) not in (IGNORE_MARKER, None):
     146            # update or remove
     147            return 'applicant_id'
    121148        elif row.get('reg_number', None) not in (IGNORE_MARKER, None):
     149            # update or remove
    122150            return 'reg_number'
    123151        else:
     
    125153
    126154    def getParent(self, row, site):
    127         if not 'applicants' in site.keys():
    128             return False
    129         return site['applicants'][row['container_code']]
     155        if self.getLocator(row) == 'container_code':
     156            return site['applicants'].get(row['container_code'], None)
     157        if self.getLocator(row) == 'reg_number':
     158            reg_number = row['reg_number']
     159            cat = queryUtility(ICatalog, name='applicants_catalog')
     160            results = list(
     161                cat.searchResults(reg_number=(reg_number, reg_number)))
     162            if results:
     163                return results[0].__parent__
     164        if self.getLocator(row) == 'applicant_id':
     165            applicant_id = row['applicant_id']
     166            cat = queryUtility(ICatalog, name='applicants_catalog')
     167            results = list(
     168                cat.searchResults(applicant_id=(applicant_id, applicant_id)))
     169            if results:
     170                return results[0].__parent__
     171        return None
    130172
    131173    def parentsExist(self, row, site):
     
    133175
    134176    def getEntry(self, row, site):
    135         if not self.parentsExist(row, site):
     177        if self.getLocator(row) == 'container_code':
     178            if row.get('application_number', None) not in (IGNORE_MARKER, None):
     179                if not self.parentsExist(row, site):
     180                    return None
     181                parent = self.getParent(row, site)
     182                return parent.get(row['application_number'])
    136183            return None
    137         parent = self.getParent(row, site)
    138         if self.getLocator(row) == 'application_number':
    139             if row['application_number'] in parent:
    140                 applicant = parent[row['application_number']]
    141                 return applicant
    142         elif self.getLocator(row) == 'reg_number':
     184        if self.getLocator(row) == 'applicant_id':
     185            applicant_id = row['applicant_id']
     186            cat = queryUtility(ICatalog, name='applicants_catalog')
     187            results = list(
     188                cat.searchResults(applicant_id=(applicant_id, applicant_id)))
     189            if results:
     190                return results[0]
     191        if self.getLocator(row) == 'reg_number':
    143192            reg_number = row['reg_number']
    144193            cat = queryUtility(ICatalog, name='applicants_catalog')
     
    167216        applicant = self.getEntry(row, site)
    168217        if applicant is not None:
    169             parent = self.getParent(row, site)
     218            parent = applicant.__parent__
    170219            del parent[applicant.application_number]
    171220        pass
     
    227276        raw_header = reader.next()
    228277        for num, field in enumerate(headerfields):
    229             if field not in ['container_code',
    230                 'application_number', 'reg_number'] and mode == 'remove':
     278            if field not in ['applicant_id', 'reg_number'] and mode == 'remove':
    231279                continue
    232280            if field == u'--IGNORE--':
     
    239287        """Validates all values in row.
    240288        """
    241         if mode in ['update', 'remove']:
    242             if self.getLocator(row) == 'reg_number':
    243                 iface = IApplicantUpdateByRegNo
    244         else:
    245             iface = self.iface
     289        iface = self.iface
     290        if self.getLocator(row) == 'reg_number' or mode == 'remove':
     291            iface = IApplicantUpdateByRegNo
    246292        converter = IObjectConverter(iface)
    247293        errs, inv_errs, conv_dict =  converter.fromStringDict(
     
    255301                # be changed if empty
    256302                conv_dict['state'] = IGNORE_MARKER
    257         application_number = row.get('application_number', IGNORE_MARKER)
     303        application_number = row.get('application_number', None)
    258304        if application_number in (IGNORE_MARKER, ''):
    259305                conv_dict['application_number'] = IGNORE_MARKER
  • main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/sample_applicant_data_update.csv

    r8290 r8331  
    1 container_code,reg_number,firstname,middlename,state
    2 dp2011,1001,Aaren,,
    3 dp2011,1002,Alfons,,admitted
    4 dp2011,1003,Abraham,,
     1applicant_id,reg_number,firstname,middlename,state
     2,1001,Aaren,,
     3dp2011_2345,6666,Alfons,,admitted
     4,1003,Abraham,,
  • main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/sample_applicant_data_update2.csv

    r8290 r8331  
    1 container_code,reg_number,firstname,middlename,application_number
    2 dp2011,1001,Aaren,XXX,
    3 dp2011,1002,Alfons,XXX,
    4 dp2011,1003,Abraham,XXX,
     1applicant_id,reg_number,firstname,middlename
     2dp2011_1234,,Aaren,XXX
     3,6666,Alfons,XXX
     4,1003,Abraham,XXX
  • main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/test_batching.py

    r8311 r8331  
    2424import tempfile
    2525import unittest
     26import grok
    2627from zope.component.hooks import setSite, clearSite
    2728from zope.component import createObject
    2829from zope.interface.verify import verifyClass, verifyObject
     30from zope.event import notify
    2931
    3032from waeup.kofa.app import University
     
    6870
    6971APPLICANT_HEADER_FIELDS_UPDATE = APPLICANT_SAMPLE_DATA_UPDATE.split(
     72    '\n')[0].split(',')
     73
     74APPLICANT_HEADER_FIELDS_UPDATE2 = APPLICANT_SAMPLE_DATA_UPDATE2.split(
    7075    '\n')[0].split(',')
    7176
     
    310315        num, num_warns, fin_file, fail_file = self.processor.doImport(
    311316            self.csv_file_update, APPLICANT_HEADER_FIELDS_UPDATE, 'update')
    312         #content = open(fail_file).read()
    313317        self.assertEqual(num_warns,0)
    314318        # The middlename import value was None.
     
    324328        # password of Finau is still unset
    325329        self.assertEqual(IUserAccount(container['2345']).password,'')
    326         shutil.rmtree(os.path.dirname(fin_file))
    327         # Now we import another file which clears all middlename attributes.
    328         num, num_warns, fin_file, fail_file = self.processor.doImport(
    329             self.csv_file_update2, APPLICANT_HEADER_FIELDS_UPDATE, 'update')
     330        # reg_number of Finau has changed
     331        self.assertEqual(container['2345'].reg_number, '6666')
     332        shutil.rmtree(os.path.dirname(fin_file))
     333        # We have to inform the catalog that the reg_number has changed
     334        notify(grok.ObjectModifiedEvent(container['2345']))
     335        # Now we import another file which clears all middlename attributes
     336        # and uses the new reg_number as locator
     337        num, num_warns, fin_file, fail_file = self.processor.doImport(
     338            self.csv_file_update2, APPLICANT_HEADER_FIELDS_UPDATE2, 'update')
     339        #content = open(fail_file).read()
     340        #print content
    330341        self.assertEqual(num_warns,0)
    331342        assert container['1234'].middlename is None
Note: See TracChangeset for help on using the changeset viewer.