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

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

Documents can't be verified without file(s) attached.

Let is_approvable and is_verifiable be more verbose.

  • Property svn:keywords set to Id
File size: 7.3 KB
Line 
1## $Id: export.py 12168 2014-12-08 06:17:30Z 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    #: Fieldnames considered by this exporter
131    fields = tuple(sorted(iface_names(ICustomer))) + (
132        'password', 'state', 'history',)
133
134    #: The title under which this exporter will be displayed
135    title = _(u'Customers')
136
137    def mangle_value(self, value, name, context=None):
138        if name == 'history':
139            value = value.messages
140        if name == 'phone' and value is not None:
141            # Append hash '#' to phone numbers to circumvent
142            # unwanted excel automatic
143            value = str('%s#' % value)
144        return super(
145            CustomerExporter, self).mangle_value(
146            value, name, context=context)
147
148
149class CustomerDocumentExporter(grok.GlobalUtility, CustomerExporterBase):
150    """Exporter for CustomerDocument instances.
151    """
152    grok.name('customerdocuments')
153
154    #: Fieldnames considered by this exporter
155    fields = tuple(
156        sorted(iface_names(
157            ICustomerDocument,
158            exclude_attribs=False,
159            omit=['is_editable_by_customer',
160                  'is_editable_by_manager',
161                  'is_verifiable',
162                  'translated_state',
163                  'formatted_transition_date',
164                  'translated_class_name',
165                  'connected_files',   # Could be used to export file URLs
166                  ])))
167
168    #: The title under which this exporter will be displayed
169    title = _(u'Customer Documents')
170
171    def filter_func(self, x, **kw):
172        return get_documents(x)
173
174    def mangle_value(self, value, name, context=None):
175
176        if name == 'history':
177            value = value.messages
178        return super(
179            CustomerDocumentExporter, self).mangle_value(
180            value, name, context=context)
181
182
183class ContractExporter(grok.GlobalUtility, CustomerExporterBase):
184    """Exporter for Contract instances.
185    """
186    grok.name('contracts')
187
188    #: Fieldnames considered by this exporter
189    fields = tuple(
190        sorted(iface_names(
191            ISampleContract,
192            exclude_attribs=False,
193            omit=['translated_state',
194                  'formatted_transition_date',
195                  'translated_class_name',
196                  'is_editable_by_customer',
197                  'is_approvable'])))
198
199    #: The title under which this exporter will be displayed
200    title = _(u'Contracts')
201
202    def filter_func(self, x, **kw):
203        return get_contracts(x)
204
205    def mangle_value(self, value, name, context=None):
206
207        if name == 'history':
208            value = value.messages
209        if name.endswith('_object'):
210            mangled_value = getattr(value, 'document_id', None)
211            if mangled_value:
212                return mangled_value
213            mangled_value = getattr(value, 'product_id', None)
214            if mangled_value:
215                return mangled_value
216        return super(
217            ContractExporter, self).mangle_value(
218            value, name, context=context)
Note: See TracBrowser for help on using the repository browser.