Exemple #1
0
def makeAbiReports (schoolyear, klass):
    """Build abitur grade reports using the grade tables defined by the
    configuration path FILE_ABITABLE.
    A template is used to construct the report files.
    The results – odt files – are placed according to the configuration
    path FILE_ABIREPORT, first removing any existing files in this folder.
    odt files are created from a template.
    Return a tuple: the output folder and a list of odt-file-names
    (without folder path).
    """
    sheetname = CONF.TABLES.ABITUR_RESULTS.GRADE_TABLE_SHEET
    infile = Paths.getYearPath (schoolyear, 'FILE_ABITABLE', klass=klass)
    filepath = Paths.getYearPath (schoolyear, 'FILE_ABIREPORT',
            klass=klass, make=-1)
    outdir = os.path.dirname (filepath)
    if os.path.isdir (outdir):
        shutil.rmtree (outdir)
    files = []
    for f in sorted (glob (infile)):
        # Extract pupil info from file-name
        try:
            _, index, pid, pname = f.rsplit ('.', 1) [0].rsplit ('-', 3)
        except:
            continue
        data = readTableData (f, table=sheetname)
        ofile = filepath.replace ('*', '{pnum}-{pid}-{name}'.format (
                pnum=index, pid=pid, name=pname))
        files.append (os.path.basename (makeAbiReport (ofile, data)))
    REPORT.Info (_MADENREPORTS, klass=klass, n=len (files), folder=outdir)
    return outdir, files
Exemple #2
0
def test_01():
    filepath = Paths.getYearPath(_year, 'FILE_SP_TEACHERS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_CLASSES')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_SUBJECTS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
    filepath = Paths.getYearPath(_year, 'FILE_SP_LESSONS')
    REPORT.Test("\n  --------------\n%s" % repr(readSPTable(filepath)))
Exemple #3
0
def importLatestRaw(schoolyear):
    allfiles = glob(Paths.getYearPath(schoolyear, 'FILE_PUPILS_RAW'))
    fpath = sorted(allfiles)[-1]
    REPORT.Info(_IMPORT_FROM, path=fpath)
    rpd = readRawPupils(schoolyear, fpath)
    updateFromRaw(schoolyear, rpd)
    return rpd
Exemple #4
0
def test_02():
    pdfBytes = makeSheets(_year, _date, Klass(_klass))
    folder = Paths.getUserPath('DIR_TEXT_REPORT_TEMPLATES')
    fpath = os.path.join(folder, 'test.pdf')
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Test(" --> %s" % fpath)
Exemple #5
0
def test_01 ():
    _term = '1'
    _date = '2016-01-29'
    for _klass, _pid in ('13', '200301'), ('12.RS', '200403'):
        klass = Klass(_klass)
        REPORT.Test("Reading basic grade data for class %s" % klass)
#TODO: This might not be the optimal location for this file.
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_TABLE',
                    term=_term).replace('*', str(klass).replace('.', '-'))
        pgrades = readGradeTable(filepath)
        REPORT.Test(" ++ INFO: %s" % repr(pgrades.info))
        for pid, grades in pgrades.items():
            REPORT.Test("\n  -- %s: %s\n" % (pid, repr(grades)))

        REPORT.Test("\nReading template data for class %s" % klass)

        # Get the report type from the term and klass/stream
        _rtype = klass.match_map(CONF.GRADES.REPORT_TEMPLATES['_' + _term])
        gradedata = GradeReportData(_testyear, _rtype, klass)
        REPORT.Test("  Indexes:\n  %s" % repr(gradedata.sgroup2indexes))
        REPORT.Test("  Grade tags:\n  %s" % repr(gradedata.sgroup2sids))

        grademap = klass.match_map(CONF.MISC.GRADE_SCALE)
        REPORT.Test("\nTemplate grade map for pupil %s (using %s)" %
                (_pid, grademap))
        tagmap = gradedata.getTagmap(pgrades[_pid], "Pupil_%s" % _pid, grademap)
        REPORT.Test("  Grade tags:\n  %s" % repr(tagmap))
Exemple #6
0
def makeAbiReport (outpath, pdata):
    """Build an Abitur grade report for a pupil.
    The necessary information is supplied in the mapping <pdata>:
        {key: value}.
    The keys are user-fields in the document template (odt), the values
    are the strings to be inserted.
    The resulting file is placed at <outpath>, creating leading folders
    if necessary. <outpath> need not end in '.odt', if not present it
    will be added automatically.
    """
    NOTCHOSEN = CONF.FORMATTING.NOTCHOSEN

    ## Get template path
    template = Paths.getUserPath ('FILE_ABITUR_REPORT_TEMPLATE')
#    fieldnames = OdtUserFields.listUserFields (template)

    ## Convert the dates.
    for f in pdata:
        d = pdata [f]
        if f.endswith ('_D'):
#            print ("???", f, d)
            if d:
                pdata [f] = Dates.dateConv (d)
        # Substitute non-date empty cells
        elif not d:
            pdata [f] = NOTCHOSEN

    folder = os.path.dirname (outpath)
    if not os.path.isdir (folder):
        os.makedirs (folder)
    ofile, used, missing = OdtUserFields.fillUserFields (
            template, outpath, pdata)
    REPORT.Info (_ABIREPORTDONE, path=ofile)
    return ofile
Exemple #7
0
def test_02():
    _term = '2'
    for ks in '10', '11.Gym', '11.RS-HS-_', '12.RS-HS', '12.Gym', '13':
        klass = Klass(ks)
        bytefile = makeGradeTable(_testyear, _term, klass, "Noten: 1. Halbjahr")
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_FULL', make=-1,
                term=_term).replace('*', str(klass).replace('.', '-')) + '.xlsx'
        with open(filepath, 'wb') as fh:
            fh.write(bytefile)
        REPORT.Test(" --> %s" % filepath)
        bytefile = stripTable(_testyear, _term, klass, "Noten: 1. Halbjahr")
        filepath = Paths.getYearPath(_testyear, 'FILE_GRADE_INPUT', make=-1,
                term=_term).replace('*', str(klass).replace('.', '-')) + '.xlsx'
        with open(filepath, 'wb') as fh:
            fh.write(bytefile)
        REPORT.Test(" --> %s" % filepath)
Exemple #8
0
def test_05():
    _klass_stream = Klass('11')
    pdfBytes = makeReports(_year, _term, _klass_stream, _date)
    folder = Paths.getUserPath('DIR_GRADE_REPORT_TEMPLATES')
    fpath = os.path.join(folder, 'test_%s_%s.pdf' % (_klass_stream, _date))
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
Exemple #9
0
def test_02():
    from glob import glob
    files = glob(Paths.getYearPath(_testyear, 'FILE_GRADE_TABLE',
                term='*'))
    for filepath in files:
        pgrades = readGradeTable(filepath)
        grades2db(_testyear, pgrades)
Exemple #10
0
def test_01():
    pdfBytes = tSheets(_year, _manager, _date)
    fpath = Paths.getYearPath(_year, 'FILE_TEACHER_REPORT_LISTS')
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Info("Class and subject lists for each teacher:\n  {path}",
                path=fpath)
Exemple #11
0
def logger(messages, suppressok):
    l = session.get('logger')
    if not l:
        user = session.get('user_id', '##')
        now = datetime.datetime.now()
        # Make new log-file
        l = now.isoformat(timespec='seconds') + '-' + user
        session['logger'] = l
    mimax = -10
    toflash = []
    for mi, mt, msg in messages:
        if mi > 9:
            msg = "Unerwarter Programmfehler: siehe Log-Datei %s" % l
        elif mi > mimax:
            mimax = mi
        try:
            etype = ERROR_TYPES[mi]
        except:
            etype = "ERROR %d" % mi
            mimax = 10
        toflash.append((etype + '::: ' + msg, mt))
    if len(toflash) > 10:
        flash("Abgekürzt: für alle Meldungen, siehe Log-Datei %s. ..." % l)
        toflash = toflash[-9:]
    for msg in toflash:
        flash(*msg)
    # Add a headline (the template will render this to the top, visible, line)
    if mimax >= 6:
        flash("!!! Aktion mit Fehler(n) abgeschlossen ...", "Error")
    elif mimax >= 4:
        flash("*** Aktion mit Warnung(en) abgeschlossen ...", "Warning")
    elif not suppressok:
        flash("+++ Aktion erfolgreich abgeschlossen ...", "Info")
    return Paths.logfile(l)
Exemple #12
0
def login():
    form = LoginForm()
    if form.validate_on_submit():
        session.clear()
        tid = form.USER.data
        permission = Users().permission(tid)
        session['user_id'] = tid
        session['permission'] = permission
        # The logging handler will be set when needed, see the start module
        # (<flask_app.__init__>, method <logger>):
        session['logger'] = None
        # Set the school-year to the latest one:
        session['year'] = Paths.getYears()[0]
        session.permanent = True

        # Delete old session files
        sdir = current_app.config['SESSION_FILE_DIR']
        now = time.time()
        for f in os.listdir(sdir):
            ff = os.path.join(sdir, f)
            delta = (now - os.path.getmtime(ff)) / 86400
            if delta > 2:
                os.remove(ff)

    if session.get('user_id'):
        return redirect(url_for('index'))
    return render_template(os.path.join(_BPNAME, 'login.html'), form=form)
Exemple #13
0
def test_04():
    """Export pupil data to a spreadsheet table.
    """
    REPORT.Test("Exporting pupil data for school-year %d" % _testyear)
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'export_pupils_0')
    classes = exportPupils(_testyear, fpath)
    REPORT.Test("Exported to %s" % fpath)
Exemple #14
0
def test_01():
    klass = Klass('13')
    bytefile = choiceTable(_testyear, klass)
    filepath = Paths.getYearPath(_testyear, 'FILE_SUBJECT_CHOICE_TABLE',
            make=-1).replace('*', str(klass).replace('.', '-')) + '.xlsx'
    with open(filepath, 'wb') as fh:
        fh.write(bytefile)
    REPORT.Test(" --> %s" % filepath)
Exemple #15
0
 def __init__(self, schoolyear):
     l = importLessons(schoolyear)
     self.newdata = l[1]
     self.tid2name = l[2]
     self.badsubjects = l[3]
     self.filepath = Paths.getYearPath(_year, 'FILE_SUBJECTS')
     self._wb = load_workbook(self.filepath + '.xlsx')
     self._ws = self._wb.active
     self.makeStyle()
Exemple #16
0
 def __init__ (self, schoolyear, klass):
     self._class = klass
     self._year = schoolyear
     self._month = Month (self._year)
     # Get the template
     self._tpath = Paths.getUserPath ('TEMPLATE_ATTENDANCE_TABLE')
     self._table = Table (self._tpath)
     self._wsInfo = self._table.getSheet (0)
     self._wsMonth = self._table.getSheet (1)
Exemple #17
0
def test_03():
    """Import pupil data – an old version (to later test updates).
    The data is in a spreadsheet table.
    """
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'import_pupils_0')
    REPORT.Test("Importing pupil data for school-year %d from %s" %
                (_testyear, fpath))
    classes = importPupils(_testyear, fpath)
    REPORT.Test("CLASSES/PUPILS: %s" % repr(classes))
Exemple #18
0
def test_07():
    # Reports for second term
    _term = '2'
    _date = '2016-06-22'
    for _ks in '11', '12.RS-HS-_', '12.Gym':
        _klass_stream = Klass(_ks)
        pdfBytes = makeReports(_year, _term, _klass_stream, _date)
        folder = Paths.getUserPath('DIR_GRADE_REPORT_TEMPLATES')
        fpath = os.path.join(folder, 'test_%s_%s.pdf' % (_klass_stream, _date))
        with open(fpath, 'wb') as fh:
            fh.write(pdfBytes)
Exemple #19
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
Exemple #20
0
def test_06():
    """Compare new raw data with saved complete version:
    Import complete version, then perform update from raw data.
    """
    REPORT.Test("\n --1-----------------\n RESET PUPILS TABLE")
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'Schuelerdaten_1')
    REPORT.Test("Importing pupil data for school-year %d from %s" %
                (_testyear, fpath))

    REPORT.Test("\n --2-----------------\n COMPARE UPDATES:")
    importLatestRaw(_testyear)
Exemple #21
0
def test_03():
    _k = '12K'
    _k = '12'
    _klass = Klass(_k)
    pupils = Pupils(_year)
    plist = pupils.classPupils(_klass)
    pdata = plist[0]
    pdfBytes = makeOneSheet(_year, _date, _klass, pdata)
    folder = Paths.getUserPath('DIR_TEXT_REPORT_TEMPLATES')
    fpath = os.path.join(folder, 'test1.pdf')
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Test(" --> %s" % fpath)
Exemple #22
0
def test_01():
    from wz_compat.template import openTemplate, getTemplateTags, pupilFields
    from glob import glob
    fbase = Paths.getUserPath('DIR_TEMPLATES')
    fx = 'Notenzeugnis/*.html'
    fmask = os.path.join(fbase, *fx.split('/'))
    for f in glob(fmask):
        fname = os.path.basename(f)
        fpath = fx.rsplit('/', 1)[0] + '/' + os.path.basename(f)
        REPORT.Test("TEMPLATE: %s" % fpath)
        t = openTemplate(fpath)
        tags = getTemplateTags(t)
        REPORT.Test("Pupil fields: %s" % repr(pupilFields(tags)))
Exemple #23
0
def test_06():
    #TODO: Perhaps if _GS is set, the type should be overriden?
    _klass = Klass('12')
    _pid = '200407'
    pupils = Pupils(_year)
    pall = pupils.classPupils(_klass)  # list of data for all pupils
    pdata = pall.pidmap[_pid]
    pdfBytes = makeOneSheet(_year, '2016-02-03', pdata, _term, 'Abgang')
    folder = Paths.getUserPath('DIR_GRADE_REPORT_TEMPLATES')
    ptag = pdata['PSORT'].replace(' ', '_')
    fpath = os.path.join(folder, 'test_%s_Abgang.pdf' % ptag)
    with open(fpath, 'wb') as fh:
        fh.write(pdfBytes)
    REPORT.Test(" --> %s" % fpath)
Exemple #24
0
    def __init__(self, schoolyear, filetag, klass=None, **kargs):
        """<filetag> is an entry in the PATHS config file, which may
        contain '*' (which will be replaced by the class).
        If there is already a file with this path, this will be read in
        using <readDBTable> (which adds a file extension if necessary).
        """
        self.schoolyear = schoolyear
        self.klass = klass
        # Configuration info for the options table
        self.fieldnames = CONF.TABLES.COURSE_PUPIL_FIELDNAMES

        self.filepath = Paths.getYearPath(schoolyear,
                                          filetag,
                                          make=-1,
                                          **kargs).replace('*', klass)
Exemple #25
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()
Exemple #26
0
def openTemplate(tpath):
    """Return a jinja2 <Template> instance.
    <tpath> is the path (folder separator '/') to the template file,
    relative to the main templates folder.
    The filepath is available as attribute <filename>.
    """
    tpsplit = tpath.split('/')
    fname = tpsplit.pop()
    tpdir = Paths.getUserPath('DIR_TEMPLATES')
    if tpsplit:
        tpdir = os.path.join(tpdir, *tpsplit)
    templateLoader = jinja2.FileSystemLoader(searchpath=tpdir)
    templateEnv = jinja2.Environment(loader=templateLoader, autoescape=True)
    try:
        return templateEnv.get_template(fname)
    except:
        REPORT.Fail(_NO_TEMPLATE, fname=os.path.join(tpdir, fname))
Exemple #27
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
Exemple #28
0
def test_02():
    """
    Initialise PUPILS table from "old" raw data (creation from scratch,
    no pre-existing table).
    """
    db = DB(_testyear, 'RECREATE')
    fpath = os.path.join(Paths.getYearPath(_testyear, 'DIR_SCHOOLDATA'),
                         '_test', 'pupil_data_0_raw')
    REPORT.Test(
        "Initialise with raw pupil data for school-year %d from:\n  %s" %
        (_testyear, fpath))
    rpd = readRawPupils(_testyear, fpath)
    for klass in sorted(rpd):
        REPORT.Test("\n +++ Class %s" % klass)
        for row in rpd[klass]:
            REPORT.Test("   --- %s" % repr(row))
    updateFromRaw(_testyear, rpd)
    db.renameTable('PUPILS', 'PUPILS0')
    db.deleteIndexes('PUPILS0')
    REPORT.Test("Saved in table PUPILS0")
Exemple #29
0
def index():
    class YearForm(FlaskForm):
        YEAR = SelectField("Schuljahr", coerce=int)

    schoolyear = session['year']
    form = YearForm()
    form.YEAR.choices = [(y, y) for y in Paths.getYears()]
    if form.validate_on_submit():
        # POST
        y = form.YEAR.data
        if y != schoolyear:
            schoolyear = y
            session['year'] = y
            flash("Schuljahr auf %d gesetzt." % y)

    # GET
    form.YEAR.default = schoolyear
    return render_template(os.path.join(_BPNAME, 'index.html'),
                            form=form,
                            heading=_HEADING)
Exemple #30
0
def readHols (schoolyear):
    """Return a <set> of <datetime.date> instances for all valid dates in the
    holidays file (configuration item "HOLIDAYS"). The dates are in isoformat
    (YYYY-MM-DD), but also MM-DD is acceptable, in which case the year will be
    added automatically (from the current school year).
    """
    deltaday = datetime.timedelta (days=1)
    kalinfo = ConfigFile (Paths.getYearPath (schoolyear, 'FILE_HOLIDAYS'))
    hols = set ()
    for d0 in kalinfo.SINGLE_DAYS.split ('|'):
        d = getDate (schoolyear, d0, dateformat=False)
        if d:
            hols.add (d)
        else:
            raise RuntimeError ("Date Error")

    for r0 in kalinfo.RANGES.split ('|'):
        try:
            d01, d02 = kalinfo [r0].split ('|')
        except:
            REPORT.Fail ("Ungültige Ferienzeit: %s" % r0)
        d1 = getDate (schoolyear, d01, dateformat=False)
        d2 = getDate (schoolyear, d02, dateformat=False)
        if (not d1) or (not d2):
            raise RuntimeError ("Date Error")
        if d1 >= d2:
            REPORT.Fail (("Ungültige Ferienangabe: %s"
                    "Startdatum ist nach dem Enddatum") % item)
            continue
        while True:
            hols.add (d1)
            d1 += deltaday
            if d1 > d2:
                break

    return hols