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

Last change on this file since 17253 was 16431, checked in by Henrik Bettermann, 4 years ago

Add payment option (p_option) field to payment tickets and add
select box on online payment add form pages. Disable this feature
in the base package.

  • Property svn:keywords set to Id
File size: 11.9 KB
RevLine 
[7865]1## $Id: export.py 16431 2021-03-25 09:45:54Z 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
[7914]21from zope.catalog.interfaces import ICatalog
22from zope.component import queryUtility
[8724]23from waeup.kofa.applicants.interfaces import (
[16064]24    IApplicantBaseData, IApplicantsContainer, IApplicantOnlinePayment,
25    IApplicantRefereeReport)
[7865]26from waeup.kofa.interfaces import ICSVExporter
[7906]27from waeup.kofa.interfaces import MessageFactory as _
[7865]28from waeup.kofa.utils.batching import ExporterBase
[8724]29from waeup.kofa.utils.helpers import iface_names
[7865]30
31class ApplicantsContainerExporter(grok.GlobalUtility, ExporterBase):
[12859]32    """The Applicants Container Exporter exports container data. It does not
33    export applicants (application records) inside the container.
[7865]34    """
35    grok.implements(ICSVExporter)
36    grok.name('applicantscontainers')
37
[8724]38    fields = tuple(sorted(iface_names(IApplicantsContainer)))
[12180]39    title = _(u'Applicants Containers')
[7906]40
41    def mangle_value(self, value, name, context=None):
42        return super(
43            ApplicantsContainerExporter, self).mangle_value(
44            value, name, context=context)
45
[7865]46    def export(self, containers, filepath=None):
47        """Export `containers`, an iterable, as CSV file.
48
49        If `filepath` is ``None``, a raw string with CSV data is returned.
50        """
51        writer, outfile = self.get_csv_writer(filepath)
52        for container in containers:
53            self.write_item(container, writer)
54        return self.close_outfile(filepath, outfile)
55
56    def export_all(self, site, filepath=None):
57        """Export applicantscontainer into filepath as CSV data.
58
59        If `filepath` is ``None``, a raw string with CSV data is returned.
60        """
61        writer, outfile = self.get_csv_writer(filepath)
62        containers = site.get('applicants', {})
63        return self.export(containers.values(), filepath)
[7914]64
[12859]65
[12079]66class ApplicantExporter(grok.GlobalUtility, ExporterBase):
[12861]67    """The Applicant Exporter exports application records (= applicants)
[12862]68    stored in the database. In contrast to the exporters in the academic
[12859]69    section this exporter does not iterate over the items of containers
[12861]70    but searches the :class:`ApplicantsCatalog` instead.
71
72    The exporter exports all applicants if started in the Data Center
73    which means in the context of the `DataCenter` object. The exporter can also
74    be started 'locally' which means in the context of an `ApplicantsContainer`
75    container. Then the :meth:`export_filtered()` instead of the
76    :meth:`export_all()` method is applied which searches for applicants
77    in the respective container.
[7914]78    """
79    grok.implements(ICSVExporter)
80    grok.name('applicants')
81
[13080]82    fields = tuple(sorted(iface_names(IApplicantBaseData))) + (
83        'password', 'state', 'history', 'container_code', 'application_number',
84        'display_fullname', 'application_date')
[7914]85    title = _(u'Applicants')
86
[7924]87    def mangle_value(self, value, name, context=None):
[12865]88        """The mangler determines the codes of the atributes `course1`,
[12859]89        `course2` and `course_admitted`. It furthermore prepares the
90        history messages and adds a hash symbol at the end of the phone number
91        to avoid annoying automatic number transformation by Excel or Calc.
92        """
[13542]93        if name.startswith('course') and value is not None:
[7924]94            value = value.code
[8052]95        #elif name == 'school_grades':
96        #    value = [eval(entry.to_string()) for entry in value]
97        elif name == 'history':
[15156]98            value = getattr(value, 'messages', None)
[9117]99        elif name == 'phone' and value is not None:
100            # Append hash '#' to phone numbers to circumvent
101            # unwanted excel automatic
102            value = str('%s#' % value)
[13216]103        elif name == 'container_code':
104            value = value.strip('+')
[7914]105        return super(
[12079]106            ApplicantExporter, self).mangle_value(
[7914]107            value, name, context=context)
108
109    def export(self, applicants, filepath=None):
110        """Export `applicants`, an iterable, as CSV file.
111        If `filepath` is ``None``, a raw string with CSV data is returned.
112        """
113        writer, outfile = self.get_csv_writer(filepath)
114        for applicant in applicants:
115            self.write_item(applicant, writer)
116        return self.close_outfile(filepath, outfile)
117
118    def export_all(self, site, filepath=None):
[12861]119        """Export all applicants into filepath as CSV data.
[7914]120        If `filepath` is ``None``, a raw string with CSV data is returned.
[13216]121        Only used records are being exported.
[7914]122        """
123        catalog = queryUtility(
124            ICatalog, context=site, name='applicants_catalog', default=None)
125        if catalog is None:
126            return self.export([], filepath)
127        applicants = catalog.searchResults(
[7924]128            # reg_num might not be set and then would not be found.
129            # We therefore search for applicant_id.
130            applicant_id=(None, None))
[13949]131        used = [value for value in applicants
132                if value.container_code.endswith('+')]
[13216]133        return self.export(used, filepath=filepath)
[10653]134
135    def export_filtered(self, site, filepath=None, **kw):
[12861]136        """Export filtered applicants in container denoted by keywords (`kw`).
[10653]137        If `filepath` is ``None``, a raw string with CSV data should
[13216]138        be returned. Only used records are being exported.
[10653]139        """
[10654]140        container = grok.getSite()['applicants'][kw['container']]
[13216]141        container_values = container.values()
[13949]142        used = [value for value in container_values
143                if value.container_code.endswith('+')]
[13216]144        return self.export(used, filepath=filepath)
[13949]145
146
147class ApplicantPaymentExporter(grok.GlobalUtility, ExporterBase):
[16064]148    """The Applicant Payment Exporter exports all payments made by applicants.
[13949]149    In other words, it exports payment tickets in state 'paid'. The exporter
150    searches :class:`ApplicantsCatalog` and iterates over all payment tickets
151    which are stored in an applicant (container).
152
153    The exporter exports all applicant payments if started in the Data Center
154    which means in the context of the `DataCenter` object. The exporter can also
155    be started 'locally' which means in the context of an
156    `ApplicantsContainer` container, see `ApplicantExporter` above.
157    """
158    grok.implements(ICSVExporter)
159    grok.name('applicantpayments')
160
161    fields = tuple(sorted(iface_names(
162        IApplicantOnlinePayment,
163        exclude_attribs=False,
[16431]164        omit=['display_item', 'p_option']))) + (
[13952]165              'applicant_id',
166              'reg_number',
167              'display_fullname',)
[13949]168    title = _(u'Applicant Payments')
169
170    def mangle_value(self, value, name, context=None):
171        """The mangler determines the applicant's id.
172        """
[13952]173        if name in ('applicant_id', 'reg_number',
174            'display_fullname',) and context is not None:
[13949]175            applicant = context.__parent__
176            value = getattr(applicant, name, None)
177        return super(
178            ApplicantPaymentExporter, self).mangle_value(
179            value, name, context=context)
180
181    def export(self, payments, filepath=None):
182        """
183        """
184        writer, outfile = self.get_csv_writer(filepath)
185        for payment in payments:
186            self.write_item(payment, writer)
187        return self.close_outfile(filepath, outfile)
188
189    def export_all(self, site, filepath=None):
190        """
191        """
192        catalog = queryUtility(
193            ICatalog, context=site, name='applicants_catalog', default=None)
194        if catalog is None:
195            return self.export([], filepath)
196        applicants = catalog.searchResults(
197            # reg_num might not be set and then would not be found.
198            # We therefore search for applicant_id.
199            applicant_id=(None, None))
200        used = [value for value in applicants
201                if value.container_code.endswith('+')]
202        payments = []
203        for applicant in used:
[13968]204            for payment in applicant.payments:
[13949]205                if payment.p_state == 'paid':
206                    payments.append(payment)
207        return self.export(payments, filepath=filepath)
208
209    def export_filtered(self, site, filepath=None, **kw):
210        """
211        """
212        container = grok.getSite()['applicants'][kw['container']]
213        container_values = container.values()
214        used = [value for value in container_values
215                if value.container_code.endswith('+')]
216        payments = []
217        for applicant in used:
[13968]218            for payment in applicant.payments:
[13949]219                if payment.p_state == 'paid':
220                    payments.append(payment)
[16064]221        return self.export(payments, filepath=filepath)
222
223class ApplicantRefereeReportExporter(grok.GlobalUtility, ExporterBase):
224    """The Applicant Referee Report Exporter exports all referee reports.
225    The exportersearches :class:`ApplicantsCatalog` and iterates over all
226    referee reports which are stored in an applicant (container).
227
228    The exporter exports all referee reports if started in the Data Center
229    which means in the context of the `DataCenter` object. The exporter can also
230    be started 'locally' which means in the context of an
231    `ApplicantsContainer` container, see `ApplicantExporter` above.
232    """
233    grok.implements(ICSVExporter)
234    grok.name('applicantrefereereports')
235
236    fields = tuple(sorted(iface_names(
237        IApplicantRefereeReport,
[16066]238        exclude_attribs=False))) + (
[16064]239              'applicant_id',
240              'reg_number',
241              'display_fullname',)
242    title = _(u'Applicant Referee Reports')
243
244    def mangle_value(self, value, name, context=None):
245        """The mangler determines the applicant's id.
246        """
247        if name in ('applicant_id', 'reg_number',
248            'display_fullname',) and context is not None:
249            applicant = context.__parent__
250            value = getattr(applicant, name, None)
251        return super(
252            ApplicantRefereeReportExporter, self).mangle_value(
253            value, name, context=context)
254
[16065]255    def export(self, refereereports, filepath=None):
[16064]256        """
257        """
258        writer, outfile = self.get_csv_writer(filepath)
[16065]259        for refereereport in refereereports:
260            self.write_item(refereereport, writer)
[16064]261        return self.close_outfile(filepath, outfile)
262
263    def export_all(self, site, filepath=None):
264        """
265        """
266        catalog = queryUtility(
267            ICatalog, context=site, name='applicants_catalog', default=None)
268        if catalog is None:
269            return self.export([], filepath)
270        applicants = catalog.searchResults(
271            # reg_num might not be set and then would not be found.
272            # We therefore search for applicant_id.
273            applicant_id=(None, None))
274        refereereports = []
275        for applicant in applicants:
276            for refereereport in applicant.refereereports:
277                refereereports.append(refereereport)
[16069]278        return self.export(refereereports, filepath=filepath)
[16064]279
280    def export_filtered(self, site, filepath=None, **kw):
281        """
282        """
283        container = grok.getSite()['applicants'][kw['container']]
284        container_values = container.values()
285        refereereports = []
286        for applicant in container_values:
287            for refereereport in applicant.refereereports:
288                refereereports.append(refereereport)
289        return self.export(refereereports, filepath=filepath)
Note: See TracBrowser for help on using the repository browser.