Changeset 9265


Ignore:
Timestamp:
1 Oct 2012, 21:18:48 (12 years ago)
Author:
Henrik Bettermann
Message:

Add AccessCodeProcessor?.

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

Legend:

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

    r9263 r9265  
    8181    grok.implements(IAccessCode)
    8282
    83     def __init__(self, batch_serial, random_num):
     83    def __init__(self, batch_serial=None, random_num=None):
    8484        super(AccessCode, self).__init__()
    8585        self.batch_serial = batch_serial
     
    154154
    155155    def __init__(self, creation_date=None, creator=None, batch_prefix=None,
    156                  cost=None, entry_num=None, num=None):
     156                 cost=None, entry_num=0, num=None):
    157157        super(AccessCodeBatch, self).__init__()
    158158        self.creation_date = creation_date
     
    317317
    318318    def addBatchByImport(self, batch, batch_id):
    319         """Add an already created `batch` by import
    320         with defined id.
    321         """
     319        """Add an already created `batch` by import with defined id.
     320
     321        We want to create a batch without access codes. Since num_entry
     322        access codes are automatically added by handle_batch_added when
     323        the batch is added to the ZODB, we have to temporarily set entry_num
     324        to zero when adding the batch persistently.
     325        """
     326        orig_entry_num = batch.entry_num
     327        batch.entry_num = 0
    322328        self[batch_id] = batch
     329        self._p_changed = True
     330        batch.entry_num = orig_entry_num
    323331        return
    324332
     
    480488
    481489    def __call__(self, *args, **kw):
    482         return AccessCodeBatch(*args, **kw)
     490        return AccessCodeBatch()
    483491
    484492    def getInterfaces(self):
    485493        return implementedBy(AccessCodeBatch)
     494
     495class AccessCodeFactory(grok.GlobalUtility):
     496    """A factory for accesscodes.
     497
     498    We need this factory for the accesscodeprocessor.
     499    """
     500    grok.implements(IFactory)
     501    grok.name(u'waeup.AccessCode')
     502    title = u"Create a new accesscode.",
     503    description = u"This factory instantiates new accesscode instances."
     504
     505    def __call__(self, *args, **kw):
     506        return AccessCode(*args, **kw)
     507
     508    def getInterfaces(self):
     509        return implementedBy(AccessCode)
    486510
    487511def get_access_code(access_code):
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/batching.py

    r9263 r9265  
    2020"""
    2121import grok
     22from hurry.workflow.interfaces import IWorkflowState
    2223from zope.interface import Interface
    23 from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER
     24from waeup.kofa.interfaces import IBatchProcessor, IGNORE_MARKER, IObjectHistory
    2425from waeup.kofa.utils.batching import BatchProcessor
    25 from waeup.kofa.accesscodes.interfaces import IAccessCodeBatch
     26from waeup.kofa.accesscodes.interfaces import IAccessCodeBatch, IAccessCode
    2627
    2728class AccessCodeBatchProcessor(BatchProcessor):
     
    6768        Returns a string describing the fields changed.
    6869        """
    69         changed = []
    70         for key, value in row.items():
    71             # Skip fields to be ignored.
    72             if value == IGNORE_MARKER:
    73                 continue
    74             if not hasattr(obj, key):
    75                 continue
    76             try:
    77                 evalvalue = eval(value)
    78                 if isinstance(evalvalue, list):
    79                     value = eval(value)
    80             except:
    81                 pass
    82             setattr(obj, key, value)
    83             log_value = getattr(value, 'code', value)
    84             changed.append('%s=%s' % (key, log_value))
    85 
     70        items_changed = super(AccessCodeBatchProcessor, self).updateEntry(
     71            obj, row, site)
    8672        # Log actions...
    8773        location_field = self.location_fields[0]
    88         items_changed = ', '.join(changed)
    8974        grok.getSite()['accesscodes'].logger.info('%s - %s - Batch updated: %s'
    9075            % (self.name, row[location_field], items_changed))
    9176        return
     77
     78class AccessCodeProcessor(BatchProcessor):
     79    """A batch processor for IAccessCode objects.
     80    """
     81    grok.implements(IBatchProcessor)
     82    grok.provides(IBatchProcessor)
     83    grok.context(Interface)
     84    util_name = 'accesscodeprocessor'
     85    grok.name(util_name)
     86
     87    name = u'AccessCode Processor'
     88    iface = IAccessCode
     89
     90    location_fields = ['representation', 'batch_prefix', 'batch_num']
     91    factory_name = 'waeup.AccessCode'
     92
     93    mode = None
     94
     95    @property
     96    def available_fields(self):
     97        return sorted(list(set(
     98                    self.location_fields + [
     99                        'random_num', 'owner', 'cost',
     100                        'state', 'batch_serial',
     101                        'history',]
     102                    )))
     103
     104    @property
     105    def required_fields(self):
     106        return ['random_num', 'state', 'batch_serial', 'history',]
     107
     108    def parentsExist(self, row, site):
     109        return self.getParent(row,site) is not None
     110
     111    def entryExists(self, row, site):
     112        parent = self.getParent(row, site)
     113        if parent is None:
     114            return False
     115        return row['representation'] in parent.keys()
     116
     117    def getParent(self, row, site):
     118        if not 'accesscodes' in site.keys():
     119            return None
     120        batch_id = '%s-%s' % (row['batch_prefix'], row['batch_num'])
     121        return site['accesscodes'].get(batch_id, None)
     122
     123    def getEntry(self, row, site):
     124        if not self.entryExists(row, site):
     125            return None
     126        parent = self.getParent(row, site)
     127        return parent.get(row['representation'], None)
     128
     129    def addEntry(self, obj, row, site):
     130        parent = self.getParent(row, site)
     131        obj.batch_serial = row['batch_serial']
     132        obj.random_num = row['random_num']
     133        parent[row['representation']] = obj
     134        return
     135
     136    def updateEntry(self, obj, row, site):
     137        """Update obj to the values given in row.
     138
     139        Returns a string describing the fields changed.
     140        """
     141        items_changed = ''
     142        # Update state
     143        if row.has_key('state'):
     144            state = row.get('state', IGNORE_MARKER)
     145            if state not in (IGNORE_MARKER, ''):
     146                value = row['state']
     147                IWorkflowState(obj).setState(value)
     148                items_changed += ('%s=%s, ' % ('state', state))
     149            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')
     159
     160        # In import files we can use the hash symbol at the end of a
     161        # random_num string to avoid annoying automatic number transformation
     162        # by Excel or Calc
     163        row['random_num'] = row['random_num'].strip('#')
     164
     165        items_changed += super(AccessCodeProcessor, self).updateEntry(
     166            obj, row, site)
     167
     168        # Log actions...
     169        grok.getSite()['accesscodes'].logger.info('%s - %s - AC updated: %s'
     170            % (self.name, row['representation'], items_changed))
     171        return
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/browser.py

    r9217 r9265  
    6767                continue
    6868            del self.context[name]
     69            self.context._p_changed = True
    6970            self.flash(_('Deleted batch ${a}', mapping = {'a':name}))
    7071            message = 'deleted: %s' % name
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/interfaces.py

    r9263 r9265  
    4949    owner = schema.TextLine(
    5050        title = _(u'Purchaser'),
     51        required = False,
    5152        )
    5253    history = schema.Text(
     
    5455        default = u'',
    5556        readonly = True,
     57        required = False,
    5658       )
    5759
  • main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/tests/test_batching.py

    r9263 r9265  
    3636from waeup.kofa.testing import (
    3737    FunctionalLayer, FunctionalTestCase, setUp, tearDown, getRootFolder)
    38 from waeup.kofa.accesscodes.batching import AccessCodeBatchProcessor
     38from waeup.kofa.accesscodes.batching import (
     39    AccessCodeBatchProcessor, AccessCodeProcessor)
    3940
    4041
     
    4445
    4546BATCH_HEADER_FIELDS = BATCH_SAMPLE_DATA.split(
     47    '\n')[0].split(',')
     48
     49AC_SAMPLE_DATA = open(
     50    os.path.join(os.path.dirname(__file__), 'sample_ac_data.csv'),
     51    'rb').read()
     52
     53AC_HEADER_FIELDS = AC_SAMPLE_DATA.split(
    4654    '\n')[0].split(',')
    4755
     
    7381        self.logfile = os.path.join(
    7482            self.app['datacenter'].storage, 'logs', 'accesscodes.log')
     83        self.workdir = tempfile.mkdtemp()
    7584
    7685    def tearDown(self):
     
    8594    def test_import(self):
    8695        self.processor = AccessCodeBatchProcessor()
    87         self.workdir = tempfile.mkdtemp()
    8896        self.csv_file = os.path.join(self.workdir, 'sample_batch_data.csv')
    8997        open(self.csv_file, 'wb').write(BATCH_SAMPLE_DATA)
     
    102110        shutil.rmtree(os.path.dirname(fin_file))
    103111        return
     112
     113class ACProcessorTest(ACFullSetup):
     114
     115    layer = FunctionalLayer
     116
     117    def test_import(self):
     118        self.processor = AccessCodeBatchProcessor()
     119        self.csv_file = os.path.join(self.workdir, 'sample_batch_data.csv')
     120        open(self.csv_file, 'wb').write(BATCH_SAMPLE_DATA)
     121        self.processor.doImport(self.csv_file, BATCH_HEADER_FIELDS)
     122
     123        self.processor = AccessCodeProcessor()
     124        self.csv_file = os.path.join(self.workdir, 'sample_ac_data.csv')
     125        open(self.csv_file, 'wb').write(AC_SAMPLE_DATA)
     126        num, num_warns, fin_file, fail_file =  self.processor.doImport(
     127            self.csv_file, AC_HEADER_FIELDS)
     128        self.assertEqual(num_warns,0)
     129        self.assertEqual(
     130            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].batch_serial, 33)
     131        self.assertEqual(
     132            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].random_num, '1625368961')
     133        self.assertEqual(
     134            self.app['accesscodes']['CLR-1']['CLR-1-1625368961'].state, 'used')
     135        logcontent = open(self.logfile).read()
     136        self.assertTrue(
     137            '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'
     142            in logcontent)
     143        shutil.rmtree(os.path.dirname(fin_file))
     144        return
  • main/waeup.kofa/trunk/src/waeup/kofa/browser/batchprocessing.txt

    r9203 r9265  
    9393    >>> importerselect = browser.getControl(name='importer')
    9494    >>> importerselect.displayOptions
    95     ['Applicant Processor', 'Applicants Container Processor',
     95    ['AccessCodeBatch Processor', 'AccessCode Processor',
     96    'Applicant Processor', 'Applicants Container Processor',
    9697    'CertificateCourse Processor', 'Certificate Processor',
    9798    'Course Processor', 'CourseTicket Processor',
  • main/waeup.kofa/trunk/src/waeup/kofa/utils/batching.py

    r9219 r9265  
    220220            if not hasattr(obj, key):
    221221                continue
    222             setattr(obj, key, value)
     222            try:
     223                setattr(obj, key, value)
     224            except AttributeError:
     225                # Computed attributes can't be set.
     226                continue
    223227            log_value = getattr(value, 'code', value)
    224228            changed.append('%s=%s' % (key, log_value))
Note: See TracChangeset for help on using the changeset viewer.