Add Cypress API test suite for the Gesamtnoteneingabe. Tests the grade-entry rules against /api/frontend/v1/Noten, where they are enforced

server-side.

Generic and reusable by the next suite: setup_testinstance.php (--setup/--verify,
delegating the rebuild to paolos db_setup.sh), tasks/db.js, tasks/sshTunnel.js,
tools/dbCheck.js and cypress.config.js carry no suite-specific knowledge. A suite
adds tools/checks/<name>.js, suites/<name>.js and its own task file.

Fixture state resets over a direct Postgres connection through an SSH tunnel the
runner opens itself.

Tests: 37 passing, 5 pending, 1 failing. Pending are opt-in (Freigabe sends
real mail; the Frist config is off). The failing spec is left red on purpose: it
documents that getLvGesamtNoten filters freigabedatum < NOW(), so the read path
hides un-freigegebene notes while the write path uses the unfiltered getter. Not really certain if that is a feature or a bug;

Working on more actual testsuites now that the setup is running as intended;
This commit is contained in:
Johann Hoffmann
2026-07-30 17:18:51 +02:00
parent 4e6a2d5218
commit beb54c1bc5
44 changed files with 4946 additions and 1 deletions
@@ -373,7 +373,8 @@ class Noten extends FHCAPI_Controller
// calculate notenvorschläge from teilnoten
foreach($studentenData as $student) {
$student->anwquote = $anwresult[$student->prestudent_id];
// null when the Anwesenheiten addon is absent - the column stays empty in the UI
$student->anwquote = $anwresult[$student->prestudent_id] ?? null;
$g = $grades[$student->uid]['grades'];
$note_lv = $grades[$student->uid]['note_lv'];
+47
View File
@@ -0,0 +1,47 @@
const { defineConfig } = require("cypress");
require("dotenv").config({ path: "tests/cypress/.env" });
// The suite being run: its cy.task handlers and its Cypress.env() values.
const suite = require("./tests/cypress/suites/noten");
module.exports = defineConfig({
// Cypress 15 deprecates Cypress.env() inside cy.request options, which the API helpers use.
allowCypressEnv: true,
// The suite lives under tests/cypress, so every default folder has to be pointed there.
fixturesFolder: "tests/cypress/fixtures",
screenshotsFolder: "tests/cypress/screenshots",
videosFolder: "tests/cypress/videos",
downloadsFolder: "tests/cypress/downloads",
e2e: {
baseUrl: process.env.BASE_URL,
specPattern: "tests/cypress/e2e/**/*.cy.{js,jsx,ts,tsx}",
supportFile: "tests/cypress/support/e2e.js",
defaultCommandTimeout: 20000,
pageLoadTimeout: 20000,
retries: { runMode: 0, openMode: 0 },
setupNodeEvents(on, config) {
// No defaults anywhere: an empty .env fails the run instead of hitting someone else's instance.
const missing = ["BASE_URL", "USER_NAME", "USER_PASSWORD"].filter((key) => !process.env[key]);
if (missing.length) throw new Error(`Missing in tests/cypress/.env: ${missing.join(", ")}`);
suite.registerTasks(on);
// otherwise the SSH forward outlives Cypress
on("after:run", () => require("./tests/cypress/tasks/sshTunnel").closeTunnel());
return config;
},
},
env: {
// HTTP Basic + LDAP user the API calls authenticate as.
adminusername: process.env.USER_NAME,
adminpassword: process.env.USER_PASSWORD,
...suite.env,
},
});
+15
View File
@@ -0,0 +1,15 @@
{
"scripts": {
"cy:open": "cypress open",
"cy:run": "cypress run",
"cy:noten": "cypress run --spec \"tests/cypress/e2e/specs/api/noten/**/*.cy.js\"",
"cy:noten:p0": "cypress run --spec \"tests/cypress/e2e/specs/api/noten/noten.pruefungsantritte.cy.js,tests/cypress/e2e/specs/api/noten/noten.frist.cy.js,tests/cypress/e2e/specs/api/noten/noten.notenschluessel.cy.js\"",
"noten:check": "node tests/cypress/tools/dbCheck.js noten"
},
"dependencies": {
"cypress": "^15.11.0",
"dotenv": "^17.4.2",
"pg": "^8.13.1",
"ssh2": "^1.17.0"
}
}
+28
View File
@@ -0,0 +1,28 @@
UPDATE public.tbl_funktion SET funktion_kurzbz='Student' WHERE funktion_kurzbz='stud';
UPDATE public.tbl_benutzer SET uid='demoadmin' WHERE uid='admin';
-- Add Missing functions
INSERT INTO public.tbl_funktion (funktion_kurzbz, beschreibung, aktiv, fachbereich, semester, hrrelevant, vertragsrelevant) VALUES('hsv', 'Hochschulvertretung', true, false, false, false, false);
INSERT INTO public.tbl_funktion (funktion_kurzbz, beschreibung, aktiv, fachbereich, semester, hrrelevant, vertragsrelevant) VALUES('jgv', 'Jahrgangsvertretung', true, false, true, false, false);
INSERT INTO public.tbl_funktion (funktion_kurzbz, beschreibung, aktiv, fachbereich, semester, hrrelevant, vertragsrelevant) VALUES('oezuordnung', 'Diszpl-Zuordnung', true, false, false, true, true);
INSERT INTO public.tbl_funktion (funktion_kurzbz, beschreibung, aktiv, fachbereich, semester, hrrelevant, vertragsrelevant) VALUES('fachzuordnung', 'Fachliche Zuordnung', true, false, false, true, true);
-- Add Permissions to Admin Role
INSERT INTO "system".tbl_rolleberechtigung (berechtigung_kurzbz, rolle_kurzbz, art, anmerkung, insertamum, insertvon) VALUES('basis/cis', 'admin', 'suid', 'Zugriff auf CIS', now(), 'demoadmin');
INSERT INTO "system".tbl_benutzerrolle (rolle_kurzbz, berechtigung_kurzbz, uid, funktion_kurzbz, oe_kurzbz, art, studiensemester_kurzbz, "start", ende, negativ, updateamum, updatevon, insertamum, insertvon, kostenstelle_id, anmerkung) VALUES
(NULL, 'dashboard/benutzer', NULL, 'Mitarbeiter', NULL, 'suid', NULL, NULL, NULL, false, NULL, NULL, now(), 'demoadmin', NULL, NULL),
(NULL, 'dashboard/benutzer', NULL, 'Student', NULL, 'suid', NULL, NULL, NULL, false, NULL, NULL, now(), 'demoadmin', NULL, NULL)
;
INSERT INTO "system".tbl_webservicetyp (webservicetyp_kurzbz, beschreibung) VALUES('content', 'CIS-Content ID');
SELECT setval('campus.seq_contentsprache', (select max(contentsprache_id) from campus.tbl_contentsprache), true);
SELECT setval('campus.seq_contentchild', (select max(contentchild_id) from campus.tbl_contentchild), true);
INSERT INTO public.tbl_gruppe (gruppe_kurzbz, studiengang_kz, semester, bezeichnung, beschreibung, sichtbar, lehre, aktiv, sort, mailgrp, generiert, updateamum, updatevon, insertamum, insertvon, ext_id, orgform_kurzbz, content_visible, gesperrt, direktinskription, zutrittssystem, aufnahmegruppe) VALUES
('MA', 0, NULL, 'MA', 'MA', false, false, true, NULL, false, false, now(), 'demoadmin', now(), 'demoadmin', NULL, NULL, true, false, false, false, false),
('STUD', 0, NULL, 'STUD', 'STUD', false, false, true, NULL, false, false, now(), 'demoadmin', now(), 'demoadmin', NULL, NULL, true, false, false, false, false)
;
+36
View File
@@ -0,0 +1,36 @@
CREATE OR REPLACE FUNCTION NearestWintersemester(var_entfernung integer) RETURNS varchar(32) AS $$
DECLARE res varchar(32);
BEGIN
WITH nearestws AS
(
SELECT studiensemester_kurzbz, start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz LIKE 'W%' AND ende>=now() ORDER BY start DESC LIMIT 1
)
SELECT studiensemester_kurzbz into res
FROM
(
SELECT studiensemester_kurzbz, 0 as "entfernung" FROM nearestws
UNION
SELECT studiensemester_kurzbz, rank() over(order by start desc) as "entfernung" FROM public.tbl_studiensemester where start>(SELECT start FROM nearestws)
UNION
SELECT studiensemester_kurzbz, (-1 * rank() over(order by start desc)) as "entfernung" FROM public.tbl_studiensemester WHERE start<(SELECT start FROM nearestws)
) x where entfernung=var_entfernung;
return res;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION CurrentSemester() RETURNS varchar(32) AS $$
DECLARE res varchar(32);
BEGIN
SELECT studiensemester_kurzbz into res FROM public.tbl_studiensemester WHERE start<=now() AND ende>=now() ORDER BY start DESC LIMIT 1;
return res;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION LastActiveSemester() RETURNS varchar(32) AS $$
DECLARE res varchar(32);
BEGIN
SELECT studiensemester_kurzbz into res FROM public.tbl_studiensemester WHERE start<=now() ORDER BY start DESC LIMIT 1;
return res;
END;
$$ LANGUAGE plpgsql;
+40
View File
@@ -0,0 +1,40 @@
-- Demodaten fuer Mitarbeiter
-- Personen
INSERT INTO public.tbl_person (person_id, staatsbuergerschaft,geburtsnation,sprache,anrede,titelpost,titelpre,vorname,nachname,vornamen,gebdatum,gebort,gebzeit,foto,anmerkung,homepage,svnr,ersatzkennzeichen,familienstand,geschlecht,anzahlkinder,aktiv,insertamum,insertvon,updateamum,updatevon,ext_id,bundesland_code,kompetenzen,kurzbeschreibung,zugangscode,foto_sperre,udf_values,bpk,matr_aktiv,matr_nr,zugangscode_timestamp,wahlname,unruly) VALUES
(21,'A','A',NULL,'Herr',NULL,NULL,'Demo','Lektor 1',NULL,'1980-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c21',false,NULL,NULL,false,NULL,NULL,NULL,false),
(22,'A','A',NULL,'Herr',NULL,NULL,'Demo','Lektor 2',NULL,'1980-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c22',false,NULL,NULL,false,NULL,NULL,NULL,false),
(23,'A','A',NULL,'Herr',NULL,NULL,'Demo','Lektor 3',NULL,'1980-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c23',false,NULL,NULL,false,NULL,NULL,NULL,false),
(24,'A','A',NULL,'Herr',NULL,NULL,'Demo','Lektor 4',NULL,'1980-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c24',false,NULL,NULL,false,NULL,NULL,NULL,false),
(25,'A','A',NULL,'Herr',NULL,NULL,'Demo','Lektor 5',NULL,'1980-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c25',false,NULL,NULL,false,NULL,NULL,NULL,false),
(26,'A','A',NULL,'Frau',NULL,NULL,'Demo','Assistenz',NULL,'1985-01-15',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c26',false,NULL,NULL,false,NULL,NULL,NULL,false)
;
INSERT INTO public.tbl_benutzer (person_id, uid, aktiv, alias, insertamum, insertvon, updateamum, updatevon, updateaktivam, updateaktivvon, aktivierungscode) VALUES
('21', 'demolektor1' , true, null, now(), 'auto', null, null, null, false, null),
('22', 'demolektor2' , true, null, now(), 'auto', null, null, null, false, null),
('23', 'demolektor3' , true, null, now(), 'auto', null, null, null, false, null),
('24', 'demolektor4' , true, null, now(), 'auto', null, null, null, false, null),
('25', 'demolektor5' , true, null, now(), 'auto', null, null, null, false, null),
('26', 'demoassistenz' , true, null, now(), 'auto', null, null, null, false, null)
;
INSERT INTO public.tbl_mitarbeiter (mitarbeiter_uid, personalnummer, telefonklappe, kurzbz, lektor, fixangestellt, stundensatz, ausbildungcode, ort_kurzbz, insertamum, insertvon, bismelden) VALUES
('demolektor1', 21, null, 'DemoLKT1', true, true, 80, null, null, now(), 'auto', true),
('demolektor2', 22, null, 'DemoLKT2', true, true, 80, null, null, now(), 'auto', true),
('demolektor3', 23, null, 'DemoLKT3', true, true, 80, null, null, now(), 'auto', true),
('demolektor4', 24, null, 'DemoLKT4', true, true, 80, null, null, now(), 'auto', true),
('demolektor5', 25, null, 'DemoLKT5', true, true, 80, null, null, now(), 'auto', true),
('demoassistenz', 26, null, 'DemoAss', true, true, 80, null, null, now(), 'auto', true)
;
INSERT INTO public.tbl_benutzergruppe (uid, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id, studiensemester_kurzbz) VALUES
('demoadmin', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demolektor1', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demolektor2', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demolektor3', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demolektor4', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demolektor5', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('demoassistenz', 'MA', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL)
;
+27
View File
@@ -0,0 +1,27 @@
-- Kompetenzfedler
INSERT INTO public.tbl_organisationseinheittyp (organisationseinheittyp_kurzbz, bezeichnung, beschreibung) VALUES('Kompetenzfeld', 'Kompetenzfeld', 'Kompetenzfeld');
INSERT INTO public.tbl_organisationseinheit (oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id) VALUES
('dep', 'etw', 'Fachabteilung', 'Abteilung', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL),
('kfSprachen', 'dep', 'Sprachen', 'Kompetenzfeld', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL),
('kfMath', 'dep', 'Mathematik', 'Kompetenzfeld', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL),
('kfTech', 'dep', 'Technik', 'Kompetenzfeld', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_organisationseinheit
(oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id, fts_bezeichnung)
VALUES('Lehrgaenge', 'etw', 'Lehrgänge', 'Abteilung', true, false, NULL, NULL, false, NULL, NULL, NULL, NULL, '''abteilung'':1 ''lehrgänge'':2'::tsvector);
INSERT INTO public.tbl_organisationseinheit
(oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id, fts_bezeichnung)
VALUES('studiengaenge', 'etw', 'Studiengänge', 'Abteilung', true, false, NULL, NULL, false, NULL, NULL, NULL, NULL, '''abteilung'':1 ''studiengänge'':2'::tsvector);
INSERT INTO public.tbl_studienjahr (studienjahr_kurzbz, bezeichnung) VALUES
('2026/27', 'Studienjahr 2026/27'),
('2027/28', 'Studienjahr 2027/28')
;
INSERT INTO public.tbl_studiensemester (studiensemester_kurzbz, "start", ende, ext_id, bezeichnung, studienjahr_kurzbz, beschreibung, onlinebewerbung) VALUES
('WS2026', '2026-09-01', '2027-01-31', NULL, 'Wintersemester 2026/27', '2026/27', NULL, false),
('SS2027', '2027-02-01', '2027-07-01', NULL, 'Sommersemester 2027', '2026/27', NULL, false),
('WS2027', '2027-09-01', '2028-01-31', NULL, 'Wintersemester 2027/28', '2027/28', NULL, false),
('SS2028', '2028-02-01', '2028-07-01', NULL, 'Sommersemester 2028', '2027/28', NULL, false)
;
+25
View File
@@ -0,0 +1,25 @@
INSERT INTO public.tbl_ort
(ort_kurzbz, bezeichnung, planbezeichnung, max_person, lehre, reservieren, aktiv, lageplan, dislozierung, kosten, ausstattung, updateamum, updatevon, insertamum, insertvon, ext_id, stockwerk, telefonklappe, standort_id, content_id, m2, gebteil, oe_kurzbz, arbeitsplaetze)
VALUES('EG03', 'Besprechungsruam EG03', 'EG03', 8, true, true, true, NULL, NULL, NULL, NULL, '2023-08-24 14:18:50.000', 'oesi', '2023-08-24 14:17:30.000', 'oesi', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_ort
(ort_kurzbz, bezeichnung, planbezeichnung, max_person, lehre, reservieren, aktiv, lageplan, dislozierung, kosten, ausstattung, updateamum, updatevon, insertamum, insertvon, ext_id, stockwerk, telefonklappe, standort_id, content_id, m2, gebteil, oe_kurzbz, arbeitsplaetze)
VALUES('EG01', 'Seminarraum EG01', 'EG01', 10, true, true, true, NULL, NULL, NULL, NULL, '2023-08-24 14:18:52.000', 'oesi', '2023-08-24 14:16:47.000', 'oesi', NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_ort
(ort_kurzbz, bezeichnung, planbezeichnung, max_person, lehre, reservieren, aktiv, lageplan, dislozierung, kosten, ausstattung, updateamum, updatevon, insertamum, insertvon, ext_id, stockwerk, telefonklappe, standort_id, content_id, m2, gebteil, oe_kurzbz, arbeitsplaetze)
VALUES('EG02', 'Seminarraum EG02', 'EG02', 10, true, true, true, NULL, NULL, NULL, NULL, '2023-08-24 14:18:54.000', 'oesi', '2023-08-24 14:16:56.000', 'oesi', NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_ort
(ort_kurzbz, bezeichnung, planbezeichnung, max_person, lehre, reservieren, aktiv, lageplan, dislozierung, kosten, ausstattung, updateamum, updatevon, insertamum, insertvon, ext_id, stockwerk, telefonklappe, standort_id, content_id, m2, gebteil, oe_kurzbz, arbeitsplaetze)
VALUES('EG04', 'EDV EG04', 'EG04', 20, true, true, true, NULL, NULL, NULL, NULL, '2023-08-24 14:18:55.000', 'oesi', '2023-08-24 14:17:49.000', 'oesi', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_ortraumtyp
(ort_kurzbz, hierarchie, raumtyp_kurzbz)
VALUES('EG01', 1, 'SEM');
INSERT INTO public.tbl_ortraumtyp
(ort_kurzbz, hierarchie, raumtyp_kurzbz)
VALUES('EG02', 1, 'SEM');
INSERT INTO public.tbl_ortraumtyp
(ort_kurzbz, hierarchie, raumtyp_kurzbz)
VALUES('EG04', 1, 'EDV2');
INSERT INTO public.tbl_ortraumtyp
(ort_kurzbz, hierarchie, raumtyp_kurzbz)
VALUES('EG04', 2, 'EDV5/6');
+114
View File
@@ -0,0 +1,114 @@
-- Demodaten fuer Studierende im Studiengang 1
INSERT INTO lehre.tbl_studienordnung
(studienordnung_id, studiengang_kz, "version", gueltigvon, gueltigbis, bezeichnung, ects, studiengangbezeichnung, studiengangbezeichnung_englisch, studiengangkurzbzlang, akadgrad_id, insertamum, insertvon, updateamum, updatevon, ext_id, status_kurzbz, standort_id)
VALUES(1, 1, '1', 'WS2023', NULL, 'BS1-WS2023', 180.00, 'Studiengang 1', 'Studiengang 1', 'STG1', NULL, '2023-08-24 14:25:41.728', 'oesi', NULL, NULL, NULL, 'development', NULL);
INSERT INTO lehre.tbl_studienplan
(studienplan_id, studienordnung_id, orgform_kurzbz, "version", bezeichnung, regelstudiendauer, sprache, aktiv, semesterwochen, testtool_sprachwahl, insertamum, insertvon, updateamum, updatevon, ext_id, ects_stpl, pflicht_sws, pflicht_lvs, onlinebewerbung_studienplan)
VALUES(1, 1, 'VZ', '1', 'BS1-WS2023-VZ', 6, NULL, true, 15, true, '2023-08-24 14:26:12.751', 'oesi', NULL, NULL, NULL, 120.00, NULL, NULL, true);
INSERT INTO lehre.tbl_studienplan_semester
( studienplan_id, studiensemester_kurzbz, semester)
VALUES(1, 'WS2025', 1);
INSERT INTO lehre.tbl_studienplan_semester
(studienplan_id, studiensemester_kurzbz, semester)
VALUES(1, 'SS2026', 1);
-- Personen
INSERT INTO public.tbl_person (person_id, staatsbuergerschaft,geburtsnation,sprache,anrede,titelpost,titelpre,vorname,nachname,vornamen,gebdatum,gebort,gebzeit,foto,anmerkung,homepage,svnr,ersatzkennzeichen,familienstand,geschlecht,anzahlkinder,aktiv,insertamum,insertvon,updateamum,updatevon,ext_id,bundesland_code,kompetenzen,kurzbeschreibung,zugangscode,foto_sperre,udf_values,bpk,matr_aktiv,matr_nr,zugangscode_timestamp,wahlname,unruly) VALUES
(101,'A','A',NULL,'Herr',NULL,NULL,'Leonardo','DiCaprio',NULL,'1974-11-11',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c101',false,NULL,NULL,false,NULL,NULL,NULL,false),
(102,'A','A',NULL,'Herr',NULL,NULL,'Robert','Downey Jr.',NULL,'1965-04-04',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c102',false,NULL,NULL,false,NULL,NULL,NULL,false),
(103,'A','A',NULL,'Herr',NULL,NULL,'Denzel','Washington',NULL,'1954-12-28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c103',false,NULL,NULL,false,NULL,NULL,NULL,false),
(104,'A','A',NULL,'Herr',NULL,NULL,'Al','Pacino',NULL,'1940-04-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c104',false,NULL,NULL,false,NULL,NULL,NULL,false),
(105,'A','A',NULL,'Herr',NULL,NULL,'Morgan','Freeman',NULL,'1937-06-01',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c105',false,NULL,NULL,false,NULL,NULL,NULL,false),
(106,'A','A',NULL,'Herr',NULL,NULL,'Daniel','Day-Lewis',NULL,'1957-04-29',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c106',false,NULL,NULL,false,NULL,NULL,NULL,false),
(107,'A','A',NULL,'Herr',NULL,NULL,'Marlon','Brando',NULL,'1924-04-03',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c107',false,NULL,NULL,false,NULL,NULL,NULL,false),
(108,'A','A',NULL,'Herr',NULL,NULL,'Tom','Hanks',NULL,'1956-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c108',false,NULL,NULL,false,NULL,NULL,NULL,false),
(109,'A','A',NULL,'Herr',NULL,NULL,'Johnny','Depp',NULL,'1963-06-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c109',false,NULL,NULL,false,NULL,NULL,NULL,false),
(110,'A','A',NULL,'Herr',NULL,NULL,'Brad','Pitt',NULL,'1963-12-18',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c8110',false,NULL,NULL,false,NULL,NULL,NULL,false),
(111,'A','A',NULL,'Herr',NULL,NULL,'Will','Smith',NULL,'1968-09-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c111',false,NULL,NULL,false,NULL,NULL,NULL,false),
(112,'A','A',NULL,'Herr',NULL,NULL,'Keanu','Reeves',NULL,'1964-09-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c112',false,NULL,NULL,false,NULL,NULL,NULL,false),
(113,'A','A',NULL,'Herr',NULL,NULL,'Robert','De Niro',NULL,'1943-08-17',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647113',false,NULL,NULL,false,NULL,NULL,NULL,false),
(114,'A','A',NULL,'Herr',NULL,NULL,'Harrison','Ford',NULL,'1942-07-13',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c114',false,NULL,NULL,false,NULL,NULL,NULL,false),
(115,'A','A',NULL,'Herr',NULL,NULL,'Samuel L.','Jackson',NULL,'1948-12-21',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c115',false,NULL,NULL,false,NULL,NULL,NULL,false),
(116,'A','A',NULL,'Herr',NULL,NULL,'Christian','Bale',NULL,'1974-01-30',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c116',false,NULL,NULL,false,NULL,NULL,NULL,false),
(117,'A','A',NULL,'Herr',NULL,NULL,'Tom','Cruise',NULL,'1962-07-03',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c1117',false,NULL,NULL,false,NULL,NULL,NULL,false),
(118,'A','A',NULL,'Herr',NULL,NULL,'Arnold','Schwarzenegger',NULL,'1947-07-30',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c118',false,NULL,NULL,false,NULL,NULL,NULL,false),
(119,'A','A',NULL,'Herr',NULL,NULL,'Sylvester','Stallone',NULL,'1946-07-06',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c119',false,NULL,NULL,false,NULL,NULL,NULL,false),
(120,'A','A',NULL,'Herr',NULL,NULL,'Karl','Klammer',NULL,'1963-06-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c120',false,NULL,NULL,false,NULL,NULL,NULL,false)
;
SELECT setval('public.tbl_person_person_id_seq', 1000,true);
-- Prestudenten
INSERT INTO public.tbl_prestudent (prestudent_id, person_id,studiengang_kz,aufmerksamdurch_kurzbz,berufstaetigkeit_code,ausbildungcode,zgv_code,zgvort,zgvdatum,zgvmas_code,zgvmaort,zgvmadatum,aufnahmeschluessel,facheinschlberuf,reihungstest_id,anmeldungreihungstest,reihungstestangetreten,rt_gesamtpunkte,bismelden,insertamum,insertvon,updateamum,updatevon,ext_id,anmerkung,dual,rt_punkte1,rt_punkte2,ausstellungsstaat,rt_punkte3,udf_values,priorisierung,zgvdoktor_code,zgvdoktorort,zgvdoktordatum,mentor,zgvnation,zgvmanation,zgvdoktornation,gsstudientyp_kurzbz,aufnahmegruppe_kurzbz,foerderrelevant,standort_code,zgv_erfuellt,zgvmas_erfuellt,zgvdoktor_erfuellt) VALUES
(1101,101,1,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1102,102,1,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1103,103,1,'k.A.',NULL,NULL,9,NULL,'2020-06-03',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1104,104,1,'k.A.',NULL,NULL,9,NULL,'2020-06-04',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1105,105,1,'k.A.',NULL,NULL,9,NULL,'2020-06-05',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1106,106,1,'k.A.',NULL,NULL,9,NULL,'2020-06-06',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1107,107,1,'k.A.',NULL,NULL,9,NULL,'2020-06-07',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1108,108,1,'k.A.',NULL,NULL,9,NULL,'2020-06-08',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1109,109,1,'k.A.',NULL,NULL,9,NULL,'2020-06-09',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1110,110,1,'k.A.',NULL,NULL,9,NULL,'2020-06-10',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1111,111,1,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1112,112,1,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1113,113,1,'k.A.',NULL,NULL,9,NULL,'2020-06-03',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1114,114,1,'k.A.',NULL,NULL,9,NULL,'2020-06-04',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1115,115,1,'k.A.',NULL,NULL,9,NULL,'2020-06-05',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1116,116,1,'k.A.',NULL,NULL,9,NULL,'2020-06-06',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1117,117,1,'k.A.',NULL,NULL,9,NULL,'2020-06-07',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1118,118,1,'k.A.',NULL,NULL,9,NULL,'2020-06-08',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1119,119,1,'k.A.',NULL,NULL,9,NULL,'2020-06-09',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(1120,120,1,'k.A.',NULL,NULL,9,NULL,'2020-06-10',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false)
;
SELECT setval('tbl_prestudent_prestudent_id_seq', 2000,true);
-- Prestudent Status
WITH status AS (
SELECT * FROM (VALUES
('Interessent','WS2025',1,'2025-01-15','2023-08-24 14:56:04','auto',NULL,NULL,NULL,1,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Bewerber','WS2025',1,'2025-02-20','2023-08-24 14:58:11','auto',NULL,NULL,NULL,1,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Aufgenommener','WS2025',1,'2025-05-01','2023-08-24 14:58:14','auto',NULL,NULL,NULL,1,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student','WS2025',1,'2025-08-24','2023-08-24 14:58:16','auto',NULL,NULL,NULL,1,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL)
) AS t(status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
),
inserts AS (
SELECT generate_series(1101, 1120) AS prestudent_id,*
FROM status
)
INSERT INTO public.tbl_prestudentstatus (prestudent_id, status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
SELECT prestudent_id, status_kurzbz, studiensemester_kurzbz, ausbildungssemester, datum::date, insertamum::timestamp, insertvon, updateamum::timestamp, updatevon,orgform_kurzbz,studienplan_id,bestaetigtam::date,bestaetigtvon,fgm::smallint,faktiv,anmerkung,bewerbung_abgeschicktamum::timestamp,rt_stufe::smallint,statusgrund_id::int
FROM inserts;
-- tbl_benutzer
WITH persons AS (
SELECT generate_series(101, 120) AS person_id
)
INSERT INTO public.tbl_benutzer (person_id, uid, aktiv, alias, insertamum, insertvon, updateamum, updatevon, updateaktivam, updateaktivvon, aktivierungscode)
SELECT person_id, 's125b' || person_id, true, null, now(), 'auto', null, null, null, false, null
FROM persons;
-- tbl_student
WITH persons AS (
SELECT generate_series(101, 120) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's125b' || person_id, '2510001' || person_id, ('1' || person_id)::integer, '1', '1', '','', null, null, now(), 'auto'
FROM persons;
-- tbl_studentlehrverband
WITH persons AS (
SELECT generate_series(101, 120) AS person_id
),
students as (
SELECT ('s125b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, 'WS2025', '1','1','','', null, null, now(), 'auto'
FROM students;
+161
View File
@@ -0,0 +1,161 @@
-- Demodaten fuer Studiengang 3: Organisationseinheit, Studienordnung, Studiengang, Lehrveranstaltungen
INSERT INTO public.tbl_organisationseinheit (oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id)
VALUES('stg3', 'studiengaenge', 'Studiengang 3', 'Studiengang', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_studiengang (studiengang_kz,kurzbz,kurzbzlang,typ,bezeichnung,english,farbe,email,telefon,max_semester,max_verband,max_gruppe,erhalter_kz,bescheid,bescheidbgbl1,bescheidbgbl2,bescheidgz,bescheidvom,titelbescheidvom,aktiv,ext_id,orgform_kurzbz,zusatzinfo_html,moodle,oe_kurzbz,sprache,testtool_sprachwahl,studienplaetze,lgartcode,mischform,projektarbeit_note_anzeige,melderelevant,foerderrelevant,standort_code,onlinebewerbung,melde_studiengang_kz) VALUES
(3,'S3','STG3','b','Studiengang 3','Studiengang 3',NULL,'[email protected]',NULL,6,'B','2',5,NULL,NULL,NULL,NULL,NULL,NULL,true,NULL,'VZ','',true,'stg3','German',true,NULL,NULL,false,true,true,true,NULL,false,'0002')
;
INSERT INTO "system".tbl_benutzerrolle
(rolle_kurzbz, berechtigung_kurzbz, uid, funktion_kurzbz, oe_kurzbz, art, studiensemester_kurzbz, "start", ende, negativ, updateamum, updatevon, insertamum, insertvon, kostenstelle_id, anmerkung)
VALUES('assistenz', NULL, 'demoassistenz', NULL, 'stg3', 'suid', NULL, '2025-09-18', NULL, false, NULL, NULL, '2025-09-18 15:46:02.000', 'demoadmin', NULL, NULL);
INSERT INTO public.tbl_lehrverband (studiengang_kz, semester, verband, gruppe, aktiv, bezeichnung, ext_id, orgform_kurzbz) VALUES
(3, 1, '','', true, null, null, null),
(3, 1, 'A','', true, null, null, null),
(3, 1, 'B','', true, null, null, null),
(3, 2, '','', true, null, null, null),
(3, 2, 'A','', true, null, null, null),
(3, 2, 'B','', true, null, null, null),
(3, 3, '','', true, null, null, null),
(3, 3, 'A','', true, null, null, null),
(3, 3, 'B','', true, null, null, null),
(3, 4, '','', true, null, null, null),
(3, 4, 'A','', true, null, null, null),
(3, 4, 'B','', true, null, null, null),
(3, 5, '','', true, null, null, null),
(3, 5, 'A','', true, null, null, null),
(3, 5, 'B','', true, null, null, null),
(3, 6, '','', true, null, null, null),
(3, 6, 'A','', true, null, null, null),
(3, 6, 'B','', true, null, null, null)
;
INSERT INTO lehre.tbl_studienordnung (studienordnung_id, studiengang_kz,"version",gueltigvon,gueltigbis,bezeichnung,ects,studiengangbezeichnung,studiengangbezeichnung_englisch,studiengangkurzbzlang,akadgrad_id,insertamum,insertvon,updateamum,updatevon,ext_id,status_kurzbz,standort_id) VALUES
(301, 3,'1','WS2023',NULL,'BS3-WS2023',180.00,'Studiengang 3','Studiengang 3','STG3',NULL,'2023-08-24 14:25:41.728215','auto',NULL,NULL,NULL,'development',NULL);
INSERT INTO lehre.tbl_studienplan (studienplan_id, studienordnung_id,orgform_kurzbz,"version",bezeichnung,regelstudiendauer,sprache,aktiv,semesterwochen,testtool_sprachwahl,insertamum,insertvon,updateamum,updatevon,ext_id,ects_stpl,pflicht_sws,pflicht_lvs,onlinebewerbung_studienplan) VALUES
(3011, 301,'VZ','1','BS3-WS2023-VZ',6,NULL,true,15,true,'2023-08-24 14:26:12.751416','auto',NULL,NULL,NULL,180.00,NULL,NULL,true);
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(311, 'MOD1.1','Sport',3,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(312, 'MOD1.2','Mathematik',3,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(313, 'MOD1.3','Grundlagen',3,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Basics','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(314, 'MOD1.4','Sprachen',3,1,'English',6.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(321, 'MOD2.1','Labor',3,2,'German',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Laboratory','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(322, 'MOD2.2','Mathematik',3,2,'German',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(323, 'MOD2.3','Sprachen',3,2,'English',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(331, 'MOD3.1','Mathematik',3,3,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(332, 'MOD3.2','Elektrische Signale',3,3,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Electric Signals','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(341, 'MOD4.1','Messtechnik',3,4,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Measurement Technology','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(342, 'MOD4.2','Forschung',3,4,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Research','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(351, 'MOD5.1','Communication',3,5,'English',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(352, 'MOD5.2','Regelungstechnik',3,5,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Control Engineering','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(361, 'MOD6.1','Bachelorarbeit',3,6,'German',30.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Bachelor Thesis','VZ',5,'regulaer','modul','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL)
;
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(3111, 'LS','Leistungssport',3,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3121, 'MAT','Mathematik 1',3,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3131, 'GL','Grundlagen der Programmierung',3,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Development Basics','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3141, 'ENG','Englisch 1',3,1,'English',6.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3211, 'EL','Elektronik Labor',3,2,'German',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'LAB','Laboratory','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3221, 'MAT','Mathematik 2',3,2,'German',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3231, 'ENG','Communcation Englisch',3,2,'English',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3311, 'MAT','Mathematik 3',3,3,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3321, 'ES','Elektrische Signale',3,3,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Electric Signals','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3411, 'MT','Messtechnik',3,4,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Measurement Technology','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3421, 'BAN','Bewegungsanalyse',3,4,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Movement Analytics','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3511, 'ENG','Communication',3,5,'English',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3521, 'RT','Regelungstechnik',3,5,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Control Engineering','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(3611, 'BA','Bachelorarbeit',3,6,'German',30.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'SE','Bachelor Thesis','VZ',5,'regulaer','lv','stg3',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL)
;
INSERT INTO lehre.tbl_studienplan_lehrveranstaltung (studienplan_lehrveranstaltung_id, studienplan_id,lehrveranstaltung_id,semester,studienplan_lehrveranstaltung_id_parent,pflicht,koordinator,insertamum,insertvon,updateamum,updatevon,sort,ext_id,curriculum,export,genehmigung) VALUES
-- MODULE im Studienplan
(301, 3011,311,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(302, 3011,312,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(303, 3011,313,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(304, 3011,314,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(305, 3011,321,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(306, 3011,322,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(307, 3011,323,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(308, 3011,331,3,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(309, 3011,332,3,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(310, 3011,341,4,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(311, 3011,342,4,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(312, 3011,351,5,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(313, 3011,352,5,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(314, 3011,361,6,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
-- LVS zu Modulen
(315, 3011,3111,1,301,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(316, 3011,3121,1,302,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(317, 3011,3131,1,303,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(318, 3011,3141,1,304,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(319, 3011,3211,2,305,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(320, 3011,3221,2,306,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(321, 3011,3231,2,307,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(322, 3011,3311,3,308,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(323, 3011,3321,3,309,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(324, 3011,3411,4,310,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(325, 3011,3421,4,311,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(326, 3011,3511,5,312,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(327, 3011,3521,5,313,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(328, 3011,3611,6,314,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true)
;
INSERT INTO lehre.tbl_studienplan_semester (studienplan_id, studiensemester_kurzbz, semester) VALUES
(3011, 'WS2023', 1),
(3011, 'SS2024', 2),
(3011, 'WS2024', 1),
(3011, 'WS2024', 3),
(3011, 'SS2025', 2),
(3011, 'SS2025', 4),
(3011, 'WS2025', 1),
(3011, 'WS2025', 3),
(3011, 'WS2025', 5),
(3011, 'SS2026', 2),
(3011, 'SS2026', 4),
(3011, 'SS2026', 6);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(31001, 3131, 'WS2025', NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 3131, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 3131, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(31001, 3, 1, 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(31001, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(31002, 3131, 'WS2025', NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 3131, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 3131, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(31002, 3, 1, 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(31002, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
-- Stundenplan Eintraege
INSERT INTO lehre.tbl_stundenplandev
(stundenplandev_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(310011, 31001, 31001, 3, 1, 'A', '', NULL, 'demolektor1', 'EG04', '2025-07-31', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplan
(stundenplan_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(310011, 31001, 31001, 3, 1, 'A', '', NULL, 'demolektor1', 'EG04', '2025-07-31', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplandev
(stundenplandev_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(310021, 31002, 31002, 3, 1, 'B', '', NULL, 'demolektor1', 'EG04', '2025-08-01', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplan
(stundenplan_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(310021, 31002, 31002, 3, 1, 'B', '', NULL, 'demolektor1', 'EG04', '2025-08-01', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
+120
View File
@@ -0,0 +1,120 @@
-- Demodaten fuer Studierende im Studiengang 3
-- Personen
INSERT INTO public.tbl_person (person_id, staatsbuergerschaft,geburtsnation,sprache,anrede,titelpost,titelpre,vorname,nachname,vornamen,gebdatum,gebort,gebzeit,foto,anmerkung,homepage,svnr,ersatzkennzeichen,familienstand,geschlecht,anzahlkinder,aktiv,insertamum,insertvon,updateamum,updatevon,ext_id,bundesland_code,kompetenzen,kurzbeschreibung,zugangscode,foto_sperre,udf_values,bpk,matr_aktiv,matr_nr,zugangscode_timestamp,wahlname,unruly) VALUES
(301,'A','A',NULL,'Herr',NULL,NULL,'Elon','Musk',NULL,'1974-11-11',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c301',false,NULL,NULL,false,NULL,NULL,NULL,false),
(302,'A','A',NULL,'Herr',NULL,NULL,'Steve','Jobs',NULL,'1965-04-04',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c302',false,NULL,NULL,false,NULL,NULL,NULL,false),
(303,'A','A',NULL,'Herr',NULL,NULL,'Bill','Gates',NULL,'1954-12-28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c303',false,NULL,NULL,false,NULL,NULL,NULL,false),
(304,'A','A',NULL,'Herr',NULL,NULL,'Linus','Torvalds',NULL,'1940-04-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c304',false,NULL,NULL,false,NULL,NULL,NULL,false),
(305,'A','A',NULL,'Herr',NULL,NULL,'Mark','Zuckerberg',NULL,'1937-06-01',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c305',false,NULL,NULL,false,NULL,NULL,NULL,false),
(306,'A','A',NULL,'Frau',NULL,NULL,'Ada','Lovelace',NULL,'1957-04-29',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c306',false,NULL,NULL,false,NULL,NULL,NULL,false),
(307,'A','A',NULL,'Herr',NULL,NULL,'Tim','Berners-Lee',NULL,'1924-04-03',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c307',false,NULL,NULL,false,NULL,NULL,NULL,false),
(308,'A','A',NULL,'Frau',NULL,NULL,'Grace','Hopper',NULL,'1956-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c308',false,NULL,NULL,false,NULL,NULL,NULL,false),
(309,'A','A',NULL,'Herr',NULL,NULL,'Jeff','Bezos',NULL,'1963-06-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c309',false,NULL,NULL,false,NULL,NULL,NULL,false),
(310,'A','A',NULL,'Herr',NULL,NULL,'Larry','Page',NULL,'1963-12-18',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c8310',false,NULL,NULL,false,NULL,NULL,NULL,false),
(311,'A','A',NULL,'Herr',NULL,NULL,'Sergey','Brin',NULL,'1968-09-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c311',false,NULL,NULL,false,NULL,NULL,NULL,false),
(312,'A','A',NULL,'Frau',NULL,NULL,'Katherine','Johnson',NULL,'1964-09-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c312',false,NULL,NULL,false,NULL,NULL,NULL,false),
(313,'A','A',NULL,'Herr',NULL,NULL,'Dennis','Ritchie',NULL,'1943-08-17',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647313',false,NULL,NULL,false,NULL,NULL,NULL,false),
(314,'A','A',NULL,'Frau',NULL,NULL,'Margaret','Hamilton',NULL,'1942-07-13',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c314',false,NULL,NULL,false,NULL,NULL,NULL,false),
(315,'A','A',NULL,'Herr',NULL,NULL,'Satya','Nadella',NULL,'1948-12-21',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c315',false,NULL,NULL,false,NULL,NULL,NULL,false),
(316,'A','A',NULL,'Frau',NULL,NULL,'Susan','Wojcicki',NULL,'1974-01-30',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c316',false,NULL,NULL,false,NULL,NULL,NULL,false),
(317,'A','A',NULL,'Frau',NULL,NULL,'Sheryl','Sandberg',NULL,'1962-07-03',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c317',false,NULL,NULL,false,NULL,NULL,NULL,false),
(318,'A','A',NULL,'Herr',NULL,NULL,'Jack','Dorsey',NULL,'1947-07-30',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c318',false,NULL,NULL,false,NULL,NULL,NULL,false),
(319,'A','A',NULL,'Frau',NULL,NULL,'Ginni','Rometty',NULL,'1946-07-06',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c319',false,NULL,NULL,false,NULL,NULL,NULL,false),
(320,'A','A',NULL,'Herr',NULL,NULL,'Sundar','Pichai',NULL,'1963-06-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c320',false,NULL,NULL,false,NULL,NULL,NULL,false)
;
SELECT setval('public.tbl_person_person_id_seq', 1000,true);
-- Prestudenten
INSERT INTO public.tbl_prestudent (prestudent_id, person_id,studiengang_kz,aufmerksamdurch_kurzbz,berufstaetigkeit_code,ausbildungcode,zgv_code,zgvort,zgvdatum,zgvmas_code,zgvmaort,zgvmadatum,aufnahmeschluessel,facheinschlberuf,reihungstest_id,anmeldungreihungstest,reihungstestangetreten,rt_gesamtpunkte,bismelden,insertamum,insertvon,updateamum,updatevon,ext_id,anmerkung,dual,rt_punkte1,rt_punkte2,ausstellungsstaat,rt_punkte3,udf_values,priorisierung,zgvdoktor_code,zgvdoktorort,zgvdoktordatum,mentor,zgvnation,zgvmanation,zgvdoktornation,gsstudientyp_kurzbz,aufnahmegruppe_kurzbz,foerderrelevant,standort_code,zgv_erfuellt,zgvmas_erfuellt,zgvdoktor_erfuellt) VALUES
(3301,301,3,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3302,302,3,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3303,303,3,'k.A.',NULL,NULL,9,NULL,'2020-06-03',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3304,304,3,'k.A.',NULL,NULL,9,NULL,'2020-06-04',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3305,305,3,'k.A.',NULL,NULL,9,NULL,'2020-06-05',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3306,306,3,'k.A.',NULL,NULL,9,NULL,'2020-06-06',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3307,307,3,'k.A.',NULL,NULL,9,NULL,'2020-06-07',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3308,308,3,'k.A.',NULL,NULL,9,NULL,'2020-06-08',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3309,309,3,'k.A.',NULL,NULL,9,NULL,'2020-06-09',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3310,310,3,'k.A.',NULL,NULL,9,NULL,'2020-06-10',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3311,311,3,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3312,312,3,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3313,313,3,'k.A.',NULL,NULL,9,NULL,'2020-06-03',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3314,314,3,'k.A.',NULL,NULL,9,NULL,'2020-06-04',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3315,315,3,'k.A.',NULL,NULL,9,NULL,'2020-06-05',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3316,316,3,'k.A.',NULL,NULL,9,NULL,'2020-06-06',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3317,317,3,'k.A.',NULL,NULL,9,NULL,'2020-06-07',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3318,318,3,'k.A.',NULL,NULL,9,NULL,'2020-06-08',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3319,319,3,'k.A.',NULL,NULL,9,NULL,'2020-06-09',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(3320,320,3,'k.A.',NULL,NULL,9,NULL,'2020-06-10',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false)
;
SELECT setval('tbl_prestudent_prestudent_id_seq', (SELECT max(prestudent_id) FROM public.tbl_prestudent),true);
-- Prestudent Status
WITH status AS (
SELECT * FROM (VALUES
('Interessent','WS2025',1,'2025-01-15','2023-08-24 14:56:04','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Bewerber','WS2025',1,'2025-02-20','2023-08-24 14:58:11','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Aufgenommener','WS2025',1,'2025-05-01','2023-08-24 14:58:14','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student','WS2025',1,'2025-08-24','2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL)
) AS t(status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
),
inserts AS (
SELECT generate_series(3301, 3320) AS prestudent_id,*
FROM status
)
INSERT INTO public.tbl_prestudentstatus (prestudent_id, status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
SELECT prestudent_id, status_kurzbz, studiensemester_kurzbz, ausbildungssemester, datum::date, insertamum::timestamp, insertvon, updateamum::timestamp, updatevon,orgform_kurzbz,studienplan_id,bestaetigtam::date,bestaetigtvon,fgm::smallint,faktiv,anmerkung,bewerbung_abgeschicktamum::timestamp,rt_stufe::smallint,statusgrund_id::int
FROM inserts;
-- tbl_benutzer
WITH persons AS (
SELECT generate_series(301, 320) AS person_id
)
INSERT INTO public.tbl_benutzer (person_id, uid, aktiv, alias, insertamum, insertvon, updateamum, updatevon, updateaktivam, updateaktivvon, aktivierungscode)
SELECT person_id, 's325b' || person_id, true, null, now(), 'auto', null, null, null, false, null
FROM persons;
-- tbl_student
-- A Verband
WITH persons AS (
SELECT generate_series(301, 310) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's325b' || person_id, '2510003' || person_id, ('3' || person_id)::integer, '3', '1', 'A','', null, null, now(), 'auto'
FROM persons;
-- B Verband
WITH persons AS (
SELECT generate_series(311, 320) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's325b' || person_id, '2510003' || person_id, ('3' || person_id)::integer, '3', '1', 'B','', null, null, now(), 'auto'
FROM persons;
-- tbl_studentlehrverband
-- A Verband
WITH persons AS (
SELECT generate_series(301, 310) AS person_id
),
students as (
SELECT ('s325b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, 'WS2025', '3','1','A','', null, null, now(), 'auto'
FROM students;
-- B Verband
WITH persons AS (
SELECT generate_series(311, 320) AS person_id
),
students as (
SELECT ('s325b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, 'WS2025', '3','1','B','', null, null, now(), 'auto'
FROM students;
+239
View File
@@ -0,0 +1,239 @@
-- Demodaten fuer Studiengang 4: Organisationseinheit, Studienordnung, Studiengang, Lehrveranstaltungen, Lehreinheiten
-- Testdaten fuer LV-Verwaltung, Tempus
INSERT INTO public.tbl_organisationseinheit (oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id)
VALUES('stg4', 'studiengaenge', 'Tempus Examples', 'Studiengang', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_studiengang (studiengang_kz,kurzbz,kurzbzlang,typ,bezeichnung,english,farbe,email,telefon,max_semester,max_verband,max_gruppe,erhalter_kz,bescheid,bescheidbgbl1,bescheidbgbl2,bescheidgz,bescheidvom,titelbescheidvom,aktiv,ext_id,orgform_kurzbz,zusatzinfo_html,moodle,oe_kurzbz,sprache,testtool_sprachwahl,studienplaetze,lgartcode,mischform,projektarbeit_note_anzeige,melderelevant,foerderrelevant,standort_code,onlinebewerbung,melde_studiengang_kz) VALUES
(4,'S4','STG4','b','Tempus Beispiele','Tempus Examples',NULL,'[email protected]',NULL,6,'B','2',5,NULL,NULL,NULL,NULL,NULL,NULL,true,NULL,'VZ','',true,'stg4','German',true,NULL,NULL,false,true,true,true,NULL,false,'0004')
;
INSERT INTO public.tbl_lehrverband (studiengang_kz, semester, verband, gruppe, aktiv, bezeichnung, ext_id, orgform_kurzbz) VALUES
(4, 1, '','', true, null, null, null),
(4, 1, 'A','', true, null, null, null),
(4, 1, 'B','', true, null, null, null),
(4, 2, '','', true, null, null, null),
(4, 2, 'A','', true, null, null, null),
(4, 2, 'B','', true, null, null, null),
(4, 3, '','', true, null, null, null),
(4, 3, 'A','', true, null, null, null),
(4, 3, 'B','', true, null, null, null),
(4, 4, '','', true, null, null, null),
(4, 4, 'A','', true, null, null, null),
(4, 4, 'B','', true, null, null, null),
(4, 5, '','', true, null, null, null),
(4, 5, 'A','', true, null, null, null),
(4, 5, 'B','', true, null, null, null),
(4, 6, '','', true, null, null, null),
(4, 6, 'A','', true, null, null, null),
(4, 6, 'B','', true, null, null, null)
;
INSERT INTO lehre.tbl_studienordnung (studienordnung_id, studiengang_kz,"version",gueltigvon,gueltigbis,bezeichnung,ects,studiengangbezeichnung,studiengangbezeichnung_englisch,studiengangkurzbzlang,akadgrad_id,insertamum,insertvon,updateamum,updatevon,ext_id,status_kurzbz,standort_id) VALUES
(401, 4,'1',NearestWintersemester(-4),NULL,'BS4'||NearestWintersemester(-4),180.00,'Tempus Beispiele','Tempus Examples','STG4',NULL,now(),'anondata',NULL,NULL,NULL,'development',NULL);
INSERT INTO lehre.tbl_studienplan (studienplan_id, studienordnung_id,orgform_kurzbz,"version",bezeichnung,regelstudiendauer,sprache,aktiv,semesterwochen,testtool_sprachwahl,insertamum,insertvon,updateamum,updatevon,ext_id,ects_stpl,pflicht_sws,pflicht_lvs,onlinebewerbung_studienplan) VALUES
(4011, 401,'VZ','1','BS4-'||NearestWintersemester(-4)||'-VZ',6,NULL,true,15,true,now(),'anondata',NULL,NULL,NULL,180.00,NULL,NULL,true);
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(411, 'MOD1.1','Standard',4,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Standard','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(412, 'MOD1.2','Advanced',4,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Advanced','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(413, 'MOD1.3','Wahlmodul',4,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Wahlmodul','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(414, 'MOD1.4','Sonstiges',4,1,'English',6.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Sonstiges','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(461, 'MOD6.1','Bachelorarbeit',4,6,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Bachelorarbeit','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(462, 'MOD6.2','International Skills',4,6,'English',5.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','International Skills','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(463, 'MOD6.3','Berufspraktikum',4,6,'German',17.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'MOD','Berufspraktikum','VZ',5,'regulaer','modul','stg4',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL)
;
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(4111, 'S1','Standardvorlesung',4,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'VO','Standardvorlesung','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4121, 'S2','Vorlesung und Uebung',4,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'ILV','VorlesungUebung','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4131, 'S3','Getrennte Gruppen',4,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'ILV','Splittet Groups','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4141, 'A1','Mehrere Lektoren',4,1,'English',6.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'VO','Multilektor','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4611, 'BA','Bachelorarbeit',4,6,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'EL','Bachelorarbeit','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4621, 'INT','International Skills',4,6,'English',5.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'PRJ','International Skills','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(4631, 'BPRAK','Berufspraktikum',4,6,'German',17.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,now(),'anondata',now(),'anondata',NULL,NULL,true,NULL,false,'SO','Berufspraktikum','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL)
;
INSERT INTO lehre.tbl_studienplan_lehrveranstaltung (studienplan_lehrveranstaltung_id, studienplan_id,lehrveranstaltung_id,semester,studienplan_lehrveranstaltung_id_parent,pflicht,koordinator,insertamum,insertvon,updateamum,updatevon,sort,ext_id,curriculum,export,genehmigung) VALUES
-- MODULE im Studienplan
(401, 4011,411,1,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(402, 4011,412,1,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(403, 4011,413,1,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(404, 4011,414,1,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(461, 4011,461,6,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(462, 4011,462,6,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(463, 4011,463,6,NULL,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
-- LVS zu Modulen
(415, 4011,4111,1,401,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(416, 4011,4121,1,401,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(417, 4011,4131,1,401,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(418, 4011,4141,1,402,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(465, 4011,4611,6,461,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(466, 4011,4621,6,462,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true),
(467, 4011,4631,6,463,true,NULL,now(),'anondata',NULL,NULL,NULL,NULL,true,true,true)
;
INSERT INTO lehre.tbl_studienplan_semester (studienplan_id, studiensemester_kurzbz, semester) VALUES
(4011, NearestWintersemester(-4), 1),
(4011, NearestWintersemester(-3), 2),
(4011, NearestWintersemester(-2), 1),
(4011, NearestWintersemester(-2), 3),
(4011, NearestWintersemester(-1), 2),
(4011, NearestWintersemester(-1), 4),
(4011, NearestWintersemester(0), 1),
(4011, NearestWintersemester(0), 3),
(4011, NearestWintersemester(0), 5),
(4011, NearestWintersemester(+1), 2),
(4011, NearestWintersemester(+1), 4),
(4011, NearestWintersemester(+1), 6);
-- ===== Standardvorlesung
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41001, 4111, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4111, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4111, 1, 'Standard ein LV-Teil, ein Lektor, eine Gruppe');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41001, 4, '1', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41001, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
-- ===== VORLESUNG UND UEBUNG
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41002, 4121, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4121, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4121, 1, 'Vorlesung');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41002, 4, '1', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41002, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41003, 4121, NearestWintersemester(0), NULL, 'UE', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4121, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4121, 1, 'Uebung');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41003, 4, '1', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41003, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
-- ======= GETRENNTE GRUPPEN
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41004, 4131, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4131, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4131, 1, 'Vorlesung 1A');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41004, 4, '1', 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41004, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41005, 4131, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4131, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4131, 1, 'Vorlesung 1B');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41005, 4, '1', 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41005, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
-- ======= Mehrere Lektoren
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41006, 4141, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4141, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4141, 1, 'Vorlesung 1A und Lektor 2 und 3');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41006, 4, '1', 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41006, 'demolektor2', 'Lektor', 8, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 8.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41006, 'demolektor3', 'Lektor', 8, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 8.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41007, 4141, NearestWintersemester(0), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4141, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4141, 1, 'Vorlesung 1B und Lektor 4 und 5');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41007, 4, '1', 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41007, 'demolektor4', 'Lektor', 8, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 8.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41007, 'demolektor5', 'Lektor', 8, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 8.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(41008, 4141, NearestWintersemester(0), NULL, 'BE', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4141, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4141, 1, 'LV Leitung die nicht verplant wird');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41008, 4, '1', 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(41008, 4, '1', 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(41008, 'demolektor4', 'LV-Leitung', 0, NULL, 1.00, NULL, false, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 5.00, NULL, NULL);
-- ===== 6. Semester
-- ===== Bachelorarbeit
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(46111, 4611, NearestWintersemester(1), NULL, 'EL', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4111, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4611, 1, 'keine Verplanung');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(46111, 4, '6', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(46111, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
-- ===== Internation Skills
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(46211, 4621, NearestWintersemester(1), NULL, 'EL', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4111, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4621, 1, 'nur für Zeugnis');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(46211, 4, '6', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(46211, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
-- ===== BPRAK
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht, anmerkung)
VALUES(46311, 4631, NearestWintersemester(1), NULL, 'EL', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, 4111, NULL, '2023-08-24 14:54:43.000', 'anondata', '2023-08-24 14:54:43.000', 'anondata', NULL, 4631, 1, 'keine Verplanung');
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(46311, 4, '6', '', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'anondata', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(46311, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'anondata', NULL, 0.00, NULL, NULL);
+266
View File
@@ -0,0 +1,266 @@
-- Demodaten fuer Studierende im Studiengang 4
-- Personen
INSERT INTO public.tbl_person (person_id, staatsbuergerschaft,geburtsnation,sprache,anrede,titelpost,titelpre,vorname,nachname,vornamen,gebdatum,gebort,gebzeit,foto,anmerkung,homepage,svnr,ersatzkennzeichen,familienstand,geschlecht,anzahlkinder,aktiv,insertamum,insertvon,updateamum,updatevon,ext_id,bundesland_code,kompetenzen,kurzbeschreibung,zugangscode,foto_sperre,udf_values,bpk,matr_aktiv,matr_nr,zugangscode_timestamp,wahlname,unruly) VALUES
(401,'A','A',NULL,'Herr',NULL,NULL,'Mario','Super',NULL,'1974-11-11',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c401',false,NULL,NULL,false,NULL,NULL,NULL,false),
(402,'A','A',NULL,'Herr',NULL,NULL,'Luigi','Green',NULL,'1965-04-04',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c402',false,NULL,NULL,false,NULL,NULL,NULL,false),
(403,'A','A',NULL,'Frau',NULL,NULL,'Peach','Princess',NULL,'1954-12-28',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c403',false,NULL,NULL,false,NULL,NULL,NULL,false),
(404,'A','A',NULL,'Herr',NULL,NULL,'Toad','Mushroom',NULL,'1940-04-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c404',false,NULL,NULL,false,NULL,NULL,NULL,false),
(405,'A','A',NULL,'Herr',NULL,NULL,'Bowser','Koopa',NULL,'1937-06-01',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c405',false,NULL,NULL,false,NULL,NULL,NULL,false),
(406,'A','A',NULL,'Frau',NULL,NULL,'Link','Hyrule',NULL,'1957-04-29',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c406',false,NULL,NULL,false,NULL,NULL,NULL,false),
(407,'A','A',NULL,'Frau',NULL,NULL,'Zelda','Hyrule',NULL,'1924-04-03',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c407',false,NULL,NULL,false,NULL,NULL,NULL,false),
(408,'A','A',NULL,'Herr',NULL,NULL,'Donkey','Kong',NULL,'1956-07-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c408',false,NULL,NULL,false,NULL,NULL,NULL,false),
(409,'A','A',NULL,'Herr',NULL,NULL,'Yoshi','Dinosaur',NULL,'1963-06-09',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c409',false,NULL,NULL,false,NULL,NULL,NULL,false),
(410,'A','A',NULL,'Frau',NULL,NULL,'Rosalina','Lumaire',NULL,'1963-12-18',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c8410',false,NULL,NULL,false,NULL,NULL,NULL,false),
(411,'A','A',NULL,'Herr',NULL,NULL,'Wario','Warioh',NULL,'1968-09-25',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'m',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c411',false,NULL,NULL,false,NULL,NULL,NULL,false),
(412,'A','A',NULL,'Frau',NULL,NULL,'Waluigi','Big',NULL,'1964-09-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c412',false,NULL,NULL,false,NULL,NULL,NULL,false),
(413,'A','A',NULL,'Frau',NULL,NULL,'Melanie','Muster',NULL,'2010-04-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c413',false,NULL,NULL,false,NULL,NULL,NULL,false),
(414,'A','A',NULL,'Frau',NULL,NULL,'Tanja','Test',NULL,'2009-03-02',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c414',false,NULL,NULL,false,NULL,NULL,NULL,false),
(415,'A','A',NULL,'Frau',NULL,NULL,'Franziska','Fake',NULL,'2003-08-05',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c415',false,NULL,NULL,false,NULL,NULL,NULL,false),
(416,'A','A',NULL,'Herr',NULL,NULL,'Simon','Simulator',NULL,'2007-07-07',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'w',NULL,true,'2023-08-24 14:56:04.509813','auto','2025-05-13 10:57:19.826386',NULL,NULL,NULL,NULL,NULL,'64e753647c416',false,NULL,NULL,false,NULL,NULL,NULL,false)
;
SELECT setval('public.tbl_person_person_id_seq', (SELECT max(person_id) FROM public.tbl_person),true);
-- Prestudenten
INSERT INTO public.tbl_prestudent (prestudent_id, person_id,studiengang_kz,aufmerksamdurch_kurzbz,berufstaetigkeit_code,ausbildungcode,zgv_code,zgvort,zgvdatum,zgvmas_code,zgvmaort,zgvmadatum,aufnahmeschluessel,facheinschlberuf,reihungstest_id,anmeldungreihungstest,reihungstestangetreten,rt_gesamtpunkte,bismelden,insertamum,insertvon,updateamum,updatevon,ext_id,anmerkung,dual,rt_punkte1,rt_punkte2,ausstellungsstaat,rt_punkte3,udf_values,priorisierung,zgvdoktor_code,zgvdoktorort,zgvdoktordatum,mentor,zgvnation,zgvmanation,zgvdoktornation,gsstudientyp_kurzbz,aufnahmegruppe_kurzbz,foerderrelevant,standort_code,zgv_erfuellt,zgvmas_erfuellt,zgvdoktor_erfuellt) VALUES
(4401,401,4,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4402,402,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4403,403,4,'k.A.',NULL,NULL,9,NULL,'2020-06-03',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4404,404,4,'k.A.',NULL,NULL,9,NULL,'2020-06-04',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4405,405,4,'k.A.',NULL,NULL,9,NULL,'2020-06-05',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4406,406,4,'k.A.',NULL,NULL,9,NULL,'2020-06-06',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4407,407,4,'k.A.',NULL,NULL,9,NULL,'2020-06-07',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4408,408,4,'k.A.',NULL,NULL,9,NULL,'2020-06-08',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4409,409,4,'k.A.',NULL,NULL,9,NULL,'2020-06-09',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4410,410,4,'k.A.',NULL,NULL,9,NULL,'2020-06-10',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4411,411,4,'k.A.',NULL,NULL,9,NULL,'2020-06-01',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4412,412,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4413,413,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4414,414,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4415,415,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false),
(4416,416,4,'k.A.',NULL,NULL,9,NULL,'2020-06-02',NULL,NULL,NULL,NULL,false,NULL,NULL,true,NULL,true,NULL,NULL,'2023-08-24 14:56:04.509813',NULL,NULL,NULL,false,NULL,NULL,'A',0.0000,NULL,NULL,NULL,NULL,NULL,NULL,'A',NULL,NULL,'Intern',NULL,NULL,NULL,false,false,false)
;
SELECT setval('tbl_prestudent_prestudent_id_seq', (SELECT max(prestudent_id) FROM public.tbl_prestudent),true);
-- Prestudent Status Drittsemestrige
WITH status AS (
SELECT * FROM (VALUES
('Interessent',NearestWintersemester(-2),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-2)),'2023-08-24 14:56:04','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Bewerber',NearestWintersemester(-2),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-2)),'2023-08-24 14:58:11','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Aufgenommener',NearestWintersemester(-2),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-2)),'2023-08-24 14:58:14','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-2),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-2)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-1),2,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-1)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(0),3,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(0)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL)
) AS t(status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
),
inserts AS (
SELECT generate_series(4401, 4412) AS prestudent_id,*
FROM status
)
INSERT INTO public.tbl_prestudentstatus (prestudent_id, status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
SELECT prestudent_id, status_kurzbz, studiensemester_kurzbz, ausbildungssemester, datum::date, insertamum::timestamp, insertvon, updateamum::timestamp, updatevon,orgform_kurzbz,studienplan_id,bestaetigtam::date,bestaetigtvon,fgm::smallint,faktiv,anmerkung,bewerbung_abgeschicktamum::timestamp,rt_stufe::smallint,statusgrund_id::int
FROM inserts;
-- tbl_benutzer
WITH persons AS (
SELECT generate_series(401, 412) AS person_id
)
INSERT INTO public.tbl_benutzer (person_id, uid, aktiv, alias, insertamum, insertvon, updateamum, updatevon, updateaktivam, updateaktivvon, aktivierungscode)
SELECT person_id, 's425b' || person_id, true, null, now(), 'auto', null, null, null, false, null
FROM persons;
-- tbl_student
-- A Verband
WITH persons AS (
SELECT generate_series(401, 405) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's425b' || person_id, '2510004' || person_id, ('4' || person_id)::integer, '4', '3', 'A','', null, null, now(), 'auto'
FROM persons;
-- B Verband
WITH persons AS (
SELECT generate_series(406, 412) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's425b' || person_id, '2510004' || person_id, ('4' || person_id)::integer, '4', '3', 'B','', null, null, now(), 'auto'
FROM persons;
-- tbl_studentlehrverband
-- A Verband
WITH persons AS (
SELECT generate_series(401, 405) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-2), '4','1','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(401, 405) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-1), '4','2','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(401, 405) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(0), '4','3','A','', null, null, now(), 'auto'
FROM students;
-- B Verband
WITH persons AS (
SELECT generate_series(406, 412) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-2), '4','1','B','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(406, 412) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-1), '4','2','B','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(406, 412) AS person_id
),
students as (
SELECT ('s425b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(0), '4','3','B','', null, null, now(), 'auto'
FROM students;
---- 6 Semestrige
WITH status AS (
SELECT * FROM (VALUES
('Interessent',NearestWintersemester(-4),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-4)),'2023-08-24 14:56:04','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Bewerber',NearestWintersemester(-4),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-4)),'2023-08-24 14:58:11','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Aufgenommener',NearestWintersemester(-4),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-4)),'2023-08-24 14:58:14','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-4),1,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-4)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-3),2,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-3)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-2),3,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-2)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(-1),4,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(-1)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(0),5,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(0)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL),
('Student',NearestWintersemester(+1),6,(SELECT start FROM public.tbl_studiensemester WHERE studiensemester_kurzbz=NearestWintersemester(+1)),'2023-08-24 14:58:16','auto',NULL,NULL,NULL,3011,'2023-08-24','demoadmin',NULL,false,NULL,NULL,NULL,NULL)
) AS t(status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
),
inserts AS (
SELECT generate_series(4413, 4416) AS prestudent_id,*
FROM status
)
INSERT INTO public.tbl_prestudentstatus (prestudent_id, status_kurzbz,studiensemester_kurzbz,ausbildungssemester,datum,insertamum,insertvon,updateamum,updatevon,orgform_kurzbz,studienplan_id,bestaetigtam,bestaetigtvon,fgm,faktiv,anmerkung,bewerbung_abgeschicktamum,rt_stufe,statusgrund_id)
SELECT prestudent_id, status_kurzbz, studiensemester_kurzbz, ausbildungssemester, datum::date, insertamum::timestamp, insertvon, updateamum::timestamp, updatevon,orgform_kurzbz,studienplan_id,bestaetigtam::date,bestaetigtvon,fgm::smallint,faktiv,anmerkung,bewerbung_abgeschicktamum::timestamp,rt_stufe::smallint,statusgrund_id::int
FROM inserts;
-- tbl_benutzer
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
)
INSERT INTO public.tbl_benutzer (person_id, uid, aktiv, alias, insertamum, insertvon, updateamum, updatevon, updateaktivam, updateaktivvon, aktivierungscode)
SELECT person_id, 's46b' || person_id, true, null, now(), 'auto', null, null, null, false, null
FROM persons;
-- tbl_student
-- A Verband
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
)
INSERT INTO public.tbl_student (student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT 's46b' || person_id, '2510004' || person_id, ('4' || person_id)::integer, '4', '6', 'A','', null, null, now(), 'auto'
FROM persons;
-- tbl_studentlehrverband
-- A Verband
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-4), '4','1','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-3), '4','2','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-2), '4','3','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(-1), '4','4','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(0), '4','5','A','', null, null, now(), 'auto'
FROM students;
WITH persons AS (
SELECT generate_series(413, 416) AS person_id
),
students as (
SELECT ('s46b' || person_id) as student_uid, person_id
FROM persons
)
INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon)
SELECT student_uid, NearestWintersemester(+1), '4','6','A','', null, null, now(), 'auto'
FROM students;
@@ -0,0 +1,16 @@
INSERT INTO lehre.tbl_projektarbeit
(projektarbeit_id, projekttyp_kurzbz, titel, lehreinheit_id, student_uid, firma_id, note, punkte, beginn, ende, faktor, freigegeben, gesperrtbis, stundensatz, themenbereich, anmerkung, updateamum, updatevon, insertamum, insertvon, ext_id, gesamtstunden, titel_english, sprache, seitenanzahl, abgabedatum, kontrollschlagwoerter, schlagwoerter, schlagwoerter_en, abstract, abstract_en, "final") VALUES
(1, 'Bachelor', 'Auswirkung der Sonneneinstrahlung auf die Gesundheit', 46111, 's46b413', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(2, 'Bachelor', 'Neue Unterrichtsmethoden mit KI', 46111, 's46b414', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(3, 'Bachelor', 'Betrugsbekämpfung bei Anwesenheitskontrolle', 46111, 's46b415', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true),
(4, 'Bachelor', 'Neuronale Netze', 46111, 's46b416', NULL, NULL, NULL, NULL, NULL, NULL, true, NULL, NULL, NULL, NULL, NULL, NULL, '2025-12-12 14:06:10.000', 'anondata', NULL, 3.0000, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, true)
;
INSERT INTO lehre.tbl_projektbetreuer
(person_id, projektarbeit_id, note, faktor, "name", punkte, stundensatz, updateamum, updatevon, insertamum, insertvon, ext_id, betreuerart_kurzbz, stunden, zugangstoken, zugangstoken_gueltigbis, vertrag_id) VALUES
(21, 1, NULL, NULL, NULL, NULL, 80.00, NULL, NULL, '2025-12-12 14:07:10.000', 'anondata', NULL, 'Begutachter', 4.0000, NULL, NULL, NULL),
(21, 2, NULL, NULL, NULL, NULL, 80.00, NULL, NULL, '2025-12-12 14:07:10.000', 'anondata', NULL, 'Begutachter', 4.0000, NULL, NULL, NULL),
(21, 3, NULL, NULL, NULL, NULL, 80.00, NULL, NULL, '2025-12-12 14:07:10.000', 'anondata', NULL, 'Begutachter', 4.0000, NULL, NULL, NULL),
(21, 4, NULL, NULL, NULL, NULL, 80.00, NULL, NULL, '2025-12-12 14:07:10.000', 'anondata', NULL, 'Begutachter', 4.0000, NULL, NULL, NULL)
;
+107
View File
@@ -0,0 +1,107 @@
INSERT INTO campus.tbl_zeitwunsch_gueltigkeit
(zeitwunsch_gueltigkeit_id, mitarbeiter_uid, von, bis, insertamum, insertvon, updateamum, updatevon)
VALUES(1, 'demolektor1', '2020-09-01', NULL, NOW(), 'demolektor1', NULL, NULL);
INSERT INTO campus.tbl_zeitwunsch
(stunde, mitarbeiter_uid, tag, gewicht, updateamum, updatevon, insertamum, insertvon, zeitwunsch_id, zeitwunsch_gueltigkeit_id) VALUES
(1, 'demolektor1', 1, -2, now(), 'demolektor1', now(), 'demolektor1', 1, 1),
(2, 'demolektor1', 1, -2, now(), 'demolektor1', now(), 'demolektor1', 2, 1),
(3, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 3, 1),
(4, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 4, 1),
(5, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 5, 1),
(6, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 6, 1),
(7, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 7, 1),
(8, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 8, 1),
(9, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 9, 1),
(10, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 10, 1),
(11, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 11, 1),
(12, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 12, 1),
(13, 'demolektor1', 1, 2, now(), 'demolektor1', now(), 'demolektor1', 13, 1),
(14, 'demolektor1', 1, -1, now(), 'demolektor1', now(), 'demolektor1', 14, 1),
(15, 'demolektor1', 1, -1, now(), 'demolektor1', now(), 'demolektor1', 15, 1),
(16, 'demolektor1', 1, -1, now(), 'demolektor1', now(), 'demolektor1', 16, 1),
(1, 'demolektor1', 2, -2, now(), 'demolektor1', now(), 'demolektor1', 17, 1),
(2, 'demolektor1', 2, -1, now(), 'demolektor1', now(), 'demolektor1', 18, 1),
(3, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 19, 1),
(4, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 20, 1),
(5, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 21, 1),
(6, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 22, 1),
(7, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 23, 1),
(8, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 24, 1),
(9, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 25, 1),
(10, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 26, 1),
(11, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 27, 1),
(12, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 28, 1),
(13, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 29, 1),
(14, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 30, 1),
(15, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 31, 1),
(16, 'demolektor1', 2, 1, now(), 'demolektor1', now(), 'demolektor1', 32, 1),
(1, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 33, 1),
(2, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 34, 1),
(3, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 35, 1),
(4, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 36, 1),
(5, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 37, 1),
(6, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 38, 1),
(7, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 39, 1),
(8, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 40, 1),
(9, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 41, 1),
(10, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 42, 1),
(11, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 43, 1),
(12, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 44, 1),
(13, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 45, 1),
(14, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 46, 1),
(15, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 47, 1),
(16, 'demolektor1', 3, 1, now(), 'demolektor1', now(), 'demolektor1', 48, 1),
(1, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 49, 1),
(2, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 50, 1),
(3, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 51, 1),
(4, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 52, 1),
(5, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 53, 1),
(6, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 54, 1),
(7, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 55, 1),
(8, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 56, 1),
(9, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 57, 1),
(10, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 58, 1),
(11, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 59, 1),
(12, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 60, 1),
(13, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 61, 1),
(14, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 62, 1),
(15, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 63, 1),
(16, 'demolektor1', 4, 1, now(), 'demolektor1', now(), 'demolektor1', 64, 1),
(1, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 65, 1),
(2, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 66, 1),
(3, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 67, 1),
(4, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 68, 1),
(5, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 69, 1),
(6, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 70, 1),
(7, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 71, 1),
(8, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 72, 1),
(9, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 73, 1),
(10, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 74, 1),
(11, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 75, 1),
(12, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 76, 1),
(13, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 77, 1),
(14, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 78, 1),
(15, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 79, 1),
(16, 'demolektor1', 5, 1, now(), 'demolektor1', now(), 'demolektor1', 80, 1),
(1, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 81, 1),
(2, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 82, 1),
(3, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 83, 1),
(4, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 84, 1),
(5, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 85, 1),
(6, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 86, 1),
(7, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 87, 1),
(8, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 88, 1),
(9, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 89, 1),
(10, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 90, 1),
(11, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 91, 1),
(12, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 92, 1),
(13, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 93, 1),
(14, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 94, 1),
(15, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 95, 1),
(16, 'demolektor1', 6, 1, now(), 'demolektor1', now(), 'demolektor1', 96, 1)
;
SELECT setval('campus.seq_zeitwunsch_zeitwunsch_id', (select max(zeitwunsch_id) from campus.tbl_zeitwunsch), true);
SELECT setval('campus.seq_zeitwunsch_gueltigkeit_zeitwunsch_gueltigkeit_id', (select max(zeitwunsch_gueltigkeit_id) from campus.tbl_zeitwunsch_gueltigkeit),true);
+38
View File
@@ -0,0 +1,38 @@
INSERT INTO campus.tbl_content
(content_id, template_kurzbz, oe_kurzbz, insertamum, insertvon, updateamum, updatevon, aktiv, menu_open, beschreibung) VALUES
(30, 'contentmittitel', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(32, 'contentmittitel', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(33, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(34, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(35, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(36, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(37, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL),
(38, 'redirect', 'etw', now(), 'demoadmin', now(), 'demoadmin', true, false, NULL)
;
INSERT INTO campus.tbl_contentsprache (sprache, content_id, "version", sichtbar, "content", reviewvon, reviewamum, updateamum, updatevon, insertamum, insertvon, titel, gesperrt_uid) VALUES
('German', 30, 1, true, '<content></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'CIS4', NULL),
('German', 32, 1, true, '<content></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Studium', NULL),
('German', 33, 1, true, '<content><url><![CDATA[../cis.php/Cis/Stundenplan]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'LV-Plan', NULL),
('German', 34, 1, true, '<content><url><![CDATA[../cis.php/Cis4]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Dahsboard', NULL),
('German', 35, 1, true, '<content><url><![CDATA[../cis.php/Cis/MyLv]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Meine LVs', NULL),
('German', 36, 1, true, '<content><url><![CDATA[../cis.php/Cis/Studium]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Studium', NULL),
('German', 37, 1, true, '<content><url><![CDATA[../cis.php/Cis/Profil]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Profil', NULL),
('German', 38, 1, true, '<content><url><![CDATA[../cis.php/Cis/Documents]]></url><target><![CDATA[]]></target></content>', NULL, NULL, now(), 'demoadmin', now(), 'demoadmin', 'Dokumente', NULL)
;
INSERT INTO campus.tbl_contentchild (content_id, child_content_id, insertamum, insertvon, updateamum, updatevon, sort) VALUES
(30, 37, now(), 'demoadmin', NULL, NULL, 5),
(30, 27, now(), 'demoadmin', NULL, NULL, 7),
(30, 32, now(), 'demoadmin', NULL, NULL, 2),
(30, 34, now(), 'demoadmin', NULL, NULL, 1),
(32, 33, now(), 'demoadmin', NULL, NULL, 1),
(32, 36, now(), 'demoadmin', NULL, NULL, 2),
(32, 38, now(), 'demoadmin', NULL, NULL, 3),
(32, 35, now(), 'demoadmin', NULL, NULL, 4)
;
INSERT INTO campus.tbl_contentgruppe (content_id, gruppe_kurzbz, insertamum, insertvon) VALUES
(30, 'MA', now(), 'demoadmin'),
(30, 'STUD', now(), 'demoadmin')
;
+231
View File
@@ -0,0 +1,231 @@
-- Demodaten fuer Studiengang 5: Organisationseinheit, Studienordnung, Studiengang, Lehrveranstaltungen
INSERT INTO public.tbl_organisationseinheit (oe_kurzbz, oe_parent_kurzbz, bezeichnung, organisationseinheittyp_kurzbz, aktiv, mailverteiler, freigabegrenze, kurzzeichen, lehre, standort, warn_semesterstunden_frei, warn_semesterstunden_fix, standort_id)
VALUES('stg5', 'studiengaenge', 'Studiengang 5', 'Studiengang', true, false, NULL, NULL, true, NULL, NULL, NULL, NULL);
INSERT INTO public.tbl_studiengang (studiengang_kz,kurzbz,kurzbzlang,typ,bezeichnung,english,farbe,email,telefon,max_semester,max_verband,max_gruppe,erhalter_kz,bescheid,bescheidbgbl1,bescheidbgbl2,bescheidgz,bescheidvom,titelbescheidvom,aktiv,ext_id,orgform_kurzbz,zusatzinfo_html,moodle,oe_kurzbz,sprache,testtool_sprachwahl,studienplaetze,lgartcode,mischform,projektarbeit_note_anzeige,melderelevant,foerderrelevant,standort_code,onlinebewerbung,melde_studiengang_kz) VALUES
(5,'S5','STG5','b','Studiengang 5','Studiengang 5',NULL,'[email protected]',NULL,6,'B','2',5,NULL,NULL,NULL,NULL,NULL,NULL,true,NULL,'VZ','',true,'stg5','German',true,NULL,NULL,false,true,true,true,NULL,false,'0002')
;
INSERT INTO "system".tbl_benutzerrolle
(rolle_kurzbz, berechtigung_kurzbz, uid, funktion_kurzbz, oe_kurzbz, art, studiensemester_kurzbz, "start", ende, negativ, updateamum, updatevon, insertamum, insertvon, kostenstelle_id, anmerkung)
VALUES('assistenz', NULL, 'demoassistenz', NULL, 'stg5', 'suid', NULL, '2025-09-18', NULL, false, NULL, NULL, '2025-09-18 15:46:02.000', 'demoadmin', NULL, NULL);
INSERT INTO public.tbl_lehrverband (studiengang_kz, semester, verband, gruppe, aktiv, bezeichnung, ext_id, orgform_kurzbz) VALUES
(5, 1, '','', true, null, null, null),
(5, 1, 'A','', true, null, null, null),
(5, 1, 'B','', true, null, null, null),
(5, 2, '','', true, null, null, null),
(5, 2, 'A','', true, null, null, null),
(5, 2, 'B','', true, null, null, null),
(5, 3, '','', true, null, null, null),
(5, 3, 'A','', true, null, null, null),
(5, 3, 'B','', true, null, null, null),
(5, 4, '','', true, null, null, null),
(5, 4, 'A','', true, null, null, null),
(5, 4, 'B','', true, null, null, null),
(5, 5, '','', true, null, null, null),
(5, 5, 'A','', true, null, null, null),
(5, 5, 'B','', true, null, null, null),
(5, 6, '','', true, null, null, null),
(5, 6, 'A','', true, null, null, null),
(5, 6, 'B','', true, null, null, null)
;
INSERT INTO lehre.tbl_studienordnung (studienordnung_id, studiengang_kz,"version",gueltigvon,gueltigbis,bezeichnung,ects,studiengangbezeichnung,studiengangbezeichnung_englisch,studiengangkurzbzlang,akadgrad_id,insertamum,insertvon,updateamum,updatevon,ext_id,status_kurzbz,standort_id) VALUES
(501, 5,'1','WS2023',NULL,'BS5-WS2023',180.00,'Studiengang 5','Studiengang 5','STG5',NULL,'2023-08-24 14:25:41.728215','auto',NULL,NULL,NULL,'development',NULL);
INSERT INTO lehre.tbl_studienplan (studienplan_id, studienordnung_id,orgform_kurzbz,"version",bezeichnung,regelstudiendauer,sprache,aktiv,semesterwochen,testtool_sprachwahl,insertamum,insertvon,updateamum,updatevon,ext_id,ects_stpl,pflicht_sws,pflicht_lvs,onlinebewerbung_studienplan) VALUES
(5011, 501,'VZ','1','BS5-WS2023-VZ',6,NULL,true,15,true,'2023-08-24 14:26:12.751416','auto',NULL,NULL,NULL,180.00,NULL,NULL,true);
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(511, 'MOD1.1','Sport',5,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(512, 'MOD1.2','Mathematik',5,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(513, 'MOD1.3','Grundlagen',5,1,'German',8.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Basics','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(514, 'MOD1.4','Sprachen',5,1,'English',6.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(521, 'MOD2.1','Labor',5,2,'German',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Laboratory','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(522, 'MOD2.2','Mathematik',5,2,'German',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(523, 'MOD2.3','Sprachen',5,2,'English',10.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(531, 'MOD3.1','Mathematik',5,3,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Mathematics','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(532, 'MOD3.2','Elektrische Signale',5,3,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Electric Signals','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(541, 'MOD4.1','Messtechnik',5,4,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Measurement Technology','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(542, 'MOD4.2','Forschung',5,4,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Research','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(551, 'MOD5.1','Communication',5,5,'English',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Communication','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(552, 'MOD5.2','Regelungstechnik',5,5,'German',15.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Control Engineering','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL),
(561, 'MOD6.1','Bachelorarbeit',5,6,'German',30.00,NULL,NULL,true,'mod',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'MOD','Bachelor Thesis','VZ',5,'regulaer','modul','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,false,true,true,NULL)
;
INSERT INTO lehre.tbl_lehrveranstaltung (lehrveranstaltung_id, kurzbz,bezeichnung,studiengang_kz,semester,sprache,ects,semesterstunden,anmerkung,lehre,lehreverzeichnis,aktiv,planfaktor,planlektoren,planpersonalkosten,plankostenprolektor,updateamum,updatevon,insertamum,insertvon,ext_id,sort,zeugnis,koordinator,projektarbeit,lehrform_kurzbz,bezeichnung_english,orgform_kurzbz,incoming,lehrmodus_kurzbz,lehrtyp_kurzbz,oe_kurzbz,raumtyp_kurzbz,anzahlsemester,semesterwochen,lvnr,farbe,old_lehrfach_id,semester_alternativ,sws,lvs,alvs,lvps,las,benotung,lvinfo,lehrauftrag,lehrveranstaltung_template_id) VALUES
(5111, 'LS','Leistungssport',5,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5121, 'MAT','Mathematik 1',5,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5131, 'GL','Grundlagen der Programmierung',5,1,'German',8.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Development Basics','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5141, 'ENG','Englisch 1',5,1,'English',6.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5211, 'EL','Elektronik Labor',5,2,'German',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'LAB','Laboratory','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5221, 'MAT','Mathematik 2',5,2,'German',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5231, 'ENG','Communcation Englisch',5,2,'English',10.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5311, 'MAT','Mathematik 3',5,3,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Mathematics','VZ',5,'regulaer','lv','kfMath',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5321, 'ES','Elektrische Signale',5,3,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Electric Signals','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5411, 'MT','Messtechnik',5,4,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Measurement Technology','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5421, 'BAN','Bewegungsanalyse',5,4,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Movement Analytics','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5511, 'ENG','Communication',5,5,'English',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'VO','Communication','VZ',5,'regulaer','lv','kfSprachen',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5521, 'RT','Regelungstechnik',5,5,'German',15.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'ILV','Control Engineering','VZ',5,'regulaer','lv','kfTech',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL),
(5611, 'BA','Bachelorarbeit',5,6,'German',30.00,NULL,NULL,true,'lv',true,NULL,NULL,NULL,NULL,'2023-08-24 14:28:39','oesi','2023-08-24 14:28:39','oesi',NULL,NULL,true,NULL,false,'SE','Bachelor Thesis','VZ',5,'regulaer','lv','stg5',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,true,true,true,NULL)
;
INSERT INTO lehre.tbl_studienplan_lehrveranstaltung (studienplan_lehrveranstaltung_id, studienplan_id,lehrveranstaltung_id,semester,studienplan_lehrveranstaltung_id_parent,pflicht,koordinator,insertamum,insertvon,updateamum,updatevon,sort,ext_id,curriculum,export,genehmigung) VALUES
-- MODULE im Studienplan
(501, 5011,511,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(502, 5011,512,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(503, 5011,513,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(504, 5011,514,1,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(505, 5011,521,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(506, 5011,522,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(507, 5011,523,2,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(508, 5011,531,3,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(509, 5011,532,3,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(510, 5011,541,4,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(511, 5011,542,4,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(512, 5011,551,5,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(513, 5011,552,5,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(514, 5011,561,6,NULL,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
-- LVS zu Modulen
(515, 5011,5111,1,501,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(516, 5011,5121,1,502,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(517, 5011,5131,1,503,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(518, 5011,5141,1,504,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(519, 5011,5211,2,505,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(520, 5011,5221,2,519,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(521, 5011,5231,2,507,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(522, 5011,5311,3,508,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(523, 5011,5321,3,509,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(524, 5011,5411,4,510,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(525, 5011,5421,4,511,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(526, 5011,5511,5,512,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(527, 5011,5521,5,513,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true),
(528, 5011,5611,6,514,true,NULL,'2023-08-24 14:29:03.506117','oesi',NULL,NULL,NULL,NULL,true,true,true)
;
INSERT INTO lehre.tbl_studienplan_semester (studienplan_id, studiensemester_kurzbz, semester) VALUES
(5011, 'WS2023', 1),
(5011, 'SS2024', 2),
(5011, 'WS2024', 1),
(5011, 'WS2024', 3),
(5011, 'SS2025', 2),
(5011, 'SS2025', 4),
(5011, 'WS2025', 1),
(5011, 'WS2025', 3),
(5011, 'WS2025', 5),
(5011, 'SS2026', 2),
(5011, 'SS2026', 4),
(5011, 'SS2026', 6);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51001, 5221, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5221, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5221, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51001, 5, 1, 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51001, 5, 1, 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51001, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51002, 5121, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5121, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5121, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51002, 5, 1, 'B', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51002, 'demolektor2', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51003, 5141, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5141, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5141, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51003, 5, 1, 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51003, 'demolektor3', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51004, 5211, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5211, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5211, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51004, 5, 1, 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51004, 'demolektor4', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51005, 5311, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5311, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5311, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51005, 5, 1, 'A', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51005, 'demolektor4', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht)
VALUES(51006, 5321, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5321, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5321, 1);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51006, 5, 1, 'C', NULL, NULL, NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitmitarbeiter
(lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz, planstunden, stundensatz, faktor, anmerkung, bismelden, updateamum, updatevon, insertamum, insertvon, ext_id, semesterstunden, standort_id, vertrag_id)
VALUES(51006, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL);
-- Stundenplan Eintraege
INSERT INTO lehre.tbl_stundenplandev
(stundenplandev_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(510011, 51001, 51001, 5, 1, 'A', '', NULL, 'demolektor1', 'EG04', '2025-07-31', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplan
(stundenplan_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(510011, 51001, 51001, 5, 1, 'A', '', NULL, 'demolektor1', 'EG04', '2025-07-31', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplandev
(stundenplandev_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(510021, 31002, 31002, 5, 1, 'B', '', NULL, 'demolektor1', 'EG04', '2025-08-01', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO lehre.tbl_stundenplan
(stundenplan_id, lehreinheit_id, unr, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, mitarbeiter_uid, ort_kurzbz, datum, stunde, titel, anmerkung, fix, updateamum, updatevon, insertamum, insertvon)
VALUES(510021, 31002, 31002, 5, 1, 'B', '', NULL, 'demolektor1', 'EG04', '2025-08-01', 7, NULL, NULL, false, '2025-07-31 13:50:49.419', 'demoadmin', '2025-07-31 13:50:49.419', NULL);
INSERT INTO public.tbl_studentlehrverband
(student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES('s125b101', LastActiveSemester(), 5, 2, ' ', ' ', NULL, NULL, '2026-06-11 14:33:58.403', 'auto', NULL);
INSERT INTO public.tbl_gruppe (gruppe_kurzbz, studiengang_kz, semester, bezeichnung, beschreibung, sichtbar, lehre, aktiv, sort, mailgrp, generiert, updateamum, updatevon, insertamum, insertvon, ext_id, orgform_kurzbz, content_visible, gesperrt, direktinskription, zutrittssystem, aufnahmegruppe) VALUES
('GRP_51003', 5, 2, 'BS5 2 ENG', null, false, false, true, NULL, false, false, now(), 'demoadmin', now(), 'demoadmin', NULL, NULL, true, false, true, false, false),
('GRP_51004', 5, 2, 'BS5 2 EL', null, false, false, true, NULL, false, false, now(), 'demoadmin', now(), 'demoadmin', NULL, NULL, true, false, true, false, false)
;
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51003, 5, 2, NULL, NULL, 'GRP_51003', NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO lehre.tbl_lehreinheitgruppe
(lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id)
VALUES(51004, 5, 2, NULL, NULL, 'GRP_51004', NULL, NULL, '2023-08-24 14:58:26.000', 'oesi', NULL);
INSERT INTO public.tbl_benutzergruppe (uid, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id, studiensemester_kurzbz) VALUES
('s125b101', 'GRP_51003', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL),
('s125b101', 'GRP_51004', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL)
;
+11
View File
@@ -0,0 +1,11 @@
INSERT INTO wawi.tbl_betriebsmitteltyp
(betriebsmitteltyp, beschreibung, anzahl, kaution, typ_code, mastershapename)
VALUES('Inventar', NULL, NULL, NULL, NULL, NULL);
INSERT INTO wawi.tbl_betriebsmittel
(betriebsmittel_id, beschreibung, betriebsmitteltyp, nummer, reservieren, updateamum, updatevon, insertamum, insertvon, ext_id, inventarnummer, oe_kurzbz, ort_kurzbz, hersteller, seriennummer, bestellung_id, bestelldetail_id, afa, verwendung, anmerkung, leasing_bis, inventuramum, inventurvon, anschaffungswert, anschaffungsdatum, tiefe, hoehe, breite, nummer2, verplanen)
VALUES
(1, 'pc', 'Laptop', NULL, false, '2024-03-07 08:17:33.000', 'demoadmin', '2015-12-01 14:55:32.000', 'demoadmin', NULL, '00001', NULL, NULL, 'pc', NULL, NULL, NULL, 3, NULL, 'Angelegt von demoadmin für die test', NULL, '2015-12-01 14:55:32.000', 'demoadmin', NULL, NULL, NULL, NULL, NULL, NULL, true),
(2, 'projector', 'Inventar', NULL, false, '2024-03-07 08:17:33.000', 'demoadmin', '2015-12-01 14:55:32.000', 'demoadmin', NULL, '00002', NULL, NULL, 'projector', NULL, NULL, NULL, 3, NULL, 'Angelegt von demoadmin für die test', NULL, '2015-12-01 14:55:32.000', 'demoadmin', NULL, NULL, NULL, NULL, NULL, NULL, true),
(3, 'workstation', 'Inventar', NULL, false, '2024-03-07 08:17:33.000', 'demoadmin', '2015-12-01 14:55:32.000', 'demoadmin', NULL, '00003', NULL, NULL, 'workstation', NULL, NULL, NULL, 3, NULL, 'Angelegt von demoadmin für die test', NULL, '2015-12-01 14:55:32.000', 'demoadmin', NULL, NULL, NULL, NULL, NULL, NULL, true),
(4, 'pc2', 'Laptop', NULL, false, '2024-03-07 08:17:33.000', 'demoadmin', '2015-12-01 14:55:32.000', 'demoadmin', NULL, '00004', NULL, NULL, 'pc2', NULL, NULL, NULL, 3, NULL, 'Angelegt von demoadmin für die test', NULL, '2015-12-01 14:55:32.000', 'demoadmin', NULL, NULL, NULL, NULL, NULL, NULL, true);
+210
View File
@@ -0,0 +1,210 @@
-- Rooms setup for calendar tests
INSERT INTO public.tbl_adresse
(adresse_id, person_id, "name", strasse, plz, ort, gemeinde, nation, typ, heimatadresse, zustelladresse, firma_id, updateamum, updatevon, insertamum, insertvon, ext_id, rechnungsadresse, anmerkung, co_name)
VALUES(1, NULL, 'Hauptwohnsitz', 'Stromstraße 18-20/1/10', '1200', 'Wien', 'Wien', 'A', 'h', true, true, NULL, '2007-08-13 10:53:40.298', 'demoadmin', '2007-08-10 10:42:02.579', 'demoadmin', 14470, false, NULL, NULL);
INSERT INTO public.tbl_standort
(kurzbz, adresse_id, standort_id, bezeichnung, insertvon, insertamum, updatevon, updateamum, ext_id, firma_id, code)
VALUES('Vienna Universit', 1, 1, 'Vienna University of Technology, Institute of Design and Assessment of Technology', 'demoadmin', '2012-02-02 10:24:11.803', 'demoadmin', '2015-05-27 09:05:53.894', NULL, 6033, NULL);
INSERT INTO public.tbl_ort
(ort_kurzbz, bezeichnung, planbezeichnung, max_person, lehre, reservieren, aktiv, lageplan, dislozierung, kosten, ausstattung, updateamum, updatevon, insertamum, insertvon, ext_id, stockwerk, telefonklappe, standort_id, content_id, m2, gebteil, oe_kurzbz, arbeitsplaetze)
VALUES
('Bro_F7.37', 'Büro', 'F7.37', NULL, true, true, true, NULL, NULL, NULL, NULL, '2023-09-19 10:35:20.000', 'demoadmin', '2012-09-05 15:20:25.979', 'demoadmin', NULL, 7, NULL, 1, NULL, 21.58, 'F', 'etw', NULL),
('Bro_F7.38', 'Büro', 'F7.38', NULL, true, true, true, NULL, NULL, NULL, NULL, '2023-09-19 10:35:20.000', 'demoadmin', '2012-09-05 15:20:25.979', 'demoadmin', NULL, 7, NULL, 1, NULL, 21.58, 'F', 'etw', NULL),
('Bro_F7.39', 'Büro', 'F7.39', NULL, true, true, true, NULL, NULL, NULL, NULL, '2023-09-19 10:35:20.000', 'demoadmin', '2012-09-05 15:20:25.979', 'demoadmin', NULL, 7, NULL, 1, NULL, 21.58, 'F', 'etw', NULL),
('Bro_F7.40', 'Büro', 'F7.40', NULL, true, true, true, NULL, NULL, NULL, NULL, '2023-09-19 10:35:20.000', 'demoadmin', '2012-09-05 15:20:25.979', 'demoadmin', NULL, 7, NULL, 1, NULL, 21.58, 'F', 'etw', NULL),
('Bro_F7.41', 'Büro', 'F7.41', NULL, true, true, true, NULL, NULL, NULL, NULL, '2023-09-19 10:35:20.000', 'demoadmin', '2012-09-05 15:20:25.979', 'demoadmin', NULL, 7, NULL, 1, NULL, 21.58, 'F', 'etw', NULL);
INSERT INTO public.tbl_ortraumtyp
(ort_kurzbz, hierarchie, raumtyp_kurzbz)
VALUES
('Bro_F7.37', 1, 'Dummy'),
('Bro_F7.38', 1, 'Dummy'),
('Bro_F7.39', 1, 'Dummy'),
('Bro_F7.40', 1, 'Dummy'),
('Bro_F7.41', 1, 'Dummy');
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for event drag and drop tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon) VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '08:00:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '08:45:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '08:45:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '09:30:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '09:40:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '11:10:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '09:40:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '09:40:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '11:10:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '10:25:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '11:10:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_ort
(location, ort_kurzbz, kalender_id)
VALUES(NULL, 'Bro_F7.37', 1);
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51001, 1),
(51002, 2),
(51003, 3),
(51003, 4),
(51002, 5),
(51006, 6),
(51002, 7),
(51006, 8);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for resize tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon) VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '08:00:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '08:45:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '10:25:00', date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '11:10:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '10:25:00', date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '11:10:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51001, 9),
(51003, 10),
(51002, 11);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for role preview tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon) VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '13:35:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '14:20:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '13:35:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '14:20:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51001, 12),
(51002, 13);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for API event creation tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon) VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '18:35:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '19:20:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '18:35:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '19:20:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51003, 14),
(51005, 15);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for API event update tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon)
VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '1 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '1 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '21:00:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '3 day' + TIME '21:00:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '4 day' + TIME '21:00:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '21:00:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '5 day' + TIME '21:00:00', 'reservierung', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_ort
(location, ort_kurzbz, kalender_id)
VALUES
(NULL, 'Bro_F7.37', 17),
(NULL, 'Bro_F7.37', 18);
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51001, 16),
(51001, 17),
(51003, 18),
(51001, 19),
(51003, 20),
(51003, 21),
(51006, 22),
(51004, 23),
(51005, 24),
(51004, 25),
(51006, 26);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for Stundenraster disabled tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, insertamum, insertvon, updateamum, updatevon) VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '11:20:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '12:05:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '11:20:00', date_trunc('week', CURRENT_DATE) + INTERVAL '2 day' + TIME '12:05:00', 'lehreinheit', 'live', NULL, now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51002, 27),
(51006, 28);
-- ////////////////////////////////////////////////////////////////////////////////////////////////////
-- Calendar setup for resources tests
INSERT INTO lehre.tbl_kalender
(von, bis, typ, status_kurzbz, vorgaenger_kalender_id, eindeutige_gruppen_id, insertamum, insertvon, updateamum, updatevon)
VALUES
(date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '19:30:00', date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '20:15:00', 'lehreinheit', 'live', NULL, 'ec1bd001-facf-4b21-a671-bcb2d4f037fd', now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '20:15:00', date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '21:00:00', 'lehreinheit', 'live', NULL, 'ec2bd001-facf-4b21-a671-bcb2d4f037fd', now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '17:50:00', date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '18:35:00', 'lehreinheit', 'live', NULL, 'ec3bd001-facf-4b21-a671-bcb2d4f037fd', now(), 'demoadmin', NULL, 'demoadmin'),
(date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '18:35:00', date_trunc('week', CURRENT_DATE) + INTERVAL '6 day' + TIME '19:20:00', 'lehreinheit', 'live', NULL, 'ec4bd001-facf-4b21-a671-bcb2d4f037fd', now(), 'demoadmin', NULL, 'demoadmin')
;
INSERT INTO lehre.tbl_kalender_lehreinheit
(lehreinheit_id, kalender_id)
VALUES
(51004, 29),
(51006, 30),
(51006, 31),
(51004, 32);
-- INSERT INTO public.tbl_variablenname
-- (name, defaultwert)
-- VALUES('ignore_resources_collisions', 'false');
INSERT INTO public.tbl_variable
(name, uid, wert)
VALUES('ignore_resources_collisions', 'demoadmin', 'false');
INSERT INTO lehre.tbl_betriebsmittel_kalender
(eindeutige_kalender_gruppen_id, betriebsmittel_id, anmerkung, quelle, insertamum, insertvon, updateamum, updatevon)
VALUES
('ec1bd001-facf-4b21-a671-bcb2d4f037fd'::uuid, 1, '', 'tempus_neu', '2026-06-17 16:48:59.669', 'demoadmin', '2026-06-17 17:13:23.000', 'demoadmin'),
('ec2bd001-facf-4b21-a671-bcb2d4f037fd'::uuid, 1, '', 'tempus_neu', '2026-06-17 16:48:59.669', 'demoadmin', '2026-06-17 17:13:23.000', 'demoadmin'),
('ec3bd001-facf-4b21-a671-bcb2d4f037fd'::uuid, 2, '', 'tempus_neu', '2026-06-17 16:48:59.669', 'demoadmin', '2026-06-17 17:13:23.000', 'demoadmin'),
('ec4bd001-facf-4b21-a671-bcb2d4f037fd'::uuid, 3, '', 'tempus_neu', '2026-06-17 16:48:59.669', 'demoadmin', '2026-06-17 17:13:23.000', 'demoadmin');
-- //////////////////////////////////////////////////////////////////////////////////////////////////--
INSERT INTO lehre.tbl_kalender_event
(kalender_id, titel, beschreibung)
VALUES(26, 'Test reservation', NULL);
INSERT INTO lehre.tbl_kalender_event_teilnehmer
(kalender_id, rolle_kurzbz, uid, studiensemester_kurzbz, gruppe_kurzbz, studiengang_kz, semester, verband, gruppe, studentenlehrverband_id)
VALUES(26, 'teilnehmer', 'demolektor4', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO campus.tbl_zeitsperre
(zeitsperre_id, zeitsperretyp_kurzbz, mitarbeiter_uid, bezeichnung, vondatum, vonstunde, bisdatum, bisstunde, vertretung_uid, updateamum, updatevon, insertamum, insertvon, erreichbarkeit_kurzbz, freigabeamum, freigabevon)
VALUES(1, 'DienstV', 'demolektor1', 'Test', date_trunc('week', CURRENT_DATE) + INTERVAL '5 day', NULL, date_trunc('week', CURRENT_DATE) + INTERVAL '5 day', NULL, 'demoadmin', '2007-04-02 11:04:31.000', 'demoadmin', '2007-04-02 11:04:31.000', 'demoadmin', 't', NULL, NULL);
+183
View File
@@ -0,0 +1,183 @@
-- Demo data for the Benotungstool / Gesamtnoteneingabe test suite.
--
-- campus.vw_student_lehrveranstaltung, the source of getStudentsByLv(), links students to
-- Lehreinheiten through tbl_lehreinheitgruppe.gruppe_kurzbz = tbl_benutzergruppe.gruppe_kurzbz AND
-- a matching Studiensemester.
--
-- RESULT: demolektor1 -> LV 5221 (12 students), demolektor2 -> LV 5121 (6, the foreign LV for the
-- access tests).
BEGIN;
-- Test semester: the running one, else the last started. Same rule as the suite.
CREATE TEMP TABLE sem AS
SELECT studiensemester_kurzbz AS kurzbz
FROM public.tbl_studiensemester
WHERE start <= now()
ORDER BY (ende >= now()) DESC, start DESC
LIMIT 1;
-- The two LV fixtures. Own Lehreinheiten (511xx) so the tempus fixtures 51001-51006 stay untouched.
-- members_up_to = highest person_id that joins this group.
CREATE TEMP TABLE lv AS
SELECT v.*, l.semester
FROM (VALUES
(true, 5221, 51101, 'GRP_CYNOTEN_H', 'Cypress Noten Haupt', 'demolektor1', 512),
(false, 5121, 51102, 'GRP_CYNOTEN_F', 'Cypress Noten Fremd', 'demolektor2', 506)
) AS v(main, lv_id, le_id, grp, grp_text, lektor, members_up_to)
JOIN lehre.tbl_lehrveranstaltung l ON l.lehrveranstaltung_id = v.lv_id;
-- The 12 students. person_id is the anchor for every derived key.
CREATE TEMP TABLE stud AS
SELECT id AS person_id, 5000 + id AS prestudent_id, 's525b' || id AS uid
FROM generate_series(501, 512) AS g(id);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM sem) THEN
RAISE EXCEPTION 'No Studiensemester found, the base dump is missing.';
END IF;
IF (SELECT count(*) FROM lv) <> 2 THEN
RAISE EXCEPTION 'LV 5221/5121 missing, apply 013_studiengang_5.sql.';
END IF;
END $$;
-- Termin3 is absent from the base dump; without it every Termin3 insert hits a foreign key error.
INSERT INTO lehre.tbl_pruefungstyp (pruefungstyp_kurzbz, beschreibung)
VALUES ('Termin3', '3. Termin')
ON CONFLICT DO NOTHING;
-- ------------------------------------------------------------------------------------- students
INSERT INTO public.tbl_person (person_id, vorname, nachname, gebdatum, geschlecht, aktiv)
SELECT person_id, 'Noten', 'Student ' || (person_id - 500), '2000-01-15', 'm', true
FROM stud
ON CONFLICT DO NOTHING;
INSERT INTO public.tbl_prestudent (prestudent_id, person_id, studiengang_kz)
SELECT prestudent_id, person_id, 5
FROM stud
ON CONFLICT DO NOTHING;
INSERT INTO public.tbl_prestudentstatus
(prestudent_id, status_kurzbz, studiensemester_kurzbz, ausbildungssemester)
SELECT s.prestudent_id, 'Student', sem.kurzbz, lv.semester
FROM stud s, sem, lv
WHERE lv.main
ON CONFLICT DO NOTHING;
INSERT INTO public.tbl_benutzer (uid, person_id, aktiv)
SELECT uid, person_id, true
FROM stud
ON CONFLICT DO NOTHING;
-- matrikelnr is UNIQUE; scheme of the existing seeders is '251000' + studiengang_kz + person_id
INSERT INTO public.tbl_student
(student_uid, matrikelnr, prestudent_id, studiengang_kz, semester, verband, gruppe)
SELECT s.uid, '2510005' || s.person_id, s.prestudent_id, 5, lv.semester, '', ''
FROM stud s, lv
WHERE lv.main
ON CONFLICT DO NOTHING;
-- Lehrverband assignment; (5, <semester>, '', '') is created by 013_studiengang_5.sql.
INSERT INTO public.tbl_studentlehrverband
(student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe)
SELECT s.uid, sem.kurzbz, 5, lv.semester, '', ''
FROM stud s, sem, lv
WHERE lv.main
ON CONFLICT DO NOTHING;
-- ------------------------------------------------------------------- Lehreinheiten and Lektoren
INSERT INTO lehre.tbl_lehreinheit
(lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrform_kurzbz,
wochenrythmus, raumtyp, raumtypalternativ, sprache, lehrfach_id)
SELECT lv.le_id, lv.lv_id, sem.kurzbz, 'VO', 1, 'Dummy', 'Dummy', 'German', lv.lv_id
FROM lv, sem
ON CONFLICT DO NOTHING;
-- Fix the semester if the Lehreinheit is left over from a run in a different one.
UPDATE lehre.tbl_lehreinheit le
SET studiensemester_kurzbz = sem.kurzbz
FROM lv, sem
WHERE le.lehreinheit_id = lv.le_id
AND le.studiensemester_kurzbz IS DISTINCT FROM sem.kurzbz;
INSERT INTO lehre.tbl_lehreinheitmitarbeiter (lehreinheit_id, mitarbeiter_uid, lehrfunktion_kurzbz)
SELECT le_id, lektor, 'Lektor'
FROM lv
ON CONFLICT DO NOTHING;
-- --------------------------------------------------------------------------------------- groups
INSERT INTO public.tbl_gruppe (gruppe_kurzbz, studiengang_kz, semester, bezeichnung, aktiv)
SELECT grp, 5, semester, grp_text, true
FROM lv
ON CONFLICT DO NOTHING;
-- The row the existing seeders lack: attach the group to the Lehreinheit with gruppe_kurzbz set.
-- The primary key is a serial, so NOT EXISTS instead of ON CONFLICT.
INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, gruppe_kurzbz)
SELECT lv.le_id, 5, lv.semester, lv.grp
FROM lv
WHERE NOT EXISTS (SELECT 1 FROM lehre.tbl_lehreinheitgruppe g
WHERE g.lehreinheit_id = lv.le_id AND g.gruppe_kurzbz = lv.grp);
-- Membership WITH a semester. The primary key is (uid, gruppe_kurzbz) and excludes the semester,
-- so DO UPDATE repairs a row from an earlier run instead of duplicating it.
INSERT INTO public.tbl_benutzergruppe (uid, gruppe_kurzbz, studiensemester_kurzbz)
SELECT s.uid, lv.grp, sem.kurzbz
FROM stud s, lv, sem
WHERE s.person_id <= lv.members_up_to
ON CONFLICT (uid, gruppe_kurzbz) DO UPDATE
SET studiensemester_kurzbz = EXCLUDED.studiensemester_kurzbz;
-- -------------------------------------------------------------------------------- Notenschluessel
INSERT INTO lehre.tbl_notenschluessel (notenschluessel_kurzbz, bezeichnung)
VALUES ('CYNOTEN', 'Cypress Testnotenschluessel')
ON CONFLICT DO NOTHING;
-- getNote() takes the row with the largest punkte value <= the points given. The 0 threshold makes
-- sure every value maps to a grade. Serial primary key, so NOT EXISTS.
INSERT INTO lehre.tbl_notenschluesselaufteilung (notenschluessel_kurzbz, note, punkte)
SELECT 'CYNOTEN', a.note, a.punkte
FROM (VALUES (5, 0.0), (4, 51.0), (3, 64.0), (2, 77.0), (1, 90.0)) AS a(note, punkte)
WHERE NOT EXISTS (SELECT 1 FROM lehre.tbl_notenschluesselaufteilung x
WHERE x.notenschluessel_kurzbz = 'CYNOTEN' AND x.punkte = a.punkte);
-- Set the semester explicitly: getKurzbzForLv() builds "... AND studiensemester_kurzbz = ? OR
-- studiensemester_kurzbz IS NULL" without parentheses, so a NULL-semester assignment would apply
-- to every Lehrveranstaltung through AND/OR precedence.
INSERT INTO lehre.tbl_notenschluesselzuordnung
(notenschluessel_kurzbz, lehrveranstaltung_id, studiensemester_kurzbz)
SELECT 'CYNOTEN', lv.lv_id, sem.kurzbz
FROM lv, sem
WHERE lv.main
AND NOT EXISTS (SELECT 1 FROM lehre.tbl_notenschluesselzuordnung z
WHERE z.notenschluessel_kurzbz = 'CYNOTEN'
AND z.lehrveranstaltung_id = lv.lv_id
AND z.studiensemester_kurzbz = sem.kurzbz);
COMMIT;
-- Fires if the view stays empty anyway, which is the bug this seeder exists to fix.
DO $$
DECLARE v_count integer;
BEGIN
SELECT count(*) INTO v_count
FROM campus.vw_student_lehrveranstaltung v, sem
WHERE v.lehrveranstaltung_id = 5221 AND v.studiensemester_kurzbz = sem.kurzbz;
IF v_count = 0 THEN
RAISE EXCEPTION 'No students in LV 5221 (%), fixture unusable.', (SELECT kurzbz FROM sem);
END IF;
RAISE NOTICE 'OK: % students in LV 5221 (%)', v_count, (SELECT kurzbz FROM sem);
END $$;
SELECT (SELECT kurzbz FROM sem) AS semester,
(SELECT count(*) FROM campus.vw_student_lehrveranstaltung v, sem
WHERE v.lehrveranstaltung_id = 5221 AND v.studiensemester_kurzbz = sem.kurzbz) AS lv5221,
(SELECT count(*) FROM campus.vw_student_lehrveranstaltung v, sem
WHERE v.lehrveranstaltung_id = 5121 AND v.studiensemester_kurzbz = sem.kurzbz) AS lv5121,
(SELECT note FROM lehre.tbl_note WHERE bezeichnung = 'entschuldigt') AS entschuldigt,
(SELECT note FROM lehre.tbl_note WHERE bezeichnung = 'Noch nicht eingetragen') AS noch_nicht,
(SELECT count(*) FROM lehre.tbl_notenschluesselaufteilung
WHERE notenschluessel_kurzbz = 'CYNOTEN') AS notenschluessel;
+33
View File
@@ -0,0 +1,33 @@
-- Grant all db users access to the "extension" schema.
--
-- The dump creates the schema and gives it no grants, unlike public/lehre/campus, and
-- truncate_db.sql only grants on public. Any application not connecting as the owner then fails
-- every query in that schema with "permission denied for schema extension"
DO $$
DECLARE
v_role text;
v_roles text[] := ARRAY['web', 'vilesci', 'wawi', 'admin'];
v_done integer := 0;
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_namespace WHERE nspname = 'extension') THEN
RAISE NOTICE 'Schema "extension" does not exist, skipped.';
RETURN;
END IF;
FOREACH v_role IN ARRAY v_roles
LOOP
CONTINUE WHEN NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = v_role);
EXECUTE format('GRANT USAGE ON SCHEMA extension TO %I', v_role);
EXECUTE format('GRANT SELECT ON ALL TABLES IN SCHEMA extension TO %I', v_role);
EXECUTE format('GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA extension TO %I', v_role);
-- and for whatever an addon creates later
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA extension GRANT SELECT ON TABLES TO %I', v_role);
EXECUTE format('ALTER DEFAULT PRIVILEGES IN SCHEMA extension GRANT EXECUTE ON FUNCTIONS TO %I', v_role);
v_done := v_done + 1;
END LOOP;
RAISE NOTICE 'Granted on schema "extension" for % role(s).', v_done;
END $$;
+32
View File
@@ -0,0 +1,32 @@
== README ==
Dieser Ordner enthält Anonyme Demo Daten
Diese können auf einen leeren FH-Complete Dump angewandt werden um Demo/Testdaten einzufügen.
Die Datensätze werden mit fixen IDs erstellt um die Verknüpfung der Elemente Untereinander zu ermöglichen.
Danach werden die Sequences entsprechend aktualisiert.
Die Inserts können daher nur auf einen leeren Dump gespielt werden da es sonst zu ID Konflikten kommmen kann.
== Logik der ID Generierung ==
Studiengangskennzahl 1
Studierende des Studiengangs 1 haben Person ID 3-Stellig mit Studiengangskennzahl startend : 101, 102, 103
PrestudentID ist 4-Stellig mit Studiengangskennzahl+PersonID: 1101, 1102, 1103
Dadurch können Inserts leichter erstellt werden.
Bei Lehrveranstaltungen gilt ähnliches Konzept für
Studienordnung
Studienplan
Modul
Lehrveranstaltung
== Helper Funktionen ==
Damit die Daten immer im aktuellen Semester angelegt werden gibt es eine Helper Funktion damit das Studiensemester nicht hartcodiert werden muss:
=== NearestWintersemester ===
NearestWintersemester(0) -> Liefert das näheste Wintersemester
NearestWintersemester(-1) -> Liefert Studiensemester VOR dem nähesten Wintersemester
NearestWintersemester(+1) -> Liefert Studiensemester NACH dem nähesten Wintersemester
+229
View File
@@ -0,0 +1,229 @@
<?php
/**
* Rebuilds a throwaway test database into a usable FHComplete instance.
*
* php system/setup_testinstance.php --setup rebuild the database, then verify
* php system/setup_testinstance.php --verify verify only, write nothing
*
* The database itself is built by db_setup.sh: truncate -> FHComplete-3.3.sql ->
* checksystem.php -> seeders. This script only adds what db_setup.sh does not cover — addon
* dbupdates, extension SQL and a closing health check.
*
* needs psql and db_setup.sh. Connection data comes from config/system.config.inc.php.
*/
if (php_sapi_name() !== 'cli') {
http_response_code(403);
exit("Command line only.\n");
}
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE & ~E_WARNING);
set_time_limit(0);
ini_set('memory_limit', '1024M');
define('SETUP_ROOT', dirname(__DIR__));
define('DB_SETUP_SH', '/home/testing/fhc-coreutils/tests/automated/db_setup.sh');
function out($msg = '') { fwrite(STDOUT, $msg . PHP_EOL); }
function step($msg) { out(''); out('=== ' . $msg . ' ' . str_repeat('=', max(0, 62 - strlen($msg)))); }
function info($msg) { out(' ' . $msg); }
function ok($msg) { out(' + ' . $msg); }
function warn($msg) { out(' ! ' . $msg); }
function bail($msg) { out(''); out(' X ' . $msg); out(''); exit(1); }
function loadConfig()
{
$file = SETUP_ROOT . '/config/system.config.inc.php';
if (!is_file($file)) bail("Config not found: $file");
require_once($file);
// the FHC config sets error_reporting(E_ALL); restore ours, or every include of the legacy
// classes prints deprecation notices over the output
error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE & ~E_WARNING);
foreach (['DB_HOST', 'DB_NAME', 'DB_USER'] as $const) {
if (!defined($const)) bail("$const is not defined in $file.");
}
putenv('PGPASSWORD=' . (defined('DB_PASSWORD') ? DB_PASSWORD : ''));
}
function connectDb()
{
$conn = @pg_connect(sprintf(
'host=%s port=%s dbname=%s user=%s password=%s',
DB_HOST, defined('DB_PORT') ? DB_PORT : '5432', DB_NAME, DB_USER,
defined('DB_PASSWORD') ? DB_PASSWORD : ''
));
if ($conn === false) bail('Cannot connect to ' . DB_NAME . '@' . DB_HOST . ' as ' . DB_USER . '.');
return $conn;
}
function scalar($conn, $sql)
{
$res = @pg_query($conn, $sql);
if ($res === false) return null;
$row = pg_fetch_row($res);
return $row ? $row[0] : null;
}
/** Runs one .sql file. Returns the error count; "already exists" is normal on a repeat run. */
function psqlFile($file)
{
exec(sprintf('psql -h %s -p %s -U %s -d %s -f %s 2>&1',
escapeshellarg(DB_HOST), escapeshellarg(defined('DB_PORT') ? DB_PORT : '5432'),
escapeshellarg(DB_USER), escapeshellarg(DB_NAME), escapeshellarg($file)), $lines);
$errors = 0;
foreach ($lines as $line) {
if (stripos($line, 'ERROR') !== false && stripos($line, 'already exists') === false) $errors++;
}
return $errors;
}
/** Guards, before anything is dropped: --setup empties the target, so refuse anything but cy-*. */
function preflight()
{
step('preflight');
if (!shell_exec('command -v psql')) bail('psql is missing. Run this on the dev machine.');
if (!is_file(DB_SETUP_SH)) bail('db_setup.sh not found: ' . DB_SETUP_SH);
if (strpos(DB_NAME, 'cy-') !== 0) {
bail("Target is '" . DB_NAME . "'. --setup drops every schema and only touches cy-* databases.");
}
$seeders = glob(SETUP_ROOT . '/system/seeders/*.sql');
if (!$seeders) bail('No seeders in ' . SETUP_ROOT . '/system/seeders/ — the rebuild would leave an empty database.');
ok(count($seeders) . ' seeders, target ' . DB_NAME);
}
/** Output is passed through verbatim, checksystem.php's HTML included. */
function rebuild()
{
step('db_setup.sh');
info('truncate -> FHComplete-3.3.sql -> checksystem.php -> seeders');
out('');
passthru(escapeshellarg(DB_SETUP_SH) . ' ' . escapeshellarg(SETUP_ROOT), $code);
if ($code !== 0) bail('db_setup.sh failed with exit code ' . $code . '.');
ok('database rebuilt');
}
/**
* Addon DB updates. Their install.php files are web installers and empty stubs; the DDL sits in
* addons/<name>/system/dbupdate_*.php and expects CHECKSYSTEM and a $db in scope.
*/
function runAddons()
{
step('addons');
$files = glob(SETUP_ROOT . '/addons/*/system/dbupdate_*.php');
if (!$files) { info('none found'); return; }
if (!defined('CHECKSYSTEM')) define('CHECKSYSTEM', 'setup_testinstance');
require_once(SETUP_ROOT . '/include/basis_db.class.php');
$db = new basis_db();
foreach ($files as $file) {
$name = basename(dirname(dirname($file))) . '/' . basename($file);
ob_start();
try {
require($file);
ob_end_clean();
ok($name);
} catch (Throwable $t) {
ob_end_clean();
warn($name . ': ' . $t->getMessage());
}
}
}
/** Extension SQL, for an instance that has the files but never ran their sql/<version>/*.sql. */
function runExtensions()
{
step('extensions');
$dirs = glob(SETUP_ROOT . '/application/extensions/*/sql', GLOB_ONLYDIR);
if (!$dirs) { info('none found'); return; }
foreach ($dirs as $dir) {
// every version the extension ships, oldest first; a test instance always wants the newest schema
$files = glob($dir . '/*/*.sql') ?: [];
sort($files, SORT_NATURAL);
$errors = 0;
foreach ($files as $file) $errors += psqlFile($file);
$label = sprintf('%s (%d file(s)%s)', basename(dirname($dir)), count($files), $errors ? ", $errors errors" : '');
if ($errors) warn($label); else ok($label);
}
}
/**
* General signs of a usable instance only. Whether a given suite's fixture is in place is that
* suite's own business (see tests/cypress/tools/dbCheck.js).
*/
function verify($conn)
{
step('verify');
$checks = [
// dump applied
['Tables', "SELECT count(*) FROM information_schema.tables
WHERE table_schema IN ('public','lehre','campus')", function ($v) { return $v > 200; }],
// checksystem.php ran
['Phrases', "SELECT count(*) FROM system.tbl_phrase", function ($v) { return $v > 0; }],
['Permissions', "SELECT count(*) FROM system.tbl_berechtigung", function ($v) { return $v > 0; }],
// seeders ran
['Studiensemester', "SELECT count(*) FROM public.tbl_studiensemester
WHERE start <= now()", function ($v) { return $v > 0; }],
['Mitarbeiter', "SELECT count(*) FROM public.tbl_mitarbeiter", function ($v) { return $v > 0; }],
['Studenten', "SELECT count(*) FROM public.tbl_student", function ($v) { return $v > 0; }],
];
$failed = 0;
foreach ($checks as list($label, $sql, $test)) {
$value = scalar($conn, $sql);
$passed = $test($value);
if (!$passed) $failed++;
out(sprintf(' [%s] %-20s %s', $passed ? 'OK ' : 'XX ', $label, $value === null ? '(null)' : $value));
}
return $failed === 0;
}
$flags = array_slice($argv, 1);
$setup = in_array('--setup', $flags, true);
$verify = in_array('--verify', $flags, true);
// --setup must be spelled out: the run empties the target database.
if (!$setup && !$verify) {
out('');
out(' php system/setup_testinstance.php --setup rebuild the database, then verify');
out(' php system/setup_testinstance.php --verify verify only, write nothing');
out('');
exit(0);
}
loadConfig();
out('');
out(' Target : ' . DB_NAME . ' @ ' . DB_HOST);
if ($setup) {
preflight();
rebuild();
runAddons();
runExtensions();
}
$success = verify(connectDb());
out('');
out($success ? ' Done.' : ' Finished with findings, see above.');
out('');
exit($success ? 0 : 1);
+56
View File
@@ -0,0 +1,56 @@
# Copy to tests/cypress/.env (gitignored) and fill in.
# THIS FILE IS COMMITTED - never put a real password in it.
# ---- required -------------------------------------------------------------------------------
# Your own instance, e.g. https://c3p0.dev.technikum-wien.at/<kuerzel>/fhcompletecis4
# No default anywhere: empty fails the run rather than pointing it at a colleague's installation.
BASE_URL=
# HTTP Basic + LDAP user the API calls authenticate as. Use the LECTURER under test
# (e.g. demolektor1) - getBenotungstoolContext resolves that user's own Lehrveranstaltungen,
# and an admin account usually teaches nothing and would resolve none.
USER_NAME=
USER_PASSWORD=
# ---- required: fixture reset ------------------------------------------------------------------
# The suite resets its fixture over a direct database connection; there is no HTTP fallback, so
# the specs fail without it. TEST_ENV_PREFIX selects the <PREFIX>_DB_* / <PREFIX>_SSH_* names.
TEST_ENV_PREFIX=NOTEN
NOTEN_DB_HOST=db.dev.technikum-wien.at
NOTEN_DB_PORT=5432
NOTEN_DB_NAME=
NOTEN_DB_USER=
NOTEN_DB_PASSWORD=
NOTEN_DB_ALLOW_WRITES=true
# ---- required from a workstation: SSH tunnel --------------------------------------------------
# pg_hba.conf admits only the application server. NOTEN_DB_HOST above stays the REAL database -
# the tunnel rewrites the connection to 127.0.0.1 itself.
#
# Two things that are easy to get wrong:
# - the SSH host is usually NOT the web hostname
# - a key whose filename is not an OpenSSH default is NEVER tried automatically; name it here,
# or leave NOTEN_SSH_KEY empty to use your SSH agent
NOTEN_SSH_TUNNEL=true
NOTEN_SSH_HOST=
NOTEN_SSH_USER=
NOTEN_SSH_KEY=
# ---- optional ---------------------------------------------------------------------------------
# Semester and LV are discovered at runtime. Pin them only when discovery picks the wrong one.
NOTEN_SEM=
NOTEN_LV_ID=
# Access-control specs: this API has no impersonation, so scoping needs a second real login.
# NOTEN_FOREIGN_LV_ID must be an LV this teacher does NOT teach. Unset -> those specs skip.
NOTEN_TEACHER_USER=
NOTEN_TEACHER_PASSWORD=
NOTEN_FOREIGN_LV_ID=
# saveStudentenNoten always sends the Notenfreigabe mail (not behind a config flag). Leave off
# unless outbound mail on this instance is a dead end. Unset -> the happy-path specs skip.
NOTEN_FREIGABE_ENABLED=false
NOTEN_FREIGABE_PASSWORD=
@@ -0,0 +1,197 @@
/**
* Access control (P2) - assertLvAccess scoping (Noten.php:243).
*
* There is no impersonation in this API, so testing teacher scoping needs that teacher's real
* credentials: NOTEN_TEACHER_USER / NOTEN_TEACHER_PASSWORD / NOTEN_FOREIGN_LV_ID.
*/
import { notenApi } from "../../../../support/api/notenApi";
import {
expectAuthError,
expectNotenError,
expectNotenSuccess,
} from "../../../../support/helpers/notenErrors";
import { loadNotenContext } from "../../../../support/helpers/notenTestData";
const NOTEN_API = "/index.ci.php/api/frontend/v1/Noten";
const teacherConfigured = () =>
Boolean(Cypress.env("NOTEN_TEACHER_USER") && Cypress.env("NOTEN_FOREIGN_LV_ID"));
/** A getStudentenNoten call as an explicitly chosen user (or with no credentials at all). */
const getStudentenNotenAs = (auth, lvId, semKurzbz) =>
cy.request({
method: "GET",
url: `${NOTEN_API}/getStudentenNoten`,
qs: { lv_id: lvId, sem_kurzbz: semKurzbz },
auth,
failOnStatusCode: false,
});
describe("Noten API - access control", () => {
let ctx;
before(() => {
loadNotenContext().then((context) => {
ctx = context;
});
});
describe("authentication", () => {
it("rejects an unauthenticated request", () => {
// Without this the auth is still active from last login
cy.clearAllCookies();
cy.request({
method: "GET",
url: `${NOTEN_API}/getCisConfig`,
failOnStatusCode: false,
}).then((response) => {
expectAuthError(response);
});
});
it("rejects invalid credentials", () => {
cy.request({
method: "GET",
url: `${NOTEN_API}/getCisConfig`,
auth: { username: "no-such-user", password: "no-such-password" },
failOnStatusCode: false,
}).then((response) => {
expectAuthError(response);
});
});
});
describe("the configured API user", () => {
it("can read the students of the test LV", () => {
notenApi.getStudentenNoten(ctx.lvId, ctx.semKurzbz).then((response) => {
const data = expectNotenSuccess(response, "getStudentenNoten on the own/admin LV");
expect(data[0], "student list").to.be.an("array").and.not.be.empty;
});
});
});
describe("teacher scoping", () => {
beforeEach(function () {
if (!teacherConfigured()) {
cy.log(
"Skipped: needs NOTEN_TEACHER_USER / NOTEN_TEACHER_PASSWORD and NOTEN_FOREIGN_LV_ID " +
"(an LV that teacher does NOT teach). This API has no impersonation, so a second " +
"real login is required.",
);
this.skip();
}
});
const teacherAuth = () => ({
username: Cypress.env("NOTEN_TEACHER_USER"),
password: Cypress.env("NOTEN_TEACHER_PASSWORD"),
});
it("lets a teacher read an LV they teach", () => {
notenApi.getBenotungstoolContext(ctx.semKurzbz).then(() => {
cy.request({
method: "GET",
url: `${NOTEN_API}/getBenotungstoolContext`,
qs: { sem_kurzbz: ctx.semKurzbz },
auth: teacherAuth(),
failOnStatusCode: false,
}).then((response) => {
const context = expectNotenSuccess(response, "teacher getBenotungstoolContext");
const lvs = context.lehrveranstaltungen || [];
expect(
lvs.length,
`${Cypress.env("NOTEN_TEACHER_USER")} must teach at least one LV in ` +
`${ctx.semKurzbz} for this test to mean anything`,
).to.be.greaterThan(0);
getStudentenNotenAs(teacherAuth(), lvs[0].lehrveranstaltung_id, ctx.semKurzbz).then(
(studentsResponse) => {
expectNotenSuccess(studentsResponse, "teacher reading their own LV");
},
);
});
});
});
it("denies a teacher access to an LV they do not teach", () => {
getStudentenNotenAs(
teacherAuth(),
Cypress.env("NOTEN_FOREIGN_LV_ID"),
ctx.semKurzbz,
).then((response) => {
expectAuthError(response);
});
});
it("denies a teacher writing a grade in an LV they do not teach", () => {
cy.request({
method: "POST",
url: `${NOTEN_API}/saveNotenvorschlag`,
body: {
lv_id: Cypress.env("NOTEN_FOREIGN_LV_ID"),
sem_kurzbz: ctx.semKurzbz,
student_uid: ctx.students[0].uid,
note: ctx.gradeNotes[0],
punkte: null,
},
auth: teacherAuth(),
failOnStatusCode: false,
}).then((response) => {
expectAuthError(response);
});
});
});
describe("getLvForStudiengang (Assistenz flow)", () => {
it("refuses a Studiengang the caller is not entitled for", () => {
// 0 is not a real studiengang_kz, so no caller can be entitled for it. Admins bypass the
// check entirely, in which case the request succeeds with an empty list instead.
notenApi.getLvForStudiengang(0, ctx.semKurzbz).then((response) => {
expect(response.status, "either denied (500) or allowed-as-admin (200)").to.be.oneOf([
200, 500,
]);
if (response.status === 500) {
expect(response.body).to.have.nested.property("meta.status", "error");
expect(response.body.errors, "a denial carries a message").to.be.an("array").and.not
.be.empty;
} else {
expect(response.body.data, "an admin gets an empty LV list").to.be.an("array");
}
});
});
it("rejects a call without the required parameters", () => {
cy.request({
method: "GET",
url: `${NOTEN_API}/getLvForStudiengang`,
qs: { sem_kurzbz: ctx.semKurzbz },
auth: {
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
},
failOnStatusCode: false,
}).then((response) => {
expect(response.status, "missing studiengang_kz").to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
});
});
});
describe("getBenotungstoolContext shape", () => {
it("returns the role-determining payload", () => {
notenApi.getBenotungstoolContext(ctx.semKurzbz).then((response) => {
const context = expectNotenSuccess(response, "getBenotungstoolContext");
expect(context).to.have.property("isAssistenz");
expect(context.isAssistenz, "isAssistenz is a boolean").to.be.a("boolean");
expect(context.studiengaenge, "studiengaenge").to.be.an("array");
expect(context.lehrveranstaltungen, "lehrveranstaltungen").to.be.an("array");
expect(context).to.have.property("preselectStudiengang_kz");
});
});
});
});
@@ -0,0 +1,223 @@
/**
* Bulk / import paths (P2).
*
* Same validatePruefungAdd guards as the single save, but reported differently: HTTP 200 with the
* error string in data[uid] per row (Noten.php:1600/:1656). createPruefungen is the main vehicle
* because it always writes "Noch nicht eingetragen" and never touches punkte.
*/
import { notenApi } from "../../../../support/api/notenApi";
import {
expectBulkRowAccepted,
expectBulkRowError,
expectNotenSuccess,
} from "../../../../support/helpers/notenErrors";
import {
attemptDate,
loadNotenContext,
readLvGesamtnote,
requireDbReset,
resetNotenState,
seedBaseline,
} from "../../../../support/helpers/notenTestData";
import {
addPruefung,
attemptsOfTyp,
enabledRetakeTypes,
readState,
} from "../../../../support/helpers/notenScenario";
describe("Noten API - bulk paths", () => {
let ctx;
before(() => {
requireDbReset();
loadNotenContext().then((context) => {
ctx = context;
});
});
describe("createPruefungen", () => {
it("rejects only the row that breaks a §1 rule and accepts the rest", () => {
const atCap = ctx.students[0];
const fresh = ctx.students[1];
const retakes = enabledRetakeTypes(ctx);
resetNotenState(ctx);
seedBaseline(ctx, atCap.uid, { freigegeben: true });
seedBaseline(ctx, fresh.uid, { freigegeben: true });
// drive the first student up to the cap
retakes.forEach((typ, i) => {
addPruefung(ctx, atCap, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, i + 1),
typ,
}).then((response) => {
expectNotenSuccess(response, `bring ${atCap.uid} to the cap via ${typ}`);
});
});
const datum = attemptDate(ctx, retakes.length + 2);
notenApi
.createPruefungen(
[
{ uid: atCap.uid, typ: retakes[retakes.length - 1], lehreinheit_id: atCap.lehreinheit_id },
{ uid: fresh.uid, typ: "Termin2", lehreinheit_id: fresh.lehreinheit_id },
],
datum,
ctx.lvId,
ctx.semKurzbz,
)
.then((response) => {
// the request as a whole succeeds - errors are per row
const data = expectNotenSuccess(response, "createPruefungen");
expectBulkRowError(data, atCap.uid, "maxAntritteReached");
expectBulkRowAccepted(data, fresh.uid);
});
readState(ctx).then((data) => {
const created = attemptsOfTyp(data, fresh.uid, "Termin2");
expect(
created.map((p) => String(p.datum).slice(0, 10)),
"the accepted row was really created",
).to.include(datum);
});
});
it("applies the chronological rule per row", () => {
const student = ctx.students[2];
resetNotenState(ctx);
seedBaseline(ctx, student.uid, { freigegeben: true });
// an open (uncounted) attempt occupies a date without consuming an Antritt
addPruefung(ctx, student, {
note: ctx.notes.nochNichtEingetragen,
datum: attemptDate(ctx, 3),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, "seed an open Termin2");
});
notenApi
.createPruefungen(
[{ uid: student.uid, typ: "Termin2", lehreinheit_id: student.lehreinheit_id }],
attemptDate(ctx, 2), // earlier than the existing attempt
ctx.lvId,
ctx.semKurzbz,
)
.then((response) => {
const data = expectNotenSuccess(response, "createPruefungen out of order");
expectBulkRowError(data, student.uid, "pruefungDatumBeforeExisting");
});
});
it("rejects a call without the required parameters", () => {
cy.request({
method: "POST",
url: "/index.ci.php/api/frontend/v1/Noten/createPruefungen",
body: { lva_id: ctx.lvId, sem_kurzbz: ctx.semKurzbz },
auth: {
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
},
failOnStatusCode: false,
}).then((response) => {
expect(response.status, "missing uids/datum").to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
});
});
});
describe("savePruefungenBulk", () => {
beforeEach(function () {
if (ctx.cisConfig.CIS_GESAMTNOTE_PUNKTE) {
// With punkte mode on, this endpoint unconditionally re-derives every row's note from
// the Notenschlüssel (Noten.php:1638-1643), so a row would need valid punkte rather than
// a grade. Covering that needs a points-based fixture; skip rather than assert nonsense.
cy.log(
"Skipped: CIS_GESAMTNOTE_PUNKTE is enabled, so savePruefungenBulk grades by points " +
"and this grade-based scenario does not apply.",
);
this.skip();
}
requireDbReset();
});
it("applies the §1 rules per row", () => {
const atCap = ctx.students[0];
const fresh = ctx.students[1];
const retakes = enabledRetakeTypes(ctx);
resetNotenState(ctx);
seedBaseline(ctx, atCap.uid, { freigegeben: true });
seedBaseline(ctx, fresh.uid, { freigegeben: true });
retakes.forEach((typ, i) => {
addPruefung(ctx, atCap, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, i + 1),
typ,
});
});
const datum = attemptDate(ctx, retakes.length + 2);
notenApi
.savePruefungenBulk(ctx.lvId, ctx.semKurzbz, [
{
uid: atCap.uid,
typ: retakes[retakes.length - 1],
note: ctx.gradeNotes[0],
punkte: null,
datum,
lehreinheit_id: atCap.lehreinheit_id,
},
{
uid: fresh.uid,
typ: "Termin2",
note: ctx.gradeNotes[0],
punkte: null,
datum,
lehreinheit_id: fresh.lehreinheit_id,
},
])
.then((response) => {
const data = expectNotenSuccess(response, "savePruefungenBulk");
expectBulkRowError(data, atCap.uid, "maxAntritteReached");
expectBulkRowAccepted(data, fresh.uid);
});
});
});
describe("saveNotenvorschlagBulk", () => {
it("writes an LV note for every row", () => {
const [a, b] = ctx.students;
resetNotenState(ctx);
notenApi
.saveNotenvorschlagBulk(ctx.lvId, ctx.semKurzbz, [
{ uid: a.uid, note: ctx.gradeNotes[0], punkte: null },
{ uid: b.uid, note: ctx.gradeNotes[1], punkte: null },
])
.then((response) => {
const data = expectNotenSuccess(response, "saveNotenvorschlagBulk");
expect(data, "one lvgesamtnote row per input row").to.be.an("array").and.have.length(2);
});
readLvGesamtnote(ctx, a.uid).then((row) => {
expect(row, `row for ${a.uid}`).to.not.be.null;
expect(String(row.note)).to.eq(String(ctx.gradeNotes[0]));
});
readLvGesamtnote(ctx, b.uid).then((row) => {
expect(row, `row for ${b.uid}`).to.not.be.null;
expect(String(row.note)).to.eq(String(ctx.gradeNotes[1]));
});
});
});
});
@@ -0,0 +1,183 @@
/**
* Notenfreigabe (P1, cases 12-14).
*
* A successful saveStudentenNoten ALWAYS sends the Notenfreigabe mail (Noten.php:585, not behind a
* config flag), so the happy path is opt-in via NOTEN_FREIGABE_ENABLED. The wrong-password test
* needs no gate: the check runs before any write and before the mail.
*/
import { notenApi } from "../../../../support/api/notenApi";
import { expectNotenError, expectNotenSuccess } from "../../../../support/helpers/notenErrors";
import {
baselineBenotungsdatum,
loadNotenContext,
readLvGesamtnote,
requireDbReset,
resetNotenState,
seedBaseline,
} from "../../../../support/helpers/notenTestData";
import { lvNoteOf, readState } from "../../../../support/helpers/notenScenario";
const freigabeEnabled = () => String(Cypress.env("NOTEN_FREIGABE_ENABLED")).toLowerCase() === "true";
const freigabePassword = () =>
Cypress.env("NOTEN_FREIGABE_PASSWORD") || Cypress.env("adminpassword");
/** The payload shape saveStudentenNoten expects per student (see the studlist builder). */
const notenPayload = (student, noteBezeichnung) => ({
uid: student.uid,
matrikelnr: student.matrikelnr || student.matr_nr || "",
kuerzel: student.kuerzel || "",
nachname: student.nachname || "",
vorname: student.vorname || "",
noteBezeichnung: noteBezeichnung || "",
});
describe("Noten API - Notenfreigabe", () => {
let ctx;
before(() => {
loadNotenContext().then((context) => {
ctx = context;
});
});
describe("password gate", () => {
it("rejects a Freigabe with a wrong password and changes nothing", () => {
requireDbReset();
const student = ctx.students[0];
resetNotenState(ctx);
seedBaseline(ctx, student.uid, {
note: ctx.gradeNotes[0],
freigegeben: false,
benotungsdatum: baselineBenotungsdatum(ctx),
});
notenApi
.saveStudentenNoten(
"definitely-not-the-password",
[notenPayload(student)],
ctx.lvId,
ctx.semKurzbz,
)
.then((response) => {
expectNotenError(response, "wrongPassword");
});
readLvGesamtnote(ctx, student.uid).then((row) => {
expect(row, "the row still exists").to.not.be.null;
expect(row.freigabedatum, "a rejected Freigabe must not stamp freigabedatum").to.be.null;
});
});
it("rejects a Freigabe without the required parameters", () => {
cy.request({
method: "POST",
url: "/index.ci.php/api/frontend/v1/Noten/saveStudentenNoten",
body: { lv_id: ctx.lvId, sem_kurzbz: ctx.semKurzbz },
auth: {
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
},
failOnStatusCode: false,
}).then((response) => {
expect(response.status, "missing password/noten").to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
});
});
});
describe("happy path (sends mail - opt in via NOTEN_FREIGABE_ENABLED)", () => {
beforeEach(function () {
if (!freigabeEnabled()) {
cy.log(
"Skipped: saveStudentenNoten sends the Notenfreigabe email on success. " +
"Set NOTEN_FREIGABE_ENABLED=true only on an environment where that mail is harmless.",
);
this.skip();
}
requireDbReset();
});
it("stamps freigabedatum on a changed note", () => {
const student = ctx.students[0];
resetNotenState(ctx);
seedBaseline(ctx, student.uid, {
note: ctx.gradeNotes[0],
freigegeben: false,
benotungsdatum: baselineBenotungsdatum(ctx),
});
notenApi
.saveStudentenNoten(
freigabePassword(),
[notenPayload(student)],
ctx.lvId,
ctx.semKurzbz,
)
.then((response) => {
const data = expectNotenSuccess(response, "saveStudentenNoten");
expect(data, "freigegebene rows are reported back").to.be.an("array");
const entry = data.find((r) => r.uid === student.uid);
expect(entry, `${student.uid} must be reported as freigegeben`).to.exist;
expect(entry.freigabedatum, "freigabedatum is stamped").to.exist;
});
readState(ctx).then((data) => {
const grades = lvNoteOf(data, student.uid);
expect(grades.freigabedatum, "the note is now freigegeben").to.exist;
});
});
it("only touches rows whose benotungsdatum is newer than their freigabedatum", () => {
const changed = ctx.students[0];
const alreadyReleased = ctx.students[1];
resetNotenState(ctx);
// changed: benotungsdatum after freigabedatum -> must be re-freigegeben
seedBaseline(ctx, changed.uid, {
note: ctx.gradeNotes[0],
freigegeben: true,
freigabedatum: `${ctx.semKurzbz.slice(2, 6)}-01-05 08:00:00`,
benotungsdatum: `${ctx.semKurzbz.slice(2, 6)}-01-10 08:00:00`,
});
// already freigegeben and untouched since -> must be left alone
seedBaseline(ctx, alreadyReleased.uid, {
note: ctx.gradeNotes[0],
freigegeben: true,
freigabedatum: `${ctx.semKurzbz.slice(2, 6)}-01-10 08:00:00`,
benotungsdatum: `${ctx.semKurzbz.slice(2, 6)}-01-10 08:00:00`,
});
notenApi
.saveStudentenNoten(
freigabePassword(),
[notenPayload(changed), notenPayload(alreadyReleased)],
ctx.lvId,
ctx.semKurzbz,
)
.then((response) => {
const data = expectNotenSuccess(response, "selective Freigabe");
const uids = data.map((r) => r.uid);
expect(uids, "the changed note is freigegeben").to.include(changed.uid);
expect(
uids,
"an unchanged, already freigegebene note must not be freigegeben again",
).to.not.include(alreadyReleased.uid);
});
readLvGesamtnote(ctx, alreadyReleased.uid).then((row) => {
expect(
new Date(row.freigabedatum).toISOString().slice(0, 10),
"the untouched row keeps its original freigabedatum",
).to.eq(`${ctx.semKurzbz.slice(2, 6)}-01-10`);
});
});
});
});
@@ -0,0 +1,128 @@
/**
* Prüfungsordnung §1 - Noteneintragungsfrist (P0, cases 8-9).
*
* enforceNoteneintragungsfrist runs after assertLvAccess but before any write, so a request naming
* a past-deadline semester is rejected without touching a row. The message carries the derived
* deadline, which doubles as a check of computeNoteneintragungsfrist
* (SS -> 15.11.yyyy, WS -> 15.05.yyyy+1).
*/
import { notenApi } from "../../../../support/api/notenApi";
import { expectNotenError, expectNotenSuccess } from "../../../../support/helpers/notenErrors";
import {
attemptDate,
expectedFristString,
fristHasPassed,
loadNotenContext,
requireDbReset,
semesterWithPastFrist,
} from "../../../../support/helpers/notenTestData";
import { addPruefung, givenBaseline } from "../../../../support/helpers/notenScenario";
// Deadlines computeNoteneintragungsfrist derives: SS -> 15.11.yyyy, WS -> 15.05.yyyy+1.
const fristConfig = () => ({ ss: { month: 11, day: 15 }, ws: { month: 5, day: 15 } });
describe("Noten API - Noteneintragungsfrist (Prüfungsordnung §1)", () => {
let ctx;
let enforced;
before(() => {
loadNotenContext().then((context) => {
ctx = context;
enforced = Boolean(ctx.cisConfig.CIS_GESAMTNOTE_NOTENEINTRAGUNGSFRIST);
cy.log(`CIS_GESAMTNOTE_NOTENEINTRAGUNGSFRIST = ${enforced}`);
});
});
describe("deadline has passed", () => {
// A rejected request writes nothing, so these need no DB reset.
[
{ type: "SS", label: "Sommersemester (deadline in the same year)" },
{ type: "WS", label: "Wintersemester (deadline in the following year)" },
].forEach(({ type, label }) => {
it(`rejects grade entry for a ${label}`, function () {
// no flag, no deadline - skip rather than pretend it passed
if (!enforced) this.skip();
const sem = semesterWithPastFrist(type);
const cfg = fristConfig();
const expectedDeadline = expectedFristString(sem, cfg.ss, cfg.ws);
expect(fristHasPassed(sem), `${sem} deadline is in the past`).to.be.true;
notenApi
.saveStudentPruefung({
student_uid: ctx.students[0].uid,
note: ctx.gradeNotes[0],
punkte: null,
datum: attemptDate(ctx, 1),
lva_id: ctx.lvId,
lehreinheit_id: ctx.students[0].lehreinheit_id,
sem_kurzbz: sem,
typ: "Termin2",
pruefung_id: null,
})
.then((response) => {
expectNotenError(response, "noteneintragungsfristVorbei");
const message = response.body.errors.map((e) => e.message).join(" | ");
expect(
message,
`the ${type} deadline the server derived for ${sem}`,
).to.include(expectedDeadline);
});
});
});
it("rejects saveNotenvorschlag past the deadline as well", function () {
if (!enforced) this.skip();
const sem = semesterWithPastFrist("SS");
notenApi
.saveNotenvorschlag(ctx.lvId, sem, ctx.students[0].uid, ctx.gradeNotes[0])
.then((response) => {
expectNotenError(response, "noteneintragungsfristVorbei");
});
});
});
describe("deadline is still ahead", () => {
before(() => {
requireDbReset();
});
it("accepts grade entry in a semester whose deadline has not passed", function () {
if (enforced && fristHasPassed(ctx.semKurzbz)) {
// writing is impossible here; the whole mutating suite would be blocked too
throw new Error(
`Noteneintragungsfrist enforcement is ON and the deadline for the test semester ` +
`${ctx.semKurzbz} (${expectedFristString(ctx.semKurzbz)}) has already passed, so no ` +
`grade can be entered. Point NOTEN_SEM at a semester whose deadline is still ahead.`,
);
}
const student = ctx.students[0];
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 1),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, `grade entry within the deadline for ${ctx.semKurzbz}`);
});
});
});
describe("deadline computation", () => {
it("derives the documented SS and WS deadlines", () => {
const cfg = fristConfig();
// pins the mapping, independent of the clock
expect(expectedFristString("SS2025", cfg.ss, cfg.ws)).to.eq("15.11.2025");
expect(expectedFristString("WS2025", cfg.ss, cfg.ws)).to.eq("15.05.2026");
});
});
});
@@ -0,0 +1,135 @@
/**
* Notenschlüssel - points to grade (P0, case 10). Read-only.
*
* getNote() picks the aufteilung row with the highest punkte <= input, and returns null when the LV
* has no Notenschlüssel. Rather than re-implementing that lookup, this sweeps the range and asserts
* the properties a correct scale must have: total, monotonic, exact at each boundary.
*/
import { notenApi } from "../../../../support/api/notenApi";
import { expectNotenSuccess } from "../../../../support/helpers/notenErrors";
import { loadNotenContext } from "../../../../support/helpers/notenTestData";
const MAX_PUNKTE = 100;
describe("Noten API - Notenschlüssel (getNoteByPunkte)", () => {
let ctx;
let lvId;
before(() => {
loadNotenContext().then((context) => {
ctx = context;
lvId = context.lvId;
});
});
/** Sweeps 0..MAX_PUNKTE and returns [{ punkte, note }] as the server reports it. */
const sweepScale = () => {
const observed = [];
for (let punkte = 0; punkte <= MAX_PUNKTE; punkte += 1) {
notenApi.getNoteByPunkte(punkte, lvId, ctx.semKurzbz).then((response) => {
const note = expectNotenSuccess(response, `getNoteByPunkte(${punkte})`);
observed.push({ punkte, note });
});
}
return cy.then(() => observed);
};
it("maps every point value through a monotonic, exact grade scale", () => {
sweepScale().then((observed) => {
const graded = observed.filter((entry) => entry.note !== null && entry.note !== undefined);
expect(
graded.length,
`LV ${lvId} in ${ctx.semKurzbz} has no Notenschlüssel - getNoteByPunkte returned null ` +
`for every value in 0..${MAX_PUNKTE}. Pin NOTEN_LV_ID to an LV that has one.`,
).to.be.greaterThan(0);
// (4) below the lowest threshold the model answers null, and that region must be a
// contiguous prefix - a null appearing *after* a graded value would mean a gap in the scale
const firstGradedIndex = observed.findIndex((e) => e.note !== null && e.note !== undefined);
observed.slice(firstGradedIndex).forEach((entry) => {
expect(
entry.note,
`points ${entry.punkte} fall inside the graded range and must map to a grade`,
).to.not.be.oneOf([null, undefined]);
});
// (2) monotonic: grade PKs run 1 (best) .. 5 (worst), so the number must never increase
for (let i = 1; i < graded.length; i += 1) {
expect(
Number(graded[i].note),
`grade at ${graded[i].punkte} points must not be worse than at ${graded[i - 1].punkte}`,
).to.be.at.most(Number(graded[i - 1].note));
}
// (3) exact boundaries: report each step so a shifted threshold is visible in the output
const boundaries = [];
for (let i = 1; i < graded.length; i += 1) {
if (Number(graded[i].note) !== Number(graded[i - 1].note)) {
boundaries.push({
punkte: graded[i].punkte,
note: graded[i].note,
previousNote: graded[i - 1].note,
});
}
}
cy.log(
`Notenschlüssel of LV ${lvId}: ${boundaries
.map((b) => `>=${b.punkte} -> ${b.note}`)
.join(", ")}`,
);
expect(
boundaries.length,
"a usable Notenschlüssel must have at least one grade boundary in the swept range",
).to.be.greaterThan(0);
// re-assert each boundary individually so a failure names the exact threshold
boundaries.forEach((boundary) => {
notenApi.getNoteByPunkte(boundary.punkte, lvId, ctx.semKurzbz).then((response) => {
const note = expectNotenSuccess(response, `boundary ${boundary.punkte}`);
expect(Number(note), `grade exactly at the ${boundary.punkte}-point boundary`).to.eq(
Number(boundary.note),
);
});
notenApi.getNoteByPunkte(boundary.punkte - 1, lvId, ctx.semKurzbz).then((response) => {
const note = expectNotenSuccess(response, `just below ${boundary.punkte}`);
expect(
Number(note),
`one point below the ${boundary.punkte}-point boundary must still be the worse grade`,
).to.eq(Number(boundary.previousNote));
});
});
});
});
it("reports no grade for an LV without a Notenschlüssel", () => {
// A non-existent LV id can have no Notenschlüssel assigned, so the model's success(null)
// contract is observable without depending on a particular fixture.
notenApi.getNoteByPunkte(50, 0, ctx.semKurzbz).then((response) => {
const note = expectNotenSuccess(response, "getNoteByPunkte for an LV without a schluessel");
expect(note, "no Notenschlüssel -> no grade").to.be.oneOf([null, undefined]);
});
});
it("rejects a request without the required parameters", () => {
cy.request({
method: "POST",
url: "/index.ci.php/api/frontend/v1/Noten/getNoteByPunkte",
body: { punkte: 50 },
auth: {
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
},
failOnStatusCode: false,
}).then((response) => {
expect(response.status, "missing lv_id/sem_kurzbz").to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
});
});
});
@@ -0,0 +1,170 @@
/**
* Notenvorschlag - LV note write and resulting state (P1, case 11).
*
* State comes from two timestamps (Benotungstool.js::checkFreigabe): no freigabedatum -> offen,
* benotungsdatum > freigabedatum -> changed, else freigegeben. The "changed" case is produced by
* seeding an already-freigegebene baseline, which keeps this spec free of the LDAP password check
* and the Freigabe mail.
*
* Caveat: getLvGesamtNoten() (behind getStudentenNoten) filters `freigabedatum < NOW()`, and
* NULL < NOW() is NULL - so offene notes are dropped, while saveNotenvorschlag writes through the
* unfiltered getLvGesamtNoteVorschlag(). The tests below separate write from read for that reason.
*/
import { notenApi } from "../../../../support/api/notenApi";
import { expectNotenSuccess } from "../../../../support/helpers/notenErrors";
import {
baselineBenotungsdatum,
loadNotenContext,
readLvGesamtnote,
requireDbReset,
resetNotenState,
seedBaseline,
} from "../../../../support/helpers/notenTestData";
import { lvNoteOf, readState } from "../../../../support/helpers/notenScenario";
describe("Noten API - Notenvorschlag", () => {
let ctx;
before(() => {
requireDbReset();
loadNotenContext().then((context) => {
ctx = context;
});
});
const readRow = (uid) => readLvGesamtnote(ctx, uid);
describe("saving a Notenvorschlag on a student without a grade", () => {
it("returns the stored note with a benotungsdatum and no freigabedatum", () => {
const student = ctx.students[0];
resetNotenState(ctx);
notenApi
.saveNotenvorschlag(ctx.lvId, ctx.semKurzbz, student.uid, ctx.gradeNotes[0])
.then((response) => {
const data = expectNotenSuccess(response, "saveNotenvorschlag");
expect(data, "saveNotenvorschlag returns [ lvgesamtnote ]").to.be.an("array").and.not
.be.empty;
const row = data[0];
expect(String(row.note), "stored note").to.eq(String(ctx.gradeNotes[0]));
expect(row.benotungsdatum, "benotungsdatum is stamped on save").to.exist;
expect(row.freigabedatum, "a fresh Notenvorschlag is not freigegeben").to.be.oneOf([
null,
undefined,
"",
]);
});
});
it("persists the row with freigabedatum NULL (state: offen)", () => {
const student = ctx.students[0];
resetNotenState(ctx);
notenApi.saveNotenvorschlag(ctx.lvId, ctx.semKurzbz, student.uid, ctx.gradeNotes[0]);
readRow(student.uid).then((row) => {
expect(row, "the lvgesamtnote row must exist in the database").to.not.be.null;
expect(String(row.note)).to.eq(String(ctx.gradeNotes[0]));
expect(row.benotungsdatum, "benotungsdatum").to.exist;
expect(row.freigabedatum, "freigabedatum stays NULL until Freigabe").to.be.null;
});
});
// EXPECTED TO FAIL while getLvGesamtNoten filters `freigabedatum < NOW()`: the row exists
// (test above proves it) but the read model drops it until the note is freigegeben.
it("reports the offen note back through getStudentenNoten", () => {
const student = ctx.students[0];
resetNotenState(ctx);
notenApi.saveNotenvorschlag(ctx.lvId, ctx.semKurzbz, student.uid, ctx.gradeNotes[0]);
readState(ctx).then((data) => {
const grades = lvNoteOf(data, student.uid);
expect(grades, `grades entry for ${student.uid}`).to.exist;
expect(
String(grades.note_lv),
"a saved (not yet freigegebene) Notenvorschlag must be readable again - if this is " +
"null, getLvGesamtNoten's `freigabedatum < NOW()` filter dropped the row",
).to.eq(String(ctx.gradeNotes[0]));
expect(grades.freigabedatum, "still offen").to.be.oneOf([null, undefined, ""]);
});
});
});
describe("re-grading an already freigegebene note", () => {
it("moves the state from freigegeben to changed", () => {
const student = ctx.students[1];
resetNotenState(ctx);
seedBaseline(ctx, student.uid, {
note: ctx.gradeNotes[0],
freigegeben: true,
benotungsdatum: baselineBenotungsdatum(ctx),
});
// baseline: benotungsdatum == freigabedatum -> freigegeben, not changed
readState(ctx).then((data) => {
const grades = lvNoteOf(data, student.uid);
expect(grades.note_lv, "seeded freigegebene note is visible").to.exist;
expect(
new Date(grades.benotungsdatum) > new Date(grades.freigabedatum),
"baseline must not already look changed",
).to.be.false;
});
notenApi
.saveNotenvorschlag(ctx.lvId, ctx.semKurzbz, student.uid, ctx.gradeNotes[1])
.then((response) => {
expectNotenSuccess(response, "re-grade after Freigabe");
});
readState(ctx).then((data) => {
const grades = lvNoteOf(data, student.uid);
expect(String(grades.note_lv), "the new grade is stored").to.eq(
String(ctx.gradeNotes[1]),
);
expect(grades.freigabedatum, "the old Freigabe timestamp is kept").to.exist;
expect(
new Date(grades.benotungsdatum) > new Date(grades.freigabedatum),
"benotungsdatum must now be newer than freigabedatum (state: changed)",
).to.be.true;
});
});
it("overwrites the grade rather than adding a second row", () => {
const student = ctx.students[1];
resetNotenState(ctx);
seedBaseline(ctx, student.uid, { note: ctx.gradeNotes[0], freigegeben: true });
notenApi.saveNotenvorschlag(ctx.lvId, ctx.semKurzbz, student.uid, ctx.gradeNotes[1]);
readRow(student.uid).then((row) => {
expect(row, "the single lvgesamtnote row").to.not.be.null;
expect(String(row.note)).to.eq(String(ctx.gradeNotes[1]));
});
});
});
describe("parameter validation", () => {
it("rejects a call without student_uid", () => {
cy.request({
method: "POST",
url: "/index.ci.php/api/frontend/v1/Noten/saveNotenvorschlag",
body: { lv_id: ctx.lvId, sem_kurzbz: ctx.semKurzbz, note: ctx.gradeNotes[0] },
auth: {
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
},
failOnStatusCode: false,
}).then((response) => {
expect(response.status, "missing student_uid").to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
});
});
});
});
@@ -0,0 +1,335 @@
/**
* Prüfungsordnung §1 - Prüfungsantritte (P0, cases 1-7).
*
* Rules fire in order A (max Antritte) -> B (chronology) -> C (occurrence limit), so each test
* builds a state where exactly one can fire; otherwise an earlier rule masks the one under test.
*
* Bookkeeping: the first Termin2 add also auto-creates a Termin1 row with the original LV note, so
* one call produces two attempts. A later Termin2 add updates the existing non-excused Termin2
* instead of inserting. "entschuldigt" and "Noch nicht eingetragen" never count towards the cap.
*/
import { expectNotenError, expectNotenSuccess } from "../../../../support/helpers/notenErrors";
import {
attemptDate,
baselineDate,
loadNotenContext,
requireDbReset,
shiftDate,
} from "../../../../support/helpers/notenTestData";
import {
addPruefung,
attemptsOfTyp,
editPruefung,
enabledRetakeTypes,
givenBaseline,
readState,
} from "../../../../support/helpers/notenScenario";
describe("Noten API - Prüfungsantritte (Prüfungsordnung §1)", () => {
let ctx;
before(() => {
requireDbReset();
loadNotenContext().then((context) => {
ctx = context;
cy.log(
`LV ${ctx.lvId} / ${ctx.semKurzbz} | maxAntritte=${ctx.maxAntritte} | ` +
`retakes=${enabledRetakeTypes(ctx).join(",") || "none"} | ` +
`entschuldigt=${ctx.notes.entschuldigt}`,
);
expect(
enabledRetakeTypes(ctx).length,
"needs TERMIN2 or TERMIN3 enabled, else saveStudentPruefung only answers wrongPruefungType",
).to.be.greaterThan(0);
});
});
// one student per test, so a leaked row cannot reach the next scenario
const studentFor = (index) => ctx.students[index % ctx.students.length];
describe("Rule A - maximum number of Prüfungsantritte", () => {
it("rejects an attempt once the configured maximum is reached", () => {
const student = studentFor(0);
const retakes = enabledRetakeTypes(ctx);
givenBaseline(ctx, student);
// Antritt 1 is the seeded LV note; each retake type adds one row -> count reaches maxAntritte
retakes.forEach((typ, i) => {
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, i + 1),
typ,
}).then((response) => {
expectNotenSuccess(response, `add ${typ} #${i + 1} (still below the cap)`);
});
});
// one more attempt of the last enabled type -> the cap must now bite
const lastTyp = retakes[retakes.length - 1];
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, retakes.length + 1),
typ: lastTyp,
}).then((response) => {
expectNotenError(response, "maxAntritteReached");
});
// and nothing was written for the rejected attempt
readState(ctx).then((data) => {
const attempts = attemptsOfTyp(data, student.uid, lastTyp);
expect(
attempts.map((p) => String(p.datum).slice(0, 10)),
`no ${lastTyp} may carry the rejected date`,
).to.not.include(attemptDate(ctx, retakes.length + 1));
});
});
});
describe("Rule B - attempts are taken in chronological order", () => {
// "Noch nicht eingetragen" occupies a date without counting towards the cap, so Rule A
// cannot fire first and mask Rule B.
const givenOpenAttemptOn = (student, datum) => {
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.notes.nochNichtEingetragen,
datum,
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, "seed an open (uncounted) Termin2");
});
};
it("rejects a new attempt dated on the same day as an existing one", () => {
const student = studentFor(1);
const existing = attemptDate(ctx, 2);
givenOpenAttemptOn(student, existing);
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: existing,
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "pruefungDatumBeforeExisting");
});
});
it("rejects a new attempt dated before an existing one", () => {
const student = studentFor(1);
const existing = attemptDate(ctx, 2);
givenOpenAttemptOn(student, existing);
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 1),
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "pruefungDatumBeforeExisting");
});
});
it("accepts a new attempt dated after every existing one", () => {
const student = studentFor(1);
givenOpenAttemptOn(student, attemptDate(ctx, 2));
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 3),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, "attempt strictly after the existing one");
});
});
});
describe("Rule C - 'entschuldigt' may be assigned only once", () => {
it("rejects a second entschuldigt attempt", () => {
const student = studentFor(2);
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.notes.entschuldigt,
datum: attemptDate(ctx, 1),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, "first entschuldigt attempt");
});
addPruefung(ctx, student, {
note: ctx.notes.entschuldigt,
datum: attemptDate(ctx, 2),
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "noteOccuranceLimitReached");
});
readState(ctx).then((data) => {
const excused = attemptsOfTyp(data, student.uid, "Termin2").filter(
(p) => String(p.note) === String(ctx.notes.entschuldigt),
);
expect(excused, "exactly one excused Termin2 may exist").to.have.length(1);
});
});
});
describe("entschuldigt does not consume an attempt", () => {
it("still accepts a real grade after an excused attempt", () => {
const student = studentFor(0);
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.notes.entschuldigt,
datum: attemptDate(ctx, 1),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(response, "excused attempt");
});
// excused must not count, so this real grade is still within the cap
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 2),
typ: "Termin2",
}).then((response) => {
expectNotenSuccess(
response,
"a real grade after an excused attempt (excused must not count towards the cap)",
);
});
});
it("preserves the excused entry as its own dated row instead of overwriting it", () => {
const student = studentFor(0);
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.notes.entschuldigt,
datum: attemptDate(ctx, 1),
typ: "Termin2",
});
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 2),
typ: "Termin2",
});
readState(ctx).then((data) => {
const termin2 = attemptsOfTyp(data, student.uid, "Termin2");
expect(termin2, "the excused row and the new row must coexist").to.have.length(2);
expect(String(termin2[0].note), "older row keeps the excused grade").to.eq(
String(ctx.notes.entschuldigt),
);
expect(String(termin2[0].datum).slice(0, 10)).to.eq(attemptDate(ctx, 1));
expect(String(termin2[1].note), "newer row carries the real grade").to.eq(
String(ctx.gradeNotes[0]),
);
expect(String(termin2[1].datum).slice(0, 10)).to.eq(attemptDate(ctx, 2));
});
});
});
describe("edit guards", () => {
/**
* Builds: Termin1 (baseline date) < excused Termin2 (attempt 1) < real Termin2 (attempt 2)
* and yields the excused row, which now has both an earlier and a later neighbour.
*/
const givenThreeAttempts = (student) => {
givenBaseline(ctx, student);
addPruefung(ctx, student, {
note: ctx.notes.entschuldigt,
datum: attemptDate(ctx, 1),
typ: "Termin2",
});
addPruefung(ctx, student, {
note: ctx.gradeNotes[0],
datum: attemptDate(ctx, 2),
typ: "Termin2",
});
return readState(ctx).then((data) => {
const excused = attemptsOfTyp(data, student.uid, "Termin2").find(
(p) => String(p.note) === String(ctx.notes.entschuldigt),
);
expect(excused, "excused Termin2 to edit").to.exist;
return excused;
});
};
it("rejects changing the grade once a later attempt exists", () => {
const student = studentFor(1);
givenThreeAttempts(student).then((excused) => {
editPruefung(ctx, student, {
pruefungId: excused.pruefung_id,
note: ctx.gradeNotes[1], // different grade -> locked
datum: attemptDate(ctx, 1),
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "pruefungNoteLocked");
});
});
});
it("still allows a date-only correction between the neighbouring attempts", () => {
const student = studentFor(1);
givenThreeAttempts(student).then((excused) => {
// same note -> the lock does not apply; date stays strictly inside (baseline, attempt2)
editPruefung(ctx, student, {
pruefungId: excused.pruefung_id,
note: excused.note,
datum: shiftDate(attemptDate(ctx, 1), 3),
typ: "Termin2",
}).then((response) => {
// NOTE: savePruefungstermin() does not receive pruefung_id - it re-derives the target
// as "the first non-excused Termin2" (Noten.php:943-968). The validation under test
// is what this asserts; the resulting row placement is covered separately.
expectNotenSuccess(response, "date-only correction inside the neighbour bounds");
});
});
});
it("rejects a date on or before the previous attempt", () => {
const student = studentFor(2);
givenThreeAttempts(student).then((excused) => {
editPruefung(ctx, student, {
pruefungId: excused.pruefung_id,
note: excused.note,
datum: baselineDate(ctx), // == the Termin1 date -> not strictly after
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "pruefungDatumOutOfRange");
});
});
});
it("rejects a date on or after the following attempt", () => {
const student = studentFor(2);
givenThreeAttempts(student).then((excused) => {
editPruefung(ctx, student, {
pruefungId: excused.pruefung_id,
note: excused.note,
datum: attemptDate(ctx, 2), // == the later Termin2 -> not strictly before
typ: "Termin2",
}).then((response) => {
expectNotenError(response, "pruefungDatumOutOfRange");
});
});
});
});
});
+28
View File
@@ -0,0 +1,28 @@
/**
* Wires the Gesamtnoteneingabe suite into cypress.config.js: its cy.task handlers plus the
* Cypress.env() values its specs read.
*
* The split is the point -- nothing NOTEN_* belongs in the config, and nothing generic belongs
* here. A second suite adds its own file next to this one and the config changes by one require.
*/
const { registerNotenDbTasks } = require("../tasks/notenDb");
module.exports = {
registerTasks: registerNotenDbTasks,
env: {
// Optional pins; semester and LV are discovered at runtime when unset.
NOTEN_SEM: process.env.NOTEN_SEM || null,
NOTEN_LV_ID: process.env.NOTEN_LV_ID || null,
// saveStudentenNoten always sends the Notenfreigabe mail - opt in explicitly.
NOTEN_FREIGABE_ENABLED: process.env.NOTEN_FREIGABE_ENABLED || "false",
NOTEN_FREIGABE_PASSWORD: process.env.NOTEN_FREIGABE_PASSWORD || null,
// Access-control specs need real per-role credentials: this API has no impersonation.
NOTEN_TEACHER_USER: process.env.NOTEN_TEACHER_USER || null,
NOTEN_TEACHER_PASSWORD: process.env.NOTEN_TEACHER_PASSWORD || null,
NOTEN_FOREIGN_LV_ID: process.env.NOTEN_FOREIGN_LV_ID || null,
},
};
+78
View File
@@ -0,0 +1,78 @@
/**
* Wrappers over the Benotungstool API. Mirrors public/js/api/factory/noten.js.
*
* GET sends factory params as query string, POST as JSON body (the controller reads
* getPostJSON()). Envelope: 200 {data, meta.status:'success'} / 500 {errors[], meta.status:'error'}.
*/
const NOTEN_API = "/index.ci.php/api/frontend/v1/Noten";
const authOptions = () => ({
username: Cypress.env("adminusername"),
password: Cypress.env("adminpassword"),
});
// Basic auth on every call rather than relying on the session cookie, so requests stay independent.
const apiGet = (path, qs) =>
cy.request({ method: "GET", url: `${NOTEN_API}/${path}`, qs, auth: authOptions(), failOnStatusCode: false });
const apiPost = (path, body) =>
cy.request({ method: "POST", url: `${NOTEN_API}/${path}`, body, auth: authOptions(), failOnStatusCode: false });
export const notenApi = {
getCisConfig: () => apiGet("getCisConfig"),
getNoten: () => apiGet("getNoten"),
getBenotungstoolContext: (sem_kurzbz, lv_id = null) =>
apiGet("getBenotungstoolContext", { sem_kurzbz, lv_id }),
getLvForStudiengang: (studiengang_kz, sem_kurzbz) =>
apiGet("getLvForStudiengang", { studiengang_kz, sem_kurzbz }),
/**
* data is a POSITIONAL array (Noten.php:431):
* [studenten, pruefungen, DOMAIN, grades-by-uid, anwesenheiten]
*/
getStudentenNoten: (lv_id, sem_kurzbz) => apiGet("getStudentenNoten", { lv_id, sem_kurzbz }),
/** data -> [lvgesamtnote] */
saveNotenvorschlag: (lv_id, sem_kurzbz, student_uid, note, punkte = null) =>
apiPost("saveNotenvorschlag", { lv_id, sem_kurzbz, student_uid, note, punkte }),
/** data -> [savedPruefung, lvgesamtnote, extraPruefung(auto-created Termin1)] */
saveStudentPruefung: ({
student_uid, note, punkte = null, datum, lva_id, lehreinheit_id, sem_kurzbz, typ, pruefung_id = null,
}) =>
apiPost("saveStudentPruefung", {
student_uid, note, punkte, datum, lva_id, lehreinheit_id, sem_kurzbz, typ, pruefung_id,
}),
/** LDAP-password gated. data -> [{uid, freigabedatum, benotungsdatum}] */
saveStudentenNoten: (password, noten, lv_id, sem_kurzbz) =>
apiPost("saveStudentenNoten", { password, noten, lv_id, sem_kurzbz }),
getNoteByPunkte: (punkte, lv_id, sem_kurzbz) =>
apiPost("getNoteByPunkte", { punkte, lv_id, sem_kurzbz }),
// Bulk paths answer 200 and put the error string in data[uid] per row - they never fail the
// whole request (Noten.php:1600/:1656).
saveNotenvorschlagBulk: (lv_id, sem_kurzbz, noten) =>
apiPost("saveNotenvorschlagBulk", { lv_id, sem_kurzbz, noten }),
savePruefungenBulk: (lv_id, sem_kurzbz, pruefungen) =>
apiPost("savePruefungenBulk", { lv_id, sem_kurzbz, pruefungen }),
createPruefungen: (uids, datum, lva_id, sem_kurzbz) =>
apiPost("createPruefungen", { uids, datum, lva_id, sem_kurzbz }),
};
// --- selectors over the getStudentenNoten payload ---
export const pruefungenOf = (data, uid) =>
(data[1] || []).filter((p) => p.student_uid === uid);
export const pruefungenOfTyp = (data, uid, typ) =>
pruefungenOf(data, uid).filter((p) => p.pruefungstyp_kurzbz === typ);
export const gradesOf = (data, uid) => (data[3] || {})[uid];
+28
View File
@@ -0,0 +1,28 @@
// Custom commands: https://on.cypress.io/custom-commands
/** Visits a page and fails if any request returned >= 400. */
Cypress.Commands.add("checkPageResources", (url) => {
const failedRequests = [];
cy.intercept("**", (req) => {
req.on("response", (res) => {
if (res.statusCode >= 400) {
failedRequests.push({ url: req.url, status: res.statusCode });
}
});
});
cy.env(["adminusername", "adminpassword"]).then(({ adminusername, adminpassword }) => {
cy.visit(url, { auth: { username: adminusername, password: adminpassword } });
});
cy.then(() => {
if (failedRequests.length > 0) {
const message = failedRequests.map((r) => `${r.status} - ${r.url}`).join("\n");
throw new Error(`Broken resources detected:\n${message}`);
}
});
});
// don't fail tests on uncaught app exceptions
Cypress.on("uncaught:exception", () => false);
+2
View File
@@ -0,0 +1,2 @@
// Loaded automatically before every spec.
import "./commands";
@@ -0,0 +1,96 @@
/**
* Assertions for the Noten error envelope.
*
* These errors carry no errorCode, only a localized message (terminateWithError + p->t()), so we
* match against the de/en phrase templates from system/phrasesupdate.php. Both languages accepted.
* Adding an errorCode server-side would remove this coupling.
*/
const PHRASES = {
maxAntritteReached: {
de: "Für Studierenden {0} sind bereits die maximal zulässigen Prüfungsantritte ({1}) vergeben. Es wurde keine Prüfung angelegt.",
en: "Student {0} has already used the maximum number of exam attempts ({1}). No exam was created.",
},
pruefungDatumBeforeExisting: {
de: "Das Prüfungsdatum für Studierenden {0} darf nicht vor oder am selben Tag wie ein bereits bestehender Prüfungstermin liegen.",
en: "The exam date for student {0} must not be on or before an existing exam date.",
},
noteOccuranceLimitReached: {
de: "Die gewählte Note darf für Studierenden {0} nicht so oft vergeben werden. Es wurde keine Prüfung angelegt.",
en: "The selected grade may not be assigned that many times for student {0}. No exam was created.",
},
pruefungNoteLocked: {
de: "Die Note für Studierenden {0} kann nicht mehr geändert werden, da bereits eine spätere Prüfung oder eine Prüfung mit höherem Antritt existiert. Das Prüfungsdatum kann weiterhin angepasst werden.",
en: "The grade for student {0} can no longer be changed because a later exam or an exam of a higher attempt already exists. The exam date can still be adjusted.",
},
pruefungDatumOutOfRange: {
de: "Das Prüfungsdatum für Studierenden {0} muss zwischen dem vorherigen und dem nachfolgenden Prüfungstermin liegen.",
en: "The exam date for student {0} must be between the previous and the following exam date.",
},
noteneintragungsfristVorbei: {
de: "Die Noteneintragungsfrist ({0}) für dieses Studiensemester ist abgelaufen. Es können keine Noten oder Prüfungen mehr eingetragen werden.",
en: "The grade entry deadline ({0}) for this study semester has passed. Grades and exams can no longer be entered.",
},
keineBerechtigungNoten: {
de: 'Keine Berechtigung, um in der Lehrveranstaltung "{0}" im Semester {1} Noten einzutragen.',
en: 'No permission to enter grades for the course "{0}" in semester {1}.',
},
wrongPassword: { de: "Falsches Passwort", en: "Wrong password" },
};
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
// Split on the {n} placeholders first, then escape - the other order breaks on the braces.
const toPattern = (text) =>
new RegExp(text.split(/\{\d+\}/).map(escapeRegExp).join("[\\s\\S]*?"));
const patternsFor = (key) => {
const phrase = PHRASES[key];
if (!phrase) throw new Error(`Unknown phrase key "${key}". Known: ${Object.keys(PHRASES).join(", ")}`);
return [toPattern(phrase.de), toPattern(phrase.en)];
};
export const messageMatchesPhrase = (message, key) =>
typeof message === "string" && patternsFor(key).some((re) => re.test(message));
export const expectNotenError = (response, key) => {
expect(response.status, `HTTP status for expected "${key}"`).to.eq(500);
expect(response.body).to.have.nested.property("meta.status", "error");
expect(response.body.errors).to.be.an("array").and.not.be.empty;
const messages = response.body.errors.map((e) => e.message);
expect(
messages.some((m) => messageMatchesPhrase(m, key)),
`expected phrase "${key}", got: ${JSON.stringify(messages)}`,
).to.be.true;
};
export const expectNotenSuccess = (response, context = "request") => {
// carry the server's message into the assertion, or a 500 says only "expected 200"
const errors = (response.body && response.body.errors || []).map((e) => e.message).join(" | ");
expect(response.status, `HTTP status for ${context}${errors ? ` -- ${errors}` : ""}`).to.eq(200);
expect(response.body, context).to.have.nested.property("meta.status", "success");
return response.body.data;
};
/** Auth failures short-circuit before any error is added, so the body carries only meta. */
export const expectAuthError = (response) => {
expect(response.status, "HTTP status for auth rejection").to.eq(401);
expect(response.body).to.have.nested.property("meta.status", "error");
};
export const expectBulkRowError = (data, uid, key) => {
expect(data).to.have.property(uid);
expect(
messageMatchesPhrase(data[uid], key),
`expected row "${uid}" to carry "${key}", got: ${JSON.stringify(data[uid])}`,
).to.be.true;
};
export const expectBulkRowAccepted = (data, uid) => {
expect(data).to.have.property(uid);
const value = data[uid];
const isError =
typeof value === "string" && Object.keys(PHRASES).some((k) => messageMatchesPhrase(value, k));
expect(isError, `expected row "${uid}" accepted, got: ${JSON.stringify(value)}`).to.be.false;
};
@@ -0,0 +1,75 @@
/**
* Fixture reset over a direct DB connection - the only mechanism.
*
* A gated HTTP reset endpoint existed briefly and was removed: it deleted grade data, and no
* gating makes that as safe as not having it. Consequence: the runner needs DB reachability, which
* from a workstation means the SSH tunnel (cypress/tasks/sshTunnel.js).
*/
let available = null;
/** Probes the DB once per run. Never throws; the caller decides how loudly to fail. */
export const resolveResetStrategy = () => {
if (available) return cy.wrap(available, { log: false });
return cy.task("noten:db:available", null, { log: false }).then((status) => {
available = { strategy: status.available ? "db" : null, reason: status.reason };
if (status.available) cy.log("Fixture reset via **direct database**");
return cy.wrap(available, { log: false });
});
};
export const describeFailure = (state) =>
` ${state.reason}\n\n` +
" Needs a database connection. From a workstation: NOTEN_SSH_TUNNEL=true plus\n" +
" NOTEN_SSH_HOST / NOTEN_SSH_USER (and NOTEN_SSH_KEY, unless an agent holds the key).";
/**
* uid to stamp as mitarbeiter_uid / freigabevon_uid.
* Not Cypress.env("adminusername"): LDAP accepts "Demolektor1" but tbl_benutzer.uid is
* "demolektor1" and the FKs are case sensitive.
*/
let cachedAuthUid = null;
const authUid = () => {
if (cachedAuthUid) return cy.wrap(cachedAuthUid, { log: false });
return cy
.request({
method: "GET",
url: "/index.ci.php/api/frontend/v1/AuthInfo/getAuthUID",
auth: { username: Cypress.env("adminusername"), password: Cypress.env("adminpassword") },
failOnStatusCode: false,
})
.then((response) => {
const uid = response.body?.data?.uid;
expect(uid, "AuthInfo/getAuthUID uid").to.be.a("string").and.not.be.empty;
cachedAuthUid = uid;
return uid;
});
};
export const performReset = (context, studentUids) =>
cy.task("noten:db:reset", {
lvId: context.lvId,
semKurzbz: context.semKurzbz,
studentUids,
});
export const performSeed = (context, studentUid, payload) =>
authUid().then((uid) =>
cy.task("noten:db:seedLvGesamtnote", {
lvId: context.lvId,
semKurzbz: context.semKurzbz,
studentUid,
mitarbeiterUid: uid,
...payload,
}),
);
export const performRead = (context, studentUid) =>
cy.task("noten:db:readLvGesamtnote", {
lvId: context.lvId,
semKurzbz: context.semKurzbz,
studentUid,
});
@@ -0,0 +1,62 @@
/** Building attempt histories and reading the resulting state. */
import { notenApi, pruefungenOfTyp, gradesOf } from "../api/notenApi";
import { expectNotenSuccess } from "./notenErrors";
import { resetNotenState, seedBaseline } from "./notenTestData";
/** Enabled in-tool retake types, in attempt order. maxAntritte == 1 + this list's length. */
export const enabledRetakeTypes = (context) => {
const types = [];
if (context.cisConfig.CIS_GESAMTNOTE_PRUEFUNG_TERMIN2) types.push("Termin2");
if (context.cisConfig.CIS_GESAMTNOTE_PRUEFUNG_TERMIN3) types.push("Termin3");
return types;
};
/**
* Adds an attempt (no pruefung_id -> server runs validatePruefungAdd).
* punkte stays null: with CIS_GESAMTNOTE_PUNKTE on, a punkte >= 0 makes the controller re-derive
* the note from the Notenschlüssel and override the grade under test (Noten.php:692).
*/
export const addPruefung = (context, student, { note, datum, typ = "Termin2" }) =>
notenApi.saveStudentPruefung({
student_uid: student.uid,
note,
punkte: null,
datum,
lva_id: context.lvId,
lehreinheit_id: student.lehreinheit_id,
sem_kurzbz: context.semKurzbz,
typ,
pruefung_id: null,
});
/** Edits an attempt (pruefung_id set -> server runs validatePruefungEdit). */
export const editPruefung = (context, student, { pruefungId, note, datum, typ = "Termin2" }) =>
notenApi.saveStudentPruefung({
student_uid: student.uid,
note,
punkte: null,
datum,
lva_id: context.lvId,
lehreinheit_id: student.lehreinheit_id,
sem_kurzbz: context.semKurzbz,
typ,
pruefung_id: pruefungId,
});
export const readState = (context) =>
notenApi
.getStudentenNoten(context.lvId, context.semKurzbz)
.then((response) => expectNotenSuccess(response, "getStudentenNoten"));
/** Attempts of one student and type, oldest first (the API returns datum DESC). */
export const attemptsOfTyp = (data, uid, typ) =>
[...pruefungenOfTyp(data, uid, typ)].sort((a, b) =>
String(a.datum).slice(0, 10).localeCompare(String(b.datum).slice(0, 10)),
);
export const lvNoteOf = (data, uid) => gradesOf(data, uid);
/** Clears the suite's rows and re-seeds the Antritt-1 baseline for one student. */
export const givenBaseline = (context, student, options = {}) =>
resetNotenState(context).then(() => seedBaseline(context, student.uid, options));
@@ -0,0 +1,214 @@
/**
* Runtime discovery + fixture helpers.
*
* No hardcoded fixture ids: the rule parameters (maxAntritte, the special note PKs) come from
* server-side config that is not in the repo, and Noten.php resolves the special notes by
* Bezeichnung. Everything is therefore read back from the API at runtime.
* Override via NOTEN_SEM / NOTEN_LV_ID.
*/
import { notenApi } from "../api/notenApi";
import { expectNotenSuccess } from "./notenErrors";
import { describeFailure, performRead, performReset, performSeed, resolveResetStrategy } from "./notenReset";
const BEZ_ENTSCHULDIGT = "entschuldigt";
const BEZ_NOCH_NICHT = "Noch nicht eingetragen";
let cachedContext = null;
// --- dates ---
export const pad2 = (n) => String(n).padStart(2, "0");
export const toDateString = (date) =>
`${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())}`;
export const shiftDate = (dateString, days) => {
const [y, m, d] = dateString.split("-").map(Number);
const date = new Date(Date.UTC(y, m - 1, d));
date.setUTCDate(date.getUTCDate() + days);
return `${date.getUTCFullYear()}-${pad2(date.getUTCMonth() + 1)}-${pad2(date.getUTCDate())}`;
};
/** Deadline the server derives (computeNoteneintragungsfrist): SS -> 15.11.yyyy, WS -> 15.05.yyyy+1. */
export const expectedFristString = (
semKurzbz,
ssConfig = { month: 11, day: 15 },
wsConfig = { month: 5, day: 15 },
) => {
const type = semKurzbz.slice(0, 2).toUpperCase();
const year = Number(semKurzbz.slice(2, 6));
const cfg = type === "SS" ? ssConfig : wsConfig;
return `${pad2(cfg.day)}.${pad2(cfg.month)}.${type === "SS" ? year : year + 1}`;
};
export const fristHasPassed = (semKurzbz) => {
const type = semKurzbz.slice(0, 2).toUpperCase();
const year = Number(semKurzbz.slice(2, 6));
if (!["SS", "WS"].includes(type) || !year) return false;
const deadline =
type === "SS" ? new Date(year, 10, 15, 23, 59, 59) : new Date(year + 1, 4, 15, 23, 59, 59);
return new Date() > deadline;
};
export const semesterWithPastFrist = (type = "SS") => {
const year = new Date().getFullYear();
for (let y = year; y >= year - 6; y -= 1) {
if (fristHasPassed(`${type}${y}`)) return `${type}${y}`;
}
return `${type}${year - 6}`;
};
// --- discovery ---
const resolveSemester = () => {
const configured = Cypress.env("NOTEN_SEM");
if (configured) return cy.wrap(configured, { log: false });
return cy
.request({
method: "GET",
url: "/index.ci.php/api/frontend/v1/organisation/Studiensemester/getAll",
qs: { order: "DESC" },
auth: { username: Cypress.env("adminusername"), password: Cypress.env("adminpassword") },
failOnStatusCode: false,
})
.then((response) => {
const semesters = expectNotenSuccess(response, "Studiensemester/getAll");
const today = toDateString(new Date());
const active = semesters
.filter((s) => (s.start || "").slice(0, 10) && (s.start || "").slice(0, 10) <= today)
.sort((a, b) => (b.start || "").localeCompare(a.start || ""))[0];
expect(active, `an active studiensemester starting on or before ${today}`).to.exist;
return active.studiensemester_kurzbz;
});
};
const resolveLehrveranstaltung = (semKurzbz) => {
const configured = Cypress.env("NOTEN_LV_ID");
if (configured) return cy.wrap(Number(configured), { log: false });
return notenApi.getBenotungstoolContext(semKurzbz).then((response) => {
const lvs = expectNotenSuccess(response, "getBenotungstoolContext").lehrveranstaltungen || [];
expect(
lvs.length,
`No Lehrveranstaltungen for ${semKurzbz}: the logged-in user teaches nothing here ` +
"(admins usually don't). Set NOTEN_LV_ID.",
).to.be.greaterThan(0);
return lvs[0].lehrveranstaltung_id;
});
};
/** maxAntritte as the server computes it: 1 + each enabled retake type. */
const computeMaxAntritte = (cisConfig) =>
1 +
(cisConfig.CIS_GESAMTNOTE_PRUEFUNG_TERMIN2 ? 1 : 0) +
(cisConfig.CIS_GESAMTNOTE_PRUEFUNG_TERMIN3 ? 1 : 0);
/** -> { semKurzbz, lvId, cisConfig, maxAntritte, notes, gradeNotes, students, studentUids } */
export const loadNotenContext = () => {
if (cachedContext) return cy.wrap(cachedContext, { log: false });
const context = {};
return resolveSemester()
.then((sem) => {
context.semKurzbz = sem;
return resolveLehrveranstaltung(sem);
})
.then((lvId) => {
context.lvId = lvId;
return notenApi.getCisConfig();
})
.then((response) => {
context.cisConfig = expectNotenSuccess(response, "getCisConfig");
context.maxAntritte = computeMaxAntritte(context.cisConfig);
return notenApi.getNoten();
})
.then((response) => {
const noten = expectNotenSuccess(response, "getNoten");
const byBezeichnung = (bez) => noten.find((n) => n.bezeichnung === bez);
const entschuldigt = byBezeichnung(BEZ_ENTSCHULDIGT);
const nochNicht = byBezeichnung(BEZ_NOCH_NICHT);
expect(entschuldigt, `tbl_note needs bezeichnung "${BEZ_ENTSCHULDIGT}"`).to.exist;
expect(nochNicht, `tbl_note needs bezeichnung "${BEZ_NOCH_NICHT}"`).to.exist;
// Restricted to the 1..5 scale: the wider lehre-Noten set contains note 0 ("Teilnote"),
// and saveStudentPruefung's `if($note=='')` guard rewrites a 0 to "Noch nicht eingetragen".
const specialPks = [entschuldigt.note, nochNicht.note];
const usable = noten.filter((n) => n.lehre && !specialPks.includes(n.note));
const ordinary = usable
.map((n) => n.note)
.filter((note) => Number(note) >= 1 && Number(note) <= 5)
.sort((a, b) => Number(a) - Number(b));
context.gradeNotes =
ordinary.length > 1
? ordinary
: usable.map((n) => n.note).filter((n) => Number(n) !== 0).sort((a, b) => Number(a) - Number(b));
expect(context.gradeNotes.length, "need two ordinary grades to vary one on edit").to.be.greaterThan(1);
context.notes = { entschuldigt: entschuldigt.note, nochNichtEingetragen: nochNicht.note };
return notenApi.getStudentenNoten(context.lvId, context.semKurzbz);
})
.then((response) => {
const data = expectNotenSuccess(response, `getStudentenNoten(${context.lvId})`);
const students = data[0] || [];
expect(students.length, `LV ${context.lvId} needs >=3 enrolled students`).to.be.greaterThan(2);
students.forEach((s) => expect(s.lehreinheit_id, `lehreinheit_id of ${s.uid}`).to.exist);
context.students = students;
context.studentUids = students.map((s) => s.uid);
cachedContext = context;
return context;
});
};
// --- fixture state ---
export const resetNotenState = (context, studentUids) =>
performReset(context, studentUids || context.studentUids);
/**
* Seeds the Antritt-1 baseline. Defaults to freigegeben:true because validatePruefungAdd reads the
* implicit first Antritt through getLvGesamtNoten(), which filters `freigabedatum < NOW()` - an
* offene note is invisible there and would not count as Antritt 1.
*/
export const seedBaseline = (context, studentUid, options = {}) =>
performSeed(context, studentUid, {
note: options.note !== undefined ? options.note : context.gradeNotes[0],
punkte: options.punkte !== undefined ? options.punkte : null,
benotungsdatum: options.benotungsdatum || baselineBenotungsdatum(context),
freigegeben: options.freigegeben !== undefined ? options.freigegeben : true,
freigabedatum: options.freigabedatum || null,
});
/** Raw row, bypassing the freigabedatum filter of getLvGesamtNoten. */
export const readLvGesamtnote = (context, studentUid) => performRead(context, studentUid);
/** Anchor date; attempt dates derive from it so ordering is known. */
export const baselineBenotungsdatum = (context) => `${Number(context.semKurzbz.slice(2, 6))}-01-10 08:00:00`;
export const baselineDate = (context) => baselineBenotungsdatum(context).slice(0, 10);
/** attemptDate(ctx,1) < attemptDate(ctx,2) < ... , all after the baseline. */
export const attemptDate = (context, index) => shiftDate(baselineDate(context), 30 * index);
/**
* Hard failure rather than a skip: these are the regulatory rules, and a green run that never
* exercised them is worse than a red one.
*/
export const requireDbReset = () =>
resolveResetStrategy().then((state) => {
expect(
state.strategy,
`Fixture reset unavailable.\n\n${describeFailure(state)}\n\n See tests/cypress/.env.example.\n`,
).to.not.be.null;
});
+150
View File
@@ -0,0 +1,150 @@
/**
* Postgres plumbing for cy.task fixture resets. Suite-agnostic.
*
* Connection, write guard, pooling and teardown live here. What to delete or seed belongs in a
* suite-specific task file -- see notenDb.js.
*
* Settings come from <PREFIX>_DB_* and <PREFIX>_SSH_*, where PREFIX is TEST_ENV_PREFIX. That
* indirection is the point: another suite sets its own prefix and reuses this file untouched.
*/
const { ensureTunnel, closeTunnel, tunnelPort } = require("./sshTunnel");
const PREFIX = process.env.TEST_ENV_PREFIX || "TEST";
const env = (key) => process.env[`${PREFIX}_DB_${key}`];
const sshEnv = (key) => process.env[`${PREFIX}_SSH_${key}`];
const dbConfigured = () => Boolean(env("HOST") && env("NAME") && env("USER"));
const writesAllowed = () => String(env("ALLOW_WRITES")).toLowerCase() === "true";
let pool = null;
const getPool = () => {
if (pool) return pool;
// lazy require so the suite loads without pg when no DB task is used
// eslint-disable-next-line global-require
const { Pool } = require("pg");
// with a tunnel up, bind to its local end - that is what gets us past pg_hba
const forwarded = tunnelPort();
pool = new Pool({
host: forwarded ? "127.0.0.1" : env("HOST"),
port: forwarded || Number(env("PORT") || 5432),
database: env("NAME"),
user: env("USER"),
password: env("PASSWORD"),
max: 4,
ssl: String(env("SSL")).toLowerCase() === "true" ? { rejectUnauthorized: false } : undefined,
});
return pool;
};
const assertWritable = () => {
if (!dbConfigured()) {
throw new Error(`db refused - set ${PREFIX}_DB_HOST / ${PREFIX}_DB_NAME / ${PREFIX}_DB_USER.`);
}
if (!writesAllowed()) {
throw new Error(`db refused - set ${PREFIX}_DB_ALLOW_WRITES=true (test databases only).`);
}
};
/** Runs fn with a pooled client and always releases it. */
const withClient = async (fn) => {
const client = await getPool().connect();
try {
return await fn(client);
} finally {
client.release();
}
};
/** Same, in a transaction that rolls back on any throw. */
const inTransaction = (fn) =>
withClient(async (client) => {
await client.query("BEGIN");
try {
const result = await fn(client);
await client.query("COMMIT");
return result;
} catch (error) {
await client.query("ROLLBACK");
throw error;
}
});
/**
* The pg_hba case is the one worth spelling out: it is server-side, so no local setting fixes it
* and the tunnel is the only workstation answer.
*/
const explainFailure = (error) => {
const msg = String(error && error.message ? error.message : error);
if (/no pg_hba\.conf entry/i.test(msg)) {
const host = (msg.match(/for host "([^"]+)"/) || [])[1] || "this machine";
return (
`the server refused the connection from ${host} - pg_hba.conf has no rule allowing it. ` +
`Use the SSH tunnel (${PREFIX}_SSH_TUNNEL=true) or have an entry added. Details: ${msg}`
);
}
if (/authentication failed/i.test(msg)) return `credentials rejected. Details: ${msg}`;
if (/database .* does not exist/i.test(msg)) return `${PREFIX}_DB_NAME does not exist. Details: ${msg}`;
if (/ECONNREFUSED/i.test(msg)) return `nothing listening on ${PREFIX}_DB_HOST:${PREFIX}_DB_PORT. Details: ${msg}`;
if (/ETIMEDOUT|EHOSTUNREACH|ENETUNREACH/i.test(msg)) return `host unreachable (firewall/VPN?). Details: ${msg}`;
return msg;
};
/** Opens the tunnel if configured, then proves the connection works. */
const checkAvailability = async ({ requireWrites = true } = {}) => {
if (!dbConfigured()) return { available: false, reason: "not-configured" };
if (requireWrites && !writesAllowed()) return { available: false, reason: "writes-disabled" };
if (String(sshEnv("TUNNEL")).toLowerCase() === "true") {
const tunnel = await ensureTunnel({
sshHost: sshEnv("HOST"),
sshPort: Number(sshEnv("PORT") || 22),
sshUser: sshEnv("USER"),
keyPath: sshEnv("KEY"),
passphrase: sshEnv("PASSPHRASE"),
agent: sshEnv("AGENT"),
dbHost: env("HOST"),
dbPort: Number(env("PORT") || 5432),
});
if (!tunnel.tunnelled) return { available: false, reason: `ssh-tunnel-failed: ${tunnel.reason}` };
}
try {
await withClient((client) => client.query("SELECT 1"));
return { available: true };
} catch (error) {
// a failed pool is poisoned - drop it so a retry reconnects cleanly
if (pool) {
try { await pool.end(); } catch (e) { /* ignore */ }
pool = null;
}
return { available: false, reason: explainFailure(error) };
}
};
const closeDb = async () => {
if (pool) {
await pool.end();
pool = null;
}
await closeTunnel();
return null;
};
module.exports = {
PREFIX,
env,
dbConfigured,
writesAllowed,
assertWritable,
withClient,
inTransaction,
checkAvailability,
closeDb,
};
+129
View File
@@ -0,0 +1,129 @@
/**
* cy.task implementations for the Gesamtnoteneingabe fixture. Connection and guards come from
* db.js; this file only knows which rows the §1 specs write and how to undo them.
*
* Needed because the Noten API has no delete endpoint, while every §1 test writes
* campus.tbl_lvgesamtnote and lehre.tbl_pruefung. Without a reset the suite is single-shot.
*
* Every statement is scoped by an explicit student_uid list plus the test LV and semester.
* No unscoped DELETE in this file.
*/
const {
assertWritable, dbConfigured, withClient, inTransaction, checkAvailability, closeDb,
} = require("./db");
const REQUIRED_SCOPE = ["lvId", "semKurzbz", "studentUids"];
const assertScope = (scope) => {
if (!scope || typeof scope !== "object") throw new Error("noten:db scope object is required");
REQUIRED_SCOPE.forEach((key) => {
if (scope[key] === undefined || scope[key] === null || scope[key] === "") {
throw new Error(`noten:db refused - missing scope key "${key}"`);
}
});
if (!Array.isArray(scope.studentUids) || scope.studentUids.length === 0) {
throw new Error("noten:db refused - studentUids must be a non-empty array");
}
if (scope.studentUids.some((uid) => typeof uid !== "string" || uid.trim() === "")) {
throw new Error("noten:db refused - studentUids must all be non-empty strings");
}
};
const resetStudents = async (scope) => {
assertWritable();
assertScope(scope);
const { lvId, semKurzbz, studentUids } = scope;
return inTransaction(async (client) => {
// pruefungen hang off lehreinheiten, so scope through the LV's lehreinheiten in this semester
const pruefungen = await client.query(
`DELETE FROM lehre.tbl_pruefung
WHERE student_uid = ANY($1::varchar[])
AND lehreinheit_id IN (
SELECT lehreinheit_id FROM lehre.tbl_lehreinheit
WHERE lehrveranstaltung_id = $2 AND studiensemester_kurzbz = $3)`,
[studentUids, lvId, semKurzbz],
);
const noten = await client.query(
`DELETE FROM campus.tbl_lvgesamtnote
WHERE student_uid = ANY($1::varchar[])
AND lehrveranstaltung_id = $2 AND studiensemester_kurzbz = $3`,
[studentUids, lvId, semKurzbz],
);
return { deletedPruefungen: pruefungen.rowCount, deletedLvGesamtnoten: noten.rowCount };
});
};
/**
* Seeds the Antritt-1 baseline. `freigegeben` matters: getLvGesamtNoten() filters
* `freigabedatum < NOW()`, so an offene note is invisible to validatePruefungAdd.
*/
const seedLvGesamtnote = async (scope) => {
assertWritable();
assertScope({ ...scope, studentUids: [scope.studentUid] });
const {
lvId, semKurzbz, studentUid, note, punkte = null, mitarbeiterUid,
benotungsdatum, freigegeben = false, freigabedatum = null,
} = scope;
if (note === undefined || note === null) throw new Error("noten:db seed - note is required");
if (!benotungsdatum) throw new Error("noten:db seed - benotungsdatum is required");
if (!mitarbeiterUid) throw new Error("noten:db seed - mitarbeiterUid is required");
// default the Freigabe to the benotungsdatum: earlier would read as "changed"
const resolvedFreigabe = freigegeben ? freigabedatum || benotungsdatum : null;
return withClient(async (client) => {
await client.query(
`DELETE FROM campus.tbl_lvgesamtnote
WHERE student_uid = $1 AND lehrveranstaltung_id = $2 AND studiensemester_kurzbz = $3`,
[studentUid, lvId, semKurzbz],
);
await client.query(
`INSERT INTO campus.tbl_lvgesamtnote
(student_uid, lehrveranstaltung_id, studiensemester_kurzbz, note, punkte,
mitarbeiter_uid, benotungsdatum, freigabedatum, freigabevon_uid, insertamum, insertvon)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, NOW(), $6)`,
[
studentUid, lvId, semKurzbz, note, punkte, mitarbeiterUid,
benotungsdatum, resolvedFreigabe, resolvedFreigabe ? mitarbeiterUid : null,
],
);
return { studentUid, note, benotungsdatum, freigabedatum: resolvedFreigabe };
});
};
/** Raw row, without the `freigabedatum < NOW()` filter getLvGesamtNoten applies. */
const readLvGesamtnote = async ({ lvId, semKurzbz, studentUid }) => {
if (!dbConfigured()) throw new Error("noten:db refused - database is not configured");
return withClient(async (client) => {
const res = await client.query(
`SELECT * FROM campus.tbl_lvgesamtnote
WHERE student_uid = $1 AND lehrveranstaltung_id = $2 AND studiensemester_kurzbz = $3`,
[studentUid, lvId, semKurzbz],
);
return res.rows[0] || null;
});
};
const registerNotenDbTasks = (on) => {
on("task", {
"noten:db:available": () => checkAvailability(),
"noten:db:reset": (scope) => resetStudents(scope),
"noten:db:seedLvGesamtnote": (scope) => seedLvGesamtnote(scope),
"noten:db:readLvGesamtnote": (scope) => readLvGesamtnote(scope),
"noten:db:close": () => closeDb(),
});
};
module.exports = { registerNotenDbTasks };
+137
View File
@@ -0,0 +1,137 @@
/**
* Local port forward over SSH, opened inside the node process.
*
* Knows nothing about the environment: the caller passes host, user and credential.
*/
const fs = require("fs");
const net = require("net");
let server = null;
let sshClient = null;
let localPort = null;
/** Local end of the forward, or null. Lets the pool bind without going through the environment. */
const tunnelPort = () => localPort;
const resolveAgent = (agent) => {
if (agent && agent !== "true") return agent;
if (process.env.SSH_AUTH_SOCK) return process.env.SSH_AUTH_SOCK;
if (process.platform === "win32") return "\\\\.\\pipe\\openssh-ssh-agent";
return null;
};
/**
* Key file or agent, either is enough. A configured but missing key path is an error rather than a
* silent fallback to the agent, since that is nearly always a typo.
*/
const resolveAuth = ({ keyPath, passphrase, agent }) => {
if (keyPath) {
const resolved = keyPath.startsWith("~")
? keyPath.replace(/^~/, process.env.HOME || process.env.USERPROFILE || "")
: keyPath;
if (!fs.existsSync(resolved)) {
throw new Error(`SSH key does not exist: ${resolved}. Fix the path, or clear it to use an agent.`);
}
return {
privateKey: fs.readFileSync(resolved),
passphrase: passphrase || undefined,
description: `key ${resolved}`,
};
}
const resolvedAgent = resolveAgent(agent);
if (resolvedAgent) return { agent: resolvedAgent, description: `agent ${resolvedAgent}` };
throw new Error("No SSH credential: set a key path, or ssh-add your key and leave it empty.");
};
/** Idempotent - repeated calls reuse the existing tunnel. */
const openTunnel = (cfg) =>
new Promise((resolve, reject) => {
if (localPort) return resolve(localPort);
if (!cfg.sshHost || !cfg.sshUser) return reject(new Error("Tunnel needs an SSH host and user."));
// eslint-disable-next-line global-require
const { Client } = require("ssh2");
let auth;
try {
auth = resolveAuth(cfg);
} catch (error) {
return reject(error);
}
sshClient = new Client();
sshClient
.on("ready", () => {
server = net.createServer((socket) => {
sshClient.forwardOut(
socket.remoteAddress || "127.0.0.1",
socket.remotePort || 0,
cfg.dbHost,
cfg.dbPort,
(err, stream) => {
if (err) return socket.destroy();
socket.pipe(stream).pipe(socket);
},
);
});
server.on("error", reject);
// port 0: let the OS pick, so a leftover process cannot collide
server.listen(0, "127.0.0.1", () => {
localPort = server.address().port;
// eslint-disable-next-line no-console
console.log(
`[db] SSH tunnel up: 127.0.0.1:${localPort} -> ${cfg.dbHost}:${cfg.dbPort} ` +
`via ${cfg.sshUser}@${cfg.sshHost} (${auth.description})`,
);
resolve(localPort);
});
})
.on("error", (err) =>
reject(
new Error(
`SSH to ${cfg.sshUser}@${cfg.sshHost} using ${auth.description} failed: ${err.message}. ` +
"The SSH host is often not the web hostname, and a non-default key filename is never " +
"tried automatically.",
),
),
)
.connect({
host: cfg.sshHost,
port: cfg.sshPort || 22,
username: cfg.sshUser,
privateKey: auth.privateKey,
passphrase: auth.passphrase,
agent: auth.agent,
readyTimeout: 15000,
});
});
const closeTunnel = async () => {
if (server) {
await new Promise((resolve) => server.close(resolve));
server = null;
}
if (sshClient) {
sshClient.end();
sshClient = null;
}
localPort = null;
return null;
};
const ensureTunnel = async (cfg) => {
try {
return { tunnelled: true, localPort: await openTunnel(cfg) };
} catch (error) {
return { tunnelled: false, reason: error.message };
}
};
module.exports = { ensureTunnel, closeTunnel, tunnelPort };
+117
View File
@@ -0,0 +1,117 @@
/**
* Fixture preconditions for the Gesamtnoteneingabe suite. Data only -- dbCheck.js runs it.
*
* Every precondition of the chain
* getBenotungstoolContext -> getStudentenNoten -> saveStudentPruefung
* is its own query, so a failure names the exact missing link instead of "no students".
*/
const path = require("path");
// tests/cypress/tools/checks -> repo root is four levels up
const seeder = (name) => path.join(__dirname, "..", "..", "..", "..", "system", "seeders", name);
/** Test semester: the running one, else the last started. Same rule as the suite and seeder 016. */
const SEM = `(SELECT studiensemester_kurzbz FROM public.tbl_studiensemester
WHERE start <= now() ORDER BY (ende >= now()) DESC, start DESC LIMIT 1)`;
module.exports = {
title: "Gesamtnoteneingabe",
sqlFiles: {
seed: seeder("016_benotungstool_noten.sql"),
},
checks: [
{
label: "Test semester (latest started)",
sql: `SELECT ${SEM} AS value`,
ok: (r) => Boolean(r.value),
hint: "No studiensemester with start <= now(). Apply the base dump + 003_kompetenzfeld.sql.",
},
{
label: "demolektor1 exists",
sql: `SELECT COUNT(*)::int AS value FROM public.tbl_mitarbeiter WHERE mitarbeiter_uid = 'demolektor1'`,
ok: (r) => r.value > 0,
hint: "Apply 002_mitarbeiter.sql.",
},
{
label: "STG5 Lehrveranstaltungen (5121 / 5221)",
sql: `SELECT COUNT(*)::int AS value FROM lehre.tbl_lehrveranstaltung
WHERE lehrveranstaltung_id IN (5121, 5221)`,
ok: (r) => r.value === 2,
hint: "Apply 013_studiengang_5.sql.",
},
{
label: "Lehreinheiten of demolektor1 in the test semester",
sql: `SELECT COUNT(*)::int AS value
FROM lehre.tbl_lehreinheit le
JOIN lehre.tbl_lehreinheitmitarbeiter USING (lehreinheit_id)
WHERE mitarbeiter_uid = 'demolektor1' AND le.studiensemester_kurzbz = ${SEM}`,
ok: (r) => r.value > 0,
hint:
"demolektor1 teaches nothing in the CURRENT test semester. The 013 seeder pins its " +
"Lehreinheiten to the semester that was active when it ran. Apply 016_benotungstool_noten.sql.",
},
{
label: "Lehreinheitgruppe rows with a non-NULL gruppe_kurzbz",
sql: `SELECT COUNT(*)::int AS value FROM lehre.tbl_lehreinheitgruppe
WHERE gruppe_kurzbz IS NOT NULL`,
ok: (r) => r.value > 0,
hint:
"campus.vw_student_lehrveranstaltung joins ONLY on gruppe_kurzbz. Lehrverband-style rows " +
"(verband set, gruppe_kurzbz NULL) never match. Apply 016_benotungstool_noten.sql.",
},
{
label: "Group memberships carrying a studiensemester",
sql: `SELECT COUNT(*)::int AS value FROM public.tbl_benutzergruppe
WHERE studiensemester_kurzbz IS NOT NULL`,
ok: (r) => r.value > 0,
hint:
"tbl_benutzergruppe.studiensemester_kurzbz must equal tbl_lehreinheit.studiensemester_kurzbz. " +
"NULL never matches. Apply 016_benotungstool_noten.sql.",
},
{
label: "Students visible in LV 5221 (the test LV)",
sql: `SELECT COUNT(*)::int AS value FROM campus.vw_student_lehrveranstaltung
WHERE lehrveranstaltung_id = 5221 AND studiensemester_kurzbz = ${SEM}`,
ok: (r) => r.value >= 3,
hint: "The suite needs at least 3 enrolled students. Apply 016_benotungstool_noten.sql.",
},
{
label: "tbl_note 'entschuldigt' (resolved by Bezeichnung)",
sql: `SELECT COALESCE((SELECT note::text FROM lehre.tbl_note
WHERE bezeichnung = 'entschuldigt'), '') AS value`,
ok: (r) => r.value !== "",
hint: "Noten.php resolves this by Bezeichnung, not by the config PK. Apply the base inserts.",
},
{
label: "tbl_note 'Noch nicht eingetragen'",
sql: `SELECT COALESCE((SELECT note::text FROM lehre.tbl_note
WHERE bezeichnung = 'Noch nicht eingetragen'), '') AS value`,
ok: (r) => r.value !== "",
hint: "Missing from the base dump. Rebuild with system/setup_testinstance.php --setup.",
},
{
label: "Pruefungstypen Termin1/Termin2/Termin3/kommPruef",
sql: `SELECT COALESCE(string_agg(pruefungstyp_kurzbz, ',' ORDER BY pruefungstyp_kurzbz), '') AS value
FROM lehre.tbl_pruefungstyp
WHERE pruefungstyp_kurzbz IN ('Termin1','Termin2','Termin3','kommPruef')`,
ok: (r) => r.value.includes("Termin1") && r.value.includes("Termin2"),
hint:
"Termin3 is absent from the base dump. Harmless while CIS_GESAMTNOTE_PRUEFUNG_TERMIN3 is " +
"off, but a Termin3 insert would hit a foreign key error. 016 adds it.",
},
{
label: "Notenschluessel assigned to LV 5221",
sql: `SELECT COUNT(*)::int AS value
FROM lehre.tbl_notenschluesselzuordnung z
JOIN lehre.tbl_notenschluesselaufteilung a USING (notenschluessel_kurzbz)
WHERE z.lehrveranstaltung_id = 5221`,
ok: (r) => r.value > 0,
hint:
"The Notenschluessel tables are empty in the base dump, so getNoteByPunkte always returns " +
"null. Apply 016_benotungstool_noten.sql.",
},
],
};
+193
View File
@@ -0,0 +1,193 @@
#!/usr/bin/env node
/**
* Diagnose or seed the database fixture a Cypress suite needs. Suite-agnostic runner.
*
* node tests/cypress/tools/dbCheck.js noten report what is present and what is missing
* node tests/cypress/tools/dbCheck.js noten seed apply the suite's seeder, then re-check
* node tests/cypress/tools/dbCheck.js noten env print the .env block to use
*
* A suite contributes tools/checks/<suite>.js exporting { title, checks, sqlFiles }. Connection,
* tunnel and output are shared and live here.
*
* `check` is read-only; `seed` needs <PREFIX>_DB_ALLOW_WRITES=true and an owner role.
*/
const fs = require("fs");
const path = require("path");
try {
require("dotenv").config({ path: path.join(__dirname, "..", ".env") });
} catch (e) {
// dotenv missing -> fall back to the ambient environment
}
const db = require("../tasks/db");
const COL = 48;
const CHECKS_DIR = path.join(__dirname, "checks");
const usage = (suite, mode) => `node tests/cypress/tools/dbCheck.js ${suite} ${mode}`;
const loadSuite = (name) => {
const file = path.join(CHECKS_DIR, `${name}.js`);
if (!fs.existsSync(file)) {
const available = fs.existsSync(CHECKS_DIR)
? fs.readdirSync(CHECKS_DIR).map((f) => f.replace(/\.js$/, "")).join(", ")
: "(none)";
console.error(`\nUnknown suite "${name}". Available: ${available}\n`);
process.exit(2);
}
// eslint-disable-next-line global-require, import/no-dynamic-require
return require(file);
};
const runChecks = async (client, suite) => {
console.log(`\n${suite.title} fixture check\n${"=".repeat(70)}`);
const failures = [];
for (const check of suite.checks) {
let row;
try {
row = (await client.query(check.sql)).rows[0] || {};
} catch (error) {
console.log(` [ERR ] ${check.label}\n ${error.message}`);
failures.push(check);
continue;
}
const passed = check.ok(row);
const value = row.value === "" ? "(none)" : String(row.value);
console.log(` [${passed ? "PASS" : "FAIL"}] ${check.label.padEnd(COL)} ${value}`);
if (!passed) failures.push(check);
}
console.log("=".repeat(70));
if (!failures.length) {
console.log("\nAll preconditions met.\n");
return 0;
}
console.log(`\n${failures.length} problem(s):\n`);
failures.forEach((f) => console.log(` - ${f.label}\n ${f.hint}\n`));
console.log(`Fix with: ${usage(suite.name, "seed")}\n`);
return 1;
};
const applySqlFile = async (client, file) => {
if (!db.writesAllowed()) {
console.error(`\nRefusing to write: set ${db.PREFIX}_DB_ALLOW_WRITES=true first.\n`);
return 2;
}
if (!fs.existsSync(file)) {
console.error(`\nFile not found: ${file}\n`);
return 2;
}
console.log(`\nApplying ${path.relative(process.cwd(), file)} ...\n`);
// One connection, one call: the seeders rely on running as a unit (temp tables, DO blocks and a
// closing verification query).
let result;
try {
result = await client.query(fs.readFileSync(file, "utf8"));
} catch (error) {
// `check` gets by as the application role; seeding creates and grants objects.
if (/permission denied/i.test(error.message)) {
console.error(`${error.message}\n`);
console.error(`Seeding needs the database owner, but ${db.PREFIX}_DB_USER is "${db.env("USER")}".`);
console.error("Point it at the owner role, or seed via system/setup_testinstance.php.\n");
return 2;
}
throw error;
}
// Print whatever the last statement returned, whatever its shape.
const results = Array.isArray(result) ? result : [result];
const last = results.filter((r) => r && r.rows && r.rows.length).pop();
if (last) {
console.log("Verification\n" + "-".repeat(50));
last.rows.forEach((row) =>
Object.entries(row).forEach(([k, v]) => console.log(` ${k.padEnd(24)} ${v}`)));
}
console.log(`\nDone: ${path.basename(file)}\n`);
return 0;
};
const printEnv = () => {
const p = db.PREFIX;
console.log(`
Add to tests/cypress/.env (gitignored):
TEST_ENV_PREFIX=${p}
${p}_DB_HOST=<postgres host>
${p}_DB_PORT=5432
${p}_DB_NAME=<test database>
${p}_DB_USER=<user>
${p}_DB_PASSWORD=<password>
${p}_DB_ALLOW_WRITES=true
If pg_hba.conf does not admit this machine, add the tunnel:
${p}_SSH_TUNNEL=true
${p}_SSH_HOST=<ssh host, often NOT the web hostname>
${p}_SSH_USER=<user>
${p}_SSH_KEY=<path, or empty to use the ssh agent>
`);
};
const main = async () => {
const suiteName = process.argv[2];
const mode = process.argv[3] || "check";
if (!suiteName || suiteName.startsWith("-")) {
console.error(`\n ${usage("<suite>", "[check|seed|env]")}\n`);
return 2;
}
if (mode === "env") {
printEnv();
return 0;
}
if (!["check", "seed"].includes(mode)) {
console.error(`Unknown mode "${mode}". Use: check | seed | env`);
return 2;
}
const suite = loadSuite(suiteName);
suite.name = suiteName;
if (mode !== "check" && !(suite.sqlFiles && suite.sqlFiles[mode])) {
console.error(`Suite "${suiteName}" defines no SQL file for "${mode}".`);
return 2;
}
// Opens the SSH tunnel when configured, so a workstation run needs no manual forward.
const status = await db.checkAvailability({ requireWrites: mode !== "check" });
if (!status.available) {
console.error(`\nCould not connect: ${status.reason}\n`);
if (status.reason === "not-configured") printEnv();
return 2;
}
try {
return await db.withClient(async (client) => {
client.on("notice", (n) => console.log(` NOTICE: ${n.message}`));
if (mode !== "check") {
const code = await applySqlFile(client, suite.sqlFiles[mode]);
if (code !== 0) return code;
}
return runChecks(client, suite);
});
} finally {
await db.closeDb();
}
};
main()
.then((code) => process.exit(code))
.catch((error) => {
console.error(`\n${error.message}\n`);
process.exit(1);
});