source: main/waeup.kofa/trunk/src/waeup/kofa/students/export.py @ 9798

Last change on this file since 9798 was 9797, checked in by uli, 12 years ago

Local exports for departments.

  • Property svn:keywords set to Id
File size: 15.8 KB
Line 
1## $Id: export.py 9797 2012-12-13 15:39:31Z uli $
2##
3## Copyright (C) 2011 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 student related stuff.
19"""
20import grok
21from datetime import datetime
22from waeup.kofa.interfaces import MessageFactory as _
23from waeup.kofa.students.catalog import StudentsQuery
24from waeup.kofa.students.interfaces import (
25    IStudent, IStudentStudyCourse, IStudentStudyLevel, ICourseTicket,
26    IStudentOnlinePayment, ICSVStudentExporter, IBedTicket)
27from waeup.kofa.students.vocabularies import study_levels
28from waeup.kofa.utils.batching import ExporterBase
29from waeup.kofa.utils.helpers import iface_names
30
31#: A tuple containing all exporter names referring to students or
32#: subobjects thereof.
33EXPORTER_NAMES = ('students', 'studentstudycourses', 'studentstudylevels',
34                  'coursetickets', 'studentpayments')
35
36def ident(x):
37    return x
38    #for item in x:
39    #    yield item
40
41def get_students(site, stud_filter=StudentsQuery()):
42    """Get all students registered in catalog in `site`.
43    """
44    return stud_filter.query()
45
46def get_studycourses(students):
47    """Get studycourses of `students`.
48    """
49    return [x.get('studycourse', None) for x in students
50            if x is not None]
51
52def get_levels(students):
53    """Get all studylevels of `students`.
54    """
55    levels = []
56    for course in get_studycourses(students):
57        for level in course.values():
58            levels.append(level)
59    return levels
60
61def get_tickets(students):
62    """Get all course tickets of `students`.
63    """
64    tickets = []
65    for level in get_levels(students):
66        for ticket in level.values():
67            tickets.append(ticket)
68    return tickets
69
70def get_payments(students):
71    """Get all payments of `students`.
72    """
73    payments = []
74    for student in students:
75        for payment in student.get('payments', {}).values():
76            payments.append(payment)
77    return payments
78
79def get_bedtickets(students):
80    """Get all bedtickets of `students`.
81    """
82    tickets = []
83    for student in students:
84        for ticket in student.get('accommodation', {}).values():
85            tickets.append(ticket)
86    return tickets
87
88class StudentExporterBase(ExporterBase):
89    """Exporter for students or related objects.
90
91    This is a baseclass.
92    """
93    grok.baseclass()
94    grok.implements(ICSVStudentExporter)
95    grok.provides(ICSVStudentExporter)
96
97    def filter_func(self, x):
98        return get_students(x)
99
100    def get_filtered(self, site, current_session=None,
101                     current_level=None, faccode=None, depcode=None, ):
102        query = StudentsQuery(
103            current_session=current_session,
104            current_level=current_level,
105            faccode=faccode, depcode=depcode)
106        return query.query()
107
108    def export(self, values, filepath=None):
109        """Export `values`, an iterable, as CSV file.
110
111        If `filepath` is ``None``, a raw string with CSV data is returned.
112        """
113        writer, outfile = self.get_csv_writer(filepath)
114        for value in values:
115            self.write_item(value, writer)
116        return self.close_outfile(filepath, outfile)
117
118    def export_all(self, site, filepath=None):
119        """Export students into filepath as CSV data.
120
121        If `filepath` is ``None``, a raw string with CSV data is returned.
122        """
123        return self.export(self.filter_func(site), filepath)
124
125    def export_student(self, student, filepath=None):
126        return self.export(self.filter_func([student]), filepath=filepath)
127
128
129class StudentsExporter(grok.GlobalUtility, StudentExporterBase):
130    """Exporter for Students.
131    """
132    grok.name('students')
133
134    #: Fieldnames considered by this exporter
135    fields = tuple(sorted(iface_names(
136        IStudent, omit=['loggerInfo']))) + (
137        'password', 'state', 'history', 'certcode', 'is_postgrad',
138        'current_level', 'current_session')
139
140    #: The title under which this exporter will be displayed
141    title = _(u'Students')
142
143    def mangle_value(self, value, name, context=None):
144        if name == 'history':
145            value = value.messages
146        if name == 'phone' and value is not None:
147            # Append hash '#' to phone numbers to circumvent
148            # unwanted excel automatic
149            value = str('%s#' % value)
150        return super(
151            StudentsExporter, self).mangle_value(
152            value, name, context=context)
153
154    def export_all(self, site, filepath=None):
155        """Export students into filepath as CSV data.
156
157        If `filepath` is ``None``, a raw string with CSV data is returned.
158        """
159        return self.export(get_students(site), filepath)
160
161    def export_student(self, student, filepath=None):
162        return self.export([student], filepath=filepath)
163
164class StudentStudyCourseExporter(grok.GlobalUtility, StudentExporterBase):
165    """Exporter for StudentStudyCourses.
166    """
167    grok.name('studentstudycourses')
168
169    #: Fieldnames considered by this exporter
170    fields = tuple(sorted(iface_names(IStudentStudyCourse))) + ('student_id',)
171
172    #: The title under which this exporter will be displayed
173    title = _(u'Student Study Courses')
174
175    def filter_func(self, x):
176        return get_studycourses(x)
177
178    def mangle_value(self, value, name, context=None):
179        """Treat location values special.
180        """
181        if name == 'certificate' and value is not None:
182            # XXX: hopefully cert codes are unique site-wide
183            value = value.code
184        if name == 'student_id' and context is not None:
185            student = context.student
186            value = getattr(student, name, None)
187        return super(
188            StudentStudyCourseExporter, self).mangle_value(
189            value, name, context=context)
190
191    def export_all(self, site, filepath=None):
192        """Export study courses into filepath as CSV data.
193
194        If `filepath` is ``None``, a raw string with CSV data is returned.
195        """
196        return self.export(get_studycourses(get_students(site)), filepath)
197
198    def export_student(self, student, filepath=None):
199        """Export studycourse of a single student object.
200        """
201        return self.export(get_studycourses([student]), filepath)
202
203    def export_filtered(self, site, filepath=None, **kw):
204        """Export items denoted by `args` and `kw`.
205
206        If `filepath` is ``None``, a raw string with CSV data should
207        be returned.
208        """
209        data = self.get_filtered(site, **kw)
210        return self.export(get_studycourses(data), filepath=filepath)
211
212
213class StudentStudyLevelExporter(grok.GlobalUtility, StudentExporterBase):
214    """Exporter for StudentStudyLevels.
215    """
216    grok.name('studentstudylevels')
217
218    #: Fieldnames considered by this exporter
219    fields = tuple(sorted(iface_names(
220        IStudentStudyLevel) + ['level'])) + (
221        'student_id', 'number_of_tickets','certcode')
222
223    #: The title under which this exporter will be displayed
224    title = _(u'Student Study Levels')
225
226    def mangle_value(self, value, name, context=None):
227        """Treat location values special.
228        """
229        if name == 'student_id' and context is not None:
230            student = context.student
231            value = getattr(student, name, None)
232        return super(
233            StudentStudyLevelExporter, self).mangle_value(
234            value, name, context=context)
235
236    def export_all(self, site, filepath=None):
237        """Export study levels into filepath as CSV data.
238
239        If `filepath` is ``None``, a raw string with CSV data is returned.
240        """
241        return self.export(get_levels(get_students(site)), filepath)
242
243    def export_student(self, student, filepath=None):
244        return self.export(get_levels([student]), filepath)
245
246    def export_filtered(self, site, filepath=None, **kw):
247        """Export items denoted by `args` and `kw`.
248
249        If `filepath` is ``None``, a raw string with CSV data should
250        be returned.
251        """
252        data = self.get_filtered(site, **kw)
253        return self.export(get_levels(data), filepath=filepath)
254
255class CourseTicketExporter(grok.GlobalUtility, StudentExporterBase):
256    """Exporter for CourseTickets.
257    """
258    grok.name('coursetickets')
259
260    #: Fieldnames considered by this exporter
261    fields = tuple(sorted(iface_names(ICourseTicket) +
262        ['level', 'code'])) + ('student_id', 'certcode')
263
264    #: The title under which this exporter will be displayed
265    title = _(u'Course Tickets')
266
267    def mangle_value(self, value, name, context=None):
268        """Treat location values special.
269        """
270        if context is not None:
271            student = context.student
272            if name == 'student_id' and student is not None:
273                value = getattr(student, name, None)
274            if name == 'level':
275                value = getattr(context, 'getLevel', lambda: None)()
276        return super(
277            CourseTicketExporter, self).mangle_value(
278            value, name, context=context)
279
280    def export_all(self, site, filepath=None):
281        """Export course tickets into filepath as CSV data.
282
283        If `filepath` is ``None``, a raw string with CSV data is returned.
284        """
285        return self.export(get_tickets(get_students(site)), filepath)
286
287    def export_student(self, student, filepath=None):
288        return self.export(get_tickets([student]), filepath)
289
290    def export_filtered(self, site, filepath=None, **kw):
291        """Export items denoted by `args` and `kw`.
292
293        If `filepath` is ``None``, a raw string with CSV data should
294        be returned.
295        """
296        data = self.get_filtered(site, **kw)
297        return self.export(get_tickets(data), filepath=filepath)
298
299
300class PaymentsExporter(grok.GlobalUtility, StudentExporterBase):
301    """Exporter for OnlinePayment instances.
302    """
303    grok.name('studentpayments')
304
305    #: Fieldnames considered by this exporter
306    fields = tuple(
307        sorted(iface_names(
308            IStudentOnlinePayment, exclude_attribs=False))) + (
309                'student_id','student_state','current_session')
310
311    #: The title under which this exporter will be displayed
312    title = _(u'Student Payments')
313
314    def mangle_value(self, value, name, context=None):
315        """Treat location values special.
316        """
317        if context is not None:
318            student = context.student
319            if name in ['student_id'] and student is not None:
320                value = getattr(student, name, None)
321        return super(
322            PaymentsExporter, self).mangle_value(
323            value, name, context=context)
324
325    def export_all(self, site, filepath=None):
326        """Export payments into filepath as CSV data.
327
328        If `filepath` is ``None``, a raw string with CSV data is returned.
329        """
330        return self.export(get_payments(get_students(site)), filepath)
331
332    def export_student(self, student, filepath=None):
333        return self.export(get_payments([student]), filepath)
334
335    def export_filtered(self, site, filepath=None, **kw):
336        """Export items denoted by `args` and `kw`.
337
338        If `filepath` is ``None``, a raw string with CSV data should
339        be returned.
340        """
341        data = self.get_filtered(site, **kw)
342        return self.export(get_payments(data), filepath=filepath)
343
344class BedTicketsExporter(grok.GlobalUtility, StudentExporterBase):
345    """Exporter for BedTicket instances.
346    """
347    grok.name('bedtickets')
348
349    #: Fieldnames considered by this exporter
350    fields = tuple(
351        sorted(iface_names(
352            IBedTicket, exclude_attribs=False))) + (
353                'student_id', 'actual_bed_type')
354
355    #: The title under which this exporter will be displayed
356    title = _(u'Bed Tickets')
357
358    def mangle_value(self, value, name, context=None):
359        """Treat location values and others special.
360        """
361        if context is not None:
362            student = context.student
363            if name in ['student_id'] and student is not None:
364                value = getattr(student, name, None)
365        if name == 'bed' and value is not None:
366            value = getattr(value, 'bed_id', None)
367        if name == 'actual_bed_type':
368            value = getattr(getattr(context, 'bed', None), 'bed_type')
369        return super(
370            BedTicketsExporter, self).mangle_value(
371            value, name, context=context)
372
373    def export_all(self, site, filepath=None):
374        """Export payments into filepath as CSV data.
375
376        If `filepath` is ``None``, a raw string with CSV data is returned.
377        """
378        return self.export(get_bedtickets(get_students(site)), filepath)
379
380    def export_student(self, student, filepath=None):
381        return self.export(get_bedtickets([student]), filepath)
382
383    def export_filtered(self, site, filepath=None, **kw):
384        """Export items denoted by `args` and `kw`.
385
386        If `filepath` is ``None``, a raw string with CSV data should
387        be returned.
388        """
389        data = self.get_filtered(site, **kw)
390        return self.export(get_bedtickets(data), filepath=filepath)
391
392class StudentPaymentsOverviewExporter(StudentsExporter):
393    """Exporter for students with payment overview.
394    """
395    grok.name('paymentsoverview')
396
397    curr_year = datetime.now().year
398    year_range = range(curr_year - 9, curr_year + 1)
399    year_range_tuple = tuple([str(year) for year in year_range])
400
401    #: Fieldnames considered by this exporter
402    fields = ('student_id', ) + (
403        'state', 'certcode', 'faccode', 'depcode', 'is_postgrad',
404        'current_level', 'current_session',
405        ) + year_range_tuple
406
407    #: The title under which this exporter will be displayed
408    title = _(u'Student Payments Overview')
409
410    def mangle_value(self, value, name, context=None):
411        if name in self.year_range_tuple and context is not None:
412            value = ''
413            for ticket in context['payments'].values():
414                if ticket.p_state == 'paid' and \
415                    ticket.p_category == 'schoolfee' and \
416                    ticket.p_session == int(name):
417                    value = ticket.amount_auth
418                    break
419        return super(
420            StudentsExporter, self).mangle_value(
421            value, name, context=context)
422
423class StudentStudyLevelsOverviewExporter(StudentsExporter):
424    """Exporter for students with study level overview.
425    """
426    grok.name('studylevelsoverview')
427
428    avail_levels = tuple([str(x) for x in study_levels(None)])
429
430    #: Fieldnames considered by this exporter
431    fields = ('student_id', ) + (
432        'state', 'certcode', 'faccode', 'depcode', 'is_postgrad',
433        'entry_session', 'current_level', 'current_session',
434        ) + avail_levels
435
436    #: The title under which this exporter will be displayed
437    title = _(u'Student Study Levels Overview')
438
439    def mangle_value(self, value, name, context=None):
440        if name in self.avail_levels and context is not None:
441            value = ''
442            for level in context['studycourse'].values():
443                if level.level == int(name):
444                    #value = '%s|%s|%s|%s' % (
445                    #    level.level_session,
446                    #    len(level),
447                    #    level.validated_by,
448                    #    level.level_verdict)
449                    value = '%s' % level.level_session
450                    break
451        return super(
452            StudentsExporter, self).mangle_value(
453            value, name, context=context)
Note: See TracBrowser for help on using the repository browser.