Ignore:
Timestamp:
2 Oct 2012, 06:43:52 (12 years ago)
Author:
Henrik Bettermann
Message:

Repair and optimize AccessCodeProcessor?. AC states and transitions can now be imported in create and update mode.

Location:
main/waeup.kofa/trunk/src/waeup/kofa/accesscodes
Files:
1 added
4 edited

Legend:

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

    r9265 r9266  
    2020"""
    2121import grok
    22 from hurry.workflow.interfaces import IWorkflowState
     22from hurry.workflow.interfaces import IWorkflowState, IWorkflowInfo
    2323from zope.interface import Interface
    24 from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER, IObjectHistory
     24from waeup.kofa.interfaces import (
     25    IBatchProcessor, IGNORE_MARKER, IObjectHistory, IObjectConverter)
    2526from waeup.kofa.utils.batching import BatchProcessor
    2627from waeup.kofa.accesscodes.interfaces import IAccessCodeBatch, IAccessCode
     28from waeup.kofa.accesscodes.workflow import INITIALIZED, USED, DISABLED
     29
     30IMPORTABLE_TRANSITIONS = (
     31    'init', 'use', 'disable_used', 'disable_used', 'reeanble')
     32
     33IMPORTABLE_STATES = (INITIALIZED, USED, DISABLED)
    2734
    2835class AccessCodeBatchProcessor(BatchProcessor):
     
    98105                    self.location_fields + [
    99106                        'random_num', 'owner', 'cost',
    100                         'state', 'batch_serial',
    101                         'history',]
     107                        'state', 'batch_serial',]
    102108                    )))
    103109
    104110    @property
    105111    def required_fields(self):
    106         return ['random_num', 'state', 'batch_serial', 'history',]
     112        return ['random_num', 'batch_serial', 'history',]
    107113
    108114    def parentsExist(self, row, site):
     
    133139        parent[row['representation']] = obj
    134140        return
     141
     142    def checkConversion(self, row, mode='create'):
     143        """Validates all values in row.
     144        """
     145        converter = IObjectConverter(self.iface)
     146        errs, inv_errs, conv_dict =  converter.fromStringDict(
     147            row, self.factory_name, mode=mode)
     148        if row.has_key('transition') and row.has_key('state'):
     149            if row['transition'] not in (IGNORE_MARKER, '') and \
     150                row['state'] not in (IGNORE_MARKER, ''):
     151                errs.append(('workflow','not allowed'))
     152                return errs, inv_errs, conv_dict
     153        if row.has_key('transition'):
     154            if row['transition'] not in IMPORTABLE_TRANSITIONS:
     155                if row['transition'] not in (IGNORE_MARKER, ''):
     156                    errs.append(('transition','not allowed'))
     157        if row.has_key('state'):
     158            if row['state'] not in IMPORTABLE_STATES:
     159                if row['state'] not in (IGNORE_MARKER, ''):
     160                    errs.append(('state','not allowed'))
     161                else:
     162                    # State is an attribute of AccessCode and must not
     163                    # be changed if empty.
     164                    conv_dict['state'] = IGNORE_MARKER
     165        return errs, inv_errs, conv_dict
     166
     167    def checkUpdateRequirements(self, obj, row, site):
     168        """Checks requirements the object must fulfill when being updated.
     169
     170        This method is not used in case of deleting or adding objects.
     171
     172        Returns error messages as strings in case of requirement
     173        problems.
     174        """
     175        transition = row.get('transition', IGNORE_MARKER)
     176        if transition not in (IGNORE_MARKER, ''):
     177            allowed_transitions = IWorkflowInfo(obj).getManualTransitionIds()
     178            if transition not in allowed_transitions:
     179                return 'Transition not allowed.'
     180        return None
    135181
    136182    def updateEntry(self, obj, row, site):
     
    147193                IWorkflowState(obj).setState(value)
    148194                items_changed += ('%s=%s, ' % ('state', state))
     195                msg = "state '%s' set" % state
     196                IObjectHistory(obj).addMessage(msg)
    149197            row.pop('state')
    150         # Update history
    151         if row.has_key('history'):
    152             history = row.get('history', IGNORE_MARKER)
    153             if history not in (IGNORE_MARKER, ''):
    154                 values = row['history'].split('||')
    155                 for value in values:
    156                     IObjectHistory(obj).addMessage(value)
    157                 items_changed += ('%s=%s, ' % ('history', history))
    158             row.pop('history')
     198        # Fire transition
     199        if row.has_key('transition'):
     200            transition = row.get('transition', IGNORE_MARKER)
     201            if transition not in (IGNORE_MARKER, ''):
     202                value = row['transition']
     203                IWorkflowInfo(obj).fireTransition(value)
     204                items_changed += ('%s=%s, ' % ('transition', transition))
     205            row.pop('transition')
    159206
    160207        # In import files we can use the hash symbol at the end of a
    161208        # random_num string to avoid annoying automatic number transformation
    162209        # by Excel or Calc
    163         row['random_num'] = row['random_num'].strip('#')
     210        if row.has_key('random_num'):
     211            random_num = row.get('random_num', IGNORE_MARKER)
     212            if random_num not in (IGNORE_MARKER, ''):
     213                row['random_num'] = random_num.strip('#')
    164214
    165215        items_changed += super(AccessCodeProcessor, self).updateEntry(
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/interfaces.py

    r9265 r9266  
    4343    state = schema.TextLine(
    4444        title = _(u'Workflow state'),
     45        required = False,
    4546        )
    4647    representation = schema.TextLine(
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/tests/sample_ac_data.csv

    r9265 r9266  
    1 batch_num,batch_prefix,batch_serial,cost,history,owner,random_num,representation,state
    2 1,CLR,33,100.0,2012-07-11 14:51:56 UTC - initialized by Manager||2012-07-11 14:55:42 UTC - invalidated by Manager,K1000009,1625368961#,CLR-1-1625368961,used
    3 1,CLR,2,100.0,2012-05-12 16:32:29 UTC - initialized by Manager,,5468453598#,CLR-1-5468453598,initialized
    4 1,HOS,731,0.0,2012-09-19 08:59:28 UTC - initialized by Manager,,0007044547#,HOS-1-0007044547,initialized
     1batch_num,batch_prefix,batch_serial,cost,history,owner,random_num,representation,state,transition
     21,CLR,33,100.0,anything,K1000009,1625368961#,CLR-1-1625368961,used,
     31,CLR,2,100.0,anything,,5468453598#,CLR-1-5468453598,initialized,
     41,HOS,456,0.0,anything,,98769876#,HOS-1-98769876,,use
     51,HOS,456,0.0,anything,,76254765#,HOS-1-76254765,,
     61,HOS,23,0.0,anything,,0007044547#,HOS-1-0007044547,nonsense,
     71,HOS,731,0.0,anything,,555#,HOS-1-555,used,disable_unused
     81,HOS,456,0.0,anything,,666#,HOS-1-666,,nonsense
     9
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/tests/test_batching.py

    r9265 r9266  
    5454    '\n')[0].split(',')
    5555
     56AC_SAMPLE_DATA_UPDATE = open(
     57    os.path.join(os.path.dirname(__file__), 'sample_ac_data_update.csv'),
     58    'rb').read()
     59
     60AC_HEADER_FIELDS_UPDATE = AC_SAMPLE_DATA_UPDATE.split(
     61    '\n')[0].split(',')
     62
    5663class ACFullSetup(FunctionalTestCase):
    5764
     
    104111        self.assertTrue(
    105112            'system - AccessCodeBatch Processor - CLR-1 - '
    106             'Batch updated: num=1, creator=system, entry_num=3, '
    107             'creation_date=2012-04-28 07:28:48.719026+00:00, '
     113            'Batch updated: num=1, creator=system, used_num=1, '
     114            'entry_num=3, creation_date=2012-04-28 07:28:48.719026+00:00, '
    108115            'prefix=CLR, cost=0.0, disabled_num=0'
    109116            in logcontent)
     
    115122    layer = FunctionalLayer
    116123
    117     def test_import(self):
     124    def test_import_create(self):
    118125        self.processor = AccessCodeBatchProcessor()
    119126        self.csv_file = os.path.join(self.workdir, 'sample_batch_data.csv')
     
    126133        num, num_warns, fin_file, fail_file =  self.processor.doImport(
    127134            self.csv_file, AC_HEADER_FIELDS)
    128         self.assertEqual(num_warns,0)
     135        self.assertEqual(num_warns,3)
     136        fail_file = open(fail_file).read()
     137        self.assertTrue(
     138            'HOS-1-0007044547,HOS,anything,state: not allowed' in fail_file)
     139        self.assertTrue(
     140            'HOS-1-555,HOS,anything,workflow: not allowed' in fail_file)
     141        self.assertTrue(
     142            'HOS-1-666,HOS,anything,transition: not allowed' in fail_file)
     143        self.assertEqual(
     144            self.app['accesscodes']['HOS-1']['HOS-1-98769876'].state, 'used')
     145        self.assertEqual(
     146            self.app['accesscodes']['HOS-1']['HOS-1-76254765'].state, 'initialized')
    129147        self.assertEqual(
    130148            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].batch_serial, 33)
     
    133151        self.assertEqual(
    134152            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].state, 'used')
     153        self.assertMatches(
     154            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].history,
     155            "<YYYY-MM-DD hh:mm:ss> UTC - initialized by system|"
     156            "|<YYYY-MM-DD hh:mm:ss> UTC - state 'used' set by system")
     157        self.assertMatches(
     158            self.app['accesscodes']['HOS-1']['HOS-1-98769876'].history,
     159            "<YYYY-MM-DD hh:mm:ss> UTC - initialized by system|"
     160            "|<YYYY-MM-DD hh:mm:ss> UTC - used by system")
    135161        logcontent = open(self.logfile).read()
    136162        self.assertTrue(
    137163            'INFO - system - AccessCode Processor - CLR-1-1625368961 - '
    138             'AC updated: state=used, history=2012-07-11 14:51:56 UTC - '
    139             'initialized by Manager||2012-07-11 14:55:42 UTC - '
    140             'invalidated by Manager, batch_serial=33, '
    141             'random_num=1625368961, cost=100.0, owner=K1000009'
     164            'AC updated: state=used, batch_serial=33, random_num=1625368961, '
     165            'cost=100.0, owner=K1000009'
    142166            in logcontent)
    143167        shutil.rmtree(os.path.dirname(fin_file))
    144168        return
     169
     170    def test_import_update(self):
     171        self.processor = AccessCodeBatchProcessor()
     172        self.csv_file = os.path.join(self.workdir, 'sample_batch_data.csv')
     173        open(self.csv_file, 'wb').write(BATCH_SAMPLE_DATA)
     174        self.processor.doImport(self.csv_file, BATCH_HEADER_FIELDS)
     175
     176        self.processor = AccessCodeProcessor()
     177        self.csv_file = os.path.join(self.workdir, 'sample_ac_data.csv')
     178        open(self.csv_file, 'wb').write(AC_SAMPLE_DATA)
     179        num, num_warns, fin_file, fail_file =  self.processor.doImport(
     180            self.csv_file, AC_HEADER_FIELDS)
     181
     182        self.csv_file = os.path.join(self.workdir, 'sample_ac_data_update.csv')
     183        open(self.csv_file, 'wb').write(AC_SAMPLE_DATA_UPDATE)
     184        num, num_warns, fin_file, fail_file =  self.processor.doImport(
     185            self.csv_file, AC_HEADER_FIELDS_UPDATE, 'update')
     186        fin_file = open(fin_file).read()
     187        self.assertEqual(num_warns,0)
     188        self.assertEqual(
     189            self.app['accesscodes']['HOS-1']['HOS-1-98769876'].state, 'disabled')
     190        self.assertEqual(
     191            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].state, 'disabled')
     192        self.assertMatches(
     193            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].history,
     194            "<YYYY-MM-DD hh:mm:ss> UTC - initialized by system|"
     195            "|<YYYY-MM-DD hh:mm:ss> UTC - state 'used' set by system|"
     196            "|<YYYY-MM-DD hh:mm:ss> UTC - state 'disabled' set by system")
     197        self.assertMatches(
     198            self.app['accesscodes']['HOS-1']['HOS-1-98769876'].history,
     199            "<YYYY-MM-DD hh:mm:ss> UTC - initialized by system|"
     200            "|<YYYY-MM-DD hh:mm:ss> UTC - used by system|"
     201            "|<YYYY-MM-DD hh:mm:ss> UTC - disabled by system")
     202        return
Note: See TracChangeset for help on using the changeset viewer.