Beispiel #1
0
def tSheets(schoolyear, manager, date):
    courses = CourseTables(schoolyear)
    tidmap = {}
    for k in courses.classes():
        klass = Klass(k)
        sid2tids = courses.filterText(klass)
        for sid, tids in sid2tids.items():
            if tids.TEXT:
                if not tids:
                    tids = [_nn]
                for tid in tids:
                    try:
                        tmap = tidmap[tid]
                    except:
                        tidmap[tid] = {klass.klass: {sid}}
                        continue
                    try:
                        tmap[klass.klass].add(sid)
                    except:
                        tmap[klass.klass] = {sid}

    noreports = []
    teachers = []
    for tid in courses.teacherData:
        lines = []
        tname = courses.teacherData.getTeacherName(tid)
        try:
            tmap = tidmap[tid]
        except:
            noreports.append(tname)
            continue
        for k in sorted(tmap):
            for sid in tmap[k]:
                sname = courses.subjectName(sid)
                lines.append((k, sname))
        teachers.append((tname, lines))

    tpdir = Paths.getUserPath('DIR_TEXT_REPORT_TEMPLATES')
    templateLoader = jinja2.FileSystemLoader(searchpath=tpdir)
    templateEnv = jinja2.Environment(loader=templateLoader, autoescape=True)
    tpfile = 'summary-teachers.html'
    try:
        template = templateEnv.get_template(tpfile)
    except:
        REPORT.Fail(_NOTEMPLATE, path=os.path.join(tpdir, tpfile))
    source = template.render(year=printSchoolYear(schoolyear),
                             manager=manager,
                             date=Dates.dateConv(date),
                             teachers=teachers,
                             noreports=noreports)
    html = HTML(string=source)
    pdfBytes = html.write_pdf()
    return pdfBytes
Beispiel #2
0
def choiceTable(schoolyear, klass):
    """Build a subject choice table for the given school-class.
    <klass> is a <Klass> instance.
     """
    template = Paths.getUserPath('FILE_SUBJECT_CHOICE_TEMPLATE')
    table = KlassMatrix(template)
    # Title already set in template:
    #table.setTitle("Kurswahl")

    # "Translation" of info items:
    kmap = CONF.TABLES.COURSE_PUPIL_FIELDNAMES
    info = (
        (kmap['SCHOOLYEAR'], str(schoolyear)),
        (kmap['CLASS'], klass.klass),
    )
    table.setInfo(info)

    ### Manage subjects
    courses = CourseTables(schoolyear)
    sid2tlist = courses.classSubjects(klass)
    # <table.headers> is a list of cell values in the header row.
    rsid = table.rowindex - 1       # row tag for sid
    rsname = table.rowindex         # row tag for subject name
    # Go through the template columns and check if they are needed:
    for sid in sid2tlist:
        if sid[0] != '_':
            sname = courses.subjectName(sid)
            # Add subject
            col = table.nextcol()
            table.write(rsid, col, sid)
            table.write(rsname, col, sname)
    # Delete excess columns
    table.delEndCols(col + 1)

    ### Add pupils
    pupils = Pupils(schoolyear)
    for pdata in pupils.classPupils(klass):
        row = table.nextrow()
        table.write(row, 0, pdata['PID'])
        table.write(row, 1, pdata.name())
        table.write(row, 2, pdata['STREAM'])
    # Delete excess rows
    table.delEndRows(row + 1)

    ### Save file
    table.protectSheet()
    return table.save()
Beispiel #3
0
def ksSheets(schoolyear, manager, date):
    courses = CourseTables(schoolyear)
    tidmap = {
        tid: courses.teacherData.getTeacherName(tid)
        for tid in courses.teacherData
    }

    klasses = []
    for k in courses.classes():
        klass = Klass(k)
        sidmap = {}
        sid2tids = courses.filterText(klass)
        for sid, tids in sid2tids.items():
            if tids.TEXT:
                if not tids:
                    tids = [_nn]
                for tid in tids:
                    try:
                        sidmap[sid].add(tid)
                    except:
                        sidmap[sid] = {tid}
        lines = []
        for sid, tids in sidmap.items():
            sname = courses.subjectName(sid)
            for tid in tids:
                lines.append((sname, tidmap[tid]))
        klasses.append((klass.klass, lines))

    tpdir = Paths.getUserPath('DIR_TEXT_REPORT_TEMPLATES')
    templateLoader = jinja2.FileSystemLoader(searchpath=tpdir)
    templateEnv = jinja2.Environment(loader=templateLoader, autoescape=True)
    tpfile = 'summary-classes.html'
    try:
        template = templateEnv.get_template(tpfile)
    except:
        REPORT.Fail(_NOTEMPLATE, path=os.path.join(tpdir, tpfile))
    source = template.render(year=printSchoolYear(schoolyear),
                             manager=manager,
                             date=Dates.dateConv(date),
                             klasses=klasses)
    html = HTML(string=source)
    pdfBytes = html.write_pdf()
    return pdfBytes
Beispiel #4
0
def stripTable(schoolyear, term, klass, title):
    """Build a basic pupil/subject table for entering grades.
    <klass> is a <Klass> instance.
    <term> is a string.
     """
    # Info concerning grade tables:
    gtinfo = CONF.GRADES.GRADE_TABLE_INFO

    ### Determine table template (output)
    t = klass.match_map(gtinfo.GRADE_INPUT_TEMPLATE)
    if not t:
        REPORT.Fail(_NO_ITEMPLATE, ks=klass)
    template = Paths.getUserPath('FILE_GRADE_TABLE_TEMPLATE').replace('*', t)
    table = KlassMatrix(template)
    table.setTitle(title)
    table.setInfo([])

    ### Read input table template (for determining subjects and order)
    # Determine table template (input)
    t = klass.match_map(gtinfo.GRADE_TABLE_TEMPLATE)
    if not t:
        REPORT.Fail(_NO_TEMPLATE, ks=klass)
    template0 = Paths.getUserPath('FILE_GRADE_TABLE_TEMPLATE').replace('*', t)
    table0 = KlassMatrix(template0)
    i, x = 0, 0
    for row0 in table0.rows:
        i += 1
        if row0[0] and row0[0] != '#':
            # The subject key line
            break
    # <row0> is the title row.

    ### Manage subjects
    courses = CourseTables(schoolyear)
    sid2tlist = courses.classSubjects(klass)
#    print ("???1", list(sid2tlist))
    # Set klass cell
    rowix = table.rowindex - 1
    table.write(rowix, 0, table.headers[0].replace('*', klass.klass))
    # Go through the template columns and check if they are needed:
    col = 0
    for sid in row0:
        if sid and sid[0] != '_' and sid in sid2tlist:
            sname = courses.subjectName(sid)
            # Add subject
            col = table.nextcol()
            table.write(rowix, col, sname)
    # Delete excess columns
    table.delEndCols(col + 1)

    ### Add pupils
    pupils = Pupils(schoolyear)
    for pdata in pupils.classPupils(klass):
        row = table.nextrow()
        table.write(row, 0, pdata.name())
        table.write(row, 1, pdata['STREAM'])
    # Delete excess rows
    table.delEndRows(row + 1)

    ### Save file
    table.protectSheet()
    return table.save()
Beispiel #5
0
class GradeReportData:
    """Manage data connected with a school-class, stream and report type.
    When referring to old report data, bear in mind that a pupil's stream,
    or even school-class, may have changed. The grade data includes the
    class and stream associated with the data.
    """
    def __init__(self, schoolyear, rtype, klass):
        """<rtype> is the report type, a key to the mapping
        GRADE.REPORT_TEMPLATES.
        <klass> is a <Klass> object, which may include stream tags.
        All streams passed in must map to the same template.
        """
        self.schoolyear = schoolyear
        self.klassdata = klass

        ### Set up categorized, ordered lists of grade fields for insertion
        ### in a report template.
        # If there is a list of streams in <klass> this will probably
        # only match '*' in the template mapping:
        self.template = getGradeTemplate(rtype, klass)
        self.alltags = getTemplateTags(self.template)
        # Extract grade-entry tags, i.e. those matching <str>_<int>:
        gtags = {}      # {subject group -> [(unsorted) index<int>, ...]}
        for tag in self.alltags:
            try:
                _group, index = tag.split('_')
                group = _group.split('.')[-1]
                i = int(index)
            except:
                continue
            try:
                gtags[group].append(i)
            except:
                gtags[group] = [i]
        # Build a sorted mapping of index lists:
        #   {subject group -> [(reverse sorted) index<int>, ...]}
        # The reversal is for popping in correct order.
        self.sgroup2indexes = {group: sorted(gtags[group], reverse=True)
                for group in gtags}
#        print("\n??? self.alltags", self.alltags)
#        print("\n??? self.sgroup2indexes", self.sgroup2indexes)

        ### Sort the subject tags into ordered groups
        self.courses = CourseTables(schoolyear)
        subjects = self.courses.filterGrades(klass)
        # Build a mapping: {subject group -> [(ordered) sid, ...]}
        self.sgroup2sids = {}
        for group in self.sgroup2indexes:
            sidlist = []
            self.sgroup2sids[group] = sidlist
            # CONF.GRADES.ORDERING: {subject group -> [(ordered) sid, ...]}
            for sid in CONF.GRADES.ORDERING[group]:
                # Include only sids relevant for the klass.
                try:
                    del(subjects[sid])
                    sidlist.append(sid)
                except:
                    pass
        # Entries remaining in <subjects> are not covered in ORDERING.
        for sid in subjects:
            REPORT.Error(_UNGROUPED_SID, sid=sid, tfile=self.template.filename)


    def getTagmap(self, grades, pname, grademap='GRADES'):
        """Prepare tag mapping for substitution in the report template,
        for the pupil <pname>.
        <grades> is a mapping {sid -> grade}, or something similar which
        can be handled by <dict(grades)>.
        <grademap> is the name of a configuration file (in 'GRADES')
        providing a grade -> text mapping.
        Grouped subjects expected by the template get two entries:
        one for the subject name and one for the grade. They are allocated
        according to the numbered slots defined for the predefined ordering
        (config: GRADES/ORDERING).
        "Grade" entries whose tag begins with '_' and which are not covered
        by the data in GRADES/ORDERING are copied directly to the output
        mapping.
        Return a mapping {template tag -> replacement text}.
        """
        tagmap = {}                     # for the result
        g2text = CONF.GRADES[grademap]  # grade -> text representation
        # Copy the grade mapping, because it will be modified to keep
        # track of unused grade entries:
        gmap = dict(grades)     # this accepts a variety of input types
        for group, sidlist in self.sgroup2sids.items():
            # Copy the indexes because the list is modified here (<pop()>)
            indexes = self.sgroup2indexes[group].copy()
            for sid in sidlist:
                try:
                    g = gmap.pop(sid)
                except:
                    REPORT.Error(_MISSING_GRADE, pname=pname, sid=sid)
                    g = '?'
                if g == _INVALID:
                    continue
                try:
                    i = indexes.pop()
                except:
                    REPORT.Fail(_TOO_MANY_SUBJECTS, group=group,
                            pname=pname, sids=repr(sidlist),
                            template=self.template.filename)
                sname = self.courses.subjectName(sid).split('|')[0].rstrip()
                tagmap["%s_%d_N" % (group, i)] = sname
                g1 = g2text.get(g)
                if not g1:
                    REPORT.Error(_NO_MAPPED_GRADE, grade=g)
                    g1 = '?'
                tagmap["%s_%d" % (group, i)] = g1
            # Process superfluous indexes
            for i in indexes:
                tagmap["%s_%d_N" % (group, i)] = g2text.NONE
                tagmap["%s_%d" % (group, i)] = g2text.NONE
        # Report unused grade entries
        unused = []
        for sid, g in gmap.items():
            if g == _INVALID:
                continue
            if sid[0] == '_':
                tagmap[sid] = g
            else:
                unused.append("%s: %s" % (sid, g))
        if unused:
            REPORT.Error(_UNUSED_GRADES, pname=pname, grades="; ".join(unused))
        return tagmap