diff --git a/migrations/.snapshot-dbildungs-iam-server.json b/migrations/.snapshot-dbildungs-iam-server.json index caa9974f8..b2c9b323a 100644 --- a/migrations/.snapshot-dbildungs-iam-server.json +++ b/migrations/.snapshot-dbildungs-iam-server.json @@ -90,20 +90,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -195,6 +181,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -320,20 +320,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -425,6 +411,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -572,20 +572,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -677,6 +663,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -816,20 +816,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -921,6 +907,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -1052,20 +1052,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -1326,6 +1312,15 @@ "VALID" ], "mappedType": "enum" + }, + "total_data_item_imported": { + "name": "total_data_item_imported", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "integer" } }, "name": "importvorgang", @@ -1378,97 +1373,6 @@ "VALID" ] }, - "organisations_typ_enum": { - "name": "organisations_typ_enum", - "schema": "public", - "items": [ - "ROOT", - "LAND", - "TRAEGER", - "SCHULE", - "KLASSE", - "ANBIETER", - "SONSTIGE ORGANISATION / EINRICHTUNG", - "UNBESTAETIGT" - ] - }, - "traegerschaft_enum": { - "name": "traegerschaft_enum", - "schema": "public", - "items": [ - "01", - "02", - "03", - "04", - "05", - "06" - ] - }, - "geschlecht_enum": { - "name": "geschlecht_enum", - "schema": "public", - "items": [ - "m", - "w", - "d", - "x" - ] - }, - "vertrauensstufe_enum": { - "name": "vertrauensstufe_enum", - "schema": "public", - "items": [ - "KEIN", - "UNBE", - "TEIL", - "VOLL" - ] - }, - "email_address_status_enum": { - "name": "email_address_status_enum", - "schema": "public", - "items": [ - "ENABLED", - "DISABLED", - "REQUESTED", - "FAILED" - ] - }, - "rollen_art_enum": { - "name": "rollen_art_enum", - "schema": "public", - "items": [ - "LERN", - "LEHR", - "EXTERN", - "ORGADMIN", - "LEIT", - "SYSADMIN" - ] - }, - "personenstatus_enum": { - "name": "personenstatus_enum", - "schema": "public", - "items": [ - "AKTIV" - ] - }, - "jahrgangsstufe_enum": { - "name": "jahrgangsstufe_enum", - "schema": "public", - "items": [ - "01", - "02", - "03", - "04", - "05", - "06", - "07", - "08", - "09", - "10" - ] - }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -1557,35 +1461,35 @@ "length": 6, "mappedType": "datetime" }, - "importvorgang_id": { - "name": "importvorgang_id", + "administriert_von": { + "name": "administriert_von", "type": "uuid", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, + "nullable": true, "mappedType": "uuid" }, - "nachname": { - "name": "nachname", - "type": "varchar(255)", + "zugehoerig_zu": { + "name": "zugehoerig_zu", + "type": "uuid", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "mappedType": "string" + "nullable": true, + "mappedType": "uuid" }, - "vorname": { - "name": "vorname", + "kennung": { + "name": "kennung", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, + "nullable": true, "mappedType": "string" }, - "klasse": { - "name": "klasse", + "name": { + "name": "name", "type": "varchar(255)", "unsigned": false, "autoincrement": false, @@ -1593,8 +1497,8 @@ "nullable": true, "mappedType": "string" }, - "personalnummer": { - "name": "personalnummer", + "namensergaenzung": { + "name": "namensergaenzung", "type": "varchar(255)", "unsigned": false, "autoincrement": false, @@ -1602,40 +1506,117 @@ "nullable": true, "mappedType": "string" }, - "validation_errors": { - "name": "validation_errors", - "type": "text[]", + "kuerzel": { + "name": "kuerzel", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, - "mappedType": "array" + "mappedType": "string" }, - "username": { - "name": "username", - "type": "varchar(50)", + "typ": { + "name": "typ", + "type": "organisations_typ_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "nativeEnumName": "organisations_typ_enum", + "enumItems": [ + "ROOT", + "LAND", + "TRAEGER", + "SCHULE", + "KLASSE", + "ANBIETER", + "SONSTIGE ORGANISATION / EINRICHTUNG", + "UNBESTAETIGT" + ], + "mappedType": "enum" + }, + "traegerschaft": { + "name": "traegerschaft", + "type": "traegerschaft_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "nativeEnumName": "traegerschaft_enum", + "enumItems": [ + "01", + "02", + "03", + "04", + "05", + "06" + ], + "mappedType": "enum" + }, + "email_domain": { + "name": "email_domain", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, - "length": 50, "mappedType": "string" }, - "password": { - "name": "password", + "email_address": { + "name": "email_address", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, "mappedType": "string" + }, + "itslearning_enabled": { + "name": "itslearning_enabled", + "type": "boolean", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "false", + "mappedType": "boolean" + }, + "version": { + "name": "version", + "type": "bigint", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "1", + "mappedType": "bigint" } }, - "name": "importdataitem", + "name": "organisation", "schema": "public", "indexes": [ { - "keyName": "importdataitem_pkey", + "columnNames": [ + "administriert_von" + ], + "composite": false, + "keyName": "organisation_administriert_von_index", + "constraint": false, + "primary": false, + "unique": false + }, + { + "columnNames": [ + "typ" + ], + "composite": false, + "keyName": "organisation_typ_index", + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "organisation_pkey", "columnNames": [ "id" ], @@ -1646,20 +1627,7 @@ } ], "checks": [], - "foreignKeys": { - "importdataitem_importvorgang_id_foreign": { - "constraintName": "importdataitem_importvorgang_id_foreign", - "columnNames": [ - "importvorgang_id" - ], - "localTableName": "public.importdataitem", - "referencedColumnNames": [ - "id" - ], - "referencedTableName": "public.importvorgang", - "updateRule": "cascade" - } - }, + "foreignKeys": {}, "nativeEnums": { "db_seed_status_enum": { "name": "db_seed_status_enum", @@ -1680,20 +1648,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -1785,6 +1739,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -1873,31 +1841,13 @@ "length": 6, "mappedType": "datetime" }, - "administriert_von": { - "name": "administriert_von", - "type": "uuid", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "uuid" - }, - "zugehoerig_zu": { - "name": "zugehoerig_zu", - "type": "uuid", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "uuid" - }, - "kennung": { - "name": "kennung", + "email": { + "name": "email", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "mappedType": "string" }, "name": { @@ -1906,36 +1856,59 @@ "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "mappedType": "string" }, - "namensergaenzung": { - "name": "namensergaenzung", + "username": { + "name": "username", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "mappedType": "string" + } + }, + "name": "ox_user_blacklist", + "schema": "public", + "indexes": [ + { + "keyName": "ox_user_blacklist_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": { + "db_seed_status_enum": { + "name": "db_seed_status_enum", + "schema": "public", + "items": [ + "STARTED", + "DONE", + "FAILED" + ] }, - "kuerzel": { - "name": "kuerzel", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "string" + "referenced_entity_type_enum": { + "name": "referenced_entity_type_enum", + "schema": "public", + "items": [ + "PERSON", + "ORGANISATION", + "ROLLE", + "SERVICE_PROVIDER" + ] }, - "typ": { - "name": "typ", - "type": "organisations_typ_enum", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "nativeEnumName": "organisations_typ_enum", - "enumItems": [ + "organisations_typ_enum": { + "name": "organisations_typ_enum", + "schema": "public", + "items": [ "ROOT", "LAND", "TRAEGER", @@ -1944,161 +1917,19 @@ "ANBIETER", "SONSTIGE ORGANISATION / EINRICHTUNG", "UNBESTAETIGT" - ], - "mappedType": "enum" + ] }, - "traegerschaft": { - "name": "traegerschaft", - "type": "traegerschaft_enum", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "nativeEnumName": "traegerschaft_enum", - "enumItems": [ + "traegerschaft_enum": { + "name": "traegerschaft_enum", + "schema": "public", + "items": [ "01", "02", "03", "04", "05", "06" - ], - "mappedType": "enum" - }, - "email_domain": { - "name": "email_domain", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "string" - }, - "email_address": { - "name": "email_address", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "string" - }, - "itslearning_enabled": { - "name": "itslearning_enabled", - "type": "boolean", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "default": "false", - "mappedType": "boolean" - }, - "version": { - "name": "version", - "type": "bigint", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "default": "1", - "mappedType": "bigint" - } - }, - "name": "organisation", - "schema": "public", - "indexes": [ - { - "columnNames": [ - "administriert_von" - ], - "composite": false, - "keyName": "organisation_administriert_von_index", - "constraint": false, - "primary": false, - "unique": false - }, - { - "columnNames": [ - "typ" - ], - "composite": false, - "keyName": "organisation_typ_index", - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "organisation_pkey", - "columnNames": [ - "id" - ], - "composite": false, - "constraint": true, - "primary": true, - "unique": true - } - ], - "checks": [], - "foreignKeys": {}, - "nativeEnums": { - "db_seed_status_enum": { - "name": "db_seed_status_enum", - "schema": "public", - "items": [ - "STARTED", - "DONE", - "FAILED" - ] - }, - "referenced_entity_type_enum": { - "name": "referenced_entity_type_enum", - "schema": "public", - "items": [ - "PERSON", - "ORGANISATION", - "ROLLE", - "SERVICE_PROVIDER" - ] - }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, - "organisations_typ_enum": { - "name": "organisations_typ_enum", - "schema": "public", - "items": [ - "ROOT", - "LAND", - "TRAEGER", - "SCHULE", - "KLASSE", - "ANBIETER", - "SONSTIGE ORGANISATION / EINRICHTUNG", - "UNBESTAETIGT" - ] - }, - "traegerschaft_enum": { - "name": "traegerschaft_enum", - "schema": "public", - "items": [ - "01", - "02", - "03", - "04", - "05", - "06" - ] + ] }, "geschlecht_enum": { "name": "geschlecht_enum", @@ -2165,6 +1996,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -2187,8 +2032,7 @@ "PERSON_SYNCHRONISIEREN", "CRON_DURCHFUEHREN", "PERSONEN_ANLEGEN", - "IMPORT_DURCHFUEHREN", - "PERSONEN_LESEN" + "IMPORT_DURCHFUEHREN" ] }, "service_provider_target_enum": { @@ -2253,8 +2097,8 @@ "length": 6, "mappedType": "datetime" }, - "email": { - "name": "email", + "keycloak_user_id": { + "name": "keycloak_user_id", "type": "varchar(255)", "unsigned": false, "autoincrement": false, @@ -2262,306 +2106,50 @@ "nullable": false, "mappedType": "string" }, - "name": { - "name": "name", + "referrer": { + "name": "referrer", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, + "nullable": true, "mappedType": "string" }, - "username": { - "name": "username", + "mandant": { + "name": "mandant", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, "mappedType": "string" - } - }, - "name": "ox_user_blacklist", - "schema": "public", - "indexes": [ - { - "keyName": "ox_user_blacklist_pkey", - "columnNames": [ - "id" - ], - "composite": false, - "constraint": true, - "primary": true, - "unique": true - } - ], - "checks": [], - "foreignKeys": {}, - "nativeEnums": { - "db_seed_status_enum": { - "name": "db_seed_status_enum", - "schema": "public", - "items": [ - "STARTED", - "DONE", - "FAILED" - ] }, - "referenced_entity_type_enum": { - "name": "referenced_entity_type_enum", - "schema": "public", - "items": [ - "PERSON", - "ORGANISATION", - "ROLLE", - "SERVICE_PROVIDER" - ] + "stammorganisation": { + "name": "stammorganisation", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "string" }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] + "familienname": { + "name": "familienname", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" }, - "organisations_typ_enum": { - "name": "organisations_typ_enum", - "schema": "public", - "items": [ - "ROOT", - "LAND", - "TRAEGER", - "SCHULE", - "KLASSE", - "ANBIETER", - "SONSTIGE ORGANISATION / EINRICHTUNG", - "UNBESTAETIGT" - ] - }, - "traegerschaft_enum": { - "name": "traegerschaft_enum", - "schema": "public", - "items": [ - "01", - "02", - "03", - "04", - "05", - "06" - ] - }, - "geschlecht_enum": { - "name": "geschlecht_enum", - "schema": "public", - "items": [ - "m", - "w", - "d", - "x" - ] - }, - "vertrauensstufe_enum": { - "name": "vertrauensstufe_enum", - "schema": "public", - "items": [ - "KEIN", - "UNBE", - "TEIL", - "VOLL" - ] - }, - "email_address_status_enum": { - "name": "email_address_status_enum", - "schema": "public", - "items": [ - "ENABLED", - "DISABLED", - "REQUESTED", - "FAILED" - ] - }, - "rollen_art_enum": { - "name": "rollen_art_enum", - "schema": "public", - "items": [ - "LERN", - "LEHR", - "EXTERN", - "ORGADMIN", - "LEIT", - "SYSADMIN" - ] - }, - "personenstatus_enum": { - "name": "personenstatus_enum", - "schema": "public", - "items": [ - "AKTIV" - ] - }, - "jahrgangsstufe_enum": { - "name": "jahrgangsstufe_enum", - "schema": "public", - "items": [ - "01", - "02", - "03", - "04", - "05", - "06", - "07", - "08", - "09", - "10" - ] - }, - "rollen_merkmal_enum": { - "name": "rollen_merkmal_enum", - "schema": "public", - "items": [ - "BEFRISTUNG_PFLICHT", - "KOPERS_PFLICHT" - ] - }, - "rollen_system_recht_enum": { - "name": "rollen_system_recht_enum", - "schema": "public", - "items": [ - "ROLLEN_VERWALTEN", - "PERSONEN_SOFORT_LOESCHEN", - "PERSONEN_VERWALTEN", - "SCHULEN_VERWALTEN", - "KLASSEN_VERWALTEN", - "SCHULTRAEGER_VERWALTEN", - "MIGRATION_DURCHFUEHREN", - "PERSON_SYNCHRONISIEREN", - "CRON_DURCHFUEHREN", - "PERSONEN_ANLEGEN", - "IMPORT_DURCHFUEHREN" - ] - }, - "service_provider_target_enum": { - "name": "service_provider_target_enum", - "schema": "public", - "items": [ - "URL", - "EMAIL", - "SCHULPORTAL_ADMINISTRATION" - ] - }, - "service_provider_kategorie_enum": { - "name": "service_provider_kategorie_enum", - "schema": "public", - "items": [ - "EMAIL", - "UNTERRICHT", - "VERWALTUNG", - "HINWEISE", - "ANGEBOTE" - ] - }, - "service_provider_system_enum": { - "name": "service_provider_system_enum", - "schema": "public", - "items": [ - "NONE", - "EMAIL", - "ITSLEARNING" - ] - } - } - }, - { - "columns": { - "id": { - "name": "id", - "type": "uuid", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "uuid" - }, - "created_at": { - "name": "created_at", - "type": "timestamptz", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "length": 6, - "mappedType": "datetime" - }, - "updated_at": { - "name": "updated_at", - "type": "timestamptz", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "length": 6, - "mappedType": "datetime" - }, - "keycloak_user_id": { - "name": "keycloak_user_id", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "string" - }, - "referrer": { - "name": "referrer", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "string" - }, - "mandant": { - "name": "mandant", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "string" - }, - "stammorganisation": { - "name": "stammorganisation", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "string" - }, - "familienname": { - "name": "familienname", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "string" - }, - "vorname": { - "name": "vorname", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "string" + "vorname": { + "name": "vorname", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" }, "initialen_familienname": { "name": "initialen_familienname", @@ -2806,14 +2394,1004 @@ "columnNames": [ "personalnummer" ], - "composite": false, - "constraint": false, + "composite": false, + "constraint": false, + "primary": false, + "unique": false, + "expression": "create unique index \"person_personalnummer_unique\" on \"person\" (\"personalnummer\") nulls distinct;" + }, + { + "keyName": "person_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "person_data_provider_id_foreign": { + "constraintName": "person_data_provider_id_foreign", + "columnNames": [ + "data_provider_id" + ], + "localTableName": "public.person", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.data_provider", + "deleteRule": "set null", + "updateRule": "cascade" + } + }, + "nativeEnums": { + "db_seed_status_enum": { + "name": "db_seed_status_enum", + "schema": "public", + "items": [ + "STARTED", + "DONE", + "FAILED" + ] + }, + "referenced_entity_type_enum": { + "name": "referenced_entity_type_enum", + "schema": "public", + "items": [ + "PERSON", + "ORGANISATION", + "ROLLE", + "SERVICE_PROVIDER" + ] + }, + "organisations_typ_enum": { + "name": "organisations_typ_enum", + "schema": "public", + "items": [ + "ROOT", + "LAND", + "TRAEGER", + "SCHULE", + "KLASSE", + "ANBIETER", + "SONSTIGE ORGANISATION / EINRICHTUNG", + "UNBESTAETIGT" + ] + }, + "traegerschaft_enum": { + "name": "traegerschaft_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06" + ] + }, + "geschlecht_enum": { + "name": "geschlecht_enum", + "schema": "public", + "items": [ + "m", + "w", + "d", + "x" + ] + }, + "vertrauensstufe_enum": { + "name": "vertrauensstufe_enum", + "schema": "public", + "items": [ + "KEIN", + "UNBE", + "TEIL", + "VOLL" + ] + }, + "email_address_status_enum": { + "name": "email_address_status_enum", + "schema": "public", + "items": [ + "ENABLED", + "DISABLED", + "REQUESTED", + "FAILED" + ] + }, + "rollen_art_enum": { + "name": "rollen_art_enum", + "schema": "public", + "items": [ + "LERN", + "LEHR", + "EXTERN", + "ORGADMIN", + "LEIT", + "SYSADMIN" + ] + }, + "personenstatus_enum": { + "name": "personenstatus_enum", + "schema": "public", + "items": [ + "AKTIV" + ] + }, + "jahrgangsstufe_enum": { + "name": "jahrgangsstufe_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10" + ] + }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, + "rollen_merkmal_enum": { + "name": "rollen_merkmal_enum", + "schema": "public", + "items": [ + "BEFRISTUNG_PFLICHT", + "KOPERS_PFLICHT" + ] + }, + "rollen_system_recht_enum": { + "name": "rollen_system_recht_enum", + "schema": "public", + "items": [ + "ROLLEN_VERWALTEN", + "PERSONEN_SOFORT_LOESCHEN", + "PERSONEN_VERWALTEN", + "SCHULEN_VERWALTEN", + "KLASSEN_VERWALTEN", + "SCHULTRAEGER_VERWALTEN", + "MIGRATION_DURCHFUEHREN", + "PERSON_SYNCHRONISIEREN", + "CRON_DURCHFUEHREN", + "PERSONEN_ANLEGEN", + "IMPORT_DURCHFUEHREN", + "PERSONEN_LESEN" + ] + }, + "service_provider_target_enum": { + "name": "service_provider_target_enum", + "schema": "public", + "items": [ + "URL", + "EMAIL", + "SCHULPORTAL_ADMINISTRATION" + ] + }, + "service_provider_kategorie_enum": { + "name": "service_provider_kategorie_enum", + "schema": "public", + "items": [ + "EMAIL", + "UNTERRICHT", + "VERWALTUNG", + "HINWEISE", + "ANGEBOTE" + ] + }, + "service_provider_system_enum": { + "name": "service_provider_system_enum", + "schema": "public", + "items": [ + "NONE", + "EMAIL", + "ITSLEARNING" + ] + } + } + }, + { + "columns": { + "id": { + "name": "id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "address": { + "name": "address", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "uuid" + }, + "ox_user_id": { + "name": "ox_user_id", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "string" + }, + "status": { + "name": "status", + "type": "email_address_status_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "nativeEnumName": "email_address_status_enum", + "enumItems": [ + "ENABLED", + "DISABLED", + "REQUESTED", + "FAILED" + ], + "mappedType": "enum" + } + }, + "name": "email_address", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "address" + ], + "composite": false, + "keyName": "email_address_address_unique", + "constraint": true, + "primary": false, + "unique": true + }, + { + "columnNames": [ + "person_id" + ], + "composite": false, + "keyName": "email_address_person_id_index", + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "email_address_pkey", + "columnNames": [ + "id", + "address" + ], + "composite": true, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": { + "email_address_person_id_foreign": { + "constraintName": "email_address_person_id_foreign", + "columnNames": [ + "person_id" + ], + "localTableName": "public.email_address", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.person", + "deleteRule": "set null", + "updateRule": "cascade" + } + }, + "nativeEnums": { + "db_seed_status_enum": { + "name": "db_seed_status_enum", + "schema": "public", + "items": [ + "STARTED", + "DONE", + "FAILED" + ] + }, + "referenced_entity_type_enum": { + "name": "referenced_entity_type_enum", + "schema": "public", + "items": [ + "PERSON", + "ORGANISATION", + "ROLLE", + "SERVICE_PROVIDER" + ] + }, + "organisations_typ_enum": { + "name": "organisations_typ_enum", + "schema": "public", + "items": [ + "ROOT", + "LAND", + "TRAEGER", + "SCHULE", + "KLASSE", + "ANBIETER", + "SONSTIGE ORGANISATION / EINRICHTUNG", + "UNBESTAETIGT" + ] + }, + "traegerschaft_enum": { + "name": "traegerschaft_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06" + ] + }, + "geschlecht_enum": { + "name": "geschlecht_enum", + "schema": "public", + "items": [ + "m", + "w", + "d", + "x" + ] + }, + "vertrauensstufe_enum": { + "name": "vertrauensstufe_enum", + "schema": "public", + "items": [ + "KEIN", + "UNBE", + "TEIL", + "VOLL" + ] + }, + "email_address_status_enum": { + "name": "email_address_status_enum", + "schema": "public", + "items": [ + "ENABLED", + "DISABLED", + "REQUESTED", + "FAILED" + ] + }, + "rollen_art_enum": { + "name": "rollen_art_enum", + "schema": "public", + "items": [ + "LERN", + "LEHR", + "EXTERN", + "ORGADMIN", + "LEIT", + "SYSADMIN" + ] + }, + "personenstatus_enum": { + "name": "personenstatus_enum", + "schema": "public", + "items": [ + "AKTIV" + ] + }, + "jahrgangsstufe_enum": { + "name": "jahrgangsstufe_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10" + ] + }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, + "rollen_merkmal_enum": { + "name": "rollen_merkmal_enum", + "schema": "public", + "items": [ + "BEFRISTUNG_PFLICHT", + "KOPERS_PFLICHT" + ] + }, + "rollen_system_recht_enum": { + "name": "rollen_system_recht_enum", + "schema": "public", + "items": [ + "ROLLEN_VERWALTEN", + "PERSONEN_SOFORT_LOESCHEN", + "PERSONEN_VERWALTEN", + "SCHULEN_VERWALTEN", + "KLASSEN_VERWALTEN", + "SCHULTRAEGER_VERWALTEN", + "MIGRATION_DURCHFUEHREN", + "PERSON_SYNCHRONISIEREN", + "CRON_DURCHFUEHREN", + "PERSONEN_ANLEGEN", + "IMPORT_DURCHFUEHREN", + "PERSONEN_LESEN" + ] + }, + "service_provider_target_enum": { + "name": "service_provider_target_enum", + "schema": "public", + "items": [ + "URL", + "EMAIL", + "SCHULPORTAL_ADMINISTRATION" + ] + }, + "service_provider_kategorie_enum": { + "name": "service_provider_kategorie_enum", + "schema": "public", + "items": [ + "EMAIL", + "UNTERRICHT", + "VERWALTUNG", + "HINWEISE", + "ANGEBOTE" + ] + }, + "service_provider_system_enum": { + "name": "service_provider_system_enum", + "schema": "public", + "items": [ + "NONE", + "EMAIL", + "ITSLEARNING" + ] + } + } + }, + { + "columns": { + "id": { + "name": "id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "name": { + "name": "name", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" + }, + "administered_by_schulstrukturknoten": { + "name": "administered_by_schulstrukturknoten", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "rollenart": { + "name": "rollenart", + "type": "rollen_art_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "nativeEnumName": "rollen_art_enum", + "enumItems": [ + "LERN", + "LEHR", + "EXTERN", + "ORGADMIN", + "LEIT", + "SYSADMIN" + ], + "mappedType": "enum" + }, + "ist_technisch": { + "name": "ist_technisch", + "type": "boolean", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "false", + "mappedType": "boolean" + }, + "version": { + "name": "version", + "type": "bigint", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "1", + "mappedType": "bigint" + } + }, + "name": "rolle", + "schema": "public", + "indexes": [ + { + "keyName": "rolle_pkey", + "columnNames": [ + "id" + ], + "composite": false, + "constraint": true, + "primary": true, + "unique": true + } + ], + "checks": [], + "foreignKeys": {}, + "nativeEnums": { + "db_seed_status_enum": { + "name": "db_seed_status_enum", + "schema": "public", + "items": [ + "STARTED", + "DONE", + "FAILED" + ] + }, + "referenced_entity_type_enum": { + "name": "referenced_entity_type_enum", + "schema": "public", + "items": [ + "PERSON", + "ORGANISATION", + "ROLLE", + "SERVICE_PROVIDER" + ] + }, + "organisations_typ_enum": { + "name": "organisations_typ_enum", + "schema": "public", + "items": [ + "ROOT", + "LAND", + "TRAEGER", + "SCHULE", + "KLASSE", + "ANBIETER", + "SONSTIGE ORGANISATION / EINRICHTUNG", + "UNBESTAETIGT" + ] + }, + "traegerschaft_enum": { + "name": "traegerschaft_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06" + ] + }, + "geschlecht_enum": { + "name": "geschlecht_enum", + "schema": "public", + "items": [ + "m", + "w", + "d", + "x" + ] + }, + "vertrauensstufe_enum": { + "name": "vertrauensstufe_enum", + "schema": "public", + "items": [ + "KEIN", + "UNBE", + "TEIL", + "VOLL" + ] + }, + "email_address_status_enum": { + "name": "email_address_status_enum", + "schema": "public", + "items": [ + "ENABLED", + "DISABLED", + "REQUESTED", + "FAILED" + ] + }, + "rollen_art_enum": { + "name": "rollen_art_enum", + "schema": "public", + "items": [ + "LERN", + "LEHR", + "EXTERN", + "ORGADMIN", + "LEIT", + "SYSADMIN" + ] + }, + "personenstatus_enum": { + "name": "personenstatus_enum", + "schema": "public", + "items": [ + "AKTIV" + ] + }, + "jahrgangsstufe_enum": { + "name": "jahrgangsstufe_enum", + "schema": "public", + "items": [ + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10" + ] + }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, + "rollen_merkmal_enum": { + "name": "rollen_merkmal_enum", + "schema": "public", + "items": [ + "BEFRISTUNG_PFLICHT", + "KOPERS_PFLICHT" + ] + }, + "rollen_system_recht_enum": { + "name": "rollen_system_recht_enum", + "schema": "public", + "items": [ + "ROLLEN_VERWALTEN", + "PERSONEN_SOFORT_LOESCHEN", + "PERSONEN_VERWALTEN", + "SCHULEN_VERWALTEN", + "KLASSEN_VERWALTEN", + "SCHULTRAEGER_VERWALTEN", + "MIGRATION_DURCHFUEHREN", + "PERSON_SYNCHRONISIEREN", + "CRON_DURCHFUEHREN", + "PERSONEN_ANLEGEN", + "IMPORT_DURCHFUEHREN", + "PERSONEN_LESEN" + ] + }, + "service_provider_target_enum": { + "name": "service_provider_target_enum", + "schema": "public", + "items": [ + "URL", + "EMAIL", + "SCHULPORTAL_ADMINISTRATION" + ] + }, + "service_provider_kategorie_enum": { + "name": "service_provider_kategorie_enum", + "schema": "public", + "items": [ + "EMAIL", + "UNTERRICHT", + "VERWALTUNG", + "HINWEISE", + "ANGEBOTE" + ] + }, + "service_provider_system_enum": { + "name": "service_provider_system_enum", + "schema": "public", + "items": [ + "NONE", + "EMAIL", + "ITSLEARNING" + ] + } + } + }, + { + "columns": { + "id": { + "name": "id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "created_at": { + "name": "created_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "length": 6, + "mappedType": "datetime" + }, + "person_id": { + "name": "person_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "organisation_id": { + "name": "organisation_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "uuid" + }, + "rolle_id": { + "name": "rolle_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "referrer": { + "name": "referrer", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "string" + }, + "mandant": { + "name": "mandant", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "string" + }, + "personenstatus": { + "name": "personenstatus", + "type": "personenstatus_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "nativeEnumName": "personenstatus_enum", + "enumItems": [ + "AKTIV" + ], + "mappedType": "enum" + }, + "jahrgangsstufe": { + "name": "jahrgangsstufe", + "type": "jahrgangsstufe_enum", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "nativeEnumName": "jahrgangsstufe_enum", + "enumItems": [ + "01", + "02", + "03", + "04", + "05", + "06", + "07", + "08", + "09", + "10" + ], + "mappedType": "enum" + }, + "sichtfreigabe": { + "name": "sichtfreigabe", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "default": "'nein'", + "mappedType": "string" + }, + "loeschung_zeitpunkt": { + "name": "loeschung_zeitpunkt", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + }, + "revision": { + "name": "revision", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "default": "'1'", + "mappedType": "string" + }, + "befristung": { + "name": "befristung", + "type": "timestamptz", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "length": 6, + "mappedType": "datetime" + } + }, + "name": "personenkontext", + "schema": "public", + "indexes": [ + { + "columnNames": [ + "person_id" + ], + "composite": false, + "keyName": "personenkontext_person_id_index", + "constraint": false, + "primary": false, + "unique": false + }, + { + "columnNames": [ + "organisation_id" + ], + "composite": false, + "keyName": "personenkontext_organisation_id_index", + "constraint": false, + "primary": false, + "unique": false + }, + { + "keyName": "personenkontext_person_id_organisation_id_rolle_id_unique", + "columnNames": [ + "person_id", + "organisation_id", + "rolle_id" + ], + "composite": true, + "constraint": true, "primary": false, - "unique": false, - "expression": "create unique index \"person_personalnummer_unique\" on \"person\" (\"personalnummer\") nulls distinct;" + "unique": true }, { - "keyName": "person_pkey", + "keyName": "personenkontext_pkey", "columnNames": [ "id" ], @@ -2825,17 +3403,28 @@ ], "checks": [], "foreignKeys": { - "person_data_provider_id_foreign": { - "constraintName": "person_data_provider_id_foreign", + "personenkontext_person_id_foreign": { + "constraintName": "personenkontext_person_id_foreign", "columnNames": [ - "data_provider_id" + "person_id" ], - "localTableName": "public.person", + "localTableName": "public.personenkontext", "referencedColumnNames": [ "id" ], - "referencedTableName": "public.data_provider", - "deleteRule": "set null", + "referencedTableName": "public.person", + "deleteRule": "cascade" + }, + "personenkontext_rolle_id_foreign": { + "constraintName": "personenkontext_rolle_id_foreign", + "columnNames": [ + "rolle_id" + ], + "localTableName": "public.personenkontext", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.rolle", "updateRule": "cascade" } }, @@ -2859,20 +3448,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -2964,6 +3539,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -2986,8 +3575,7 @@ "PERSON_SYNCHRONISIEREN", "CRON_DURCHFUEHREN", "PERSONEN_ANLEGEN", - "IMPORT_DURCHFUEHREN", - "PERSONEN_LESEN" + "IMPORT_DURCHFUEHREN" ] }, "service_provider_target_enum": { @@ -3032,15 +3620,6 @@ "nullable": false, "mappedType": "uuid" }, - "address": { - "name": "address", - "type": "varchar(255)", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": false, - "mappedType": "string" - }, "created_at": { "name": "created_at", "type": "timestamptz", @@ -3070,62 +3649,99 @@ "nullable": true, "mappedType": "uuid" }, - "ox_user_id": { - "name": "ox_user_id", + "import_by_username": { + "name": "import_by_username", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" + }, + "rolle_id": { + "name": "rolle_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "uuid" + }, + "rollename": { + "name": "rollename", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, + "nullable": false, + "mappedType": "string" + }, + "organisation_id": { + "name": "organisation_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, "nullable": true, + "mappedType": "uuid" + }, + "organisationsname": { + "name": "organisationsname", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, "mappedType": "string" }, + "data_item_count": { + "name": "data_item_count", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "integer" + }, "status": { "name": "status", - "type": "email_address_status_enum", + "type": "import_status_enum", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, - "nativeEnumName": "email_address_status_enum", + "nativeEnumName": "import_status_enum", "enumItems": [ - "ENABLED", - "DISABLED", - "REQUESTED", - "FAILED" + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" ], "mappedType": "enum" + }, + "total_data_item_imported": { + "name": "total_data_item_imported", + "type": "int", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "integer" } }, - "name": "email_address", + "name": "importvorgang", "schema": "public", "indexes": [ { + "keyName": "importvorgang_pkey", "columnNames": [ - "address" - ], - "composite": false, - "keyName": "email_address_address_unique", - "constraint": true, - "primary": false, - "unique": true - }, - { - "columnNames": [ - "person_id" + "id" ], "composite": false, - "keyName": "email_address_person_id_index", - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "email_address_pkey", - "columnNames": [ - "id", - "address" - ], - "composite": true, "constraint": true, "primary": true, "unique": true @@ -3133,18 +3749,44 @@ ], "checks": [], "foreignKeys": { - "email_address_person_id_foreign": { - "constraintName": "email_address_person_id_foreign", + "importvorgang_person_id_foreign": { + "constraintName": "importvorgang_person_id_foreign", "columnNames": [ "person_id" ], - "localTableName": "public.email_address", + "localTableName": "public.importvorgang", "referencedColumnNames": [ "id" ], "referencedTableName": "public.person", "deleteRule": "set null", "updateRule": "cascade" + }, + "importvorgang_rolle_id_foreign": { + "constraintName": "importvorgang_rolle_id_foreign", + "columnNames": [ + "rolle_id" + ], + "localTableName": "public.importvorgang", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.rolle", + "deleteRule": "set null", + "updateRule": "cascade" + }, + "importvorgang_organisation_id_foreign": { + "constraintName": "importvorgang_organisation_id_foreign", + "columnNames": [ + "organisation_id" + ], + "localTableName": "public.importvorgang", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.organisation", + "deleteRule": "set null", + "updateRule": "cascade" } }, "nativeEnums": { @@ -3167,20 +3809,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -3272,6 +3900,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -3294,8 +3936,7 @@ "PERSON_SYNCHRONISIEREN", "CRON_DURCHFUEHREN", "PERSONEN_ANLEGEN", - "IMPORT_DURCHFUEHREN", - "PERSONEN_LESEN" + "IMPORT_DURCHFUEHREN" ] }, "service_provider_target_enum": { @@ -3360,8 +4001,26 @@ "length": 6, "mappedType": "datetime" }, - "name": { - "name": "name", + "importvorgang_id": { + "name": "importvorgang_id", + "type": "uuid", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "uuid" + }, + "nachname": { + "name": "nachname", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": false, + "mappedType": "string" + }, + "vorname": { + "name": "vorname", "type": "varchar(255)", "unsigned": false, "autoincrement": false, @@ -3369,59 +4028,58 @@ "nullable": false, "mappedType": "string" }, - "administered_by_schulstrukturknoten": { - "name": "administered_by_schulstrukturknoten", - "type": "uuid", + "klasse": { + "name": "klasse", + "type": "varchar(255)", + "unsigned": false, + "autoincrement": false, + "primary": false, + "nullable": true, + "mappedType": "string" + }, + "personalnummer": { + "name": "personalnummer", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "mappedType": "uuid" + "nullable": true, + "mappedType": "string" }, - "rollenart": { - "name": "rollenart", - "type": "rollen_art_enum", + "validation_errors": { + "name": "validation_errors", + "type": "text[]", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "nativeEnumName": "rollen_art_enum", - "enumItems": [ - "LERN", - "LEHR", - "EXTERN", - "ORGADMIN", - "LEIT", - "SYSADMIN" - ], - "mappedType": "enum" + "nullable": true, + "mappedType": "array" }, - "ist_technisch": { - "name": "ist_technisch", - "type": "boolean", + "username": { + "name": "username", + "type": "varchar(50)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "default": "false", - "mappedType": "boolean" + "nullable": true, + "length": 50, + "mappedType": "string" }, - "version": { - "name": "version", - "type": "bigint", + "password": { + "name": "password", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "default": "1", - "mappedType": "bigint" + "nullable": true, + "mappedType": "string" } }, - "name": "rolle", + "name": "importdataitem", "schema": "public", "indexes": [ { - "keyName": "rolle_pkey", + "keyName": "importdataitem_pkey", "columnNames": [ "id" ], @@ -3432,7 +4090,20 @@ } ], "checks": [], - "foreignKeys": {}, + "foreignKeys": { + "importdataitem_importvorgang_id_foreign": { + "constraintName": "importdataitem_importvorgang_id_foreign", + "columnNames": [ + "importvorgang_id" + ], + "localTableName": "public.importdataitem", + "referencedColumnNames": [ + "id" + ], + "referencedTableName": "public.importvorgang", + "updateRule": "cascade" + } + }, "nativeEnums": { "db_seed_status_enum": { "name": "db_seed_status_enum", @@ -3453,20 +4124,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -3558,6 +4215,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -3580,8 +4251,7 @@ "PERSON_SYNCHRONISIEREN", "CRON_DURCHFUEHREN", "PERSONEN_ANLEGEN", - "IMPORT_DURCHFUEHREN", - "PERSONEN_LESEN" + "IMPORT_DURCHFUEHREN" ] }, "service_provider_target_enum": { @@ -3646,8 +4316,8 @@ "length": 6, "mappedType": "datetime" }, - "person_id": { - "name": "person_id", + "importvorgang_id": { + "name": "importvorgang_id", "type": "uuid", "unsigned": false, "autoincrement": false, @@ -3655,35 +4325,26 @@ "nullable": false, "mappedType": "uuid" }, - "organisation_id": { - "name": "organisation_id", - "type": "uuid", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "mappedType": "uuid" - }, - "rolle_id": { - "name": "rolle_id", - "type": "uuid", + "nachname": { + "name": "nachname", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": false, - "mappedType": "uuid" + "mappedType": "string" }, - "referrer": { - "name": "referrer", + "vorname": { + "name": "vorname", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": true, + "nullable": false, "mappedType": "string" }, - "mandant": { - "name": "mandant", + "klasse": { + "name": "klasse", "type": "varchar(255)", "unsigned": false, "autoincrement": false, @@ -3691,119 +4352,49 @@ "nullable": true, "mappedType": "string" }, - "personenstatus": { - "name": "personenstatus", - "type": "personenstatus_enum", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "nativeEnumName": "personenstatus_enum", - "enumItems": [ - "AKTIV" - ], - "mappedType": "enum" - }, - "jahrgangsstufe": { - "name": "jahrgangsstufe", - "type": "jahrgangsstufe_enum", - "unsigned": false, - "autoincrement": false, - "primary": false, - "nullable": true, - "nativeEnumName": "jahrgangsstufe_enum", - "enumItems": [ - "01", - "02", - "03", - "04", - "05", - "06", - "07", - "08", - "09", - "10" - ], - "mappedType": "enum" - }, - "sichtfreigabe": { - "name": "sichtfreigabe", + "personalnummer": { + "name": "personalnummer", "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, - "default": "'nein'", "mappedType": "string" }, - "loeschung_zeitpunkt": { - "name": "loeschung_zeitpunkt", - "type": "timestamptz", + "validation_errors": { + "name": "validation_errors", + "type": "text[]", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, - "length": 6, - "mappedType": "datetime" + "mappedType": "array" }, - "revision": { - "name": "revision", - "type": "varchar(255)", + "username": { + "name": "username", + "type": "varchar(50)", "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, - "default": "'1'", + "nullable": true, + "length": 50, "mappedType": "string" }, - "befristung": { - "name": "befristung", - "type": "timestamptz", + "password": { + "name": "password", + "type": "varchar(255)", "unsigned": false, "autoincrement": false, "primary": false, "nullable": true, - "length": 6, - "mappedType": "datetime" + "mappedType": "string" } }, - "name": "personenkontext", + "name": "importdataitem", "schema": "public", "indexes": [ { - "columnNames": [ - "person_id" - ], - "composite": false, - "keyName": "personenkontext_person_id_index", - "constraint": false, - "primary": false, - "unique": false - }, - { - "columnNames": [ - "organisation_id" - ], - "composite": false, - "keyName": "personenkontext_organisation_id_index", - "constraint": false, - "primary": false, - "unique": false - }, - { - "keyName": "personenkontext_person_id_organisation_id_rolle_id_unique", - "columnNames": [ - "person_id", - "organisation_id", - "rolle_id" - ], - "composite": true, - "constraint": true, - "primary": false, - "unique": true - }, - { - "keyName": "personenkontext_pkey", + "keyName": "importdataitem_pkey", "columnNames": [ "id" ], @@ -3815,28 +4406,16 @@ ], "checks": [], "foreignKeys": { - "personenkontext_person_id_foreign": { - "constraintName": "personenkontext_person_id_foreign", - "columnNames": [ - "person_id" - ], - "localTableName": "public.personenkontext", - "referencedColumnNames": [ - "id" - ], - "referencedTableName": "public.person", - "deleteRule": "cascade" - }, - "personenkontext_rolle_id_foreign": { - "constraintName": "personenkontext_rolle_id_foreign", + "importdataitem_importvorgang_id_foreign": { + "constraintName": "importdataitem_importvorgang_id_foreign", "columnNames": [ - "rolle_id" + "importvorgang_id" ], - "localTableName": "public.personenkontext", + "localTableName": "public.importdataitem", "referencedColumnNames": [ "id" ], - "referencedTableName": "public.rolle", + "referencedTableName": "public.importvorgang", "updateRule": "cascade" } }, @@ -3860,20 +4439,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -3965,6 +4530,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -4108,20 +4687,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -4213,6 +4778,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -4366,20 +4945,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -4471,6 +5036,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -4692,20 +5271,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -4797,6 +5362,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -5041,20 +5620,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -5146,6 +5711,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -5286,20 +5865,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -5391,6 +5956,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -5530,20 +6109,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -5635,6 +6200,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -5821,20 +6400,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -5926,6 +6491,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", @@ -6004,20 +6583,6 @@ "SERVICE_PROVIDER" ] }, - "import_status_enum": { - "name": "import_status_enum", - "schema": "public", - "items": [ - "CANCELLED", - "COMPLETED", - "FAILED", - "FINISHED", - "INPROGRESS", - "INVALID", - "STARTED", - "VALID" - ] - }, "organisations_typ_enum": { "name": "organisations_typ_enum", "schema": "public", @@ -6109,6 +6674,20 @@ "10" ] }, + "import_status_enum": { + "name": "import_status_enum", + "schema": "public", + "items": [ + "CANCELLED", + "COMPLETED", + "FAILED", + "FINISHED", + "INPROGRESS", + "INVALID", + "STARTED", + "VALID" + ] + }, "rollen_merkmal_enum": { "name": "rollen_merkmal_enum", "schema": "public", diff --git a/migrations/Migration20241218233107-S.ts b/migrations/Migration20241218233107-S.ts new file mode 100644 index 000000000..41f87c316 --- /dev/null +++ b/migrations/Migration20241218233107-S.ts @@ -0,0 +1,30 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20241218233107 extends Migration { + public async up(): Promise { + this.addSql('alter table "importvorgang" drop column "import_by_person_id";'); + + this.addSql( + 'alter table "importvorgang" add column "person_id" uuid null, add column "total_data_item_imported" int not null;', + ); + this.addSql( + 'alter table "importvorgang" add constraint "importvorgang_person_id_foreign" foreign key ("person_id") references "person" ("id") on update cascade on delete set null;', + ); + this.addSql( + 'alter table "importvorgang" add constraint "importvorgang_rolle_id_foreign" foreign key ("rolle_id") references "rolle" ("id") on update cascade on delete set null;', + ); + this.addSql( + 'alter table "importvorgang" add constraint "importvorgang_organisation_id_foreign" foreign key ("organisation_id") references "organisation" ("id") on update cascade on delete set null;', + ); + } + + public override async down(): Promise { + this.addSql('alter table "importvorgang" drop constraint "importvorgang_person_id_foreign";'); + this.addSql('alter table "importvorgang" drop constraint "importvorgang_rolle_id_foreign";'); + this.addSql('alter table "importvorgang" drop constraint "importvorgang_organisation_id_foreign";'); + + this.addSql('alter table "importvorgang" drop column "person_id", drop column "total_data_item_imported";'); + + this.addSql('alter table "importvorgang" add column "import_by_person_id" uuid null;'); + } +} diff --git a/src/modules/import/api/import.controller.integration-spec.ts b/src/modules/import/api/import.controller.integration-spec.ts index 50daaed0b..579ea06f1 100644 --- a/src/modules/import/api/import.controller.integration-spec.ts +++ b/src/modules/import/api/import.controller.integration-spec.ts @@ -786,7 +786,7 @@ describe('Import API', () => { describe('/GET importstatus by id', () => { it('should return 200 OK with import ststus', async () => { const importVorgang: ImportVorgang = await importVorgangRepository.save( - DoFactory.createImportVorgang(false, { status: ImportStatus.COMPLETED }), + DoFactory.createImportVorgang(false, { status: ImportStatus.COMPLETED, totalDataItemImported: 100 }), ); const response: Response = await request(app.getHttpServer() as App) @@ -794,7 +794,12 @@ describe('Import API', () => { .send(); expect(response.status).toBe(200); - expect(response.body).toEqual({ status: ImportStatus.COMPLETED } as ImportVorgangStatusResponse); + expect(response.body).toBeInstanceOf(Object); + expect(response.body).toEqual({ + dataItemCount: 100, + status: ImportStatus.COMPLETED, + totalDataItemImported: 100, + } as ImportVorgangStatusResponse); }); it('should return 404 if importvorgang does not exist', async () => { diff --git a/src/modules/import/api/importvorgang-status.response.ts b/src/modules/import/api/importvorgang-status.response.ts index 1d1023687..d7651e1c9 100644 --- a/src/modules/import/api/importvorgang-status.response.ts +++ b/src/modules/import/api/importvorgang-status.response.ts @@ -3,10 +3,18 @@ import { ImportStatus, ImportStatusName } from '../domain/import.enums.js'; import { ImportVorgang } from '../domain/import-vorgang.js'; export class ImportVorgangStatusResponse { + @ApiProperty() + public dataItemCount: number; + @ApiProperty({ enum: ImportStatus, enumName: ImportStatusName }) public status: ImportStatus; + @ApiProperty() + public totalDataItemImported: number; + public constructor(importVorgang: ImportVorgang) { + this.dataItemCount = importVorgang.dataItemCount; this.status = importVorgang.status; + this.totalDataItemImported = importVorgang.totalDataItemImported; } } diff --git a/src/modules/import/domain/import-event-handler.spec.ts b/src/modules/import/domain/import-event-handler.spec.ts index 77d3f2c77..697e2bddf 100644 --- a/src/modules/import/domain/import-event-handler.spec.ts +++ b/src/modules/import/domain/import-event-handler.spec.ts @@ -23,6 +23,8 @@ import { ClassLogger } from '../../../core/logging/class-logger.js'; import { ImportExecutedEvent } from '../../../shared/events/import-executed.event.js'; import { RolleNurAnPassendeOrganisationError } from '../../personenkontext/specification/error/rolle-nur-an-passende-organisation.js'; import { ImportPasswordEncryptor } from './import-password-encryptor.js'; +import { ImportDomainError } from './import-domain.error.js'; +import { ImportStatus } from './import.enums.js'; describe('ImportEventHandler', () => { let module: TestingModule; @@ -167,13 +169,21 @@ describe('ImportEventHandler', () => { personenkontextCreationServiceMock.createPersonWithPersonenkontexte.mockResolvedValueOnce(error); organisationRepoMock.findById.mockResolvedValueOnce(schule); - await sut.handleExecuteImport(event); + const importDomainError: DomainError = new ImportDomainError( + `The creation of person with personenkontexte for the import transaction:${importvorgang.id} failed`, + importvorgang.id, + ); + + await expect(sut.handleExecuteImport(event)).rejects.toThrowError(importDomainError); expect(loggerMock.error).toHaveBeenCalledWith( `System hat versucht einen neuen Benutzer für ${importDataItem.vorname} ${importDataItem.nachname} anzulegen. Fehler: ${error.message}`, ); expect(importDataRepositoryMock.save).not.toHaveBeenCalled(); - expect(importVorgangRepositoryMock.save).not.toHaveBeenCalled(); + expect(importVorgangRepositoryMock.save).toHaveBeenCalledWith({ + ...importvorgang, + status: ImportStatus.FAILED, + }); }); it('should log error if the person has no start password', async () => { @@ -206,12 +216,20 @@ describe('ImportEventHandler', () => { personenkontextCreationServiceMock.createPersonWithPersonenkontexte.mockResolvedValueOnce(pks); organisationRepoMock.findById.mockResolvedValueOnce(schule); - await sut.handleExecuteImport(event); + const error: DomainError = new ImportDomainError( + `The creation for a password for the person with ID ${person.id} for the import transaction:${importvorgang.id} has failed`, + importvorgang.id, + ); + + await expect(sut.handleExecuteImport(event)).rejects.toThrowError(error); expect(person.newPassword).toBeUndefined(); expect(loggerMock.error).toHaveBeenCalledWith(`Person with ID ${person.id} has no start password!`); expect(importDataRepositoryMock.save).not.toHaveBeenCalled(); - expect(importVorgangRepositoryMock.save).not.toHaveBeenCalled(); + expect(importVorgangRepositoryMock.save).toHaveBeenCalledWith({ + ...importvorgang, + status: ImportStatus.FAILED, + }); }); it('should log info if the person and PKs were saved successfully', async () => { @@ -258,8 +276,8 @@ describe('ImportEventHandler', () => { expect(loggerMock.info).toHaveBeenCalledWith( `System hat einen neuen Benutzer ${person.referrer} (${person.id}) angelegt.`, ); - expect(importDataRepositoryMock.save).toHaveBeenCalled(); - expect(importVorgangRepositoryMock.save).toHaveBeenCalledTimes(1); + expect(importDataRepositoryMock.replaceAll).toHaveBeenCalled(); + expect(importVorgangRepositoryMock.save).toHaveBeenCalledTimes(2); }); }); }); diff --git a/src/modules/import/domain/import-event-handler.ts b/src/modules/import/domain/import-event-handler.ts index b8c31fa2d..0094263a9 100644 --- a/src/modules/import/domain/import-event-handler.ts +++ b/src/modules/import/domain/import-event-handler.ts @@ -18,12 +18,16 @@ import { OrganisationByIdAndName } from './import-workflow.js'; import { Injectable } from '@nestjs/common'; import { ClassLogger } from '../../../core/logging/class-logger.js'; import { ImportPasswordEncryptor } from './import-password-encryptor.js'; +import { PersonPermissions } from '../../authentication/domain/person-permissions.js'; +import { ImportDomainError } from './import-domain.error.js'; @Injectable() export class ImportEventHandler { public selectedOrganisationId!: string; public selectedRolleId!: string; + private readonly USER_IMPORT_BATCH_SIZE: number = 25; + public constructor( private readonly organisationRepository: OrganisationRepository, private readonly importDataRepository: ImportDataRepository, @@ -51,7 +55,6 @@ export class ImportEventHandler { } }); - const importDataItemsWithLoginInfo: ImportDataItem[] = []; const importvorgangId: string = event.importVorgangId; const importVorgang: Option> = await this.importVorgangRepository.findById(importvorgangId); if (!importVorgang) { @@ -64,15 +67,42 @@ export class ImportEventHandler { return this.logger.error(`No import data itemns found for Importvorgang:${importvorgangId}`); } + while (importDataItems.length > 0) { + const dataItemsToImport: ImportDataItem[] = importDataItems.splice(0, this.USER_IMPORT_BATCH_SIZE); + // eslint-disable-next-line no-await-in-loop + await this.savePersonWithPersonenkontext( + importVorgang, + dataItemsToImport, + klassenByIDandName, + event.permissions, + ); + + importVorgang.incrementTotalImportDataItems(dataItemsToImport.length); + // eslint-disable-next-line no-await-in-loop + await this.importVorgangRepository.save(importVorgang); + } + + importVorgang.finish(); + await this.importVorgangRepository.save(importVorgang); + } + + private async savePersonWithPersonenkontext( + importVorgang: ImportVorgang, + dataItems: ImportDataItem[], + klassenByIDandName: OrganisationByIdAndName[], + permissions: PersonPermissions, + ): Promise { + const importDataItemsWithLoginInfo: ImportDataItem[] = []; //We must create every peron individually otherwise it cannot assign the correct username when we have multiple users with the same name - /* eslint-disable no-await-in-loop */ - for (const importDataItem of importDataItems) { + + for (const importDataItem of dataItems) { const klasse: OrganisationByIdAndName | undefined = klassenByIDandName.find( (organisationByIdAndName: OrganisationByIdAndName) => organisationByIdAndName.name === importDataItem.klasse, ); if (!klasse) { importVorgang.fail(); + // eslint-disable-next-line no-await-in-loop await this.importVorgangRepository.save(importVorgang); throw new EntityNotFoundError('Organisation', importDataItem.klasse, [ @@ -92,8 +122,9 @@ export class ImportEventHandler { ]; const savedPersonWithPersonenkontext: DomainError | PersonPersonenkontext = + // eslint-disable-next-line no-await-in-loop await this.personenkontextCreationService.createPersonWithPersonenkontexte( - event.permissions, + permissions, importDataItem.vorname, importDataItem.nachname, createPersonenkontexte, @@ -104,14 +135,29 @@ export class ImportEventHandler { `System hat einen neuen Benutzer ${savedPersonWithPersonenkontext.person.referrer} (${savedPersonWithPersonenkontext.person.id}) angelegt.`, ); } else { - return this.logger.error( + this.logger.error( `System hat versucht einen neuen Benutzer für ${importDataItem.vorname} ${importDataItem.nachname} anzulegen. Fehler: ${savedPersonWithPersonenkontext.message}`, ); + + importVorgang.fail(); + // eslint-disable-next-line no-await-in-loop + await this.importVorgangRepository.save(importVorgang); + + throw new ImportDomainError( + `The creation of person with personenkontexte for the import transaction:${importVorgang.id} failed`, + importVorgang.id, + ); } if (!savedPersonWithPersonenkontext.person.newPassword) { - return this.logger.error( - `Person with ID ${savedPersonWithPersonenkontext.person.id} has no start password!`, + this.logger.error(`Person with ID ${savedPersonWithPersonenkontext.person.id} has no start password!`); + + importVorgang.fail(); + // eslint-disable-next-line no-await-in-loop + await this.importVorgangRepository.save(importVorgang); + throw new ImportDomainError( + `The creation for a password for the person with ID ${savedPersonWithPersonenkontext.person.id} for the import transaction:${importVorgang.id} has failed`, + importVorgang.id, ); } @@ -127,21 +173,14 @@ export class ImportEventHandler { importDataItem.personalnummer, importDataItem.validationErrors, savedPersonWithPersonenkontext.person.referrer, + // eslint-disable-next-line no-await-in-loop await this.importPasswordEncryptor.encryptPassword( savedPersonWithPersonenkontext.person.newPassword, ), ), ); } - /* eslint-disable no-await-in-loop */ - - await Promise.allSettled( - importDataItemsWithLoginInfo.map(async (importDataItem: ImportDataItem) => - this.importDataRepository.save(importDataItem), - ), - ); - importVorgang.finish(); - await this.importVorgangRepository.save(importVorgang); + await this.importDataRepository.replaceAll(importDataItemsWithLoginInfo); } } diff --git a/src/modules/import/domain/import-vorgang.ts b/src/modules/import/domain/import-vorgang.ts index 263301ae9..0add01f8c 100644 --- a/src/modules/import/domain/import-vorgang.ts +++ b/src/modules/import/domain/import-vorgang.ts @@ -10,6 +10,7 @@ export class ImportVorgang { public organisationsname: string, public dataItemCount: number, public status: Persisted, + public totalDataItemImported: number, public importByPersonId?: string, public rolleId?: string, public organisationId?: string, @@ -24,6 +25,7 @@ export class ImportVorgang { organisationsname: string, dataItemCount: number, status: ImportStatus, + totalDataItemImported: number, importByPersonId?: string, rolleId?: string, organisationId?: string, @@ -37,6 +39,7 @@ export class ImportVorgang { organisationsname, dataItemCount, status, + totalDataItemImported, importByPersonId, rolleId, organisationId, @@ -61,6 +64,7 @@ export class ImportVorgang { organisationsname, dataItemCount, undefined, + 0, importByPersonId, rolleId, organisationId, @@ -90,4 +94,8 @@ export class ImportVorgang { public finish(): void { this.status = ImportStatus.FINISHED; } + + public incrementTotalImportDataItems(totalDataItemImported: number): void { + this.totalDataItemImported += totalDataItemImported; + } } diff --git a/src/modules/import/domain/import-workflow.ts b/src/modules/import/domain/import-workflow.ts index 1c465eef3..939483459 100644 --- a/src/modules/import/domain/import-workflow.ts +++ b/src/modules/import/domain/import-workflow.ts @@ -186,48 +186,55 @@ export class ImportWorkflow { ); const savedImportvorgang: ImportVorgang = await this.importVorgangRepository.save(importVorgang); + const totalImportDataItems: number = parsedDataItems.length; + /* eslint-disable no-await-in-loop */ + while (parsedDataItems.length > 0) { + const dataItems: CSVImportDataItemDTO[] = parsedDataItems.splice(0, 50); - const promises: Promise>[] = parsedDataItems.map((value: CSVImportDataItemDTO) => { - const importDataItemErrors: string[] = []; + const importDataItems: ImportDataItem[] = dataItems.map((value: CSVImportDataItemDTO) => { + const importDataItemErrors: string[] = []; - // Validate object - for (const error of validateSync(value, { forbidUnknownValues: true })) { - if (error.constraints) { - for (const message of Object.values(error.constraints)) { - importDataItemErrors.push(message); + // Validate object + for (const error of validateSync(value, { forbidUnknownValues: true })) { + if (error.constraints) { + for (const message of Object.values(error.constraints)) { + importDataItemErrors.push(message); + } } } - } - if (value.klasse) { - const klasse: OrganisationByIdAndName | undefined = klassenByIDandName.find( - (organisationByIdAndName: OrganisationByIdAndName) => organisationByIdAndName.name === value.klasse, //Klassennamen sind case sensitive - ); + if (value.klasse) { + const klasse: OrganisationByIdAndName | undefined = klassenByIDandName.find( + (organisationByIdAndName: OrganisationByIdAndName) => + organisationByIdAndName.name === value.klasse, //Klassennamen sind case sensitive + ); - //Only check if the Klasse exists - //Do not need to check if the Klasse can be assigned to rolle for now, because we only impport RollenArt=LERN - if (!klasse) { - importDataItemErrors.push(ImportDomainErrorI18nTypes.IMPORT_DATA_ITEM_KLASSE_NOT_FOUND); + //Only check if the Klasse exists + //Do not need to check if the Klasse can be assigned to rolle for now, because we only impport RollenArt=LERN + if (!klasse) { + importDataItemErrors.push(ImportDomainErrorI18nTypes.IMPORT_DATA_ITEM_KLASSE_NOT_FOUND); + } } - } - const importDataItem: ImportDataItem = ImportDataItem.createNew( - savedImportvorgang.id, - value.nachname, - value.vorname, - value.klasse, - value.personalnummer, - importDataItemErrors, - ); + const importDataItem: ImportDataItem = ImportDataItem.createNew( + savedImportvorgang.id, + value.nachname, + value.vorname, + value.klasse, + value.personalnummer, + importDataItemErrors, + ); - if (importDataItemErrors.length > 0) { - invalidImportDataItems.push(importDataItem); - } + if (importDataItemErrors.length > 0) { + invalidImportDataItems.push(importDataItem); + } - return this.importDataRepository.save(importDataItem); - }); + return importDataItem; + }); - await Promise.all(promises); + await this.importDataRepository.createAll(importDataItems); + } + /* eslint-disable no-await-in-loop */ savedImportvorgang.validate(invalidImportDataItems.length); await this.importVorgangRepository.save(savedImportvorgang); @@ -235,7 +242,7 @@ export class ImportWorkflow { return { importVorgangId: savedImportvorgang.id, isValid: invalidImportDataItems.length === 0, - totalImportDataItems: parsedDataItems.length, + totalImportDataItems: totalImportDataItems, totalInvalidImportDataItems: invalidImportDataItems.length, invalidImportDataItems, }; @@ -250,11 +257,6 @@ export class ImportWorkflow { }; } - // Get all import data items with importvorgangId - //Optimierung: für das folgeTicket mit z.B. 800 Lehrer , muss der thread so manipuliert werden (sobald ein Resultat da ist, wird der nächste request abgeschickt) - //Optimierung: Process 10 dataItems at time for createPersonWithPersonenkontexte - // const offset: number = 0; - // const limit: number = 10; const importVorgang: Option> = await this.importVorgangRepository.findById(importvorgangId); if (!importVorgang) { this.logger.warning(`Importvorgang: ${importvorgangId} not found`); diff --git a/src/modules/import/persistence/import-data.repository.integration-spec.ts b/src/modules/import/persistence/import-data.repository.integration-spec.ts index 40cf69475..272ee7142 100644 --- a/src/modules/import/persistence/import-data.repository.integration-spec.ts +++ b/src/modules/import/persistence/import-data.repository.integration-spec.ts @@ -12,6 +12,8 @@ import { ImportDataItemEntity } from './import-data-item.entity.js'; import { ImportDataItem } from '../domain/import-data-item.js'; import { ImportVorgangRepository } from './import-vorgang.repository.js'; import { ImportVorgang } from '../domain/import-vorgang.js'; +import { DomainError } from '../../../shared/error/domain.error.js'; +import { ImportDomainError } from '../domain/import-domain.error.js'; describe('ImportDataRepository', () => { let module: TestingModule; @@ -234,4 +236,108 @@ describe('ImportDataRepository', () => { expect(findTotal).toBe(0); }); }); + + describe('createAll', () => { + it('should create all importDataItems', async () => { + const importvorgangId: string = (await importVorgangRepository.save(DoFactory.createImportVorgang(false))) + .id; + const importDataItems: ImportDataItem[] = [ + DoFactory.createImportDataItem(false, { importvorgangId }), + DoFactory.createImportDataItem(false, { importvorgangId }), + ]; + + const savedImportDataItems: string[] = await sut.createAll(importDataItems); + + expect( + savedImportDataItems.every((savedImportDataItem: string) => savedImportDataItem !== undefined), + ).toBeTruthy(); + expect(savedImportDataItems.length).toBe(importDataItems.length); + }); + }); + + describe('replaceAll', () => { + let importDataItem1: ImportDataItem; + let importDataItem2: ImportDataItem; + let importvorgangId: string; + + beforeEach(async () => { + importvorgangId = (await importVorgangRepository.save(DoFactory.createImportVorgang(false))).id; + importDataItem1 = await sut.save(DoFactory.createImportDataItem(false, { importvorgangId })); + importDataItem2 = await sut.save(DoFactory.createImportDataItem(false, { importvorgangId })); + }); + + it('should replace all when found', async () => { + const newUsername: string = faker.internet.userName(); + const newUsername2: string = faker.internet.userName(); + const pass1: string = faker.internet.password({ length: 32 }); + const pass2: string = faker.internet.password({ length: 32 }); + const personalnummer: string = faker.random.alphaNumeric(7); + + const updateImportDataItems: ImportDataItem[] = [ + { + ...importDataItem1, + username: newUsername, + password: pass1, + personalnummer: personalnummer, + validationErrors: [], + }, + { + ...importDataItem2, + username: newUsername2, + password: pass2, + validationErrors: [], + }, + ]; + const result: ImportDataItem[] = await sut.replaceAll(updateImportDataItems); + + expect(result.length).toBe(2); + expect(result[0]).toMatchObject({ + id: importDataItem1.id, + importvorgangId: importvorgangId, + klasse: importDataItem1.klasse, + nachname: importDataItem1.nachname, + vorname: importDataItem1.vorname, + personalnummer: personalnummer, + validationErrors: [], + username: newUsername, + password: pass1, + }); + + expect(result[1]).toMatchObject({ + id: importDataItem2.id, + importvorgangId: importvorgangId, + klasse: importDataItem2.klasse, + nachname: importDataItem2.nachname, + vorname: importDataItem2.vorname, + personalnummer: null, + validationErrors: [], + username: newUsername2, + password: pass2, + }); + }); + + it('should throw an ImportDomainError if one data-item is not found', async () => { + const updateImportDataItems: ImportDataItem[] = [ + { + ...importDataItem1, + validationErrors: ['error1'], + }, + { + ...importDataItem2, + validationErrors: ['error1'], + }, + { + ...DoFactory.createImportDataItem(true, { importvorgangId }), + validationErrors: ['error1'], + }, + ]; + + const importDomainError: DomainError = new ImportDomainError( + `Update all has failed because not all entities were found. importDataItemsCount:${updateImportDataItems.length}, numberOfEntitiesFound:${2}`, + 'IMPORT_DATA_ITEM_NOT_FOUND', + ); + + await expect(sut.replaceAll(updateImportDataItems)).rejects.toThrowError(importDomainError); + }); + }); }); diff --git a/src/modules/import/persistence/import-data.repository.ts b/src/modules/import/persistence/import-data.repository.ts index 2909ade7e..305817cbf 100644 --- a/src/modules/import/persistence/import-data.repository.ts +++ b/src/modules/import/persistence/import-data.repository.ts @@ -3,6 +3,7 @@ import { Injectable } from '@nestjs/common'; import { ImportDataItemEntity } from './import-data-item.entity.js'; import { ImportDataItemScope } from './import-data-item.scope.js'; import { ImportDataItem } from '../domain/import-data-item.js'; +import { ImportDomainError } from '../domain/import-domain.error.js'; export function mapAggregateToData(importDataItem: ImportDataItem): RequiredEntityData { return { @@ -36,7 +37,6 @@ export function mapEntityToAggregate(entity: ImportDataItemEntity): ImportDataIt export class ImportDataRepository { public constructor(private readonly em: EntityManager) {} - //Optimierung: alle 50 Datensätze mit einem Call persistieren public async save(importDataItem: ImportDataItem): Promise> { if (importDataItem.id) { return this.update(importDataItem); @@ -66,6 +66,39 @@ export class ImportDataRepository { await this.em.nativeDelete(ImportDataItemEntity, { importvorgangId: importvorgangId }); } + public async createAll(importDataItems: ImportDataItem[]): Promise { + const entities: ImportDataItemEntity[] = importDataItems.map((importDataItem: ImportDataItem) => { + return this.em.create(ImportDataItemEntity, mapAggregateToData(importDataItem)); + }); + + await this.em.persistAndFlush(entities); + + return entities.map((entity: ImportDataItemEntity) => entity.id); + } + + /** + * Replace import data entities matching the ids with the given import data items. + * @param importDataItems all the import data items will be replaced in the DB. + * @returns + */ + + public async replaceAll(importDataItems: ImportDataItem[]): Promise[]> { + const ids: string[] = importDataItems.map((importDataItem: ImportDataItem) => importDataItem.id); + + const entitiesCount: number = await this.em.count(ImportDataItemEntity, { id: { $in: ids } }); + + if (entitiesCount !== importDataItems.length) { + throw new ImportDomainError( + `Update all has failed because not all entities were found. importDataItemsCount:${importDataItems.length}, numberOfEntitiesFound:${entitiesCount}`, + 'IMPORT_DATA_ITEM_NOT_FOUND', + ); + } + + const updateResult: ImportDataItemEntity[] = await this.em.upsertMany(ImportDataItemEntity, importDataItems); + + return updateResult.map((entity: ImportDataItemEntity) => mapEntityToAggregate(entity)); + } + private async create(importDataItem: ImportDataItem): Promise> { const entity: ImportDataItemEntity = this.em.create(ImportDataItemEntity, mapAggregateToData(importDataItem)); diff --git a/src/modules/import/persistence/import-vorgang.entity.ts b/src/modules/import/persistence/import-vorgang.entity.ts index 28c966cfd..e688f8955 100644 --- a/src/modules/import/persistence/import-vorgang.entity.ts +++ b/src/modules/import/persistence/import-vorgang.entity.ts @@ -1,23 +1,44 @@ import { TimestampedEntity } from '../../../persistence/timestamped.entity.js'; -import { Entity, Enum, Opt, Property } from '@mikro-orm/core'; +import { Entity, Enum, ManyToOne, Opt, Property, Ref } from '@mikro-orm/core'; import { ImportStatus } from '../domain/import.enums.js'; +import { RolleEntity } from '../../rolle/entity/rolle.entity.js'; +import { OrganisationEntity } from '../../organisation/persistence/organisation.entity.js'; +import { PersonEntity } from '../../person/persistence/person.entity.js'; @Entity({ tableName: 'importvorgang' }) export class ImportVorgangEntity extends TimestampedEntity { - @Property({ columnType: 'uuid', nullable: true }) - public readonly importByPersonId?: string; + @ManyToOne({ + fieldName: 'person_id', + columnType: 'uuid', + ref: true, + nullable: true, + entity: () => PersonEntity, + }) + public readonly importByPersonId?: Ref; @Property() public readonly importByUsername!: string; - @Property({ columnType: 'uuid', nullable: true }) - public readonly rolleId?: string; + @ManyToOne({ + fieldName: 'rolle_id', + columnType: 'uuid', + ref: true, + nullable: true, + entity: () => RolleEntity, + }) + public readonly rolleId?: Ref; @Property() public rollename!: string; - @Property({ columnType: 'uuid', nullable: true }) - public readonly organisationId?: string; + @ManyToOne({ + fieldName: 'organisation_id', + columnType: 'uuid', + ref: true, + nullable: true, + entity: () => OrganisationEntity, + }) + public readonly organisationId?: Ref; @Property() public organisationsname!: string; @@ -31,4 +52,7 @@ export class ImportVorgangEntity extends TimestampedEntity { onCreate: () => ImportStatus.STARTED, }) public status!: ImportStatus & Opt; + + @Property({ type: 'int' }) + public totalDataItemImported!: number; } diff --git a/src/modules/import/persistence/import-vorgang.repository.integration-spec.ts b/src/modules/import/persistence/import-vorgang.repository.integration-spec.ts index 24b47180d..0b8f9bf87 100644 --- a/src/modules/import/persistence/import-vorgang.repository.integration-spec.ts +++ b/src/modules/import/persistence/import-vorgang.repository.integration-spec.ts @@ -6,6 +6,7 @@ import { DatabaseTestModule, DEFAULT_TIMEOUT_FOR_TESTCONTAINERS, DoFactory, + MapperTestModule, } from '../../../../test/utils/index.js'; import { ImportQueryOptions, @@ -18,32 +19,130 @@ import { ImportVorgangEntity } from './import-vorgang.entity.js'; import { ImportStatus } from '../domain/import.enums.js'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { PersonPermissions } from '../../authentication/domain/person-permissions.js'; +import { PersonFactory } from '../../person/domain/person.factory.js'; +import { PersonRepository } from '../../person/persistence/person.repository.js'; +import { KeycloakUserService } from '../../keycloak-administration/index.js'; +import { DomainError } from '../../../shared/error/domain.error.js'; +import { generatePassword } from '../../../shared/util/password-generator.js'; +import { Person } from '../../person/domain/person.js'; +import { UsernameGeneratorService } from '../../person/domain/username-generator.service.js'; +import { UserLockRepository } from '../../keycloak-administration/repository/user-lock.repository.js'; +import { EventService } from '../../../core/eventbus/index.js'; +import { ClassLogger } from '../../../core/logging/class-logger.js'; +import { OrganisationEntity } from '../../organisation/persistence/organisation.entity.js'; +import { RolleRepo } from '../../rolle/repo/rolle.repo.js'; +import { RolleModule } from '../../rolle/rolle.module.js'; +import { OrganisationsTyp } from '../../organisation/domain/organisation.enums.js'; +import { Rolle } from '../../rolle/domain/rolle.js'; +import { OrganisationModule } from '../../organisation/organisation.module.js'; +import { RollenArt } from '../../rolle/domain/rolle.enums.js'; describe('ImportVorgangRepository', () => { let module: TestingModule; let sut: ImportVorgangRepository; let orm: MikroORM; let em: EntityManager; + let personFactory: PersonFactory; + let personRepository: PersonRepository; + let rolleRepo: RolleRepo; beforeAll(async () => { module = await Test.createTestingModule({ - imports: [ConfigTestModule, DatabaseTestModule.forRoot({ isDatabaseRequired: true })], - providers: [ImportVorgangRepository], + imports: [ + RolleModule, + OrganisationModule, + MapperTestModule, + ConfigTestModule, + DatabaseTestModule.forRoot({ isDatabaseRequired: true }), + ], + providers: [ + ImportVorgangRepository, + PersonFactory, + PersonRepository, + UsernameGeneratorService, + { + provide: EventService, + useValue: createMock(), + }, + { + provide: ClassLogger, + useValue: createMock(), + }, + { + provide: KeycloakUserService, + useValue: createMock({ + create: () => + Promise.resolve({ + ok: true, + value: faker.string.uuid(), + }), + setPassword: () => + Promise.resolve({ + ok: true, + value: faker.string.alphanumeric(16), + }), + }), + }, + { + provide: UserLockRepository, + useValue: createMock(), + }, + ], }).compile(); sut = module.get(ImportVorgangRepository); orm = module.get(MikroORM); em = module.get(EntityManager); + personFactory = module.get(PersonFactory); + personRepository = module.get(PersonRepository); + rolleRepo = module.get(RolleRepo); await DatabaseTestModule.setupDatabase(orm); }, DEFAULT_TIMEOUT_FOR_TESTCONTAINERS); + async function createPerson(): Promise> { + const personResult: Person | DomainError = await personFactory.createNew({ + vorname: faker.person.firstName(), + familienname: faker.person.lastName(), + username: faker.internet.userName(), + password: generatePassword(), + }); + if (personResult instanceof DomainError) { + throw personResult; + } + const person: Person | DomainError = await personRepository.create(personResult); + if (person instanceof DomainError) { + throw person; + } + + return person; + } + + async function createOrga(): Promise { + const organisation: OrganisationEntity = new OrganisationEntity(); + organisation.typ = OrganisationsTyp.SCHULE; + await em.persistAndFlush(organisation); + await em.findOneOrFail(OrganisationEntity, { id: organisation.id }); + return organisation.id; + } + + async function createRolle(orgaId: string): Promise> { + const rolle: Rolle | DomainError = await rolleRepo.save( + DoFactory.createRolle(false, { + administeredBySchulstrukturknoten: orgaId, + rollenart: RollenArt.LERN, + }), + ); + if (rolle instanceof DomainError) throw Error(); + return rolle; + } + afterAll(async () => { + await orm.close(); await module.close(); }); beforeEach(async () => { await DatabaseTestModule.clearDatabase(orm); - jest.resetAllMocks(); }); it('should be defined', () => { @@ -61,6 +160,7 @@ describe('ImportVorgangRepository', () => { faker.lorem.word(), 100, ImportStatus.STARTED, + 0, faker.string.uuid(), faker.string.uuid(), faker.string.uuid(), @@ -72,6 +172,7 @@ describe('ImportVorgangRepository', () => { 'organisationsname', 'dataItemCount', 'status', + 'totalDataItemImported', 'importByPersonId', 'rolleId', 'organisationId', @@ -99,7 +200,15 @@ describe('ImportVorgangRepository', () => { describe('save', () => { it('should create a new ImportVorgang', async () => { - const importVorgang: ImportVorgang = DoFactory.createImportVorgang(false); + const person: Person = await createPerson(); + const organisationId: string = await createOrga(); + const rolle: Rolle = await createRolle(organisationId); + + const importVorgang: ImportVorgang = DoFactory.createImportVorgang(false, { + importByPersonId: person.id, + rolleId: rolle.id, + organisationId: organisationId, + }); const result: ImportVorgang = await sut.save(importVorgang); @@ -107,7 +216,15 @@ describe('ImportVorgangRepository', () => { }); it('should update an existing ImportVorgang', async () => { - const importVorgang: ImportVorgang = DoFactory.createImportVorgang(false); + const person: Person = await createPerson(); + const organisationId: string = await createOrga(); + const rolle: Rolle = await createRolle(organisationId); + + const importVorgang: ImportVorgang = DoFactory.createImportVorgang(false, { + importByPersonId: person.id, + rolleId: rolle.id, + organisationId: organisationId, + }); const createdImportVorgang: ImportVorgang = await sut.save(importVorgang); createdImportVorgang.status = ImportStatus.VALID; @@ -119,20 +236,6 @@ describe('ImportVorgangRepository', () => { }); describe('findById', () => { - let importVorgang1: ImportVorgang; - let entity1: ImportVorgangEntity; - - beforeEach(async () => { - importVorgang1 = DoFactory.createImportVorgang(false); - - entity1 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang1)); - await em.persistAndFlush([entity1]); - }); - - afterEach(async () => { - await em.removeAndFlush([entity1]); - }); - it('should return null if the ImportVorgang does not exist', async () => { const result: Option> = await sut.findById(faker.string.uuid()); @@ -140,7 +243,18 @@ describe('ImportVorgangRepository', () => { }); it('should return the ImportVorgang', async () => { - const result: Option> = await sut.findById(entity1.id); + const person: Person = await createPerson(); + const organisationId: string = await createOrga(); + const rolle: Rolle = await createRolle(organisationId); + + const importVorgang: ImportVorgang = DoFactory.createImportVorgang(false, { + importByPersonId: person.id, + rolleId: rolle.id, + organisationId: organisationId, + }); + const savedImportVorgang: ImportVorgang = await sut.save(importVorgang); + + const result: Option> = await sut.findById(savedImportVorgang.id); expect(result).toBeDefined(); expect(result).toBeInstanceOf(ImportVorgang); @@ -148,115 +262,134 @@ describe('ImportVorgangRepository', () => { }); describe('findAuthorized', () => { - let importVorgang1: ImportVorgang; - let importVorgang2: ImportVorgang; - let importVorgang3: ImportVorgang; - let entity1: ImportVorgangEntity; - let entity2: ImportVorgangEntity; - let entity3: ImportVorgangEntity; - - const importByPersonId: string = faker.string.uuid(); - const rolleId: string = faker.string.uuid(); - const orgaId1: string = faker.string.uuid(); - const orgaId2: string = faker.string.uuid(); - - beforeEach(async () => { - importVorgang1 = DoFactory.createImportVorgang(false, { - importByPersonId: importByPersonId, - organisationId: orgaId1, - }); - importVorgang2 = DoFactory.createImportVorgang(false, { - importByPersonId: importByPersonId, - rolleId: rolleId, - organisationId: orgaId2, - }); - importVorgang3 = DoFactory.createImportVorgang(true, { - importByPersonId: faker.string.uuid(), - rolleId: rolleId, - status: ImportStatus.COMPLETED, + describe('should import history data', () => { + let importVorgang1: ImportVorgang; + let importVorgang2: ImportVorgang; + let importVorgang3: ImportVorgang; + let entity1: ImportVorgangEntity; + let entity2: ImportVorgangEntity; + let entity3: ImportVorgangEntity; + + let importByPersonId: string = faker.string.uuid(); + let rolleId: string = faker.string.uuid(); + let orgaId1: string = faker.string.uuid(); + let orgaId2: string = faker.string.uuid(); + + beforeEach(async () => { + const personA: Person = await createPerson(); + orgaId1 = await createOrga(); + const rolle: Rolle = await createRolle(orgaId1); + + importByPersonId = personA.id; + rolleId = rolle.id; + + const personB: Person = await createPerson(); + orgaId2 = await createOrga(); + const rolle2: Rolle = await createRolle(orgaId2); + + const orgaId3: string = await createOrga(); + + importVorgang1 = DoFactory.createImportVorgang(false, { + importByPersonId: importByPersonId, + rolleId: rolle2.id, + organisationId: orgaId1, + }); + importVorgang2 = DoFactory.createImportVorgang(false, { + importByPersonId: importByPersonId, + rolleId: rolleId, + organisationId: orgaId2, + }); + importVorgang3 = DoFactory.createImportVorgang(true, { + importByPersonId: personB.id, + rolleId: rolleId, + organisationId: orgaId3, + status: ImportStatus.COMPLETED, + }); + + entity1 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang1)); + entity2 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang2)); + entity3 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang3)); + await em.persistAndFlush([entity1, entity2, entity3]); }); - entity1 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang1)); - entity2 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang2)); - entity3 = em.create(ImportVorgangEntity, mapAggregateToData(importVorgang3)); - await em.persistAndFlush([entity1, entity2, entity3]); - }); + afterEach(async () => { + await em.removeAndFlush([entity1, entity2, entity3]); + }); - afterEach(async () => { - await em.removeAndFlush([entity1, entity2, entity3]); - }); + it('when search by importByPersonId', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); - it('should return empty array when admin des not have IMPORT_DURCHFUEHREN rights', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(false); + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { + personId: importByPersonId, + }); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized( - permissions, - createMock(), - ); + expect(result.length).toBe(2); + expect(total).toBe(2); + }); - expect(result).toEqual([]); - expect(total).toBe(0); - }); + it('when search by rolleIds', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); - it('should return import history when search by importByPersonId', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { + rolleIds: [rolleId], + }); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { - personId: importByPersonId, + expect(result.length).toBe(2); + expect(total).toBe(2); }); - expect(result.length).toBe(2); - expect(total).toBe(2); - }); + it('when search by organisationIds', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); - it('should return import history when search by rolleIds', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { + organisationIds: [orgaId1, orgaId2], + }); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { - rolleIds: [rolleId], + expect(result.length).toBe(2); + expect(total).toBe(2); }); - expect(result.length).toBe(2); - expect(total).toBe(2); - }); + it('should return import history when search by status', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); - it('should return import history when search by organisationIds', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { + status: ImportStatus.COMPLETED, + }); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { - organisationIds: [orgaId1, orgaId2], + expect(result.length).toBe(1); + expect(total).toBe(1); }); - - expect(result.length).toBe(2); - expect(total).toBe(2); }); - it('should return import history when search by status', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); + describe('Should return empty array', () => { + it('when admin des not have IMPORT_DURCHFUEHREN rights', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(false); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { - status: ImportStatus.COMPLETED, + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized( + permissions, + createMock(), + ); + + expect(result).toEqual([]); + expect(total).toBe(0); }); - expect(result.length).toBe(1); - expect(total).toBe(1); - }); + it('if no import transaction was found', async () => { + const permissions: DeepMocked = createMock(); + permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); - it('should return an empty array if no import transaction was found', async () => { - const permissions: DeepMocked = createMock(); - permissions.hasSystemrechteAtRootOrganisation.mockResolvedValueOnce(true); + const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { + status: ImportStatus.FAILED, + }); - const [result, total]: [ImportVorgang[], number] = await sut.findAuthorized(permissions, { - status: ImportStatus.FAILED, + expect(result.length).toBe(0); + expect(total).toBe(0); }); - - expect(result.length).toBe(0); - expect(total).toBe(0); }); }); }); diff --git a/src/modules/import/persistence/import-vorgang.repository.ts b/src/modules/import/persistence/import-vorgang.repository.ts index 04f10f66f..37efd7b3e 100644 --- a/src/modules/import/persistence/import-vorgang.repository.ts +++ b/src/modules/import/persistence/import-vorgang.repository.ts @@ -13,6 +13,7 @@ export function mapAggregateToData(importVorgang: ImportVorgang): Requi organisationsname: importVorgang.organisationsname, dataItemCount: importVorgang.dataItemCount, status: importVorgang.status, + totalDataItemImported: importVorgang.totalDataItemImported, importByPersonId: importVorgang.importByPersonId, rolleId: importVorgang.rolleId, organisationId: importVorgang.organisationId, @@ -29,9 +30,10 @@ export function mapEntityToAggregate(entity: ImportVorgangEntity): ImportVorgang entity.organisationsname, entity.dataItemCount, entity.status, - entity.importByPersonId, - entity.rolleId, - entity.organisationId, + entity.totalDataItemImported, + entity.importByPersonId?.unwrap().id, + entity.rolleId?.unwrap().id, + entity.organisationId?.unwrap().id, ); } diff --git a/test/utils/do-factory.ts b/test/utils/do-factory.ts index 126da248e..3a6193f98 100644 --- a/test/utils/do-factory.ts +++ b/test/utils/do-factory.ts @@ -250,6 +250,7 @@ export class DoFactory { organisationsname: faker.lorem.word(), dataItemCount: 100, status: ImportStatus.STARTED, + totalDataItemImported: 0, importByPersonId: faker.string.uuid(), rolleId: faker.string.uuid(), organisationId: faker.string.uuid(),