"""UI components for accesscodes. """ import grok from datetime import datetime from waeup.sirp.browser import WAeUPPage, WAeUPAddFormPage from waeup.sirp.browser.breadcrumbs import Breadcrumb from waeup.sirp.browser.pages import UniversityPage from waeup.sirp.browser.viewlets import ( AdminTask, AddActionButton, SearchActionButton, BatchOpButton, ManageLink) from waeup.sirp.interfaces import IWAeUPObject, IUniversity from waeup.sirp.accesscodes.accesscodes import AccessCodeBatch from waeup.sirp.accesscodes.interfaces import ( IAccessCodeBatchContainer, IAccessCodeBatch, ) grok.context(IWAeUPObject) class BatchContainerPage(WAeUPPage): grok.name('index') grok.context(IAccessCodeBatchContainer) grok.template('batchcontainer') grok.require('waeup.manageACBatches') title = 'Access Code Batches' pnav = 0 def update(self, batches=None, archive=None, delete=None): if archive is None and delete is None: return if not batches: self.flash('No batch selected.') return if isinstance(batches, basestring): batches = [batches] for name in batches: batch = self.context[name] csv_file = batch.archive() self.flash('Archived %s (%s)' % (name, csv_file)) if delete is None: continue del self.context[name] self.flash('Deleted batch %s' % name) class AddBatchPage(WAeUPAddFormPage): grok.name('add') grok.context(IAccessCodeBatchContainer) grok.require('waeup.manageACBatches') title = 'Create Scratch Card Batch' pnav = 0 form_fields = grok.AutoFields(IAccessCodeBatch).select( 'batch_prefix', 'entry_num', 'cost') @grok.action('Cancel') def cancel(self, *args, **kw): self.flash('Batch creation cancelled.') self.redirect(self.url(self.context)) @grok.action('Create batch') def createBatch(self, **data): creator = self.request.principal.id creation_date = datetime.now() data.update(creation_date=creation_date, creator=creator) batch = self.context.createBatch(**data) csv_file = batch.createCSVLogFile() self.context._p_changed = True self.flash('Batch created (%s entries)' % data['entry_num']) self.flash('Data written to %s' % csv_file) self.redirect(self.url(self.context)) class ReimportBatchPage(WAeUPPage): """Screen for reimporting AC batches. """ grok.name('reimport') grok.context(IAccessCodeBatchContainer) grok.template('reimportbatchpage') grok.require('waeup.manageACBatches') title = 'Reimport Access Code Batches' pnav = 0 def update(self, filenames=None, reimport=None, cancel=None): if cancel is not None: self.flash('Reimport cancelled.') self.redirect(self.url(self.context)) return if reimport is None: return if not filenames: self.flash('No file chosen. Action cancelled.') self.redirect(self.url(self.context)) return if isinstance(filenames, basestring): filenames = [filenames] userid = self.request.principal.id for filename in filenames: try: self.context.reimport(filename, userid) except KeyError: self.flash('This batch already exists: %s' % filename) continue self.flash('Successfully reimported: %s' % filename) self.redirect(self.url(self.context)) class BatchContainerSearchPage(WAeUPPage): grok.name('search') grok.context(IAccessCodeBatchContainer) grok.template('searchpage') grok.require('waeup.manageACBatches') title = 'Search Scratch Cards' pnav = 0 def update(self, search=None, searchterm=None, searchtype=None, entries=None, disable=None, enable=None): self.searchresults = None if search is not None: searchresults = self.context.search(searchterm, searchtype) if len(searchresults) == 0: return self.searchresults = [] for result in searchresults: status = u'unused' if result.disabled is True: status = u'disabled by %s on %s' % ( result.student_id, result.invalidation_date.strftime('%c') ) elif result.invalidation_date is not None: status = u'invalidated by %s on %s' % ( result.student_id, result.invalidation_date.strftime('%c') ) entry = dict( serial = result.batch_serial, code = result.representation, status = status) self.searchresults.append(entry) if entries is None: return if isinstance(entries, basestring): entries = [entries] for entry in entries: if disable is not None: self.context.disable(entry, self.request.principal.id) self.flash('disabled %s' % entry) elif enable is not None: self.context.enable(entry) self.flash('(re-)enabled %s' % entry) return class BatchContainerBreadcrumb(Breadcrumb): """A breadcrumb for ac batch containers. """ grok.require('waeup.manageACBatches') grok.context(IAccessCodeBatchContainer) title = u'Access Code Batches' parent_viewname = 'administration' class BatchContainerSearchBreadcrumb(Breadcrumb): """A breadcrumb for ac batch containers search page. """ grok.require('waeup.manageACBatches') grok.context(IAccessCodeBatchContainer) grok.name('search') title = u'Search Scratch Cards' viewname = 'search' parent_viewname = 'index' class AdminTaskManageACBatches(AdminTask): """Entry on administration page that links to batch container. """ grok.order(5) grok.require('waeup.manageACBatches') grok.template('admintaskacbatches') link_title = 'Access Code Batches' target_viewname = 'accesscodes' class CreateBatchButton(AddActionButton): """Action button on batch container page which links to batch creation. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') text = 'Add Scratch Card Batch' class ReimportBatchButton(BatchOpButton): """Action button on batch container page which links to batch reimport. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') target = 'reimport' text = 'Reimport Scratch Card Batch' class SearchAccessCodeButton(SearchActionButton): """Action button on batch container page which links to search. """ grok.context(IAccessCodeBatchContainer) grok.view(BatchContainerPage) grok.require('waeup.manageACBatches') text = 'Search Scratch Cards' class ManageAccessCodes(ManageLink): """Link in upper left box to access code management. """ grok.order(6) grok.require('waeup.manageACBatches') link = u'accesscodes' text = u'Access Codes'