Projektarbeit Studierendenverwaltung: now possible to save and edit Projektbetreuer

This commit is contained in:
Alexei Karpenko
2025-05-16 13:37:21 +02:00
parent 405062f549
commit 382006aa8b
14 changed files with 1002 additions and 934 deletions
+6 -1
View File
@@ -54,7 +54,7 @@ $config['tabs'] =
],
]
];
// List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined
$fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code'];
@@ -74,3 +74,8 @@ if (!defined('ZGV_DOKTOR_ANZEIGEN') || !ZGV_DOKTOR_ANZEIGEN) {
$fieldsZgvDoktor
);
}
$config['tabs']['projektarbeit']['defaultProjektbetreuerStunden'] = '4.0';
$config['tabs']['projektarbeit']['defaultProjektbetreuerStundenDiplom'] = '5.0';
$config['tabs']['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'] = true;
$config['tabs']['projektarbeit']['defaultProjektbetreuerStundensatz'] = '80.0';
@@ -125,7 +125,8 @@ class Config extends FHCAPI_Controller
$result['projektarbeit'] = [
'title' => $this->p->t('stv', 'tab_projektarbeit'),
'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js'
'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js',
'config' => $config['projektarbeit']
];
$result['mobility'] = [
@@ -323,7 +324,7 @@ class Config extends FHCAPI_Controller
$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" .
@@ -17,7 +17,7 @@ class Projektarbeit extends FHCAPI_Controller
'getTypenProjektarbeit' => ['admin:r', 'assistenz:r'],
'getFirmen' => ['admin:r', 'assistenz:r'],
'getLehrveranstaltungen' => ['admin:r', 'assistenz:r'],
'getNoten' => ['admin:rw', 'assistenz:rw']
'getNoten' => ['admin:r', 'assistenz:r']
]);
// Load Libraries
@@ -91,7 +91,7 @@ class Projektarbeit extends FHCAPI_Controller
);
$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');
$this->ProjektarbeitModel->addJoin('public.tbl_firma fa', 'firma_id', 'LEFT');
$result = $this->ProjektarbeitModel->loadWhere(
array('projektarbeit_id' => $projektarbeit_id)
);
@@ -170,7 +170,7 @@ class Projektarbeit extends FHCAPI_Controller
if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL);
$result = $this->ProjektarbeitModel->delete(
array('projektarbeit_id' => $projektarbeit_id)
['projektarbeit_id' => $projektarbeit_id]
);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
@@ -273,10 +273,9 @@ class Projektarbeit extends FHCAPI_Controller
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Projekttyp'])
]);
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|numeric', [
$this->form_validation->set_rules('lehreinheit_id', 'Lehreinheit', 'required|is_natural', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']),
//'matches' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Lehreinheit']),
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
'is_natural' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Lehreinheit'])
]);
$this->form_validation->set_rules('beginn', 'Beginn', 'is_valid_date', [
@@ -0,0 +1,333 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Projektbetreuer extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getProjektbetreuer' => ['admin:r', 'assistenz:r'],
'saveProjektbetreuer' => ['admin:rw', 'assistenz:rw'],
'deleteProjektbetreuer' => ['admin:rw', 'assistenz:rw'],
'getBetreuerarten' => ['admin:r', 'assistenz:r'],
'getNoten' => ['admin:r', 'assistenz:r'],
'getDefaultStundensaetze' => ['admin:r', 'assistenz:r'],
'getProjektbetreuerBySearchQuery' => ['admin:r', 'assistenz:r'],
'validateProjektbetreuer' => ['admin:r', 'assistenz:r']
]);
// Load Libraries
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'person',
'projektarbeit'
]);
// Load models
$this->load->model('education/Projektbetreuer_model', 'ProjektbetreuerModel');
$this->load->model('education/Betreuerart_model', 'BetreuerartModel');
$this->load->model('ressource/Stundensatz_model', 'StundensatzModel');
$this->load->model('education/Projektarbeit_model', 'ProjektarbeitModel');
$this->load->model('education/Note_model', 'NoteModel');
$this->load->model('person/Person_model', 'PersonModel');
// load libraries
$this->load->library('PermissionLib');
}
public function getProjektbetreuer()
{
$projektarbeit_id = $this->input->get('projektarbeit_id');
if (!isset($projektarbeit_id)) $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL);
$this->ProjektbetreuerModel->addSelect(
'projektarbeit_id, person_id, nachname, vorname, note, punkte, stunden, stundensatz, betreuerart_kurzbz, vertrag_id, titelpre, titelpost'
);
$this->ProjektbetreuerModel-> addSelect("CASE
WHEN EXISTS
(SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=pers.person_id)
THEN 'Mitarbeiter'
WHEN EXISTS
(SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=pers.person_id)
THEN 'Student'
ELSE 'Person'
END AS status");
$this->ProjektbetreuerModel->addJoin('public.tbl_person pers', 'person_id');
$result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id]);
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
if (!hasData($result)) $this->terminateWithSuccess([]);
$projektbetreuer = getData($result);
//~ foreach ($projektbetreuer as $projektarbeit)
//~ {
//~ $projektarbeit_id = $projektarbeit->projektarbeit_id;
//~ $abgabeRes = $this->PaabgabeModel->getEndabgabe($projektarbeit_id);
//~ if (isError($abgabeRes)) $this->terminateWithError(getError($abgabeRes), self::ERROR_TYPE_GENERAL);
//~ if (hasData($abgabeRes))
//~ {
//~ $paabgabe = getData($abgabeRes)[0];
//~ $projektarbeit->abgabedatum = $paabgabe->abgabedatum;
//~ }
//~ }
$this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer));
}
public function saveProjektbetreuer()
{
$projektarbeit_id = $this->input->post('projektarbeit_id');
if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektarbeit ID']), self::ERROR_TYPE_GENERAL);
if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
$projektbetreuer = $this->input->post('projektbetreuerListe');
//$this->addMeta('form', $projektbetreuer);
if (!is_array($projektbetreuer))
{
return $this->terminateWithError(
$this->p->t('projektarbeit', 'error_invalidProjektbetreuer'), self::ERROR_TYPE_GENERAL
);
}
foreach ($projektbetreuer as $pb)
{
if ($this->_validate($pb) == false)
{
$this->addMeta('test', 'foisch');
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
}
$result = null;
foreach ($projektbetreuer as $pb)
{
//~ $this->addMeta('form', $pb);
//~ error_log(print_r($pb, true));
//die();
//~ $this->ProjektbetreuerModel->addSelect('1');
//~ $checkResult = $this->ProjektbetreuerModel->loadWhere(
//~ ['person_id' => $pb['person_id'], 'projektarbeit_id' => $projektarbeit_id, 'betreuerart_kurzbz' => $pb['betreuerart_kurzbz']]
//~ );
//~ if (isError($checkResult)) $this->terminateWithError(getError($checkResult), self::ERROR_TYPE_GENERAL);
$betreuer = [
'projektarbeit_id' => $projektarbeit_id,
'person_id' => $pb['person_id'],
'note' => $pb['note'],
'stunden' => $pb['stunden'],
'stundensatz' => $pb['stundensatz'],
'betreuerart_kurzbz' => $pb['betreuerart_kurzbz']
];
if (isset($pb['person_id_old']) && isset($pb['betreuerart_kurzbz_old']))
{
$result = $this->ProjektbetreuerModel->update(
[
'projektarbeit_id' => $projektarbeit_id,
'person_id' => $pb['person_id_old'],
'betreuerart_kurzbz' => $pb['betreuerart_kurzbz_old']
],
array_merge($betreuer, ['updateamum' => date('c'), 'updatevon' => getAuthUID()])
);
}
else
{
$result = $this->ProjektbetreuerModel->insert(
array_merge($betreuer, ['insertamum' => date('c'), 'insertvon' => getAuthUID()])
);
}
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function deleteProjektbetreuer()
{
$projektarbeit_id = $this->input->post('projektarbeit_id');
$person_id = $this->input->post('person_id');
$betreuerart_kurzbz = $this->input->post('betreuerart_kurzbz');
if (!isset($projektarbeit_id) || !is_numeric($projektarbeit_id))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Projektbetreuer ID'], self::ERROR_TYPE_GENERAL));
if (!isset($person_id) || !is_numeric($person_id))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID'], self::ERROR_TYPE_GENERAL));
if (!isset($betreuerart_kurzbz))
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Betreuerart'], self::ERROR_TYPE_GENERAL));
if (!$this->ProjektarbeitModel->hasBerechtigungForProjektarbeit($projektarbeit_id))
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'assistenz:rw']]);
$validate = $this->_validateDelete($projektarbeit_id, $person_id);
if (isError($validate)) return $this->terminateWithError(getError($validate), self::ERROR_TYPE_GENERAL);
$result = $this->ProjektbetreuerModel->delete(
['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id, 'betreuerart_kurzbz' => $betreuerart_kurzbz]
);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
if (!hasData($result))
{
$this->outputJson($result);
}
return $this->terminateWithSuccess(current(getData($result)) ? : null);
}
public function getBetreuerarten()
{
$result = $this->BetreuerartModel->loadWhere(['aktiv' => true]);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function getNoten()
{
$result = $this->NoteModel->load();
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
}
public function getDefaultStundensaetze()
{
$person_id = $this->input->get('person_id');
$studiensemester_kurzbz = $this->input->get('studiensemester_kurzbz');
$result = $this->StundensatzModel->getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz);
$this->addMeta('res', $result);
//if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess($result);
}
public function getProjektbetreuerBySearchQuery()
{
$searchString = $this->input->get('searchString');
if (!isset($searchString)) $this->terminateWithError($this->p->t('projektarbeit', 'error_searchStringMissing', self::ERROR_TYPE_GENERAL));
$result = $this->PersonModel->searchPerson($searchString);
$this->addMeta('met', $result);
if (isError($result)) return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
return $this->terminateWithSuccess(hasData($result) ? $this->_addFullNameToBetreuer(getData($result)) : []);
}
/**
*
* @param
* @return object success or error
*/
public function validateProjektbetreuer()
{
$projektbetreuerArr = $this->input->post('projektbetreuer');
if (!is_array($projektbetreuerArr)) $projektbetreuerArr = [$projektbetreuerArr];
foreach ($projektbetreuerArr as $pb)
{
if ($this->_validate($pb) == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
}
$this->terminateWithSuccess([]);
}
/**
*
* @param
* @return object success or error
*/
private function _validate($formData)
{
$this->form_validation->set_data($formData);
$this->form_validation->set_rules('betreuerart_kurzbz', 'Betreuerart', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Betreuerart'])
]);
$this->form_validation->set_rules('person_id', 'Person', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Person ID'])
]);
$this->form_validation->set_rules('stunden', 'Stunden', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stunden'])
]);
$this->form_validation->set_rules('stundensatz', 'Stundensatz', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Stundensatz'])
]);
return $this->form_validation->run();
}
/**
*
* @param
* @return object success or error
*/
private function _validateDelete($projektarbeit_id, $person_id)
{
$this->ProjektbetreuerModel->addSelect('vertrag_id');
$result = $this->ProjektbetreuerModel->loadWhere(['projektarbeit_id' => $projektarbeit_id, 'person_id' => $person_id]);
if (isError($result)) return $result;
if (hasData($result) && getData($result)[0]->vertrag_id != null) return error($this->p->t('projektarbeit', 'error_betreuerHatVertrag'));
return success();
}
/**
*
* @param
* @return object success or error
*/
private function _addFullNameToBetreuer($betreuerArr)
{
foreach ($betreuerArr as $betreuer)
{
$betreuer->name = ($betreuer->titelpre ? $betreuer->titelpre . ' ' : '') .
$betreuer->nachname . ' ' . $betreuer->vorname . ($betreuer->titelpost ? ' ' . $betreuer->titelpre : '').
' (' . $betreuer->status . ')';
}
return $betreuerArr;
}
}
@@ -29,12 +29,11 @@ class Projektarbeit_model extends DB_Model
tbl_firma.name AS firma_name
FROM
lehre.tbl_projektarbeit
JOIN
lehre.tbl_projekttyp USING (projekttyp_kurzbz), lehre.tbl_lehreinheit, lehre.tbl_lehrveranstaltung, public.tbl_firma
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
tbl_projektarbeit.lehreinheit_id=tbl_lehreinheit.lehreinheit_id AND
tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id AND
tbl_projektarbeit.firma_id = tbl_firma.firma_id AND
tbl_projektarbeit.student_uid = ?";
$params = array($student_uid);
@@ -10,6 +10,7 @@ class Projektbetreuer_model extends DB_Model
parent::__construct();
$this->dbTable = 'lehre.tbl_projektbetreuer';
$this->pk = array('betreuerart_kurzbz', 'projektarbeit_id', 'person_id');
$this->hasSequence = false;
}
/**
+14 -5
View File
@@ -151,12 +151,21 @@ class Person_model extends DB_Model
*/
public function searchPerson($filter)
{
$this->addSelect('vorname, nachname, gebdatum, person_id');
$this->addSelect('vorname, nachname, gebdatum, person_id, titelpre, titelpost');
$this->addSelect("CASE
WHEN EXISTS
(SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_mitarbeiter ON(uid=mitarbeiter_uid) WHERE person_id=tbl_person.person_id)
THEN 'Mitarbeiter'
WHEN EXISTS
(SELECT 1 FROM public.tbl_benutzer JOIN public.tbl_student ON(uid=student_uid) WHERE person_id=tbl_person.person_id)
THEN 'Student'
ELSE 'Person'
END AS status");
$result = $this->loadWhere(
'lower(nachname) like '.$this->db->escape('%'.$filter.'%')."
'lower(nachname) like '.$this->db->escape('%'.mb_strtolower($filter).'%')."
OR lower(vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.$filter.'%')."
OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.$filter.'%')
OR lower(nachname || ' ' || vorname) like ".$this->db->escape('%'.mb_strtolower($filter).'%')."
OR lower(vorname || ' ' || nachname) like ".$this->db->escape('%'.mb_strtolower($filter).'%')
);
return $result;
@@ -423,4 +432,4 @@ class Person_model extends DB_Model
return success($result);
}
}
}
}
@@ -2,7 +2,7 @@
class Stundensatz_model extends DB_Model
{
/**
* Constructor
*/
@@ -42,4 +42,95 @@ class Stundensatz_model extends DB_Model
return $this->execQuery($qry, $params);
}
}
public function getStundensatzForMitarbeiter($person_id, $studiensemester_kurzbz)
{
$this->load->config('stv');
$useFixangestelltStundensatz = $this->config->item('tabs')['projektarbeit']['lvLektroinnenzuteilungFixangestelltStundensatz'];
$defaultStundensatz = $this->config->item('tabs')['projektarbeit']['defaultProjektbetreuerStundensatz'];
$stundensatz = '';
if(isset($person_id) && isset($studiensemester_kurzbz))
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
$this->StudiensemesterModel->addSelect('start, ende');
$result = $this->StudiensemesterModel->load($studiensemester_kurzbz);
if (hasData($result))
{
$studiensemester = getData($result)[0];
if (isset($useFixangestelltStundensatz) && !$useFixangestelltStundensatz)
{
// load Mitarbeiter
$params = [$person_id];
$qry = "
SELECT
mitarbeiter_uid, fixangestellt
FROM
public.tbl_mitarbeiter
JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid)
WHERE
person_id=?
ORDER BY
tbl_mitarbeiter.insertamum DESC NULLS LAST
LIMIT 1";
$result = $this->execQuery($qry, $params);
if (hasData($result))
{
foreach (getData($result) as $ma)
{
if (!$ma->fixangestellt)
{
$stundensatzRes = $this->getStundensatzByDatum(
$ma->mitarbeiter_uid, $studiensemester->start, $studiensemester->ende, 'lehre'
);
if (hasData($stundensatzRes))
$stundensatz = getData($stundensatzRes)[0]->stundensatz;
else
$stundensatz = '0.00';
}
}
}
else
{
$stundensatz = '0.00';
}
}
else
{
$params = [$person_id, $studiensemester->ende, $studiensemester->start];
$qry = "SELECT ss.stundensatz
FROM hr.tbl_stundensatz ss
JOIN public.tbl_mitarbeiter ON ss.uid = tbl_mitarbeiter.mitarbeiter_uid
JOIN public.tbl_benutzer ON(tbl_benutzer.uid=tbl_mitarbeiter.mitarbeiter_uid)
WHERE person_id=?
AND stundensatztyp = 'lehre'
AND gueltig_von <= ?
AND (gueltig_bis >= ? OR gueltig_bis IS NULL)
ORDER BY gueltig_bis DESC NULLS FIRST, gueltig_von DESC NULLS LAST LIMIT 1";
$result = $this->execQuery($qry, $params);
if (hasData($result))
{
$stundensatz = getData($result)[0]->stundensatz;
}
else
{
$stundensatz = $defaultStundensatz;
}
}
}
}
return $stundensatz;
}
}
@@ -0,0 +1,73 @@
/**
* 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 {
getProjektbetreuer(projektarbeit_id ) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuer',
params: { projektarbeit_id }
};
},
getBetreuerarten() {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektbetreuer/getBetreuerarten'
};
},
getDefaultStundensaetze(person_id, studiensemester_kurzbz) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektbetreuer/getDefaultStundensaetze',
params: { person_id, studiensemester_kurzbz }
};
},
getNoten() {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektbetreuer/getNoten'
};
},
saveProjektbetreuer(projektarbeit_id, projektbetreuerListe) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektbetreuer/saveProjektbetreuer',
params: { projektarbeit_id, projektbetreuerListe }
};
},
deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektbetreuer/deleteProjektbetreuer',
params: { projektarbeit_id, person_id, betreuerart_kurzbz }
};
},
getProjektbetreuerBySearchQuery(searchString) {
return {
method: 'get',
url: 'api/frontend/v1/stv/projektbetreuer/getProjektbetreuerBySearchQuery',
params: { searchString }
};
},
validateProjektbetreuer(projektbetreuer) {
return {
method: 'post',
url: 'api/frontend/v1/stv/projektbetreuer/validateProjektbetreuer',
params: { projektbetreuer }
};
}
};
@@ -1,847 +0,0 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import ApiStvAbschlusspruefung from '../../../../../api/factory/stv/abschlusspruefung.js';
export default {
components: {
CoreFilterCmpt,
BsModal,
FormForm,
FormInput,
PvAutoComplete,
AbschlusspruefungDropdown,
PruefungList
},
inject: {
cisRoot: {
from: 'cisRoot'
},
config: {
from: 'config',
required: true
},
$reloadList: {
from: '$reloadList',
required: true
},
isBerechtigtDocAndOdt: {
from: 'hasPermissionOutputformat',
default: false
}
},
computed: {
studentUids() {
if (this.student.uid)
{
return [this.student.uid];
}
return this.student.map(e => e.uid);
},
studentKzs(){
if (this.student.uid)
{
return [this.student.studiengang_kz];
}
return this.student.map(e => e.studiengang_kz);
},
stg_kz(){
return this.studentKzs[0];
},
},
props: {
student: Object
},
data() {
return {
tabulatorOptions: {
ajaxURL: 'dummy',
ajaxRequestFunc: () => this.$api.call(ApiStvAbschlusspruefung.getAbschlusspruefung(this.student.uid)),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "vorsitz", field: "vorsitz_nachname"},
{title: "abschlussbeurteilung", field: "beurteilung_bezeichnung"},
{title: "prueferIn1", field: "p1_nachname", visible: false},
{title: "prueferIn2", field: "p2_nachname", visible: false},
{title: "prueferIn3", field: "p3_nachname", visible: false},
{
title: "datum",
field: "datum",
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",
hour12: false
});
}
},
{title: "uhrzeit", field: "uhrzeit"},
{
title: "freigabe",
field: "freigabedatum",
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",
hour12: false
});
}
},
{title: "pruefungsantritt", field: "antritt_bezeichnung"},
{
title: "sponsion",
field: "sponsion",
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",
hour12: false
});
}
},
{title: "anmerkung", field: "anmerkung"},
{title: "abschlusspruefung_id", field: "abschlusspruefung_id", visible: false},
{title: "typ", field: "pruefungstyp_kurzbz", visible: false},
{
title: 'Aktionen', field: 'actions',
minWidth: 150, // Ensures Action-buttons will be always fully displayed
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$p.t('ui', 'bearbeiten');
button.addEventListener('click', (event) =>
this.actionEditAbschlusspruefung(cell.getData().abschlusspruefung_id)
);
container.append(button);
button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-xmark"></i>';
button.title = this.$p.t('ui', 'loeschen');
button.addEventListener('click', () =>
this.actionDeleteAbschlusspruefung(cell.getData().abschlusspruefung_id)
);
container.append(button);
container.append(cell.getData().actionDiv);
return container;
},
frozen: true
},
],
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
height: 'auto',
minHeight: '200',
selectable: true,
index: 'abschlusspruefung_id',
persistenceID: 'stv-details-finalexam'
},
tabulatorEvents: [
{
event: 'dataLoaded',
handler: data => this.tabulatorData = data.map(item => {
item.actionDiv = document.createElement('div');
return item;
}),
},
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'abschlusspruefung', 'ui']);
let cm = this.$refs.table.tabulator.columnManager;
cm.getColumnByField('vorsitz_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'vorsitz_header')
});
cm.getColumnByField('beurteilung_bezeichnung').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'abschlussbeurteilung')
});
cm.getColumnByField('p1_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer1')
});
cm.getColumnByField('p2_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer2')
});
cm.getColumnByField('p3_nachname').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefer3')
});
cm.getColumnByField('datum').component.updateDefinition({
title: this.$p.t('global', 'datum')
});
cm.getColumnByField('uhrzeit').component.updateDefinition({
title: this.$p.t('global', 'uhrzeit')
});
cm.getColumnByField('freigabedatum').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'freigabe')
});
cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefungsantritt')
});
cm.getColumnByField('sponsion').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'sponsion')
});
cm.getColumnByField('anmerkung').component.updateDefinition({
title: this.$p.t('global', 'anmerkung')
});
cm.getColumnByField('pruefungstyp_kurzbz').component.updateDefinition({
title: this.$p.t('global', 'typ')
});
cm.getColumnByField('abschlusspruefung_id').component.updateDefinition({
title: this.$p.t('ui', 'abschlusspruefung_id')
});
/*
cm.getColumnByField('actions').component.updateDefinition({
title: this.$p.t('global', 'aktionen')
});
*/
}
}
],
tabulatorData: [],
lastSelected: null,
formData: {
typStg: null,
pruefungstyp_kurzbz: null,
akadgrad_id: null,
vorsitz: null,
pruefungsantritt_kurzbz: null,
abschlussbeurteilung_kurzbz: null,
datum: null,
sponsion: null,
pruefer1: null,
pruefer2: null,
pruefer3: null,
anmerkung: null,
protokoll: null,
note: null,
link: null
},
statusNew: true,
arrTypen: [],
arrAntritte: [],
arrBeurteilungen: [],
arrAkadGrad: [],
arrNoten: [],
filteredMitarbeiter: [],
filteredPruefer: [],
abortController: {
mitarbeiter: null,
pruefer: null
},
stgInfo: { typ: '', oe_kurzbz: '' }
}
},
watch: {
student(){
if (this.$refs.table) {
this.$refs.table.reloadTable();
}
this.getStudiengangByKz();
}
},
methods: {
getStudiengangByKz(){
this.stgInfo = { typ: '', oe_kurzbz: '' };
this.$api
.call(ApiStudiengang.getStudiengangByKz(this.stg_kz))
.then(result => this.stgInfo = result.data)
.catch(this.$fhcAlert.handleSystemError);
},
actionNewAbschlusspruefung() {
this.resetForm();
this.statusNew = true;
this.$refs.finalexamModal.show();
this.setDefaultFormData();
},
actionEditAbschlusspruefung(abschlusspruefung_id) {
this.resetForm();
this.statusNew = false;
this.$refs.finalexamModal.show();
this.loadAbschlusspruefung(abschlusspruefung_id);
},
actionDeleteAbschlusspruefung(abschlusspruefung_id) {
this.$fhcAlert
.confirmDelete()
.then(result => result
? abschlusspruefung_id
: Promise.reject({handled: true}))
.then(this.deleteAbschlusspruefung)
.catch(this.$fhcAlert.handleSystemError);
},
addNewAbschlusspruefung() {
const dataToSend = {
uid: this.student.uid,
formData: this.formData
};
return this.$refs.formFinalExam
.call(ApiStvAbschlusspruefung.addNewAbschlusspruefung(dataToSend))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.hideModal('finalexamModal');
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
hideModal(modalRef){
this.$refs[modalRef].hide();
},
reload() {
this.$refs.table.reloadTable();
},
loadAbschlusspruefung(abschlusspruefung_id) {
return this.$api
.call(ApiStvAbschlusspruefung.loadAbschlusspruefung(abschlusspruefung_id))
.then(result => {
this.formData = result.data;
//TODO(Manu) check if cisRoot is okay
this.formData.link = this.cisRoot + 'index.ci.php/lehre/Pruefungsprotokoll/showProtokoll?abschlusspruefung_id=' + this.formData.abschlusspruefung_id + '&fhc_controller_id=67481e5ed5490';
return result;
})
.catch(this.$fhcAlert.handleSystemError);
},
updateAbschlusspruefung(abschlusspruefung_id) {
const dataToSend = {
id: abschlusspruefung_id,
formData: this.formData
};
return this.$refs.formFinalExam
.call(ApiStvAbschlusspruefung.updateAbschlusspruefung(dataToSend))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.hideModal('finalexamModal');
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
deleteAbschlusspruefung(abschlusspruefung_id) {
return this.$api
.call(ApiStvAbschlusspruefung.deleteAbschlusspruefung(abschlusspruefung_id))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
resetForm() {
this.formData.pruefungstyp_kurzbz = null;
this.formData.akadgrad_id = null;
this.formData.vorsitz = null;
this.formData.pruefungsantritt_kurzbz = null;
this.formData.abschlussbeurteilung_kurzbz = null;
this.formData.datum = null; //oder new Date();
this.formData.sponsion = null;
this.formData.pruefer1 = null;
this.formData.pruefer2 = null;
this.formData.pruefer3 = null;
this.formData.anmerkung = null;
this.formData.protokoll = null;
this.formData.note = null;
this.formData.p1 = null;
this.formData.p2 = null;
this.formData.p3 = null;
this.formData.pv = null;
},
search(event) {
if (this.abortController.mitarbeiter) {
this.abortController.mitarbeiter.abort();
}
this.abortController.mitarbeiter = new AbortController();
return this.$api
.call(ApiStvAbschlusspruefung.getMitarbeiter(event.query))
.then(result => {
this.filteredMitarbeiter = result.data.retval;
});
},
searchNotAkad(event) {
if (this.abortController.pruefer) {
this.abortController.pruefer.abort();
}
this.abortController.pruefer = new AbortController();
return this.$api
.call(ApiStvAbschlusspruefung.getPruefer(event.query))
.then(result => {
this.filteredPruefer = result.data.retval;
});
},
setDefaultFormData() {
this.resetForm();
if (this.stgInfo.typ === 'b') {
this.formData.pruefungstyp_kurzbz = 'Bachelor';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgInfo.typ === 'd' || this.stgInfo === 'm') {
this.formData.pruefungstyp_kurzbz = 'Diplom';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgInfo.typ === 'lg') {
this.formData.pruefungstyp_kurzbz = 'lgabschluss';
}
if (!this.formData.akadgrad_id && this.arrAkadGrad.length > 0) {
this.formData.akadgrad_id = this.arrAkadGrad[0].akadgrad_id;
}
},
printDocument(link) {
window.open(link, '_blank');
},
},
created() {
this.$api
.call(ApiStvAbschlusspruefung.getTypenAbschlusspruefung())
.then(result => {
this.arrTypen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getTypenAntritte())
.then(result => {
this.arrAntritte = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getBeurteilungen())
.then(result => {
this.arrBeurteilungen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getNoten())
.then(result => {
this.arrNoten = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvAbschlusspruefung.getAkadGrade(this.student.studiengang_kz))
.then(result => {
this.arrAkadGrad = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
if (!this.student.length) {
this.$api
.call(ApiStudiengang.getStudiengangByKz(this.student.studiengang_kz))
.then(result => {
this.stgInfo = result.data;
this.setDefaultFormData();
})
.catch(this.$fhcAlert.handleSystemError);
} else
this.getStudiengangByKz();
},
template: `
<div class="stv-details-abschlusspruefung h-100 pb-3">
<h4>{{this.$p.t('stv','tab_finalexam')}}</h4>
<div v-if="this.student.length">
<abschlusspruefung-dropdown
:showAllFormats="isBerechtigtDocAndOdt"
:studentUids="studentUids"
:showDropDownMulti="true"
:stgTyp="stgInfo.typ"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></abschlusspruefung-dropdown>
</div>
<core-filter-cmpt
v-if="!this.student.length"
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
reload
new-btn-show
:new-btn-label="this.$p.t('stv', 'tab_finalexam')"
@click:new="actionNewAbschlusspruefung"
>
</core-filter-cmpt>
<!--Modal: finalexamModal-->
<bs-modal ref="finalexamModal" dialog-class="modal-xl modal-dialog-scrollable">
<template #title>
<p v-if="statusNew" class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungAnlegen')}}</p>
<p v-else class="fw-bold mt-3">{{$p.t('abschlusspruefung', 'abschluessPruefungBearbeiten')}}</p>
</template>
<pruefung-list ref="pruefungList" :uid="student.uid"></pruefung-list>
<form-form v-if="!this.student.length" ref="formFinalExam" @submit.prevent>
<legend>{{this.$p.t('global','details')}}</legend>
<p v-if="statusNew">[{{$p.t('ui', 'neu')}}]</p>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-typ"
:label="$p.t('global', 'typ')"
type="select"
v-model="formData.pruefungstyp_kurzbz"
name="pruefungstyp_kurzbz"
>
<option
v-for="typ in arrTypen"
:key="typ.pruefungstyp_kurzbz"
:value="typ.pruefungstyp_kurzbz"
>
{{typ.beschreibung}}
</option>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-note"
:label="$p.t('abschlusspruefung', 'notekommpruefung')"
type="select"
v-model="formData.note"
name="note"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="note in arrNoten"
:key="note.note"
:value="note.note"
>
{{note.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefungsantritt"
:label="$p.t('abschlusspruefung', 'pruefungsantritt')"
type="select"
v-model="formData.pruefungsantritt_kurzbz"
name="pruefungsantritt_kurzbz"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="antritt in arrAntritte"
:key="antritt.pruefungsantritt_kurzbz"
:value="antritt.pruefungsantritt_kurzbz"
>
{{antritt.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.vorsitz"
name="vorsitz"
:suggestions="filteredMitarbeiter"
@complete="search"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.pv"
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
v-model="formData.pv"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-vorsitz"
:label="$p.t('abschlusspruefung', 'vorsitz_header')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.vorsitz"
name="vorsitz"
:suggestions="filteredMitarbeiter"
@complete="search"
:min-length="3"
>
</form-input>
</template>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
:label="$p.t('abschlusspruefung', 'pruefer1')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer1"
name="pruefer1"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p1"
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer1')"
v-model="formData.p1"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer1"
:label="$p.t('abschlusspruefung', 'pruefer1')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer1"
name="pruefer1"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-abschlussbeurteilung_kurzbz"
:label="$p.t('abschlusspruefung', 'abschlussbeurteilung')"
type="select"
v-model="formData.abschlussbeurteilung_kurzbz"
name="abschlussbeurteilung_kurzbz"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="beurteilung in arrBeurteilungen"
:key="beurteilung.abschlussbeurteilung_kurzbz"
:value="beurteilung.abschlussbeurteilung_kurzbz"
>
{{beurteilung.bezeichnung}}
</option>
</form-input>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
:label="$p.t('abschlusspruefung', 'pruefer2')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer2"
name="pruefer2"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p2"
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer2')"
v-model="formData.p2"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer2"
:label="$p.t('abschlusspruefung', 'pruefer2')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer2"
name="pruefer2"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-akadgrad"
:label="$p.t('abschlusspruefung', 'akadGrad')"
type="select"
v-model="formData.akadgrad_id"
name="akadgrad_id"
>
<option
v-for="grad in arrAkadGrad"
:key="grad.akadgrad_id"
:value="grad.akadgrad_id"
>
{{grad.titel}}
</option>
</form-input>
<template v-if="statusNew">
<form-input
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
:label="$p.t('abschlusspruefung', 'pruefer3')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer3"
name="pruefer3"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
<template v-else >
<form-input
v-if= "formData.p3"
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
type="text"
name="name"
:label="$p.t('abschlusspruefung', 'pruefer3')"
v-model="formData.p3"
>
</form-input>
<form-input
v-else
container-class="col-6 stv-details-abschlusspruefung-pruefer3"
:label="$p.t('abschlusspruefung', 'pruefer3')"
type="autocomplete"
optionLabel="mitarbeiter"
v-model="formData.pruefer3"
name="pruefer3"
:suggestions="filteredPruefer"
@complete="searchNotAkad"
:min-length="3"
>
</form-input>
</template>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-datum"
:label="$p.t('global', 'datum')"
type="DatePicker"
v-model="formData.datum"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="datum"
:teleport="true"
>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-anmerkung"
:label="$p.t('global', 'anmerkung')"
type="textarea"
v-model="formData.anmerkung"
name="anmerkung"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-abschlusspruefung-sponsion"
:label="$p.t('abschlusspruefung', 'sponsion')"
type="DatePicker"
v-model="formData.sponsion"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
name="sponsion"
:teleport="true"
>
</form-input>
<form-input
container-class="col-6 stv-details-abschlusspruefung-protokoll"
:label="$p.t('abschlusspruefung', 'protokoll')"
type="textarea"
v-model="formData.protokoll"
name="protokoll"
:rows= 10
>
</form-input>
</div>
<div class="row mb-3 col-6">
<div class="col">
<p >{{$p.t('abschlusspruefung', 'zurBeurteilung')}}</p>
</div>
<div class="col">
<p>
<a :href="formData.link" target="_blank" rel="noopener noreferrer">
{{$p.t('abschlusspruefung', 'pruefungsprotokoll')}}
</a>
</p>
</div>
</div>
</form-form>
<template #footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
<button v-if="statusNew" class="btn btn-primary" @click="addNewAbschlusspruefung()"> {{$p.t('ui', 'speichern')}}</button>
<button v-else class="btn btn-primary" @click="updateAbschlusspruefung(formData.abschlusspruefung_id)"> {{$p.t('ui', 'speichern')}}</button>
</template>
</bs-modal>
<Teleport v-for="data in tabulatorData" :key="data.abschlusspruefung_id" :to="data.actionDiv">
<abschlusspruefung-dropdown
:showAllFormats="isBerechtigtDocAndOdt"
:showDropDownMulti="false"
:abschlusspruefung_id="data.abschlusspruefung_id"
:studentUids="data.student_uid"
:stgPrfgTyp="data.pruefungstyp_kurzbz"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></abschlusspruefung-dropdown>
</Teleport>
</div>
`
}
@@ -1,4 +1,3 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
@@ -7,7 +6,6 @@ import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js
export default {
components: {
CoreFilterCmpt,
FormForm,
FormInput,
PvAutoComplete
@@ -48,23 +46,12 @@ export default {
}
return lehreinheiten;
},
//~ preparedFormData() {
//~ console.log("FOR DATA CALLEd");
//~ if (this.formData.projektarbeit_id == null) delete(this.formData.projektarbeit_id);
//~ if (this.formData.firma) this.formData.firma_id = this.formData.firma.firma_id;
//~ delete(this.formData.firma);
//~ delete(this.formData.firma_name);
//~ delete(this.formData.lehrveranstaltung_id);
//~ // convert null value fields from string to null
//~ return this.formData;
//~ }
}
},
props: {
statusNew: Boolean,
student: Object,
projektarbeit: Object,
stg_kz: Number
projektarbeit: Object
},
data() {
return {
@@ -177,21 +164,13 @@ export default {
})
.catch(this.$fhcAlert.handleSystemError);
},
setFormData(arrTypen, arrLvs, arrNoten, projektarbeitData) {
this.arrTypen = arrTypen;
this.arrLvs = arrLvs;
this.arrNoten = arrNoten;
if (projektarbeitData) {
projektarbeitData.firma = {firma_id: projektarbeitData.firma_id, name: projektarbeitData.firma_name};
this.formData = projektarbeitData;
}
},
loadProjektarbeit(projektarbeit_id) {
return this.$api
.call(ApiStvProjektarbeit.loadProjektarbeit(projektarbeit_id))
.then(result => {
this.formData = result.data;
if (this.formData.firma_id) this.formData.firma = {firma_id: this.formData.firma_id, name: this.formData.firma_name};
return result;
})
.catch(this.$fhcAlert.handleSystemError)
@@ -7,6 +7,7 @@ import PvAutoComplete from "../../../../../../../index.ci.php/public/js/componen
import ApiStvProjektarbeit from '../../../../../api/factory/stv/projektarbeit.js';
import ProjektarbeitDetails from "./Details.js";
import Projektbetreuer from "./Projektbetreuer.js";
export default {
components: {
@@ -15,7 +16,8 @@ export default {
FormForm,
FormInput,
PvAutoComplete,
ProjektarbeitDetails
ProjektarbeitDetails,
Projektbetreuer
},
inject: {
cisRoot: {
@@ -174,7 +176,9 @@ export default {
button.title = this.$p.t('ui', 'bearbeiten');
button.addEventListener('click', (event) => {
let data = cell.getData();
this.actionEditProjektarbeit(data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id);
this.actionEditProjektarbeit(
data.projektarbeit_id, data.studiensemester_kurzbz, data.lehrveranstaltung_id, data.projekttyp_kurzbz
);
});
container.append(button);
@@ -195,7 +199,6 @@ export default {
},
],
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
height: 'auto',
minHeight: '200',
selectable: 1,
@@ -240,25 +243,20 @@ export default {
lehrveranstaltung_id: null
}
},
//~ watch: {
//~ student(){
//~ if (this.$refs.table) {
//~ this.$refs.table.reloadTable();
//~ }
//~ this.getStudiengangByKz();
//~ }
//~ },
methods: {
actionNewProjektarbeit() {
this.statusNew = true;
this.$refs.projektarbeitDetails.resetForm();
this.$refs.projektarbeitDetails.getFormData();
this.$refs.projektbetreuer.getData();
this.$refs.projektarbeitModal.show();
},
actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id) {
actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) {
this.statusNew = false;
this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id);
// TODO: maybe preload projektarbeit? not just on edit?
this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id);
this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz);
this.$refs.projektarbeitModal.show();
},
actionDeleteProjektarbeit(projektarbeit_id) {
@@ -271,41 +269,41 @@ export default {
.catch(this.$fhcAlert.handleSystemError);
},
addNewProjektarbeit() {
Promise.allSettled([
this.$refs.projektarbeitDetails.addNewProjektarbeit()
]).then((results) => {
let hasError = false;
results.forEach((promise_result) => {
this.$refs.projektbetreuer.validateProjektbetreuer()
.then(() => {
return this.$refs.projektarbeitDetails.addNewProjektarbeit();
})
.then((result) => {
const projektarbeit_id = result.data;
console.log(projektarbeit_id);
if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) {
hasError = true;
if (!isNaN(projektarbeit_id)) {
return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id);
}
});
if (!hasError) {
})
.then((result) => {
console.log(result);
this.projektarbeitSaved();
}
});
})
.catch(this.$fhcAlert.handleSystemError);
},
updateProjektarbeit() {
Promise.allSettled(
[
this.$refs.projektarbeitDetails.updateProjektarbeit()
]).then((results) => {
let hasError = false;
results.forEach((promise_result) => {
this.$refs.projektbetreuer.validateProjektbetreuer()
.then(() => {
return this.$refs.projektarbeitDetails.updateProjektarbeit();
})
.then((result) => {
const projektarbeit_id = result.data;
console.log(projektarbeit_id);
if (!(promise_result.status === 'fulfilled' && promise_result.value.meta.status === "success")) {
hasError = true;
if (!isNaN(projektarbeit_id)) {
return this.$refs.projektbetreuer.saveProjektbetreuer(projektarbeit_id);
}
});
if (!hasError) {
})
.then((result) => {
this.projektarbeitSaved();
}
});
})
.catch(this.$fhcAlert.handleSystemError);
},
deleteProjektarbeit(projektarbeit_id) {
return this.$api
@@ -325,7 +323,6 @@ export default {
this.$refs.projektarbeitDetails.resetForm();
},
rowSelectionChanged(data) {
console.log("selection changed");
this.lastSelected = data.length > 0 ? data[0] : null;
},
hideModal(modalRef){
@@ -362,7 +359,14 @@ export default {
<p v-else class="fw-bold mt-3">{{$p.t('projektarbeit', 'projektarbeitBearbeiten')}}</p>
</template>
<projektarbeit-details ref="projektarbeitDetails" :student="student" :stg_kz="stg_kz"></projektarbeit-details>
<div class="row">
<div class="col-6">
<projektarbeit-details ref="projektarbeitDetails" :student="student"></projektarbeit-details>
</div>
<div class="col-6">
<projektbetreuer ref="projektbetreuer" :config="config"></projektbetreuer>
</div>
</div>
<template #footer>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{$p.t('ui', 'abbrechen')}}</button>
@@ -0,0 +1,421 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import FormForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js';
export default {
components: {
CoreFilterCmpt,
FormForm,
FormInput,
PvAutoComplete
},
inject: {
},
computed: {
},
props: {
config: {
type: Object,
default: {}
}
},
data() {
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: 'Aktionen', field: 'actions',
minWidth: 150, // Ensures Action-buttons will be always fully displayed
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement('div');
container.className = "d-flex gap-2";
let button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$p.t('ui', 'bearbeiten');
button.addEventListener('click', (event) => {
let data = cell.getData();
this.actionEditProjektbetreuer(data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz);
});
container.append(button);
button = document.createElement('button');
button.className = 'btn btn-outline-secondary btn-action';
button.innerHTML = '<i class="fa fa-xmark"></i>';
button.title = this.$p.t('ui', 'loeschen');
button.addEventListener('click', () => {
const data = cell.getData();
this.actionDeleteProjektbetreuer(data.betreuer_id, data.projektarbeit_id, data.person_id, data.betreuerart_kurzbz)
});
container.append(button);
//container.append(cell.getData().actionDiv);
return container;
},
frozen: true
},
],
layout: 'fitDataFill',
layoutColumnsOnNewData: false,
height: 'auto',
minHeight: '100',
selectable: true,
selectable: 1,
index: 'betreuer_id',
persistenceID: 'stv-details-projektbetreuer'
},
tabulatorEvents: [
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'projektarbeit', 'ui']);
}
}
],
formData: {
betreuerart_kurzbz: null,
note: null,
stunden: null,
stundensatz: null
},
initialFormData: null,
defaultFormDataValues: {stunden: null, stundensatz: null},
projektarbeit_id: null,
statusNew: true,
editedBetreuerIdx: -1,
arrBetreuerart: [],
arrNoten: [],
filteredBetreuer: [],
autocompleteSelectedBetreuer: null,
abortController: {
betreuer: null
}
}
},
methods: {
actionNewProjektbetreuer() {
this.resetForm();
this.statusNew = true;
this.captureFormData();
},
actionEditProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) {
this.$api
.call(ApiStvProjektbetreuer.getDefaultStundensaetze(person_id, this.studiensemester_kurzbz))
.then(result => {
this.resetForm();
this.statusNew = false;
let projektbetreuerListe = this.$refs.table.tabulator.getData();
const idx = projektbetreuerListe.findIndex(
betr =>
betr.person_id === person_id &&
betr.projektarbeit_id === projektarbeit_id &&
betr.betreuerart_kurzbz === betreuerart_kurzbz
);
let betreuer = [];
if (idx >= 0) {
betreuer = projektbetreuerListe[idx];
this.formData = betreuer;
this.autocompleteSelectedBetreuer = {
person_id: this.formData.person_id,
name: this.formData.name,
vorname: this.formData.vorname,
nachname: this.formData.nachname
};
}
if (this.formData.stundensatz == null) this.formData.stundensatz = result.data;
this.captureFormData();
})
.catch(this.$fhcAlert.handleSystemError);
},
actionDeleteProjektbetreuer(betreuer_id, projektarbeit_id, person_id, betreuerart_kurzbz) {
this.$fhcAlert
.confirmDelete()
.then(result => result
? {projektarbeit_id, person_id, betreuerart_kurzbz}
: Promise.reject({handled: true}))
.then(result => {
return this.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)
})
.then(result => {
this.$refs.table.tabulator.deleteRow(betreuer_id);
})
.catch(this.$fhcAlert.handleSystemError);
},
getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz) {
console.log(projekttyp_kurzbz);
this.studiensemester_kurzbz = studiensemester_kurzbz;
this.defaultFormDataValues.stunden = '0.0';
if (projekttyp_kurzbz == 'Bachelor') this.defaultFormDataValues.stunden = this.config.defaultProjektbetreuerStunden;
if (projekttyp_kurzbz == 'Diplom') this.defaultFormDataValues.stunden = this.config.defaultProjektbetreuerStundenDiplom;
this.defaultFormDataValues.stundensatz = this.config.defaultProjektbetreuerStundensatz;
this.$api
.call(ApiStvProjektbetreuer.getBetreuerarten())
.then(result => {
this.arrBetreuerart = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$api
.call(ApiStvProjektbetreuer.getNoten())
.then(result => {
this.arrNoten = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
if (projektarbeit_id) {
this.projektarbeit_id = projektarbeit_id;
this.$api
.call(ApiStvProjektbetreuer.getProjektbetreuer(projektarbeit_id))
.then(result => {
this.$refs.table.tabulator.setData(this.addIds(result.data));
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError);
} else {
this.$refs.table.tabulator.setData([]);
this.resetForm();
}
},
confirmProjektbetreuer() {
if (!this.formDataModified()) return;
if (this.statusNew) {
this.formData.betreuer_id = this.getNewBetreuerId();
this.$refs.table.tabulator.addData(this.addAutoCompleteBetreuerToFormData(this.formData));
} else {
this.$refs.table.tabulator.updateData([this.formData]);
this.statusNew = true;
}
},
confirmProjektbetreuerAfterValidation() {
if (!this.formDataModified()) return;
this.validateProjektbetreuer()
.then(result => {
this.confirmProjektbetreuer();
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError);
},
saveProjektbetreuer(projektarbeit_id) {
this.confirmProjektbetreuer();
return this.$refs.formProjektbetreuer.call(
ApiStvProjektbetreuer.saveProjektbetreuer(projektarbeit_id, this.$refs.table.tabulator.getData())
);
},
deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) {
return this.$api
.call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError)
},
searchBetreuer(event) {
if (this.abortController.betreuer) {
this.abortController.betreuer.abort();
}
this.abortController.betreuer = new AbortController();
return this.$api
.call(ApiStvProjektbetreuer.getProjektbetreuerBySearchQuery(event.query))
.then(result => {
this.filteredBetreuer = result.data;
});
},
validateProjektbetreuer() {
let alleBetreuer = this.$refs.table.tabulator.getData();
if (this.formDataModified()) {
alleBetreuer.push(this.addAutoCompleteBetreuerToFormData(this.formData));
}
return this.$api.call(ApiStvProjektbetreuer.validateProjektbetreuer(alleBetreuer));
},
resetForm() {
this.formData = this.getDefaultFormData();
this.autocompleteSelectedBetreuer = null;
this.initialFormData = null;
},
getDefaultFormData() {
let formData = {betreuerart_kurzbz : null, note: null};
for (const name in this.defaultFormDataValues) {
formData[name] = this.defaultFormDataValues[name];
}
return formData;
},
captureFormData() {
this.initialFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy
},
addIds(betreuerListe) {
for (const idx in betreuerListe) {
let betreuer = betreuerListe[idx];
betreuer.person_id_old = betreuer.person_id;
betreuer.betreuerart_kurzbz_old = betreuer.betreuerart_kurzbz;
betreuer.betreuer_id = parseInt(idx);
}
return betreuerListe;
},
addAutoCompleteBetreuerToFormData() {
let preparedFormData = this.formData;
preparedFormData.projektarbeit_id = this.projektarbeit_id;
if (this.autocompleteSelectedBetreuer) {
preparedFormData.person_id = this.autocompleteSelectedBetreuer.person_id;
preparedFormData.name = this.autocompleteSelectedBetreuer.name;
preparedFormData.vorname = this.autocompleteSelectedBetreuer.vorname;
preparedFormData.nachname = this.autocompleteSelectedBetreuer.nachname;
}
return preparedFormData;
},
getNewBetreuerId() {
let max = 0;
for (const betreuer of this.$refs.table.tabulator.getData()) {
console.log(typeof betreuer.betreuer_id);
if (betreuer.betreuer_id > max) max = betreuer.betreuer_id;
}
return max + 1;
},
formDataModified() {
if (this.autocompleteSelectedBetreuer != null) return true;
console.log(this.formData);
console.log(this.initialFormData);
for (const prop in this.initialFormData) {
if (typeof this.formData[prop] == 'undefined') return true;
if (this.formData[prop] != this.initialFormData[prop]) return true;
}
return false;
},
reload() {
this.$refs.table.reloadTable();
}
},
template: `
<div class="stv-details-projektbetreuer h-100 pb-3">
<legend>{{this.$p.t('stv','betreuer')}}</legend>
<!-- <p v-if="statusNew">[{{$p.t('ui', 'neu')}}]</p> -->
<core-filter-cmpt
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
:side-menu="false"
new-btn-show
:new-btn-label="this.$p.t('stv', 'betreuer')"
@click:new="actionNewProjektbetreuer"
>
</core-filter-cmpt>
<form-form ref="formProjektbetreuer" @submit.prevent>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-betreuer"
:label="$p.t('projektarbeit', 'betreuer')"
type="autocomplete"
optionLabel="name"
v-model="autocompleteSelectedBetreuer"
name="betreuer"
:suggestions="filteredBetreuer"
@complete="searchBetreuer"
:min-length="3"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-6 stv-details-projektbetreuer-betreuerart"
:label="$p.t('global', 'betreuer')"
type="select"
v-model="formData.betreuerart_kurzbz"
name="betreuerart_kurzbz"
>
<option
v-for="art in arrBetreuerart"
:key="art.betreuerart_kurzbz"
:value="art.betreuerart_kurzbz"
>
{{art.beschreibung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="col-8 stv-details-projektbetreuer-note"
:label="$p.t('projektarbeit', 'note')"
type="select"
v-model="formData.note"
name="note"
>
<option :value="null"> -- {{$p.t('fehlermonitoring', 'keineAuswahl')}} -- </option>
<option
v-for="note in arrNoten"
:key="note.note"
:value="note.note"
>
{{note.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-stunden"
type="text"
name="stunden"
:label="$p.t('projektarbeit', 'stunden')"
v-model="formData.stunden"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
container-class="stv-details-projektarbeit-stundensatz"
type="text"
name="stundensatz"
:label="$p.t('projektarbeit', 'stundensatz')"
v-model="formData.stundensatz"
>
</form-input>
</div>
</form-form>
<button class="btn btn-primary" @click="confirmProjektbetreuerAfterValidation">{{ $p.t('projektarbeit', 'betreuerBestaetigen') }}</button>
</div>
`
}
+1 -1
View File
@@ -25025,7 +25025,7 @@ array(
),
array(
'sprache' => 'English',
'text' => 'The Field {Field} must contain only numbers.',
'text' => 'The Field {field} must contain only numbers.',
'description' => '',
'insertvon' => 'system'
)