fsi.ims_import ============== .. py:module:: fsi.ims_import .. autoapi-nested-parse:: Dateien: - Kurse: Die Liste der Kurse - Personen -> importiert aus ldap - Teilnehmer: repräsentiert die Anmeldungen mit referenz zu Personen und Durchführungen - Ausführungen: die Listen der Durchführungen. Verlinkungen - Teilnehmer.TEILNEHMER_ID is ForeignKey für Personen.OBJ_ID Im folgenden eine Beschreibung der Beobachtungen zu den Files Personen.txt: (Daten sind sortiert nach Nachname/Vorname) - Es gibt Email-Adressen wie user@sg.ch.local, und dann in den Anmeldungen ohne .local. - Was bedeutet das Feld P_VALID_TILL? Relevant? - es gibt viele Einträge ohne email und/oder Kürzel (P_USERID), z.B. Zeilen - es gibt viele fehlende Vornamen/Nachnamen (evtl auffindbar in Teilnehmer.txt) - Neu erstellte Einträge mit gleicher Email und sonst gleichen Informationen: Beispiel Zeilen 2215/2216. Wie vorgehen, wenn es alte Anmeldungen zu Kursen gibt, die auf den alten Eintrag zeigen? Fragen: - Sind in Personen.txt auch externe Benutzer erfasst? - Kann ich externe Benutzer über den Eintrag P_VERWALTUNG identifizieren? Hier gibt es - [spezielle/ungültige/fehlerhafte] - Dritte - Gemeinde - Kantonale Verwaltung Zug - Staatskanzlei Welche von denen sind in unserem LDAP? Das sollte ich in etwa wissen. - Was ist zu tun mit 'alten' Benutzern? Und wie definieren wir alte Benutzer? - Ist ein alter Benutzer, der sich nicht mehr einloggen kann? - Inwieweit sollen 'alte' Benutzer noch in die Datenbank rein? - Sollen damit Anmeldungen von 'alten' Benutzern nicht importiert werden? Ausführungen.txt: - Wir haben Start und/oder Ende einer Durchführung fehlend, bei verschiedenen manchmal mit BUCHUNGSTATUS = Keine Buchung, kann aber auch Erfasst oder Abgesagt sein, ein Datum muss in der neuen Datenbank eingetragen werden. - Fehlende Namen der Kursleitung: Entweder 'Unbekannter Referent' als default oder Datenbank abändern (in Formularen weiterhin Pflichtfeld). Teilnehmer.txt - Field ANWESEND oft leer, soll Ja oder Nein gewählt werden? - Einträge ohne TEILNEHMER_ID (Link zu Personen.txt) sind externe Benutzer z.B. FAZIT Vorgeschlagenes Vorgehen: Die "single source of truth" bildet das bereits umegesetzte Verzeichnis der gültigen Benutzer aus dem LDAP kombiniert mit den weiteren Verzeichnissen. Es sollen nur Anmeldungen von mittels LDAP identifizierbaren Personen importiert werden. Es werden nicht importiert: - Personen, ohne Kürzel und Email sowie deren alte Anmeldungen - Durchführungen mit BUCHUNGS_STATUS = Keine Buchung and Start/Ende fehlend werden auch nicht mehr importiert. - Durchführungen ohne Start UND Ende unabhängig von Status Vervollständigungen - .local in Email-Adressen wird herausgenommen - Fehlender Wert für ANWESEND bei alten Anmeldungen wird mit JA gefüllt. - Referent Kurs: Standard-Wert einfügen "Unbekannter Referent" sofern fehlend Gemäss dem code (src/onegov/fsi/ims_import.py:368) gibt es keine Benutzer in Personen.txt die weder email noch code haben und von den Teilnehmer.txt her aus vervollständigt werden müssten. Anmeldungen in Teilnehmer.txt die keine Referenz zu Personen.txt haben, wurden berücksichtigt, sofern eine Email vorlag. Attributes ---------- .. autoapisummary:: fsi.ims_import.T fsi.ims_import.Ts Exceptions ---------- .. autoapisummary:: fsi.ims_import.InconsistencyError Functions --------- .. autoapisummary:: fsi.ims_import.parse_email fsi.ims_import.parse_date fsi.ims_import.parse_status fsi.ims_import.validate_integer fsi.ims_import.with_open fsi.ims_import.import_teacher_data fsi.ims_import.parse_completed fsi.ims_import.parse_persons fsi.ims_import.parse_courses fsi.ims_import.parse_events fsi.ims_import.parse_subscriptions fsi.ims_import.map_persons_to_known_ldap_user fsi.ims_import.parse_ims_data fsi.ims_import.import_ims_data Module Contents --------------- .. py:data:: T .. py:data:: Ts .. py:exception:: InconsistencyError(msg: str, file: str, rownumber: int | None = None) Bases: :py:obj:`BaseException` Common base class for all exceptions .. py:attribute:: msg .. py:attribute:: file .. py:attribute:: rownumber :value: None .. py:method:: __str__() -> str Return str(self). .. py:function:: parse_email(email: str) -> str | None .. py:function:: parse_date(val: str | None, default: DefaultT = None) -> datetime.datetime | DefaultT .. py:function:: parse_status(val: str) -> onegov.fsi.models.course_event.EventStatusType .. py:function:: validate_integer(val: str | None, treat_none_as_default: bool = True, default: int = 0) -> int .. py:function:: with_open(func: collections.abc.Callable[[onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow], *Ts], T]) -> collections.abc.Callable[[str, *Ts], T] .. py:function:: import_teacher_data(csvfile: onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow], request: onegov.fsi.request.FsiRequest, clean: bool = False) -> None .. py:function:: parse_completed(val: str | None) -> bool .. py:function:: parse_persons(csvfile: onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow]) -> dict[str, PersonDict] Pure extracting information .. py:function:: parse_courses(csvfile: onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow]) -> tuple[dict[int, str], dict[str, onegov.fsi.models.Course]] .. py:function:: parse_events(csvfile: onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow], courses: dict[str, onegov.fsi.models.Course]) -> tuple[dict[int, str], dict[str, onegov.fsi.models.CourseEvent]] .. py:function:: parse_subscriptions(csvfile: onegov.core.csv.CSVFile[onegov.core.csv.DefaultRow], persons: dict[str, PersonDict], events: dict[str, onegov.fsi.models.CourseEvent]) -> tuple[dict[int, str], dict[str, PersonDict], dict[str, UserDict]] :param csvfile: :param persons: dict of dicts of person records :param events: dict of CourseEvent classes :return: subscriptions within persons and within maybe_external_in_ldap .. py:function:: map_persons_to_known_ldap_user(person_record: PersonDict | UserDict, session: sqlalchemy.orm.Session) -> onegov.fsi.models.CourseAttendee | None Since the exported persons table contains records without email from various sources, we have to try to map it to an existing record or create a new one. The ldap fetched users have an attendee created with first_name, last_name and email set on the attendee as well. Returns an attendee or None .. py:function:: parse_ims_data(subscriptions_file: str, events_file: str, courses_file: str, persons_file: str) -> tuple[dict[str, dict[int, str]], dict[str, PersonDict] | None, dict[str, onegov.fsi.models.Course] | None, dict[str, onegov.fsi.models.CourseEvent] | None, dict[str, UserDict] | None] .. py:function:: import_ims_data(session: sqlalchemy.orm.Session, persons: dict[str, PersonDict], courses: dict[str, onegov.fsi.models.Course], events: dict[str, onegov.fsi.models.CourseEvent], possible_ldap_users: dict[str, UserDict]) -> dict[str, int]