source: main/waeup.sirp/trunk/src/waeup/sirp/accesscodes/accesscodes.py @ 5117

Last change on this file since 5117 was 5116, checked in by uli, 15 years ago
  • Use only uppercase prefixes.
  • Be accurate when determining the next batch number.
File size: 4.8 KB
Line 
1"""Components to handle access codes.
2"""
3import csv
4import grok
5import os
6from random import SystemRandom as random
7from waeup.sirp.interfaces import IWAeUPSIRPPluggable
8from waeup.sirp.accesscodes.interfaces import (
9    IAccessCode, IAccessCodeBatch, IAccessCodeBatchContainer
10    )
11
12class ManageACBatches(grok.Permission):
13    grok.name('waeup.manageACBatches')
14
15class AccessCode(grok.Model):
16    grok.implements(IAccessCode)
17
18    def __init__(self, batch_serial, random_num, cost,
19                 invalidation_date=None, student_id=None):
20        self.batch_serial = batch_serial
21        self.random_num = random_num
22        self.cost = cost
23        self.invalidation_date = invalidation_date
24        self.student_id = student_id
25
26    @property
27    def representation(self):
28        return '%s-%s-%s' % (
29            self.batch_prefix, self.batch_num, self.random_num)
30
31    @property
32    def batch(self):
33        return getattr(self, '__parent__', None)
34
35    @property
36    def batch_prefix(self):
37        if self.batch is None:
38            return ''
39        return self.batch.prefix
40
41    @property
42    def batch_num(self):
43        if self.batch is None:
44            return ''
45        return self.batch.num
46
47class AccessCodeBatch(grok.Container):
48    """A batch of access codes.
49    """
50    grok.implements(IAccessCodeBatch)
51
52    def __init__(self, creation_date, creator, batch_prefix, cost,
53                 entry_num, num=None):
54        super(AccessCodeBatch, self).__init__()
55        self.creation_date = creation_date
56        self.creator = creator
57        self.prefix = batch_prefix.upper()
58        self.cost = cost
59        self.entry_num = entry_num
60        self.num = num
61
62    def createEntries(self):
63        """Create the entries for this batch.
64        """
65        rands = self.getNewRandomNum(num=self.entry_num)
66        for num in range(self.entry_num):
67            ac = AccessCode(num, rands[num], self.cost)
68            self[str(num)] = ac
69        return
70       
71    def getNewRandomNum(self, num=1):
72        """Create a set of ``num`` random numbers of 10 digits each.
73
74        The number is returned as string.
75        """
76        results = {}
77        while len(results) < num:
78            pin = ''
79            for x in range(10):
80                pin += str(random().randint(0, 9))
81            results[pin] = True
82        return results.keys()
83
84    def createCSVLogFile(self):
85        """Create a CSV file with data in batch.
86
87        Data will not contain invalidation date nor student ids.  File
88        will be created in ``accesscodes`` subdir of data center
89        storage path.
90
91        Returns name of created file.
92        """
93        site = grok.getSite()
94        storagepath = site['datacenter'].storage
95        ac_storage = os.path.join(storagepath, 'accesscodes')
96        if not os.path.exists(ac_storage):
97            os.mkdir(ac_storage)
98        date = self.creation_date.strftime('%Y_%m_%d_%H_%M_%S')
99        csv_path = os.path.join(
100            ac_storage, '%s-%s-%s-%s.csv' % (
101                self.prefix, self.num, date, self.creator)
102            )
103        writer = csv.writer(open(csv_path, 'w'), quoting=csv.QUOTE_ALL)
104        writer.writerow(['serial', 'ac', 'cost'])
105        writer.writerow([self.prefix, str(self.num), "%0.2f" % self.cost])
106        for key, value in self.items():
107            writer.writerow(
108                [str(value.batch_serial), str(value.representation)]
109                )
110        logger = site.logger
111        logger.info(
112            "Created batch %s-%s" % (self.prefix, self.num))
113        logger.info(
114            "Written batch CSV to %s" % csv_path)
115        return os.path.basename(csv_path)
116
117   
118class AccessCodeBatchContainer(grok.Container):
119    grok.implements(IAccessCodeBatchContainer)
120
121    def addBatch(self, batch):
122        """Add a batch.
123        """
124        batch.num = self.getNum(batch.prefix)
125        key = "%s-%s" % (batch.prefix, batch.num)
126        self[key] = batch
127        batch.createEntries()
128        self._p_changed = True
129
130    def getNum(self, prefix):
131        """Get next unused num for given prefix.
132        """
133        num = 1
134        while self.get('%s-%s' % (prefix, num), None) is not None:
135            num += 1
136        return num
137
138class AccessCodePlugin(grok.GlobalUtility):
139    grok.name('accesscodes')
140    grok.implements(IWAeUPSIRPPluggable)
141
142    def setup(self, site, name, logger):
143        site['accesscodes'] = AccessCodeBatchContainer()
144        logger.info('Installed container for access code batches.')
145        return
146
147    def update(self, site, name, logger):
148        if not 'accesscodes' in site.keys():
149            logger.info('Updating site at %s. Installing access codes.' % (
150                    site,))
151            self.setup(site, name, logger)
152        else:
153            logger.info(
154                'AccessCodePlugin: Updating site at %s: Nothing to do.' % (
155                    site, ))
156        return
Note: See TracBrowser for help on using the repository browser.