source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/reports/contract_statistics.py @ 14395

Last change on this file since 14395 was 12663, checked in by Henrik Bettermann, 10 years ago

Extend contract workflow to integrate payment.

Prepare (empty) page to select payment method and finally create a payment object.

  • Property svn:keywords set to Id
File size: 8.3 KB
Line 
1## $Id: contract_statistics.py 12663 2015-03-05 07:28:31Z henrik $
2##
3## Copyright (C) 2015 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##
18import grok
19from zope.i18n import translate
20from zope.catalog.interfaces import ICatalog
21from zope.component import queryUtility, getUtility
22from zope.interface import implementer, Interface, Attribute
23from waeup.ikoba.interfaces import (
24    IIkobaUtils,
25    CREATED, APPROVED,
26    SUBMITTED, EXPIRED,
27    REJECTED, AWAITING)
28from waeup.ikoba.customers.interfaces import ICustomersUtils
29from waeup.ikoba.interfaces import MessageFactory as _
30from waeup.ikoba.reports import IReport
31
32class IContractStatisticsReport(IReport):
33
34    creation_dt_string = Attribute('Human readable report creation datetime')
35
36def get_contract_stats():
37    """Get contracts
38
39    Returns a table ordered by contract type and
40    contract state (cols). The result is a 3-tuple representing
41    ((<TYPES>), (<STATES>), (<NUM_OF_CUSTOMERS>)). The
42    (<NUM_OF_CUSTOMERS>) is an n-tuple with each entry containing the
43    number of contracts found for that type and with the respective
44    state.
45
46    Sample result:
47
48      >>> ((u'Sample Contract 1', u'Sample Contract 2'),
49      ...  ('created', 'submitted for approval', 'approved'),
50      ...  ((12, 10, 1), (0, 5, 25)))
51
52    This result means: there are 5 contracts of type 'Sample Contract 2'
53    are in state 'submitted'.
54    """
55    site = grok.getSite()
56    TYPES = getUtility(ICustomersUtils).CONTYPES_DICT
57    types = TYPES.keys()
58    type_names = tuple(TYPES.values()) + (u'All',)
59    states = (CREATED, AWAITING, SUBMITTED, APPROVED, EXPIRED, REJECTED)
60    STATES = getUtility(ICustomersUtils).TRANSLATED_CONTRACT_STATES
61    state_names = tuple([STATES[state] for state in states]) + (u'Total',)
62    # find all contracts
63    cat = queryUtility(ICatalog, name="contracts_catalog")
64    contracts = cat.searchResults(contract_id=(None, None))
65    # create empty table
66    table = [[0 for x in xrange(len(STATES)+1)] for y in xrange(len(TYPES)+1)]
67    # fill table
68    for contract in contracts:
69        row = types.index(contract.class_name)
70        col = states.index(contract.state)
71        table[row][col] += 1
72        table[-1][col] += 1
73        table[row][-1] += 1
74        table[-1][-1] += 1
75    # turn lists into tuples
76    table = tuple([tuple(row) for row in table])
77    return (type_names, state_names, table)
78
79
80from reportlab.lib import colors
81from reportlab.lib.styles import getSampleStyleSheet
82from reportlab.lib.units import cm
83from reportlab.platypus import Paragraph, Table, Spacer
84from waeup.ikoba.reports import IReport, IReportGenerator
85from waeup.ikoba.reports import Report
86from waeup.ikoba.browser.interfaces import IPDFCreator
87
88STYLE = getSampleStyleSheet()
89
90def tbl_data_to_table(row_names, col_names, data):
91    result = []
92    new_col_names = []
93    for name in col_names:
94        new_col_names.append(name.replace(' ', '\n'))
95    head = [''] + list(new_col_names)
96    result = [head]
97    for idx, row_name in enumerate(row_names):
98        row = [row_name] + list(data[idx])
99        result.append(row)
100    return result
101
102TABLE_STYLE = [
103    ('FONT', (0,0), (-1,-1), 'Helvetica', 8),
104    ('FONT', (0,0), (0,-1), 'Helvetica-Bold', 8),
105    ('FONT', (0,0), (-1,0), 'Helvetica-Bold', 8),
106    ('FONT', (0,-1), (-1,-1), 'Helvetica-Bold', 8),
107    ('FONT', (-1,0), (-1,-1), 'Helvetica-Bold', 8),
108    ('ALIGN', (1,1), (-1,-1), 'RIGHT'),
109    ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
110    ('LINEBELOW', (0,-1), (-1,-1), 0.25, colors.black),
111    ('LINEAFTER', (-1,0), (-1,-1), 0.25, colors.black),
112    ('LINEBEFORE', (-1,0), (-1,-1), 1.0, colors.black),
113    ('LINEABOVE', (0,-1), (-1,-1), 1.0, colors.black),
114    #('LINEABOVE', (0,0), (-1,0), 0.25, colors.black),
115    ]
116
117@implementer(IContractStatisticsReport)
118class ContractStatisticsReport(Report):
119
120    data = None
121
122    def __init__(self, author='System'):
123        super(ContractStatisticsReport, self).__init__(
124            args=[], kwargs={'author':author})
125        self.author = author
126        self.creation_dt_string = self.creation_dt.astimezone(
127            getUtility(IIkobaUtils).tzinfo).strftime("%Y-%m-%d %H:%M:%S %Z")
128        self.data = get_contract_stats()
129
130    def create_pdf(self):
131        portal_language = getUtility(IIkobaUtils).PORTAL_LANGUAGE
132        creator = getUtility(IPDFCreator, name='landscape')
133        table_data = tbl_data_to_table(*self.data)
134        col_widths = [None,] + [1.6*cm] * len(self.data[1]) + [None,]
135        pdf_data = [Paragraph('<b>%s</b>' % self.creation_dt_string,
136                              STYLE["Normal"]),
137                    Spacer(1, 12),]
138        pdf_data += [
139            Table(table_data, style=TABLE_STYLE, colWidths=col_widths)]
140        doc_title = translate(_('Contracts'), 'waeup.ikoba',
141            target_language=portal_language)
142        footer_title = doc_title
143
144        pdf = creator.create_pdf(
145            pdf_data, None, doc_title, self.author, footer_title
146            )
147        return pdf
148
149@implementer(IReportGenerator)
150class ContractStatisticsReportGenerator(grok.GlobalUtility):
151
152    title = _('Contract Statistics')
153    grok.name('contract_stats')
154
155    def generate(self, site, author=None):
156        result = ContractStatisticsReport(
157            author=author)
158        return result
159
160###############################################################
161## Browser related stuff
162##
163## XXX: move to local browser module
164###############################################################
165from waeup.ikoba.browser.layout import IkobaPage
166from waeup.ikoba.reports import get_generators
167from waeup.ikoba.browser.breadcrumbs import Breadcrumb
168grok.templatedir('browser_templates')
169class ContractStatisticsReportGeneratorPage(IkobaPage):
170
171    grok.context(ContractStatisticsReportGenerator)
172    grok.name('index.html')
173    grok.require('waeup.manageReports')
174
175    label = _('Create contract statistics report')
176
177    @property
178    def generator_name(self):
179        for name, gen in get_generators():
180            if gen == self.context:
181                return name
182        return None
183
184    def update(self, CREATE=None):
185        self.parent_url = self.url(self.context.__parent__)
186        if CREATE:
187            # create a new report job for contracts
188            container = self.context.__parent__
189            user_id = self.request.principal.id
190            kw = dict()
191            self.flash(_('New report is being created in background'))
192            job_id = container.start_report_job(
193                self.generator_name, user_id, kw=kw)
194            ob_class = self.__implemented__.__name__.replace('waeup.ikoba.','')
195            grok.getSite().logger.info(
196                '%s - report %s created: %s' % (
197                ob_class, job_id, self.context.title))
198            self.redirect(self.parent_url)
199            return
200        return
201
202class ContractStatisticsReportPDFView(grok.View):
203
204    grok.context(IContractStatisticsReport)
205    grok.name('pdf')
206    grok.require('waeup.Public')
207    prefix = ''
208
209    def _filename(self):
210        return 'ContractStatisticsReport.pdf'
211
212    def render(self):
213        filename = self._filename().replace(
214            '/', '_').replace(' ','_').replace(':', '-')
215        self.response.setHeader(
216            'Content-Type', 'application/pdf')
217        self.response.setHeader(
218            'Content-Disposition:', 'attachment; filename="%s' % filename)
219        pdf_stream = self.context.create_pdf()
220        ob_class = self.__implemented__.__name__.replace('waeup.ikoba.','')
221        grok.getSite().logger.info('%s - report %s downloaded: %s' % (
222            ob_class, self.context.__name__, filename))
223        return pdf_stream
224
225class ContractStatsBreadcrumb(Breadcrumb):
226    """A breadcrumb for reports.
227    """
228    grok.context(ContractStatisticsReportGenerator)
229    title = _(u'Contract Statistics')
230    target = None
Note: See TracBrowser for help on using the repository browser.