source: main/waeup.kofa/trunk/src/waeup/kofa/accesscodes/browser.py @ 8305

Last change on this file since 8305 was 8194, checked in by Henrik Bettermann, 13 years ago

Store utc without tzinfo in persistent datetime objects. Localisation will be done in views only.

  • Property svn:keywords set to Id
File size: 9.8 KB
RevLine 
[7195]1## $Id: browser.py 8194 2012-04-17 11:40:06Z henrik $
2##
3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
[5082]18"""UI components for accesscodes.
19"""
20import grok
[5088]21from datetime import datetime
[8182]22from zope.component import getUtility
[6450]23from hurry.workflow.interfaces import InvalidTransitionError
[7811]24from waeup.kofa.browser.resources import datatable
[7819]25from waeup.kofa.browser import KofaPage, KofaAddFormPage, NullValidator
[7811]26from waeup.kofa.browser.breadcrumbs import Breadcrumb
27from waeup.kofa.browser.viewlets import (
[5381]28    AdminTask, AddActionButton, SearchActionButton, BatchOpButton, ManageLink)
[8182]29from waeup.kofa.interfaces import IKofaObject, IKofaUtils
[7811]30from waeup.kofa.interfaces import MessageFactory as _
31from waeup.kofa.accesscodes.interfaces import (
[5088]32    IAccessCodeBatchContainer, IAccessCodeBatch,
33    )
[7811]34from waeup.kofa.accesscodes.catalog import search
35from waeup.kofa.browser.layout import action
[5082]36
[7819]37grok.context(IKofaObject)
[5082]38
[7819]39class BatchContainerPage(KofaPage):
[5082]40    grok.name('index')
41    grok.context(IAccessCodeBatchContainer)
42    grok.template('batchcontainer')
[5104]43    grok.require('waeup.manageACBatches')
[7719]44    archive_button = _('Archive')
45    delete_button = _('Archive and delete')
[5082]46
[7719]47    label = _('Access Code Batches')
[5082]48    pnav = 0
49
[5117]50    def update(self, batches=None, archive=None, delete=None):
51        if archive is None and delete is None:
52            return
[5124]53        if not batches:
[7719]54            self.flash(_('No batch selected.'))
[5124]55            return
[5117]56        if isinstance(batches, basestring):
57            batches = [batches]
[7811]58        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
[5117]59        for name in batches:
60            batch = self.context[name]
61            csv_file = batch.archive()
[7719]62            self.flash(_('Archived ${a} (${b})',
63                mapping = {'a':name, 'b':csv_file}))
[7747]64            message = 'archived: %s (%s)' % (name,csv_file)
65            self.context.logger_info(ob_class, message)
[5117]66            if delete is None:
67                continue
68            del self.context[name]
[7719]69            self.flash(_('Deleted batch ${a}', mapping = {'a':name}))
[7747]70            message = 'deleted: %s' % name
71            self.context.logger_info(ob_class, message)
[5104]72
[7819]73class AddBatchPage(KofaAddFormPage):
[5084]74    grok.name('add')
75    grok.context(IAccessCodeBatchContainer)
[5104]76    grok.require('waeup.manageACBatches')
[5084]77
[7719]78    label = _('Create Access Code Batch')
[5084]79    pnav = 0
80
[5088]81    form_fields = grok.AutoFields(IAccessCodeBatch).select(
[6417]82        'prefix', 'entry_num', 'cost')
[5088]83
[7719]84    @action(_('Create batch'), style='primary')
[5084]85    def createBatch(self, **data):
[5088]86        creator = self.request.principal.id
[8194]87        creation_date = datetime.utcnow()
[5088]88        data.update(creation_date=creation_date, creator=creator)
[5126]89        batch = self.context.createBatch(**data)
[5113]90        csv_file = batch.createCSVLogFile()
[5088]91        self.context._p_changed = True
[7720]92        self.flash(_('Batch created (${a} entries)',
93            mapping = {'a':data['entry_num']}))
94        self.flash(_('Data written to ${a}', mapping = {'a':csv_file}))
[7811]95        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
[7747]96        message = 'created: %s (%d, %f)' % (
97            csv_file, data['entry_num'], data['cost'])
98        self.context.logger_info(ob_class, message)
[5084]99        self.redirect(self.url(self.context))
100
[7719]101    @action(_('Cancel'), validator=NullValidator)
[7488]102    def cancel(self, *args, **kw):
[7719]103        self.flash(_('Batch creation cancelled.'))
[7488]104        self.redirect(self.url(self.context))
105
[7819]106class ReimportBatchPage(KofaPage):
[5132]107    """Screen for reimporting AC batches.
108    """
[5130]109    grok.name('reimport')
110    grok.context(IAccessCodeBatchContainer)
111    grok.template('reimportbatchpage')
112    grok.require('waeup.manageACBatches')
[7719]113    reimport_button = _('Reimport')
114    cancel_button = _('Cancel')
[5130]115
[7719]116    label = _('Reimport Access Code Batches')
[5130]117    pnav = 0
118
[5132]119    def update(self, filenames=None, reimport=None, cancel=None):
120        if cancel is not None:
[7719]121            self.flash(_('Reimport cancelled.'))
[5132]122            self.redirect(self.url(self.context))
123            return
124        if reimport is None:
125            return
126        if not filenames:
[7719]127            self.flash(_('No file chosen. Action cancelled.'))
[5132]128            self.redirect(self.url(self.context))
129            return
130        if isinstance(filenames, basestring):
131            filenames = [filenames]
132        userid = self.request.principal.id
133        for filename in filenames:
134            try:
135                self.context.reimport(filename, userid)
136            except KeyError:
[7719]137                self.flash(_('This batch already exists: ${a}',
138                    mapping = {'a':filename}))
[5132]139                continue
[7719]140            self.flash(_('Successfully reimported: ${a}',
141                mapping = {'a':filename}))
[7811]142            ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
[7747]143            message = 'reimported: %s' % filename
144            self.context.logger_info(ob_class, message)
[5132]145        self.redirect(self.url(self.context))
[6388]146
[7819]147class BatchContainerSearchPage(KofaPage):
[5155]148    grok.name('search')
149    grok.context(IAccessCodeBatchContainer)
150    grok.template('searchpage')
151    grok.require('waeup.manageACBatches')
152    pnav = 0
[7719]153    label = _('Search and Manage Access Codes')
154    search_button = _('Search')
155    disable_button = _('Disable ACs')
156    enable_button = _('Enable ACs')
[5155]157
[6450]158    def update(self, *args, **kw):
[6455]159        datatable.need()
[6450]160        form = self.request.form
161        self.hitlist = []
162        if 'searchterm' in form and form['searchterm']:
163            self.searchterm = form['searchterm']
164            self.searchtype = form['searchtype']
165        elif 'old_searchterm' in form:
166            self.searchterm = form['old_searchterm']
167            self.searchtype = form['old_searchtype']
168        else:
[5155]169            return
[6450]170        if not 'entries' in form:
171            self.hitlist = search(query=self.searchterm,
172                searchtype=self.searchtype, view=self)
173            return
174        entries = form['entries']
[5155]175        if isinstance(entries, basestring):
176            entries = [entries]
[7811]177        ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
[5155]178        for entry in entries:
[6450]179            if 'disable' in form:
180                try:
[7745]181                    comment = _(u"disabled")
[6459]182                    self.context.disable(entry, comment)
[7719]183                    self.flash(_('${a} disabled.', mapping = {'a':entry}))
[7747]184                    message = 'disabled: %s' % entry
185                    self.context.logger_info(ob_class, message)
[6450]186                except InvalidTransitionError:
[7719]187                    self.flash(_('${a}: Disable transition not allowed.',
188                        mapping = {'a':entry}))
[6450]189            elif 'enable' in form:
190                try:
[7745]191                    comment = _(u"re-enabled")
[6459]192                    self.context.enable(entry, comment)
[7719]193                    self.flash(_('${a} (re-)enabled.', mapping = {'a':entry}))
[7747]194                    message = '(re-)enabled: %s' % entry
195                    self.context.logger_info(ob_class, message)
[6450]196                except InvalidTransitionError:
[7719]197                    self.flash(_('${a}: Re-enable transition not allowed.', mapping = {'a':entry}))
[6450]198        self.hitlist = search(query=self.searchterm,
199            searchtype=self.searchtype, view=self)
[5155]200        return
201
[5082]202class BatchContainerBreadcrumb(Breadcrumb):
203    """A breadcrumb for ac batch containers.
[5104]204    """
205    grok.require('waeup.manageACBatches')
[5082]206    grok.context(IAccessCodeBatchContainer)
[7719]207    title = _(u'Access Code Batches')
[5082]208    parent_viewname = 'administration'
209
[7488]210#class BatchContainerSearchBreadcrumb(Breadcrumb):
211#    """A breadcrumb for ac batch containers search page.
212#    """
213#    grok.require('waeup.manageACBatches')
214#    grok.context(IAccessCodeBatchContainer)
215#    grok.name('search')
216#    title = u'Search Access Codes'
217#    viewname = 'search'
218#    parent_viewname = 'index'
[5155]219
[5082]220class AdminTaskManageACBatches(AdminTask):
221    """Entry on administration page that links to batch container.
222    """
223    grok.order(5)
[5104]224    grok.require('waeup.manageACBatches')
[5082]225    grok.template('admintaskacbatches')
226
[7719]227    link_title = _('Access Code Batches')
[5082]228    target_viewname = 'accesscodes'
[5084]229
230class CreateBatchButton(AddActionButton):
231    """Action button on batch container page which links to batch creation.
232    """
233    grok.context(IAccessCodeBatchContainer)
234    grok.view(BatchContainerPage)
[5104]235    grok.require('waeup.manageACBatches')
[7719]236    text = _('Add Access Code Batch')
[5104]237
[5129]238class ReimportBatchButton(BatchOpButton):
239    """Action button on batch container page which links to batch reimport.
240    """
241    grok.context(IAccessCodeBatchContainer)
242    grok.view(BatchContainerPage)
243    grok.require('waeup.manageACBatches')
244    target = 'reimport'
[7719]245    text = _('Reimport Access Code Batch')
[5129]246
[5155]247class SearchAccessCodeButton(SearchActionButton):
248    """Action button on batch container page which links to search.
249    """
250    grok.context(IAccessCodeBatchContainer)
251    grok.view(BatchContainerPage)
252    grok.require('waeup.manageACBatches')
[7719]253    text = _('Search Access Codes')
[6388]254
[5381]255class ManageAccessCodes(ManageLink):
256    """Link in upper left box to access code management.
[5104]257    """
258    grok.order(6)
259    grok.require('waeup.manageACBatches')
260
[5381]261    link = u'accesscodes'
[7719]262    text = _(u'Access Codes')
Note: See TracBrowser for help on using the repository browser.