e-valuation / EvaP

a university course evaluation system written in Python using Django
Other
95 stars 146 forks source link

JSON enrollment data importer (v1) #2131

Open janno42 opened 4 months ago

janno42 commented 4 months ago

Edits: - 2024-03-25: Added "scale" which defines whether the Course is graded or not - 2024-03-25: Added "relatedevents" which defines that two events belong to the same Course, changed previous logic with "lvnr" - 2024-05-27: Removed that "All changes should be made by an 'import user' who will be the user for LogEntrys." Other automatic changes have no user set in the LogEntry, so we don't need it here either.


A new enrollment data importer must be implemented. This importer will process JSON files containing account and course/evaluation data. This is a first version of the importer, it will be extended in future issues. The JSON files will contain additional information that is omitted here (e.g. "students" in "events" will have additional attributes, hence the bulky format).

The importer will be called by a management command (which will be called by a cron job) and will process a single file specified by a parameter. A second parameter specifies the Semester for which the data is to be imported. Unlike the current importer, there won't be a GUI, so error messages will have to be sent by email. In addition, a log should be created and also sent by email after a successful import. This log should contain

The JSON file is formatted as described below.

Changes to existing evaluations should only be made when the evaluation is in a state < APPROVED. Attempted changes in later states should be logged.


Format

{
    "students": [
        {
            "gguid": 34 character ID String,
            "email": String,
            "name": String,
            "christianname": String
        }
    ],
    "lecturers": [
        {
            "gguid": 34 character ID String,
            "email": String,
            "name": String,
            "christianname": String,
            "titlefront": String
        }
    ],
    "events": [
        {
            "gguid": 34 character ID String,
            "lvnr": double,
            "title": String,
            "title_en": String,
            "type": String,
            "isexam": boolean,
            "courses": [
                {
                    "cprid": String,
                    "scale": String
                },
                {
                    "cprid": String,
                    "scale": String
                }
            ],
            "relatedevents": {
                "gguid": 34 character ID String
            },
            "appointments": [
                {
                    "begin": String (Datetime),
                    "end": String (Datetime)
                }
            ],
            "lecturers": [
                {
                    "gguid": 34 character ID String
                }
            ],
            "students": [
                {
                    "gguid": 34 character ID String
                }
            ]
        }
    ]
}

Example

{
    "students": [
        {
            "gguid": "0x1",
            "email": "1@example.com",
            "name": "1",
            "christianname": "1"
        },
        {
            "gguid": "0x2",
            "email": "2@example.com",
            "name": "2",
            "christianname": "2"
        }
    ],
    "lecturers": [
        {
            "gguid": "0x3",
            "email": "3@example.com",
            "name": "3",
            "christianname": "3",
            "titlefront": "Prof. Dr."
        },
        {
            "gguid": "0x4",
            "email": "4@example.com",
            "name": "4",
            "christianname": "4",
            "titlefront": "Dr."
        }
    ],
    "events": [
        {
            "gguid": "0x5",
            "lvnr": "1",
            "title": "Prozessorientierte Informationssysteme",
            "title_en": "Process-oriented information systems",
            "type": "Vorlesung",
            "isexam": "false",
            "courses": [
                {
                    "cprid": "BA-Inf",
                    "scale": "GRADE_PARTICIPATION"
                },
                {
                    "cprid": "MA-Inf",
                    "scale": "GRADE_PARTICIPATION"
                },
            ],
            "relatedevents": {
                "gguid": "0x6"
            },
            "appointments": [
                {
                    "begin": "15.04.2024 10:15",
                    "end": "15.07.2024 11:45"
                }
            ],
            "lecturers": [
                {
                    "gguid": "0x3"
                }
            ],
            "students": [
                {
                    "gguid": "0x1"
                },
                {
                    "gguid": "0x2"
                }
            ]
        },
        {
            "gguid": "0x6",
            "lvnr": "2",
            "title": "Prozessorientierte Informationssysteme",
            "title_en": "Process-oriented information systems",
            "type": "Klausur",
            "isexam": "true",
            "courses": [
                {
                    "cprid": "BA-Inf",
                    "scale": "GRADE_TO_A_THIRD"
                },
                {
                    "cprid": "MA-Inf",
                    "scale": "GRADE_TO_A_THIRD"
                }
            ],
            "relatedevents": {
                "gguid": "0x5"
            },
            "appointments": [
                {
                    "begin": "29.07.2024 10:15",
                    "end": "29.07.2024 11:45"
                }
            ],
            "lecturers": [
                {
                    "gguid": "0x3"
                },
                {
                    "gguid": "0x4"
                }
            ],
            "students": [
                {
                    "gguid": "0x1"
                },
                {
                    "gguid": "0x2"
                }
            ]
        }
    ]
}
richardebeling commented 4 months ago

Thoughts / Questions / Ideas

janno42 commented 4 months ago
  • Ambiguity in emails: We should probably filter emails through clean_email to have INSTITUTION_EMAIL_REPLACEMENTS applied?

yes, this logic needs to be applied here as well

  • I could see conflicts with Update user data on login #2096 if SSO and CMS have different names stored. Maybe we should close it (depending on when we expect the CMS to go up)

closed

  • Removal of Evaluations / Courses: Those will simply not be contained anymore in the JSON, so we would just delete all courses/evaluations of the import semester whose cms_id is not contained in the json file?

yes, but only if they have a cms_id set (so we won't delete evaluations that have been created manually)

  • The logged attempted changes for state >= APPROVED should probably be grouped by course/evaluation.

yes, please

  • We treat their gguid values as blobs that must bit-match to be identical? Then, for us, 0xf and 0xF would be two different values. Especially asking because I'd expect them to send RFC4122-compliant UUIDs where capitalization doesn't matter. In the worst case, we would delete a course and recreate it with a differently capitalized cms_id.

we can assume them to be standard-compliant case-insensitive UUIDs for now

  • In general: We expect high-quality data (e.g. trimmed attributes). We trust the CMS to not mess up our data and we do not perform sanity checks.

yes (for now)

  • An import run could possibly delete (almost) all courses/evaluations of the semester during the preparation phase.

do you mean if for some reason the CMS doesn't export them correctly anymore? courses/evaluations are only added to the JSON file when there are enrollments for them. so there should be almost no cases where they are manually deleted from that point on. then let's say for all deletions we only notify by email and expect the managers to do the deletion manually.