def make1(pid, rtype, rtag, kname): """View: Edit data for the report to be created, submit to build it. <rtype> is the report type. <rtag> is a TERM field entry from the GRADES table (term or date). <kname> is the school-class with stream tag. """ class _Form(FlaskForm): DATE_D = DateField('Ausgabedatum', validators=[InputRequired()]) def prepare(): # Get the name of the relevant grade scale configuration file: grademap = klass.match_map(CONF.MISC.GRADE_SCALE) gradechoices = [(g, g) for g in CONF.GRADES[grademap].VALID] # Get existing grades grades = getGradeData(schoolyear, pid, rtag) ### Get template fields which need to be set here gdata = GradeReportData(schoolyear, rtype, klass) groups = [] for sgroup in sorted(gdata.sgroup2sids): # grouped subject-ids fields = [] for sid in gdata.sgroup2sids[sgroup]: if sid.startswith('__'): gcalc.append(sid) continue sname = gdata.courses.subjectName(sid) try: grade = grades['GRADES'][sid] except: grade = '/' sfield = SelectField(sname, choices=gradechoices, default=grade) key = sgroup + '_' + sid setattr(_Form, key, sfield) fields.append(key) if fields: groups.append((sgroup, fields)) # "Extra" fields like "_GS" (one initial underline!) xfields = [] # Build roughly as for subjects, but in group <None> for tag in gdata.alltags: if tag.startswith('grades._'): xfield = tag.split('.', 1)[1] if xfield[1] == '_': # Calculated fields should not be presented here continue # Get options/field type try: xfconf = CONF.GRADES.XFIELDS[xfield] values = xfconf.VALUES except: flash( "Feld %s unbekannt: Vorlage %s" % (xfield, gdata.template.filename), "Error") continue # Check class/report-type validity rtypes = klass.match_map(xfconf.KLASS) if not rtypes: continue if rtype not in rtypes.split(): continue # Get existing value for this field try: val = grades['GRADES'][xfield] except: val = None # Determine field type if xfield.endswith('_D'): # An optional date field: d = datetime.date.fromisoformat(val) if val else None sfield = DateField(xfconf.NAME, default=d, validators=[Optional()]) else: try: # Assume a select field. # The choices depend on the tag. choices = [(c, c) for c in xfconf.VALUES] sfield = SelectField(xfconf.NAME, choices=choices, default=val) except: flash( "Unbekannter Feldtyp: %s in Vorlage %s" % (xfield, gdata.template.filename), "Error") continue key = 'Z_' + xfield setattr(_Form, key, sfield) xfields.append(key) if xfields: groups.append((None, xfields)) return groups def enterGrades(): # Add calculated grade entries gradeCalc(gmap, gcalc) # Enter grade data into db singleGrades2db(schoolyear, pid, klass, term=rtag, date=DATE_D, rtype=rtype, grades=gmap) return True schoolyear = session['year'] klass = Klass(kname) gcalc = [] # list of composite sids groups = REPORT.wrap(prepare, suppressok=True) if not groups: # Return to caller return redirect(request.referrer) # Get pupil data pupils = Pupils(schoolyear) pdata = pupils.pupil(pid) pname = pdata.name() form = _Form() if form.validate_on_submit(): # POST DATE_D = form.DATE_D.data.isoformat() gmap = {} # grade mapping {sid -> "grade"} for g, keys in groups: for key in keys: gmap[key.split('_', 1)[1]] = form[key].data if REPORT.wrap(enterGrades, suppressok=True): pdfBytes = REPORT.wrap(makeOneSheet, schoolyear, DATE_D, pdata, rtag, rtype) session['filebytes'] = pdfBytes session['download'] = 'Notenzeugnis_%s.pdf' % ( pdata['PSORT'].replace(' ', '_')) return redirect(url_for('bp_grades.pupils', klass=klass.klass)) #TODO: ? # There is no point to +/-, as these won't appear in the report and # are only intended for Notenkonferenzen. However, they might be of # interest for future reference? # GET # Set initial date of issue try: form.DATE_D.data = datetime.date.fromisoformat(rtag) except ValueError: form.DATE_D.data = datetime.date.today() return render_template(os.path.join(_BPNAME, 'make1.html'), form=form, groups=groups, heading=_HEADING, pid=pid, pname=pname, rtype=rtype, klass=klass.klass, stream=klass.stream)
def pupil(pid): """View: select report type and [edit-existing vs. new] for single report. All existing report dates for this pupil will be presented for selection. If there are no existing dates for this pupil, the only option is to construct a new one. Also a report type can be selected. The list might include invalid types as it is difficult at this stage (considering potential changes of stream or even school-class) to determine exactly which ones are valid. """ class _Form(FlaskForm): KLASS = SelectField("Klasse") STREAM = SelectField("Maßstab") EDITNEW = SelectField("Ausgabedatum") RTYPE = SelectField("Zeugnistyp") schoolyear = session['year'] # Get pupil data pupils = Pupils(schoolyear) pdata = pupils.pupil(pid) pname = pdata.name() klass = pdata.getKlass(withStream=True) # Get existing dates. db = DB(schoolyear) rows = db.select('GRADES', PID=pid) dates = [_NEWDATE] for row in db.select('GRADES', PID=pid): dates.append(row['TERM']) # If the stream, or even school-class have changed since an # existing report, the templates and available report types may be # different. To keep it simple, a list of all report types from the # configuration file GRADES.REPORT_TEMPLATES is presented for selection. # An invalid choice can be flagged at the next step. # If there is a mismatch between school-class/stream of the pupil as # selected on this page and that of the existing GRADES entry, a # warning can be shown at the next step. rtypes = [ rtype for rtype in CONF.GRADES.REPORT_TEMPLATES if rtype[0] != '_' ] kname = klass.klass stream = klass.stream form = _Form(KLASS=kname, STREAM=stream, RTYPE=_DEFAULT_RTYPE) form.KLASS.choices = [(k, k) for k in reversed(pupils.classes())] form.STREAM.choices = [(s, s) for s in CONF.GROUPS.STREAMS] form.EDITNEW.choices = [(d, d) for d in dates] form.RTYPE.choices = [(t, t) for t in rtypes] if form.validate_on_submit(): # POST klass = Klass.fromKandS(form.KLASS.data, form.STREAM.data) rtag = form.EDITNEW.data rtype = form.RTYPE.data kmap = CONF.GRADES.REPORT_TEMPLATES[rtype] tfile = klass.match_map(kmap) if tfile: return redirect( url_for('bp_grades.make1', pid=pid, kname=klass, rtag=rtag, rtype=rtype)) else: flash( "Zeugnistyp '%s' nicht möglich für Gruppe %s" % (rtype, klass), "Error") # GET return render_template(os.path.join(_BPNAME, 'pupil.html'), form=form, heading=_HEADING, klass=kname, pname=pname)