source: main/waeup.kofa/trunk/src/waeup/kofa/applicants/export.py @ 13951

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

Add ApplicantPaymentExporter.

  • Property svn:keywords set to Id
File size: 9.0 KB
Line 
1## $Id: export.py 13949 2016-06-17 07:46:34Z henrik $
2##
3## Copyright (C) 2012 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 applicant-related stuff.
19"""
20import grok
21from zope.catalog.interfaces import ICatalog
22from zope.component import queryUtility
23from waeup.kofa.applicants.interfaces import (
24    IApplicantBaseData, IApplicantsContainer, IApplicantOnlinePayment)
25from waeup.kofa.interfaces import ICSVExporter
26from waeup.kofa.interfaces import MessageFactory as _
27from waeup.kofa.utils.batching import ExporterBase
28from waeup.kofa.utils.helpers import iface_names
29
30class ApplicantsContainerExporter(grok.GlobalUtility, ExporterBase):
31    """The Applicants Container Exporter exports container data. It does not
32    export applicants (application records) inside the container.
33    """
34    grok.implements(ICSVExporter)
35    grok.name('applicantscontainers')
36
37    fields = tuple(sorted(iface_names(IApplicantsContainer)))
38    title = _(u'Applicants Containers')
39
40    def mangle_value(self, value, name, context=None):
41        return super(
42            ApplicantsContainerExporter, self).mangle_value(
43            value, name, context=context)
44
45    def export(self, containers, filepath=None):
46        """Export `containers`, an iterable, as CSV file.
47
48        If `filepath` is ``None``, a raw string with CSV data is returned.
49        """
50        writer, outfile = self.get_csv_writer(filepath)
51        for container in containers:
52            self.write_item(container, writer)
53        return self.close_outfile(filepath, outfile)
54
55    def export_all(self, site, filepath=None):
56        """Export applicantscontainer into filepath as CSV data.
57
58        If `filepath` is ``None``, a raw string with CSV data is returned.
59        """
60        writer, outfile = self.get_csv_writer(filepath)
61        containers = site.get('applicants', {})
62        return self.export(containers.values(), filepath)
63
64
65class ApplicantExporter(grok.GlobalUtility, ExporterBase):
66    """The Applicant Exporter exports application records (= applicants)
67    stored in the database. In contrast to the exporters in the academic
68    section this exporter does not iterate over the items of containers
69    but searches the :class:`ApplicantsCatalog` instead.
70
71    The exporter exports all applicants if started in the Data Center
72    which means in the context of the `DataCenter` object. The exporter can also
73    be started 'locally' which means in the context of an `ApplicantsContainer`
74    container. Then the :meth:`export_filtered()` instead of the
75    :meth:`export_all()` method is applied which searches for applicants
76    in the respective container.
77    """
78    grok.implements(ICSVExporter)
79    grok.name('applicants')
80
81    fields = tuple(sorted(iface_names(IApplicantBaseData))) + (
82        'password', 'state', 'history', 'container_code', 'application_number',
83        'display_fullname', 'application_date')
84    title = _(u'Applicants')
85
86    def mangle_value(self, value, name, context=None):
87        """The mangler determines the codes of the atributes `course1`,
88        `course2` and `course_admitted`. It furthermore prepares the
89        history messages and adds a hash symbol at the end of the phone number
90        to avoid annoying automatic number transformation by Excel or Calc.
91        """
92        if name.startswith('course') and value is not None:
93            value = value.code
94        #elif name == 'school_grades':
95        #    value = [eval(entry.to_string()) for entry in value]
96        elif name == 'history':
97            value = value.messages
98        elif name == 'phone' and value is not None:
99            # Append hash '#' to phone numbers to circumvent
100            # unwanted excel automatic
101            value = str('%s#' % value)
102        elif name == 'container_code':
103            value = value.strip('+')
104        return super(
105            ApplicantExporter, self).mangle_value(
106            value, name, context=context)
107
108    def export(self, applicants, filepath=None):
109        """Export `applicants`, an iterable, as CSV file.
110        If `filepath` is ``None``, a raw string with CSV data is returned.
111        """
112        writer, outfile = self.get_csv_writer(filepath)
113        for applicant in applicants:
114            self.write_item(applicant, writer)
115        return self.close_outfile(filepath, outfile)
116
117    def export_all(self, site, filepath=None):
118        """Export all applicants into filepath as CSV data.
119        If `filepath` is ``None``, a raw string with CSV data is returned.
120        Only used records are being exported.
121        """
122        catalog = queryUtility(
123            ICatalog, context=site, name='applicants_catalog', default=None)
124        if catalog is None:
125            return self.export([], filepath)
126        applicants = catalog.searchResults(
127            # reg_num might not be set and then would not be found.
128            # We therefore search for applicant_id.
129            applicant_id=(None, None))
130        used = [value for value in applicants
131                if value.container_code.endswith('+')]
132        return self.export(used, filepath=filepath)
133
134    def export_filtered(self, site, filepath=None, **kw):
135        """Export filtered applicants in container denoted by keywords (`kw`).
136        If `filepath` is ``None``, a raw string with CSV data should
137        be returned. Only used records are being exported.
138        """
139        container = grok.getSite()['applicants'][kw['container']]
140        container_values = container.values()
141        used = [value for value in container_values
142                if value.container_code.endswith('+')]
143        return self.export(used, filepath=filepath)
144
145
146class ApplicantPaymentExporter(grok.GlobalUtility, ExporterBase):
147    """The Applicant Payments Exporter exports all payments made by applicants.
148    In other words, it exports payment tickets in state 'paid'. The exporter
149    searches :class:`ApplicantsCatalog` and iterates over all payment tickets
150    which are stored in an applicant (container).
151
152    The exporter exports all applicant payments if started in the Data Center
153    which means in the context of the `DataCenter` object. The exporter can also
154    be started 'locally' which means in the context of an
155    `ApplicantsContainer` container, see `ApplicantExporter` above.
156    """
157    grok.implements(ICSVExporter)
158    grok.name('applicantpayments')
159
160    fields = tuple(sorted(iface_names(
161        IApplicantOnlinePayment,
162        exclude_attribs=False,
163        omit=['display_item']))) + ('applicant_id',)
164    title = _(u'Applicant Payments')
165
166    def mangle_value(self, value, name, context=None):
167        """The mangler determines the applicant's id.
168        """
169        if name == 'applicant_id' and context is not None:
170            applicant = context.__parent__
171            value = getattr(applicant, name, None)
172        return super(
173            ApplicantPaymentExporter, self).mangle_value(
174            value, name, context=context)
175
176    def export(self, payments, filepath=None):
177        """
178        """
179        writer, outfile = self.get_csv_writer(filepath)
180        for payment in payments:
181            self.write_item(payment, writer)
182        return self.close_outfile(filepath, outfile)
183
184    def export_all(self, site, filepath=None):
185        """
186        """
187        catalog = queryUtility(
188            ICatalog, context=site, name='applicants_catalog', default=None)
189        if catalog is None:
190            return self.export([], filepath)
191        applicants = catalog.searchResults(
192            # reg_num might not be set and then would not be found.
193            # We therefore search for applicant_id.
194            applicant_id=(None, None))
195        used = [value for value in applicants
196                if value.container_code.endswith('+')]
197        payments = []
198        for applicant in used:
199            for payment in applicant.values():
200                if payment.p_state == 'paid':
201                    payments.append(payment)
202        return self.export(payments, filepath=filepath)
203
204    def export_filtered(self, site, filepath=None, **kw):
205        """
206        """
207        container = grok.getSite()['applicants'][kw['container']]
208        container_values = container.values()
209        used = [value for value in container_values
210                if value.container_code.endswith('+')]
211        payments = []
212        for applicant in used:
213            for payment in applicant.values():
214                if payment.p_state == 'paid':
215                    payments.append(payment)
216        return self.export(payments, filepath=filepath)
Note: See TracBrowser for help on using the repository browser.