diff --git a/application/controllers/api/frontend/v1/LvPlan.php b/application/controllers/api/frontend/v1/LvPlan.php index 28b48e3f1..257c04960 100644 --- a/application/controllers/api/frontend/v1/LvPlan.php +++ b/application/controllers/api/frontend/v1/LvPlan.php @@ -41,7 +41,9 @@ class LvPlan extends FHCAPI_Controller 'getLehreinheitStudiensemester' => self::PERM_LOGGED, 'studiensemesterDateInterval' => self::PERM_LOGGED, 'getLvPlanForStudiensemester' => self::PERM_LOGGED, - 'getLv' => self::PERM_LOGGED + 'getLv' => self::PERM_LOGGED, + 'getLeEvents' => self::PERM_LOGGED, + 'getLvEvents' => self::PERM_LOGGED, ]); $this->load->library('LogLib'); @@ -54,6 +56,12 @@ class LvPlan extends FHCAPI_Controller )); $this->load->library('form_validation'); + $this->load->library('PhrasesLib'); + $this->loadPhrases( + array( + 'ui' + ) + ); } //------------------------------------------------------------------------------------------------------------------ @@ -145,6 +153,39 @@ class LvPlan extends FHCAPI_Controller )); } + public function getLeEvents($le_id = null, $start_date = null, $end_date = null, $stundenplan = 'stundenplandev') + { + + if (is_null($le_id) || is_null($start_date) || is_null($end_date)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + if ($stundenplan !== 'stundenplandev' && $stundenplan !== 'stundenplan') + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->library('StundenplanLib'); + + $result = $this->stundenplanlib->getEventsByLE($le_id, $start_date, $end_date, $stundenplan); + $lvplanEvents = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($lvplanEvents); + } + + public function getLvEvents($lv_id = null, $start_date = null, $end_date = null, $stundenplan = 'stundenplandev') + { + if (is_null($lv_id) || is_null($start_date) || is_null($end_date)) + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + if ($stundenplan !== 'stundenplandev' && $stundenplan !== 'stundenplan') + $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->library('StundenplanLib'); + + $result = $this->stundenplanlib->getEventsByLV($lv_id, $start_date, $end_date, $stundenplan); + $lvplanEvents = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($lvplanEvents); + } + //TODO: delete this function if we don't use the old calendar export endpoints anymore public function studiensemesterDateInterval($date){ $this->load->model('organisation/Studiensemester_model','StudiensemesterModel'); diff --git a/application/controllers/api/frontend/v1/lv/Noten.php b/application/controllers/api/frontend/v1/lv/Noten.php new file mode 100644 index 000000000..614ee6609 --- /dev/null +++ b/application/controllers/api/frontend/v1/lv/Noten.php @@ -0,0 +1,84 @@ + 'student/noten:r', + 'getTeacherProposal' => 'student/noten:r', + ]); + + // Load Libraries + $this->load->library('VariableLib', ['uid' => getAuthUID()]); + + // Load Phrases + $this->loadPhrases([ + 'stv', + 'person', + 'lehre' + ]); + } + + public function getCertificate($lv_id, $studiensemester_kurzbz = null) + { + if (is_null($lv_id) || !ctype_digit((string)$lv_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Zeugnisnote_model', 'ZeugnisnoteModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->LehrveranstaltungModel->loadWhere([ + 'lehrveranstaltung_id' => $lv_id + ]); + + $lehrveranstaltung = $this->getDataOrTerminateWithError($result); + + if (!$lehrveranstaltung) + $this->terminateWithSuccess([]); + + if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $result = $this->ZeugnisnoteModel->getZeugnisnoten(null, $studiensemester_kurzbz, $lehrveranstaltung[0]->lehrveranstaltung_id); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + + public function getTeacherProposal($lv_id, $studiensemester_kurzbz = null) + { + if (is_null($lv_id) || !ctype_digit((string)$lv_id)) + $this->terminateWithError( $this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL); + + $this->load->model('education/lehrveranstaltung_model', 'LehrveranstaltungModel'); + $this->load->model('education/Lvgesamtnote_model', 'LvgesamtnoteModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $result = $this->LehrveranstaltungModel->loadWhere([ + 'lehrveranstaltung_id' => $lv_id + ]); + + $lehrveranstaltung = $this->getDataOrTerminateWithError($result); + + if (!$lehrveranstaltung) + $this->terminateWithSuccess([]); + + if ($studiensemester_kurzbz !== null && !$this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz)) + { + $this->terminateWithError($studiensemester_kurzbz . ' - ' . $this->p->t('lehre', 'error_noStudiensemester')); + } + + $result = $this->LvgesamtnoteModel->getLvGesamtNoten($lv_id, null, $studiensemester_kurzbz); + + $grades = $this->getDataOrTerminateWithError($result); + + $this->terminateWithSuccess($grades); + } + +} diff --git a/application/controllers/api/frontend/v1/lv/Setup.php b/application/controllers/api/frontend/v1/lv/Setup.php index a2c167dd6..e506a9d1b 100644 --- a/application/controllers/api/frontend/v1/lv/Setup.php +++ b/application/controllers/api/frontend/v1/lv/Setup.php @@ -27,7 +27,8 @@ class Setup extends FHCAPI_Controller public function __construct() { parent::__construct([ - 'getTabs' => ['admin:r', 'assistenz:r'], + 'getLETabs' => ['admin:r', 'assistenz:r'], + 'getLVTabs' => ['admin:r', 'assistenz:r'], 'getStudiensemester' => ['admin:r', 'assistenz:r'], 'getSprache' => ['admin:r', 'assistenz:r'], 'getRaumtyp' => ['admin:r', 'assistenz:r'], @@ -41,9 +42,10 @@ class Setup extends FHCAPI_Controller $this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel'); $this->_ci->load->library('VariableLib', ['uid' => $this->_uid]); + $this->_ci->load->helper('hlp_document'); } - public function getTabs() + public function getLETabs() { $tabs['details'] = array ( 'title' => 'Details', @@ -60,6 +62,11 @@ class Setup extends FHCAPI_Controller 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Lektor.js', 'config' => [] ); + $tabs['termine'] = array ( + 'title' => 'Termine', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Termine.js', + 'config' => [] + ); $tabs['notiz'] = array ( 'title' => 'Notizen', 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Notiz.js', @@ -68,6 +75,28 @@ class Setup extends FHCAPI_Controller $this->terminateWithSuccess($tabs); } + public function getLVTabs() + { + $tabs['termine'] = array ( + 'title' => 'Termine', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/LVTermine.js', + 'config' => [] + ); + $tabs['noten'] = array ( + 'title' => 'Noten', + 'component' => APP_ROOT . 'public/js/components/LVVerwaltung/Tabs/Noten.js', + 'config' => [ + 'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE, + 'edit' => 'both', // Possible values: both|header|inline + 'delete' => 'inline', // Possible values: both|header|inline + 'documents' => 'inline', // Possible values: both|header|inline + 'documentslist' => gradesDocumentsList(), + 'semesterSelect' => false + ] + ); + $this->terminateWithSuccess($tabs); + } + public function getStudiensemester() { $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php index 17b360f8c..957b00134 100644 --- a/application/controllers/api/frontend/v1/stv/Config.php +++ b/application/controllers/api/frontend/v1/stv/Config.php @@ -299,6 +299,7 @@ class Config extends FHCAPI_Controller public function student() { + $this->load->helper('hlp_document'); $result = []; $config = $this->config->item('tabs'); @@ -374,9 +375,9 @@ class Config extends FHCAPI_Controller 'config' => [ 'usePoints' => defined('CIS_GESAMTNOTE_PUNKTE') && CIS_GESAMTNOTE_PUNKTE, 'edit' => 'both', // Possible values: both|header|inline - 'delete' => 'both', // Possible values: both|header|inline - 'documents' => 'both', // Possible values: both|header|inline - 'documentslist' => $this->gradesDocumentsList() + 'delete' => 'inline', // Possible values: both|header|inline + 'documents' => 'inline', // Possible values: both|header|inline + 'documentslist' => gradesDocumentsList() ] ]; @@ -620,188 +621,6 @@ class Config extends FHCAPI_Controller ] + $this->kontoColumns(); } - /** - * Helper function to generate the default documentslist config for the - * grades tab. - * - * The resulting array consists of elements which are associative arrays - * that can have the following entries: - * title (required) on the first level this can be HTML code. - * permissioncheck (optional) an URL to an FHCAPI endpoint which returns - * true or false. - * link (optional) an URL that will be called if "action" and - * "children" are not defined. - * action (optional) an associative array that describes an - * POST action that will be called if "children" is - * not defined. - * It can have the following entries: - * - url (required) an URL to an FHCAPI endpoint. - * - post (optional) an associative array with the POST data to - * be sent. - * - response (optional) a string that will be displayed on success. - * children (optional) an array of child elements - * - * All strings that start with { and end with } in the URLs and the - * actions post parameter will be replaced with the corresponding - * attribute of the current dataset (e.G: {uid} will be replaced with the - * uid of the current dataset) - * - * @return array - */ - protected function gradesDocumentsList() - { - $permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}"); - - $title_ger = $this->p->t("global", "deutsch"); - $title_eng = $this->p->t("global", "englisch"); - $title_ff = $this->p->t("stv", "document_certificate"); - $title_lv = $this->p->t("stv", "document_coursecertificate"); - - $link_ff = "documents/export/" . - "zertifikat.rdf.php/" . - "Zertifikat" . - "?stg_kz={studiengang_kz_lv}" . - "&uid={uid}" . - "&ss={studiensemester_kurzbz}" . - "&lvid={lehrveranstaltung_id}"; - $link_lv_ger = "documents/export/" . - "lehrveranstaltungszeugnis.rdf.php/" . - "LVZeugnis" . - "?stg_kz={studiengang_kz}" . - "&uid={uid}" . - "&ss={studiensemester_kurzbz}" . - "&lvid={lehrveranstaltung_id}"; - $link_lv_eng = "documents/export/" . - "lehrveranstaltungszeugnis.rdf.php/" . - "LVZeugnisEng" . - "?stg_kz={studiengang_kz}" . - "&uid={uid}" . - "&ss={studiensemester_kurzbz}" . - "&lvid={lehrveranstaltung_id}"; - - $archive_url = "api/frontend/v1/documents/archiveSigned"; - $archive_response = $this->p->t("stv", "document_signed_and_archived"); - $archive_post_ff = [ - "xml" => "zertifikat.rdf.php", - "xsl" => "Zertifikat", - "stg_kz" => "{studiengang_kz_lv}", - "uid" => "{uid}", - "ss" => "{studiensemester_kurzbz}", - "lvid" => "{lehrveranstaltung_id}" - ]; - $archive_post_lv_ger = [ - "xml" => "lehrveranstaltungszeugnis.rdf.php", - "xsl" => "LVZeugnis", - "stg_kz" => "{studiengang_kz}", - "uid" => "{uid}", - "ss" => "{studiensemester_kurzbz}", - "lvid" => "{lehrveranstaltung_id}" - ]; - $archive_post_lv_eng = [ - "xml" => "lehrveranstaltungszeugnis.rdf.php", - "xsl" => "LVZeugnisEng", - "stg_kz" => "{studiengang_kz}", - "uid" => "{uid}", - "ss" => "{studiensemester_kurzbz}", - "lvid" => "{lehrveranstaltung_id}" - ]; - - $list = [ - [ - 'title' => '', - 'children' => [ - [ - 'title' => $title_ff, - 'link' => site_url($link_ff) - ], - [ - 'title' => $title_lv, - 'children' => [ - [ - 'title' => $title_ger, - 'link' => site_url($link_lv_ger), - 'children' => [ - [ - 'title' => 'PDF', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_ger) - ], - [ - 'title' => 'DOC', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_ger . "&output=doc") - ], - [ - 'title' => 'ODT', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_ger . "&output=odt") - ] - ] - ], - [ - 'title' => $title_eng, - 'link' => site_url($link_lv_eng), - 'children' => [ - [ - 'title' => 'PDF', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_eng) - ], - [ - 'title' => 'DOC', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_eng . "&output=doc") - ], - [ - 'title' => 'ODT', - 'permissioncheck' => $permissioncheck, - 'link' => site_url($link_lv_eng . "&output=odt") - ] - ] - ] - ] - ] - ] - ], - [ - 'title' => '', - 'children' => [ - [ - 'title' => $title_ff, - 'action' => [ - 'url' => site_url($archive_url), - 'post' => $archive_post_ff, - 'response' => $archive_response - ] - ], - [ - 'title' => $title_lv, - 'children' => [ - [ - 'title' => $title_ger, - 'action' => [ - 'url' => site_url($archive_url), - 'post' => $archive_post_lv_ger, - 'response' => $archive_response - ] - ], - [ - 'title' => $title_eng, - 'action' => [ - 'url' => site_url($archive_url), - 'post' => $archive_post_lv_eng, - 'response' => $archive_response - ] - ] - ] - ] - ] - ] - ]; - - return $list; - } - /** * Sort tab list * diff --git a/application/controllers/api/frontend/v1/stv/LvTermine.php b/application/controllers/api/frontend/v1/stv/LvTermine.php index c29f56964..b9e23e77d 100644 --- a/application/controllers/api/frontend/v1/stv/LvTermine.php +++ b/application/controllers/api/frontend/v1/stv/LvTermine.php @@ -34,7 +34,7 @@ class LvTermine extends FHCAPI_Controller //TODO Build own lib or combine with Controller Stundenplan.php //here use of logic of Stundenplan.php, extended with parameters uid, grouping, and used dbTable - public function getStundenplan($uid, $start_date = null, $end_date = null, $groupConsecutiveHours = false, $dbStundenplanTable = "stundenplan") + public function getStundenplan($uid, $start_date = null, $end_date = null, $dbStundenplanTable = "stundenplan", $groupConsecutiveHours = false) { $student_uid = $uid; $semester_range = $this->studienSemesterErmitteln($start_date, $end_date); @@ -80,13 +80,6 @@ class LvTermine extends FHCAPI_Controller $stundenplan_data = $this->getDataOrTerminateWithError($stundenplan_data) ?? []; $this->terminateWithSuccess($stundenplan_data); - - $this->expand_object_information($stundenplan_data); - - $this->returnObj['$stundenplan_query'] = $stundenplan_query; - $this->returnObj['$student_lehrverband'] = $student_lehrverband; - $this->returnObj['$benutzer_gruppen'] = $benutzer_gruppen; - $this->terminateWithSuccess($stundenplan_data); } public function getStudiensemester() diff --git a/application/helpers/hlp_document_helper.php b/application/helpers/hlp_document_helper.php new file mode 100644 index 000000000..5b457fe82 --- /dev/null +++ b/application/helpers/hlp_document_helper.php @@ -0,0 +1,188 @@ +load->library('PhrasesLib', array('stv'), 'p'); + + $permissioncheck = site_url("api/frontend/v1/documents/permissionAlternativeFormat/{studiengang_kz}"); + + $title_ger = $ci->p->t("global", "deutsch"); + $title_eng = $ci->p->t("global", "englisch"); + $title_ff = $ci->p->t("stv", "document_certificate"); + $title_lv = $ci->p->t("stv", "document_coursecertificate"); + + $link_ff = "documents/export/" . + "zertifikat.rdf.php/" . + "Zertifikat" . + "?stg_kz={studiengang_kz_lv}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + $link_lv_ger = "documents/export/" . + "lehrveranstaltungszeugnis.rdf.php/" . + "LVZeugnis" . + "?stg_kz={studiengang_kz}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + $link_lv_eng = "documents/export/" . + "lehrveranstaltungszeugnis.rdf.php/" . + "LVZeugnisEng" . + "?stg_kz={studiengang_kz}" . + "&uid={uid}" . + "&ss={studiensemester_kurzbz}" . + "&lvid={lehrveranstaltung_id}"; + + $archive_url = "api/frontend/v1/documents/archiveSigned"; + $archive_response = $ci->p->t("stv", "document_signed_and_archived"); + $archive_post_ff = [ + "xml" => "zertifikat.rdf.php", + "xsl" => "Zertifikat", + "stg_kz" => "{studiengang_kz_lv}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + $archive_post_lv_ger = [ + "xml" => "lehrveranstaltungszeugnis.rdf.php", + "xsl" => "LVZeugnis", + "stg_kz" => "{studiengang_kz}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + $archive_post_lv_eng = [ + "xml" => "lehrveranstaltungszeugnis.rdf.php", + "xsl" => "LVZeugnisEng", + "stg_kz" => "{studiengang_kz}", + "uid" => "{uid}", + "ss" => "{studiensemester_kurzbz}", + "lvid" => "{lehrveranstaltung_id}" + ]; + + $list = [ + [ + 'title' => '', + 'children' => [ + [ + 'title' => $title_ff, + 'link' => site_url($link_ff) + ], + [ + 'title' => $title_lv, + 'children' => [ + [ + 'title' => $title_ger, + 'link' => site_url($link_lv_ger), + 'children' => [ + [ + 'title' => 'PDF', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger) + ], + [ + 'title' => 'DOC', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger . "&output=doc") + ], + [ + 'title' => 'ODT', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_ger . "&output=odt") + ] + ] + ], + [ + 'title' => $title_eng, + 'link' => site_url($link_lv_eng), + 'children' => [ + [ + 'title' => 'PDF', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng) + ], + [ + 'title' => 'DOC', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng . "&output=doc") + ], + [ + 'title' => 'ODT', + 'permissioncheck' => $permissioncheck, + 'link' => site_url($link_lv_eng . "&output=odt") + ] + ] + ] + ] + ] + ] + ], + [ + 'title' => '', + 'children' => [ + [ + 'title' => $title_ff, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_ff, + 'response' => $archive_response + ] + ], + [ + 'title' => $title_lv, + 'children' => [ + [ + 'title' => $title_ger, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_lv_ger, + 'response' => $archive_response + ] + ], + [ + 'title' => $title_eng, + 'action' => [ + 'url' => site_url($archive_url), + 'post' => $archive_post_lv_eng, + 'response' => $archive_response + ] + ] + ] + ] + ] + ] + ]; + + return $list; +} diff --git a/application/libraries/StundenplanLib.php b/application/libraries/StundenplanLib.php index 7ed64da2c..b65922633 100644 --- a/application/libraries/StundenplanLib.php +++ b/application/libraries/StundenplanLib.php @@ -181,6 +181,21 @@ class StundenplanLib return success($stundenplan_data); } + public function getEventsByLE($lehreinheit_id, $start, $end, $stundenplan) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + return $this->_ci->StundenplanModel->getStundenplanLE($lehreinheit_id, $start, $end, $stundenplan); + } + + public function getEventsByLV($lehrveranstaltung_id, $start, $end, $stundenplan) + { + $this->_ci =& get_instance(); + + $this->_ci->load->model('ressource/Stundenplan_model', 'StundenplanModel'); + return $this->_ci->StundenplanModel->getStundenplanLV($lehrveranstaltung_id, $start, $end, $stundenplan); + } /** * Get stundenplan for a room * diff --git a/application/models/education/Lvgesamtnote_model.php b/application/models/education/Lvgesamtnote_model.php index c30045ff0..0a7638869 100644 --- a/application/models/education/Lvgesamtnote_model.php +++ b/application/models/education/Lvgesamtnote_model.php @@ -29,10 +29,14 @@ class Lvgesamtnote_model extends DB_Model $this->addSelect("lv.bezeichnung AS lehrveranstaltung_bezeichnung"); $this->addSelect("lv.studiengang_kz"); $this->addSelect("UPPER(stg.typ || stg.kurzbz) AS studiengang"); + $this->addSelect("person.vorname"); + $this->addSelect("person.nachname"); $this->addJoin("lehre.tbl_note n", "note"); $this->addJoin("lehre.tbl_lehrveranstaltung lv", "lehrveranstaltung_id"); $this->addJoin("public.tbl_studiengang stg", "studiengang_kz"); + $this->addJoin("public.tbl_benutzer benutzer", "uid = student_uid", "LEFT"); + $this->addJoin("public.tbl_person person", "person_id", "LEFT"); $this->db->where($this->dbTable . ".freigabedatum <", "NOW()", false); diff --git a/application/models/education/Zeugnisnote_model.php b/application/models/education/Zeugnisnote_model.php index f32713dec..694c5d5c0 100644 --- a/application/models/education/Zeugnisnote_model.php +++ b/application/models/education/Zeugnisnote_model.php @@ -148,7 +148,7 @@ class Zeugnisnote_model extends DB_Model * * @return object */ - public function getZeugnisnoten($student_uid, $studiensemester_kurzbz) + public function getZeugnisnoten($student_uid, $studiensemester_kurzbz, $lehrveranstaltung_id = null) { $params = array(); $where=''; @@ -163,6 +163,11 @@ class Zeugnisnote_model extends DB_Model $where.=" AND vw_student_lehrveranstaltung.studiensemester_kurzbz= ?"; $params[] = $studiensemester_kurzbz; } + if($lehrveranstaltung_id != null) + { + $where .= " AND vw_student_lehrveranstaltung.lehrveranstaltung_id = ?"; + $params[] = $lehrveranstaltung_id; + } $where2=''; @@ -176,6 +181,11 @@ class Zeugnisnote_model extends DB_Model $where2 .= " AND studiensemester_kurzbz= ?"; $params[] = $studiensemester_kurzbz; } + if($lehrveranstaltung_id != null) + { + $where2 .=" AND lehrveranstaltung_id = ?"; + $params[] = $lehrveranstaltung_id; + } $qry = "SELECT a.*, @@ -188,7 +198,10 @@ class Zeugnisnote_model extends DB_Model lv.semester AS semester_lv, lv.ects AS ects_lv, lv.zeugnis, - lv.bezeichnung_english AS lehrveranstaltung_bezeichnung_english + lv.bezeichnung_english AS lehrveranstaltung_bezeichnung_english, + s.verband, + person.vorname, + person.nachname FROM ( SELECT vw_student_lehrveranstaltung.lehrveranstaltung_id, uid, vw_student_lehrveranstaltung.studiensemester_kurzbz, note, punkte, uebernahmedatum, benotungsdatum, @@ -231,6 +244,8 @@ class Zeugnisnote_model extends DB_Model ORDER BY sort ) a LEFT JOIN public.tbl_student s ON (a.uid = s.student_uid) + LEFT JOIN public.tbl_benutzer benutzer ON benutzer.uid = s.student_uid + LEFT JOIN public.tbl_person person ON benutzer.person_id = person.person_id LEFT JOIN public.tbl_studiengang stg1 ON (s.studiengang_kz = stg1.studiengang_kz) LEFT JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id) LEFT JOIN public.tbl_studiengang stg2 ON (lv.studiengang_kz = stg2.studiengang_kz)"; diff --git a/application/models/ressource/Stundenplan_model.php b/application/models/ressource/Stundenplan_model.php index 067e2b790..0bfd3c2f1 100644 --- a/application/models/ressource/Stundenplan_model.php +++ b/application/models/ressource/Stundenplan_model.php @@ -333,6 +333,64 @@ class Stundenplan_model extends DB_Model ", [$start_date, $end_date, $lv_id]); } + public function getStundenplanLE($lehreinheit, $start_date, $end_date, $stundenplan) + { + $qry = " + WITH lehreinheiten AS ( + SELECT lehreinheit_id FROM lehre.tbl_lehreinheit WHERE lehreinheit_id = ? + ), " . $this->getStundenplanCTE($stundenplan) . " + SELECT * + FROM stundenplanentries + "; + + return $this->execReadOnlyQuery($qry, array($lehreinheit, $start_date, $end_date)); + } + + public function getStundenplanLV($lehrveranstaltung_id, $start_date, $end_date, $stundenplan) + { + $qry = " + WITH lehreinheiten AS ( + SELECT lehreinheit_id FROM lehre.tbl_lehreinheit WHERE lehrveranstaltung_id = ? + ), " . $this->getStundenplanCTE($stundenplan) . " + SELECT * + FROM stundenplanentries + "; + + return $this->execReadOnlyQuery($qry, array($lehrveranstaltung_id, $start_date, $end_date)); + } + + private function getStundenplanCTE($stundenplan) + { + return "entries AS ( + SELECT + datum, min(stunde) as stunde_beginn, max(stunde) as stunde_ende, + array_agg(DISTINCT( + CASE WHEN gruppe_kurzbz is not null THEN gruppe_kurzbz + ELSE (UPPER(stg_typ || stg_kurzbz) || COALESCE(semester,'0') || COALESCE(verband,'') || COALESCE(gruppe,'')) + END)) as gruppen_kuerzel, + array_agg(DISTINCT CONCAT(vorname || ' ' || nachname)) as lektorname, + array_agg(DISTINCT stundenplan.ort_kurzbz) as ort_kurzbz, + array_agg(DISTINCT titel) as titel, + lehrfach_bez, stundenplan.lehreinheit_id, lehrveranstaltung_id + FROM lehre.vw_$stundenplan as stundenplan + JOIN public.tbl_mitarbeiter ON stundenplan.uid = tbl_mitarbeiter.mitarbeiter_uid + JOIN tbl_benutzer ON tbl_mitarbeiter.mitarbeiter_uid = tbl_benutzer.uid + JOIN tbl_person USING(person_id) + JOIN lehreinheiten ON stundenplan.lehreinheit_id = lehreinheiten.lehreinheit_id + WHERE datum >= ? AND datum <= ? + GROUP BY datum, unr, stundenplan.lehreinheit_id, lehrveranstaltung_id, lehrfach_bez, lehrfach_bez + ORDER BY datum, min(stunde), unr, lehreinheit_id + ), + stundenplanentries AS ( + SELECT + entries.*, + stundeb.beginn AS beginn, + stundee.ende AS ende + FROM entries + JOIN lehre.tbl_stunde stundeb ON stundeb.stunde = entries.stunde_beginn + JOIN lehre.tbl_stunde stundee ON stundee.stunde = entries.stunde_ende + )"; + } /** * queries Stundenplan and filters by assigned ma_kurzbz, very similar to get by LVA * diff --git a/public/js/api/factory/stv/coursedates.js b/public/js/api/factory/stv/coursedates.js index 71ded7285..dc047f815 100644 --- a/public/js/api/factory/stv/coursedates.js +++ b/public/js/api/factory/stv/coursedates.js @@ -16,16 +16,20 @@ */ export default { - getCourselist(params) { + getCourselist(student_uid, start_date, end_date, stundenplan) { return { method: 'get', - url: 'api/frontend/v1/stv/LvTermine/getStundenplan/' + params.student_uid + '/' - + params.start_date + '/' - + params.end_date + '/' - + params.group_consecutiveHours + '/' - + params.dbStundenplanTable + url: 'api/frontend/v1/stv/LvTermine/getStundenplan/' + encodeURIComponent(student_uid) + '/' + + encodeURIComponent(start_date) + '/' + + encodeURIComponent(end_date) + '/' + + encodeURIComponent(stundenplan) + '/' + + encodeURIComponent(true) }; }, + exportCalendar(student_uid, stundenplan) + { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + 'content/statistik/termine.xls.php?student_uid=' + encodeURIComponent(student_uid) + '&db_stpl_table='+encodeURIComponent(stundenplan); + }, getStudiensemester(){ return { method: 'get', diff --git a/public/js/api/lehrveranstaltung/letermine.js b/public/js/api/lehrveranstaltung/letermine.js new file mode 100644 index 000000000..e5b3093f5 --- /dev/null +++ b/public/js/api/lehrveranstaltung/letermine.js @@ -0,0 +1,19 @@ +export default { + getCourselist(le_id, start_date, end_date, stundenplan) + { + return { + method: 'get', + url: '/api/frontend/v1/lvPlan/getLeEvents/' + encodeURIComponent(le_id) + "/" + encodeURIComponent(start_date) + "/" + encodeURIComponent(end_date) + "/" + encodeURIComponent(stundenplan), + }; + }, + exportCalendar(le_id, stundenplan) + { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + 'content/statistik/termine.xls.php?lehreinheit_id=' + encodeURIComponent(le_id) + '&db_stpl_table='+encodeURIComponent(stundenplan); + }, + getStudiensemester(){ + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getStudiensemester/' + }; + }, +}; diff --git a/public/js/api/lehrveranstaltung/lvtermine.js b/public/js/api/lehrveranstaltung/lvtermine.js new file mode 100644 index 000000000..35fdc5ca8 --- /dev/null +++ b/public/js/api/lehrveranstaltung/lvtermine.js @@ -0,0 +1,19 @@ +export default { + getCourselist(lv_id, start_date, end_date, stundenplan) + { + return { + method: 'get', + url: '/api/frontend/v1/lvPlan/getLvEvents/' + encodeURIComponent(lv_id) + "/" + encodeURIComponent(start_date) + "/" + encodeURIComponent(end_date) + "/" + encodeURIComponent(stundenplan), + }; + }, + exportCalendar(lv_id, stundenplan) + { + return FHC_JS_DATA_STORAGE_OBJECT.app_root + 'content/statistik/termine.xls.php?lehrveranstaltung_id=' + encodeURIComponent(lv_id) + '&db_stpl_table='+encodeURIComponent(stundenplan); + }, + getStudiensemester(){ + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getStudiensemester/' + }; + }, +}; diff --git a/public/js/api/lehrveranstaltung/noten.js b/public/js/api/lehrveranstaltung/noten.js new file mode 100644 index 000000000..fdcbb6f1e --- /dev/null +++ b/public/js/api/lehrveranstaltung/noten.js @@ -0,0 +1,25 @@ +import Grades from '../factory/stv/grades.js'; + +export default { + ...Grades, + getCertificate(lv_id, studiensemester_kurzbz) { + let url = 'api/frontend/v1/lv/noten/getCertificate/' + encodeURIComponent(lv_id); + if (!!studiensemester_kurzbz) { + url = url + '/' + encodeURIComponent(studiensemester_kurzbz); + } + return { + method: 'get', + url: url + }; + }, + getTeacherProposal(lv_id, studiensemester_kurzbz) { + let url = 'api/frontend/v1/lv/noten/getTeacherProposal/' + encodeURIComponent(lv_id); + if (!!studiensemester_kurzbz) { + url = url + '/' + encodeURIComponent(studiensemester_kurzbz); + } + return { + method: 'get', + url: url + }; + }, +}; \ No newline at end of file diff --git a/public/js/api/lehrveranstaltung/setup.js b/public/js/api/lehrveranstaltung/setup.js index 78f78b05b..dab1062a4 100644 --- a/public/js/api/lehrveranstaltung/setup.js +++ b/public/js/api/lehrveranstaltung/setup.js @@ -1,9 +1,16 @@ export default { - getTabs() + getLETabs() { return { method: 'get', - url: '/api/frontend/v1/lv/setup/getTabs/' + url: '/api/frontend/v1/lv/setup/getLETabs/' + }; + }, + getLVTabs() + { + return { + method: 'get', + url: '/api/frontend/v1/lv/setup/getLVTabs/' }; }, } diff --git a/public/js/components/LVVerwaltung/LVVerwaltung.js b/public/js/components/LVVerwaltung/LVVerwaltung.js index 42c50bdfa..e9c1da205 100644 --- a/public/js/components/LVVerwaltung/LVVerwaltung.js +++ b/public/js/components/LVVerwaltung/LVVerwaltung.js @@ -8,7 +8,6 @@ import LvTabs from "./Setup/Tabs.js"; import ApiDetails from "../../api/lehrveranstaltung/details.js"; import ApiLektor from "../../api/lehrveranstaltung/lektor.js"; -import ApiGruppe from "../../api/lehrveranstaltung/gruppe.js"; import ApiStudiengangTree from "../../api/lehrveranstaltung/studiengangtree.js"; import ApiSearchbar from "../../api/factory/searchbar.js"; diff --git a/public/js/components/LVVerwaltung/Setup/Table.js b/public/js/components/LVVerwaltung/Setup/Table.js index db1053875..33439b057 100644 --- a/public/js/components/LVVerwaltung/Setup/Table.js +++ b/public/js/components/LVVerwaltung/Setup/Table.js @@ -368,14 +368,13 @@ export default { if (data[0]?.lehreinheit_id !== undefined && this.selectedColumnValues.length === 1) { - this.$emit('update:selected', [data[0]]); this.lv_info = false } else if (data[0]?.lehrveranstaltung_id) { - this.$emit('update:selected', {}); this.getLVInfos(data[0]); } + this.$emit('update:selected', [data[0]]); }, getLVInfos(data) { diff --git a/public/js/components/LVVerwaltung/Setup/Tabs.js b/public/js/components/LVVerwaltung/Setup/Tabs.js index 62c5bbc31..5425b5169 100644 --- a/public/js/components/LVVerwaltung/Setup/Tabs.js +++ b/public/js/components/LVVerwaltung/Setup/Tabs.js @@ -8,6 +8,7 @@ export default { }, data() { return { + configLETabs: {}, configLVTabs: {}, }; }, @@ -19,7 +20,7 @@ export default { if (!this.lv || !this.lv.length) return {}; - return this.configLVTabs; + return this.configLETabs; } }, methods: { @@ -31,25 +32,42 @@ export default { } }, created() { - this.$api.call(Setup.getTabs()) + this.$api.call(Setup.getLETabs()) + .then(result => { + this.configLETabs = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + + this.$api.call(Setup.getLVTabs()) .then(result => { this.configLVTabs = result.data; }) .catch(this.$fhcAlert.handleSystemError); - }, template: `
Bitte eine Lehreinheit auswählen!
-
+
+
diff --git a/public/js/components/LVVerwaltung/Tabs/LVTermine.js b/public/js/components/LVVerwaltung/Tabs/LVTermine.js new file mode 100644 index 000000000..e064dbae9 --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/LVTermine.js @@ -0,0 +1,21 @@ +import TableLvList from "../../Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js"; +import ApiLVTermine from "../../../api/lehrveranstaltung/lvtermine.js"; + +export default { + name: "LVTabTermine", + components: { + TableLvList + }, + props: { + modelValue: Object, + }, + data() { + return { + endpoint: ApiLVTermine + }; + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Tabs/Noten.js b/public/js/components/LVVerwaltung/Tabs/Noten.js new file mode 100644 index 000000000..8b01a017d --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/Noten.js @@ -0,0 +1,116 @@ +import NotenZeugnis from "../../Stv/Studentenverwaltung/Details/Noten/Zeugnis.js"; +import NotenTeacher from "../../Stv/Studentenverwaltung/Details/Noten/Teacher.js"; +import NotenRepeater from "../../Stv/Studentenverwaltung/Details/Noten/Repeater.js"; +import ApiLVNoten from "../../../api/lehrveranstaltung/noten.js"; +import { highlightGesamtnote } from "../../../helpers/DocumentHelper.js"; +const LOCAL_STORAGE_ID = 'lv_details_noten_2025_12_02_stdsem_all'; + +export default { + name: "LVTabNoten", + components: { + NotenZeugnis, + NotenTeacher, + NotenRepeater + }, + provide() { + return { + config: this.config + } + }, + props: { + modelValue: Object, + config: Object + }, + data() { + return { + stdsem: '', + endpoint: ApiLVNoten, + tabulatorOptions: { + visibleColumns: { + vorname: true, + nachname: true, + lehrveranstaltung_bezeichnung: false + }, + headerFilter: { + vorname: true, + nachname: true, + lehrveranstaltung_bezeichnung: false + }, + persistenceZeugnisID: 'lv-details-noten-zeugnis-2025120401', + persistenceTeacherID: 'lv-details-noten-teacher-2025120401', + }, + zeugnisLoaded: false, + teacherLoaded: false, + }; + }, + methods: { + reload() { + this.zeugnisLoaded = false; + this.teacherLoaded = false; + + this.$refs.zeugnis.$refs.table.reloadTable(); + this.$refs.teacher.$refs.table.reloadTable(); + }, + saveStdsem(event) { + window.localStorage.setItem(LOCAL_STORAGE_ID, event.target.value); + }, + onZeugnisLoaded() { + this.zeugnisLoaded = true; + this.checkHighlight(); + }, + onTeacherLoaded() { + this.teacherLoaded = true; + this.checkHighlight(); + }, + checkHighlight() + { + if (!this.zeugnisLoaded || !this.teacherLoaded) + return; + + if (!this.$refs.zeugnis || !this.$refs.teacher) + return; + + let zeugnisTable = this.$refs.zeugnis.$refs.table.tabulator; + let teacherTable = this.$refs.teacher.$refs.table.tabulator; + + if (!zeugnisTable || !teacherTable) + return; + + highlightGesamtnote(zeugnisTable, teacherTable); + } + }, + created() { + const savedPath = window.localStorage.getItem(LOCAL_STORAGE_ID); + this.stdsem = savedPath || ''; + }, + template: ` +
+
+ +
+
+
+ +
+
+ +
+
+
` +}; \ No newline at end of file diff --git a/public/js/components/LVVerwaltung/Tabs/Termine.js b/public/js/components/LVVerwaltung/Tabs/Termine.js new file mode 100644 index 000000000..8b005b6b4 --- /dev/null +++ b/public/js/components/LVVerwaltung/Tabs/Termine.js @@ -0,0 +1,21 @@ +import TableLvList from "../../Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js"; +import ApiLETermine from "../../../api/lehrveranstaltung/letermine.js"; + +export default { + name: "LETabTermine", + components: { + TableLvList + }, + props: { + modelValue: Object, + }, + data() { + return { + endpoint: ApiLETermine + }; + }, + template: ` +
+ +
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js index 6845613ab..6eb324f27 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine.js @@ -1,4 +1,5 @@ import TableLvList from "./Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js"; +import ApiStvCoursedates from "../../../../api/factory/stv/coursedates.js"; export default { name: "TabCourseList", @@ -8,11 +9,13 @@ export default { props: { modelValue: Object, }, - data(){ - return {} + data() { + return { + endpoint: ApiStvCoursedates + }; }, template: `
- +
` }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js index 20cb95fbd..67052460c 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Lehrveranstaltungstermine/ListLehrveranstaltungstermine.js @@ -2,8 +2,6 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; import FormInput from "../../../../Form/Input.js"; import FormForm from '../../../../Form/Form.js'; -import ApiStvCoursedates from "../../../../../api/factory/stv/coursedates.js"; - export default { name: "TblCourseList", components: { @@ -12,17 +10,6 @@ export default { FormForm }, computed: { - downloadLink: function(){ - if(!this.dataSem.start || !this.dataSem.ende || !this.student.uid) return; - let start = new Date(this.dataSem.start); - start = Math.floor(start.getTime()/1000); - let ende = new Date(this.dataSem.ende); - ende = Math.floor(ende.getTime() / 1000); - - let link = - FHC_JS_DATA_STORAGE_OBJECT.app_root + "cis/private/lvplan/stpl_kalender.php?type=student&pers_uid=" + this.student.uid + "&begin=" + start + "&ende= " +ende + "&format=excel"; - return link; - }, dbStundenplanTable: function (){ return this.showStundenplanDev ? 'stundenplandev' : 'stundenplan'; } @@ -33,7 +20,14 @@ export default { }, }, props: { - student: Object + id: { + type: [Number, String], + required: true + }, + endpoint: { + type: Object, + required: true + }, }, data(){ return { @@ -48,14 +42,7 @@ export default { initTabulatorOptions(){ this.tabulatorOptions = { ajaxURL: 'dummy', - ajaxRequestFunc: () => this.$api.call( - ApiStvCoursedates.getCourselist({ - student_uid: this.student.uid, - start_date: this.dataSem.start, - end_date: this.dataSem.ende, - group_consecutiveHours: true, - dbStundenplanTable: this.dbStundenplanTable}) - ), + ajaxRequestFunc: () => this.$api.call(this.endpoint.getCourselist(this.id, this.dataSem.start, this.dataSem.ende, this.dbStundenplanTable)), ajaxResponse: (url, params, response) => { return response.data; }, @@ -137,7 +124,7 @@ export default { this.dataSem = this.listStudiensemester.find(item => item.studiensemester_kurzbz === studiensemester_kurzbz); }, exportToExcel(){ - window.open(this.downloadLink, '_blank'); + window.open(this.endpoint.exportCalendar(this.id, this.dbStundenplanTable), '_blank'); }, reload() { this.$refs.table.reloadTable(); @@ -151,10 +138,13 @@ export default { currentSemester(newVal, oldVal) { this.getDatesOfSemester(newVal); }, + id() { + this.reload(); + } }, created(){ this.$api - .call(ApiStvCoursedates.getStudiensemester()) + .call(this.endpoint.getStudiensemester()) .then(result => { this.listStudiensemester = result.data; this.getDatesOfSemester(this.currentSemester); diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten.js index 71b8096ec..3217f192c 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten.js @@ -2,6 +2,9 @@ import NotenZeugnis from './Noten/Zeugnis.js'; import NotenTeacher from './Noten/Teacher.js'; import NotenRepeater from './Noten/Repeater.js'; +import ApiStvGrades from '../../../../api/factory/stv/grades.js'; +import { highlightGesamtnote } from "../../../../helpers/DocumentHelper"; + const LOCAL_STORAGE_ID = 'stv_details_noten_2024-11-25_stdsem_all'; export default { @@ -22,7 +25,10 @@ export default { }, data() { return { - stdsem: '' + stdsem: '', + endpoint: ApiStvGrades, + zeugnisLoaded: false, + teacherLoaded: false, }; }, methods: { @@ -33,6 +39,30 @@ export default { }, saveStdsem(event) { window.localStorage.setItem(LOCAL_STORAGE_ID, event.target.value); + }, + onZeugnisLoaded() { + this.zeugnisLoaded = true; + this.checkHighlight(); + }, + onTeacherLoaded() { + this.teacherLoaded = true; + this.checkHighlight(); + }, + checkHighlight() + { + if (!this.zeugnisLoaded || !this.teacherLoaded) + return; + + if (!this.$refs.zeugnis || !this.$refs.teacher) + return; + + let zeugnisTable = this.$refs.zeugnis.$refs.table.tabulator; + let teacherTable = this.$refs.teacher.$refs.table.tabulator; + + if (!zeugnisTable || !teacherTable) + return; + + highlightGesamtnote(zeugnisTable, teacherTable); } }, created() { @@ -49,10 +79,10 @@ export default {
- +
- +
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Teacher.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Teacher.js index e566d3a09..f25d291cf 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Teacher.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Teacher.js @@ -1,13 +1,12 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; -import ApiStvGrades from '../../../../../api/factory/stv/grades.js'; - export default { components: { CoreFilterCmpt }, emits: [ - "copied" + "copied", + "loaded" ], inject: { currentSemester: { @@ -16,47 +15,127 @@ export default { } }, props: { - student: Object, - allSemester: Boolean + endpoint: { + type: Object, + required: true + }, + id: { + type: [Number, String], + required: true + }, + allSemester: Boolean, + optionalTabulatorOptions: Object, }, data() { return { - tabulatorEvents: [] + tabulatorEvents: [ + { + event: "dataProcessed", + handler: () => this.$emit("loaded"), + }, + ] }; }, computed: { tabulatorOptions() { return { ajaxURL: 'dummy', - ajaxRequestFunc: () => this.$api.call(ApiStvGrades.getTeacherProposal( - this.student.prestudent_id, + ajaxRequestFunc: () => this.$api.call(this.endpoint.getTeacherProposal( + this.id, (!this.allSemester ? this.currentSemester : null) )), ajaxResponse: (url, params, response) => { return response.data || []; }, columns: [ - { field: 'lehrveranstaltung_bezeichnung', title: this.$p.t('lehre/lehrveranstaltung') }, - { field: 'note_bezeichnung', title: this.$p.t('lehre/note') }, - { field: 'mitarbeiter_uid', title: this.$p.t('profil/mitarbeiterIn'), visible: false }, - { field: 'benotungsdatum', title: this.$p.t('stv/grades_gradingdate'), visible: false }, - { field: 'freigabedatum', title: this.$p.t('stv/grades_approvaldate'), visible: false }, - { field: 'studiensemester_kurzbz', title: this.$p.t('lehre/studiensemester'), visible: false }, - { field: 'note', title: this.$p.t('stv/grades_numericgrade'), visible: false }, - { field: 'student_uid', title: this.$p.t('profil/studentIn'), visible: false }, - { field: 'lehrveranstaltung_id', title: this.$p.t('lehre/lehrveranstaltung_id'), visible: false }, - { field: 'punkte', title: this.$p.t('stv/grades_points'), visible: false } + { + field: 'lehrveranstaltung_bezeichnung', + title: this.$p.t('lehre/lehrveranstaltung'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrveranstaltung_bezeichnung ?? true, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrveranstaltung_bezeichnung || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'note_bezeichnung', + title: this.$p.t('lehre/note'), + visible: this.optionalTabulatorOptions?.visibleColumns?.note_bezeichnung ?? true, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.note_bezeichnung || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'mitarbeiter_uid', + title: this.$p.t('profil/mitarbeiterIn'), + visible: this.optionalTabulatorOptions?.visibleColumns?.mitarbeiter_uid ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.mitarbeiter_uid || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'benotungsdatum', + title: this.$p.t('stv/grades_gradingdate'), + visible: this.optionalTabulatorOptions?.visibleColumns?.benotungsdatum ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.benotungsdatum || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'freigabedatum', + title: this.$p.t('stv/grades_approvaldate'), + visible: this.optionalTabulatorOptions?.visibleColumns?.freigabedatum ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.freigabedatum || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'studiensemester_kurzbz', + title: this.$p.t('lehre/studiensemester'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiensemester_kurzbz ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiensemester_kurzbz || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'note', + title: this.$p.t('stv/grades_numericgrade'), + visible: this.optionalTabulatorOptions?.visibleColumns?.note ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.note || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'student_uid', + title: this.$p.t('profil/studentIn'), + visible: this.optionalTabulatorOptions?.visibleColumns?.student_uid ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.student_uid || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'lehrveranstaltung_id', + title: this.$p.t('lehre/lehrveranstaltung_id'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrveranstaltung_id ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrveranstaltung_id || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'punkte', + title: this.$p.t('stv/grades_points'), + visible: this.optionalTabulatorOptions?.visibleColumns?.punkte ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.punkte || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'vorname', + title: this.$p.t('person/vorname'), + visible: this.optionalTabulatorOptions?.visibleColumns?.vorname ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.vorname || this.optionalTabulatorOptions?.headerFilter || false + }, + { + field: 'nachname', + title: this.$p.t('person/nachname'), + visible: this.optionalTabulatorOptions?.visibleColumns?.nachname ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.nachname || this.optionalTabulatorOptions?.headerFilter || false + } ], + columnDefaults: { + headerFilter: this.optionalTabulatorOptions?.headerFilter ?? false, + }, layout: 'fitDataStretch', height: '100%', selectable: true, + selectableRows: true, // needed for Tabulator v6 + selectableRowsRangeMode: 'click', // needed for Tabulator v6 selectableRangeMode: 'click', - persistenceID: 'stv-details-noten-teacher' + persistenceID: this.optionalTabulatorOptions?.persistenceTeacherID ?? 'stv-details-noten-teacher-2025120401', }; } }, watch: { - student(n) { + id() { this.$refs.table.reloadTable(); }, allSemester(n) { @@ -67,7 +146,7 @@ export default { copyGrades(selected) { const promises = selected.map( grade => this.$api - .call(ApiStvGrades.copyTeacherProposalToCertificate(grade), { + .call(this.endpoint.copyTeacherProposalToCertificate(grade), { errorHeader: grade.lehrveranstaltung_bezeichnung }) .then(() => { diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js index 4d0996b6b..8e921c668 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Noten/Zeugnis.js @@ -2,8 +2,6 @@ import {CoreFilterCmpt} from "../../../../filter/Filter.js"; import ZeugnisActions from './Zeugnis/Actions.js'; import ZeugnisDocuments from './Zeugnis/Documents.js'; -import ApiStvGrades from '../../../../../api/factory/stv/grades.js'; - export default { name: 'Zeugnis', components: { @@ -11,6 +9,7 @@ export default { ZeugnisActions, ZeugnisDocuments }, + emits: ['loaded'], inject: { config: { from: 'config', @@ -22,7 +21,15 @@ export default { } }, props: { - student: Object, + endpoint: { + type: Object, + required: true + }, + id: { + type: [Number, String], + required: true + }, + optionalTabulatorOptions: Object, allSemester: Boolean }, data() { @@ -35,6 +42,10 @@ export default { return item; }) }, + { + event: "dataProcessed", + handler: () => this.$emit("loaded") + }, { event: "rowSelected", handler: row => row.getElement().style.zIndex = 12 @@ -53,7 +64,7 @@ export default { computed: { tabulatorOptions() { const listPromise = this.$api - .call(ApiStvGrades.list()) + .call(this.endpoint.list()) .then(res => res.data.map(({bezeichnung: label, note: value}) => ({label, value}))); let gradeField = { @@ -86,7 +97,7 @@ export default { note_bezeichnung })) // send to backend - .then(data => this.$api.call(ApiStvGrades.updateCertificate(data))) + .then(data => this.$api.call(this.endpoint.updateCertificate(data))) // get bezeichnung again .then(() => listPromise) .then(list => list.find(el => el.value == note)) @@ -109,7 +120,7 @@ export default { if (filterTerm) { return this.$api .call( - ApiStvGrades.getGradeFromPoints( + this.endpoint.getGradeFromPoints( filterTerm, cell.getData().lehrveranstaltung_id, this.currentSemester @@ -142,27 +153,146 @@ export default { .then(() => node.innerText = this.$p.t('ui/loading')) .catch(this.$fhcAlert.handleSystemError); gradeField.editorParams.placeholderLoading = node; + gradeField.visible = this.optionalTabulatorOptions?.visibleColumns?.note ?? true + gradeField.headerFiler = this.optionalTabulatorOptions?.headerFilter?.note || this.optionalTabulatorOptions?.note || false } const columns = [ - { field: 'zeugnis', title: this.$p.t('stv/grades_zeugnis'), formatter: 'tickCross' }, - { field: 'lehrveranstaltung_bezeichnung', title: this.$p.t('lehre/lehrveranstaltung') }, - gradeField, - { field: 'uebernahmedatum', title: this.$p.t('stv/grades_takeoverdate'), visible: false }, - { field: 'benotungsdatum', title: this.$p.t('stv/grades_gradingdate'), visible: false }, - { field: 'studiensemester_kurzbz', title: this.$p.t('lehre/studiensemester'), visible: false }, - { field: 'note_number', title: this.$p.t('stv/grades_numericgrade'), visible: false, formatter: cell => cell.getData().note, tooltip: (evt, cell) => cell.getData().note }, - { field: 'lehrveranstaltung_id', title: this.$p.t('lehre/lehrveranstaltung_id'), visible: false }, - { field: 'studiengang', title: this.$p.t('lehre/studiengang'), visible: false }, - { field: 'studiengang_kz', title: this.$p.t('lehre/studiengangskennzahlLehre'), visible: false }, - { field: 'studiengang_lv', title: this.$p.t('stv/grades_studiengang_lv'), visible: false }, - { field: 'studiengang_kz_lv', title: this.$p.t('stv/grades_studiengang_kz_lv'), visible: false }, - { field: 'semester_lv', title: this.$p.t('stv/grades_semester_lv'), visible: false }, - { field: 'ects_lv', title: this.$p.t('lehre/ects'), visible: false }, - { field: 'lehrform', title: this.$p.t('lehre/lehrform'), visible: false }, - { field: 'kurzbz', title: this.$p.t('lehre/kurzbz'), visible: false }, - { field: 'punkte', title: this.$p.t('stv/grades_points'), visible: false }, - { field: 'lehrveranstaltung_bezeichnung_english', title: this.$p.t('stv/grades_lehrveranstaltung_bezeichnung_english'), visible: false } + { + field: 'zeugnis', + title: this.$p.t('stv/grades_zeugnis'), + formatter: 'tickCross', + visible: this.optionalTabulatorOptions?.visibleColumns?.zeugnis ?? true, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.zeugnis || this.optionalTabulatorOptions?.zeugnis || false + }, + { + field: 'lehrveranstaltung_bezeichnung', + title: this.$p.t('lehre/lehrveranstaltung'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrveranstaltung_bezeichnung ?? true, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrveranstaltung_bezeichnung || this.optionalTabulatorOptions?.lehrveranstaltung_bezeichnung || false + + }, + gradeField, + { + field: 'uebernahmedatum', + title: this.$p.t('stv/grades_takeoverdate'), + visible: this.optionalTabulatorOptions?.visibleColumns?.uebernahmedatum ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.uebernahmedatum || this.optionalTabulatorOptions?.uebernahmedatum || false + + }, + { + field: 'benotungsdatum', + title: this.$p.t('stv/grades_gradingdate'), + visible: this.optionalTabulatorOptions?.visibleColumns?.benotungsdatum ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.benotungsdatum || this.optionalTabulatorOptions?.benotungsdatum || false + + }, + { + field: 'studiensemester_kurzbz', + title: this.$p.t('lehre/studiensemester'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiensemester_kurzbz ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiensemester_kurzbz || this.optionalTabulatorOptions?.studiensemester_kurzbz || false + + }, + { + field: 'note_number', + title: this.$p.t('stv/grades_numericgrade'), + visible: this.optionalTabulatorOptions?.visibleColumns?.note_number ?? false, + formatter: cell => cell.getData().note, tooltip: (evt, cell) => cell.getData().note, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.note_number || this.optionalTabulatorOptions?.note_number || false + + }, + { + field: 'lehrveranstaltung_id', + title: this.$p.t('lehre/lehrveranstaltung_id'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrveranstaltung_id ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrveranstaltung_id || this.optionalTabulatorOptions?.lehrveranstaltung_id || false + + }, + { + field: 'studiengang', + title: this.$p.t('lehre/studiengang'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiengang ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiengang || this.optionalTabulatorOptions?.studiengang || false + + }, + { + field: 'studiengang_kz', + title: this.$p.t('lehre/studiengangskennzahlLehre'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiengang_kz ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiengang_kz || this.optionalTabulatorOptions?.studiengang_kz || false + + }, + { + field: 'studiengang_lv', + title: this.$p.t('stv/grades_studiengang_lv'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiengang_lv ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiengang_lv || this.optionalTabulatorOptions?.studiengang_lv || false + + }, + { + field: 'studiengang_kz_lv', + title: this.$p.t('stv/grades_studiengang_kz_lv'), + visible: this.optionalTabulatorOptions?.visibleColumns?.studiengang_kz_lv ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.studiengang_kz_lv || this.optionalTabulatorOptions?.studiengang_kz_lv || false + + }, + { + field: 'semester_lv', + title: this.$p.t('stv/grades_semester_lv'), + visible: this.optionalTabulatorOptions?.visibleColumns?.semester_lv ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.semester_lv || this.optionalTabulatorOptions?.semester_lv || false + + }, + { + field: 'ects_lv', + title: this.$p.t('lehre/ects'), + visible: this.optionalTabulatorOptions?.visibleColumns?.ects_lv ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.ects_lv || this.optionalTabulatorOptions?.ects_lv || false + + }, + { + field: 'lehrform', + title: this.$p.t('lehre/lehrform'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrform ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrform || this.optionalTabulatorOptions?.lehrform || false + + }, + { + field: 'kurzbz', + title: this.$p.t('lehre/kurzbz'), + visible: this.optionalTabulatorOptions?.visibleColumns?.kurzbz ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.kurzbz || this.optionalTabulatorOptions?.kurzbz || false + + }, + { + field: 'punkte', + title: this.$p.t('stv/grades_points'), + visible: this.optionalTabulatorOptions?.visibleColumns?.punkte ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.punkte || this.optionalTabulatorOptions?.punkte || false + + }, + { + field: 'vorname', + title: this.$p.t('person/vorname'), + visible: this.optionalTabulatorOptions?.visibleColumns?.vorname ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.vorname || this.optionalTabulatorOptions?.vorname || false + + }, + { + field: 'nachname', + title: this.$p.t('person/nachname'), + visible: this.optionalTabulatorOptions?.visibleColumns?.nachname ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.nachname || this.optionalTabulatorOptions?.nachname || false + + }, + { + field: 'lehrveranstaltung_bezeichnung_english', + title: this.$p.t('stv/grades_lehrveranstaltung_bezeichnung_english'), + visible: this.optionalTabulatorOptions?.visibleColumns?.lehrveranstaltung_bezeichnung_english ?? false, + headerFilter: this.optionalTabulatorOptions?.headerFilter?.lehrveranstaltung_bezeichnung_english || this.optionalTabulatorOptions?.lehrveranstaltung_bezeichnung_english || false + + } ]; const hasDocuments = ['both', 'inline'].includes(this.config.documents); @@ -208,8 +338,8 @@ export default { return { ajaxURL: 'dummy', - ajaxRequestFunc: () => this.$api.call(ApiStvGrades.getCertificate( - this.student.prestudent_id, + ajaxRequestFunc: () => this.$api.call(this.endpoint.getCertificate( + this.id, (!this.allSemester ? this.currentSemester : null) )), ajaxResponse: (url, params, response) => { @@ -218,9 +348,11 @@ export default { columns, height: '100%', layout: 'fitDataStretchFrozen', - selectable: 1, + selectable: true, selectableRangeMode: 'click', - persistenceID: 'stv-details-noten-zeugnis-2025112401', + selectableRowsRangeMode: 'click', //needed for Tabulator v6 + selectableRows: true, //needed for Tabulator v6 + persistenceID: this.optionalTabulatorOptions?.persistenceZeugnisID ?? 'stv-details-noten-zeugnis-2025120302', persistence:{ columns: ["width", "visible", "frozen"] } @@ -228,7 +360,8 @@ export default { } }, watch: { - student(n) { + id() + { this.$refs.table.reloadTable(); }, allSemester(n) { @@ -239,7 +372,7 @@ export default { setGrade(data) { this.$api .call( - ApiStvGrades.updateCertificate(data), + this.endpoint.updateCertificate(data), { errorHeader: data.lehrveranstaltung_bezeichnung } ) .then(this.$refs.table.reloadTable) @@ -252,7 +385,7 @@ export default { .confirmDelete() .then(result => result ? data : Promise.reject({handled:true})) .then(data => this.$api.call( - ApiStvGrades.deleteCertificate(data), + this.endpoint.deleteCertificate(data), { errorHeader: data.lehrveranstaltung_bezeichnung } )) .then(this.$refs.table.reloadTable) @@ -261,7 +394,7 @@ export default { } }, created() { - this.$p.loadCategory(['global', 'stv', 'lehre']) + this.$p.loadCategory(['global', 'stv', 'lehre', 'person']) .then(() => { if (this.$refs.table.tableBuilt) this.$refs.table.tabulator.columnManager.setColumns(this.tabulatorOptions.columns); diff --git a/public/js/helpers/DocumentHelper.js b/public/js/helpers/DocumentHelper.js new file mode 100644 index 000000000..c37c632d5 --- /dev/null +++ b/public/js/helpers/DocumentHelper.js @@ -0,0 +1,44 @@ +export function highlightGesamtnote(zeugnisTable, teacherTable) +{ + let zeugnisData = zeugnisTable.getData(); + + let studentsWithNote = new Set(); + + zeugnisData.forEach(row => { + let student = row.uid; + let lv = row.lehrveranstaltung_id; + let note = row.note; + + if (!student || !lv) + return; + + if (note == null || note === "") + return; + + let key = `${student}_${lv}`; + studentsWithNote.add(key); + }); + + teacherTable.deselectRow(); + + teacherTable.getRows().forEach(row => { + let data = row.getData(); + + let student = data.student_uid; + let lv = data.lehrveranstaltung_id; + let note = data.note; + + if (!student || !lv) + return; + + if (note == null || note === "") + return; + + let key = `${student}_${lv}`; + + if (!studentsWithNote.has(key)) + { + row.select(); + } + }); +} \ No newline at end of file