source: main/waeup.ikoba/trunk/src/waeup/ikoba/customers/export.py @ 12278

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

Reorganize exporters slightly to ease customization.

  • Property svn:keywords set to Id
File size: 7.5 KB
Line 
1## $Id: export.py 12275 2014-12-21 07:46:55Z henrik $
2##
3## Copyright (C) 2014 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##
18"""Exporters for customer related stuff.
19"""
20import os
21import grok
22from datetime import datetime
23from zope.component import getUtility
24from waeup.ikoba.interfaces import (
25    IExtFileStore, IFileStoreNameChooser)
26from waeup.ikoba.interfaces import MessageFactory as _
27from waeup.ikoba.customers.catalog import CustomersQuery
28from waeup.ikoba.customers.interfaces import (
29    ICustomer, ICSVCustomerExporter, ICustomerDocument,
30    ISampleContract)
31from waeup.ikoba.utils.batching import ExporterBase
32from waeup.ikoba.utils.helpers import iface_names, to_timezone
33
34#: A tuple containing all exporter names referring to customers or
35#: subobjects thereof.
36EXPORTER_NAMES = ('customers', 'customerdocuments')
37
38
39def get_customers(site, cust_filter=CustomersQuery()):
40    """Get all customers registered in catalog in `site`.
41    """
42    return cust_filter.query()
43
44def get_documents(customers):
45    """Get all documents of `customers`.
46    """
47    documents = []
48    for customer in customers:
49        for document in customer.get('documents', {}).values():
50            documents.append(document)
51    return documents
52
53def get_contracts(customers):
54    """Get all contracts of `customers`.
55    """
56    contracts = []
57    for customer in customers:
58        for contract in customer.get('contracts', {}).values():
59            contracts.append(contract)
60    return contracts
61
62class CustomerExporterBase(ExporterBase):
63    """Exporter for customers or related objects.
64
65    This is a baseclass.
66    """
67    grok.baseclass()
68    grok.implements(ICSVCustomerExporter)
69    grok.provides(ICSVCustomerExporter)
70
71    def filter_func(self, x, **kw):
72        return x
73
74    def get_filtered(self, site, **kw):
75        """Get customers from a catalog filtered by keywords.
76
77        customers_catalog is the default catalog. The keys must be valid
78        catalog index names.
79        Returns a simple empty list, a list with `Customer`
80        objects or a catalog result set with `Customer`
81        objects.
82
83        .. seealso:: `waeup.ikoba.customers.catalog.CustomersCatalog`
84
85        """
86        # Pass only given keywords to create FilteredCatalogQuery objects.
87        # This way we avoid
88        # trouble with `None` value ambivalences and queries are also
89        # faster (normally less indexes to ask). Drawback is, that
90        # developers must look into catalog to see what keywords are
91        # valid.
92        query = CustomersQuery(**kw)
93        return query.query()
94
95    def export(self, values, filepath=None):
96        """Export `values`, an iterable, as CSV file.
97
98        If `filepath` is ``None``, a raw string with CSV data is returned.
99        """
100        writer, outfile = self.get_csv_writer(filepath)
101        for value in values:
102            self.write_item(value, writer)
103        return self.close_outfile(filepath, outfile)
104
105    def export_all(self, site, filepath=None):
106        """Export customers into filepath as CSV data.
107
108        If `filepath` is ``None``, a raw string with CSV data is returned.
109        """
110        return self.export(self.filter_func(get_customers(site)), filepath)
111
112    def export_customer(self, customer, filepath=None):
113        return self.export(self.filter_func([customer]), filepath=filepath)
114
115    def export_filtered(self, site, filepath=None, **kw):
116        """Export items denoted by `kw`.
117
118        If `filepath` is ``None``, a raw string with CSV data should
119        be returned.
120        """
121        data = self.get_filtered(site, **kw)
122        return self.export(self.filter_func(data, **kw), filepath=filepath)
123
124
125class CustomerExporter(grok.GlobalUtility, CustomerExporterBase):
126    """Exporter for Customers.
127    """
128    grok.name('customers')
129
130    iface = ICustomer
131
132    #: The title under which this exporter will be displayed
133    title = _(u'Customers')
134
135    #: Fieldnames considered by this exporter
136    @property
137    def fields(self):
138        return tuple(sorted(iface_names(self.iface))) + (
139            'password', 'state', 'history',)
140
141    def mangle_value(self, value, name, context=None):
142        if name == 'history':
143            value = value.messages
144        if name == 'phone' and value is not None:
145            # Append hash '#' to phone numbers to circumvent
146            # unwanted excel automatic
147            value = str('%s#' % value)
148        return super(
149            CustomerExporter, self).mangle_value(
150            value, name, context=context)
151
152
153class CustomerDocumentExporter(grok.GlobalUtility, CustomerExporterBase):
154    """Exporter for CustomerDocument instances.
155    """
156    grok.name('customerdocuments')
157
158    iface = ICustomerDocument
159
160    #: The title under which this exporter will be displayed
161    title = _(u'Customer Documents')
162
163    #: Fieldnames considered by this exporter
164    @property
165    def fields(self):
166        return tuple(
167            sorted(iface_names(
168                self.iface, exclude_attribs=False,
169                omit=['is_editable_by_customer',
170                      'is_editable_by_manager',
171                      'is_verifiable',
172                      'translated_state',
173                      'formatted_transition_date',
174                      'translated_class_name',
175                      'connected_files',   # Could be used to export file URLs
176                      ])))
177
178    def filter_func(self, x, **kw):
179        return get_documents(x)
180
181    def mangle_value(self, value, name, context=None):
182
183        if name == 'history':
184            value = value.messages
185        return super(
186            CustomerDocumentExporter, self).mangle_value(
187            value, name, context=context)
188
189
190class ContractExporter(grok.GlobalUtility, CustomerExporterBase):
191    """Exporter for Contract instances.
192    """
193    grok.name('contracts')
194
195    iface = ISampleContract
196
197    #: The title under which this exporter will be displayed
198    title = _(u'Contracts')
199
200    #: Fieldnames considered by this exporter
201    @property
202    def fields(self):
203        return tuple(
204            sorted(iface_names(
205                self.iface, exclude_attribs=False,
206                omit=['translated_state',
207                      'formatted_transition_date',
208                      'translated_class_name',
209                      'is_editable_by_customer',
210                      'is_approvable'])))
211
212    def filter_func(self, x, **kw):
213        return get_contracts(x)
214
215    def mangle_value(self, value, name, context=None):
216
217        if name == 'history':
218            value = value.messages
219        if name.endswith('_object'):
220            mangled_value = getattr(value, 'document_id', None)
221            if mangled_value:
222                return mangled_value
223            mangled_value = getattr(value, 'product_id', None)
224            if mangled_value:
225                return mangled_value
226        return super(
227            ContractExporter, self).mangle_value(
228            value, name, context=context)
Note: See TracBrowser for help on using the repository browser.