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

Last change on this file since 14022 was 13135, checked in by Henrik Bettermann, 9 years ago

Extend interfaces (for future documentation).

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