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

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

Oh, students passed the same course twice.

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