source: main/waeup.aaue/trunk/src/waeup/aaue/students/export.py @ 17673

Last change on this file since 17673 was 16916, checked in by Henrik Bettermann, 3 years ago

Remove passed tickets too.

  • Property svn:keywords set to Id
File size: 12.1 KB
RevLine 
[11546]1## $Id: export.py 16916 2022-04-09 19:33:01Z henrik $
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"""
[14593]20import grok
[16865]21from copy import deepcopy
[16859]22from zope.component import getUtility, createObject
[13569]23from waeup.kofa.utils.batching import ExporterBase
[13768]24from waeup.kofa.utils.helpers import iface_names
[14593]25from waeup.kofa.interfaces import IKofaUtils
26from waeup.kofa.students.export import (get_levels,
[15452]27    DataForLecturerExporter, StudentExporterBase,
28    SchoolFeePaymentsOverviewExporter, StudentExporter)
[11546]29from waeup.aaue.students.interfaces import (
30    ICustomStudent, ICustomStudentStudyCourse,
31    ICustomStudentStudyLevel,
32    ICustomCourseTicket,
33    ICustomStudentOnlinePayment)
34from kofacustom.nigeria.students.export import (
[12081]35    NigeriaStudentExporter, NigeriaStudentStudyCourseExporter,
[11546]36    NigeriaStudentStudyLevelExporter,
[12876]37    NigeriaCourseTicketExporter, NigeriaStudentPaymentExporter)
[11546]38
[13768]39
[16859]40def get_tickets_for_ict(students, previous=0, **kw):
41    """
42    """
[16865]43    tickets = list()
[16859]44    #code = kw.get('code', None)
45    level = kw.get('level', None)
46    session = kw.get('session', None)
47    ct_level = kw.get('ct_level', None)
48    ct_session = kw.get('ct_session', None)
49    ct_semester = kw.get('ct_semester', None)
50    for level_obj in get_levels(students, previous, **kw):
[16903]51        allticketcodes = list()
[16859]52        for ticket in level_obj.values():
53            if ct_level not in ('all', None):
54                if level_obj.level in (10, 999, 1000, None)  \
55                    and int(ct_level) != level_obj.level:
56                    continue
57                if level_obj.level not in range(
58                    int(ct_level), int(ct_level)+100, 10):
59                    continue
60            if ct_session not in ('all', None) and \
61                int(ct_session) != level_obj.level_session:
62                continue
63            if ct_semester not in ('all', None) and \
64                int(ct_semester) != ticket.semester:
65                continue
66            if ticket.total_score is not None:
67                if ticket.total_score < ticket.passmark:
68                    remark = 'failed'
69                else:
70                    remark = 'passed'
71            else:
72                remark = 'nottaken'
73            ticket.remark = remark
[16914]74            ticket.stdnt = level_obj.student
[16859]75            tickets.append(ticket)
76            allticketcodes.append(ticket.code)
77        # collect missed tickets for each study level
78        certificate = getattr(
79            level_obj.student.get('studycourse', None), 'certificate', None)
80        if certificate:
81            for certcourse in certificate.values():
82                if certcourse.level != level_obj.level:
83                    continue
84                if certcourse.getCourseCode() not in allticketcodes:
85                    ticket = createObject(u'waeup.CourseTicket')
86                    ticket.code = certcourse.getCourseCode()
87                    ticket.remark = 'missed'
88                    ticket.course_category = certcourse.course_category
89                    ticket.stdnt = level_obj.student
90                    tickets.append(ticket)
[16865]91    # Remove failed or missed tickets if they have been passed later
92    obsolete = list()
[16914]93    for student in students:
94        all_tickets = [i for i in tickets if student == i.stdnt]
95        passed_tickets = [i for i in all_tickets if i.remark == 'passed']
96        for passed_ticket in passed_tickets:
97            for ticket in all_tickets:
[16916]98                 if ticket.code == passed_ticket.code: # remove passed ticket too
[16914]99                    obsolete.append(ticket)
[16904]100    for ticket in set(obsolete):
[16865]101        tickets.remove(ticket)
[16859]102    return tickets
103
[12081]104class CustomStudentExporter(NigeriaStudentExporter):
[11546]105    """Exporter for Students.
106    """
107
108    fields = tuple(sorted(iface_names(
109        ICustomStudent, omit=['loggerInfo']))) + (
110        'password', 'state', 'history', 'certcode', 'is_postgrad',
111        'current_level', 'current_session')
112
113class CustomStudentStudyCourseExporter(NigeriaStudentStudyCourseExporter):
114    """Exporter for StudentStudyCourses.
115    """
116
117    fields = tuple(
[14622]118        sorted(iface_names(ICustomStudentStudyCourse))) + (
119            'matric_number', 'state', 'student_id',)
[11546]120
[14622]121    def mangle_value(self, value, name, context=None):
122        if name == 'certificate' and value is not None:
123            # XXX: hopefully cert codes are unique site-wide
124            value = value.code
125        if name in ('student_id', 'matric_number', 'state') and context is not None:
126            student = context.student
127            value = getattr(student, name, None)
128        return ExporterBase().mangle_value(value, name, context=context)
129
[11546]130class CustomCourseTicketExporter(NigeriaCourseTicketExporter):
131    """Exporter for CourseTickets.
132    """
133
134    fields = tuple(sorted(iface_names(ICustomCourseTicket) +
135        ['level', 'code', 'level_session'])) + ('student_id',
[16039]136        'certcode', 'display_fullname', 'matric_number', 'state', 'grade',
[16859]137        'total_score', 'total_credits', 'previous')
[11546]138
[13569]139    def mangle_value(self, value, name, context=None):
140        """The mangler determines the student's id and fullname.
141        """
[16859]142        if name == 'previous':
143            return self.previous
[13569]144        if context is not None:
145            student = context.student
[15336]146            if name in ('student_id', 'display_fullname', 'matric_number', 'state') \
[13569]147                and student is not None:
148                value = getattr(student, name, None)
[16617]149            if name == 'total_credits':
150                value = context.__parent__.total_credits
[13569]151        return ExporterBase().mangle_value(value, name, context=context)
152
[11546]153class CustomStudentStudyLevelExporter(NigeriaStudentStudyLevelExporter):
154    """Exporter for StudentStudyLevels.
155    """
156    #: Fieldnames considered by this exporter
157    fields = tuple(sorted(iface_names(
[12876]158        ICustomStudentStudyLevel))) + (
[14442]159        'student_id', 'matric_number', 'number_of_tickets','certcode', 'cgpa')
[11546]160
[14436]161    def mangle_value(self, value, name, context=None):
162        """The mangler determines the student id, nothing else.
163        """
164        if name in ('student_id', 'matric_number') and context is not None:
165            student = context.student
166            value = getattr(student, name, None)
[14442]167        elif name == 'cgpa':
168            value = context.cumulative_params[0]
[14436]169        return super(
170            CustomStudentStudyLevelExporter, self).mangle_value(
171            value, name, context=context)
172
[12876]173class CustomStudentPaymentExporter(NigeriaStudentPaymentExporter):
[11546]174    """Exporter for OnlinePayment instances.
175    """
176
177    fields = tuple(
178        sorted(iface_names(
179            ICustomStudentOnlinePayment, exclude_attribs=False,
[15471]180            omit=['display_item','formatted_p_date']))) + (
[11546]181            'student_id','state','current_session')
182
[13768]183class CustomDataForLecturerExporter(DataForLecturerExporter):
184    """
185    """
186
[14360]187    fields = ('matric_number', 'student_id','display_fullname',
[14701]188              'depcode', 'faccode',
189              'level', 'code', 'level_session', 'ca', 'score',
[15414]190              'total_score', 'grade', 'imported_ts')
[13768]191
[14701]192    def mangle_value(self, value, name, context=None):
193        """The mangler determines the student's id and fullname.
194        """
195        if context is not None:
196            student = context.student
197            if name in ('matric_number',
198                        'reg_number',
199                        'student_id',
200                        'display_fullname',
201                        'depcode',
202                        'faccode') and student is not None:
203                value = getattr(student, name, None)
204        return super(
205            DataForLecturerExporter, self).mangle_value(
206            value, name, context=context)
207
[14593]208class LevelReportDataExporter(grok.GlobalUtility, StudentExporterBase):
209    """
210    """
211    grok.name('levelreportdata')
212
[14595]213    fields = ('matric_number', 'display_fullname','level','level_session',
[14593]214        'credits_counted', 'credits_passed','level_gpa',
215        'failed_courses','not_taken_courses','cum_credits_taken',
216        'cum_credits_passed','cgpa','remark')
217    title = u'Summary of Result Data'
218
219    def filter_func(self, x, **kw):
[16038]220        return get_levels(x, **kw)
[14593]221
222    def mangle_value(self, value, name, context=None):
223        """The mangler determines the student id, nothing else.
224        """
225        if context is not None:
226            student = context.student
227            format_float = getUtility(IKofaUtils).format_float
228            if name in ('matric_number',
229                        'display_fullname',) and student is not None:
230                value = getattr(student, name, None)
231            elif name == 'credits_counted':
232                value = context.gpa_params[1]
233            elif name == 'credits_passed':
234                value = context.passed_params[2]
235            elif name == 'level_gpa':
236                value = format_float(context.gpa_params[0], 3)
237            elif name == 'failed_courses':
238                value = context.passed_params[4]
239            elif name == 'not_taken_courses':
240                value = context.passed_params[5]
241            elif name == 'cum_credits_taken':
242                value = context.cumulative_params[1]
243            elif name == 'cum_credits_passed':
244                value = context.cumulative_params[4]
245            elif name == 'cgpa':
246                value = format_float(context.cumulative_params[0], 3)
247            elif name == 'remark':
248                value = getattr(context, 'remark', '')
249        return super(
250            LevelReportDataExporter, self).mangle_value(
251            value, name, context=context)
252
[15452]253class CustomSchoolFeePaymentsOverviewExporter(SchoolFeePaymentsOverviewExporter):
254    """
255    """
256
257    def mangle_value(self, value, name, context=None):
258        """
259        """
260        if name in self.year_range_tuple and context is not None:
261            value = 0
262            for ticket in context['payments'].values():
263                if ticket.p_category in (
264                    'schoolfee',
265                    'schoolfee_1',
266                    'schoolfee_2',
267                    'schoolfee_incl',) and \
268                    ticket.p_session == int(name):
269                    if ticket.p_state == 'waived':
270                        value = 'waived'
271                        break
272                    if ticket.p_state == 'paid':
273                        try:
274                            value += ticket.amount_auth
275                        except TypeError:
276                            pass
277            if value == 0:
278                value = ''
279            elif isinstance(value, float):
280                value = round(value, 2)
281        return super(
282            StudentExporter, self).mangle_value(
283            value, name, context=context)
[16859]284
285class OutstandingCourses2Exporter(grok.GlobalUtility, StudentExporterBase):
286    """
287    """
288    grok.name('outstandingcourses_2')
289
290    title = u'Outstanding Courses V2'
291
292    fields = ('student_id', 'matric_number', 'certcode', 'display_fullname',
293              'code', 'course_category', 'remark')
294
295    def filter_func(self, x, **kw):
296        return get_tickets_for_ict(x, **kw)
297
298    def mangle_value(self, value, name, context=None):
299        """The mangler determines the student's id and fullname.
300        """
301        if context is not None:
302            student = context.student
303            if not student:
304                student = getattr(context, 'stdnt', None)
305            if name in ('student_id', 'display_fullname', 'matric_number',
306                'certcode') and student is not None:
307                value = getattr(student, name, None)
308        return ExporterBase().mangle_value(value, name, context=context)
Note: See TracBrowser for help on using the repository browser.