mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-10-12 15:04:04 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aabec8d6fd | ||
|
|
0d82753833 | ||
|
|
a9b9cd59b0 | ||
|
|
2050f5ae65 | ||
|
|
587e523990 | ||
|
|
5ec1a1c54c | ||
|
|
2c65ccc8da | ||
|
|
787308aad4 | ||
|
|
ba92eea7eb | ||
|
|
50951dfdcf | ||
|
|
be7527e994 | ||
|
|
c1939d0e23 | ||
|
|
d5c1721ab1 | ||
|
|
8eb27b194f | ||
|
|
579a55a00d | ||
|
|
0a00caa1e4 | ||
|
|
c53040ed5c | ||
|
|
f7465047cb | ||
|
|
0dadaece08 | ||
|
|
73c63c791d | ||
|
|
7c9bcb6fd2 | ||
|
|
69fd223358 | ||
|
|
4399857f4a | ||
|
|
9c43374267 | ||
|
|
ea7c0cccde | ||
|
|
6dfe292776 | ||
|
|
3212800643 | ||
|
|
c90f7a31bb | ||
|
|
073160dde4 | ||
|
|
6d2cbf4896 | ||
|
|
56fe8c9d09 | ||
|
|
9a3532265f | ||
|
|
4abe6f0d24 | ||
|
|
9fbbd6b855 | ||
|
|
59b4b2bac9 | ||
|
|
5f546fca2a | ||
|
|
1bf2b707ef | ||
|
|
f74b885253 | ||
|
|
3ab402adef | ||
|
|
52f24645fb | ||
|
|
4ac108174b | ||
|
|
6378b80d87 | ||
|
|
658c8d6bd4 | ||
|
|
bf29faa5a7 | ||
|
|
2ada167557 | ||
|
|
cc9d1f983e | ||
|
|
57c48f2c4a | ||
|
|
e32691994c | ||
|
|
6d641bbd06 | ||
|
|
3455aed3f5 | ||
|
|
f84d12277d | ||
|
|
9bf5bc2ad9 | ||
|
|
27765606e3 | ||
|
|
75d2cabdbe | ||
|
|
bae9d6d9a0 | ||
|
|
43d6a882ce | ||
|
|
7f3b4100ab | ||
|
|
9f54ecce54 | ||
|
|
7af0f4a478 | ||
|
|
0f843db33d | ||
|
|
3e59648d5b | ||
|
|
5923991848 | ||
|
|
55a6ec9d0d | ||
|
|
78505589c8 | ||
|
|
5e15d4b219 | ||
|
|
afb8011347 | ||
|
|
46f8d0d07d | ||
|
|
15beaa9be8 | ||
|
|
574057da88 | ||
|
|
9274743df3 | ||
|
|
a5797a0bde | ||
|
|
97be497fda | ||
|
|
37d5f2da5d | ||
|
|
27c39cfdca | ||
|
|
06895510e0 | ||
|
|
83b06b6c50 | ||
|
|
eeb1529b64 | ||
|
|
98c3707802 | ||
|
|
3c9f46941c | ||
|
|
c9c92f82d3 | ||
|
|
e5c8807f17 | ||
|
|
56fcb23275 | ||
|
|
dba199b531 | ||
|
|
193dd166c3 | ||
|
|
431e0bb341 | ||
|
|
beb54c1bc5 | ||
|
|
4e6a2d5218 | ||
|
|
273f00a9c4 | ||
|
|
32de4aac6b | ||
|
|
66e400013a | ||
|
|
3f95bfd82f | ||
|
|
dc22ac6b06 | ||
|
|
8bf18b0d37 | ||
|
|
79c0f31ddc | ||
|
|
49d61342c2 | ||
|
|
be0943f1ba | ||
|
|
f4cc311806 | ||
|
|
df46b8ebdd | ||
|
|
870c36e76b | ||
|
|
c56064d189 | ||
|
|
96b2d88d39 | ||
|
|
474fc1fc57 | ||
|
|
3825e2fb38 | ||
|
|
f6747713a1 | ||
|
|
4c0635be7c | ||
|
|
67b863f9db | ||
|
|
7628ebc9ca | ||
|
|
deb6dad7ad | ||
|
|
077f052112 | ||
|
|
e7f57c9ddd | ||
|
|
095e2bf581 | ||
|
|
25345a0522 | ||
|
|
e2b5201b5a | ||
|
|
5c80a382bf | ||
|
|
aa940683d6 | ||
|
|
843c65d52b | ||
|
|
e26f4262df | ||
|
|
dde586e004 | ||
|
|
506c23ae89 | ||
|
|
e90e03e0cc | ||
|
|
335671b46a | ||
|
|
19b8c16057 | ||
|
|
dea3aac222 | ||
|
|
5d7281e470 | ||
|
|
a7d925a177 | ||
|
|
4ef4a06a7e | ||
|
|
29515491a2 | ||
|
|
6cb8d0a9d1 | ||
|
|
2c4574d93b | ||
|
|
2fde630971 | ||
|
|
fce5ee7a16 | ||
|
|
8ccb9cd892 | ||
|
|
d1af44bcdc | ||
|
|
5a6d20f817 | ||
|
|
ce5da22180 | ||
|
|
05b2c3c42b | ||
|
|
2dd732b924 | ||
|
|
110f73e622 | ||
|
|
bb0d118284 | ||
|
|
701ccadff3 | ||
|
|
34555504df | ||
|
|
d1f5220925 | ||
|
|
decd514b22 | ||
|
|
6cf7093293 | ||
|
|
17f11fa871 | ||
|
|
96812868a4 | ||
|
|
40c79158f7 | ||
|
|
054663ee00 | ||
|
|
81eee814e9 | ||
|
|
390a3c0d5a | ||
|
|
695dd655c0 | ||
|
|
957da460a6 | ||
|
|
2cee36d7b5 | ||
|
|
43925e3088 | ||
|
|
1c236cce02 | ||
|
|
4956a517ca | ||
|
|
efc67d14a5 | ||
|
|
a6167583a3 | ||
|
|
1e68eb0b90 | ||
|
|
332efd4106 | ||
|
|
f303191c54 | ||
|
|
d6c7f16ceb | ||
|
|
f1912fe739 | ||
|
|
2f7fe05d21 | ||
|
|
ee4b61f549 | ||
|
|
511a4256bc | ||
|
|
3c9db86df2 | ||
|
|
367204a1ee | ||
|
|
bbe55a75ea | ||
|
|
e58bf3a8cf | ||
|
|
1f2f866c61 | ||
|
|
6ccbc95697 | ||
|
|
52d9e0a195 | ||
|
|
6a3982347b | ||
|
|
fe7feeb74e | ||
|
|
658fe79ad7 | ||
|
|
5bbf05ac8a |
@@ -3,3 +3,4 @@
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
$config['infocenter_studiengang_kz'] = '10021, 10027, 10002';
|
||||
$config['infocenter_qualifikationskurs_kz'] = '10002';
|
||||
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
// The configuration of the Benotungstool. The tool reads two sources:
|
||||
// this file $this->config->item('KEY')
|
||||
// global.config.inc.php define() flags of the old tool: CIS_GESAMTNOTE_PUNKTE, CIS_GESAMTNOTE_GEWICHTUNG,
|
||||
// CIS_GESAMTNOTE_FREIGABEMAIL_NOTE, CIS_GESAMTNOTE_PRUEFUNG_MOODLE_LE_NOTE and
|
||||
// CIS_GESAMTNOTE_PRUEFUNG_TERMIN2/TERMIN3/KOMMPRUEF (see CIS_GESAMTNOTE_MAX_ANTRITTE)
|
||||
//
|
||||
// The prefixes in this file:
|
||||
// NOTEN_, NOTE_ name a Note by its Bezeichnung. The server finds its key in lehre.tbl_note.
|
||||
// PRUEFUNG_ name a Pruefungstyp from lehre.tbl_pruefungstyp.
|
||||
// CIS_GESAMTNOTE_ the switches and values of the tool.
|
||||
//
|
||||
// Every key must be present. The code has no default values.
|
||||
|
||||
// --- Noten ---------------------------------------------------------------------------------------
|
||||
|
||||
// Noten that use no Antritt.
|
||||
$config['NOTEN_OHNE_ANTRITT_BEZEICHNUNGEN'] = ['Noch nicht eingetragen', 'entschuldigt'];
|
||||
|
||||
// Anrechnung Noten: an earlier result counts for this LV. As a Zeugnisnote they block every Pruefung.
|
||||
$config['NOTEN_ANRECHNUNG_BEZEICHNUNGEN'] = ['angerechnet', 'intern angerechnet'];
|
||||
|
||||
// How often a Note may occur in the Pruefungen of one student.
|
||||
$config['NOTEN_OCCURRENCE_LIMIT_MAP'] = ['entschuldigt' => 1];
|
||||
|
||||
// The Note 'entschuldigt'. An addon can report a Pruefung date as entschuldigt.
|
||||
$config['NOTE_ENTSCHULDIGT_BEZEICHNUNG'] = 'entschuldigt';
|
||||
|
||||
// The Note of a Pruefung without a result.
|
||||
$config['NOTE_NICHT_EINGETRAGEN_BEZEICHNUNG'] = 'Noch nicht eingetragen';
|
||||
|
||||
// Noten with no better one. They always close the Antritt chain.
|
||||
$config['NOTEN_ABSCHLIESSEND_BEZEICHNUNGEN'] = ['Sehr Gut', 'Bestanden', 'Approbiert', 'Erfolgreich absolviert'];
|
||||
|
||||
// The order of the Noten, best first. tbl_note.notenwert is NULL everywhere, so the order cannot come
|
||||
// from the database. A Note outside this list is not comparable.
|
||||
$config['NOTEN_RANGFOLGE_BEZEICHNUNGEN'] = ['Sehr Gut', 'Gut', 'Befriedigend', 'Genügend', 'Nicht Genügend'];
|
||||
|
||||
// The order of the Noten in the lists: 'skala' = 1-5 first, then alphabetical; 'bezeichnung' = alphabetical.
|
||||
$config['NOTEN_SORTIERUNG'] = 'skala';
|
||||
|
||||
// --- Antritte -------------------------------------------------------------------------------------
|
||||
|
||||
// The maximum number of Antritte, Antritt 1 and the kommissionelle Pruefung included.
|
||||
// null = 1 + CIS_GESAMTNOTE_PRUEFUNG_TERMIN2 + CIS_GESAMTNOTE_PRUEFUNG_TERMIN3 + CIS_GESAMTNOTE_PRUEFUNG_KOMMPRUEF.
|
||||
// The Pruefungsordnung permits three Antritte: TERMIN2 and KOMMPRUEF give 3, TERMIN3 adds one more.
|
||||
$config['CIS_GESAMTNOTE_MAX_ANTRITTE'] = null;
|
||||
|
||||
// The Antritt from which the Pruefung is kommissionell:
|
||||
// 'letzter' the last Antritt (CIS_GESAMTNOTE_MAX_ANTRITTE)
|
||||
// 0 never
|
||||
// 3 from Antritt 3 on
|
||||
// A chain of one Antritt is never kommissionell.
|
||||
$config['CIS_GESAMTNOTE_KOMMISSIONELL_AB_ANTRITT'] = 'letzter';
|
||||
|
||||
// The Benotungstool may create the kommissionelle Pruefung. Some installations enter it in the StV.
|
||||
// false: the tool shows an existing kommissionelle Pruefung, but it creates none. The chain then ends
|
||||
// one Antritt earlier for this tool.
|
||||
$config['CIS_GESAMTNOTE_ALLOW_CREATE_KOMMPRUEF'] = true;
|
||||
|
||||
// Allow another Antritt after a positive Note. It uses an Antritt like any repeat.
|
||||
$config['CIS_GESAMTNOTE_NOTENVERBESSERUNG'] = false;
|
||||
|
||||
// A worse repeat keeps the better LV-Note. The Pruefung keeps its own Note.
|
||||
$config['CIS_GESAMTNOTE_VERBESSERUNG_BESSERE_GEWINNT'] = false;
|
||||
|
||||
// Create Antritt 1 as its own Pruefung when a Note becomes the LV-Note: the proposal, the import, the
|
||||
// Freigabe, and the Notenuebernahme in the StV.
|
||||
$config['CIS_GESAMTNOTE_ERSTANTRITT_BEI_UEBERNAHME'] = true;
|
||||
|
||||
// --- Pruefungstypen ---------------------------------------------------------------------------------
|
||||
// The tool derives the position of a Pruefung from its date. The type marks a kommissionelle Pruefung,
|
||||
// sorts old Pruefungen without a date, separates Antritt 1 from a repeat (verlauf.hasRepeat), and feeds
|
||||
// the old reports of the StV.
|
||||
|
||||
// The Pruefungstypen of a kommissionelle Pruefung.
|
||||
$config['PRUEFUNG_KOMMISSIONELL_TYPEN'] = ['kommPruef', 'zusKommPruef'];
|
||||
|
||||
// The Pruefungstyp that the tool writes for a kommissionelle Pruefung.
|
||||
$config['PRUEFUNG_TYP_KOMMISSIONELL'] = 'kommPruef';
|
||||
|
||||
// Pruefungstypen that never use an Antritt. A zusKommPruef repeats a kommissionelle Pruefung with a
|
||||
// procedural fault. The StV enters it.
|
||||
$config['PRUEFUNG_TYPEN_OHNE_ANTRITT'] = ['zusKommPruef'];
|
||||
|
||||
// The Pruefungstyp that the tool writes for each Antritt. A type that tbl_pruefungstyp does not have
|
||||
// is skipped (Termin3 is absent by default).
|
||||
$config['PRUEFUNG_TYP_JE_ANTRITT'] = [1 => 'Termin1', 2 => 'Termin2', 3 => 'Termin3'];
|
||||
|
||||
// --- Pruefung dates -------------------------------------------------------------------------------
|
||||
|
||||
// Allow a new Pruefung on the day of an existing one.
|
||||
$config['CIS_GESAMTNOTE_PRUEFUNG_GLEICHER_TAG'] = false;
|
||||
|
||||
// A later Pruefung locks the Note of an earlier one. Its date stays editable.
|
||||
$config['CIS_GESAMTNOTE_NOTE_SPERRE_BEI_SPAETERER_PRUEFUNG'] = true;
|
||||
|
||||
// Allow a Benotungsdatum in the future: the day of Antritt 1 when the LV-Note is written. A Pruefung
|
||||
// may always lie in the future: without a Note it waits for its result.
|
||||
$config['CIS_GESAMTNOTE_DATUM_ZUKUNFT'] = false;
|
||||
|
||||
// The minimum number of days between two Antritte. A Pruefung without an Antritt does not count.
|
||||
// null = off
|
||||
$config['CIS_GESAMTNOTE_ANTRITT_MIN_ABSTAND_TAGE'] = null;
|
||||
|
||||
// The maximum number of days between two Antritte. null = off
|
||||
$config['CIS_GESAMTNOTE_ANTRITT_MAX_ABSTAND_TAGE'] = null;
|
||||
|
||||
// --- Frist ----------------------------------------------------------------------------------------
|
||||
// The Frist (Pruefungsordnung §1) is a day in the year of the Studiensemester:
|
||||
// Sommersemester SSyyyy -> the same year
|
||||
// Wintersemester WSyyyy -> the next year
|
||||
|
||||
$config['NOTENEINTRAGUNGSFRIST_SS'] = ['month' => 11, 'day' => 15];
|
||||
$config['NOTENEINTRAGUNGSFRIST_WS'] = ['month' => 5, 'day' => 15];
|
||||
|
||||
// No entry after the Frist.
|
||||
$config['CIS_GESAMTNOTE_FRIST_EINGABE'] = true;
|
||||
|
||||
// No Pruefung date after the Frist.
|
||||
// Example: a Pruefung must take place before the Frist, but the Note may come later -> EINGABE false.
|
||||
$config['CIS_GESAMTNOTE_FRIST_PRUEFUNGSDATUM'] = true;
|
||||
|
||||
// Permissions that may enter after the Frist. The Pruefung date has no exception.
|
||||
// Example: ['admin', 'lehre/benotungstool_assistenz']
|
||||
$config['CIS_GESAMTNOTE_FRIST_AUSNAHME'] = [];
|
||||
|
||||
// --- Roles and Freigabe ---------------------------------------------------------------------------
|
||||
|
||||
// The actions of each permission. The keys are also the permissions that open the tool.
|
||||
// lvnote write the LV-Note (the proposal)
|
||||
// pruefung create or edit a Pruefung
|
||||
// kommpruef create the kommissionelle Pruefung (also needs CIS_GESAMTNOTE_ALLOW_CREATE_KOMMPRUEF)
|
||||
// freigabe the Freigabe
|
||||
// import the two imports
|
||||
// A user with several permissions gets all their actions.
|
||||
$config['CIS_GESAMTNOTE_ROLLENMATRIX'] = [
|
||||
'lehre/benotungstool' => ['lvnote', 'pruefung', 'kommpruef', 'freigabe', 'import'],
|
||||
'lehre/benotungstool_assistenz' => ['lvnote', 'pruefung', 'kommpruef', 'freigabe', 'import']
|
||||
];
|
||||
|
||||
// A Lektor sees only the LVs that the Lektor teaches.
|
||||
$config['CIS_GESAMTNOTE_LEKTOR_NUR_EIGENE_LV'] = true;
|
||||
|
||||
// The Freigabe asks for the password of the user.
|
||||
$config['CIS_GESAMTNOTE_FREIGABE_PASSWORT'] = true;
|
||||
|
||||
// The Freigabe sends a mail.
|
||||
$config['CIS_GESAMTNOTE_FREIGABEMAIL'] = true;
|
||||
|
||||
// The recipients of the mail: 'studiengang' = the addresses of the Studiengang, 'aufrufer' = the user.
|
||||
// An entry with an '@' is a fixed address.
|
||||
$config['CIS_GESAMTNOTE_FREIGABEMAIL_EMPFAENGER'] = ['studiengang', 'aufrufer'];
|
||||
|
||||
// The Sancho template of the mail. The text is in the database.
|
||||
$config['CIS_GESAMTNOTE_FREIGABEMAIL_VORLAGE'] = 'Notenfreigabe';
|
||||
|
||||
// A freigegeben LV-Note is final. No path can change it.
|
||||
$config['CIS_GESAMTNOTE_FREIGABE_FINAL'] = false;
|
||||
|
||||
// A new or changed Pruefung cancels the Freigabe of the LV-Note: it sets the benotungsdatum.
|
||||
$config['CIS_GESAMTNOTE_PRUEFUNG_HEBT_FREIGABE_AUF'] = true;
|
||||
|
||||
// --- LV-Note and proposal -------------------------------------------------------------------------
|
||||
|
||||
// An LV-Note must be a Note of the Lehre (tbl_note.lehre).
|
||||
$config['CIS_GESAMTNOTE_LVNOTE_NUR_LEHRENOTEN'] = true;
|
||||
|
||||
// The proposal stays open after a repeat. false: after a repeat the Lektor changes the LV-Note
|
||||
// through the Pruefung.
|
||||
$config['CIS_GESAMTNOTE_VORSCHLAG_NACH_WIEDERHOLUNG'] = false;
|
||||
|
||||
// The rounding of the Teilnoten average. The smaller number is the better Note:
|
||||
// 'kaufmaennisch' 2.5 -> 3
|
||||
// 'besser' 2.5 -> 2
|
||||
// 'schlechter' 2.1 -> 3
|
||||
$config['CIS_GESAMTNOTE_VORSCHLAG_RUNDUNG'] = 'kaufmaennisch';
|
||||
|
||||
// The decimals of the Punkte average before the Notenschluessel applies.
|
||||
$config['CIS_GESAMTNOTE_VORSCHLAG_PUNKTE_STELLEN'] = 2;
|
||||
|
||||
// --- Import and display ---------------------------------------------------------------------------
|
||||
|
||||
// The two imports. With both on, the tool shows two buttons.
|
||||
$config['CIS_GESAMTNOTE_PRUEFUNGSIMPORT'] = true; // one Pruefung per row: Kennung, Datum, Note
|
||||
$config['CIS_GESAMTNOTE_NOTENIMPORT'] = false; // one LV-Note per row: Kennung, Note
|
||||
|
||||
// The Note column of an import accepts the key of lehre.tbl_note. true also accepts the short form
|
||||
// from lehre.tbl_note.anmerkung ('nb', 'ea', 'en') of the Excel Notenliste.
|
||||
$config['CIS_GESAMTNOTE_IMPORT_NOTENKUERZEL'] = false;
|
||||
|
||||
// The column order of an import. Allowed: 'kennung', 'datum', 'note'.
|
||||
$config['CIS_GESAMTNOTE_IMPORT_SPALTEN_NOTEN'] = ['kennung', 'note'];
|
||||
$config['CIS_GESAMTNOTE_IMPORT_SPALTEN_PRUEFUNG'] = ['kennung', 'datum', 'note'];
|
||||
|
||||
// The date format of an import: 'dd.MM.yyyy' or 'yyyy-MM-dd'.
|
||||
$config['CIS_GESAMTNOTE_IMPORT_DATUMSFORMAT'] = 'dd.MM.yyyy';
|
||||
|
||||
// An import stops at the first rejected row. false: it reports the row and writes the others.
|
||||
$config['CIS_GESAMTNOTE_IMPORT_ABBRUCH'] = false;
|
||||
|
||||
// The Pruefung columns of the table. The user can switch the layout; the browser keeps the choice.
|
||||
// 'antritt' one column per Antritt, the date is in the cell
|
||||
// 'datum' one column per Pruefung date
|
||||
$config['CIS_GESAMTNOTE_PRUEFUNGSSPALTEN'] = 'antritt';
|
||||
|
||||
// The badge in a Pruefung cell; {n} is the Antritt number.
|
||||
$config['CIS_GESAMTNOTE_ANTRITT_ZEICHEN'] = [
|
||||
'kommissionell' => '{n}-K',
|
||||
'kommissionell_ohne_antritt' => 'K',
|
||||
'antritt' => '{n}',
|
||||
'ohne_antritt' => '–'
|
||||
];
|
||||
@@ -64,6 +64,7 @@ $route['api/v1/system/[S|s]prache/(:any)'] = 'api/v1/system/sprache2/$1';
|
||||
$route['Cis/LvPlan/.*'] = 'Cis/LvPlan/index/$1';
|
||||
$route['Cis/MyLvPlan/.*'] = 'Cis/MyLvPlan/index/$1';
|
||||
$route['Cis/MyLv/.*'] = 'Cis/MyLv/index/$1';
|
||||
$route['Cis/Benotungstool/.*'] = 'Cis/Benotungstool/index/$1';
|
||||
$route['Cis/OtherLvPlan/.*'] = 'Cis/OtherLvPlan/index/$1';
|
||||
//Route for LV Plan Stg/Semester/Verband/Gruppe
|
||||
$route['Cis/StgOrgLvPlan/.*'] = 'Cis/StgOrgLvPlan/index/$1';
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
// the constructor needs the permissions before CodeIgniter can load a helper
|
||||
require_once APPPATH . 'helpers/hlp_benotungstool_helper.php';
|
||||
|
||||
/**
|
||||
* The page of the Benotungstool. The same permissions open it as the Noten API.
|
||||
*/
|
||||
class Benotungstool extends Auth_Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct([
|
||||
'index' => benotungstoolPermissions()
|
||||
]);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Benotungstool']);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -91,6 +91,8 @@ class CisMenu extends FHCAPI_Controller
|
||||
$doc->loadXML($menuItem->content);
|
||||
$urlElem = $doc->getElementsByTagName('url')->item(0);
|
||||
|
||||
$this->menuItemUrlTargetHelper($menuItem, $doc);
|
||||
|
||||
if (!$urlElem) {
|
||||
return '';
|
||||
}
|
||||
@@ -122,5 +124,18 @@ class CisMenu extends FHCAPI_Controller
|
||||
return $url;
|
||||
}
|
||||
|
||||
private function menuItemUrlTargetHelper($menuItem, $xmldoc)
|
||||
{
|
||||
if($menuItem->template_kurzbz === 'redirect')
|
||||
{
|
||||
$targetElem = $xmldoc->getElementsByTagName('target')->item(0);
|
||||
$target = ($targetElem) ? $targetElem->textContent : '';
|
||||
if(!in_array($target, array('_self', '_top', '_blank')))
|
||||
{
|
||||
$target = '_self';
|
||||
}
|
||||
$menuItem->target = $target;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,18 +18,9 @@
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
//require_once('../../../include/studiengang.class.php');
|
||||
//require_once('../../../include/student.class.php');
|
||||
//require_once('../../../include/datum.class.php');
|
||||
//require_once('../../../include/mail.class.php');
|
||||
//require_once('../../../include/benutzerberechtigung.class.php');
|
||||
//require_once('../../../include/phrasen.class.php');
|
||||
//require_once('../../../include/projektarbeit.class.php');
|
||||
//require_once('../../../include/projektbetreuer.class.php');
|
||||
|
||||
class Lehre extends FHCAPI_Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Object initialization
|
||||
*/
|
||||
@@ -41,37 +32,53 @@ class Lehre extends FHCAPI_Controller
|
||||
'Pruefungen' => self::PERM_LOGGED,
|
||||
'semesterAverageGrade' => self::PERM_LOGGED,
|
||||
]);
|
||||
|
||||
|
||||
$this->load->library('PhrasesLib');
|
||||
|
||||
$this->loadPhrases(
|
||||
array(
|
||||
'global',
|
||||
'ui',
|
||||
'abgabetool'
|
||||
)
|
||||
);
|
||||
|
||||
$this->load->helper('hlp_sancho_helper');
|
||||
|
||||
require_once(FHCPATH . 'include/studiengang.class.php');
|
||||
require_once(FHCPATH . 'include/student.class.php');
|
||||
require_once(FHCPATH . 'include/projektarbeit.class.php');
|
||||
require_once(FHCPATH . 'include/projektbetreuer.class.php');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
/**
|
||||
* constructs the emails of the groups from a lehrveranstaltung
|
||||
*/
|
||||
public function lvStudentenMail()
|
||||
public function lvStudentenMail()
|
||||
{
|
||||
$lehreinheit_id = $this->input->get("lehreinheit_id",TRUE);
|
||||
|
||||
// return early if the required parameter is missing
|
||||
if(!isset($lehreinheit_id))
|
||||
{
|
||||
$this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
$lehreinheit_id = $this->input->get("lehreinheit_id",TRUE);
|
||||
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
|
||||
$studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id);
|
||||
// return early if the required parameter is missing
|
||||
if(!isset($lehreinheit_id))
|
||||
{
|
||||
$this->terminateWithError('Missing required parameter', self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
$studentenMails = $this->getDataOrTerminateWithError($studentenMails);
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
|
||||
$studentenMails = $this->LehreinheitModel->getStudentenMail($lehreinheit_id);
|
||||
|
||||
$studentenMails = $this->getDataOrTerminateWithError($studentenMails);
|
||||
|
||||
//convert array of objects into array of strings
|
||||
$studentenMails = array_map(function($element){
|
||||
return $element->mail;
|
||||
}, $studentenMails);
|
||||
|
||||
$this->terminateWithSuccess($studentenMails);
|
||||
$this->terminateWithSuccess($studentenMails);
|
||||
}
|
||||
|
||||
public function LV($studiensemester_kurzbz, $lehrveranstaltung_id)
|
||||
@@ -81,13 +88,13 @@ class Lehre extends FHCAPI_Controller
|
||||
$result = $this->LehrveranstaltungModel->getLvsByStudentWithGrades(getAuthUID(), $studiensemester_kurzbz, getUserLanguage(), $lehrveranstaltung_id);
|
||||
|
||||
$result = current($this->getDataOrTerminateWithError($result));
|
||||
|
||||
|
||||
$this->terminateWithSuccess($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetches all Pruefungen of a student for a specific lehrveranstaltung
|
||||
* if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database
|
||||
* if the student passed the Pruefung on the first attempt, no information about the Pruefungen is stored in the database
|
||||
* @param mixed $lehrveranstaltung_id
|
||||
* @return void
|
||||
*/
|
||||
@@ -145,5 +152,5 @@ class Lehre extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess(['average_grade' => $averageGrade, 'weighted_average_grade' => $weightedAverageGrade]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -81,7 +81,7 @@ class Lehrveranstaltung extends FHCAPI_Controller
|
||||
{
|
||||
$studiengang_kz = $this->getStudiengangKz($stg_kz);
|
||||
|
||||
if (is_null($studiengang_kz) || !preg_match("/^-?[1-9][0-9]*$/", (string)$studiengang_kz))
|
||||
if (is_null($studiengang_kz) || !preg_match("/^(-?[1-9][0-9]*|0)$/", (string)$studiengang_kz))
|
||||
$this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$verband = null;
|
||||
|
||||
@@ -114,6 +114,7 @@ class LvPlan extends FHCAPI_Controller
|
||||
|
||||
// fetching lvplan events
|
||||
$result = $this->stundenplanlib->getEventsUser($start_date, $end_date, $uid);
|
||||
|
||||
$lvplanEvents = $this->getDataOrTerminateWithError($result);
|
||||
|
||||
// fetching moodle events
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -167,7 +167,9 @@ class Studium extends FHCAPI_Controller
|
||||
if($aktuelles_studienplan){
|
||||
$lehrveranstaltungen = $this->computeStudienplanLehrveranstaltungen($aktuelles_studienplan->studienplan_id, $aktuelles_semester);
|
||||
foreach($lehrveranstaltungen as $lehrv){
|
||||
foreach($lehrv->lehrveranstaltungen as $lv){
|
||||
// a lehrveranstaltung without a modul has no children and gets its lektoren directly
|
||||
$lvs = isset($lehrv->lehrveranstaltungen) ? $lehrv->lehrveranstaltungen : [$lehrv];
|
||||
foreach($lvs as $lv){
|
||||
$lvLektoren =$this->computeLektorenFromLehrveranstaltung($lv->lehrveranstaltung_id,$aktuelles_semester, $aktuelles_studiengang->studiengang_kz, $aktuelles_studiensemester->studiensemester_kurzbz);
|
||||
$lv->lektoren = $lvLektoren;
|
||||
}
|
||||
@@ -286,6 +288,7 @@ SELECT tbl_lehrveranstaltung.*,
|
||||
$lehrveranstaltungen = $this->LehrveranstaltungModel->execReadOnlyQuery($query,[$studienplan_id, $semester]);
|
||||
|
||||
$lehrveranstaltungen = $this->getDataOrTerminateWithError($lehrveranstaltungen);
|
||||
|
||||
usort($lehrveranstaltungen, function($a, $b){
|
||||
if($a->lehrtyp_kurzbz == "modul"){
|
||||
return -1;
|
||||
@@ -302,12 +305,17 @@ SELECT tbl_lehrveranstaltung.*,
|
||||
}
|
||||
else{
|
||||
$parent =array_filter($carry, function($item)use($lehrv){
|
||||
return $item->studienplan_lehrveranstaltung_id == $lehrv->studienplan_lehrveranstaltung_id_parent;
|
||||
return isset($item->lehrveranstaltungen)
|
||||
&& $item->studienplan_lehrveranstaltung_id == $lehrv->studienplan_lehrveranstaltung_id_parent;
|
||||
});
|
||||
$parent = current($parent);
|
||||
if($parent){
|
||||
$parent->lehrveranstaltungen[] = $lehrv;
|
||||
}
|
||||
else{
|
||||
// lehrveranstaltung without a modul: keep it on the top level
|
||||
array_push($carry, $lehrv);
|
||||
}
|
||||
}
|
||||
return $carry;
|
||||
}, []);
|
||||
|
||||
@@ -41,6 +41,9 @@ class Grades extends FHCAPI_Controller
|
||||
|
||||
// Load Libraries
|
||||
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
|
||||
$this->load->library('PruefungsverlaufLib', null, 'VerlaufLib');
|
||||
|
||||
$this->load->config('noten');
|
||||
|
||||
// Load Phrases
|
||||
$this->loadPhrases([
|
||||
@@ -355,23 +358,24 @@ class Grades extends FHCAPI_Controller
|
||||
$data['lehrveranstaltung_id'] = $lehrveranstaltung_id;
|
||||
$data['student_uid'] = $student_uid;
|
||||
$data['studiensemester_kurzbz'] = $studiensemester_kurzbz;
|
||||
|
||||
$this->ZeugnisnoteModel->insert($data);
|
||||
|
||||
if (defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN')
|
||||
&& FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN) {
|
||||
$result = $this->addTestsForGrade(
|
||||
$studiensemester_kurzbz,
|
||||
$student_uid,
|
||||
$lehrveranstaltung_id,
|
||||
$teacherGrade->note,
|
||||
$teacherGrade->punkte
|
||||
);
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
}
|
||||
$this->ZeugnisnoteModel->insert($data);
|
||||
}
|
||||
|
||||
// Der erste Antritt wird bereits bei der Übernahme als eigene Prüfung angelegt, damit der
|
||||
// Prüfungsverlauf von Anfang an vollständig ist und das Benotungstool ihn nicht erst beim
|
||||
// Anlegen einer Wiederholung nachtragen muss. Läuft bewusst in BEIDEN Zweigen (auch beim
|
||||
// Überschreiben einer bestehenden Zeugnisnote) und ist idempotent.
|
||||
if ($this->config->item('CIS_GESAMTNOTE_ERSTANTRITT_BEI_UEBERNAHME')) {
|
||||
$result = $this->addErstantrittForGrade(
|
||||
$studiensemester_kurzbz,
|
||||
$student_uid,
|
||||
$lehrveranstaltung_id,
|
||||
$teacherGrade
|
||||
);
|
||||
$this->getDataOrTerminateWithError($result);
|
||||
}
|
||||
|
||||
|
||||
$this->terminateWithSuccess(true);
|
||||
}
|
||||
|
||||
@@ -491,20 +495,32 @@ class Grades extends FHCAPI_Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that adds tests for a student
|
||||
* (Entries in lehre.tbl_pruefung)
|
||||
* Legt bei der Notenübernahme den ersten Prüfungsantritt als eigenen Datensatz an
|
||||
* (Eintrag in lehre.tbl_pruefung).
|
||||
*
|
||||
* @param string $studiensemester_kurzbz
|
||||
* @param string $student_uid
|
||||
* @param integer $lehrveranstaltung_id
|
||||
* @param integer $note
|
||||
* @param numeric $punkte
|
||||
* Idempotent: existiert für den Studenten in dieser LV bereits ein Termin, passiert nichts -
|
||||
* die Übernahme darf beliebig oft laufen, ohne den Verlauf zu verfälschen.
|
||||
*
|
||||
* Datiert auf das Freigabedatum der LV-Note: das ist der Zeitpunkt, zu dem die
|
||||
* Leistungsfeststellung verbindlich wurde. Das Benotungsdatum ändert sich bei jeder Korrektur,
|
||||
* der Übernahmezeitpunkt ist reine Verwaltungsarbeit - beide taugen nicht als Termindatum.
|
||||
*
|
||||
* @param string $studiensemester_kurzbz
|
||||
* @param string $student_uid
|
||||
* @param integer $lehrveranstaltung_id
|
||||
* @param stdClass $teacherGrade die übernommene LV-Gesamtnote
|
||||
*
|
||||
* @return stdClass
|
||||
*/
|
||||
protected function addTestsForGrade($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $note, $punkte)
|
||||
protected function addErstantrittForGrade($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id, $teacherGrade)
|
||||
{
|
||||
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
|
||||
$this->load->model('education/LePruefung_model', 'LePruefungModel');
|
||||
|
||||
// bereits ein Termin vorhanden -> der Verlauf beginnt schon, nichts nachzutragen
|
||||
$vorhanden = $this->VerlaufLib->getPruefungen($student_uid, $lehrveranstaltung_id, $studiensemester_kurzbz);
|
||||
if (count($vorhanden) > 0)
|
||||
return success(null);
|
||||
|
||||
// Get Lehreinheit
|
||||
$result = $this->LehrveranstaltungModel->getLeByStudent($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id);
|
||||
@@ -515,19 +531,24 @@ class Grades extends FHCAPI_Controller
|
||||
return error($this->p->t("stv", "grades_error_lehreinheit_id"));
|
||||
$le = current(getData($result));
|
||||
|
||||
$datum = $teacherGrade->freigabedatum ?: ($teacherGrade->benotungsdatum ?: date('Y-m-d'));
|
||||
$now = date('Y-m-d H:i:s');
|
||||
|
||||
// Prepare
|
||||
$this->load->model('education/LePruefung_model', 'LePruefungModel');
|
||||
$data = [
|
||||
"student_uid" => $student_uid,
|
||||
"lehreinheit_id" => $le->lehreinheit_id,
|
||||
"datum" => date('Y-m-d'),
|
||||
"pruefungstyp_kurzbz" => "Termin1",
|
||||
"note" => $note
|
||||
"mitarbeiter_uid" => $teacherGrade->mitarbeiter_uid,
|
||||
"datum" => $datum,
|
||||
"pruefungstyp_kurzbz" => $this->VerlaufLib->legacyTypFuerAntritt(1),
|
||||
"note" => $teacherGrade->note,
|
||||
"insertamum" => $now,
|
||||
"insertvon" => getAuthUID()
|
||||
];
|
||||
|
||||
if (defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE)
|
||||
$data["punkte"] = $punkte;
|
||||
|
||||
$data["punkte"] = $teacherGrade->punkte;
|
||||
|
||||
// Get Anwesenheit
|
||||
$this->load->model('education/Anwesenheit_model', 'AnwesenheitModel');
|
||||
$result = $this->AnwesenheitModel->loadAnwesenheitStudiensemester($studiensemester_kurzbz, $student_uid, $lehrveranstaltung_id);
|
||||
@@ -535,7 +556,8 @@ class Grades extends FHCAPI_Controller
|
||||
return $result;
|
||||
$anwesenheit = getData($result);
|
||||
|
||||
if ($anwesenheit && (float)current($anwesenheit)->prozent < FAS_ANWESENHEIT_ROT) {
|
||||
if (defined('FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN') && FAS_PRUEFUNG_BEI_NOTENEINGABE_ANLEGEN
|
||||
&& $anwesenheit && (float)current($anwesenheit)->prozent < FAS_ANWESENHEIT_ROT) {
|
||||
// Get Anwesenheitsbefreiung
|
||||
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
|
||||
$result = $this->BenutzerfunktionModel->getBenutzerFunktionByUidInStdsem($student_uid, $studiensemester_kurzbz, 'awbefreit');
|
||||
@@ -545,7 +567,10 @@ class Grades extends FHCAPI_Controller
|
||||
|
||||
$anwesenheitsbefreit = hasData($result);
|
||||
|
||||
// Wenn nicht Anwesenheitsbefreit und Anwesenheit unter einem bestimmten Prozentsatz fällt dann wird ein Pruefungsantritt abgezogen
|
||||
// Bei zu geringer Anwesenheit ohne Befreiung wird ein zusätzlicher Termin
|
||||
// 'Nicht beurteilt' vor dem eigentlichen Antritt festgehalten. ACHTUNG: diese Note
|
||||
// zählt nicht mehr als Antritt (NOTEN_OHNE_ANTRITT_BEZEICHNUNGEN) - der frühere
|
||||
// "Antritt abziehen"-Effekt entfällt damit, der Eintrag ist reine Dokumentation.
|
||||
if (!$anwesenheitsbefreit) {
|
||||
$data2 = $data;
|
||||
$data2["note"] = 7;
|
||||
@@ -556,8 +581,6 @@ class Grades extends FHCAPI_Controller
|
||||
|
||||
if (isError($result))
|
||||
return $result;
|
||||
|
||||
$data["pruefungstyp_kurzbz"] = "Termin2";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -370,6 +370,7 @@ class LvTermine extends FHCAPI_Controller
|
||||
$result->semester = $item->semester;
|
||||
$result->verband = $item->verband;
|
||||
$result->gruppe = $item->gruppe;
|
||||
$result->studiensemester_kurzbz = $item->studiensemester_kurzbz;
|
||||
return $result;
|
||||
},
|
||||
$lehrverband_query_result));
|
||||
|
||||
@@ -42,6 +42,8 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
$this->load->model('education/Note_model', 'NoteModel');
|
||||
$this->load->model('education/Projektbetreuer_model', 'BetreuerModel');
|
||||
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
|
||||
$this->load->model('crm/Student_model', 'StudentModel');
|
||||
$this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel');
|
||||
|
||||
// load libraries
|
||||
$this->load->library('PermissionLib');
|
||||
@@ -100,16 +102,16 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
private function fetchProjektarbeitById($projektarbeit_id) {
|
||||
$this->ProjektarbeitModel->resetQuery();
|
||||
$this->ProjektarbeitModel->addSelect(
|
||||
'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, lehrveranstaltung_id, lehreinheit_id,
|
||||
firma_id, beginn, ende, gesperrtbis, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name'
|
||||
'lehre.tbl_projektarbeit.projektarbeit_id, titel, titel_english, themenbereich, projekttyp_kurzbz, lehrveranstaltung_id, lehreinheit_id,
|
||||
tbl_projektarbeit.studiensemester_kurzbz, firma_id, beginn, ende, gesperrtbis, note, final, freigegeben, tbl_projektarbeit.anmerkung, fa.name AS firma_name'
|
||||
);
|
||||
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehreinheit le', 'lehreinheit_id');
|
||||
$this->ProjektarbeitModel->addJoin('lehre.tbl_lehrveranstaltung lv', 'lehrveranstaltung_id');
|
||||
$this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT');
|
||||
|
||||
|
||||
return $this->ProjektarbeitModel->loadWhere(
|
||||
array('projektarbeit_id' => $projektarbeit_id)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -246,14 +248,38 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
$additional_lehrveranstaltung_id = $this->input->get('additional_lehrveranstaltung_id');
|
||||
|
||||
if (!isset($student_uid)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
|
||||
if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemster missing', self::ERROR_TYPE_GENERAL);
|
||||
if (!isset($studiensemester_kurzbz)) $this->terminateWithError('Studiensemester missing', self::ERROR_TYPE_GENERAL);
|
||||
|
||||
// get Lvs
|
||||
// get prestudent_id from student model
|
||||
$studentRes = $this->StudentModel->load(['student_uid' => $student_uid]);
|
||||
if(hasData($studentRes)) {
|
||||
$student = getData($studentRes);
|
||||
} else {
|
||||
$this->terminateWithError($studentRes, self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
// to get prestudent_status history
|
||||
$historyRes = $this->PrestudentstatusModel->getHistoryPrestudent($student[0]->prestudent_id);
|
||||
if(hasData($historyRes)) {
|
||||
$history = getData($historyRes);
|
||||
} else {
|
||||
$this->terminateWithError($historyRes, self::ERROR_TYPE_GENERAL);
|
||||
}
|
||||
|
||||
// query for every lva of a studiengang that has projektarbeit flag true
|
||||
$lvsResult = $this->LehrveranstaltungModel->getLvsForProjektarbeit($student_uid, $studiengang_kz, $additional_lehrveranstaltung_id);
|
||||
|
||||
if (isError($lvsResult)) return $this->terminateWithError($lvsResult, self::ERROR_TYPE_GENERAL);
|
||||
|
||||
$lvs = hasData($lvsResult) ? getData($lvsResult) : [];
|
||||
|
||||
$lvsIDs = array_column($lvs, 'lehrveranstaltung_id');
|
||||
|
||||
// get current studienplan_id from status history to find out which lva options are actually assigned to the students studienplan
|
||||
// important so the projektarbeit has the correct lva assigned to be able to find and print the thesis title on the degree documents!
|
||||
$currentStatus = $history[0];
|
||||
$lvByStudienPlanRes = $this->LehrveranstaltungModel->getLvsByStudienplanByLvaIDs($currentStatus->studienplan_id, $lvsIDs);
|
||||
if(hasData($lvByStudienPlanRes)) {
|
||||
$lvs = getData($lvByStudienPlanRes);
|
||||
}
|
||||
|
||||
foreach ($lvs as $lv)
|
||||
{
|
||||
@@ -320,11 +346,18 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|is_natural', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']),
|
||||
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'is_natural', [
|
||||
'is_natural' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('lehrveranstaltung_id', 'Lehrveranstaltung', 'required', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehrveranstaltung'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required', [
|
||||
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Studiensemester'])
|
||||
]);
|
||||
|
||||
$this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [
|
||||
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Beginn'])
|
||||
]);
|
||||
@@ -354,6 +387,8 @@ class Projektarbeit extends FHCAPI_Controller
|
||||
'projekttyp_kurzbz' => $formData['projekttyp_kurzbz'],
|
||||
'firma_id' => $formData['firma_id'] ?? null,
|
||||
'lehreinheit_id' => $formData['lehreinheit_id'],
|
||||
'lehrveranstaltung_id' => $formData['lehrveranstaltung_id'],
|
||||
'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
|
||||
'beginn' => isset($formData['beginn']) && !isEmptyString($formData['beginn']) ? $formData['beginn'] : null,
|
||||
'ende' => isset($formData['ende']) && !isEmptyString($formData['ende']) ? $formData['ende'] : null,
|
||||
'note' => $formData['note'] ?? null,
|
||||
|
||||
@@ -108,6 +108,7 @@ class Students extends FHCAPI_Controller
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
]);
|
||||
|
||||
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
|
||||
|
||||
$this->studentlistlib->addJoin(
|
||||
"(
|
||||
@@ -153,7 +154,8 @@ class Students extends FHCAPI_Controller
|
||||
$this->addMeta('ci_params', [
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
]);
|
||||
|
||||
|
||||
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
|
||||
|
||||
$this->studentlistlib->addJoin(
|
||||
"(
|
||||
@@ -213,6 +215,7 @@ class Students extends FHCAPI_Controller
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
]);
|
||||
|
||||
$studiensemester_kurzbz = $this->getStudiensemesterKurzbz($studiensemester_kurzbz);
|
||||
|
||||
$this->studentlistlib->addJoin(
|
||||
"(
|
||||
|
||||
@@ -803,7 +803,7 @@ class ReihungstestJob extends JOB_Controller
|
||||
{
|
||||
if (!isset($studiensemester) || isEmptyString($studiensemester))
|
||||
{
|
||||
$this->logError("Studiensemster not passed as parameter");
|
||||
$this->logError("Studiensemester not passed as parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ class InfoCenter extends Auth_Controller
|
||||
const PREV_FILTER_ID = 'prev_filter_id';
|
||||
const KEEP_TABLESORTER_FILTER = 'keepTsFilter';
|
||||
|
||||
const ONBOARDING_INSERTVON = 'onboarding';
|
||||
const ONBOARDING_KENNZEICHENTYP = 'eobRegistrierungsId';
|
||||
|
||||
private $_uid; // contains the UID of the logged user
|
||||
|
||||
// Used to log with PersonLogLib
|
||||
@@ -175,6 +178,7 @@ class InfoCenter extends Auth_Controller
|
||||
$this->load->model('person/Kontakt_model', 'KontaktModel');
|
||||
$this->load->model('person/Geschlecht_model', 'GeschlechtModel');
|
||||
$this->load->model('person/adresse_model', 'AdresseModel');
|
||||
$this->load->model('person/Kennzeichen_model', 'KennzeichenModel');
|
||||
|
||||
// Loads libraries
|
||||
$this->load->library('PersonLogLib');
|
||||
@@ -1452,6 +1456,100 @@ class InfoCenter extends Auth_Controller
|
||||
|
||||
$this->outputJsonSuccess("Done!");
|
||||
}
|
||||
|
||||
public function getAbsageData()
|
||||
{
|
||||
$stg_typ = $this->getStudienArtBerechtigung(['b', 'm']);
|
||||
|
||||
if (!is_null($stg_typ))
|
||||
{
|
||||
$statusgruende = $this->StatusgrundModel->getStatus(self::ABGEWIESENERSTATUS, true)->retval;
|
||||
$studienSemester = $this->variablelib->getVar('infocenter_studiensemester');
|
||||
$studiengaenge = $this->StudiengangModel->getStudiengaengeWithOrgForm(array_column($stg_typ, 'typ'), $studienSemester);
|
||||
|
||||
$data = array (
|
||||
'statusgruende' => $statusgruende,
|
||||
'studiengaenge' => $studiengaenge->retval
|
||||
);
|
||||
|
||||
$this->outputJsonSuccess($data);
|
||||
}
|
||||
else
|
||||
$this->outputJsonSuccess(null);
|
||||
}
|
||||
|
||||
public function getStudienArtBerechtigung($typ = null)
|
||||
{
|
||||
$studiengang_kz_all = $this->permissionlib->getSTG_isEntitledFor('infocenter');
|
||||
$stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, $typ);
|
||||
return getData($stg_typ);
|
||||
}
|
||||
|
||||
public function getStudienartData()
|
||||
{
|
||||
$this->outputJsonSuccess($this->getStudienArtBerechtigung(['b', 'm', 'l']));
|
||||
}
|
||||
|
||||
public function saveAbsageForAll()
|
||||
{
|
||||
$statusgrund = $this->input->post('statusgrund');
|
||||
$studiengang = $this->input->post('studiengang');
|
||||
$abgeschickt = $this->input->post('abgeschickt');
|
||||
$personen = $this->input->post('personen');
|
||||
$studienSemester = $this->variablelib->getVar('infocenter_studiensemester');
|
||||
|
||||
if ($statusgrund === 'null' || $studiengang === 'null' || $abgeschickt === 'null' || empty($personen))
|
||||
$this->terminateWithJsonError("Bitte füllen Sie alle Felder aus");
|
||||
|
||||
if ($studiengang === 'all' && $abgeschickt === 'all')
|
||||
{
|
||||
foreach($personen as $person)
|
||||
{
|
||||
$prestudenten = $this->PrestudentModel->getByPersonWithoutLehrgang($person, $studienSemester);
|
||||
|
||||
if (!hasData($prestudenten))
|
||||
continue;
|
||||
|
||||
$prestudentenData = getData($prestudenten);
|
||||
|
||||
foreach ($prestudentenData as $prestudent)
|
||||
{
|
||||
$this->saveAbsage($prestudent->prestudent_id, $statusgrund);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
|
||||
$this->StudienplanModel->addSelect('1');
|
||||
$this->StudienplanModel->addJoin('lehre.tbl_studienordnung so', 'studienordnung_id');
|
||||
$escaped = $this->StudienplanModel->db->escape(strtoupper($studiengang));
|
||||
$this->StudienplanModel->db->where("UPPER(so.studiengangkurzbzlang || ':' || tbl_studienplan.orgform_kurzbz) = $escaped");
|
||||
$this->StudienplanModel->addLimit(1);
|
||||
$studiengangResult = $this->StudienplanModel->load();
|
||||
|
||||
if (hasData($studiengangResult))
|
||||
{
|
||||
foreach($personen as $person)
|
||||
{
|
||||
$prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $abgeschickt === 'all');
|
||||
|
||||
if (!hasData($prestudent))
|
||||
continue;
|
||||
|
||||
$prestudentData = getData($prestudent);
|
||||
$this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund);
|
||||
}
|
||||
}
|
||||
else
|
||||
$this->terminateWithJsonError("Falschen Studiengang übergeben!");
|
||||
|
||||
}
|
||||
|
||||
$this->outputJsonSuccess("Success");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------
|
||||
// Private methods
|
||||
|
||||
@@ -1946,6 +2044,17 @@ class InfoCenter extends Auth_Controller
|
||||
show_error(getError($user_person));
|
||||
}
|
||||
|
||||
// add info about first electronig onboarding login
|
||||
$this->KennzeichenModel->addSelect('insertamum');
|
||||
$onboarding_first_login = $this->KennzeichenModel->loadWhere(
|
||||
array('person_id' => $person_id, 'kennzeichentyp_kurzbz' => self::ONBOARDING_KENNZEICHENTYP)
|
||||
);
|
||||
|
||||
if (isError($onboarding_first_login))
|
||||
{
|
||||
show_error(getError($onboarding_first_login));
|
||||
}
|
||||
|
||||
$data = array (
|
||||
'lockedby' => $lockedby,
|
||||
'lockedbyother' => $lockedbyother,
|
||||
@@ -1955,7 +2064,9 @@ class InfoCenter extends Auth_Controller
|
||||
'messages' => $messages->retval,
|
||||
'logs' => $logs,
|
||||
'notizen' => $notizen->retval,
|
||||
'notizenbewerbung' => $notizen_bewerbung->retval
|
||||
'notizenbewerbung' => $notizen_bewerbung->retval,
|
||||
'created_by_onboarding' => $stammdaten->retval->insertvon == self::ONBOARDING_INSERTVON,
|
||||
'onboarding_first_login' => hasData($onboarding_first_login) ? getData($onboarding_first_login)[0]->insertamum : null
|
||||
);
|
||||
|
||||
return $data;
|
||||
@@ -2375,97 +2486,4 @@ class InfoCenter extends Auth_Controller
|
||||
$this->loglib->logError('Studiengang has no mail for sending Freigabe mail');
|
||||
}
|
||||
}
|
||||
|
||||
public function getAbsageData()
|
||||
{
|
||||
$stg_typ = $this->getStudienArtBerechtigung(['b', 'm']);
|
||||
|
||||
if (!is_null($stg_typ))
|
||||
{
|
||||
$statusgruende = $this->StatusgrundModel->getStatus(self::ABGEWIESENERSTATUS, true)->retval;
|
||||
$studienSemester = $this->variablelib->getVar('infocenter_studiensemester');
|
||||
$studiengaenge = $this->StudiengangModel->getStudiengaengeWithOrgForm(array_column($stg_typ, 'typ'), $studienSemester);
|
||||
|
||||
$data = array (
|
||||
'statusgruende' => $statusgruende,
|
||||
'studiengaenge' => $studiengaenge->retval
|
||||
);
|
||||
|
||||
$this->outputJsonSuccess($data);
|
||||
}
|
||||
else
|
||||
$this->outputJsonSuccess(null);
|
||||
}
|
||||
|
||||
public function getStudienArtBerechtigung($typ = null)
|
||||
{
|
||||
$studiengang_kz_all = $this->permissionlib->getSTG_isEntitledFor('infocenter');
|
||||
$stg_typ = $this->StudiengangModel->getStudiengangTyp($studiengang_kz_all, $typ);
|
||||
return getData($stg_typ);
|
||||
}
|
||||
|
||||
public function getStudienartData()
|
||||
{
|
||||
$this->outputJsonSuccess($this->getStudienArtBerechtigung(['b', 'm', 'l']));
|
||||
}
|
||||
|
||||
public function saveAbsageForAll()
|
||||
{
|
||||
$statusgrund = $this->input->post('statusgrund');
|
||||
$studiengang = $this->input->post('studiengang');
|
||||
$abgeschickt = $this->input->post('abgeschickt');
|
||||
$personen = $this->input->post('personen');
|
||||
$studienSemester = $this->variablelib->getVar('infocenter_studiensemester');
|
||||
|
||||
if ($statusgrund === 'null' || $studiengang === 'null' || $abgeschickt === 'null' || empty($personen))
|
||||
$this->terminateWithJsonError("Bitte füllen Sie alle Felder aus");
|
||||
|
||||
if ($studiengang === 'all' && $abgeschickt === 'all')
|
||||
{
|
||||
foreach($personen as $person)
|
||||
{
|
||||
$prestudenten = $this->PrestudentModel->getByPersonWithoutLehrgang($person, $studienSemester);
|
||||
|
||||
if (!hasData($prestudenten))
|
||||
continue;
|
||||
|
||||
$prestudentenData = getData($prestudenten);
|
||||
|
||||
foreach ($prestudentenData as $prestudent)
|
||||
{
|
||||
$this->saveAbsage($prestudent->prestudent_id, $statusgrund);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->load->model('organisation/Studienplan_model', 'StudienplanModel');
|
||||
|
||||
$this->StudienplanModel->addSelect('1');
|
||||
$this->StudienplanModel->addJoin('lehre.tbl_studienordnung so', 'studienordnung_id');
|
||||
$escaped = $this->StudienplanModel->db->escape(strtoupper($studiengang));
|
||||
$this->StudienplanModel->db->where("UPPER(so.studiengangkurzbzlang || ':' || tbl_studienplan.orgform_kurzbz) = $escaped");
|
||||
$this->StudienplanModel->addLimit(1);
|
||||
$studiengangResult = $this->StudienplanModel->load();
|
||||
|
||||
if (hasData($studiengangResult))
|
||||
{
|
||||
foreach($personen as $person)
|
||||
{
|
||||
$prestudent = $this->PrestudentModel->getPrestudentByStudiengangAndPerson($studiengang, $person, $studienSemester, $abgeschickt, $abgeschickt === 'all');
|
||||
|
||||
if (!hasData($prestudent))
|
||||
continue;
|
||||
|
||||
$prestudentData = getData($prestudent);
|
||||
$this->saveAbsage($prestudentData[0]->prestudent_id, $statusgrund);
|
||||
}
|
||||
}
|
||||
else
|
||||
$this->terminateWithJsonError("Falschen Studiengang übergeben!");
|
||||
|
||||
}
|
||||
|
||||
$this->outputJsonSuccess("Success");
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,8 @@ class Rueckstellung extends Auth_Controller
|
||||
private $_ci; // Code igniter instance
|
||||
private $_uid;
|
||||
|
||||
const ZGV_UEBERPRUEFUNG_MAIL_VORLAGE = 'ZGVUEP';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(
|
||||
@@ -23,6 +25,7 @@ class Rueckstellung extends Auth_Controller
|
||||
$this->load->model('crm/RueckstellungStatus_model', 'RueckstellungStatusModel');
|
||||
$this->load->model('person/Person_model', 'PersonModel');
|
||||
$this->load->library('PersonLogLib');
|
||||
$this->load->library('MessageLib');
|
||||
|
||||
$this->_setAuthUID(); // sets property uid
|
||||
|
||||
@@ -78,6 +81,8 @@ class Rueckstellung extends Auth_Controller
|
||||
|
||||
$this->_log($person_id, $status_kurzbz);
|
||||
|
||||
if ($status_kurzbz === 'onhold_zgv')
|
||||
$this->sendRueckstellungMessage($person_id);
|
||||
$this->outputJson($result);
|
||||
}
|
||||
|
||||
@@ -104,6 +109,10 @@ class Rueckstellung extends Auth_Controller
|
||||
if (isError($result))
|
||||
$this->terminateWithJsonError(getError($result));
|
||||
$this->_log($person, $status_kurzbz);
|
||||
|
||||
if ($status_kurzbz === 'onhold_zgv')
|
||||
$this->sendRueckstellungMessage($person);
|
||||
|
||||
}
|
||||
$this->outputJsonSuccess("Erfolgreich gespeichert!");
|
||||
}
|
||||
@@ -160,4 +169,26 @@ class Rueckstellung extends Auth_Controller
|
||||
$this->_uid
|
||||
);
|
||||
}
|
||||
|
||||
private function sendRueckstellungMessage($person_id)
|
||||
{
|
||||
$person = $this->_ci->PersonModel->load($person_id);
|
||||
|
||||
if (hasData($person))
|
||||
{
|
||||
$person = getData($person)[0];
|
||||
|
||||
return $this->messagelib->sendMessageUserTemplate(
|
||||
$person_id,
|
||||
self::ZGV_UEBERPRUEFUNG_MAIL_VORLAGE,
|
||||
array(
|
||||
'anrede' => $person->anrede,
|
||||
'nachname' => $person->nachname
|
||||
),
|
||||
null,
|
||||
getAuthPersonId(),
|
||||
'infocenter'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* The permissions that open the Benotungstool: the keys of CIS_GESAMTNOTE_ROLLENMATRIX. The page and
|
||||
* the Noten API read this one list. A constructor needs it before CodeIgniter can load a configuration,
|
||||
* so this reads the file itself.
|
||||
*
|
||||
* @return array one 'permission:rw' entry per key
|
||||
*/
|
||||
function benotungstoolPermissions()
|
||||
{
|
||||
$config = array();
|
||||
include APPPATH . 'config/noten.php';
|
||||
|
||||
$permissions = array();
|
||||
foreach (array_keys($config['CIS_GESAMTNOTE_ROLLENMATRIX']) as $permission) $permissions[] = $permission . ':rw';
|
||||
|
||||
return $permissions;
|
||||
}
|
||||
@@ -741,7 +741,7 @@ class AnrechnungLib
|
||||
$fullname = hasData($result) ? $result->retval[0]->vorname. $result->retval[0]->nachname : '';
|
||||
|
||||
// Return filename
|
||||
return 'Anrechnungsantrag'. $orgform_kurzbz .'_LV-'. $lehrveranstaltung_id. '_'. $fullname;
|
||||
return 'Anrechnungsantrag'. $orgform_kurzbz .'_LV-'. $lehrveranstaltung_id. '_'. $fullname . '.pdf';
|
||||
}
|
||||
|
||||
public function LVhasLector($anrechnung_id)
|
||||
|
||||
@@ -0,0 +1,765 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (C) 2026 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
if (! defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
/**
|
||||
* The Verlauf of one student in one LV: the order of the Pruefungen, the Antritte and the limits.
|
||||
*
|
||||
* This class holds the rules of the Antritt chain. The controller holds access, Frist and Freigabe.
|
||||
* The client only reads the Verlauf.
|
||||
*
|
||||
* The StV calls getPruefungen() and legacyTypFuerAntritt(). Keep their names and signatures.
|
||||
*/
|
||||
class PruefungsverlaufLib
|
||||
{
|
||||
/** Antritt 1. Without a Pruefung the LV-Note itself is Antritt 1. */
|
||||
const ROLE_ERSTANTRITT = 'erstantritt';
|
||||
|
||||
/** Each Antritt after the first one. */
|
||||
const ROLE_PRUEFUNG = 'pruefung';
|
||||
|
||||
/** The Antritt before a commission (CIS_GESAMTNOTE_KOMMISSIONELL_AB_ANTRITT). */
|
||||
const ROLE_KOMMISSIONELL = 'kommissionell';
|
||||
|
||||
/** upsertErstantritt(): an existing Antritt 1 keeps its date. */
|
||||
const KEEP_DATUM = false;
|
||||
|
||||
/** upsertErstantritt(): an existing Antritt 1 takes the new date. */
|
||||
const SET_DATUM = true;
|
||||
|
||||
private $_ci;
|
||||
private $_noteCache = [];
|
||||
private $_specialNotes = null;
|
||||
private $_types = null;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->_ci =& get_instance();
|
||||
$this->_ci->load->model('education/LePruefung_model', 'LePruefungModel');
|
||||
$this->_ci->load->model('education/Note_model', 'NoteModel');
|
||||
$this->_ci->load->model('education/Pruefungstyp_model', 'PruefungstypModel');
|
||||
$this->_ci->load->config('noten');
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Verlauf. Each Pruefung gets position, is_antritt, antritt_nr, kommissionell and
|
||||
* note_locked. The rules and the client read this one object.
|
||||
*
|
||||
* @param array $pruefungen the Pruefungen of one student in one LV
|
||||
* @param mixed|null $lvNote Antritt 1 while no Pruefung is an Antritt
|
||||
* @param mixed|null $zeugnisnote an Anrechnung blocks every Pruefung
|
||||
* @return stdClass
|
||||
*/
|
||||
public function buildVerlauf($pruefungen, $lvNote, $zeugnisnote)
|
||||
{
|
||||
$pruefungen = $this->sortPruefungen($pruefungen);
|
||||
|
||||
// a later Pruefung locks the Note of an earlier one; its date stays editable
|
||||
$lockedByLater = $this->configBool('CIS_GESAMTNOTE_NOTE_SPERRE_BEI_SPAETERER_PRUEFUNG');
|
||||
|
||||
$antrittCount = 0;
|
||||
$terminal = false;
|
||||
$entries = [];
|
||||
|
||||
foreach ($pruefungen as $i => $pruefung) {
|
||||
$isAntritt = $this->isAntritt($pruefung->note, $pruefung->pruefungstyp_kurzbz);
|
||||
if ($isAntritt) $antrittCount++;
|
||||
|
||||
// A kommissionelle Pruefung closes the chain, also if its Note uses no Antritt.
|
||||
$kommissionell = $this->isKommissionell($pruefung->pruefungstyp_kurzbz);
|
||||
if ($kommissionell) $terminal = true;
|
||||
|
||||
$entry = clone $pruefung;
|
||||
$entry->position = $i + 1;
|
||||
$entry->is_antritt = $isAntritt;
|
||||
$entry->antritt_nr = $isAntritt ? $antrittCount : null;
|
||||
$entry->kommissionell = $kommissionell;
|
||||
$entry->note_locked = $lockedByLater && $i < count($pruefungen) - 1;
|
||||
$entries[] = $entry;
|
||||
}
|
||||
|
||||
// without a Pruefung that is an Antritt, the LV-Note itself is Antritt 1
|
||||
$implicit = ($antrittCount === 0 && $lvNote !== null && $this->isAntritt($lvNote));
|
||||
if ($implicit) $antrittCount = 1;
|
||||
|
||||
// the deciding Note: the last Antritt, else the LV-Note
|
||||
$currentNote = null;
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry->is_antritt) $currentNote = $entry->note;
|
||||
}
|
||||
if ($currentNote === null && $implicit) $currentNote = $lvNote;
|
||||
|
||||
// a closing Note always ends the chain, any other positive Note only without Notenverbesserung
|
||||
$bestanden = $this->isClosingNote($currentNote)
|
||||
|| (!$this->allowsImprovement() && $this->isPositiveNote($currentNote));
|
||||
if ($bestanden) $terminal = true;
|
||||
|
||||
$verlauf = new stdClass();
|
||||
$verlauf->pruefungen = $entries;
|
||||
$verlauf->antrittCount = $antrittCount;
|
||||
$verlauf->maxAntritte = $this->getMaxAntritte();
|
||||
$verlauf->terminal = $terminal;
|
||||
// closed by a pass, not by the limit
|
||||
$verlauf->bestanden = $bestanden;
|
||||
// the row stays visible, but nobody can enter anything
|
||||
$verlauf->angerechnet = $this->isAnrechnungNote($zeugnisnote);
|
||||
$verlauf->implicitErstantritt = $implicit;
|
||||
$verlauf->canAdd = !$terminal && !$verlauf->angerechnet && $antrittCount < $verlauf->maxAntritte;
|
||||
|
||||
// a second Pruefung, or one Pruefung that is not Antritt 1 (next to an implicit Antritt 1).
|
||||
// This is the only rule that reads the legacy Pruefungstyp back.
|
||||
$verlauf->hasRepeat = count($entries) > 1
|
||||
|| (count($entries) === 1 && $entries[0]->pruefungstyp_kurzbz !== $this->legacyTypFuerAntritt(1));
|
||||
|
||||
// The role follows from the position (§17 Abs 1), so the user interface offers no type.
|
||||
if (count($entries) === 0 && !$implicit) {
|
||||
$verlauf->nextRole = self::ROLE_ERSTANTRITT;
|
||||
} else {
|
||||
// a Pruefung exists: the next one is a repeat, also if no Pruefung is an Antritt yet
|
||||
$verlauf->nextRole = $this->roleForAntritt(max(2, $antrittCount + 1));
|
||||
}
|
||||
|
||||
// the next Antritt is kommissionell, and this tool may not create it
|
||||
$verlauf->kommPruefLocked = $verlauf->canAdd
|
||||
&& $verlauf->nextRole === self::ROLE_KOMMISSIONELL
|
||||
&& !$this->canCreateKommPruef();
|
||||
if ($verlauf->kommPruefLocked) $verlauf->canAdd = false;
|
||||
|
||||
$verlauf->earliestNewDay = $this->earliestNewDay($entries);
|
||||
$verlauf->notenAtLimit = $this->notenAtLimit($entries);
|
||||
|
||||
return $verlauf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed|null $lvNote see buildVerlauf
|
||||
* @param mixed|null $zeugnisnote see buildVerlauf
|
||||
* @return stdClass
|
||||
*/
|
||||
public function getVerlauf($student_uid, $lv_id, $sem_kurzbz, $lvNote, $zeugnisnote)
|
||||
{
|
||||
return $this->buildVerlauf($this->getPruefungen($student_uid, $lv_id, $sem_kurzbz), $lvNote, $zeugnisnote);
|
||||
}
|
||||
|
||||
/** All Pruefungen of one student in one LV, in the order of the Verlauf. The StV calls it. @return array */
|
||||
public function getPruefungen($student_uid, $lv_id, $sem_kurzbz)
|
||||
{
|
||||
$result = $this->_ci->LePruefungModel->getPruefungenByStudent($student_uid, $lv_id, $sem_kurzbz);
|
||||
if (isError($result) || !hasData($result)) return [];
|
||||
|
||||
return $this->sortPruefungen(getData($result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a NEW Antritt: A the limit, B the order of the dates, C the occurrence limit, D the gap.
|
||||
*
|
||||
* @param stdClass $verlauf from buildVerlauf
|
||||
* @return array|null [phraseKey, params] or null
|
||||
*/
|
||||
public function validateAdd($verlauf, $note, $datum)
|
||||
{
|
||||
if ($verlauf->angerechnet) return ['c4angerechnetKeinePruefung', []];
|
||||
if ($verlauf->kommPruefLocked) return ['kommPruefNichtErlaubt', []];
|
||||
|
||||
// A: Antritt 1 only writes the LV-Note down, so it needs no free Antritt
|
||||
if ($verlauf->nextRole !== self::ROLE_ERSTANTRITT && !$verlauf->canAdd) {
|
||||
if ($verlauf->bestanden) return ['pruefungNachBestandenerNote', []];
|
||||
|
||||
return ['maxAntritteReached', [$verlauf->maxAntritte]];
|
||||
}
|
||||
|
||||
// one Pruefung without a result per Verlauf; more of them break the order of the Antritte
|
||||
if ($this->isOpen($note) && $this->hasOpenPruefung($verlauf->pruefungen)) return ['pruefungOhneErgebnis', []];
|
||||
|
||||
// B: no Pruefung before an existing one
|
||||
$newDay = substr((string) $datum, 0, 10);
|
||||
if ($verlauf->earliestNewDay !== null && $newDay < $verlauf->earliestNewDay) return ['pruefungDatumBeforeExisting', []];
|
||||
|
||||
// C: for example one 'entschuldigt' only
|
||||
if ($this->exceedsNoteLimit($verlauf->pruefungen, $note)) return ['noteOccuranceLimitReached', []];
|
||||
|
||||
// D
|
||||
return $this->checkAntrittGap($verlauf, $newDay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a CHANGED Pruefung. The date must stay between its neighbours, and a later Pruefung locks
|
||||
* the Note.
|
||||
*
|
||||
* @param stdClass $verlauf from buildVerlauf
|
||||
* @return array|null [phraseKey, params] or null
|
||||
*/
|
||||
public function validateEdit($verlauf, $pruefung_id, $note, $datum)
|
||||
{
|
||||
if ($verlauf->angerechnet) return ['c4angerechnetKeinePruefung', []];
|
||||
|
||||
// only a Pruefung of this student in this LV; the StV owns the types without an Antritt
|
||||
$current = $this->findPruefung($verlauf->pruefungen, $pruefung_id);
|
||||
if ($current === null || in_array($current->pruefungstyp_kurzbz, $this->getTypesWithoutAntritt())) {
|
||||
return ['pruefungNichtBearbeitbar', []];
|
||||
}
|
||||
|
||||
if ($this->isOpen($note) && $this->hasOpenPruefung($verlauf->pruefungen, $pruefung_id)) return ['pruefungOhneErgebnis', []];
|
||||
|
||||
if ($current->note_locked && $note != $current->note) return ['pruefungNoteLocked', []];
|
||||
|
||||
// the date must stay strictly between the dates of the neighbours
|
||||
$currentDay = substr((string) $current->datum, 0, 10);
|
||||
$newDay = substr((string) $datum, 0, 10);
|
||||
$lower = null;
|
||||
$upper = null;
|
||||
foreach ($verlauf->pruefungen as $pruefung) {
|
||||
$day = substr((string) $pruefung->datum, 0, 10);
|
||||
if ($pruefung->pruefung_id == $current->pruefung_id || $day === '') continue;
|
||||
|
||||
if ($day < $currentDay && ($lower === null || $day > $lower)) $lower = $day;
|
||||
if ($day > $currentDay && ($upper === null || $day < $upper)) $upper = $day;
|
||||
}
|
||||
if (($lower !== null && $newDay <= $lower) || ($upper !== null && $newDay >= $upper)) {
|
||||
return ['pruefungDatumOutOfRange', []];
|
||||
}
|
||||
|
||||
if ($this->exceedsNoteLimit($verlauf->pruefungen, $note, $current->pruefung_id)) {
|
||||
return ['noteOccuranceLimitReached', []];
|
||||
}
|
||||
|
||||
// only a new date: an old gap outside the rule must not block a Note correction
|
||||
if ($newDay === $currentDay) return null;
|
||||
|
||||
return $this->checkAntrittGap($verlauf, $newDay, $current->pruefung_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The LV-Note after one Pruefung write: the Note of the last Antritt. Without an Antritt the
|
||||
* implicit Antritt 1 stays, else nothing is entered. The LV-Note is never 'entschuldigt'.
|
||||
*
|
||||
* With CIS_GESAMTNOTE_VERBESSERUNG_BESSERE_GEWINNT a worse new Antritt keeps the old LV-Note.
|
||||
*
|
||||
* @param stdClass $verlauf from buildVerlauf, before this write
|
||||
* @param mixed $pruefung_id set = the changed Pruefung, empty = a new Pruefung after all others
|
||||
* @return array [note, punkte]
|
||||
*/
|
||||
public function deriveLvNote($verlauf, $pruefung_id, $note, $punkte, $lvNote, $lvPunkte)
|
||||
{
|
||||
$isNew = $pruefung_id === null || $pruefung_id === '';
|
||||
|
||||
$result = null;
|
||||
foreach ($verlauf->pruefungen as $pruefung) {
|
||||
$row = (!$isNew && $pruefung->pruefung_id == $pruefung_id) ? [$note, $punkte] : [$pruefung->note, $pruefung->punkte];
|
||||
if ($this->isAntritt($row[0], $pruefung->pruefungstyp_kurzbz)) $result = $row;
|
||||
}
|
||||
if ($isNew && $this->isAntritt($note)) $result = [$note, $punkte];
|
||||
|
||||
if ($result === null) {
|
||||
if ($verlauf->implicitErstantritt) return [$lvNote, $lvPunkte];
|
||||
|
||||
return [$this->getNoteNichtEingetragen(), null];
|
||||
}
|
||||
|
||||
if ($result[0] == $note
|
||||
&& $this->configBool('CIS_GESAMTNOTE_VERBESSERUNG_BESSERE_GEWINNT')
|
||||
&& $this->isWorse($note, $lvNote)) {
|
||||
return [$lvNote, $lvPunkte];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes Antritt 1 as its own Pruefung. An LV-Note without a Pruefung IS Antritt 1. While that row
|
||||
* is missing, the next Pruefung becomes Antritt 2 and the Pruefungstypen of the chain shift.
|
||||
*
|
||||
* Writes nothing once a repeat exists, and nothing into a Pruefung with a result of its own.
|
||||
*
|
||||
* @param bool $datumMode self::SET_DATUM or self::KEEP_DATUM for an existing Antritt 1
|
||||
* @return stdClass|null the Pruefung, or null if nothing was written
|
||||
*/
|
||||
public function upsertErstantritt($student_uid, $lv_id, $sem_kurzbz, $note, $punkte, $datum, $datumMode, $mitarbeiter_uid, $lehreinheit_id)
|
||||
{
|
||||
$pruefungen = $this->getPruefungen($student_uid, $lv_id, $sem_kurzbz);
|
||||
// hasRepeat reads only the Pruefungen
|
||||
if ($this->buildVerlauf($pruefungen, null, null)->hasRepeat) return null;
|
||||
|
||||
$now = date('Y-m-d H:i:s');
|
||||
$day = substr((string) $datum, 0, 10);
|
||||
|
||||
if (count($pruefungen) === 1) {
|
||||
if (!$this->canOverwriteErstantritt($pruefungen[0])) return null;
|
||||
|
||||
$data = [
|
||||
'note' => $note,
|
||||
'punkte' => $punkte,
|
||||
'updateamum' => $now,
|
||||
'updatevon' => getAuthUID()
|
||||
];
|
||||
if ($datumMode === self::SET_DATUM) $data['datum'] = $day;
|
||||
|
||||
$this->_ci->LePruefungModel->update($pruefungen[0]->pruefung_id, $data);
|
||||
|
||||
return $this->loadPruefung($pruefungen[0]->pruefung_id);
|
||||
}
|
||||
|
||||
if ($lehreinheit_id === null) return null;
|
||||
|
||||
$result = $this->_ci->LePruefungModel->insert([
|
||||
'lehreinheit_id' => $lehreinheit_id,
|
||||
'student_uid' => $student_uid,
|
||||
'mitarbeiter_uid' => $mitarbeiter_uid,
|
||||
'note' => $note,
|
||||
'punkte' => $punkte,
|
||||
'pruefungstyp_kurzbz' => $this->legacyTypFuerAntritt(1),
|
||||
'datum' => $day,
|
||||
'anmerkung' => '',
|
||||
'insertamum' => $now,
|
||||
'insertvon' => getAuthUID(),
|
||||
'updateamum' => null,
|
||||
'updatevon' => null,
|
||||
'ext_id' => null
|
||||
]);
|
||||
|
||||
return $result ? $this->loadPruefung($result->retval) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Pruefungstyp that the tool writes for an Antritt. The StV still reads that column and calls
|
||||
* this method. A type that tbl_pruefungstyp does not have breaks the foreign key, so step down.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function legacyTypFuerAntritt($antrittNr)
|
||||
{
|
||||
$antrittNr = max(1, (int) $antrittNr);
|
||||
$types = $this->getTypes();
|
||||
|
||||
$kommissionell = $this->_ci->config->item('PRUEFUNG_TYP_KOMMISSIONELL');
|
||||
if ($this->roleForAntritt($antrittNr) === self::ROLE_KOMMISSIONELL && isset($types[$kommissionell])) {
|
||||
return $kommissionell;
|
||||
}
|
||||
|
||||
$typePerAntritt = $this->configArray('PRUEFUNG_TYP_JE_ANTRITT');
|
||||
for ($nr = $antrittNr; $nr >= 1; $nr--) {
|
||||
if (isset($typePerAntritt[$nr]) && isset($types[$typePerAntritt[$nr]])) return $typePerAntritt[$nr];
|
||||
}
|
||||
|
||||
return $typePerAntritt[1];
|
||||
}
|
||||
|
||||
/** The Pruefungstyp of a new repeat; never below Antritt 2. @return string */
|
||||
public function legacyTypeForRepeat($verlauf)
|
||||
{
|
||||
return $this->legacyTypFuerAntritt(max(2, $verlauf->antrittCount + 1));
|
||||
}
|
||||
|
||||
/** Antritte, Antritt 1 and the kommissionelle Pruefung included. @return int */
|
||||
public function getMaxAntritte()
|
||||
{
|
||||
$max = $this->_ci->config->item('CIS_GESAMTNOTE_MAX_ANTRITTE');
|
||||
if ($max !== null) return (int) $max;
|
||||
|
||||
// the flags of the old tool: Antritt 1 plus one Antritt per flag
|
||||
return 1 + (int) CIS_GESAMTNOTE_PRUEFUNG_TERMIN2 + (int) CIS_GESAMTNOTE_PRUEFUNG_TERMIN3 + (int) CIS_GESAMTNOTE_PRUEFUNG_KOMMPRUEF;
|
||||
}
|
||||
|
||||
/** The Antritt from which a Pruefung is kommissionell, or null. @return int|null */
|
||||
public function getKommissionellFromAntritt()
|
||||
{
|
||||
$value = $this->_ci->config->item('CIS_GESAMTNOTE_KOMMISSIONELL_AB_ANTRITT');
|
||||
|
||||
if ($value === 'letzter') {
|
||||
$max = $this->getMaxAntritte();
|
||||
|
||||
// a chain of one has nothing to close
|
||||
return $max > 1 ? $max : null;
|
||||
}
|
||||
|
||||
return (int) $value >= 1 ? (int) $value : null;
|
||||
}
|
||||
|
||||
/** May this tool create the kommissionelle Pruefung? It always shows an existing one. @return bool */
|
||||
public function canCreateKommPruef()
|
||||
{
|
||||
return $this->configBool('CIS_GESAMTNOTE_ALLOW_CREATE_KOMMPRUEF');
|
||||
}
|
||||
|
||||
/** May a student take another Antritt after a positive Note? @return bool */
|
||||
public function allowsImprovement()
|
||||
{
|
||||
return $this->configBool('CIS_GESAMTNOTE_NOTENVERBESSERUNG');
|
||||
}
|
||||
|
||||
/** @return array the Pruefungstypen that never use an Antritt */
|
||||
public function getTypesWithoutAntritt()
|
||||
{
|
||||
return $this->configArray('PRUEFUNG_TYPEN_OHNE_ANTRITT');
|
||||
}
|
||||
|
||||
/**
|
||||
* The special Noten. The configuration names them, lehre.tbl_note gives their keys: a key means
|
||||
* something else in every installation. An unknown name is dropped.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSpecialNotes()
|
||||
{
|
||||
if ($this->_specialNotes !== null) return $this->_specialNotes;
|
||||
|
||||
$entschuldigt = $this->getNoteByBezeichnung($this->_ci->config->item('NOTE_ENTSCHULDIGT_BEZEICHNUNG'));
|
||||
|
||||
$ohneAntritt = $this->resolveNoten('NOTEN_OHNE_ANTRITT_BEZEICHNUNGEN');
|
||||
if ($entschuldigt !== null && !in_array($entschuldigt, $ohneAntritt)) $ohneAntritt[] = $entschuldigt;
|
||||
|
||||
// the configuration names a Note, the rules work with its key
|
||||
$limitMap = [];
|
||||
foreach ($this->configArray('NOTEN_OCCURRENCE_LIMIT_MAP') as $bezeichnung => $limit) {
|
||||
$note = $this->getNoteByBezeichnung($bezeichnung);
|
||||
if ($note !== null) $limitMap[$note] = $limit;
|
||||
}
|
||||
|
||||
$this->_specialNotes = [
|
||||
'entschuldigt' => $entschuldigt,
|
||||
'ohneAntritt' => array_values($ohneAntritt),
|
||||
'anrechnung' => $this->resolveNoten('NOTEN_ANRECHNUNG_BEZEICHNUNGEN'),
|
||||
'abschliessend' => $this->resolveNoten('NOTEN_ABSCHLIESSEND_BEZEICHNUNGEN'),
|
||||
'nichtEingetragen' => $this->getNoteByBezeichnung($this->_ci->config->item('NOTE_NICHT_EINGETRAGEN_BEZEICHNUNG')),
|
||||
// best first
|
||||
'rangfolge' => $this->resolveNoten('NOTEN_RANGFOLGE_BEZEICHNUNGEN'),
|
||||
'limitMap' => $limitMap
|
||||
];
|
||||
return $this->_specialNotes;
|
||||
}
|
||||
|
||||
/** The Note of a Pruefung without a result ('Noch nicht eingetragen'). @return mixed|null */
|
||||
public function getNoteNichtEingetragen()
|
||||
{
|
||||
return $this->getSpecialNotes()['nichtEingetragen'];
|
||||
}
|
||||
|
||||
/** 'angerechnet' or 'intern angerechnet'. Ask it about the Zeugnisnote. @return bool */
|
||||
public function isAnrechnungNote($note)
|
||||
{
|
||||
if ($note === null || $note === '') return false;
|
||||
|
||||
return in_array($note, $this->getSpecialNotes()['anrechnung']);
|
||||
}
|
||||
|
||||
/** Would one more $note cross NOTEN_OCCURRENCE_LIMIT_MAP? $pruefung_id skips the changed row. @return bool */
|
||||
public function exceedsNoteLimit($pruefungen, $note, $pruefung_id = null)
|
||||
{
|
||||
$limit = null;
|
||||
foreach ($this->getSpecialNotes()['limitMap'] as $limitNote => $value) {
|
||||
if ($limitNote == $note) $limit = $value;
|
||||
}
|
||||
if ($limit === null) return false;
|
||||
|
||||
$count = 0;
|
||||
foreach ($pruefungen as $pruefung) {
|
||||
if ($pruefung_id !== null && $pruefung->pruefung_id == $pruefung_id) continue;
|
||||
if ($pruefung->note == $note) $count++;
|
||||
}
|
||||
|
||||
return $count + 1 > $limit;
|
||||
}
|
||||
|
||||
// --- private --------------------------------------------------------------------------------
|
||||
|
||||
/** The role of one Antritt: 1 = erstantritt, later = pruefung, from the commission on = kommissionell. @return string */
|
||||
private function roleForAntritt($antrittNr)
|
||||
{
|
||||
$nr = max(1, (int) $antrittNr);
|
||||
$fromAntritt = $this->getKommissionellFromAntritt();
|
||||
|
||||
if ($fromAntritt !== null && $nr >= $fromAntritt) return self::ROLE_KOMMISSIONELL;
|
||||
|
||||
return $nr === 1 ? self::ROLE_ERSTANTRITT : self::ROLE_PRUEFUNG;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this Note use an Antritt? The Note decides; the type only through PRUEFUNG_TYPEN_OHNE_ANTRITT.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isAntritt($note, $type = null)
|
||||
{
|
||||
if ($type !== null && in_array($type, $this->getTypesWithoutAntritt())) return false;
|
||||
if ($note === null || $note === '') return false;
|
||||
if (in_array($note, $this->getSpecialNotes()['ohneAntritt'])) return false;
|
||||
|
||||
// an Anrechnung is no assessment
|
||||
if ($this->isAnrechnungNote($note)) return false;
|
||||
|
||||
$noteRow = $this->getNote($note);
|
||||
return $noteRow ? (bool) $noteRow->lehre : false;
|
||||
}
|
||||
|
||||
/** Is this Pruefungstyp kommissionell? @return bool */
|
||||
private function isKommissionell($type)
|
||||
{
|
||||
return in_array($type, $this->configArray('PRUEFUNG_KOMMISSIONELL_TYPEN'));
|
||||
}
|
||||
|
||||
/** Is the new Note worse? A Note outside NOTEN_RANGFOLGE_BEZEICHNUNGEN is never worse. @return bool */
|
||||
private function isWorse($newNote, $oldNote)
|
||||
{
|
||||
$rangfolge = $this->getSpecialNotes()['rangfolge'];
|
||||
|
||||
$newRank = array_search($newNote, $rangfolge);
|
||||
$oldRank = array_search($oldNote, $rangfolge);
|
||||
if ($newRank === false || $oldRank === false) return false;
|
||||
|
||||
return $newRank > $oldRank;
|
||||
}
|
||||
|
||||
/** The order of the Verlauf: datum, then tbl_pruefungstyp.sort (old rows without a date), then pruefung_id. */
|
||||
private function sortPruefungen($pruefungen)
|
||||
{
|
||||
$pruefungen = array_values($pruefungen);
|
||||
$types = $this->getTypes();
|
||||
|
||||
usort($pruefungen, function ($a, $b) use ($types) {
|
||||
$dayA = substr((string) $a->datum, 0, 10);
|
||||
$dayB = substr((string) $b->datum, 0, 10);
|
||||
|
||||
if ($dayA !== $dayB) {
|
||||
if ($dayA === '') return -1;
|
||||
if ($dayB === '') return 1;
|
||||
return ($dayA < $dayB) ? -1 : 1;
|
||||
}
|
||||
|
||||
$sortA = isset($types[$a->pruefungstyp_kurzbz]) ? (int) $types[$a->pruefungstyp_kurzbz]->sort : 0;
|
||||
$sortB = isset($types[$b->pruefungstyp_kurzbz]) ? (int) $types[$b->pruefungstyp_kurzbz]->sort : 0;
|
||||
if ($sortA !== $sortB) return ($sortA < $sortB) ? -1 : 1;
|
||||
|
||||
return ((int) $a->pruefung_id < (int) $b->pruefung_id) ? -1 : 1;
|
||||
});
|
||||
|
||||
return $pruefungen;
|
||||
}
|
||||
|
||||
/**
|
||||
* May the LV-Note go into this Pruefung? Antritt 1 and the LV-Note are the same result, and an
|
||||
* empty Pruefung waits for its result. A Pruefung with a result of its own ('entschuldigt',
|
||||
* 'Nicht beurteilt') keeps it: the LV-Note then stays the implicit Antritt 1.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function canOverwriteErstantritt($pruefung)
|
||||
{
|
||||
if (in_array($pruefung->pruefungstyp_kurzbz, $this->getTypesWithoutAntritt())) return false;
|
||||
if ($this->isAntritt($pruefung->note, $pruefung->pruefungstyp_kurzbz)) return true;
|
||||
|
||||
return $this->isOpen($pruefung->note);
|
||||
}
|
||||
|
||||
/**
|
||||
* The first day for a new Pruefung: it comes after all others. CIS_GESAMTNOTE_PRUEFUNG_GLEICHER_TAG
|
||||
* allows the day of the last one.
|
||||
*
|
||||
* @return string|null Y-m-d, or null without a dated Pruefung
|
||||
*/
|
||||
private function earliestNewDay($entries)
|
||||
{
|
||||
$lastDay = null;
|
||||
foreach ($entries as $entry) {
|
||||
$day = substr((string) $entry->datum, 0, 10);
|
||||
if ($day !== '' && ($lastDay === null || $day > $lastDay)) $lastDay = $day;
|
||||
}
|
||||
|
||||
if ($lastDay === null || $this->configBool('CIS_GESAMTNOTE_PRUEFUNG_GLEICHER_TAG')) return $lastDay;
|
||||
|
||||
return date('Y-m-d', strtotime($lastDay . ' +1 day'));
|
||||
}
|
||||
|
||||
/** The Noten that NOTEN_OCCURRENCE_LIMIT_MAP allows no more time in this Verlauf. @return array Note => limit */
|
||||
private function notenAtLimit($entries)
|
||||
{
|
||||
$atLimit = [];
|
||||
foreach ($this->getSpecialNotes()['limitMap'] as $limitNote => $limit) {
|
||||
$count = 0;
|
||||
foreach ($entries as $entry) {
|
||||
if ($entry->note == $limitNote) $count++;
|
||||
}
|
||||
if ($count >= $limit) $atLimit[$limitNote] = $limit;
|
||||
}
|
||||
|
||||
return $atLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The gaps between a Pruefung on $newDay and the Antritte next to it: the last one on or before
|
||||
* the day, and the first one after it. A new Pruefung has no Antritt after it. A Pruefung without
|
||||
* an Antritt does not count: an entschuldigt date must not push the next Antritt away.
|
||||
*
|
||||
* @param mixed $pruefung_id the changed Pruefung, which is no neighbour of itself; null for a new one
|
||||
* @return array|null [phraseKey, params] or null
|
||||
*/
|
||||
private function checkAntrittGap($verlauf, $newDay, $pruefung_id = null)
|
||||
{
|
||||
$min = $this->_ci->config->item('CIS_GESAMTNOTE_ANTRITT_MIN_ABSTAND_TAGE');
|
||||
$max = $this->_ci->config->item('CIS_GESAMTNOTE_ANTRITT_MAX_ABSTAND_TAGE');
|
||||
if (($min === null && $max === null) || $newDay === '') return null;
|
||||
|
||||
$before = null;
|
||||
$after = null;
|
||||
foreach ($verlauf->pruefungen as $pruefung) {
|
||||
$day = substr((string) $pruefung->datum, 0, 10);
|
||||
if (!$pruefung->is_antritt || $day === '' || ($pruefung_id !== null && $pruefung->pruefung_id == $pruefung_id)) continue;
|
||||
|
||||
if ($day <= $newDay && ($before === null || $day > $before)) $before = $day;
|
||||
if ($day > $newDay && ($after === null || $day < $after)) $after = $day;
|
||||
}
|
||||
|
||||
foreach ([[$before, $newDay], [$newDay, $after]] as list($from, $to)) {
|
||||
$gap = ($from !== null && $to !== null) ? $this->daysBetween($from, $to) : null;
|
||||
if ($gap === null) continue;
|
||||
|
||||
if ($min !== null && $gap < (int) $min) return ['pruefungAbstandZuKurz', [(int) $min]];
|
||||
if ($max !== null && $gap > (int) $max) return ['pruefungAbstandZuLang', [(int) $max]];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return array the list under $key, or an empty list */
|
||||
private function configArray($key)
|
||||
{
|
||||
$value = $this->_ci->config->item($key);
|
||||
return is_array($value) ? $value : [];
|
||||
}
|
||||
|
||||
/** @return bool */
|
||||
private function configBool($key)
|
||||
{
|
||||
return (bool) $this->_ci->config->item($key);
|
||||
}
|
||||
|
||||
/** Whole days from $from to $to (Y-m-d). @return int|null */
|
||||
private function daysBetween($from, $to)
|
||||
{
|
||||
$a = DateTime::createFromFormat('Y-m-d|', $from);
|
||||
$b = DateTime::createFromFormat('Y-m-d|', $to);
|
||||
if ($a === false || $b === false) return null;
|
||||
|
||||
$diff = $a->diff($b);
|
||||
|
||||
return $diff->invert ? -((int) $diff->days) : (int) $diff->days;
|
||||
}
|
||||
|
||||
/** @return stdClass|null */
|
||||
private function findPruefung($pruefungen, $pruefung_id)
|
||||
{
|
||||
foreach ($pruefungen as $pruefung) {
|
||||
if ($pruefung->pruefung_id == $pruefung_id) return $pruefung;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return stdClass|null the tbl_note row */
|
||||
private function getNote($note)
|
||||
{
|
||||
if (!array_key_exists($note, $this->_noteCache)) {
|
||||
$result = $this->_ci->NoteModel->load($note);
|
||||
$this->_noteCache[$note] = (!isError($result) && hasData($result)) ? getData($result)[0] : null;
|
||||
}
|
||||
|
||||
return $this->_noteCache[$note];
|
||||
}
|
||||
|
||||
/** @return mixed|null the key of the Note, or null if no Note has this Bezeichnung */
|
||||
private function getNoteByBezeichnung($bezeichnung)
|
||||
{
|
||||
if (!is_string($bezeichnung) || trim($bezeichnung) === '') return null;
|
||||
|
||||
$result = $this->_ci->NoteModel->loadWhere(['bezeichnung' => $bezeichnung]);
|
||||
return (!isError($result) && hasData($result)) ? getData($result)[0]->note : null;
|
||||
}
|
||||
|
||||
/** lehre.tbl_pruefungstyp by pruefungstyp_kurzbz. @return array */
|
||||
private function getTypes()
|
||||
{
|
||||
if ($this->_types !== null) return $this->_types;
|
||||
|
||||
$this->_types = [];
|
||||
$result = $this->_ci->PruefungstypModel->load();
|
||||
if (!isError($result) && hasData($result)) {
|
||||
foreach (getData($result) as $type) $this->_types[$type->pruefungstyp_kurzbz] = $type;
|
||||
}
|
||||
|
||||
return $this->_types;
|
||||
}
|
||||
|
||||
/** Does a Pruefung other than $pruefung_id still wait for its result? @return bool */
|
||||
private function hasOpenPruefung($pruefungen, $pruefung_id = null)
|
||||
{
|
||||
foreach ($pruefungen as $pruefung) {
|
||||
if ($pruefung->pruefung_id != $pruefung_id && $this->isOpen($pruefung->note)) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** A Note with no better one ends the chain for good. @return bool */
|
||||
private function isClosingNote($note)
|
||||
{
|
||||
if ($note === null || $note === '') return false;
|
||||
|
||||
return in_array($note, $this->getSpecialNotes()['abschliessend']);
|
||||
}
|
||||
|
||||
/** 'Noch nicht eingetragen': the Pruefung waits for its result. @return bool */
|
||||
private function isOpen($note)
|
||||
{
|
||||
$open = $this->getNoteNichtEingetragen();
|
||||
|
||||
return $open !== null && $note !== null && $note !== '' && $note == $open;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this Note a pass? tbl_note.positiv is also true for 'entschuldigt' and 'Teilgenommen', so ask
|
||||
* it only about a Note that uses an Antritt.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isPositiveNote($note)
|
||||
{
|
||||
if ($note === null || $note === '') return false;
|
||||
|
||||
$noteRow = $this->getNote($note);
|
||||
return $noteRow ? (bool) $noteRow->positiv : false;
|
||||
}
|
||||
|
||||
/** @return stdClass|null */
|
||||
private function loadPruefung($pruefung_id)
|
||||
{
|
||||
$result = $this->_ci->LePruefungModel->load($pruefung_id);
|
||||
return (!isError($result) && hasData($result)) ? getData($result)[0] : null;
|
||||
}
|
||||
|
||||
/** The keys of the Noten that one configuration key names. @return array */
|
||||
private function resolveNoten($key)
|
||||
{
|
||||
$noten = [];
|
||||
foreach ($this->configArray($key) as $bezeichnung) {
|
||||
$note = $this->getNoteByBezeichnung($bezeichnung);
|
||||
if ($note !== null && !in_array($note, $noten)) $noten[] = $note;
|
||||
}
|
||||
|
||||
return $noten;
|
||||
}
|
||||
}
|
||||
@@ -94,13 +94,13 @@ class StundenplanLib
|
||||
if (isError($benutzer_gruppen))
|
||||
return $benutzer_gruppen;
|
||||
$benutzer_gruppen = getData($benutzer_gruppen);
|
||||
|
||||
$this->_ci->addMeta('spezialgruppen', $benutzer_gruppen);
|
||||
// getting the student_lehrverbaende of the student in the different studiensemester
|
||||
$student_lehrverband = $this->fetchStudentlehrverbandFromStudiensemester($student_uid, $semester_range);
|
||||
if (isError($student_lehrverband))
|
||||
return $student_lehrverband;
|
||||
$student_lehrverband = getData($student_lehrverband);
|
||||
|
||||
$this->_ci->addMeta('studentlehrvebaende', $student_lehrverband);
|
||||
$stundenplan_query = $this->_ci->StundenplanModel->getStundenplanQuery(
|
||||
$start,
|
||||
$end,
|
||||
@@ -632,6 +632,7 @@ class StundenplanLib
|
||||
$result->semester = $item->semester;
|
||||
$result->verband = $item->verband;
|
||||
$result->gruppe = $item->gruppe;
|
||||
$result->studiensemester_kurzbz = $item->studiensemester_kurzbz;
|
||||
return $result;
|
||||
},
|
||||
$lehrverband_query_result);
|
||||
|
||||
@@ -28,10 +28,21 @@ class CoreMissingZgvTagLib
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
|
||||
|
||||
$this->ci->PrestudentModel->db->group_start();
|
||||
|
||||
$this->ci->PrestudentModel->db->where('zgvdatum', null);
|
||||
$this->ci->PrestudentModel->db->where('typ', 'b');
|
||||
|
||||
$this->ci->PrestudentModel->db->or_group_start();
|
||||
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
|
||||
$this->ci->PrestudentModel->db->where('typ', 'm');
|
||||
$this->ci->PrestudentModel->db->group_end();
|
||||
|
||||
$this->ci->PrestudentModel->db->group_end();
|
||||
|
||||
$result = $this->ci->PrestudentModel-> loadWhere(array(
|
||||
'bn.aktiv' => true, //check if necessary
|
||||
'zgvdatum' => null,
|
||||
'typ' => 'b',
|
||||
'bn.aktiv' => true,
|
||||
'studiensemester_kurzbz' => $semester
|
||||
));
|
||||
|
||||
@@ -60,16 +71,36 @@ class CoreMissingZgvTagLib
|
||||
$semester = $params['studiensemester_kurzbz'];
|
||||
$prestudent_id = $params['id'];
|
||||
|
||||
$this->ci->PrestudentModel->addSelect('prestudent_id');
|
||||
$this->ci->PrestudentModel->addSelect('start as von');
|
||||
$this->ci->PrestudentModel->addSelect('ende as bis');
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id');
|
||||
|
||||
//add studiensemester also here for manual rebuild
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz');
|
||||
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id');
|
||||
$this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz');
|
||||
$result = $this->ci->PrestudentModel->loadWhere(array(
|
||||
'bn.aktiv' => true, //check if necessary
|
||||
'zgvdatum' => null,
|
||||
'typ' => 'b',
|
||||
|
||||
$this->ci->PrestudentModel->db->group_start();
|
||||
|
||||
$this->ci->PrestudentModel->db->where('zgvdatum', null);
|
||||
$this->ci->PrestudentModel->db->where('typ', 'b');
|
||||
|
||||
$this->ci->PrestudentModel->db->or_group_start();
|
||||
$this->ci->PrestudentModel->db->where('zgvmadatum', null);
|
||||
$this->ci->PrestudentModel->db->where('typ', 'm');
|
||||
$this->ci->PrestudentModel->db->group_end();
|
||||
|
||||
$this->ci->PrestudentModel->db->group_end();
|
||||
$this->ci->PrestudentModel->db->limit(1);
|
||||
|
||||
$result = $this->ci->PrestudentModel-> loadWhere(array(
|
||||
'bn.aktiv' => true,
|
||||
'studiensemester_kurzbz' => $semester,
|
||||
'prestudent_id' => $prestudent_id
|
||||
));
|
||||
|
||||
if(hasData($result))
|
||||
{
|
||||
return $result;
|
||||
|
||||
@@ -225,6 +225,10 @@ class Gehaltsbestandteil extends AbstractBestandteil implements \JsonSerializabl
|
||||
$grundbetrag = number_format($grundbetrag, 2, '.', '');
|
||||
}
|
||||
$this->markDirty('grundbetrag', $this->grundbetrag, $grundbetrag);
|
||||
if(in_array('grundbetrag', $this->modifiedcolumns))
|
||||
{
|
||||
$this->setBetrag_valorisiert($grundbetrag);
|
||||
}
|
||||
$this->grundbetrag = $grundbetrag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -31,18 +31,20 @@ class Vertrag_model extends DB_Model
|
||||
*/
|
||||
public function save($person_id, $mitarbeiter_uid, $lehrveranstaltung_id, $lehreinheit_id, $projektarbeit_id = null, $vertragsstunden, $betrag, $studiensemester_kurzbz)
|
||||
{
|
||||
$person_id = (isset($person_id) && is_numeric($person_id))
|
||||
$vertragstyp_kurzbz = (is_null($projektarbeit_id)) ? 'Lehrauftrag' : 'Betreuung';
|
||||
|
||||
$person_id = (isset($person_id) && is_numeric($person_id))
|
||||
? $person_id
|
||||
: show_error('peron_id must be set and numeric.');
|
||||
$lehreinheit_id = (isset($lehreinheit_id) && is_numeric($lehreinheit_id))
|
||||
? $lehreinheit_id
|
||||
: show_error('lehreinheit_id must be set and numeric.');
|
||||
$lehrveranstaltung_id = (isset($lehrveranstaltung_id) && is_numeric($lehrveranstaltung_id))
|
||||
? $lehrveranstaltung_id
|
||||
: show_error('lehrveranstaltung_id must be set and numeric.');
|
||||
$projektarbeit_id = (isset($projektarbeit_id) && is_numeric($projektarbeit_id))
|
||||
? $projektarbeit_id
|
||||
: null;
|
||||
$lehreinheit_id = (isset($lehreinheit_id) && is_numeric($lehreinheit_id))
|
||||
? $lehreinheit_id
|
||||
: (($vertragstyp_kurzbz == 'Betreuung') ? null : show_error('lehreinheit_id must be set and numeric.'));
|
||||
$vertragsstunden = (isset($vertragsstunden) && is_numeric($vertragsstunden))
|
||||
? $vertragsstunden
|
||||
: 0;
|
||||
@@ -53,7 +55,7 @@ class Vertrag_model extends DB_Model
|
||||
? $mitarbeiter_uid
|
||||
: show_error('mitarbeiter_uid must be set and a string value.');;
|
||||
|
||||
$vertragstyp_kurzbz = (is_null($projektarbeit_id)) ? 'Lehrauftrag' : 'Betreuung';
|
||||
|
||||
|
||||
// First check if Vertrag already exists for that Lehrauftrag or for that Projektbetreuerauftrag
|
||||
if ($vertragstyp_kurzbz == 'Lehrauftrag')
|
||||
@@ -257,7 +259,7 @@ class Vertrag_model extends DB_Model
|
||||
}
|
||||
elseif ($vertragstyp_kurzbz == 'Betreuung')
|
||||
{
|
||||
$this->addSelect('lehreinheit_id');
|
||||
$this->addSelect('lehreinheit_id, lehre.tbl_projektarbeit.lehrveranstaltung_id, lehre.tbl_projektarbeit.studiensemester_kurzbz');
|
||||
$this->addJoin('lehre.tbl_projektbetreuer', 'vertrag_id');
|
||||
$this->addJoin('lehre.tbl_projektarbeit', 'projektarbeit_id');
|
||||
if ($result = $this->loadWhere(array('vertrag_id' => $vertrag_id)))
|
||||
@@ -281,17 +283,22 @@ class Vertrag_model extends DB_Model
|
||||
{
|
||||
if ($result = getData($this->getLehreinheitID($vertrag_id)))
|
||||
{
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->LehreinheitModel->addSelect($select);
|
||||
if (!empty($result[0]->lehreinheit_id))
|
||||
{
|
||||
$this->load->model('education/Lehreinheit_model', 'LehreinheitModel');
|
||||
$this->LehreinheitModel->addSelect($select);
|
||||
|
||||
if($result = $this->LehreinheitModel->load($result[0]->lehreinheit_id))
|
||||
{
|
||||
return success($result->retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
return error('Fehler beim Laden der Lehreinheit');
|
||||
if ($result = $this->LehreinheitModel->load($result[0]->lehreinheit_id))
|
||||
{
|
||||
return success($result->retval);
|
||||
}
|
||||
else
|
||||
{
|
||||
return error('Fehler beim Laden der Lehreinheit');
|
||||
}
|
||||
}
|
||||
|
||||
return success($result);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -563,14 +570,13 @@ SELECT
|
||||
null::integer as pruefung_id,
|
||||
projektarbeit_id,
|
||||
(tbl_projektbetreuer.stunden*tbl_projektbetreuer.stundensatz) as betrag1,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
tbl_projektbetreuer.betreuerart_kurzbz,
|
||||
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
|
||||
as bezeichnung
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
tbl_projektbetreuer.person_id=?
|
||||
AND vertrag_id IS NULL
|
||||
@@ -619,14 +625,13 @@ SELECT
|
||||
null::integer as pruefung_id,
|
||||
projektarbeit_id,
|
||||
(tbl_projektbetreuer.stunden * tbl_projektbetreuer.stundensatz) as betrag,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
tbl_projektbetreuer.betreuerart_kurzbz,
|
||||
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
|
||||
as bezeichnung, vertrag_id
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
tbl_projektbetreuer.person_id=?
|
||||
AND vertrag_id = ?
|
||||
|
||||
@@ -11,4 +11,73 @@ class Mobilitaet_model extends DB_Model
|
||||
$this->dbTable = 'bis.tbl_mobilitaet';
|
||||
$this->pk = 'mobilitaet_id';
|
||||
}
|
||||
|
||||
public function getMobilityZusatzForUids($uids) {
|
||||
$qry = "SELECT distinct on(nachname, vorname, public.tbl_benutzer.person_id) uid,
|
||||
tbl_mitarbeiter.mitarbeiter_uid,
|
||||
tbl_note.lkt_ueberschreibbar, tbl_note.anmerkung,
|
||||
tbl_mobilitaet.mobilitaetstyp_kurzbz,
|
||||
(CASE WHEN bis.tbl_mobilitaet.studiensemester_kurzbz = vw_student_lehrveranstaltung.studiensemester_kurzbz THEN 1 ELSE 0 END) as doubledegree,
|
||||
public.tbl_prestudent.gsstudientyp_kurzbz as ddtype,
|
||||
(SELECT status_kurzbz FROM public.tbl_prestudentstatus
|
||||
WHERE prestudent_id=tbl_student.prestudent_id
|
||||
ORDER BY datum DESC, insertamum DESC, ext_id DESC LIMIT 1) as studienstatus
|
||||
FROM
|
||||
campus.vw_student_lehrveranstaltung
|
||||
JOIN public.tbl_benutzer USING(uid)
|
||||
JOIN public.tbl_person USING(person_id)
|
||||
LEFT JOIN public.tbl_student ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid)
|
||||
LEFT JOIN public.tbl_studentlehrverband USING(student_uid,studiensemester_kurzbz)
|
||||
LEFT JOIN lehre.tbl_zeugnisnote on(vw_student_lehrveranstaltung.lehrveranstaltung_id=tbl_zeugnisnote.lehrveranstaltung_id
|
||||
AND tbl_zeugnisnote.student_uid=tbl_student.student_uid
|
||||
AND tbl_zeugnisnote.studiensemester_kurzbz=tbl_studentlehrverband.studiensemester_kurzbz)
|
||||
LEFT JOIN lehre.tbl_note USING (note)
|
||||
LEFT JOIN bis.tbl_bisio ON(uid=tbl_bisio.student_uid)
|
||||
LEFT JOIN public.tbl_studiengang ON(tbl_student.studiengang_kz=tbl_studiengang.studiengang_kz)
|
||||
LEFT JOIN bis.tbl_mobilitaet USING(prestudent_id)
|
||||
LEFT JOIN public.tbl_prestudent USING(prestudent_id)
|
||||
WHERE uid IN ?";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, [$uids]);
|
||||
}
|
||||
|
||||
public function formatZusatz($entry, $erhalter_kz) {
|
||||
$zusatz = '';
|
||||
|
||||
if (isset($entry->studienstatus) && $entry->studienstatus === 'Incoming') {
|
||||
$zusatz = '(i)';
|
||||
}
|
||||
|
||||
if (isset($entry->lkt_ueberschreibbar) && $entry->lkt_ueberschreibbar === false) {
|
||||
$zusatz .= ' (' . ($entry->anmerkung ?? '') . ')';
|
||||
}
|
||||
|
||||
if (isset($entry->mitarbeiter_uid) && $entry->mitarbeiter_uid !== null) {
|
||||
$zusatz .= ' (ma)';
|
||||
}
|
||||
|
||||
if (isset($entry->stg_kz_student) && $entry->stg_kz_student == $erhalter_kz) {
|
||||
$zusatz .= ' (a.o.)';
|
||||
}
|
||||
|
||||
if (
|
||||
isset($entry->mobilitaetstyp_kurzbz) && $entry->mobilitaetstyp_kurzbz &&
|
||||
isset($entry->doubledegree) && $entry->doubledegree === 1
|
||||
) {
|
||||
$zusatz .= ' (d.d.';
|
||||
|
||||
$ddtype = $entry->ddtype ?? null;
|
||||
|
||||
if ($ddtype == 'Intern') {
|
||||
$zusatz .= 'int.)';
|
||||
} elseif ($ddtype == 'Extern') {
|
||||
$zusatz .= 'ext.)';
|
||||
} else {
|
||||
$zusatz .= ')';
|
||||
}
|
||||
}
|
||||
|
||||
return $zusatz;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ class Prestudentstatus_model extends DB_Model
|
||||
* @param prestudent_id ID of the Prestudent.
|
||||
* @param $status_kurzbz kurzbz of the status.
|
||||
* @param $ausbildungssemester ausbildungssemester of the status.
|
||||
* @param $studiensemester_kurzbz studiensemster of the status.
|
||||
* @param $studiensemester_kurzbz studiensemester of the status.
|
||||
*
|
||||
* @return result object with all the status entries
|
||||
*/
|
||||
|
||||
@@ -204,7 +204,7 @@ class Student_model extends DB_Model
|
||||
|
||||
Events::trigger(
|
||||
'generate_student_uid',
|
||||
function ($value) use ($uid) {
|
||||
function ($value) use (&$uid) {
|
||||
$uid = $value;
|
||||
},
|
||||
$stgkzl,
|
||||
|
||||
@@ -52,4 +52,47 @@ class LePruefung_model extends DB_Model
|
||||
'student_uid' => $student_uid
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* All Pruefungen of one LV in one Studiensemester.
|
||||
*
|
||||
* Note and Pruefungstyp are LEFT JOINs: a Pruefung with a type that tbl_pruefungstyp does not know
|
||||
* stays in the Verlauf. Else the rules count one Antritt too few.
|
||||
*
|
||||
* No ORDER BY: PruefungsverlaufLib sorts the rows into the order of the Verlauf.
|
||||
*/
|
||||
public function getPruefungenByLvStudiensemester($lv_id, $sem_kurzbz) {
|
||||
$qry = "SELECT tbl_pruefung.*, tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
tbl_note.bezeichnung as note_bezeichnung, tbl_pruefungstyp.beschreibung as typ_beschreibung, tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz
|
||||
FROM lehre.tbl_pruefung
|
||||
JOIN lehre.tbl_lehreinheit ON (tbl_pruefung.lehreinheit_id = tbl_lehreinheit.lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung ON (tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id)
|
||||
LEFT JOIN lehre.tbl_note ON (tbl_pruefung.note = tbl_note.note)
|
||||
LEFT JOIN lehre.tbl_pruefungstyp ON (tbl_pruefung.pruefungstyp_kurzbz = tbl_pruefungstyp.pruefungstyp_kurzbz)
|
||||
WHERE tbl_lehrveranstaltung.lehrveranstaltung_id = ?
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ?";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($lv_id, $sem_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* All Pruefungen of one student in one LV.
|
||||
*
|
||||
* Note and Pruefungstyp are LEFT JOINs. PruefungsverlaufLib derives the Antritt numbers from this
|
||||
* list, and a missing row shifts the whole chain.
|
||||
*/
|
||||
public function getPruefungenByStudent($student_uid, $lv_id, $sem_kurzbz) {
|
||||
$qry = "SELECT tbl_pruefung.*, tbl_lehrveranstaltung.bezeichnung as lehrveranstaltung_bezeichnung, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
tbl_note.bezeichnung as note_bezeichnung, tbl_pruefungstyp.beschreibung as typ_beschreibung, tbl_lehreinheit.studiensemester_kurzbz as studiensemester_kurzbz
|
||||
FROM lehre.tbl_pruefung
|
||||
JOIN lehre.tbl_lehreinheit ON (tbl_pruefung.lehreinheit_id = tbl_lehreinheit.lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung ON (tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id)
|
||||
LEFT JOIN lehre.tbl_note ON (tbl_pruefung.note = tbl_note.note)
|
||||
LEFT JOIN lehre.tbl_pruefungstyp ON (tbl_pruefung.pruefungstyp_kurzbz = tbl_pruefungstyp.pruefungstyp_kurzbz)
|
||||
WHERE tbl_pruefung.student_uid = ?
|
||||
AND tbl_lehrveranstaltung.lehrveranstaltung_id = ?
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ?";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($student_uid, $lv_id, $sem_kurzbz));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -741,4 +741,28 @@ EOSQL;
|
||||
)";
|
||||
}
|
||||
|
||||
|
||||
public function getLehreinheitenForLv($lv_id, $sem_kurzbz)
|
||||
{
|
||||
// every Lehreinheit of the LV; the caller checks the access
|
||||
$query = "SELECT DISTINCT tbl_lehreinheit.lehreinheit_id, tbl_lehreinheit.lehrveranstaltung_id, tbl_lehreinheit.lehrform_kurzbz,
|
||||
tbl_gruppe.direktinskription,
|
||||
tbl_lehreinheitgruppe.semester,
|
||||
tbl_lehreinheitgruppe.verband,
|
||||
tbl_lehreinheitgruppe.gruppe,
|
||||
tbl_lehreinheitgruppe.gruppe_kurzbz,
|
||||
tbl_lehrveranstaltung.kurzbz,
|
||||
tbl_studiengang.kurzbzlang,
|
||||
(SELECT COUNT(DISTINCT datum) FROM campus.vw_stundenplan WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as termincount,
|
||||
(SELECT COUNT(*) FROM campus.vw_student_lehrveranstaltung WHERE lehreinheit_id = lehre.tbl_lehreinheit.lehreinheit_id) as studentcount
|
||||
FROM lehre.tbl_lehreinheit
|
||||
JOIN lehre.tbl_lehreinheitgruppe USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang ON (tbl_lehreinheitgruppe.studiengang_kz = tbl_studiengang.studiengang_kz)
|
||||
LEFT JOIN public.tbl_gruppe ON (tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz)
|
||||
WHERE lehrveranstaltung_id = ? AND tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
ORDER BY tbl_lehreinheitgruppe.gruppe_kurzbz";
|
||||
|
||||
return $this->execReadOnlyQuery($query, [$lv_id, $sem_kurzbz]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +85,18 @@ class Lehreinheitmitarbeiter_model extends DB_Model
|
||||
|
||||
public function getLektorenByLe($lehreinheit_id)
|
||||
{
|
||||
$this->addSelect('vorname, nachname, tbl_lehreinheitmitarbeiter.*, stundenplan.verplant');
|
||||
$this->addSelect('tbl_person.vorname, tbl_person.nachname, tbl_lehreinheitmitarbeiter.*, stundenplan.verplant,
|
||||
COALESCE(insertvonperson.vorname || \' \' || insertvonperson.nachname, tbl_lehreinheitmitarbeiter.insertvon) as insertvon,
|
||||
COALESCE(updatevonperson.vorname || \' \' || updatevonperson.nachname, tbl_lehreinheitmitarbeiter.updatevon) as updatevon');
|
||||
$this->addJoin('tbl_benutzer', 'uid = mitarbeiter_uid');
|
||||
$this->addJoin('tbl_person', 'person_id');
|
||||
$this->addJoin('tbl_benutzer insertvonbenutzer', 'insertvonbenutzer.uid = tbl_lehreinheitmitarbeiter.insertvon', 'LEFT');
|
||||
$this->addJoin('tbl_person insertvonperson', 'insertvonperson.person_id = insertvonbenutzer.person_id', 'LEFT');
|
||||
|
||||
$this->addJoin('tbl_benutzer updatevonbenutzer', 'updatevonbenutzer.uid = tbl_lehreinheitmitarbeiter.updatevon', 'LEFT');
|
||||
$this->addJoin('tbl_person updatevonperson', 'updatevonperson.person_id = updatevonbenutzer.person_id', 'LEFT');
|
||||
|
||||
|
||||
|
||||
$this->addJoin('(
|
||||
SELECT 1 as verplant, lehreinheit_id, mitarbeiter_uid
|
||||
|
||||
@@ -317,7 +317,7 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
tbl_bisio.bisio_id, tbl_bisio.von, tbl_bisio.bis, tbl_student.studiengang_kz AS stg_kz_student,
|
||||
tbl_zeugnisnote.note, tbl_mitarbeiter.mitarbeiter_uid, tbl_person.matr_nr, tbl_benutzer.uid,
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as kuerzel, tbl_studiengang.orgform_kurzbz, vw_student_lehrveranstaltung.semester, vw_student_lehrveranstaltung.studiensemester_kurzbz, vw_student_lehrveranstaltung.bezeichnung,
|
||||
tbl_student.prestudent_id
|
||||
tbl_student.prestudent_id, campus.vw_student_lehrveranstaltung.lehreinheit_id
|
||||
FROM
|
||||
campus.vw_student_lehrveranstaltung
|
||||
JOIN public.tbl_benutzer USING(uid)
|
||||
@@ -685,10 +685,22 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
]);
|
||||
|
||||
$this->dbTable = $tmp;
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* All Lehreinheiten of a student in a Lehrveranstaltung, lowest id first.
|
||||
*/
|
||||
public function getLeIdsByStudent($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id)
|
||||
{
|
||||
$qry = "SELECT DISTINCT lehreinheit_id FROM campus.vw_student_lehrveranstaltung
|
||||
WHERE uid = ? AND lehrveranstaltung_id = ? AND studiensemester_kurzbz = ?
|
||||
ORDER BY lehreinheit_id";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($student_uid, $lehrveranstaltung_id, $studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sucht nach LV Templates und gibt Id und Label ("bezeichnung [kurzbz]") aus
|
||||
* Diese funktion ist für autocomplete gedacht
|
||||
@@ -1263,6 +1275,39 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets lehrveranstaltungen of Studienplan of a certain lva_id set
|
||||
* used if a bigger set of lva id is already available and it needs to be checked against a certain studienplan aswell
|
||||
* @param $studienplan_id ID des Studienplans
|
||||
* @param $lva_ids LVA_ID welche abgegleicht werden sollen
|
||||
* @return array|null
|
||||
*/
|
||||
public function getLvsByStudienplanByLvaIDs($studienplan_id, $lva_ids)
|
||||
{
|
||||
$params = array($studienplan_id, $lva_ids);
|
||||
|
||||
$qry = "SELECT tbl_lehrveranstaltung.*,
|
||||
tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id,
|
||||
tbl_studienplan_lehrveranstaltung.semester as stpllv_semester,
|
||||
tbl_studienplan_lehrveranstaltung.pflicht as stpllv_pflicht,
|
||||
tbl_studienplan_lehrveranstaltung.koordinator as stpllv_koordinator,
|
||||
tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent,
|
||||
tbl_studienplan_lehrveranstaltung.sort stpllv_sort,
|
||||
tbl_studienplan_lehrveranstaltung.curriculum,
|
||||
tbl_studienplan_lehrveranstaltung.export,
|
||||
tbl_studienplan_lehrveranstaltung.genehmigung
|
||||
FROM lehre.tbl_lehrveranstaltung
|
||||
JOIN lehre.tbl_studienplan_lehrveranstaltung
|
||||
USING(lehrveranstaltung_id)
|
||||
WHERE tbl_studienplan_lehrveranstaltung.studienplan_id = ?
|
||||
AND tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id IN ?
|
||||
";
|
||||
|
||||
$qry .= " ORDER BY stpllv_sort, semester, sort";
|
||||
|
||||
return $this->execQuery($qry, $params);
|
||||
}
|
||||
|
||||
public function getAllOe($lv_id)
|
||||
{
|
||||
$qry = "SELECT DISTINCT oe_kurzbz
|
||||
@@ -1346,4 +1391,73 @@ class Lehrveranstaltung_model extends DB_Model
|
||||
|
||||
return $this->execQuery($qry, $params);
|
||||
}
|
||||
|
||||
public function getLvForLektorInSemester($sem_kurzbz, $uid) {
|
||||
$qry = "SELECT DISTINCT (tbl_lehrveranstaltung.lehrveranstaltung_id),
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as stg_kurzbz,
|
||||
tbl_studiengang.studiengang_kz,
|
||||
tbl_lehrveranstaltung.semester as lv_semester,
|
||||
tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung,
|
||||
(SELECT kurzbz FROM public.tbl_mitarbeiter
|
||||
WHERE mitarbeiter_uid=tbl_lehreinheitmitarbeiter.mitarbeiter_uid) as lektor,
|
||||
lehre.tbl_lehrveranstaltung.orgform_kurzbz as orgform
|
||||
|
||||
FROM
|
||||
lehre.tbl_lehreinheit JOIN lehre.tbl_lehreinheitmitarbeiter USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
JOIN lehre.tbl_lehrveranstaltung as lehrfach ON(tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.studiensemester_kurzbz = ?
|
||||
AND mitarbeiter_uid = ?
|
||||
ORDER BY stg_kurzbz,lv_semester,lv_bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($sem_kurzbz, $uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* All Lehrveranstaltungen of a Studiengang offered in a Studiensemester.
|
||||
*/
|
||||
public function getLvForStudiengangInSemester($sem_kurzbz, $studiengang_kz) {
|
||||
$qry = "SELECT DISTINCT (tbl_lehrveranstaltung.lehrveranstaltung_id),
|
||||
UPPER(tbl_studiengang.typ::varchar(1) || tbl_studiengang.kurzbz) as stg_kurzbz,
|
||||
tbl_studiengang.studiengang_kz,
|
||||
tbl_lehrveranstaltung.semester as lv_semester,
|
||||
tbl_lehrveranstaltung.bezeichnung as lv_bezeichnung,
|
||||
tbl_lehrveranstaltung.orgform_kurzbz as orgform
|
||||
FROM
|
||||
lehre.tbl_lehrveranstaltung JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE
|
||||
tbl_lehrveranstaltung.studiengang_kz = ?
|
||||
AND tbl_lehrveranstaltung.aktiv = TRUE
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM lehre.tbl_lehreinheit le
|
||||
WHERE le.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND le.studiensemester_kurzbz = ?
|
||||
)
|
||||
ORDER BY stg_kurzbz,lv_semester,lv_bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($studiengang_kz, $sem_kurzbz));
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of Lehreinheit assignments the given mitarbeiter has for a Lehrveranstaltung (i.e. whether
|
||||
* they teach it), optionally restricted to a Studiensemester. Returns a single row with a `teaches`
|
||||
* count - check `teaches > 0`. Used to scope teacher access in the Benotungstool to their own LVs.
|
||||
*/
|
||||
public function getLektorIsTeachingLva($lva_id, $ma_uid, $studiensemester_kurzbz = null)
|
||||
{
|
||||
$params = array($lva_id, $ma_uid);
|
||||
$query = "SELECT COUNT(*) AS teaches
|
||||
FROM lehre.tbl_lehreinheitmitarbeiter
|
||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
WHERE lehrveranstaltung_id = ? AND mitarbeiter_uid = ?";
|
||||
if ($studiensemester_kurzbz !== null && $studiensemester_kurzbz !== '') {
|
||||
$query .= " AND tbl_lehreinheit.studiensemester_kurzbz = ?";
|
||||
$params[] = $studiensemester_kurzbz;
|
||||
}
|
||||
|
||||
return $this->execReadOnlyQuery($query, $params);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,4 +50,27 @@ class Lvgesamtnote_model extends DB_Model
|
||||
|
||||
return $this->loadWhere($where);
|
||||
}
|
||||
|
||||
/**
|
||||
* The LV-Note of one student, without the Freigabe filter of getLvGesamtNoten().
|
||||
*/
|
||||
public function getByStudent($lehrveranstaltung_id, $student_uid, $studiensemester_kurzbz)
|
||||
{
|
||||
return $this->loadWhere(array(
|
||||
'student_uid' => $student_uid,
|
||||
'lehrveranstaltung_id' => $lehrveranstaltung_id,
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* All LV-Noten of one LV in one Studiensemester, without the Freigabe filter.
|
||||
*/
|
||||
public function getByLvStudiensemester($lehrveranstaltung_id, $studiensemester_kurzbz)
|
||||
{
|
||||
return $this->loadWhere(array(
|
||||
'lehrveranstaltung_id' => $lehrveranstaltung_id,
|
||||
'studiensemester_kurzbz' => $studiensemester_kurzbz
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,31 @@ class Note_model extends DB_Model
|
||||
$this->dbTable = 'lehre.tbl_note';
|
||||
$this->pk = 'note';
|
||||
}
|
||||
|
||||
public function getAllActive() {
|
||||
|
||||
/**
|
||||
* Sorted like the Notenliste of the StV: the scale 1-5 by its value first, every other Note
|
||||
* alphabetically after it.
|
||||
*
|
||||
* @param string|null $sortOrder 'skala' or 'bezeichnung'. The caller holds the configuration.
|
||||
* Without a value the model reads NOTEN_SORTIERUNG itself, for the
|
||||
* callers outside the Benotungstool.
|
||||
*/
|
||||
public function getAllActive($sortOrder = null) {
|
||||
$qry ="SELECT *
|
||||
FROM lehre.tbl_note
|
||||
WHERE aktiv = true";
|
||||
|
||||
if($sortOrder === null) {
|
||||
$this->config->load('noten', FALSE, TRUE);
|
||||
$sortOrder = $this->config->item('NOTEN_SORTIERUNG');
|
||||
}
|
||||
|
||||
$qry .= ($sortOrder === 'bezeichnung')
|
||||
? " ORDER BY bezeichnung"
|
||||
: " ORDER BY CASE WHEN note BETWEEN 1 AND 5 THEN 0 ELSE 1 END,
|
||||
CASE WHEN note BETWEEN 1 AND 5 THEN note END,
|
||||
bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class Notenschluesselaufteilung_model extends DB_Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert die Note zu Punkten einer Lehrveranstaltung
|
||||
* Gives the Note for the Punkte of an LV.
|
||||
*
|
||||
* @param number $points
|
||||
* @param integer $lehrveranstaltung_id
|
||||
@@ -23,9 +23,18 @@ class Notenschluesselaufteilung_model extends DB_Model
|
||||
*/
|
||||
public function getNote($points, $lehrveranstaltung_id, $studiensemester_kurzbz)
|
||||
{
|
||||
// Without valid Punkte no Note follows. Without this guard the query builder makes a bad
|
||||
// statement from "punkte <=" => null ('punkte' < 'IS' 'NULL'), and the request fails with
|
||||
// HTTP 500 instead of an answer that says "no Note".
|
||||
if (!is_numeric($points))
|
||||
return success(null);
|
||||
|
||||
$this->load->model('education/Notenschluesselzuordnung_model', 'NotenschluesselzuordnungModel');
|
||||
$notenschluessel_kurzbz = $this->NotenschluesselzuordnungModel->getKurzbzForLv($lehrveranstaltung_id, $studiensemester_kurzbz);
|
||||
|
||||
if($notenschluessel_kurzbz == null)
|
||||
return success(null);
|
||||
|
||||
$this->addSelect("note");
|
||||
$this->addOrder("punkte", "DESC");
|
||||
$this->addLimit(1);
|
||||
|
||||
@@ -50,8 +50,7 @@ class Paabgabe_model extends DB_Model
|
||||
JOIN lehre.tbl_projektbetreuer USING(projektarbeit_id)
|
||||
JOIN public.tbl_benutzer bn_student ON(tbl_projektarbeit.student_uid=bn_student.uid)
|
||||
JOIN public.tbl_person person_student ON(bn_student.person_id=person_student.person_id)
|
||||
JOIN lehre.tbl_lehreinheit ON(tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung ON(tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang ON(tbl_lehrveranstaltung.studiengang_kz=tbl_studiengang.studiengang_kz)
|
||||
JOIN campus.tbl_paabgabetyp USING(paabgabetyp_kurzbz)
|
||||
WHERE
|
||||
@@ -68,14 +67,13 @@ class Paabgabe_model extends DB_Model
|
||||
campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum,
|
||||
campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel,
|
||||
UPPER(tbl_studiengang.typ) as stgtyp, UPPER(tbl_studiengang.kurzbz) as stgkz, public.tbl_studiengang.studiengang_kz,
|
||||
public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_lehreinheit.studiensemester_kurzbz,
|
||||
public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_projektarbeit.studiensemester_kurzbz,
|
||||
public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost
|
||||
FROM campus.tbl_paabgabe
|
||||
JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz)
|
||||
JOIN lehre.tbl_projektarbeit USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit using(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang on(lehre.tbl_lehrveranstaltung.studiengang_kz = public.tbl_studiengang.studiengang_kz)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang ON(lehre.tbl_lehrveranstaltung.studiengang_kz = public.tbl_studiengang.studiengang_kz)
|
||||
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
|
||||
JOIN public.tbl_person USING (person_id)
|
||||
|
||||
@@ -93,7 +91,7 @@ class Paabgabe_model extends DB_Model
|
||||
campus.tbl_paabgabe.insertvon, campus.tbl_paabgabe.insertamum, campus.tbl_paabgabe.updatevon, campus.tbl_paabgabe.updateamum,
|
||||
campus.tbl_paabgabe.note, upload_allowed, beurteilungsnotiz, student_uid, tbl_projektarbeit.note, lehre.tbl_projektarbeit.titel,
|
||||
UPPER(tbl_studiengang.typ) as stgtyp, UPPER(tbl_studiengang.kurzbz) as stgkz, public.tbl_studiengang.studiengang_kz,
|
||||
public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_lehreinheit.studiensemester_kurzbz,
|
||||
public.tbl_studiengang.oe_kurzbz as stg_oe_kurzbz, tbl_projektarbeit.studiensemester_kurzbz,
|
||||
lehre.tbl_projektbetreuer.betreuerart_kurzbz, lehre.tbl_projektbetreuer.person_id,
|
||||
public.tbl_person.anrede, public.tbl_person.titelpre, public.tbl_person.vorname, public.tbl_person.nachname, public.tbl_person.titelpost
|
||||
|
||||
@@ -101,8 +99,7 @@ class Paabgabe_model extends DB_Model
|
||||
JOIN campus.tbl_paabgabetyp USING (paabgabetyp_kurzbz)
|
||||
JOIN lehre.tbl_projektarbeit USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_projektbetreuer USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit using(lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung using(lehrveranstaltung_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang on(lehre.tbl_lehrveranstaltung.studiengang_kz = public.tbl_studiengang.studiengang_kz)
|
||||
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
|
||||
JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
|
||||
|
||||
@@ -25,7 +25,7 @@ class Projektarbeit_model extends DB_Model
|
||||
{
|
||||
$qry = "SELECT
|
||||
pa.*, tbl_projekttyp.bezeichnung,
|
||||
tbl_lehreinheit.studiensemester_kurzbz, tbl_lehrveranstaltung.lehrveranstaltung_id,
|
||||
pa.studiensemester_kurzbz, pa.lehrveranstaltung_id,
|
||||
tbl_firma.name AS firma_name,
|
||||
(
|
||||
SELECT
|
||||
@@ -41,7 +41,6 @@ class Projektarbeit_model extends DB_Model
|
||||
FROM
|
||||
lehre.tbl_projektarbeit pa
|
||||
JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_firma USING (firma_id)
|
||||
WHERE
|
||||
@@ -57,7 +56,7 @@ class Projektarbeit_model extends DB_Model
|
||||
|
||||
if (isset($studiensemester_kurzbz))
|
||||
{
|
||||
$qry .= ' AND tbl_lehreinheit.studiensemester_kurzbz=?';
|
||||
$qry .= ' AND tbl_projektarbeit.studiensemester_kurzbz=?';
|
||||
$params[] = $studiensemester_kurzbz;
|
||||
}
|
||||
|
||||
@@ -134,7 +133,7 @@ class Projektarbeit_model extends DB_Model
|
||||
projektarbeit_id,
|
||||
lehre.tbl_projekttyp.bezeichnung as projekttypbezeichnung,
|
||||
lehre.tbl_projekttyp.projekttyp_kurzbz as projekttypkurzbz,
|
||||
lehre.tbl_lehreinheit.studiensemester_kurzbz,
|
||||
lehre.tbl_projektarbeit.studiensemester_kurzbz,
|
||||
lehre.tbl_lehrveranstaltung.studiengang_kz,
|
||||
public.tbl_studiengang.kurzbzlang,
|
||||
lehre.tbl_projektarbeit.note as note,
|
||||
@@ -157,7 +156,6 @@ class Projektarbeit_model extends DB_Model
|
||||
LEFT JOIN public.tbl_benutzer USING(person_id)
|
||||
LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
LEFT JOIN lehre.tbl_betreuerart USING(betreuerart_kurzbz)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_mitarbeiter ON(public.tbl_mitarbeiter.mitarbeiter_uid = public.tbl_benutzer.uid)
|
||||
LEFT JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
@@ -366,7 +364,7 @@ class Projektarbeit_model extends DB_Model
|
||||
tbl_studiengang.typ, tbl_studiengang.kurzbz,
|
||||
tbl_projektarbeit.projekttyp_kurzbz, tbl_projekttyp.bezeichnung,
|
||||
tbl_projektarbeit.titel, tbl_projektarbeit.projektarbeit_id, tbl_projektarbeit.note,
|
||||
student_benutzer.uid, tbl_student.matrikelnr, tbl_lehreinheit.studiensemester_kurzbz, public.tbl_student.student_uid,
|
||||
student_benutzer.uid, tbl_student.matrikelnr, tbl_projektarbeit.studiensemester_kurzbz, public.tbl_student.student_uid,
|
||||
|
||||
lehre.tbl_projektarbeit.sprache,
|
||||
lehre.tbl_projektarbeit.seitenanzahl,
|
||||
@@ -430,7 +428,6 @@ class Projektarbeit_model extends DB_Model
|
||||
LEFT JOIN public.tbl_benutzer student_benutzer ON student_benutzer.uid = lehre.tbl_projektarbeit.student_uid
|
||||
LEFT JOIN public.tbl_person student_person ON student_benutzer.person_id = student_person.person_id
|
||||
LEFT JOIN public.tbl_student ON student_benutzer.uid = public.tbl_student.student_uid
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang ON public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
|
||||
LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
@@ -503,7 +500,7 @@ class Projektarbeit_model extends DB_Model
|
||||
student_person.vorname AS student_vorname,
|
||||
student_person.nachname AS student_nachname,
|
||||
public.tbl_student.matrikelnr,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
betreuer_benutzer.uid AS betreuer_benutzer_uid,
|
||||
betreuer_person.titelpre AS betreuer_titelpre,
|
||||
betreuer_person.vorname AS betreuer_vorname,
|
||||
@@ -565,7 +562,6 @@ class Projektarbeit_model extends DB_Model
|
||||
LEFT JOIN public.tbl_benutzer student_benutzer ON student_benutzer.uid = lehre.tbl_projektarbeit.student_uid
|
||||
LEFT JOIN public.tbl_person student_person ON student_benutzer.person_id = student_person.person_id
|
||||
LEFT JOIN public.tbl_student ON student_benutzer.uid = public.tbl_student.student_uid
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang ON public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
|
||||
LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
@@ -633,7 +629,7 @@ class Projektarbeit_model extends DB_Model
|
||||
student_person.vorname AS student_vorname,
|
||||
student_person.nachname AS student_nachname,
|
||||
public.tbl_student.matrikelnr,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
betreuer_benutzer.uid AS betreuer_benutzer_uid,
|
||||
betreuer_person.titelpre AS betreuer_titelpre,
|
||||
betreuer_person.vorname AS betreuer_vorname,
|
||||
@@ -695,7 +691,6 @@ class Projektarbeit_model extends DB_Model
|
||||
LEFT JOIN public.tbl_benutzer student_benutzer ON student_benutzer.uid = lehre.tbl_projektarbeit.student_uid
|
||||
LEFT JOIN public.tbl_person student_person ON student_benutzer.person_id = student_person.person_id
|
||||
LEFT JOIN public.tbl_student ON student_benutzer.uid = public.tbl_student.student_uid
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING (lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang ON public.tbl_student.studiengang_kz = public.tbl_studiengang.studiengang_kz
|
||||
LEFT JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
|
||||
@@ -306,4 +306,5 @@ class Pruefung_model extends DB_Model
|
||||
|
||||
return $this->loadWhereCommitteeExamsFailed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -457,6 +457,7 @@ class Studiengang_model extends DB_Model
|
||||
*/
|
||||
public function getLeitung($studiengang_kz = null)
|
||||
{
|
||||
$this->addDistinct();
|
||||
$this->addSelect('uid, studiengang_kz, oe_kurzbz, vorname, nachname, email, titelpre, titelpost, alias');
|
||||
$this->addJoin('public.tbl_benutzerfunktion', 'oe_kurzbz');
|
||||
$this->addJoin('public.tbl_benutzer', 'uid');
|
||||
|
||||
@@ -59,6 +59,37 @@ class Studienplan_model extends DB_Model
|
||||
'tbl_studienplan_lehrveranstaltung.semester' => $semester
|
||||
));
|
||||
}
|
||||
|
||||
public function getStudienplanByLvaSemKurzbz($lehrveranstaltung_id, $studiensemester_kurzbz) {
|
||||
$qry= "
|
||||
SELECT
|
||||
DISTINCT tbl_studienplan.*
|
||||
FROM
|
||||
lehre.tbl_studienplan
|
||||
JOIN lehre.tbl_studienplan_lehrveranstaltung
|
||||
USING(studienplan_id)
|
||||
WHERE
|
||||
tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id IN (
|
||||
SELECT
|
||||
lv.lehrveranstaltung_id
|
||||
FROM
|
||||
lehre.tbl_lehrveranstaltung AS lv
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung AS t ON t.lehrveranstaltung_id=lv.lehrveranstaltung_template_id
|
||||
WHERE
|
||||
lv.lehrtyp_kurzbz<>'tpl'
|
||||
AND (lv.lehrveranstaltung_id= ? OR (lv.lehrveranstaltung_template_id= ? AND t.lehrtyp_kurzbz='tpl'))
|
||||
)
|
||||
AND EXISTS (
|
||||
SELECT 1
|
||||
FROM
|
||||
lehre.tbl_studienplan_semester
|
||||
WHERE studienplan_id=tbl_studienplan.studienplan_id
|
||||
AND studiensemester_kurzbz= ?
|
||||
AND semester = tbl_studienplan_lehrveranstaltung.semester)
|
||||
ORDER BY bezeichnung";
|
||||
|
||||
return $this->execReadOnlyQuery($qry, array($lehrveranstaltung_id, $lehrveranstaltung_id, $studiensemester_kurzbz));
|
||||
}
|
||||
|
||||
public function getStudienplanLehrveranstaltungForPrestudent($studienplan_id, $semester, $prestudent_id)
|
||||
{
|
||||
|
||||
@@ -218,7 +218,7 @@ class Studiensemester_model extends DB_Model
|
||||
*/
|
||||
public function getByDate($date)
|
||||
{
|
||||
// gets the studiensemster of a date or the next closest previous studiensemester if a date is not within a studiensemester
|
||||
// gets the studiensemester of a date or the next closest previous studiensemester if a date is not within a studiensemester
|
||||
$query = "
|
||||
SELECT studiensemester_kurzbz, start, ende
|
||||
FROM public.tbl_studiensemester
|
||||
|
||||
@@ -98,7 +98,7 @@ class Notiz_model extends DB_Model
|
||||
/**
|
||||
* Add a Notiz for a given person
|
||||
*/
|
||||
public function addNotizForPerson($person_id, $titel, $text, $erledigt, $verfasser_uid)
|
||||
public function addNotizForPerson($person_id, $titel, $text, $erledigt, $verfasser_uid, $insertvon = null)
|
||||
{
|
||||
// Loads model Notizzuordnung_model
|
||||
$this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel');
|
||||
@@ -106,8 +106,15 @@ class Notiz_model extends DB_Model
|
||||
// Start DB transaction
|
||||
$this->db->trans_start(false);
|
||||
|
||||
$result = $this->insert(array('titel' => $titel, 'text' => $text, 'erledigt' => $erledigt, 'verfasser_uid' => $verfasser_uid,
|
||||
"insertvon" => $verfasser_uid));
|
||||
$result = $this->insert(
|
||||
array(
|
||||
'titel' => $titel,
|
||||
'text' => $text,
|
||||
'erledigt' => $erledigt,
|
||||
'verfasser_uid' => $verfasser_uid,
|
||||
'insertvon' => $insertvon ?? $verfasser_uid
|
||||
)
|
||||
);
|
||||
|
||||
if (isSuccess($result))
|
||||
{
|
||||
|
||||
@@ -604,11 +604,17 @@ class Stundenplan_model extends DB_Model
|
||||
{
|
||||
foreach($semester_date_range as $sem_date => $sem_date_range)
|
||||
{
|
||||
if(!array_key_exists($sem_date,$studentlehrverbaende) || count($studentlehrverbaende[$sem_date]) == 0)
|
||||
if(!array_key_exists($sem,$studentlehrverbaende) || count($studentlehrverbaende[$sem]) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach($studentlehrverbaende[$sem_date] as $key=>$lehrverband)
|
||||
$studlvbds = array_filter(
|
||||
$studentlehrverbaende[$sem],
|
||||
function($value) use ($sem_date) {
|
||||
return $value->studiensemester_kurzbz === $sem_date;
|
||||
}
|
||||
);
|
||||
foreach($studlvbds as $key=>$lehrverband)
|
||||
{
|
||||
$query .= "(((sp.studiengang_kz = ".$this->escape($lehrverband->studiengang_kz)." AND sp.semester = ".$this->escape($lehrverband->semester)." AND sp.verband = ".$this->escape($lehrverband->verband)." AND sp.gruppe = ".$this->escape($lehrverband->gruppe)." AND sp.datum BETWEEN ".$this->escape($sem_date_range->start)." AND ".$this->escape($sem_date_range->ende).")";
|
||||
// Eintraege fuer den ganzen Verband
|
||||
|
||||
@@ -23,7 +23,8 @@ $includesArray = array(
|
||||
'public/css/components/FormUnderline.css',
|
||||
'public/css/components/abgabetool/abgabe.css',
|
||||
'public/css/Cis4/Cms.css',
|
||||
'public/css/Cis4/Studium.css'
|
||||
'public/css/Cis4/Studium.css',
|
||||
'public/css/Cis4/Benotungstool.css'
|
||||
),
|
||||
'customJSs' => array(
|
||||
'vendor/npm-asset/primevue/accordion/accordion.min.js',
|
||||
@@ -37,11 +38,15 @@ $includesArray = array(
|
||||
'vendor/npm-asset/primevue/timeline/timeline.min.js',
|
||||
'vendor/npm-asset/primevue/inplace/inplace.min.js',
|
||||
'vendor/npm-asset/primevue/message/message.min.js',
|
||||
'vendor/npm-asset/primevue/divider/divider.min.js',
|
||||
'vendor/npm-asset/primevue/password/password.js',
|
||||
'vendor/npm-asset/primevue/multiselect/multiselect.js',
|
||||
'vendor/npm-asset/primevue/tieredmenu/tieredmenu.js',
|
||||
'vendor/moment/luxonjs/luxon.min.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/Cis/Cis.js',
|
||||
'vendor/olifolkerd/tabulator5/src/js/modules/ColumnCalcs/ColumnCalcs.js'
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ $query = '
|
||||
anrechnung.begruendung_id,
|
||||
anrechnung.dms_id,
|
||||
CASE
|
||||
WHEN stg.typ || stg.kurzbz IN (' . $ORGANISATIONSEINHEITEN_SCHREIBBERECHTIGT . ') THEN TRUE
|
||||
WHEN stg.oe_kurzbz IN (' . $ORGANISATIONSEINHEITEN_SCHREIBBERECHTIGT . ') THEN TRUE
|
||||
ELSE FALSE
|
||||
END "schreibberechtigt",
|
||||
anrechnung.studiensemester_kurzbz,
|
||||
|
||||
@@ -232,8 +232,8 @@ FROM
|
||||
SELECT
|
||||
pa.lehreinheit_id,
|
||||
lv.lehrveranstaltung_id,
|
||||
pa.projektarbeit_id::text AS "projektarbeit_id",
|
||||
le.studiensemester_kurzbz,
|
||||
pa.projektarbeit_id::text AS "projektarbeit_id",
|
||||
pa.studiensemester_kurzbz,
|
||||
stg.studiengang_kz,
|
||||
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
|
||||
lv.orgform_kurzbz,
|
||||
@@ -268,8 +268,7 @@ FROM
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer pb
|
||||
JOIN lehre.tbl_projektarbeit pa USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv ON (pa.lehrveranstaltung_id = lv.lehrveranstaltung_id)
|
||||
JOIN PUBLIC.tbl_organisationseinheit oe USING (oe_kurzbz)
|
||||
JOIN PUBLIC.tbl_person person USING (person_id)
|
||||
LEFT JOIN lehre.tbl_vertrag vertrag USING (vertrag_id)
|
||||
@@ -280,7 +279,7 @@ FROM
|
||||
/* filter projektbetreuuer */
|
||||
pb.person_id = \'' . $PERSON_ID . '\'
|
||||
/* filter studiensemester */
|
||||
AND le.studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
|
||||
AND pa.studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
|
||||
/* filter active lehrveranstaltungen */
|
||||
AND lv.aktiv = TRUE
|
||||
/* filter active organisationseinheiten */
|
||||
|
||||
@@ -242,8 +242,8 @@ FROM
|
||||
pa.lehreinheit_id,
|
||||
lv.lehrveranstaltung_id,
|
||||
lv.bezeichnung AS "lv_bezeichnung",
|
||||
(pa.projektarbeit_id::text) AS "projektarbeit_id",
|
||||
le.studiensemester_kurzbz,
|
||||
(pa.projektarbeit_id::text) AS "projektarbeit_id",
|
||||
pa.studiensemester_kurzbz,
|
||||
stg.studiengang_kz,
|
||||
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
|
||||
lv.orgform_kurzbz,
|
||||
@@ -270,7 +270,7 @@ FROM
|
||||
ELSE (oe.organisationseinheittyp_kurzbz ||
|
||||
\' \' || oe.bezeichnung)
|
||||
END AS "lv_oe_kurzbz",
|
||||
(nachname || \' \' || vorname) AS "lektor",
|
||||
(nachname || \' \' || vorname) AS "lektor",
|
||||
TRUNC(pb.stunden, 1) AS "stunden",
|
||||
pb.stundensatz,
|
||||
TRUNC((pb.stunden * pb.stundensatz), 2) AS "betrag",
|
||||
@@ -280,8 +280,7 @@ FROM
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer pb
|
||||
JOIN lehre.tbl_projektarbeit pa USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv ON (pa.lehrveranstaltung_id = lv.lehrveranstaltung_id)
|
||||
JOIN PUBLIC.tbl_organisationseinheit oe USING (oe_kurzbz)
|
||||
JOIN PUBLIC.tbl_person person USING (person_id)
|
||||
LEFT JOIN lehre.tbl_vertrag vertrag USING (vertrag_id)
|
||||
@@ -291,7 +290,7 @@ FROM
|
||||
/* filter organisationseinheit */
|
||||
lv.oe_kurzbz IN (\'' . implode('\',\'', $ORGANISATIONSEINHEIT) . '\')
|
||||
/* filter studiensemester */
|
||||
AND le.studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
|
||||
AND pa.studiensemester_kurzbz = \'' . $STUDIENSEMESTER . '\'
|
||||
/* filter active lehrveranstaltungen */
|
||||
AND lv.aktiv = TRUE
|
||||
/* filter active organisationseinheiten */
|
||||
|
||||
@@ -272,8 +272,8 @@ FROM
|
||||
pa.lehreinheit_id,
|
||||
lv.lehrveranstaltung_id,
|
||||
lv.bezeichnung AS "lv_bezeichnung",
|
||||
pa.projektarbeit_id::text AS "projektarbeit_id",
|
||||
le.studiensemester_kurzbz,
|
||||
pa.projektarbeit_id::text AS "projektarbeit_id",
|
||||
pa.studiensemester_kurzbz,
|
||||
stg.studiengang_kz,
|
||||
upper(stg.typ || stg.kurzbz) AS "stg_typ_kurzbz",
|
||||
lv.orgform_kurzbz,
|
||||
@@ -310,8 +310,7 @@ FROM
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer pb
|
||||
JOIN lehre.tbl_projektarbeit pa USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit le USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv ON (pa.lehrveranstaltung_id = lv.lehrveranstaltung_id)
|
||||
JOIN PUBLIC.tbl_organisationseinheit oe USING (oe_kurzbz)
|
||||
JOIN PUBLIC.tbl_person person USING (person_id)
|
||||
LEFT JOIN lehre.tbl_vertrag vertrag USING (vertrag_id)
|
||||
@@ -321,7 +320,7 @@ FROM
|
||||
/* filter studiengang */
|
||||
lv.studiengang_kz IN ('. implode(',', $STUDIENGANG) . ')
|
||||
/* filter studiensemester */
|
||||
AND le.studiensemester_kurzbz = \''. $STUDIENSEMESTER. '\'
|
||||
AND pa.studiensemester_kurzbz = \''. $STUDIENSEMESTER. '\'
|
||||
/* filter active lehrveranstaltungen */
|
||||
AND lv.aktiv = TRUE
|
||||
/* filter ausbildungssemester */
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="row<?php if ($lockedbyother) echo ' alert-danger' ?>">
|
||||
<div class="col-lg-8">
|
||||
<h3 class="page-header">
|
||||
Infocenter Details: <a target="_blank" title="Studentenverwaltung" href="<?php echo site_url('/Studentenverwaltung/' . $studiensemester . '/person/' . $stammdaten->person_id) ?>"><?php echo $stammdaten->vorname.' '.$stammdaten->nachname ?> <i class="fa fa-external-link" style="font-size:small"></i></a>
|
||||
Infocenter Details: <a target="_blank" title="Studentenverwaltung" href="<?php echo site_url('/studvw/stdsem/' . $studiensemester . '/person/' . $stammdaten->person_id) ?>"><?php echo $stammdaten->vorname.' '.$stammdaten->nachname ?> <i class="fa fa-external-link" style="font-size:small"></i></a>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
$LOGDATA_NAME = '\'Login with code\', \'Login with user\', \'Attempt to register with existing mailadress\', \'Access code sent\', \'Personal data saved\'';
|
||||
$REJECTED_STATUS = '\'Abgewiesener\'';
|
||||
$ADDITIONAL_STG = $this->config->item('infocenter_studiengang_kz');
|
||||
$QUALIFIKATIONSKURS = $this->config->item('infocenter_qualifikationskurs_kz');
|
||||
$STATUS_KURZBZ = '\'Wartender\', \'Bewerber\', \'Aufgenommener\', \'Student\'';
|
||||
$STUDIENSEMESTER = '\''.$this->variablelib->getVar('infocenter_studiensemester').'\'';
|
||||
$ORG_NAME = '\'InfoCenter\'';
|
||||
@@ -277,7 +278,26 @@ $query = '
|
||||
WHERE konto.person_id = p.person_id
|
||||
AND konto.studiensemester_kurzbz = '. $STUDIENSEMESTER .'
|
||||
AND konto.buchungstyp_kurzbz = '. $KAUTION_DRITT_STAAT .'
|
||||
) AS "Kaution"
|
||||
) AS "Kaution",
|
||||
(
|
||||
SELECT 1
|
||||
FROM public.tbl_prestudentstatus pss
|
||||
JOIN public.tbl_prestudent ps USING(prestudent_id)
|
||||
JOIN public.tbl_studiengang sg USING(studiengang_kz)
|
||||
JOIN lehre.tbl_studienplan sp USING(studienplan_id)
|
||||
JOIN lehre.tbl_studienordnung so USING(studienordnung_id)
|
||||
WHERE pss.status_kurzbz = '.$INTERESSENT_STATUS.'
|
||||
AND pss.bewerbung_abgeschicktamum IS NOT NULL
|
||||
AND ps.person_id = p.person_id
|
||||
AND sg.studiengang_kz in('.$QUALIFIKATIONSKURS.')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM tbl_prestudentstatus spss
|
||||
WHERE spss.prestudent_id = ps.prestudent_id
|
||||
AND spss.status_kurzbz = '.$REJECTED_STATUS.'
|
||||
)
|
||||
LIMIT 1
|
||||
) AS "Qualikurs"
|
||||
FROM public.tbl_person p
|
||||
LEFT JOIN (
|
||||
SELECT tpl.person_id,
|
||||
@@ -351,7 +371,8 @@ $query = '
|
||||
'ZGV Nation MA',
|
||||
'InfoCenter Mitarbeiter',
|
||||
'Identitätsnachweis',
|
||||
ucfirst($this->p->t('infocenter', 'kaution'))
|
||||
ucfirst($this->p->t('infocenter', 'kaution')),
|
||||
'Qualikurs'
|
||||
),
|
||||
'formatRow' => function($datasetRaw) {
|
||||
|
||||
@@ -480,6 +501,14 @@ $query = '
|
||||
$datasetRaw->{'Kaution'} = 'Offen';
|
||||
}
|
||||
|
||||
if ($datasetRaw->{'Qualikurs'} === null)
|
||||
{
|
||||
$datasetRaw->{'Qualikurs'} = 'Nein';
|
||||
}
|
||||
else
|
||||
{
|
||||
$datasetRaw->{'Qualikurs'} = 'Ja';
|
||||
}
|
||||
return $datasetRaw;
|
||||
},
|
||||
'markRow' => function($datasetRaw) {
|
||||
|
||||
@@ -92,6 +92,14 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-lg-6 table-responsive">
|
||||
<?php if ($onboarding_first_login): ?>
|
||||
<div class="row" id="onboardingRow">
|
||||
<?php if ($created_by_onboarding): ?>
|
||||
<div class="col-xs-5"><strong><?php echo $this->p->t('infocenter','onboardingRegistriert') ?></strong></div>
|
||||
<?php endif; ?>
|
||||
<div class="col-xs-7<?php echo $created_by_onboarding ? ' text-right' : '' ?>"><strong><?php echo $this->p->t('infocenter','ersterOnboardingLogin').': '.date_format(date_create($onboarding_first_login), 'd.m.Y') ?></strong></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<table class="table table-bordered stammdaten_form">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -191,12 +199,12 @@
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="col-xs-6">
|
||||
<a class="editStammdaten">
|
||||
<a class="editStammdaten" href="javascript:void(0);">
|
||||
<i class="fa fa-edit"></i> <?php echo $this->p->t('ui','bearbeiten'); ?></a>
|
||||
<div class="editActionStammdaten" style="display:none">
|
||||
<a class="cancelStammdaten">
|
||||
<a class="cancelStammdaten" href="javascript:void(0);">
|
||||
<i class="fa fa-trash"></i> <?php echo $this->p->t('ui','abbrechen');?></a>
|
||||
<a class="saveStammdaten">
|
||||
<a class="saveStammdaten" href="javascript:void(0);">
|
||||
<i class="fa fa-save"></i> <?php echo $this->p->t('ui','speichern'); ?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1824,7 +1824,7 @@ $htmlstring .= "
|
||||
|
||||
</table>
|
||||
";
|
||||
if ($anzahlChanged > 0)
|
||||
if (isset($anzahlChanged) && $anzahlChanged > 0)
|
||||
echo '<div id="notenWarning" class="warning">' . $p->t('benotungstool/geaenderteNotenVorhanden') . '</div>';
|
||||
|
||||
echo $htmlstring;
|
||||
|
||||
@@ -159,6 +159,41 @@ if (!$berechtigung->isBerechtigt('admin')
|
||||
// let's merge
|
||||
$format_title->setAlign('merge');
|
||||
|
||||
// Importkonfiguration aus dem CI-Config (application/config/noten.php) lesen, damit nur die
|
||||
// Spalten des jeweils aktiven Importtyps hervorgehoben (grau) werden.
|
||||
$CIS_GESAMTNOTE_NOTENIMPORT = false;
|
||||
$CIS_GESAMTNOTE_PRUEFUNGSIMPORT = true;
|
||||
$notenConfigFile = __DIR__.'/../../../application/config/noten.php';
|
||||
if(is_file($notenConfigFile))
|
||||
{
|
||||
if(!defined('BASEPATH')) define('BASEPATH', true);
|
||||
$config = array();
|
||||
include($notenConfigFile);
|
||||
if(isset($config['CIS_GESAMTNOTE_NOTENIMPORT'])) $CIS_GESAMTNOTE_NOTENIMPORT = $config['CIS_GESAMTNOTE_NOTENIMPORT'];
|
||||
if(isset($config['CIS_GESAMTNOTE_PRUEFUNGSIMPORT'])) $CIS_GESAMTNOTE_PRUEFUNGSIMPORT = $config['CIS_GESAMTNOTE_PRUEFUNGSIMPORT'];
|
||||
unset($config);
|
||||
}
|
||||
|
||||
// plain (non-highlighted) variants used when an import type is disabled
|
||||
$format_plain =& $workbook->addFormat();
|
||||
$format_plain->setAlign('left');
|
||||
$format_plain->setNumFormat(49);
|
||||
|
||||
$format_plainright =& $workbook->addFormat();
|
||||
$format_plainright->setAlign('right');
|
||||
$format_plainright->setNumFormat(49);
|
||||
|
||||
// highlight only the cells belonging to an enabled import flow:
|
||||
// - Notenimport -> Personenkennzeichen + Note (main block)
|
||||
// - Prüfungsimport -> Personenkennzeichen + Datum + Note (Termin2/Termin3 blocks)
|
||||
$fmtNoteImportPkz = $CIS_GESAMTNOTE_NOTENIMPORT ? $format_highlight : $format_plain;
|
||||
$fmtNoteImportNote = $CIS_GESAMTNOTE_NOTENIMPORT ? $format_highlightright : $format_plainright;
|
||||
$fmtPruefImportPkz = $CIS_GESAMTNOTE_PRUEFUNGSIMPORT ? $format_highlight : $format_plain;
|
||||
$fmtPruefImportDate = $CIS_GESAMTNOTE_PRUEFUNGSIMPORT ? $format_highlightright_date : $format_plainright;
|
||||
$fmtPruefImportNote = $CIS_GESAMTNOTE_PRUEFUNGSIMPORT ? $format_highlightright : $format_plainright;
|
||||
|
||||
$lvobj = new lehrveranstaltung($lvid);
|
||||
|
||||
$worksheet->write(0,0,$p->t('anwesenheitsliste/notenliste')." ".($sprache=='English'?$lvobj->bezeichnung_english:$lvobj->bezeichnung),$format_bold);
|
||||
|
||||
$stg_obj = new studiengang($stg);
|
||||
|
||||
@@ -345,11 +345,10 @@ $qry = "SELECT
|
||||
WHERE uid=student_uid) as student, tbl_lehrveranstaltung.studiengang_kz, tbl_lehrveranstaltung.semester,
|
||||
tbl_studiengang.email, tbl_betreuerart.beschreibung AS beutreuerart_beschreibung, tbl_projektbetreuer.stunden
|
||||
FROM
|
||||
lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektarbeit, lehre.tbl_projektbetreuer, public.tbl_studiengang, lehre.tbl_betreuerart
|
||||
lehre.tbl_lehrveranstaltung, lehre.tbl_projektarbeit, lehre.tbl_projektbetreuer, public.tbl_studiengang, lehre.tbl_betreuerart
|
||||
WHERE
|
||||
tbl_lehreinheit.lehreinheit_id=tbl_projektarbeit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($stdsem)." AND
|
||||
tbl_lehrveranstaltung.lehrveranstaltung_id=tbl_projektarbeit.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($stdsem)." AND
|
||||
tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_lehrveranstaltung.studiengang_kz=tbl_studiengang.studiengang_kz AND
|
||||
tbl_projektbetreuer.betreuerart_kurzbz=tbl_betreuerart.betreuerart_kurzbz AND
|
||||
|
||||
@@ -143,7 +143,6 @@ if($aktion!='zip')
|
||||
JOIN campus.tbl_paabgabe USING(projektarbeit_id)
|
||||
LEFT JOIN public.tbl_benutzer ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_person ON(tbl_benutzer.person_id=tbl_person.person_id)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom')
|
||||
@@ -214,7 +213,6 @@ if(isset($_REQUEST['ok']) || (isset($_REQUEST['aktion']) && $_REQUEST['aktion']=
|
||||
JOIN campus.tbl_paabgabe USING(projektarbeit_id)
|
||||
LEFT JOIN public.tbl_benutzer ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_person ON(tbl_benutzer.person_id=tbl_person.person_id)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom')
|
||||
|
||||
@@ -87,7 +87,6 @@ cellSeparator (default value: "|")
|
||||
JOIN campus.tbl_paabgabe USING(projektarbeit_id)
|
||||
LEFT JOIN public.tbl_benutzer ON(uid=student_uid)
|
||||
LEFT JOIN public.tbl_person ON(tbl_benutzer.person_id=tbl_person.person_id)
|
||||
LEFT JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
LEFT JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
LEFT JOIN public.tbl_studiengang USING(studiengang_kz)
|
||||
WHERE (projekttyp_kurzbz='Bachelor' OR projekttyp_kurzbz='Diplom')
|
||||
|
||||
@@ -122,8 +122,7 @@ foreach ($project_arr as $project)
|
||||
|
||||
// * get studiensemester
|
||||
$pa = new Projektarbeit($pa_id);
|
||||
$le = new Lehreinheit($pa->lehreinheit_id);
|
||||
$studiensemester_kurzbz = $le->studiensemester_kurzbz;
|
||||
$studiensemester_kurzbz = $pa->studiensemester_kurzbz;
|
||||
|
||||
// * get begin- and end date of studiensemester
|
||||
$ss = new Studiensemester($studiensemester_kurzbz);
|
||||
|
||||
@@ -107,16 +107,14 @@ SELECT
|
||||
FROM
|
||||
lehre.tbl_projektarbeit,
|
||||
lehre.tbl_lehrveranstaltung,
|
||||
lehre.tbl_lehreinheit,
|
||||
lehre.tbl_projektbetreuer,
|
||||
public.tbl_person
|
||||
WHERE
|
||||
tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_lehreinheit.lehreinheit_id=tbl_projektarbeit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektbetreuer.person_id=tbl_person.person_id AND
|
||||
tbl_projektbetreuer.stunden<>0 AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($stsem)."
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($stsem)."
|
||||
GROUP BY studiengang_kz,geschlecht";
|
||||
|
||||
if(!$result = $db->db_query($qry))
|
||||
@@ -231,7 +229,7 @@ if($format=='xls')
|
||||
if(!isset($stunden['w']))
|
||||
$stunden['w']=0;
|
||||
$summe_w+=$stunden['w'];
|
||||
if(!isset($summe_oe[$oe]['w']))
|
||||
if(!isset($summe_oe[$oe]['w']))
|
||||
$summe_oe[$oe]['w']=0;
|
||||
$summe_oe[$oe]['w']+=$stunden['w'];
|
||||
$worksheet->write($zeile,$organisationseinheiten_idx[$oe]+1,$stunden['w'],$format_data);
|
||||
|
||||
@@ -85,7 +85,7 @@ $db = new basis_db();
|
||||
//Daten holen
|
||||
$qry = "SELECT * FROM (
|
||||
SELECT
|
||||
tbl_lehreinheit.*, tbl_person.vorname, tbl_person.nachname, tbl_person.titelpre,
|
||||
tbl_person.vorname, tbl_person.nachname, tbl_person.titelpre,
|
||||
tbl_mitarbeiter.personalnummer, tbl_person.person_id, tbl_mitarbeiter.mitarbeiter_uid,
|
||||
tbl_mitarbeiter.fixangestellt,
|
||||
tbl_lehreinheitmitarbeiter.stundensatz as stundensatz,
|
||||
@@ -109,21 +109,20 @@ if($semester!='')
|
||||
//Projektsbetreuungen
|
||||
$qry.= " UNION
|
||||
SELECT
|
||||
tbl_lehreinheit.*, tbl_person.vorname, tbl_person.nachname, tbl_person.titelpre,
|
||||
tbl_person.vorname, tbl_person.nachname, tbl_person.titelpre,
|
||||
tbl_mitarbeiter.personalnummer, tbl_person.person_id, tbl_mitarbeiter.mitarbeiter_uid,
|
||||
tbl_mitarbeiter.fixangestellt,
|
||||
0 as stundensatz,
|
||||
0 as semesterstunden
|
||||
FROM
|
||||
lehre.tbl_lehreinheit, lehre.tbl_projektarbeit, lehre.tbl_projektbetreuer,
|
||||
lehre.tbl_projektarbeit, lehre.tbl_projektbetreuer,
|
||||
public.tbl_mitarbeiter, public.tbl_benutzer, lehre.tbl_lehrveranstaltung, public.tbl_person
|
||||
WHERE
|
||||
tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid AND
|
||||
tbl_benutzer.person_id = tbl_projektbetreuer.person_id AND
|
||||
tbl_projektarbeit.projektarbeit_id = tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_projektarbeit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." AND
|
||||
tbl_lehrveranstaltung.studiengang_kz = ".$db->db_add_param($studiengang_kz, FHC_INTEGER)." AND
|
||||
tbl_person.person_id = tbl_projektbetreuer.person_id";
|
||||
if($semester!='')
|
||||
@@ -164,16 +163,15 @@ if($result = $db->db_query($qry))
|
||||
$qry = "
|
||||
SELECT
|
||||
tbl_projektbetreuer.stunden, tbl_projektbetreuer.stundensatz
|
||||
FROM lehre.tbl_projektbetreuer, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung,
|
||||
FROM lehre.tbl_projektbetreuer, lehre.tbl_lehrveranstaltung,
|
||||
public.tbl_benutzer, lehre.tbl_projektarbeit, campus.vw_student
|
||||
WHERE
|
||||
tbl_projektbetreuer.person_id=tbl_benutzer.person_id
|
||||
AND tbl_benutzer.uid=".$db->db_add_param($uid)."
|
||||
AND tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id
|
||||
AND student_uid=vw_student.uid
|
||||
AND tbl_lehreinheit.lehreinheit_id=tbl_projektarbeit.lehreinheit_id
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
AND tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
AND tbl_projektarbeit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER);
|
||||
if($semester!='')
|
||||
$qry.=" AND tbl_lehrveranstaltung.semester=".$db->db_add_param($semester, FHC_INTEGER);
|
||||
|
||||
@@ -99,10 +99,9 @@ $qry_stg = "SELECT distinct studiengang_kz, typ, kurzbz
|
||||
studiengang_kz
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer JOIN lehre.tbl_projektarbeit ON tbl_projektbetreuer.projektarbeit_id=tbl_projektarbeit.projektarbeit_id
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_projektarbeit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrveranstaltung_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_projektarbeit.lehrveranstaltung_id
|
||||
WHERE
|
||||
lehre.tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
lehre.tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
) as foo
|
||||
JOIN public.tbl_studiengang USING (studiengang_kz)
|
||||
";
|
||||
@@ -506,10 +505,9 @@ if ($result_stg = $db->db_query($qry_stg))
|
||||
JOIN public.tbl_benutzer ON tbl_benutzer.person_id=tbl_person.person_id
|
||||
JOIN public.tbl_mitarbeiter ON tbl_mitarbeiter.mitarbeiter_uid=tbl_benutzer.uid
|
||||
JOIN lehre.tbl_projektarbeit ON tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id=tbl_projektarbeit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrveranstaltung_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_projektarbeit.lehrveranstaltung_id
|
||||
WHERE
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND
|
||||
tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER)." AND
|
||||
NOT EXISTS (SELECT
|
||||
mitarbeiter_uid
|
||||
@@ -589,12 +587,11 @@ if ($result_stg = $db->db_query($qry_stg))
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer JOIN public.tbl_benutzer ON tbl_projektbetreuer.person_id = tbl_benutzer.person_id
|
||||
JOIN lehre.tbl_projektarbeit ON tbl_projektarbeit.projektarbeit_id = tbl_projektbetreuer.projektarbeit_id
|
||||
JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_projektarbeit.lehreinheit_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
JOIN lehre.tbl_lehrveranstaltung ON tbl_projektarbeit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
JOIN campus.vw_student ON vw_student.uid = student_uid
|
||||
WHERE
|
||||
tbl_benutzer.uid = ".$db->db_add_param($uid)."
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
AND tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
AND tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER);
|
||||
|
||||
if ($result = $db->db_query($qry))
|
||||
@@ -825,15 +822,14 @@ if ($result_stg = $db->db_query($qry_stg))
|
||||
$worksheet =& $workbook->addWorksheet('Betreuerstunden');
|
||||
$worksheet->setInputEncoding('utf-8');
|
||||
$qry = "SELECT
|
||||
studiensemester_kurzbz, nachname, vorname, sum(stunden) AS stunden, titelpre,
|
||||
lehre.tbl_projektarbeit.studiensemester_kurzbz, nachname, vorname, sum(stunden) AS stunden, titelpre,
|
||||
sum(tbl_projektbetreuer.stundensatz*tbl_projektbetreuer.stunden)::numeric(8, 2) AS euro, person_id
|
||||
FROM
|
||||
public.tbl_person JOIN lehre.tbl_projektbetreuer USING (person_id)
|
||||
JOIN lehre.tbl_projektarbeit USING (projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
|
||||
JOIN lehre.tbl_lehrveranstaltung USING(lehrveranstaltung_id)
|
||||
WHERE
|
||||
studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." AND
|
||||
lehre.tbl_projektarbeit.studiensemester_kurzbz = ".$db->db_add_param($semester_aktuell)." AND
|
||||
stunden > 0";
|
||||
|
||||
if (count($stg_arr) > 0)
|
||||
@@ -841,7 +837,7 @@ if ($result_stg = $db->db_query($qry_stg))
|
||||
|
||||
$qry .= "
|
||||
GROUP BY
|
||||
studiensemester_kurzbz, person_id, nachname, vorname, titelpre
|
||||
lehre.tbl_projektarbeit.studiensemester_kurzbz, person_id, nachname, vorname, titelpre
|
||||
ORDER BY
|
||||
nachname, vorname
|
||||
";
|
||||
|
||||
@@ -304,15 +304,14 @@ if($studiengang_kz!='')
|
||||
$qry = "SELECT
|
||||
*
|
||||
FROM
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung,
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehrveranstaltung,
|
||||
lehre.tbl_projektbetreuer, public.tbl_person
|
||||
WHERE
|
||||
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_person.person_id=tbl_projektbetreuer.person_id AND
|
||||
tbl_lehrveranstaltung.studiengang_kz=".$db->db_add_param($studiengang_kz, FHC_INTEGER)." AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
";
|
||||
|
||||
if($semester!='')
|
||||
@@ -323,14 +322,13 @@ elseif($mitarbeiter_uid!='')
|
||||
$qry = "SELECT
|
||||
*
|
||||
FROM
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektbetreuer, public.tbl_person
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektbetreuer, public.tbl_person
|
||||
WHERE
|
||||
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_person.person_id=tbl_projektbetreuer.person_id AND
|
||||
tbl_projektbetreuer.person_id=".$db->db_add_param($mitarbeiter->person_id, FHC_INTEGER)." AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)."
|
||||
";
|
||||
}
|
||||
elseif($oe_kurzbz!='')
|
||||
@@ -338,15 +336,14 @@ elseif($oe_kurzbz!='')
|
||||
$qry = "SELECT
|
||||
*
|
||||
FROM
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektbetreuer,
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehrveranstaltung, lehre.tbl_projektbetreuer,
|
||||
public.tbl_person, lehre.tbl_lehrveranstaltung as lehrfach
|
||||
WHERE
|
||||
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.projektarbeit_id=tbl_projektbetreuer.projektarbeit_id AND
|
||||
tbl_lehreinheit.lehrfach_id=lehrfach.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=lehrfach.lehrveranstaltung_id AND
|
||||
tbl_person.person_id=tbl_projektbetreuer.person_id AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($semester_aktuell)." AND
|
||||
lehrfach.oe_kurzbz=".$db->db_add_param($oe_kurzbz)."
|
||||
";
|
||||
}
|
||||
|
||||
@@ -490,15 +490,13 @@ if($result = $db->db_query($qry))
|
||||
tbl_projektbetreuer.person_id,
|
||||
tbl_lehrveranstaltung.orgform_kurzbz
|
||||
FROM lehre.tbl_projektarbeit,
|
||||
lehre.tbl_lehreinheit,
|
||||
lehre.tbl_lehrveranstaltung,
|
||||
lehre.tbl_projektbetreuer,
|
||||
PUBLIC.tbl_person
|
||||
WHERE tbl_projektarbeit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
|
||||
AND tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
WHERE tbl_projektarbeit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id
|
||||
AND tbl_projektarbeit.projektarbeit_id = tbl_projektbetreuer.projektarbeit_id
|
||||
AND tbl_person.person_id = tbl_projektbetreuer.person_id
|
||||
AND tbl_lehreinheit.studiensemester_kurzbz = ".$db->db_add_param($studiensemester_kurzbz);
|
||||
AND tbl_projektarbeit.studiensemester_kurzbz = ".$db->db_add_param($studiensemester_kurzbz);
|
||||
|
||||
if($uid!=='')
|
||||
{
|
||||
|
||||
@@ -84,15 +84,14 @@ $qry = "SELECT
|
||||
ende, CASE WHEN freigegeben THEN 'Ja' ELSE 'Nein' END, gesperrtbis, themenbereich,
|
||||
tbl_projektarbeit.anmerkung, projektarbeit_id
|
||||
FROM
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung,
|
||||
lehre.tbl_projektarbeit, lehre.tbl_lehrveranstaltung,
|
||||
public.tbl_benutzer, public.tbl_person, lehre.tbl_projekttyp
|
||||
WHERE
|
||||
tbl_projektarbeit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_lehreinheit.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.student_uid = tbl_benutzer.uid AND
|
||||
tbl_benutzer.person_id = tbl_person.person_id AND
|
||||
tbl_projektarbeit.projekttyp_kurzbz = tbl_projekttyp.projekttyp_kurzbz AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz = ".$db->db_add_param($studiensemester_kurzbz)." AND
|
||||
tbl_projektarbeit.studiensemester_kurzbz = ".$db->db_add_param($studiensemester_kurzbz)." AND
|
||||
tbl_lehrveranstaltung.studiengang_kz = ".$db->db_add_param($studiengang_kz)." AND
|
||||
tbl_projektarbeit.projekttyp_kurzbz IN ('Bachelor','Diplom','Projekt')";
|
||||
|
||||
|
||||
@@ -4374,6 +4374,8 @@ if(!$error)
|
||||
$projektarbeit->titel = $_POST['titel'];
|
||||
$projektarbeit->titel_english = $_POST['titel_english'];
|
||||
$projektarbeit->lehreinheit_id = $_POST['lehreinheit_id'];
|
||||
$projektarbeit->lehrveranstaltung_id = $_POST['lehrveranstaltung_id'];
|
||||
$projektarbeit->studiensemester_kurzbz = $_POST['studiensemester_kurzbz'];
|
||||
$projektarbeit->student_uid = $_POST['student_uid'];
|
||||
$projektarbeit->firma_id = $_POST['firma_id'];
|
||||
$projektarbeit->note = $_POST['note'];
|
||||
|
||||
@@ -239,6 +239,7 @@ function StudentProjektarbeitDetailDisableFields(val)
|
||||
document.getElementById('student-projektarbeit-button-speichern').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-projekttyp').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-lehrveranstaltung').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-studiensemester').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-lehreinheit').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-firma').disabled=val;
|
||||
document.getElementById('student-projektarbeit-menulist-note').disabled=val;
|
||||
@@ -290,6 +291,7 @@ function StudentProjektarbeitResetFields()
|
||||
document.getElementById('student-projektarbeit-menulist-firma').value='';
|
||||
document.getElementById('student-projektarbeit-menulist-note').value='';
|
||||
document.getElementById('student-projektarbeit-checkbox-final').checked=true;
|
||||
document.getElementById('student-projektarbeit-menulist-studiensemester').value=getStudiensemester();
|
||||
|
||||
var stg_kz = document.getElementById('student-detail-menulist-studiengang_kz').value;
|
||||
|
||||
@@ -379,6 +381,7 @@ function StudentProjektarbeitAuswahl()
|
||||
lehreinheit_id = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#lehreinheit_id" ));
|
||||
lehrveranstaltung_id = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#lehrveranstaltung_id" ));
|
||||
lehreinheit_stsem = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#lehreinheit_stsem" ));
|
||||
projektarbeit_stsem = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#projektarbeit_stsem" ));
|
||||
student_uid = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#student_uid" ));
|
||||
firma_id = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#firma_id" ));
|
||||
note = getTargetHelper(dsource,subject,rdfService.GetResource( predicateNS + "#note" ));
|
||||
@@ -399,7 +402,7 @@ function StudentProjektarbeitAuswahl()
|
||||
|
||||
//Lehrveranstaltung DropDown laden
|
||||
var LvDropDown = document.getElementById('student-projektarbeit-menulist-lehrveranstaltung');
|
||||
url='<?php echo APP_ROOT;?>rdf/lehrveranstaltung.rdf.php?uid='+student_uid+"&projektarbeit=true&withlv="+lehrveranstaltung_id+"&"+gettimestamp();
|
||||
url='<?php echo APP_ROOT;?>rdf/lehrveranstaltung.rdf.php?uid='+student_uid+"&stg_kz="+stg_kz+"&projektarbeit=true&withlv="+lehrveranstaltung_id+"&"+gettimestamp();
|
||||
|
||||
//Alte DS entfernen
|
||||
var oldDatasources = LvDropDown.database.GetDataSources();
|
||||
@@ -420,7 +423,7 @@ function StudentProjektarbeitAuswahl()
|
||||
|
||||
// Lehreinheit Drop Down laden
|
||||
var LeDropDown = document.getElementById('student-projektarbeit-menulist-lehreinheit');
|
||||
url='<?php echo APP_ROOT;?>rdf/lehreinheit.rdf.php?lehrveranstaltung_id='+lehrveranstaltung_id+"&studiensemester_kurzbz="+lehreinheit_stsem+"&"+gettimestamp();
|
||||
url='<?php echo APP_ROOT;?>rdf/lehreinheit.rdf.php?lehrveranstaltung_id='+lehrveranstaltung_id+"&studiensemester_kurzbz="+projektarbeit_stsem+"&"+gettimestamp();
|
||||
|
||||
//Alte DS entfernen
|
||||
var oldDatasources = LeDropDown.database.GetDataSources();
|
||||
@@ -442,6 +445,7 @@ function StudentProjektarbeitAuswahl()
|
||||
//Werte setzen
|
||||
document.getElementById('student-projektarbeit-textbox-projektarbeit_id').value=projektarbeit_id;
|
||||
document.getElementById('student-projektarbeit-textbox-lehreinheit_stsem').value=lehreinheit_stsem;
|
||||
document.getElementById('student-projektarbeit-menulist-studiensemester').value=projektarbeit_stsem;
|
||||
document.getElementById('student-projektarbeit-menulist-projekttyp').value=projekttyp_kurzbz;
|
||||
document.getElementById('student-projektarbeit-menulist-lehrveranstaltung').value=lehrveranstaltung_id;
|
||||
document.getElementById('student-projektarbeit-menulist-lehreinheit').value=lehreinheit_id;
|
||||
@@ -539,6 +543,7 @@ function StudentProjektarbeitSpeichern()
|
||||
projektarbeit_id = document.getElementById('student-projektarbeit-textbox-projektarbeit_id').value;
|
||||
projekttyp_kurzbz = document.getElementById('student-projektarbeit-menulist-projekttyp').value;
|
||||
lehrveranstaltung_id = document.getElementById('student-projektarbeit-menulist-lehrveranstaltung').value;
|
||||
studiensemester_kurzbz = document.getElementById('student-projektarbeit-menulist-studiensemester').value;
|
||||
lehreinheit_id = document.getElementById('student-projektarbeit-menulist-lehreinheit').value;
|
||||
titel = document.getElementById('student-projektarbeit-textbox-titel').value;
|
||||
titel_english = document.getElementById('student-projektarbeit-textbox-titel_english').value;
|
||||
@@ -585,12 +590,18 @@ function StudentProjektarbeitSpeichern()
|
||||
return false;
|
||||
}
|
||||
|
||||
if(lehreinheit_id=='')
|
||||
if(lehrveranstaltung_id=='')
|
||||
{
|
||||
alert('Bitte einen LV-Teil auswaehlen');
|
||||
alert('Bitte eine Lehrveranstaltung auswaehlen');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(studiensemester_kurzbz=='')
|
||||
{
|
||||
alert('Bitte ein Studiensemester auswaehlen');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(isNaN(gesamtstunden))
|
||||
gesamtstunden=0;
|
||||
|
||||
@@ -603,6 +614,8 @@ function StudentProjektarbeitSpeichern()
|
||||
req.add('projekttyp_kurzbz', projekttyp_kurzbz );
|
||||
req.add('titel', titel);
|
||||
req.add('titel_english', titel_english);
|
||||
req.add('lehrveranstaltung_id', lehrveranstaltung_id);
|
||||
req.add('studiensemester_kurzbz', studiensemester_kurzbz);
|
||||
req.add('lehreinheit_id', lehreinheit_id);
|
||||
req.add('student_uid', student_uid);
|
||||
req.add('firma_id', firma_id);
|
||||
@@ -738,7 +751,7 @@ function StudentProjektarbeitLVAChange()
|
||||
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||
|
||||
lehrveranstaltung_id = document.getElementById('student-projektarbeit-menulist-lehrveranstaltung').value;
|
||||
studiensemester_kurzbz = getStudiensemester();
|
||||
studiensemester_kurzbz = document.getElementById('student-projektarbeit-menulist-studiensemester').value;
|
||||
|
||||
// Lehreinheit Drop Down laden
|
||||
var LeDropDown = document.getElementById('student-projektarbeit-menulist-lehreinheit');
|
||||
@@ -897,8 +910,8 @@ function StudentProjektbetreuerAuswahl()
|
||||
document.getElementById('student-projektbetreuer-textbox-person_id').value=person_id;
|
||||
document.getElementById('student-projektbetreuer-checkbox-neu').checked=false;
|
||||
|
||||
var lehreinheitstsem = document.getElementById('student-projektarbeit-textbox-lehreinheit_stsem').value;
|
||||
var default_stundensatz = StudentProjektbetreuerLoadStundensatz(person_id, lehreinheitstsem);
|
||||
var projektarbeitstsem = document.getElementById('student-projektarbeit-menulist-studiensemester').value;
|
||||
var default_stundensatz = StudentProjektbetreuerLoadStundensatz(person_id, projektarbeitstsem);
|
||||
|
||||
if (default_stundensatz != '')
|
||||
default_stundensatz = 'Stundensatz (Default '+default_stundensatz+'):';
|
||||
@@ -1410,9 +1423,10 @@ function StudentProjektbetreuerLoadStundensatz(person_id, studiensemester)
|
||||
function StudentProjektbetreuerLoadMitarbeiterDaten()
|
||||
{
|
||||
var person_id = MenulistGetSelectedValue('student-projektbetreuer-menulist-person');
|
||||
var lehreinheitstsem = document.getElementById('student-projektarbeit-textbox-lehreinheit_stsem').value;
|
||||
var projektarbeitstsem = document.getElementById('student-projektarbeit-menulist-studiensemester').value;
|
||||
|
||||
var stundensatz = StudentProjektbetreuerLoadStundensatz(person_id, lehreinheitstsem);
|
||||
|
||||
var stundensatz = StudentProjektbetreuerLoadStundensatz(person_id, projektarbeitstsem);
|
||||
|
||||
if (stundensatz != '')
|
||||
default_stundensatz = 'Stundensatz (Default '+stundensatz+'):';
|
||||
|
||||
@@ -104,6 +104,10 @@ $is_hidden = (!defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN')
|
||||
class="sortDirectionIndicator"
|
||||
sort="rdf:http://www.technikum-wien.at/projektarbeit/rdf#projektarbeit_id" />
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="student-projektarbeit-tree-lehrveranstaltung_id" label="LehrveranstaltungID" flex="2" hidden="true"
|
||||
class="sortDirectionIndicator"
|
||||
sort="rdf:http://www.technikum-wien.at/projektarbeit/rdf#lehrveranstaltung_id" />
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="student-projektarbeit-tree-lehreinheit_id" label="LehreinheitID" flex="2" hidden="true"
|
||||
class="sortDirectionIndicator"
|
||||
sort="rdf:http://www.technikum-wien.at/projektarbeit/rdf#lehreinheit_id" />
|
||||
@@ -131,7 +135,7 @@ $is_hidden = (!defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN')
|
||||
<treeitem uri="rdf:*">
|
||||
<treerow>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#bezeichnung"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#lehreinheit_stsem"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#projektarbeit_stsem"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#titel"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#note"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#beginn"/>
|
||||
@@ -141,6 +145,7 @@ $is_hidden = (!defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN')
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#themenbereich"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#anmerkung"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#projektarbeit_id"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#lehrveranstaltung_id"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#lehreinheit_id"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#student_uid"/>
|
||||
<treecell label="rdf:http://www.technikum-wien.at/projektarbeit/rdf#firma_id"/>
|
||||
@@ -249,6 +254,20 @@ $is_hidden = (!defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN')
|
||||
</template>
|
||||
</menulist>
|
||||
</row>
|
||||
<row>
|
||||
<label value="Studiensemester" control="student-projektarbeit-menulist-studiensemester"/>
|
||||
<menulist id="student-projektarbeit-menulist-studiensemester" disabled="true"
|
||||
datasources="<?php echo APP_ROOT ?>rdf/studiensemester.rdf.php?order=desc" flex="1"
|
||||
ref="http://www.technikum-wien.at/studiensemester/liste">
|
||||
<template>
|
||||
<menupopup>
|
||||
<menuitem value="rdf:http://www.technikum-wien.at/studiensemester/rdf#kurzbz"
|
||||
label="rdf:http://www.technikum-wien.at/studiensemester/rdf#kurzbz"
|
||||
uri="rdf:*"/>
|
||||
</menupopup>
|
||||
</template>
|
||||
</menulist>
|
||||
</row>
|
||||
<row>
|
||||
<label value="LV-Teil" control="student-projektarbeit-menulist-lehreinheit"/>
|
||||
<menulist id="student-projektarbeit-menulist-lehreinheit" disabled="true"
|
||||
|
||||
@@ -271,7 +271,8 @@ foreach ($uid_arr as $uid)
|
||||
'matr_nr' => $person->matr_nr,
|
||||
'ausstellungsdatum' => date('M.Y'),
|
||||
'gueltigbis' => $datum_obj->formatDatum($gueltigbis, 'd.m.Y'),
|
||||
'gueltigbis_3jahre' => date('d.m.Y', strtotime('+3 years'))
|
||||
'gueltigbis_3jahre' => date('d.m.Y', strtotime('+3 years')),
|
||||
'gueltigbis_2jahre' => date('d.m.Y', strtotime('+2 years'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
require("dotenv").config({ path: "tests/cypress/.env" });
|
||||
|
||||
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(", ")}`);
|
||||
|
||||
// each suite registers its own tasks and Cypress.env() values
|
||||
return require("./tests/cypress/suites/noten").setupNodeEvents(on, config);
|
||||
},
|
||||
},
|
||||
|
||||
env: {
|
||||
adminusername: process.env.USER_NAME,
|
||||
adminpassword: process.env.USER_PASSWORD,
|
||||
},
|
||||
});
|
||||
@@ -521,5 +521,63 @@ class adresse extends basis_db
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Laedt die österreichische Zustell Adresse einer Person
|
||||
* @param $person_id ID der Person
|
||||
* @return true wenn ok, false im Fehlerfall
|
||||
*/
|
||||
public function loadOesterreichischeZustellAdresse($person_id, $typ = null)
|
||||
{
|
||||
//Pruefen ob person_id eine gueltige Zahl ist
|
||||
if(!is_numeric($person_id) || $person_id == '')
|
||||
{
|
||||
$this->errormsg = 'PersonID muss eine Zahl sein';
|
||||
return false;
|
||||
}
|
||||
$typ_clause = '';
|
||||
if (isset($typ)) $typ_clause = "AND typ=".$this->db_add_param($typ);
|
||||
|
||||
//Daten aus der Datenbank lesen
|
||||
$qry = "SELECT * FROM public.tbl_adresse WHERE person_id=".$this->db_add_param($person_id, FHC_INTEGER, false)."
|
||||
AND nation = 'A'
|
||||
{$typ_clause}
|
||||
ORDER BY zustelladresse DESC, adresse_id DESC LIMIT 1";
|
||||
|
||||
if(!$this->db_query($qry))
|
||||
{
|
||||
$this->errormsg = 'Fehler bei einer Datenbankabfrage';
|
||||
return false;
|
||||
}
|
||||
|
||||
if($row = $this->db_fetch_object())
|
||||
{
|
||||
$this->adresse_id = $row->adresse_id;
|
||||
$this->heimatadresse = $this->db_parse_bool($row->heimatadresse);
|
||||
$this->zustelladresse = $this->db_parse_bool($row->zustelladresse);
|
||||
$this->gemeinde = $row->gemeinde;
|
||||
$this->name = $row->name;
|
||||
$this->nation = $row->nation;
|
||||
$this->ort = $row->ort;
|
||||
$this->person_id = $row->person_id;
|
||||
$this->plz = $row->plz;
|
||||
$this->strasse = $row->strasse;
|
||||
$this->typ = $row->typ;
|
||||
$this->updateamum = $row->updateamum;
|
||||
$this->updatevon = $row->updatevon;
|
||||
$this->insertamum = $row->insertamum;
|
||||
$this->insertvon = $row->insertvon;
|
||||
$this->firma_id = $row->firma_id;
|
||||
$this->rechnungsadresse = $this->db_parse_bool($row->rechnungsadresse);
|
||||
$this->anmerkung = $row->anmerkung;
|
||||
$this->co_name = $row->co_name;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Es ist kein Datensatz mit dieser ID vorhanden';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -48,7 +48,7 @@ class bisarchiv extends basis_db
|
||||
*/
|
||||
protected function validate()
|
||||
{
|
||||
if($this->studiensemster_kurzbz == null || mb_strlen($this->studiensemster_kurzbz) > 6)
|
||||
if($this->studiensemester_kurzbz == null || mb_strlen($this->studiensemester_kurzbz) > 6)
|
||||
{
|
||||
$this->errormsg = "Studiensemester ist ungueltig";
|
||||
return false;
|
||||
@@ -107,7 +107,7 @@ class bisarchiv extends basis_db
|
||||
return false;
|
||||
|
||||
$qry = "INSERT INTO bis.tbl_archiv (studiensemester_kurzbz, meldung, html, studiengang_kz, insertamum, insertvon, typ) VALUES ("
|
||||
. $this->db_add_param($this->studiensemster_kurzbz) . ","
|
||||
. $this->db_add_param($this->studiensemester_kurzbz) . ","
|
||||
. $this->db_add_param($this->meldung) . ","
|
||||
. $this->db_add_param($this->html) . ","
|
||||
. $this->db_add_param($this->studiengang_kz) . ","
|
||||
|
||||
@@ -2088,7 +2088,7 @@ class lehrveranstaltung extends basis_db
|
||||
/**
|
||||
* lädt die Lehrveranstaltungen zum zugehörigen Mitarbeiter
|
||||
* @param String $uid User ID des Mitarbeiters
|
||||
* @param String $studiensemster_kurzbz Kurzbezeichnung des Studiensemesters
|
||||
* @param String $studiensemester_kurzbz Kurzbezeichnung des Studiensemesters
|
||||
*/
|
||||
public function getLVByMitarbeiter($uid, $studiensemester_kurzbz = null)
|
||||
{
|
||||
@@ -2911,5 +2911,176 @@ class lehrveranstaltung extends basis_db
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filtert die geladenen Lehrveranstaltungen gegen den aktuellen Studienplan des Studenten.
|
||||
* Ermittelt den Studienplan über den Prestudent-Status (aktuellster Eintrag) und gleicht
|
||||
* die vorhandenen IDs mit der Tabelle tbl_studienplan_lehrveranstaltung ab.
|
||||
* Die interne Liste wird nur bei gefundenen Treffern aktualisiert.
|
||||
*
|
||||
* @param string $student_uid Student uid.
|
||||
* @return bool True bei erfolgreicher Abwicklung oder leeren Ausgangsdaten, False bei Datenbankfehlern.
|
||||
*/
|
||||
public function checkLvaAgainstStudentCurrentStudienplan($student_uid) {
|
||||
$qryStudent = "SELECT prestudent_id FROM tbl_student WHERE student_uid = ".$this->db_add_param($student_uid)."";
|
||||
|
||||
if($result = $this->db_query($qryStudent))
|
||||
{
|
||||
if($row = $this->db_fetch_object($result))
|
||||
{
|
||||
$prestudent_id = $row->prestudent_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler beim Ermitteln der des aktuellen studienplan für studenten über prestudent';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg='Fehler bei Datenbankabfrage ' .$this->db_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
$qryHistory = "SELECT studienplan_id
|
||||
FROM public.tbl_prestudentstatus
|
||||
WHERE prestudent_id = ".$this->db_add_param($prestudent_id)."
|
||||
ORDER BY public.tbl_prestudentstatus.datum DESC";
|
||||
if($result = $this->db_query($qryHistory))
|
||||
{
|
||||
if($row = $this->db_fetch_object($result))
|
||||
{
|
||||
$studienplan_id = $row->studienplan_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg = 'Fehler beim Ermitteln der des aktuellen studienplan für studenten über prestudentstatus';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg='Fehler bei Datenbankabfrage ' .$this->db_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
// needs to have lva_ids from previous query in this context
|
||||
$lvsIDs = array_column($this->lehrveranstaltungen, 'lehrveranstaltung_id');
|
||||
|
||||
if (empty($lvsIDs)) {
|
||||
// exit without modifying object state if no lva_id to query by are found
|
||||
return true;
|
||||
}
|
||||
|
||||
$ids = $this->db_implode4SQL($lvsIDs);
|
||||
|
||||
$qry = "SELECT tbl_lehrveranstaltung.*,
|
||||
tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id,
|
||||
tbl_studienplan_lehrveranstaltung.semester as stpllv_semester,
|
||||
tbl_studienplan_lehrveranstaltung.pflicht as stpllv_pflicht,
|
||||
tbl_studienplan_lehrveranstaltung.koordinator as stpllv_koordinator,
|
||||
tbl_studienplan_lehrveranstaltung.studienplan_lehrveranstaltung_id_parent,
|
||||
tbl_studienplan_lehrveranstaltung.sort stpllv_sort,
|
||||
tbl_studienplan_lehrveranstaltung.curriculum,
|
||||
tbl_studienplan_lehrveranstaltung.export,
|
||||
tbl_studienplan_lehrveranstaltung.genehmigung
|
||||
FROM lehre.tbl_lehrveranstaltung
|
||||
JOIN lehre.tbl_studienplan_lehrveranstaltung
|
||||
USING(lehrveranstaltung_id)
|
||||
WHERE tbl_studienplan_lehrveranstaltung.studienplan_id = ".$this->db_add_param($studienplan_id)."
|
||||
AND tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id IN (".$ids.");";
|
||||
|
||||
if($result = $this->db_query($qry))
|
||||
{
|
||||
// reset the lva array and fill it with the new set
|
||||
$temp_lvas = array();
|
||||
while($row = $this->db_fetch_object($result))
|
||||
{
|
||||
$obj = new lehrveranstaltung();
|
||||
|
||||
$obj->lehrveranstaltung_id = $row->lehrveranstaltung_id;
|
||||
$obj->studiengang_kz = $row->studiengang_kz;
|
||||
$obj->bezeichnung = $row->bezeichnung;
|
||||
$obj->kurzbz = $row->kurzbz;
|
||||
$obj->lehrform_kurzbz = $row->lehrform_kurzbz;
|
||||
$obj->semester = $row->semester;
|
||||
$obj->ects = $row->ects;
|
||||
$obj->semesterstunden = $row->semesterstunden;
|
||||
$obj->anmerkung = $row->anmerkung;
|
||||
$obj->lehre = $this->db_parse_bool($row->lehre);
|
||||
$obj->lehreverzeichnis = $row->lehreverzeichnis;
|
||||
$obj->aktiv = $this->db_parse_bool($row->aktiv);
|
||||
$obj->ext_id = $row->ext_id;
|
||||
$obj->insertamum = $row->insertamum;
|
||||
$obj->insertvon = $row->insertvon;
|
||||
$obj->planfaktor = $row->planfaktor;
|
||||
$obj->planlektoren = $row->planlektoren;
|
||||
$obj->planpersonalkosten = $row->planpersonalkosten;
|
||||
$obj->plankostenprolektor = $row->plankostenprolektor;
|
||||
$obj->updateamum = $row->updateamum;
|
||||
$obj->updatevon = $row->updatevon;
|
||||
$obj->sprache = $row->sprache;
|
||||
$obj->sort = $row->sort;
|
||||
$obj->incoming = $row->incoming;
|
||||
$obj->zeugnis = $this->db_parse_bool($row->zeugnis);
|
||||
$obj->projektarbeit = $this->db_parse_bool($row->projektarbeit);
|
||||
$obj->koordinator = $row->koordinator;
|
||||
$obj->bezeichnung_english = $row->bezeichnung_english;
|
||||
$obj->orgform_kurzbz = $row->orgform_kurzbz;
|
||||
$obj->lehrtyp_kurzbz = $row->lehrtyp_kurzbz;
|
||||
$obj->lehrmodus_kurzbz = $row->lehrmodus_kurzbz;
|
||||
$obj->oe_kurzbz = $row->oe_kurzbz;
|
||||
$obj->raumtyp_kurzbz = $row->raumtyp_kurzbz;
|
||||
$obj->anzahlsemester = $row->anzahlsemester;
|
||||
$obj->semesterwochen = $row->semesterwochen;
|
||||
$obj->lvnr = $row->lvnr;
|
||||
$obj->semester_alternativ = $row->semester_alternativ;
|
||||
$obj->farbe = $row->farbe;
|
||||
$obj->lehrveranstaltung_template_id = $row->lehrveranstaltung_template_id;
|
||||
$obj->stpllv_sort = $row->stpllv_sort;
|
||||
$obj->benotung = $this->db_parse_bool($row->benotung);
|
||||
$obj->lvinfo = $this->db_parse_bool($row->lvinfo);
|
||||
$obj->lehrauftrag = $this->db_parse_bool($row->lehrauftrag);
|
||||
$obj->evaluierung = $this->db_parse_bool($row->evaluierung);
|
||||
|
||||
$obj->bezeichnung_arr['German'] = $row->bezeichnung;
|
||||
$obj->bezeichnung_arr['English'] = $row->bezeichnung_english;
|
||||
if ($obj->bezeichnung_arr['English'] == '')
|
||||
$obj->bezeichnung_arr['English'] = $obj->bezeichnung_arr['German'];
|
||||
|
||||
$obj->sws = $row->sws;
|
||||
$obj->lvs = $row->lvs;
|
||||
$obj->alvs = $row->alvs;
|
||||
$obj->lvps = $row->lvps;
|
||||
$obj->las = $row->las;
|
||||
|
||||
$obj->stpllv_semester = $row->stpllv_semester;
|
||||
$obj->stpllv_pflicht = $this->db_parse_bool($row->stpllv_pflicht);
|
||||
$obj->stpllv_koordinator = $row->stpllv_koordinator;
|
||||
$obj->studienplan_lehrveranstaltung_id = $row->studienplan_lehrveranstaltung_id;
|
||||
$obj->studienplan_lehrveranstaltung_id_parent = $row->studienplan_lehrveranstaltung_id_parent;
|
||||
$obj->curriculum = $this->db_parse_bool($row->curriculum);
|
||||
$obj->export = $this->db_parse_bool($row->export);
|
||||
$obj->genehmigung = $this->db_parse_bool($row->genehmigung);
|
||||
$obj->new = false;
|
||||
|
||||
$temp_lvas[] = $obj;
|
||||
}
|
||||
|
||||
// Only update the class property if we actually found matching records.
|
||||
// If $temp_lvas is empty, $this->lehrveranstaltungen remains unchanged.
|
||||
if (!empty($temp_lvas)) {
|
||||
$this->lehrveranstaltungen = $temp_lvas;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->errormsg='Fehler bei Datenbankabfrage ' .$this->db_last_error();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -37,6 +37,8 @@ class projektarbeit extends basis_db
|
||||
public $titel; // string
|
||||
public $titel_english; // string
|
||||
public $lehreinheit_id; // integer
|
||||
public $lehrveranstaltung_id; // integer
|
||||
public $studiensemester_kurzbz; // string
|
||||
public $student_uid; // integer
|
||||
public $firma_id; // integer
|
||||
public $note; // integer
|
||||
@@ -129,6 +131,8 @@ class projektarbeit extends basis_db
|
||||
$this->titel = $row->titel;
|
||||
$this->titel_english = $row->titel_english;
|
||||
$this->lehreinheit_id = $row->lehreinheit_id;
|
||||
$this->lehrveranstaltung_id = $row->lehrveranstaltung_id;
|
||||
$this->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
||||
$this->student_uid = $row->student_uid;
|
||||
$this->firma_id = $row->firma_id;
|
||||
$this->note = $row->note;
|
||||
@@ -178,9 +182,13 @@ class projektarbeit extends basis_db
|
||||
{
|
||||
$this->errormsg='Projekttyp_kurzbz darf nicht NULL sein!';
|
||||
}
|
||||
if ($this->lehreinheit_id==null)
|
||||
if ($this->lehrveranstaltung_id==null)
|
||||
{
|
||||
$this->errormsg='Lehreinheit_id darf nicht NULL sein!';
|
||||
$this->errormsg='Lehrveranstaltung_id darf nicht NULL sein!';
|
||||
}
|
||||
if ($this->studiensemester_kurzbz==null)
|
||||
{
|
||||
$this->errormsg='Studiensemester_kurzbz darf nicht NULL sein!';
|
||||
}
|
||||
if(mb_strlen($this->projekttyp_kurzbz)>16)
|
||||
{
|
||||
@@ -261,12 +269,15 @@ class projektarbeit extends basis_db
|
||||
{
|
||||
//Neuen Datensatz einfuegen
|
||||
|
||||
$qry='BEGIN; INSERT INTO lehre.tbl_projektarbeit (projekttyp_kurzbz, titel, lehreinheit_id, student_uid, firma_id, note, punkte,
|
||||
$qry='BEGIN; INSERT INTO lehre.tbl_projektarbeit (projekttyp_kurzbz, titel, lehreinheit_id,
|
||||
lehrveranstaltung_id, studiensemester_kurzbz, student_uid, firma_id, note, punkte,
|
||||
beginn, ende, faktor, freigegeben, gesperrtbis, stundensatz, gesamtstunden, themenbereich, anmerkung,
|
||||
insertamum, insertvon, updateamum, updatevon, titel_english, final) VALUES('.
|
||||
$this->db_add_param($this->projekttyp_kurzbz).', '.
|
||||
$this->db_add_param($this->titel).', '.
|
||||
$this->db_add_param($this->lehreinheit_id, FHC_INTEGER).', '.
|
||||
$this->db_add_param($this->lehrveranstaltung_id, FHC_INTEGER).', '.
|
||||
$this->db_add_param($this->studiensemester_kurzbz).', '.
|
||||
$this->db_add_param($this->student_uid).', '.
|
||||
$this->db_add_param($this->firma_id, FHC_INTEGER).', '.
|
||||
$this->db_add_param($this->note).', '.
|
||||
@@ -301,6 +312,8 @@ class projektarbeit extends basis_db
|
||||
'titel='.$this->db_add_param($this->titel).', '.
|
||||
'titel_english='.$this->db_add_param($this->titel_english).', '.
|
||||
'lehreinheit_id='.$this->db_add_param($this->lehreinheit_id, FHC_INTEGER).', '.
|
||||
'lehrveranstaltung_id='.$this->db_add_param($this->lehrveranstaltung_id, FHC_INTEGER).', '.
|
||||
'studiensemester_kurzbz='.$this->db_add_param($this->studiensemester_kurzbz).', '.
|
||||
'student_uid='.$this->db_add_param($this->student_uid).', '.
|
||||
'firma_id='.$this->db_add_param($this->firma_id, FHC_INTEGER).', '.
|
||||
'note='.$this->db_add_param($this->note).', '.
|
||||
@@ -406,6 +419,8 @@ class projektarbeit extends basis_db
|
||||
$obj->titel = $row->titel;
|
||||
$obj->titel_english = $row->titel_english;
|
||||
$obj->lehreinheit_id = $row->lehreinheit_id;
|
||||
$obj->lehrveranstaltung_id = $row->lehrveranstaltung_id;
|
||||
$obj->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
||||
$obj->student_uid = $row->student_uid;
|
||||
$obj->firma_id = $row->firma_id;
|
||||
$obj->note = $row->note;
|
||||
@@ -449,14 +464,13 @@ class projektarbeit extends basis_db
|
||||
tbl_projektarbeit.* , tbl_projekttyp.bezeichnung
|
||||
FROM
|
||||
lehre.tbl_projektarbeit
|
||||
JOIN
|
||||
lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung
|
||||
JOIN lehre.tbl_projekttyp USING (projekttyp_kurzbz)
|
||||
JOIN lehre.tbl_lehrveranstaltung ON (lehre.tbl_projektarbeit.lehrveranstaltung_id = lehre.tbl_lehrveranstaltung.lehrveranstaltung_id)
|
||||
|
||||
WHERE
|
||||
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
|
||||
tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_projektarbeit.lehrveranstaltung_id=tbl_lehrveranstaltung.lehrveranstaltung_id AND
|
||||
tbl_lehrveranstaltung.studiengang_kz=".$this->db_add_param($studiengang_kz, FHC_INTEGER)." AND
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz);
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz);
|
||||
|
||||
if($this->db_query($qry))
|
||||
{
|
||||
@@ -470,6 +484,8 @@ class projektarbeit extends basis_db
|
||||
$obj->titel = $row->titel;
|
||||
$obj->titel_english = $row->titel_english;
|
||||
$obj->lehreinheit_id = $row->lehreinheit_id;
|
||||
$obj->lehrveranstaltung_id = $row->lehrveranstaltung_id;
|
||||
$obj->studiensemester_kurzbz = $row->studiensemester_kurzbz;
|
||||
$obj->student_uid = $row->student_uid;
|
||||
$obj->firma_id = $row->firma_id;
|
||||
$obj->note = $row->note;
|
||||
@@ -534,7 +550,6 @@ class projektarbeit extends basis_db
|
||||
pa.projekttyp_kurzbz
|
||||
FROM
|
||||
lehre.tbl_projektarbeit pa
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
JOIN public.tbl_studiensemester sem USING(studiensemester_kurzbz)
|
||||
LEFT JOIN (
|
||||
SELECT
|
||||
|
||||
+11
-15
@@ -121,7 +121,7 @@ class vertrag extends basis_db
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
vertrag_id=tbl_vertrag.vertrag_id
|
||||
AND studiensemester_kurzbz in (SELECT studiensemester_kurzbz FROM public.tbl_studiensemester WHERE start>=".$this->db_add_param($datum).")
|
||||
AND studiensemester_kurzbz in (SELECT studiensemester_kurzbz FROM public.tbl_studiensemester WHERE start>".$this->db_add_param($datum).")
|
||||
)
|
||||
)";
|
||||
}
|
||||
@@ -371,14 +371,14 @@ class vertrag extends basis_db
|
||||
null::integer as pruefung_id,
|
||||
projektarbeit_id,
|
||||
(tbl_projektbetreuer.stunden*tbl_projektbetreuer.stundensatz) as betrag,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
tbl_projektbetreuer.betreuerart_kurzbz,
|
||||
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
|
||||
as bezeichnung
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
|
||||
WHERE
|
||||
tbl_projektbetreuer.person_id=".$this->db_add_param($person_id, FHC_INTEGER)."
|
||||
AND vertrag_id IS NULL";
|
||||
@@ -461,9 +461,8 @@ class vertrag extends basis_db
|
||||
OR
|
||||
EXISTS (SELECT 1 FROM lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
tbl_lehreinheit.studiensemester_kurzbz=".$db->db_add_param($studiensemester_kurzbz)."
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$db->db_add_param($studiensemester_kurzbz)."
|
||||
AND tbl_projektbetreuer.person_id=tbl_person.person_id
|
||||
AND tbl_projektbetreuer.vertrag_id IS NULL
|
||||
)
|
||||
@@ -535,12 +534,12 @@ class vertrag extends basis_db
|
||||
UNION
|
||||
SELECT
|
||||
'Betreuung' as type,
|
||||
tbl_projektarbeit.lehreinheit_id as lehreinheit_id,
|
||||
NULL as lehreinheit_id,
|
||||
null as mitarbeiter_uid,
|
||||
null::integer as pruefung_id,
|
||||
projektarbeit_id,
|
||||
(tbl_projektbetreuer.stunden*tbl_projektbetreuer.stundensatz) as betrag,
|
||||
tbl_lehreinheit.studiensemester_kurzbz,
|
||||
tbl_projektarbeit.studiensemester_kurzbz,
|
||||
tbl_projektbetreuer.betreuerart_kurzbz,
|
||||
(SELECT nachname || ' ' || vorname FROM public.tbl_person JOIN public.tbl_benutzer USING(person_id) WHERE uid=tbl_projektarbeit.student_uid)
|
||||
as bezeichnung,
|
||||
@@ -549,7 +548,6 @@ class vertrag extends basis_db
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
JOIN lehre.tbl_vertrag USING (vertrag_id)
|
||||
WHERE
|
||||
vertrag_id=".$this->db_add_param($vertrag_id, FHC_INTEGER).";";
|
||||
@@ -942,17 +940,16 @@ class vertrag extends basis_db
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
vertrag_id=tbl_vertrag.vertrag_id
|
||||
AND studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
AND lehre.tbl_lehreinheit.studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
OR
|
||||
EXISTS (SELECT
|
||||
1
|
||||
FROM
|
||||
lehre.tbl_projektbetreuer
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
vertrag_id=tbl_vertrag.vertrag_id
|
||||
AND studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
AND lehre.tbl_projektarbeit.studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
OR
|
||||
(NOT EXISTS (SELECT
|
||||
1
|
||||
@@ -980,7 +977,7 @@ class vertrag extends basis_db
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
vertrag_id=tbl_vertrag.vertrag_id
|
||||
AND studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
AND lehre.tbl_lehreinheit.studiensemester_kurzbz=".$this->db_add_param($stsem).")
|
||||
)
|
||||
AND tbl_benutzer.uid=".$this->db_add_param($mitarbeiter_uid);
|
||||
|
||||
@@ -1077,7 +1074,7 @@ class vertrag extends basis_db
|
||||
JOIN lehre.tbl_lehreinheitmitarbeiter USING(vertrag_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz)."
|
||||
lehre.tbl_lehreinheit.studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz)."
|
||||
AND tbl_lehreinheitmitarbeiter.mitarbeiter_uid NOT IN(SELECT uid FROM public.tbl_benutzer WHERE person_id=tbl_vertrag.person_id)
|
||||
UNION
|
||||
SELECT
|
||||
@@ -1086,9 +1083,8 @@ class vertrag extends basis_db
|
||||
lehre.tbl_vertrag
|
||||
JOIN lehre.tbl_projektbetreuer USING(vertrag_id)
|
||||
JOIN lehre.tbl_projektarbeit USING(projektarbeit_id)
|
||||
JOIN lehre.tbl_lehreinheit USING(lehreinheit_id)
|
||||
WHERE
|
||||
studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz)."
|
||||
tbl_projektarbeit.studiensemester_kurzbz=".$this->db_add_param($studiensemester_kurzbz)."
|
||||
AND tbl_projektbetreuer.person_id!=tbl_vertrag.person_id";
|
||||
|
||||
if($result = $this->db_query($qry))
|
||||
|
||||
@@ -748,17 +748,14 @@ or not exists
|
||||
UNION
|
||||
SELECT sum(pb.stunden) AS semstunden
|
||||
FROM
|
||||
lehre.tbl_projektarbeit pa,
|
||||
lehre.tbl_projektbetreuer pb,
|
||||
public.tbl_benutzer b,
|
||||
lehre.tbl_lehreinheit l
|
||||
JOIN
|
||||
lehre.tbl_lehrveranstaltung lv using (lehrveranstaltung_id)
|
||||
JOIN
|
||||
public.tbl_studiengang s using (studiengang_kz)
|
||||
lehre.tbl_projektarbeit pa
|
||||
JOIN lehre.tbl_projektbetreuer pb ON(pa.projektarbeit_id = pb.projektarbeit_id)
|
||||
JOIN public.tbl_benutzer b ON(pb.person_id = b.person_id)
|
||||
JOIN lehre.tbl_lehreinheit l ON(pa.lehrveranstaltung_id = l.lehrveranstaltung_id AND pa.studiensemester_kurzbz = l.studiensemester_kurzbz)
|
||||
JOIN lehre.tbl_lehrveranstaltung lv ON (l.lehrveranstaltung_id = lv.lehrveranstaltung_id)
|
||||
JOIN public.tbl_studiengang s USING (studiengang_kz)
|
||||
|
||||
WHERE
|
||||
pa.lehreinheit_id = l.lehreinheit_id AND
|
||||
pb.projektarbeit_id = pa.projektarbeit_id AND
|
||||
pb.person_id = b.person_id AND
|
||||
b.uid = ".$this->db_add_param($user)." AND
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"scripts": {
|
||||
"noten:check": "node tests/cypress/tools/dbCheck.js noten",
|
||||
"noten:api": "cypress run --spec \"tests/cypress/e2e/specs/api/**/*.cy.js\"",
|
||||
"noten:ui": "cypress run --browser chrome --spec \"tests/cypress/e2e/specs/ui/**/*.cy.js\""
|
||||
},
|
||||
"//": [
|
||||
"pg: the suite resets and seeds the test database directly (tasks/db.js, tools/dbCheck.js)",
|
||||
"dotenv: cypress.config.js and the suite read URL, accounts and DB access from the .env files"
|
||||
],
|
||||
"dependencies": {
|
||||
"cypress": "^15.21.1",
|
||||
"dotenv": "^17.4.2",
|
||||
"pg": "^8.13.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
/* Pinned columns (tableLayout.js). The four columns that can be pinned always have .sticky-col.
|
||||
A `sticky-on-<field>` class on #notentable pins one of them, and --sl-<field> is its left offset,
|
||||
so that the pinned columns stand next to each other. */
|
||||
#notentable .tabulator-header .tabulator-col.sticky-col,
|
||||
#notentable .tabulator-tableholder .tabulator-row .tabulator-cell.sticky-col {
|
||||
background-color: #fff; /* the cells below do not show through */
|
||||
}
|
||||
|
||||
/* also on row hover */
|
||||
#notentable .tabulator-row:hover .tabulator-cell.sticky-col {
|
||||
background-color: #ccc;
|
||||
}
|
||||
|
||||
/* the container pins a column */
|
||||
#notentable.sticky-on-selectCol .sticky-col[tabulator-field="selectCol"],
|
||||
#notentable.sticky-on-uid .sticky-col[tabulator-field="uid"],
|
||||
#notentable.sticky-on-vorname .sticky-col[tabulator-field="vorname"],
|
||||
#notentable.sticky-on-nachname .sticky-col[tabulator-field="nachname"] {
|
||||
position: sticky;
|
||||
z-index: 10; /* above the Pruefung columns */
|
||||
border-right: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#notentable.sticky-on-selectCol .sticky-col[tabulator-field="selectCol"] { left: var(--sl-selectCol, 0); }
|
||||
#notentable.sticky-on-uid .sticky-col[tabulator-field="uid"] { left: var(--sl-uid, 0); }
|
||||
#notentable.sticky-on-vorname .sticky-col[tabulator-field="vorname"] { left: var(--sl-vorname, 0); }
|
||||
#notentable.sticky-on-nachname .sticky-col[tabulator-field="nachname"] { left: var(--sl-nachname, 0); }
|
||||
|
||||
|
||||
/* the content of a cell, from the formatters in Benotungstool.js */
|
||||
#notentable .cell-start,
|
||||
#notentable .cell-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#notentable .cell-start { justify-content: start; }
|
||||
#notentable .cell-center { justify-content: center; }
|
||||
|
||||
/* a Zeugnisnote that differs from the LV-Note */
|
||||
#notentable .zeugnisnote-differs {
|
||||
color: red;
|
||||
border: 1px solid red;
|
||||
}
|
||||
|
||||
/* a proposal that the user cannot change */
|
||||
#notentable .proposal-locked {
|
||||
color: gray;
|
||||
font-style: italic;
|
||||
background-color: #f0f0f0;
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
user-select: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
#notentable .teilnote-negativ { color: red; }
|
||||
#notentable .freigegeben-icon { color: green; }
|
||||
#notentable .mail-icon { color: #00649C; }
|
||||
|
||||
|
||||
/* the editable proposal columns */
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="proposed_punkte"] {
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 157, 0.73);
|
||||
}
|
||||
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="proposed_note"] {
|
||||
position: relative;
|
||||
background-color: rgba(255, 255, 157, 0.73);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#notentable .tabulator-tableholder .tabulator-editable[tabulator-field="proposed_note"]::after {
|
||||
content: "▾";
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(0deg);
|
||||
transform-origin: center;
|
||||
color: rgba(120, 120, 60, 0.85);
|
||||
font-size: 0.9rem;
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
|
||||
/* the arrow points up while the list is open */
|
||||
#notentable .tabulator-tableholder .tabulator-cell.tabulator-editing[tabulator-field="proposed_note"]::after {
|
||||
transform: translateY(-50%) rotate(180deg);
|
||||
}
|
||||
|
||||
/* A Pruefung cell: fixed tracks for Note | date | action, so that they align in all rows. */
|
||||
.pruefung-cell {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 6.5rem; /* Note | action */
|
||||
align-items: center;
|
||||
column-gap: 0.5rem;
|
||||
height: 100%;
|
||||
padding-left: 44px;
|
||||
padding-right: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pruefung-cell.with-datum {
|
||||
grid-template-columns: minmax(0, 1fr) 4.75rem 6.5rem; /* Note | datum | action */
|
||||
}
|
||||
|
||||
.pruefung-cell.without-action {
|
||||
grid-template-columns: minmax(0, 1fr); /* Note */
|
||||
}
|
||||
|
||||
.pruefung-cell.without-action.with-datum {
|
||||
grid-template-columns: minmax(0, 1fr) 4.75rem; /* Note | datum */
|
||||
}
|
||||
|
||||
.pruefung-cell .pruefung-note {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* the reason instead of a button, for example after a pass */
|
||||
.pruefung-cell .pruefung-hint {
|
||||
grid-column: 1 / -1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
opacity: 0.7;
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.pruefung-cell .pruefung-datum {
|
||||
font-size: 0.75rem;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* always the last track, also in an empty cell with only the add button */
|
||||
.pruefung-cell .pruefung-action {
|
||||
grid-column: -2 / -1;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.pruefung-cell .pruefung-action .btn {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pruefung-badge::before {
|
||||
content: attr(data-antritt);
|
||||
position: absolute;
|
||||
left: 6px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 20px;
|
||||
height: 20px;
|
||||
padding: 0 5px;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pruefung-badge.antritt-1::before { background: #0072B2; }
|
||||
.pruefung-badge.antritt-2::before { background: #E69F00; }
|
||||
.pruefung-badge.antritt-3::before { background: #CC79A7; }
|
||||
.pruefung-badge.antritt-k::before { background: #D55E00; }
|
||||
.pruefung-badge.antritt-none::before { background: #767676; }
|
||||
@@ -62,3 +62,16 @@
|
||||
top:13%;"
|
||||
z-index: 104; font-size: 1rem; width: 2.5rem; height: 2.5rem; opacity:0; transition: opacity 0.2s; top:13%;"
|
||||
}*/
|
||||
|
||||
.tag-hover:hover {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.green {
|
||||
background-color: #e9ecef;
|
||||
}
|
||||
|
||||
.btn-hover {
|
||||
--bs-btn-hover-bg: #e9ecef; /* Neue Hintergrundfarbe beim Hover */
|
||||
--bs-btn-hover-border-color: #e9ecef; /* Neue Rahmenfarbe beim Hover */
|
||||
}
|
||||
|
||||
@@ -107,4 +107,9 @@
|
||||
|
||||
.gesperrtoption {
|
||||
color: gray;
|
||||
}
|
||||
|
||||
#onboardingRow
|
||||
{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
@@ -145,3 +145,8 @@
|
||||
float: right;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.btn-hover {
|
||||
--bs-btn-hover-bg: #e9ecef;
|
||||
--bs-btn-hover-border-color: #e9ecef;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Copyright (C) 2025 fhcomplete.org
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
export default {
|
||||
getCisConfig() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getCisConfig'
|
||||
};
|
||||
},
|
||||
getNoten() {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getNoten'
|
||||
};
|
||||
},
|
||||
getBenotungstoolContext(sem_kurzbz, lv_id = null) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getBenotungstoolContext',
|
||||
params: { sem_kurzbz, lv_id }
|
||||
};
|
||||
},
|
||||
getLvForStudiengang(studiengang_kz, sem_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getLvForStudiengang',
|
||||
params: { studiengang_kz, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
getLehreinheitenForLv(lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getLehreinheitenForLv',
|
||||
params: { lv_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
getLektorenForLehreinheit(lv_id, sem_kurzbz, lehreinheit_id) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getLektorenForLehreinheit',
|
||||
params: { lv_id, sem_kurzbz, lehreinheit_id }
|
||||
};
|
||||
},
|
||||
// -> { students, domain }
|
||||
getStudentenNoten(lv_id, sem_kurzbz) {
|
||||
return {
|
||||
method: 'get',
|
||||
url: '/api/frontend/v1/Noten/getStudentenNoten',
|
||||
params: { lv_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
getNoteByPunkte(lv_id, sem_kurzbz, punkte) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/getNoteByPunkte',
|
||||
params: { lv_id, sem_kurzbz, punkte }
|
||||
};
|
||||
},
|
||||
|
||||
// Each write answers { <uid>: { lvgesamtnote, verlauf, pruefung } }. A rejected row of a bulk
|
||||
// write is { <uid>: { error: { code, message } } }.
|
||||
|
||||
// datum: the day of Antritt 1 (YYYY-MM-DD); without it the server takes today
|
||||
saveLvNote(lv_id, sem_kurzbz, student_uid, note, punkte, datum) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveLvNote',
|
||||
params: { lv_id, sem_kurzbz, student_uid, note, punkte, datum }
|
||||
};
|
||||
},
|
||||
// lv_noten: [{ uid, note, punkte }]
|
||||
importLvNoten(lv_id, sem_kurzbz, lv_noten) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/importLvNoten',
|
||||
params: { lv_id, sem_kurzbz, lv_noten }
|
||||
};
|
||||
},
|
||||
// pruefung: { pruefung_id (null = a new Pruefung), lehreinheit_id, datum, note, punkte, mitarbeiter_uid }
|
||||
savePruefung(lv_id, sem_kurzbz, student_uid, pruefung) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/savePruefung',
|
||||
params: { lv_id, sem_kurzbz, student_uid, ...pruefung }
|
||||
};
|
||||
},
|
||||
// students: [{ uid, lehreinheit_id }]; pruefung: { datum, note, punkte, mitarbeiter_uid }
|
||||
createPruefungen(lv_id, sem_kurzbz, students, pruefung) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/createPruefungen',
|
||||
params: { lv_id, sem_kurzbz, students, ...pruefung }
|
||||
};
|
||||
},
|
||||
// pruefungen: [{ uid, lehreinheit_id, datum, note, punkte }]
|
||||
importPruefungen(lv_id, sem_kurzbz, pruefungen) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/importPruefungen',
|
||||
params: { lv_id, sem_kurzbz, pruefungen }
|
||||
};
|
||||
},
|
||||
saveFreigabe(lv_id, sem_kurzbz, password, uids) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveFreigabe',
|
||||
params: { lv_id, sem_kurzbz, password, uids }
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -17,6 +17,7 @@ import AbgabetoolMitarbeiter from "../../components/Cis/Abgabetool/AbgabetoolMit
|
||||
import AbgabetoolAssistenz from "../../components/Cis/Abgabetool/AbgabetoolAssistenz.js";
|
||||
import DeadlineOverview from "../../components/Cis/Abgabetool/DeadlineOverview.js";
|
||||
import Studium from "../../components/Cis/Studium/Studium.js";
|
||||
import Benotungstool from "../../components/Cis/Benotungstool/Benotungstool.js";
|
||||
import StgOrgLvPlan from "../../components/Cis/LvPlan/StgOrg.js";
|
||||
import OtherLvPlan from "../../components/Cis/LvPlan/OtherLvPlan.js";
|
||||
|
||||
@@ -77,6 +78,13 @@ const router = VueRouter.createRouter({
|
||||
component: Raumsuche,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
// semester first: a URL without a course must not read the semester as lv_id
|
||||
path: `/Cis/Benotungstool/:sem_kurzbz?/:lv_id?`,
|
||||
name: 'Benotungstool',
|
||||
component: Benotungstool,
|
||||
props: true
|
||||
},
|
||||
// Redirect old links to new format
|
||||
{
|
||||
path: "/CisVue/Cms/getRoomInformation/:ort_kurzbz",
|
||||
@@ -152,7 +160,7 @@ const router = VueRouter.createRouter({
|
||||
path: `/Cis/MyLv/:studiensemester?`,
|
||||
name: 'MyLv',
|
||||
component: MylvStudent,
|
||||
props: true,
|
||||
props: true
|
||||
},
|
||||
{
|
||||
path: `/Cis/MyLv/Info/:studien_semester/:lehrveranstaltung_id`,
|
||||
|
||||
@@ -148,4 +148,4 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
@@ -174,6 +174,9 @@ export default {
|
||||
>
|
||||
{{ $p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
<div v-else-if="!renderers || !renderers[event.type]" class="placeholder-glow">
|
||||
<span class="placeholder col-12"></span>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
:class="'event-type-' + event.type + ' ' + mode + 'PageContainer'"
|
||||
|
||||
@@ -79,6 +79,9 @@ export default {
|
||||
>
|
||||
{{ $p.t('lehre/noLvFound') }}
|
||||
</div>
|
||||
<div v-else-if="!renderers || !renderers[event.type]" class="placeholder-glow">
|
||||
<span class="placeholder col-12"></span>
|
||||
</div>
|
||||
<component
|
||||
v-else-if="mode == 'eventheader'"
|
||||
:is="renderers[event.type]?.modalTitle"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
import BsModal from '../../Bootstrap/Modal.js';
|
||||
|
||||
/**
|
||||
* The Freigabe dialog: the changed LV-Noten and the password. It emits the password; the parent
|
||||
* writes the Freigabe.
|
||||
*
|
||||
* open() -> 'save-freigabe' (password)
|
||||
*/
|
||||
export default {
|
||||
name: "BenotungstoolFreigabeDialog",
|
||||
components: {
|
||||
BsModal,
|
||||
Password: primevue.password
|
||||
},
|
||||
props: {
|
||||
// the rows with an LV-Note that changed since the last Freigabe
|
||||
lvNoten: { type: Array, default: () => [] },
|
||||
notenOptions: { type: Array, default: () => [] }
|
||||
},
|
||||
emits: ['save-freigabe'],
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
password: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
/** The Freigabe writes the LV-Note, not the Zeugnisnote. So the dialog shows both. */
|
||||
summary() {
|
||||
return this.lvNoten.map(s => ({
|
||||
uid: s.uid,
|
||||
name: `${s.vorname} ${s.nachname}`,
|
||||
zeugnisnote: this.bezeichnungOf(s.zeugnisnote) ?? s.zeugnisnote ?? '—',
|
||||
lvNote: this.bezeichnungOf(s.lv_note) ?? s.lv_note ?? '—',
|
||||
changed: (s.zeugnisnote ?? '') != (s.lv_note ?? '')
|
||||
}));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
|
||||
submit() {
|
||||
const password = this.password;
|
||||
|
||||
// the password leaves the memory with the dialog
|
||||
this.password = '';
|
||||
this.$refs.modal.hide();
|
||||
this.$emit('save-freigabe', password);
|
||||
},
|
||||
|
||||
bezeichnungOf(note) {
|
||||
return this.notenOptions.find(n => n.note == note)?.bezeichnung;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<bs-modal data-cy="modal-freigabe" ref="modal" class="bootstrap-prompt" dialogClass="modal-lg" bodyClass="px-4 py-4"
|
||||
@hideBsModal="visible = false"
|
||||
@showBsModal="visible = true">
|
||||
<template v-slot:title>{{ $p.t('benotungstool/noteneingabeSpeichern') }}</template>
|
||||
<template v-slot:default>
|
||||
<div v-html="$capitalize($p.t('benotungstool/notenfreigabeHinweistextv4'))"></div>
|
||||
<div v-if="summary.length" class="mt-3">
|
||||
<div class="fw-bold mb-1">{{ $p.t('benotungstool/c4freigabeSummaryHeading', [summary.length]) }}</div>
|
||||
<div class="border rounded" style="max-height: 250px; overflow-y: auto;">
|
||||
<table class="table table-sm table-hover align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="bg-body sticky-top">{{ $capitalize($p.t('benotungstool/c4student')) }}</th>
|
||||
<th class="bg-body sticky-top">{{ $capitalize($p.t('benotungstool/c4freigabeSummaryCurrent')) }}</th>
|
||||
<th class="bg-body sticky-top"></th>
|
||||
<th class="bg-body sticky-top">{{ $capitalize($p.t('benotungstool/c4freigabeSummaryReleased')) }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="row in summary" :key="row.uid" :data-cy="'freigabe-row-' + row.uid">
|
||||
<td>{{ row.name }} <span class="text-muted">({{ row.uid }})</span></td>
|
||||
<td>{{ row.zeugnisnote }}</td>
|
||||
<td class="text-center"><i class="fa fa-arrow-right"></i></td>
|
||||
<td data-cy="freigabe-row-lvnote" :class="{ 'fw-bold text-success': row.changed }">{{ row.lvNote }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="small text-muted mt-1">{{ $p.t('benotungstool/c4freigabeSummaryLegend') }}</div>
|
||||
</div>
|
||||
<div v-else class="mt-3 text-center text-muted" data-cy="freigabe-summary-empty">{{ $p.t('benotungstool/c4freigabeSummaryEmpty') }}</div>
|
||||
<!-- The password field exists only while the dialog is open. Else the password manager
|
||||
offers its entries on every other text field, for example the date of the proposal. -->
|
||||
<div v-if="visible" class="mt-3 d-flex justify-content-center" data-cy="freigabe-password">
|
||||
<Password v-model="password" :feedback="false" showIcon="fa fa-eye" :toggleMask="true" :promptLabel="$p.t('benotungstool/passwort')"></Password>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" data-cy="freigabe-submit" class="btn btn-primary" :disabled="!summary.length" @click="submit">{{ $p.t('benotungstool/noteneingabeBestätigen') }}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,204 @@
|
||||
import BsModal from '../../Bootstrap/Modal.js';
|
||||
import NotenlisteLinks from "./NotenlisteLinks.js";
|
||||
import {dmyToIso, isoToDmy} from "../../../helpers/DateHelpers.js";
|
||||
|
||||
/**
|
||||
* The two import dialogs. The user pastes lines from Excel: one row per line, the cells separated by a
|
||||
* tab. The dialog finds the student and checks the format of each cell. It warns for a bad line and
|
||||
* emits the other rows. The parent checks the Antritt chain and sends the rows.
|
||||
*
|
||||
* Pruefung import Kennung, Datum, Note -> 'import-pruefungen' [{ uid, lehreinheit_id, datum, note, punkte }]
|
||||
* Noten import Kennung, Note -> 'import-lv-noten' [{ uid, note, punkte }]
|
||||
*
|
||||
* CIS_GESAMTNOTE_IMPORT_SPALTEN_* gives the column order. In the Punkte mode the Note cell holds Punkte.
|
||||
*/
|
||||
export default {
|
||||
name: "BenotungstoolImport",
|
||||
components: {
|
||||
BsModal,
|
||||
NotenlisteLinks,
|
||||
Textarea: primevue.textarea
|
||||
},
|
||||
props: {
|
||||
students: { type: Array, default: () => [] },
|
||||
config: { type: Object, default: null },
|
||||
notenOptions: { type: Array, default: () => [] },
|
||||
lehrveranstaltung: { type: Object, default: null },
|
||||
semKurzbz: { type: String, default: null },
|
||||
lehreinheiten: { type: Array, default: () => [] },
|
||||
selectedLehreinheit: { type: Object, default: null }
|
||||
},
|
||||
emits: ['import-pruefungen', 'import-lv-noten'],
|
||||
data() {
|
||||
return {
|
||||
pruefungenText: '',
|
||||
lvNotenText: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pruefungenHint() {
|
||||
return this.$capitalize(this.$p.t('benotungstool/notenimportHinweistextv6')) + this.kuerzelHint;
|
||||
},
|
||||
lvNotenHint() {
|
||||
return this.$capitalize(this.$p.t('benotungstool/notenimportHinweistextv5')) + this.kuerzelHint;
|
||||
},
|
||||
/** One more bullet while the short form of tbl_note.anmerkung is allowed. */
|
||||
kuerzelHint() {
|
||||
if (!this.config?.CIS_GESAMTNOTE_IMPORT_NOTENKUERZEL) return '';
|
||||
|
||||
return '• ' + this.$capitalize(this.$p.t('benotungstool/c4importNotenkuerzel')) + '<br>';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openPruefungen() {
|
||||
this.$refs.modalPruefungen.show();
|
||||
},
|
||||
|
||||
openLvNoten() {
|
||||
this.$refs.modalLvNoten.show();
|
||||
},
|
||||
|
||||
submitPruefungen() {
|
||||
const rows = this.parseLines(this.pruefungenText, 3, 'c4importRowNotDateFormat', this.parsePruefungRow);
|
||||
this.$refs.modalPruefungen.hide();
|
||||
this.$emit('import-pruefungen', rows);
|
||||
},
|
||||
|
||||
submitLvNoten() {
|
||||
const rows = this.parseLines(this.lvNotenText, 2, 'c4importRowNotNoteFormat', this.parseLvNoteRow);
|
||||
this.$refs.modalLvNoten.hide();
|
||||
this.$emit('import-lv-noten', rows);
|
||||
},
|
||||
|
||||
/** Splits the text into rows. A line with the wrong number of cells names only its line number. */
|
||||
parseLines(text, cellCount, formatPhrase, parseRow) {
|
||||
const rows = [];
|
||||
|
||||
text.split('\n').forEach((line, index) => {
|
||||
if (line.trim() === '') return;
|
||||
|
||||
const lineNr = index + 1;
|
||||
const cells = line.split('\t');
|
||||
if (cells.length !== cellCount) {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('benotungstool/' + formatPhrase, [lineNr]));
|
||||
return;
|
||||
}
|
||||
|
||||
const row = parseRow(cells, lineNr);
|
||||
if (row) rows.push(row);
|
||||
});
|
||||
|
||||
return rows;
|
||||
},
|
||||
|
||||
parsePruefungRow(cells, lineNr) {
|
||||
const kennung = cells[this.columnIndex('pruefung', 'kennung')];
|
||||
|
||||
const student = this.findStudent(kennung);
|
||||
if (!student) return this.warnLine('c4importNoStudentFoundForIdInRow', kennung, lineNr);
|
||||
|
||||
const datum = this.parseDatum(cells[this.columnIndex('pruefung', 'datum')]);
|
||||
if (!datum) return this.warnLine('c4importInvalidDateFoundForIdInRow', kennung, lineNr);
|
||||
|
||||
const value = this.parseNoteCell(cells[this.columnIndex('pruefung', 'note')]);
|
||||
if (!value) return this.warnLine('c4importNoGradeFoundForIdInRow', kennung, lineNr);
|
||||
|
||||
return { uid: student.uid, lehreinheit_id: student.lehreinheit_id, datum, ...value };
|
||||
},
|
||||
|
||||
parseLvNoteRow(cells, lineNr) {
|
||||
const kennung = cells[this.columnIndex('noten', 'kennung')];
|
||||
|
||||
const student = this.findStudent(kennung);
|
||||
if (!student) return this.warnLine('c4importNoStudentFoundForIdInRow', kennung, lineNr);
|
||||
|
||||
const value = this.parseNoteCell(cells[this.columnIndex('noten', 'note')]);
|
||||
if (!value) return this.warnLine('c4importNoGradeFoundForIdInRow', kennung, lineNr);
|
||||
|
||||
return { uid: student.uid, ...value };
|
||||
},
|
||||
|
||||
/** @param {'pruefung'|'noten'} kind */
|
||||
columnIndex(kind, name) {
|
||||
const key = kind === 'pruefung' ? 'CIS_GESAMTNOTE_IMPORT_SPALTEN_PRUEFUNG' : 'CIS_GESAMTNOTE_IMPORT_SPALTEN_NOTEN';
|
||||
return this.config[key].indexOf(name);
|
||||
},
|
||||
|
||||
/** A Kennung is a uid (it starts with a letter) or a Matrikelnummer (it starts with a digit). */
|
||||
findStudent(kennung) {
|
||||
const value = String(kennung ?? '').trim();
|
||||
|
||||
if (/^[0-9]/.test(value)) return this.students.find(s => s.matrikelnr?.trim() === value);
|
||||
if (/^[a-zA-Z]/.test(value)) return this.students.find(s => s.uid?.trim() === value);
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
/** @returns {string|null} 'yyyy-MM-dd', or null if the value does not match CIS_GESAMTNOTE_IMPORT_DATUMSFORMAT */
|
||||
parseDatum(value) {
|
||||
const text = String(value ?? '').trim();
|
||||
|
||||
if (this.config.CIS_GESAMTNOTE_IMPORT_DATUMSFORMAT === 'yyyy-MM-dd') {
|
||||
// the round trip rejects a day that does not exist, for example 2026-02-31
|
||||
return dmyToIso(isoToDmy(text)) === text ? text : null;
|
||||
}
|
||||
|
||||
return dmyToIso(text);
|
||||
},
|
||||
|
||||
/**
|
||||
* The Note cell: in the Punkte mode a number (a decimal comma counts as a point), else a Note of
|
||||
* the Lehre, by its key or, with CIS_GESAMTNOTE_IMPORT_NOTENKUERZEL, by its short form.
|
||||
*
|
||||
* @returns {{note, punkte}|null}
|
||||
*/
|
||||
parseNoteCell(value) {
|
||||
const text = String(value ?? '').trim();
|
||||
|
||||
if (this.config.CIS_GESAMTNOTE_PUNKTE) return { note: null, punkte: Number.parseFloat(text.replace(',', '.')) };
|
||||
|
||||
const option = this.findNote(text);
|
||||
return option?.lehre ? { note: option.note, punkte: null } : null;
|
||||
},
|
||||
|
||||
findNote(text) {
|
||||
if (text === '') return null;
|
||||
|
||||
const byKey = this.notenOptions.find(n => String(n.note).trim() === text);
|
||||
if (byKey || !this.config.CIS_GESAMTNOTE_IMPORT_NOTENKUERZEL) return byKey ?? null;
|
||||
|
||||
const byKuerzel = this.notenOptions.filter(n => String(n.anmerkung ?? '').trim().toLowerCase() === text.toLowerCase());
|
||||
return byKuerzel.length === 1 ? byKuerzel[0] : null;
|
||||
},
|
||||
|
||||
warnLine(phrase, kennung, lineNr) {
|
||||
this.$fhcAlert.alertWarning(this.$p.t('benotungstool/' + phrase, [kennung, lineNr]));
|
||||
return null;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<bs-modal data-cy="modal-pruefung-import" ref="modalPruefungen" class="bootstrap-prompt" dialogClass="modal-lg" bodyClass="px-4 py-4">
|
||||
<template v-slot:title>{{ $capitalize($p.t('benotungstool/c4pruefungImportieren')) }}</template>
|
||||
<template v-slot:default>
|
||||
<div v-html="pruefungenHint"></div>
|
||||
<Textarea data-cy="pruefung-import-text" v-model="pruefungenText" rows="5" class="w-100 mt-3" :placeholder="$p.t('benotungstool/c4importPlaceholder')"></Textarea>
|
||||
<NotenlisteLinks class="mt-3" :lehrveranstaltung="lehrveranstaltung" :sem_kurzbz="semKurzbz" :lehreinheiten="lehreinheiten" :selected-lehreinheit="selectedLehreinheit" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" data-cy="pruefung-import-submit" class="btn btn-primary" @click="submitPruefungen">{{ $capitalize($p.t('benotungstool/c4import')) }}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
|
||||
<bs-modal data-cy="modal-lvnoten-import" ref="modalLvNoten" class="bootstrap-prompt" dialogClass="modal-lg" bodyClass="px-4 py-4">
|
||||
<template v-slot:title>{{ $capitalize($p.t('benotungstool/c4notenImportieren')) }}</template>
|
||||
<template v-slot:default>
|
||||
<div v-html="lvNotenHint"></div>
|
||||
<Textarea data-cy="lvnoten-import-text" v-model="lvNotenText" rows="5" class="w-100 mt-3" :placeholder="$p.t('benotungstool/c4importNotePlaceholder')"></Textarea>
|
||||
<NotenlisteLinks class="mt-3" :lehrveranstaltung="lehrveranstaltung" :sem_kurzbz="semKurzbz" :lehreinheiten="lehreinheiten" :selected-lehreinheit="selectedLehreinheit" />
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" data-cy="lvnoten-import-submit" class="btn btn-primary" @click="submitLvNoten">{{ $capitalize($p.t('benotungstool/c4import')) }}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
// The links to the Excel Notenliste of the LV and of each Lehreinheit.
|
||||
export const NotenlisteLinks = {
|
||||
name: "NotenlisteLinks",
|
||||
props: {
|
||||
lehrveranstaltung: { type: Object, default: null },
|
||||
sem_kurzbz: { type: String, default: null },
|
||||
lehreinheiten: { type: Array, default: () => [] },
|
||||
selectedLehreinheit: { type: Object, default: null }
|
||||
},
|
||||
computed: {
|
||||
/** A selected Lehreinheit shows only its own link. */
|
||||
shownLehreinheiten() {
|
||||
if (this.selectedLehreinheit?.lehreinheit_id == null) return this.lehreinheiten;
|
||||
|
||||
return this.lehreinheiten.filter(le => le.lehreinheit_id === this.selectedLehreinheit.lehreinheit_id);
|
||||
},
|
||||
baseUrl() {
|
||||
return FHC_JS_DATA_STORAGE_OBJECT.app_root
|
||||
+ 'cis/private/lehre/notenliste.xls.php';
|
||||
},
|
||||
ready() {
|
||||
const lv = this.lehrveranstaltung;
|
||||
return !!(lv && lv.studiengang_kz != null && lv.lv_semester != null
|
||||
&& lv.lehrveranstaltung_id != null && this.sem_kurzbz);
|
||||
},
|
||||
fullListUrl() {
|
||||
if (!this.ready) return null;
|
||||
return this.buildUrl();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
buildUrl(lehreinheit_id = null) {
|
||||
const lv = this.lehrveranstaltung;
|
||||
const params = new URLSearchParams({
|
||||
stg: lv.studiengang_kz,
|
||||
sem: lv.lv_semester,
|
||||
lvid: lv.lehrveranstaltung_id,
|
||||
stsem: this.sem_kurzbz
|
||||
});
|
||||
if (lehreinheit_id != null) params.set('lehreinheit_id', lehreinheit_id);
|
||||
return this.baseUrl + '?' + params.toString();
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div v-if="ready">
|
||||
<div class="fw-bold mb-2">{{ $capitalize($p.t('benotungstool/c4notenlisten')) }}</div>
|
||||
|
||||
<div class="mb-1">
|
||||
<a class="Item" :href="fullListUrl" target="_blank" rel="noopener">
|
||||
{{ $capitalize($p.t('benotungstool/c4gesamtliste')) }} {{ lehrveranstaltung.lv_bezeichnung }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div v-for="le in shownLehreinheiten" :key="le.lehreinheit_id" class="mb-1" style="padding-left: 1.5rem;">
|
||||
<a class="Item" :href="buildUrl(le.lehreinheit_id)" target="_blank" rel="noopener">
|
||||
{{ le.infoString }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="text-muted">
|
||||
{{ $capitalize($p.t('benotungstool/c4keineStudentenGefunden')) }}
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
export default NotenlisteLinks;
|
||||
@@ -0,0 +1,295 @@
|
||||
import BsModal from '../../Bootstrap/Modal.js';
|
||||
import VueDatePicker from '../../vueDatepicker.js.php';
|
||||
import ApiNoten from "../../../api/factory/noten.js";
|
||||
import {debounce} from "../../../helpers/debounce.js";
|
||||
import {today, toIsoDate, parseIsoDate, addDays} from "../../../helpers/DateHelpers.js";
|
||||
|
||||
/**
|
||||
* The Pruefung dialog. It collects the input and emits it. The parent checks the Antritt chain and
|
||||
* writes.
|
||||
*
|
||||
* openForCell(student, pruefung, field) a new or a changed Pruefung of one student -> 'save-pruefung' (student, pruefung)
|
||||
* openForSelection() one new Pruefung on one day for the selection -> 'create-pruefungen' (pruefung)
|
||||
*
|
||||
* The table holds the selection. The multiselect emits 'select-students', the parent selects the rows,
|
||||
* and the prop selectedStudents follows.
|
||||
*/
|
||||
export default {
|
||||
name: "BenotungstoolPruefungDialog",
|
||||
components: {
|
||||
BsModal,
|
||||
Datepicker: VueDatePicker,
|
||||
Dropdown: primevue.dropdown,
|
||||
InputNumber: primevue.inputnumber,
|
||||
Multiselect: primevue.multiselect
|
||||
},
|
||||
props: {
|
||||
config: { type: Object, default: null },
|
||||
notenOptions: { type: Array, default: () => [] },
|
||||
lvId: { default: null },
|
||||
semKurzbz: { type: String, default: null },
|
||||
// the students that can get a Pruefung, in the order of the table
|
||||
studentOptions: { type: Array, default: () => [] },
|
||||
selectedStudents: { type: Array, default: () => [] }
|
||||
},
|
||||
emits: ['save-pruefung', 'create-pruefungen', 'select-students'],
|
||||
data() {
|
||||
return {
|
||||
// the student of the cell; null in the dialog for the selection
|
||||
student: null,
|
||||
pruefung: null,
|
||||
selectedDate: today(),
|
||||
selectedNote: null,
|
||||
selectedPunkte: null,
|
||||
// a later Pruefung locks the Note; the date stays editable
|
||||
noteLocked: false,
|
||||
dateMin: null,
|
||||
dateMax: null,
|
||||
// the Pruefung names the Lektor of the Lehreinheit, not the user; with several Lektoren the user selects one
|
||||
lektoren: [],
|
||||
selectedLektor: null,
|
||||
debouncedShowNoteForPunkte: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
if (!this.student) return this.$capitalize(this.$p.t('benotungstool/c4addNewPruefung'));
|
||||
|
||||
const phrase = this.pruefung ? 'benotungstool/editPruefungFor' : 'benotungstool/createPruefungFor';
|
||||
return this.$capitalize(this.$p.t(phrase)) + ' ' + this.student.vorname + ' ' + this.student.nachname;
|
||||
},
|
||||
lehreNoten() {
|
||||
return this.notenOptions.filter(n => n.lehre === true);
|
||||
},
|
||||
/** The students that get the Pruefung. */
|
||||
students() {
|
||||
return this.student ? [this.student] : this.selectedStudents;
|
||||
},
|
||||
/** The hint: for these students the new Pruefung also writes the LV-Note. */
|
||||
withoutLvNote() {
|
||||
return this.pruefung ? [] : this.students.filter(s => !s.verlauf.hasLvNote);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
/** Warns early if the selected Note reached its limit (verlauf.notenAtLimit); the server checks it too. */
|
||||
selectedNote(option, previous) {
|
||||
if (!option || !this.student) return;
|
||||
|
||||
// the changed Pruefung may keep its own Note
|
||||
const limit = this.student.verlauf.notenAtLimit[option.note];
|
||||
if (limit == null || option.note == this.pruefung?.note) return;
|
||||
|
||||
this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('benotungstool/c4noteLimitUeberschritten', [
|
||||
option.bezeichnung, this.student.uid, limit
|
||||
])));
|
||||
this.selectedNote = previous;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.debouncedShowNoteForPunkte = debounce(this.showNoteForPunkte, 500);
|
||||
},
|
||||
methods: {
|
||||
openForCell(student, pruefung, field) {
|
||||
this.student = student;
|
||||
this.pruefung = pruefung;
|
||||
this.loadLektoren([student.lehreinheit_id]);
|
||||
|
||||
// the 'antritt' column has no date, so a new Pruefung starts with today
|
||||
const datum = pruefung?.datum ?? (/^\d{4}-\d{2}-\d{2}$/.test(field) ? field : null);
|
||||
this.selectedDate = datum ? parseIsoDate(datum) : today();
|
||||
this.selectedNote = pruefung ? this.notenOptions.find(n => n.note == pruefung.note) ?? null : null;
|
||||
this.selectedPunkte = pruefung?.punkte ?? null;
|
||||
// the server locks the Note of a Pruefung with a later one
|
||||
this.noteLocked = !!pruefung?.note_locked;
|
||||
|
||||
const bounds = this.pruefungDateBounds(student, pruefung, field);
|
||||
this.dateMin = bounds.min;
|
||||
this.dateMax = bounds.max;
|
||||
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
|
||||
openForSelection() {
|
||||
this.student = null;
|
||||
this.pruefung = null;
|
||||
this.loadLektoren(this.selectedStudents.map(s => s.lehreinheit_id));
|
||||
|
||||
// empty, without a Note
|
||||
this.selectedDate = today();
|
||||
this.selectedNote = null;
|
||||
this.selectedPunkte = null;
|
||||
this.noteLocked = false;
|
||||
this.dateMin = null;
|
||||
this.dateMax = null;
|
||||
|
||||
this.$refs.modal.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* The date of a Pruefung stays strictly between its neighbours, so the order of the Antritte
|
||||
* stays. A column without a date ('antritt_2') means a new Pruefung after all others.
|
||||
*
|
||||
* @returns {{min: Date|null, max: Date|null}} the inclusive bounds of the date picker
|
||||
*/
|
||||
pruefungDateBounds(student, pruefung, field) {
|
||||
const own = String(pruefung?.datum ?? field ?? '').slice(0, 10);
|
||||
const reference = /^\d{4}-\d{2}-\d{2}$/.test(own) ? own : '9999-12-31';
|
||||
|
||||
let lower = null;
|
||||
let upper = null;
|
||||
(student.verlauf.pruefungen ?? []).forEach(p => {
|
||||
if (pruefung && p.pruefung_id === pruefung.pruefung_id) return;
|
||||
|
||||
const day = String(p.datum ?? '').slice(0, 10);
|
||||
if (!day) return;
|
||||
if (day < reference && (lower === null || day > lower)) lower = day;
|
||||
if (day > reference && (upper === null || day < upper)) upper = day;
|
||||
});
|
||||
|
||||
return {
|
||||
min: lower ? addDays(parseIsoDate(lower), 1) : null,
|
||||
max: upper ? addDays(parseIsoDate(upper), -1) : null
|
||||
};
|
||||
},
|
||||
|
||||
submit() {
|
||||
if (this.student) this.submitForCell(); else this.submitForSelection();
|
||||
},
|
||||
|
||||
submitForCell() {
|
||||
// a typed date can pass the bounds of the date picker
|
||||
if ((this.dateMin && this.selectedDate < this.dateMin) || (this.dateMax && this.selectedDate > this.dateMax)) {
|
||||
this.$fhcAlert.alertWarning(this.$capitalize(this.$p.t('benotungstool/pruefungDatumOutOfRangeHint')));
|
||||
return;
|
||||
}
|
||||
|
||||
// Without a selection the Note stays empty; the server writes 'Noch nicht eingetragen'. Without
|
||||
// the Punkte mode a 0 would be a value: the server derives the Note from it.
|
||||
const pruefung = {
|
||||
pruefung_id: this.pruefung?.pruefung_id ?? null,
|
||||
lehreinheit_id: this.student.lehreinheit_id,
|
||||
datum: toIsoDate(this.selectedDate),
|
||||
note: this.noteLocked ? this.pruefung.note : (this.selectedNote?.note ?? ''),
|
||||
punkte: this.config.CIS_GESAMTNOTE_PUNKTE ? (this.noteLocked ? this.pruefung.punkte : this.selectedPunkte) ?? null : null,
|
||||
mitarbeiter_uid: this.selectedLektor
|
||||
};
|
||||
|
||||
this.$refs.modal.hide();
|
||||
this.$emit('save-pruefung', this.student, pruefung);
|
||||
},
|
||||
|
||||
submitForSelection() {
|
||||
// a missing LV-Note blocks nothing: the server writes it with the Note of this Pruefung
|
||||
const pruefung = {
|
||||
datum: toIsoDate(this.selectedDate),
|
||||
note: this.selectedNote?.note ?? null,
|
||||
punkte: this.selectedPunkte ?? null,
|
||||
mitarbeiter_uid: this.selectedLektor
|
||||
};
|
||||
|
||||
this.$refs.modal.hide();
|
||||
this.$emit('create-pruefungen', pruefung);
|
||||
},
|
||||
|
||||
/** The parent selects the rows in the table; the Lektoren follow the new selection. */
|
||||
selectStudents(students) {
|
||||
this.$emit('select-students', students);
|
||||
this.loadLektoren(students.map(s => s.lehreinheit_id));
|
||||
},
|
||||
|
||||
/** The Lektoren of the Lehreinheit. With exactly one Lektor the selection stays empty; the server sets that Lektor. */
|
||||
loadLektoren(lehreinheitIds) {
|
||||
this.lektoren = [];
|
||||
this.selectedLektor = null;
|
||||
|
||||
// a Lektor selection makes sense only if all students share one Lehreinheit
|
||||
const distinct = [...new Set(lehreinheitIds.filter(id => id != null))];
|
||||
if (distinct.length !== 1) return;
|
||||
|
||||
this.$api.call(ApiNoten.getLektorenForLehreinheit(this.lvId, this.semKurzbz, distinct[0])).then(res => {
|
||||
this.lektoren = res.data.map(l => ({
|
||||
...l,
|
||||
name: `${l.vorname ?? ''} ${l.nachname ?? ''}`.trim() || l.mitarbeiter_uid
|
||||
}));
|
||||
|
||||
// a selection only if there is something to select
|
||||
if (this.lektoren.length > 1) {
|
||||
const current = this.pruefung?.mitarbeiter_uid;
|
||||
this.selectedLektor = this.lektoren.some(l => l.mitarbeiter_uid === current) ? current : this.lektoren[0].mitarbeiter_uid;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/** In the Punkte mode the dialog shows the Note of the Punkte, from the Notenschluessel of the LV. */
|
||||
showNoteForPunkte(event) {
|
||||
const punkte = event.value === '' ? null : event.value;
|
||||
|
||||
this.$api.call(ApiNoten.getNoteByPunkte(this.lvId, this.semKurzbz, punkte)).then(res => {
|
||||
if (res.data >= 0) this.selectedNote = this.notenOptions.find(n => n.note == res.data);
|
||||
});
|
||||
},
|
||||
|
||||
/** The multiselect label: "uid – Nachname Vorname – Antritte: n". */
|
||||
studentLabel(student) {
|
||||
return `${student.uid} – ${student.nachname} ${student.vorname} – ${this.$capitalize(this.$p.t('benotungstool/c4antrittCountv2'))}: ${student.verlauf.antrittCount}`;
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<bs-modal data-cy="modal-pruefung" ref="modal" class="bootstrap-prompt" dialogClass="modal-lg" bodyClass="px-4 py-4">
|
||||
<template v-slot:title>{{ title }}</template>
|
||||
<template v-slot:default>
|
||||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-3 text-center">{{ $capitalize($p.t('benotungstool/c4date')) }}:</div>
|
||||
<div class="col-6" data-cy="pruefung-datum">
|
||||
<datepicker v-model="selectedDate" :clearable="false" :enableTimePicker="false" format="dd.MM.yyyy" placeholder="TT.MM.JJJJ"
|
||||
:min-date="dateMin" :max-date="dateMax" :text-input="true" :auto-apply="true">
|
||||
</datepicker>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="noteLocked" class="row mt-2 justify-content-center">
|
||||
<div class="col-9 text-center text-muted small" data-cy="pruefung-note-locked">{{ $capitalize($p.t('benotungstool/pruefungNoteLockedHint')) }}</div>
|
||||
</div>
|
||||
<div v-if="config?.CIS_GESAMTNOTE_PUNKTE" class="row mt-3 align-items-center justify-content-center">
|
||||
<div class="col-3 text-center">{{ $capitalize($p.t('benotungstool/c4punkte')) }}:</div>
|
||||
<div class="col-6">
|
||||
<InputNumber data-cy="pruefung-punkte" v-model="selectedPunkte" @input="debouncedShowNoteForPunkte" :disabled="noteLocked"
|
||||
inputId="pruefungPunkte" :min="0" :max="100000" class="w-100">
|
||||
</InputNumber>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 align-items-center justify-content-center">
|
||||
<div class="col-3 text-center">{{ $capitalize($p.t('lehre/note')) }}:</div>
|
||||
<div class="col-6">
|
||||
<Dropdown data-cy="pruefung-note" :placeholder="$capitalize($p.t('lehre/note'))" :disabled="config?.CIS_GESAMTNOTE_PUNKTE || noteLocked"
|
||||
:style="{'width': '100%'}" optionLabel="bezeichnung" v-model="selectedNote" :options="lehreNoten" showClear>
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!student" class="row mt-3 align-items-center justify-content-center">
|
||||
<div class="col-3 text-center">{{ $capitalize($p.t('benotungstool/prueflingSelectionv2')) }}:</div>
|
||||
<div class="col-6">
|
||||
<Multiselect data-cy="pruefung-students" :modelValue="selectedStudents" @update:modelValue="selectStudents" :options="studentOptions" :optionLabel="studentLabel"
|
||||
:placeholder="$capitalize($p.t('benotungstool/prueflingSelectionv2'))" :maxSelectedLabels="3" showToggleAll class="w-100" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="lektoren.length > 1" class="row mt-3 align-items-center justify-content-center">
|
||||
<div class="col-3 text-center">{{ $capitalize($p.t('benotungstool/c4lektor')) }}:</div>
|
||||
<div class="col-6">
|
||||
<Dropdown data-cy="pruefung-lektor" :style="{'width': '100%'}" v-model="selectedLektor" :options="lektoren"
|
||||
optionLabel="name" optionValue="mitarbeiter_uid">
|
||||
</Dropdown>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="withoutLvNote.length" class="alert alert-info mt-3 mb-0 py-2" data-cy="pruefung-without-lvnote">
|
||||
<div>{{ $p.t('benotungstool/c4lvNoteWirdAngelegtHinweis') }}</div>
|
||||
<div v-if="!student" class="small mt-1">{{ withoutLvNote.map(s => s.vorname + ' ' + s.nachname + ' (' + s.uid + ')').join(', ') }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" data-cy="pruefung-submit" class="btn btn-primary" @click="submit">
|
||||
{{ student ? $capitalize($p.t('global/speichern')) : $capitalize($p.t('benotungstool/c4addNewPruefung')) }}
|
||||
</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
`
|
||||
};
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* The layout of the Benotungstool table: what the browser keeps (column order, width, visibility,
|
||||
* filters, sort), the sticky columns, and the scroll position during a render.
|
||||
*/
|
||||
|
||||
/** Reads a value that the browser keeps. Private mode or a broken value give `fallback`. */
|
||||
export function loadKept(key, fallback) {
|
||||
try {
|
||||
const value = localStorage.getItem(key);
|
||||
return value === null ? fallback : JSON.parse(value);
|
||||
} catch (e) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveKept(key, value) {
|
||||
try {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} catch (e) {
|
||||
// private mode: the value lasts until the next load
|
||||
}
|
||||
}
|
||||
|
||||
/** Keeps the layout of the columns in `fields`. The Pruefung columns change per LV, so they are left out. */
|
||||
export function saveLayout(key, table, fields) {
|
||||
saveKept(key, {
|
||||
columns: table.getColumnLayout()
|
||||
.filter(col => fields.includes(col.field))
|
||||
.map(col => ({ field: col.field, visible: col.visible, width: col.width })),
|
||||
sort: table.getSorters().map(s => ({ field: s.field, dir: s.dir })),
|
||||
filters: table.getFilters(),
|
||||
headerFilters: table.getHeaderFilters()
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The column definitions in the kept order, with the kept width and visibility. New columns come last.
|
||||
* Apply it BEFORE Tabulator takes the columns: after that the definitions and the Vue titles conflict.
|
||||
*/
|
||||
export function restoreColumns(columns, layout) {
|
||||
if (!layout?.columns) return columns;
|
||||
|
||||
const byField = new Map(columns.map(c => [c.field, c]));
|
||||
const restored = [];
|
||||
|
||||
layout.columns.forEach(kept => {
|
||||
const column = byField.get(kept.field);
|
||||
if (!column) return;
|
||||
|
||||
restored.push({ ...column, width: kept.width, visible: kept.visible });
|
||||
byField.delete(kept.field);
|
||||
});
|
||||
|
||||
byField.forEach(column => restored.push(column));
|
||||
return restored;
|
||||
}
|
||||
|
||||
/** Applies the kept filters and sort. Call it once, after the first rows: then the Pruefung columns exist. */
|
||||
export function restoreFiltersAndSort(table, layout) {
|
||||
if (layout?.filters?.length) table.setFilter(layout.filters);
|
||||
|
||||
(layout?.headerFilters ?? []).forEach(hf => table.setHeaderFilterValue(hf.field, hf.value));
|
||||
|
||||
// a Pruefung column of another LV does not exist in this table
|
||||
const fields = table.getColumns().map(column => column.getField());
|
||||
const sorters = (layout?.sort ?? [])
|
||||
.filter(s => fields.includes(s.field))
|
||||
.map(s => ({ column: s.field, dir: s.dir }));
|
||||
if (sorters.length) table.setSort(sorters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins the selected columns to the left. A `sticky-on-<field>` class on the container switches one
|
||||
* column on (see Benotungstool.css), and `--sl-<field>` is its left offset: the width of the pinned
|
||||
* columns before it, so that the pinned columns stand next to each other.
|
||||
*/
|
||||
export function applyStickyColumns(element, table, fields, selected) {
|
||||
if (!element || !table) return;
|
||||
|
||||
let offset = 0;
|
||||
// the display order, so a moved column keeps the right offset
|
||||
table.getColumns().forEach(column => {
|
||||
const field = column.getField();
|
||||
if (!fields.includes(field)) return;
|
||||
|
||||
const pinned = selected.includes(field);
|
||||
element.classList.toggle('sticky-on-' + field, pinned);
|
||||
element.style.setProperty('--sl-' + field, offset + 'px');
|
||||
if (pinned) offset += column.getWidth();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps the scroll position while `operation` renders the table again.
|
||||
*
|
||||
* Read and write .tabulator-tableholder directly: Tabulator does not update rowManager.scrollLeft.
|
||||
* Set the position again in the next two frames: Tabulator renders later and resets it, and
|
||||
* Vue.nextTick is too early.
|
||||
*/
|
||||
export function preserveScroll(table, operation) {
|
||||
const holder = table?.element?.querySelector('.tabulator-tableholder');
|
||||
const left = holder?.scrollLeft ?? 0;
|
||||
const top = holder?.scrollTop ?? 0;
|
||||
|
||||
const result = operation();
|
||||
|
||||
// nothing to keep; do not work against a scroll to the top that the user wants
|
||||
if (!holder || (!left && !top)) return result;
|
||||
|
||||
const restore = () => {
|
||||
holder.scrollLeft = left;
|
||||
holder.scrollTop = top;
|
||||
};
|
||||
|
||||
restore();
|
||||
requestAnimationFrame(() => { restore(); requestAnimationFrame(restore); });
|
||||
|
||||
// setData returns a promise; set the position again after the load
|
||||
if (result && typeof result.then === 'function') result.then(() => requestAnimationFrame(restore));
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -72,20 +72,10 @@ export default {
|
||||
return this.entry.url.startsWith(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_router)
|
||||
},
|
||||
target() {
|
||||
if (this.entry.template_kurzbz == 'redirect') {
|
||||
if (!this.entry.content)
|
||||
return '';
|
||||
let xmlDoc = (new DOMParser()).parseFromString(this.entry.content,"text/xml");
|
||||
let target = xmlDoc.getElementsByTagName('target')[0];
|
||||
if (!target)
|
||||
return '';
|
||||
|
||||
target = target.childNodes[0].nodeValue + "";
|
||||
if (target == 'content' || target == '_self')
|
||||
target = "";
|
||||
return target;
|
||||
if (this.entry?.target) {
|
||||
return this.entry.target;
|
||||
}
|
||||
return ''
|
||||
return '_self';
|
||||
},
|
||||
hasChilds() {
|
||||
return this.entry.childs && this.entry.childs.length !== 0;
|
||||
|
||||
@@ -206,6 +206,8 @@ export default {
|
||||
});
|
||||
|
||||
this.lehrveranstaltungen.forEach((lehrveranstaltung)=>{
|
||||
// a lehrveranstaltung without a modul has no children
|
||||
if(!Array.isArray(lehrveranstaltung.lehrveranstaltungen)) return;
|
||||
lehrveranstaltung.lehrveranstaltungen.sort((lv1,lv2)=>{
|
||||
if (lv1.bezeichnung.toLowerCase() > lv2.bezeichnung.toLowerCase()) {
|
||||
return 1;
|
||||
@@ -393,6 +395,16 @@ export default {
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card" v-else-if="!Array.isArray(lehrveranstaltung.lehrveranstaltungen)">
|
||||
<div class="card-body">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="d-flex list-group-item">
|
||||
<a class="fhc-link-color d-block me-auto" href="#" @click="openLvUebersicht(lehrveranstaltung)">{{isGermanLanguage ? lehrveranstaltung.bezeichnung : lehrveranstaltung.bezeichnung_english}}</a>
|
||||
<p>{{lehrveranstaltung.lehrform_kurzbz}}</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -400,32 +400,37 @@ export default {
|
||||
|
||||
<div v-if="headerData.length == 1">
|
||||
<div v-if="!isLoading" class="d-flex align-items-center gap-3">
|
||||
<h2 class="h4">
|
||||
<h2 class="h4 mt-2">
|
||||
{{headerData[0].titelpre}}
|
||||
{{headerData[0].vorname}}
|
||||
{{headerData[0].nachname}}
|
||||
<span v-if="headerData[0].titelpost">, </span>
|
||||
{{headerData[0].titelpost}}
|
||||
</h2>
|
||||
<core-tag ref="tagComponent"
|
||||
v-if="tagsEnabled"
|
||||
:endpoint="tagEndpoint"
|
||||
:values="prestudentIds"
|
||||
@added="addedTag"
|
||||
@deleted="deletedTag"
|
||||
@updated="updatedTag"
|
||||
zuordnung_typ="prestudent_id"
|
||||
></core-tag>
|
||||
<div
|
||||
role="button"
|
||||
v-if="tagsEnabled"
|
||||
@click="rebuildPrestudentTags"
|
||||
class="btn btn-outline btn-light mb-1"
|
||||
:title="'Automatische Tags fuer ' + currentSemester + ' neu laden'"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i>
|
||||
<span>{{currentSemester}}</span>
|
||||
|
||||
<div class="d-flex border rounded align-items-center ps-1">
|
||||
<core-tag ref="tagComponent"
|
||||
v-if="tagsEnabled"
|
||||
:endpoint="tagEndpoint"
|
||||
:values="prestudentIds"
|
||||
:show-hover="true"
|
||||
@added="addedTag"
|
||||
@deleted="deletedTag"
|
||||
@updated="updatedTag"
|
||||
zuordnung_typ="prestudent_id"
|
||||
></core-tag>
|
||||
<div
|
||||
role="button"
|
||||
v-if="tagsEnabled"
|
||||
@click="rebuildPrestudentTags"
|
||||
class="btn btn-outline btn-sm btn-hover m-1"
|
||||
:title="$p.t('tag','rebuild_tags') + ' ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i>
|
||||
<span>{{currentSemester}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h6 v-if="headerData[0].unruly" class="badge" :class="'bg-unruly rounded-0'"><strong>unruly</strong></h6>
|
||||
</div>
|
||||
<div v-else class="d-flex align-items-center gap-3">
|
||||
|
||||
@@ -49,6 +49,52 @@ export default{
|
||||
{title: this.$p.t('person', 'nachname'), field:"nachname"},
|
||||
{title: this.$p.t('person', 'vorname'), field:"vorname"},
|
||||
{title: this.$p.t('person', 'uid'), field:"mitarbeiter_uid"},
|
||||
{title: this.$p.t('global/insertvon'), field: 'insertvon', visible: false},
|
||||
{
|
||||
title: this.$p.t('global/insertamum'),
|
||||
field: "insertamum",
|
||||
visible: false,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: this.$p.t('global/updatevon'), field: 'updatevon', visible: false},
|
||||
{
|
||||
title: this.$p.t('global/updateamum'),
|
||||
field: "updateamum",
|
||||
visible: false,
|
||||
formatter: function (cell) {
|
||||
const dateStr = cell.getValue();
|
||||
|
||||
if (!dateStr) return "";
|
||||
|
||||
const date = new Date(dateStr);
|
||||
|
||||
return date.toLocaleString("de-DE", {
|
||||
day: "2-digit",
|
||||
month: "2-digit",
|
||||
year: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
second: "2-digit",
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
},
|
||||
{title: this.$p.t('lehre', 'lehreinheit_id'), field:"lehreinheit_id"},
|
||||
{
|
||||
title: this.$p.t('lehre', 'verplant'),
|
||||
@@ -102,7 +148,7 @@ export default{
|
||||
selectable: true,
|
||||
selectableRangeMode: 'click',
|
||||
selectableRows:1,
|
||||
persistenceID: 'lehrveranstaltungen_lektor_table_2025_05_27_v1',
|
||||
persistenceID: 'lehrveranstaltungen_lektor_table_2026_09_11_v1',
|
||||
}},
|
||||
},
|
||||
mounted(){
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
export const MobilityLegende = {
|
||||
name: 'MobilityLegende',
|
||||
template:`
|
||||
<div class="col-auto" style="max-width: 60vw">
|
||||
<!-- TODO: phrasen definieren & verwenden-->
|
||||
<div class="row" style="font-weight: bold"><h6>Legende</h6></div>
|
||||
<div class="row"><h6>(i) ... Incoming</h6></div>
|
||||
<div class="row"><h6>(o) ... Outgoing</h6></div>
|
||||
<div class="row"><h6>(ar) ... angerechnet </h6></div>
|
||||
<div class="row"><h6>(iar) ... intern angerechnet</h6></div>
|
||||
<div class="row"><h6>(nz) ... nicht zugelassen</h6></div>
|
||||
<div class="row"><h6>(ma) ... MitarbeiterIn</h6></div>
|
||||
<div class="row"><h6>(a.o.) ... Außerordentliche/r HörerIn</h6></div>
|
||||
<div class="row"><h6>(d.d.) ... Double Degree Program</h6></div>
|
||||
</div>
|
||||
`
|
||||
};
|
||||
|
||||
export default MobilityLegende;
|
||||
+6
-2
@@ -553,8 +553,12 @@ export default {
|
||||
}
|
||||
|
||||
if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) {
|
||||
if(this.student.geschlecht == 'w')
|
||||
this.formData.akadgrad_id = this.arrAkadGrad[1].akadgrad_id;
|
||||
const akadGradByGeschlecht = this.arrAkadGrad.find((item) => {
|
||||
return item.geschlecht === this.student.geschlecht;
|
||||
});
|
||||
|
||||
if(akadGradByGeschlecht)
|
||||
this.formData.akadgrad_id = akadGradByGeschlecht.akadgrad_id;
|
||||
else
|
||||
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ export default {
|
||||
deleteButton.className = 'btn btn-outline-secondary';
|
||||
const icon = document.createElement('i');
|
||||
icon.className = 'fa fa-trash';
|
||||
icon.title = this.$p.t('ui/loeschen');
|
||||
icon.title = this.$p.t('lehre/info_deleteMarkEntry');
|
||||
deleteButton.append(icon);
|
||||
deleteButton.addEventListener('click', evt => {
|
||||
evt.stopPropagation();
|
||||
|
||||
@@ -193,7 +193,7 @@ export default {
|
||||
return this.$api
|
||||
.call(ApiStvProjektarbeit.getLehrveranstaltungen(
|
||||
this.student.uid,
|
||||
this.newProjektarbeit ? this.student.studiengang_kz : null,
|
||||
this.student.studiengang_kz,
|
||||
this.studiensemester,
|
||||
this.additional_lehrveranstaltung_id
|
||||
))
|
||||
@@ -227,7 +227,8 @@ export default {
|
||||
if (preparedFormData.projektarbeit_id == null) delete(preparedFormData.projektarbeit_id);
|
||||
delete(preparedFormData.firma);
|
||||
delete(preparedFormData.firma_name);
|
||||
delete(preparedFormData.lehrveranstaltung_id);
|
||||
|
||||
preparedFormData.studiensemester_kurzbz = this.studiensemester
|
||||
|
||||
return preparedFormData;
|
||||
}
|
||||
@@ -290,7 +291,7 @@ export default {
|
||||
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-10">
|
||||
<div class="col-9">
|
||||
<form-input
|
||||
container-class="stv-details-projektarbeit-firma"
|
||||
:label="$p.t('projektarbeit', 'firma')"
|
||||
@@ -304,7 +305,7 @@ export default {
|
||||
>
|
||||
</form-input>
|
||||
</div>
|
||||
<div class="col-2 align-content-center">
|
||||
<div class="col-3 align-content-center">
|
||||
<a :href="firmenverwaltungLink" target="_blank">
|
||||
{{ $p.t('projektarbeit', 'zurFirmenverwaltung') }}
|
||||
</a>
|
||||
@@ -313,14 +314,13 @@ export default {
|
||||
|
||||
<div class="row mb-3">
|
||||
<form-input
|
||||
container-class="stv-details-projektarbeit-lv col-10"
|
||||
container-class="stv-details-projektarbeit-lv col-9"
|
||||
:label="$p.t('projektarbeit', 'lehrveranstaltung')"
|
||||
type="select"
|
||||
v-model="formData.lehrveranstaltung_id"
|
||||
name="lehrveranstaltung_id"
|
||||
@change="lvChanged($event)"
|
||||
>
|
||||
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
|
||||
<option
|
||||
v-for="lv in arrLvs"
|
||||
:key="lv.lehrveranstaltung_id"
|
||||
@@ -330,14 +330,13 @@ export default {
|
||||
</option>
|
||||
</form-input>
|
||||
<form-input
|
||||
container-class="col-2"
|
||||
container-class="col-3"
|
||||
:label="$p.t('lehre', 'studiensemester')"
|
||||
type="select"
|
||||
v-model="studiensemester"
|
||||
name="studiensemester"
|
||||
@change="studiensemesterChanged"
|
||||
>
|
||||
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
|
||||
<option
|
||||
v-for="sem in arrStudiensemester"
|
||||
:key="sem.studiensemester_kurzbz"
|
||||
|
||||
+10
-10
@@ -42,16 +42,16 @@ export default {
|
||||
return {
|
||||
tabulatorOptions: {
|
||||
columns: [
|
||||
{title: "Nachname", field: "nachname"},
|
||||
{title: "Vorname", field: "vorname"},
|
||||
{title: "Note", field: "note"},
|
||||
{title: "Punkte", field: "punkte"},
|
||||
{title: "Stunden", field: "stunden"},
|
||||
{title: "Stundensatz", field: "stundensatz", visible: false},
|
||||
{title: "Art", field: "betreuerart_kurzbz", visible: false},
|
||||
{title: "Person ID", field: "person_id", visible: false},
|
||||
{title: "Vertrag ID", field: "vertrag_id", visible: false},
|
||||
{title: "Projektarbeit ID", field: "projektarbeit_id", visible: false},
|
||||
{title: "Nachname", field: "nachname", widthGrow: 2},
|
||||
{title: "Vorname", field: "vorname", widthGrow: 2},
|
||||
{title: "Note", field: "note", widthGrow: 1},
|
||||
{title: "Punkte", field: "punkte", widthGrow: 1},
|
||||
{title: "Stunden", field: "stunden", widthGrow: 1},
|
||||
{title: "Stundensatz", field: "stundensatz", visible: false, widthGrow: 1},
|
||||
{title: "Art", field: "betreuerart_kurzbz", visible: false, widthGrow: 2},
|
||||
{title: "Person ID", field: "person_id", visible: false, widthGrow: 1},
|
||||
{title: "Vertrag ID", field: "vertrag_id", visible: false, widthGrow: 1},
|
||||
{title: "Projektarbeit ID", field: "projektarbeit_id", visible: false, widthGrow: 1},
|
||||
{
|
||||
title: 'Aktionen',
|
||||
field: 'actions',
|
||||
|
||||
@@ -317,6 +317,7 @@ export default {
|
||||
"$p.user_language.value"(n, o) {
|
||||
if (n !== o && o !== undefined && this.$refs.table.tableBuilt) {
|
||||
this.translateTabulator();
|
||||
this.$reloadList();
|
||||
}
|
||||
},
|
||||
"tagFilterState.selectedOptions": {
|
||||
@@ -821,18 +822,33 @@ export default {
|
||||
@headerFilterOn="handleHeaderFilter"
|
||||
>
|
||||
|
||||
<!--
|
||||
<template #actions>
|
||||
<div>
|
||||
<button
|
||||
class="btn btn-outline-success sm mb-1"
|
||||
:title="'Export ' + selectedPrestudents.length + ' prestudent(s) to Excel'"
|
||||
>
|
||||
<i class="fas fa-file-excel fa-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
-->
|
||||
|
||||
<template #actions>
|
||||
<!-- <div>
|
||||
<button
|
||||
class="btn btn-outline-success sm mb-1"
|
||||
:title="'Export ' + selectedPrestudents.length + ' prestudent(s) to Excel'"
|
||||
>
|
||||
<i class="fas fa-file-excel fa-xl"></i>
|
||||
</button>
|
||||
</div> -->
|
||||
<template v-if="filter.length || headerFilterActive">
|
||||
<div class="d-flex justify-content-center align-items-center gap-2 ps-4 position-absolute start-50 translate-middle-x">
|
||||
<p class="text-danger mb-0">
|
||||
<strong>{{$p.t('filter','filterActive')}}</strong>
|
||||
</p>
|
||||
|
||||
<button
|
||||
class="btn btn-outline-danger sm"
|
||||
:title="$p.t('filter/filterDelete')"
|
||||
@click="resetFilter"
|
||||
>
|
||||
<span class="fa-solid fa-filter-circle-xmark"></span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
|
||||
<template #additional>
|
||||
<div class="pe-1">
|
||||
@@ -842,50 +858,37 @@ export default {
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #actions>
|
||||
<core-tag ref="tagComponent"
|
||||
v-if="tagsEnabled"
|
||||
:endpoint="tagEndpoint"
|
||||
:values="selectedColumnValues"
|
||||
@added="addedTag"
|
||||
@deleted="deletedTag"
|
||||
@updated="updatedTag"
|
||||
zuordnung_typ="prestudent_id"
|
||||
></core-tag>
|
||||
|
||||
<button
|
||||
v-if="!selected.length"
|
||||
class="btn btn-outline btn-light mb-1"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' Stg ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> STG
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-outline btn-light mb-1"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' ' + $p.t('ui','selection') + ' ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> {{selected.length}}
|
||||
</button>
|
||||
|
||||
<template v-if="filter.length || headerFilterActive">
|
||||
<div class="d-flex justify-content-center align-items-center gap-2 ps-4 position-absolute start-50 translate-middle-x">
|
||||
<p class="text-danger mb-0">
|
||||
<strong>{{$p.t('filter','filterActive')}}</strong>
|
||||
</p>
|
||||
<template #tags>
|
||||
<div class="d-flex border rounded align-items-center ps-1">
|
||||
<core-tag ref="tagComponent"
|
||||
v-if="tagsEnabled"
|
||||
:endpoint="tagEndpoint"
|
||||
:values="selectedColumnValues"
|
||||
@added="addedTag"
|
||||
@deleted="deletedTag"
|
||||
@updated="updatedTag"
|
||||
zuordnung_typ="prestudent_id"
|
||||
show-hover
|
||||
></core-tag>
|
||||
|
||||
<button
|
||||
class="btn btn-outline-danger sm"
|
||||
:title="$p.t('filter/filterDelete')"
|
||||
@click="resetFilter"
|
||||
>
|
||||
<span class="fa-solid fa-filter-circle-xmark"></span>
|
||||
v-if="!selected.length"
|
||||
class="btn btn-outline btn-sm m-1 btn-hover"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' Stg ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> STG
|
||||
</button>
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-outline btn-sm m-1 btn-hover"
|
||||
@click="rebuild(selected)"
|
||||
:title="$p.t('tag','rebuild_tags') + ' ' + $p.t('ui','selection') + ' ' + currentSemester"
|
||||
>
|
||||
<i class="fa-solid fa-refresh pe-1"></i> {{selected.length}}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<template #filter>
|
||||
@@ -895,6 +898,7 @@ export default {
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
<list-new ref="new" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></list-new>
|
||||
|
||||
@@ -28,6 +28,10 @@ export default {
|
||||
confirmLimit: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
showHover: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -228,7 +232,8 @@ export default {
|
||||
<span :title="values.length === 0 ? 'Bitte Zeilen markieren' : ''">
|
||||
<button @mouseover="showList = true"
|
||||
:disabled="!values || values.length === 0"
|
||||
class="btn btn-sm">
|
||||
class="btn btn-sm"
|
||||
:class="{'btn-hover': showHover}">
|
||||
<i class="fa-solid fa-tag fa-xl"></i>
|
||||
</button>
|
||||
</span>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user