Merge branch 'feature-54564/FHC-4_Studierendenverwaltung_Abschlusspruefung' into merge_FHC4_C4

This commit is contained in:
Harald Bamberger
2025-01-27 18:17:50 +01:00
18 changed files with 1938 additions and 23 deletions
+51 -17
View File
@@ -2,25 +2,59 @@
$config['tabs'] =
[
'details' => [
//all fields can be configured to be hidden, see class attribute stv-details-details-name for name
'hiddenFields' => [],
'hideUDFs' => false
],
'prestudent' => [
//all fields can be configured to be hidden, see class attribute stv-details-prestudent-name for name
'hiddenFields' => [
//propably used by FH-Communities
'aufnahmeschluessel', 'standort_code', 'facheinschlaegigBerufstaetig'
'details' => [
//all fields can be configured to be hidden, see class attribute stv-details-details-name for name
'hiddenFields' => [],
'hideUDFs' => false
],
'hideUDFs' => false
]
];
'prestudent' => [
//all fields can be configured to be hidden, see class attribute stv-details-prestudent-name for name
'hiddenFields' => [
//propably used by FH-Communities
'aufnahmeschluessel', 'standort_code', 'facheinschlaegigBerufstaetig'
],
'hideUDFs' => false
],
'finalexam' => [
'documents' => [
'pruefungsprotokoll' => [
'de' => [
'Bakk' => 'PrProtBA',
'Master' => 'PrProtMA',
],
'en' => [
'Bakk' => 'PrProtBAEng',
'Master' => 'PrProtMAEng',
],
],
'pruefungszeugnis' => [
'de' => [
'Bakk' => 'Bakkzeugnis',
'Master' => 'Diplomzeugnis',
],
'en' => [
'Bakk' => 'BakkzeugnisEng',
'Master' => 'DiplomzeugnisEng',
],
],
'urkunde' => [
'de' => [
'Bakk' => 'Bakkurkunde',
'Master' => 'Diplomurkunde',
],
'en' => [
'Bakk' => 'BakkurkundeEng',
'Master' => 'DiplomurkundeEng',
],
],
],
]
];
// List of fields to show when ZGV_DOKTOR_ANZEIGEN is defined
$fieldsZgvDoktor = ['zgvdoktorort', 'zgvdoktordatum', 'zgvdoktornation', 'zgvdoktor_erfuellt', 'zgvdoktor_code'];
@@ -30,7 +30,8 @@ class Studentenverwaltung extends Auth_Controller
'admin' => $this->permissionlib->isBerechtigt('admin'),
'assistenz_schreibrechte' => $this->permissionlib->isBerechtigt('assistenz','suid'),
'student/keine_studstatuspruefung' => $this->permissionlib->isBerechtigt('student/keine_studstatuspruefung'),
'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht')
'lehre/reihungstestAufsicht' => $this->permissionlib->isBerechtigt('lehre/reihungstestAufsicht'),
'system/change_outputformat' => $this->permissionlib->getOE_isEntitledFor('system/change_outputformat'),
],
'variables' => [
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell')
@@ -0,0 +1,407 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Abschlusspruefung extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getAbschlusspruefung' => ['admin:r', 'assistenz:r'],
'loadAbschlusspruefung' => ['admin:r', 'assistenz:r'],
'insertAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'updateAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'deleteAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'getTypenAbschlusspruefung' => ['admin:rw', 'assistenz:rw'],
'getNoten' => ['admin:rw', 'assistenz:rw'],
'getTypenAntritte' => ['admin:rw', 'assistenz:rw'],
'getBeurteilungen' => ['admin:rw', 'assistenz:rw'],
'getAkadGrade' => ['admin:rw', 'assistenz:rw'],
'getMitarbeiter' => ['admin:rw', 'assistenz:rw'],
'getPruefer' => ['admin:rw', 'assistenz:rw'],
'getTypStudiengang' => ['admin:rw', 'assistenz:rw'],
'checkForExistingExams' => ['admin:rw', 'assistenz:rw'],
]);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'person',
'abschlusspruefung'
]);
// Load models
$this->load->model('education/Abschlusspruefung_model', 'AbschlusspruefungModel');
}
public function getAbschlusspruefung($student_uid)
{
$result = $this->AbschlusspruefungModel->getAbschlusspruefungForPrestudent($student_uid);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess((getData($result) ?: []));
}
public function loadAbschlusspruefung()
{
$abschlusspruefung_id = $this->input->post('id');
$this->AbschlusspruefungModel->addSelect('lehre.tbl_abschlusspruefung.*');
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer1 IS NOT NULL
THEN CONCAT(p1.nachname, ' ', p1.vorname, COALESCE(' ' || p1.titelpre, ''))
ELSE NULL
END AS p1
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer2 IS NOT NULL
THEN CONCAT(p2.nachname, ' ', p2.vorname, COALESCE(' ' || p2.titelpre, ''))
ELSE NULL
END AS p2
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN pruefer3 IS NOT NULL
THEN CONCAT(p3.nachname, ' ', p3.vorname, COALESCE(' ' || p3.titelpre, ''))
ELSE NULL
END AS p3
");
$this->AbschlusspruefungModel->addSelect("
CASE
WHEN vorsitz IS NOT NULL
THEN CONCAT(pv.nachname, ' ', pv.vorname, COALESCE(' ' || pv.titelpre, ''), ' (', ben.uid , ')' )
ELSE NULL
END AS pv
");
$this->AbschlusspruefungModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = lehre.tbl_abschlusspruefung.vorsitz)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person pv', 'ON (pv.person_id = ben.person_id)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p1', 'ON (p1.person_id = lehre.tbl_abschlusspruefung.pruefer1)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p2', 'ON (p2.person_id = lehre.tbl_abschlusspruefung.pruefer2)', 'LEFT');
$this->AbschlusspruefungModel->addJoin('public.tbl_person p3', 'ON (p3.person_id = lehre.tbl_abschlusspruefung.pruefer3)', 'LEFT');
$result = $this->AbschlusspruefungModel->loadWhere(
array('abschlusspruefung_id' => $abschlusspruefung_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function getTypenAbschlusspruefung()
{
$this->load->model('education/Pruefungstyp_model', 'PruefungstypModel');
$result = $this->PruefungstypModel->loadWhere(
array('abschluss' => true)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getTypenAntritte()
{
$this->load->model('education/Pruefungsantritt_model', 'PruefungsantrittModel');
$result = $this->PruefungsantrittModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getBeurteilungen()
{
$this->load->model('education/Abschlussbeurteilung_model', 'AbschlussbeurteilungModel');
$result = $this->AbschlussbeurteilungModel->load();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getAkadGrade()
{
$studiengang_kz= $this->input->post('studiengang_kz');
$this->load->model('education/Akadgrad_model', 'AkadgradModel');
$result = $this->AkadgradModel->loadWhere(
array('studiengang_kz' => $studiengang_kz)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getTypStudiengang()
{
$studiengang_kz= $this->input->post('studiengang_kz');
/* if (!$studiengang_kzs || !is_array($studiengang_kzs)) {
$this->load->library('form_validation');
$this->form_validation->set_rules('studiengang_kzs', '', 'required|is_null', [
'is_null' => $this->p->t('ui', 'error_fieldMustBeArray')
]);
if (!$this->form_validation->run())
$this->terminateWithValidationErrors($this->form_validation->error_array());
}*/
$this->load->model('organisation/Studiengang_model', 'StudiengangModel');
$result = $this->StudiengangModel->loadWhere(
array('studiengang_kz' => $studiengang_kz)
);
$data = $this->getDataOrTerminateWithError($result);
$typStudiengang = current($data)->typ;
$this->terminateWithSuccess($typStudiengang);
}
public function getMitarbeiter($searchString)
{
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'mitAkadGrad');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function getPruefer($searchString)
{
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$result = $this->MitarbeiterModel->searchMitarbeiter($searchString, 'ohneMaUid');
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function getNoten()
{
$this->load->model('education/Note_model', 'NoteModel');
$this->NoteModel->addOrder('note', 'ASC');
$result = $this->NoteModel->load();
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
return $this->terminateWithSuccess(getData($result) ?: []);
}
public function insertAbschlusspruefung()
{
$this->load->library('form_validation');
$student_uid = $this->input->post('uid');
if(!$student_uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Student UID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['pruefungstyp_kurzbz'] = $formData['pruefungstyp_kurzbz'];
$_POST['akadgrad_id']= $formData['akadgrad_id'];
$_POST['vorsitz'] = isset($formData['vorsitz']['mitarbeiter_uid']) ? $formData['vorsitz']['mitarbeiter_uid'] : $formData['vorsitz'];
$_POST['pruefer1'] = isset($formData['pruefer1']['person_id']) ? $formData['pruefer1']['person_id'] : $formData['pruefer1'];
$_POST['pruefer2'] = isset($formData['pruefer2']['person_id']) ? $formData['pruefer2']['person_id'] : $formData['pruefer2'];
$_POST['pruefer3'] = isset($formData['pruefer3']['person_id']) ? $formData['pruefer3']['person_id'] : $formData['pruefer3'];
$_POST['pruefungsantritt_kurzbz'] = $formData['pruefungsantritt_kurzbz'];
$_POST['abschlussbeurteilung_kurzbz'] = $formData['abschlussbeurteilung_kurzbz'];
$_POST['datum']= $formData['datum'];
$_POST['sponsion']= $formData['sponsion'];
$_POST['anmerkung'] = $formData['anmerkung'];
$_POST['protokoll']= $formData['protokoll'];
$_POST['note'] = $formData['note'];
$this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ'])
]);
$this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum'])
]);
$this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->AbschlusspruefungModel->insert([
'student_uid' => $student_uid,
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'akadgrad_id' => $this->input->post('akadgrad_id'),
'vorsitz' => $this->input->post('vorsitz'),
'pruefungsantritt_kurzbz' => $this->input->post('pruefungsantritt_kurzbz'),
'abschlussbeurteilung_kurzbz' => $this->input->post('abschlussbeurteilung_kurzbz'),
'datum' => $this->input->post('datum'), //TODO(Manu) check if minute format like FAS
'sponsion' => $this->input->post('sponsion'),
'pruefer1' => $this->input->post('pruefer1'),
'pruefer2' => $this->input->post('pruefer2'),
'pruefer3' => $this->input->post('pruefer3'),
'protokoll' => $this->input->post('protokoll'),
'note' => $this->input->post('note'),
'anmerkung' => $this->input->post('anmerkung'),
'insertamum' => date('c'),
'insertvon' => getAuthUID()
]);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function updateAbschlusspruefung()
{
$this->load->library('form_validation');
$abschlusspruefung_id = $this->input->post('id');
if(!$abschlusspruefung_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Abschlussprüfung ID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$_POST['student_uid'] = $formData['student_uid'];
$_POST['pruefungstyp_kurzbz'] = $formData['pruefungstyp_kurzbz'];
$_POST['akadgrad_id']= $formData['akadgrad_id'];
$_POST['vorsitz'] = isset($formData['vorsitz']['mitarbeiter_uid']) ? $formData['vorsitz']['mitarbeiter_uid'] : $formData['vorsitz'];
$_POST['pruefer1'] = isset($formData['pruefer1']['person_id']) ? $formData['pruefer1']['person_id'] : $formData['pruefer1'];
$_POST['pruefer2'] = isset($formData['pruefer2']['person_id']) ? $formData['pruefer2']['person_id'] : $formData['pruefer2'];
$_POST['pruefer3'] = isset($formData['pruefer3']['person_id']) ? $formData['pruefer3']['person_id'] : $formData['pruefer3'];
$_POST['pruefungsantritt_kurzbz'] = $formData['pruefungsantritt_kurzbz'];
$_POST['abschlussbeurteilung_kurzbz'] = $formData['abschlussbeurteilung_kurzbz'];
$_POST['datum']= $formData['datum'];
$_POST['sponsion']= $formData['sponsion'];
$_POST['anmerkung'] = $formData['anmerkung'];
$_POST['protokoll']= $formData['protokoll'];
$_POST['note'] = $formData['note'];
$this->form_validation->set_rules('pruefungstyp_kurzbz', 'Typ', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Typ'])
]);
$this->form_validation->set_rules('datum', 'Datum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Datum'])
]);
$this->form_validation->set_rules('sponsion', 'Sponsion', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Sponsion'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->AbschlusspruefungModel->update(
[
'abschlusspruefung_id' => $abschlusspruefung_id
],
[
'student_uid' => $this->input->post('student_uid'),
'pruefungstyp_kurzbz' => $this->input->post('pruefungstyp_kurzbz'),
'akadgrad_id' => $this->input->post('akadgrad_id'),
'vorsitz' => $this->input->post('vorsitz'),
'pruefungsantritt_kurzbz' => $this->input->post('pruefungsantritt_kurzbz'),
'abschlussbeurteilung_kurzbz' => $this->input->post('abschlussbeurteilung_kurzbz'),
'datum' => $this->input->post('datum'),
'sponsion' => $this->input->post('sponsion'),
'pruefer1' => $this->input->post('pruefer1'),
'pruefer2' => $this->input->post('pruefer2'),
'pruefer3' => $this->input->post('pruefer3'),
'protokoll' => $this->input->post('protokoll'),
'note' => $this->input->post('note'),
'anmerkung' => $this->input->post('anmerkung'),
'insertamum' => date('c'),
'insertvon' => getAuthUID()
]
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteAbschlusspruefung()
{
$abschlusspruefung_id = $this->input->post('id');
$result = $this->AbschlusspruefungModel->delete(
array('abschlusspruefung_id' => $abschlusspruefung_id)
);
if (isError($result))
{
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
$this->outputJson($result);
}
return $this->terminateWithSuccess(current(getData($result)) ? : null);
}
public function checkForExistingExams()
{
$warning = false;
$output = [];
$student_uids = $this->input->post('uids');
if (empty($student_uids)) {
throw new InvalidArgumentException("Keine UID(s) übergeben.");
}
foreach ($student_uids as $uid)
{
$result = $this->AbschlusspruefungModel->loadWhere(
array('student_uid' => $uid)
);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
if (!hasData($result))
{
$warning = true;
$output[] = $uid;
}
}
if($warning)
{
$uids = is_array($output) ? implode(", ", $output) : $output;
return $this->terminateWithError($this->p->t('abschlusspruefung', 'error_studentOhneFinalExam', ['id'=> $uids]), self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess('step3');
}
}
@@ -44,7 +44,8 @@ class Config extends FHCAPI_Controller
'person',
'lehre',
'stv',
'konto'
'konto',
'abschlusspruefung'
]);
// Load Config
@@ -109,6 +110,12 @@ class Config extends FHCAPI_Controller
'component' => './Stv/Studentenverwaltung/Details/Pruefung.js'
];
$result['finalexam'] = [
'title' => $this->p->t('stv', 'tab_finalexam'),
'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js',
'config' => $config['finalexam']
];
Events::trigger('stv_conf_student', function & () use (&$result) {
return $result;
});
@@ -119,6 +126,7 @@ class Config extends FHCAPI_Controller
public function students()
{
$result = [];
$config = $this->config->item('tabs');
$result['banking'] = [
'title' => $this->p->t('stv', 'tab_banking'),
'component' => './Stv/Studentenverwaltung/Details/Konto.js',
@@ -142,6 +150,11 @@ class Config extends FHCAPI_Controller
'changeStatusToAbsolvent' => $this->permissionlib->isBerechtigt('admin')
]
];
$result['finalexam'] = [
'title' => $this->p->t('stv', 'tab_finalexam'),
'component' => './Stv/Studentenverwaltung/Details/Abschlusspruefung.js',
'config' => $config['finalexam']
];
Events::trigger('stv_conf_students', function & () use (&$result) {
return $result;
@@ -48,7 +48,7 @@ class Favorites extends FHCAPI_Controller
if (!$data)
$this->terminateWithSuccess(null);
else
$this->terminateWithSuccess($data['stv_favorites']);
$this->terminateWithSuccess($data['stv_favorites'] ?? null);
}
public function set()
@@ -113,4 +113,60 @@ class Abschlusspruefung_model extends DB_Model
return success($abschlusspruefungdata);
}
/**
* Gets data of an Abschlusspruefung
* @param $student_uid
* @return object
*/
public function getAbschlusspruefungForPrestudent($student_uid)
{
$qry = "
SELECT
exam.*,
CONCAT(
person_pruefer1.nachname || ' ',
person_pruefer1.vorname,
COALESCE(' ' || person_pruefer1.titelpre)
) AS person_pruefer1,
CONCAT(
person_pruefer2.nachname || ' ',
person_pruefer2.vorname,
COALESCE(' ' || person_pruefer2.titelpre)
) AS person_pruefer2,
CONCAT(
person_pruefer3.nachname || ' ',
person_pruefer3.vorname,
COALESCE(' ' || person_pruefer3.titelpre)
) AS person_pruefer3,
CONCAT(
person_vorsitzender.nachname || ' ',
person_vorsitzender.vorname,
COALESCE(' ' || person_vorsitzender.titelpre)
) AS person_vorsitzender,
TO_CHAR(datum::timestamp, 'DD.MM.YYYY') AS format_datum,
TO_CHAR(freigabedatum::timestamp, 'DD.MM.YYYY') AS format_freigabedatum,
TO_CHAR(sponsion::timestamp, 'DD.MM.YYYY') AS format_sponsion,
person_pruefer1.nachname as p1_nachname,
person_pruefer2.nachname as p2_nachname,
person_pruefer3.nachname as p3_nachname,
person_vorsitzender.nachname as vorsitz_nachname,
beurteilung.bezeichnung as beurteilung_bezeichnung,
antritt.bezeichnung as antritt_bezeichnung
FROM
lehre.tbl_abschlusspruefung exam
JOIN lehre.tbl_pruefungstyp USING (pruefungstyp_kurzbz)
LEFT JOIN public.tbl_benutzer ben_vorsitzender ON (ben_vorsitzender.uid = vorsitz)
LEFT JOIN public.tbl_person person_vorsitzender ON (ben_vorsitzender.person_id = person_vorsitzender.person_id)
LEFT JOIN public.tbl_person person_pruefer1 ON (person_pruefer1.person_id = pruefer1)
LEFT JOIN public.tbl_person person_pruefer2 ON (person_pruefer2.person_id = pruefer2)
LEFT JOIN public.tbl_person person_pruefer3 ON (person_pruefer3.person_id = pruefer3)
LEFT JOIN lehre.tbl_abschlussbeurteilung beurteilung USING (abschlussbeurteilung_kurzbz)
LEFT JOIN lehre.tbl_abschlusspruefung_antritt antritt USING (pruefungsantritt_kurzbz)
WHERE student_uid = ?
ORDER BY datum DESC
";
return $this->execQuery($qry, array('student_uid' => $student_uid));
}
}
@@ -0,0 +1,14 @@
<?php
class Akadgrad_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'lehre.tbl_akadgrad';
$this->pk = 'akadgrad_id';
}
}
@@ -0,0 +1,14 @@
<?php
class Pruefungsantritt_model extends DB_Model
{
/**
* Constructor
*/
public function __construct()
{
parent::__construct();
$this->dbTable = 'lehre.tbl_abschlusspruefung_antritt';
$this->pk = 'pruefungsantritt_kurzbz';
}
}
@@ -217,12 +217,28 @@ class Mitarbeiter_model extends DB_Model
return success($kurzbz);
}
public function searchMitarbeiter($filter)
/**
* Search function for mitarbeiter
* @param $filter searchstring: searches for nachname, vorname, mitarbeiter_uid
* $param $mode gives the resultobject in different version:
* null : "[mitarbeiter_uid], Nachname, Vorname, (mitarbeiter_uid)"
* 'mitAkadGrad': "[mitarbeiter_uid], Nachname, Vorname, Titelpre, Titelpost (mitarbeiter_uid)"
* 'ohneMaUid' : "[mitarbeiter_uid], Nachname, Vorname, Titelpre, Titelpost"
* @return object in 3 versions
*/
public function searchMitarbeiter($filter, $mode=null)
{
$filter = strtoLower($filter);
if ($mode == "mitAkadGrad")
$returnwert = "ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' ', p.titelpost, ' ', p.titelpre, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter";
elseif ($mode == "ohneMaUid")
$returnwert = "p.person_id, CONCAT(p.nachname, ' ', p.vorname, ' ', p.titelpost, ' ', p.titelpre) as mitarbeiter";
else
$returnwert = "ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter";
$qry = "
SELECT
ma.mitarbeiter_uid, CONCAT(p.nachname, ' ', p.vorname, ' (', ma.mitarbeiter_uid , ')') as mitarbeiter
SELECT " . $returnwert . "
FROM
public.tbl_mitarbeiter ma
JOIN
+25
View File
@@ -52,6 +52,31 @@ html {
height: 0;
}
/* Dropdown AbschlusspruefungList.js */
.tabulator-row {
overflow: visible !important;
}
.tabulator-cell {
overflow: visible !important;
}
.p-dropdown-item{
z-index: 1201 !important;
}
.l-dropdown-item{
z-index: 1301 !important;
}
.tabulator-row .dropdown-menu {
position: absolute;
z-index: 1204; /* Ensure it's above other elements */
}
.tabulator-table {
overflow: visible !important;
}
@media (min-width: 768px) {
#sidebarMenu {
visibility: visible!important;
+2
View File
@@ -7,6 +7,7 @@ import prestudent from './stv/prestudent.js';
import status from './stv/status.js';
import details from './stv/details.js';
import exam from './stv/exam.js';
import abschlusspruefung from './stv/abschlusspruefung.js';
export default {
verband,
@@ -18,6 +19,7 @@ export default {
status,
details,
exam,
abschlusspruefung,
configStudent() {
return this.$fhcApi.get('api/frontend/v1/stv/config/student');
},
+48
View File
@@ -0,0 +1,48 @@
export default {
getAbschlusspruefung (url, config, params){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getAbschlusspruefung/' + params.id);
},
addNewAbschlusspruefung(data) {
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/insertAbschlusspruefung/', data
);
},
loadAbschlusspruefung(id){
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/loadAbschlusspruefung/', {id});
},
updateAbschlusspruefung(data) {
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/updateAbschlusspruefung/', data
);
},
deleteAbschlusspruefung(id){
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/deleteAbschlusspruefung/', {id});
},
getTypenAbschlusspruefung(){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getTypenAbschlusspruefung/');
},
getTypenAntritte(){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getTypenAntritte/');
},
getBeurteilungen(){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getBeurteilungen/');
},
getAkadGrade(studiengang_kz){
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/getAkadGrade/', {studiengang_kz});
},
getTypStudiengang(studiengang_kz){
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/getTypStudiengang/', {studiengang_kz});
},
getMitarbeiter(searchString){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getMitarbeiter/' + searchString);
},
getPruefer(searchString){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getPruefer/' + searchString);
},
getNoten(){
return this.$fhcApi.get('api/frontend/v1/stv/abschlusspruefung/getNoten/');
},
checkForExistingExams(uids) {
return this.$fhcApi.post('api/frontend/v1/stv/abschlusspruefung/checkForExistingExams/', {uids}
);
}
}
@@ -55,6 +55,7 @@ export default {
hasAdminPermission: this.permissions['admin'],
hasPermissionToSkipStatusCheck: this.permissions['student/keine_studstatuspruefung'],
hasPermissionRtAufsicht: this.permissions['lehre/reihungstestAufsicht'],
hasPermissionOutputformat: this.permissions['system/change_outputformat'],
lists: this.lists,
currentSemester: Vue.computed(() => this.studiensemesterKurzbz),
defaultSemester: this.defaultSemester,
@@ -0,0 +1,24 @@
import AbschlussPruefung from "./Abschlusspruefung/Abschlusspruefung.js";
export default {
components: {
AbschlussPruefung
},
provide() {
return {
config: this.config
};
},
props: {
modelValue: Object,
config: Object
},
data(){
return {}
},
template: `
<div class="stv-details-abschlusspruefung h-100 d-flex flex-column">
<abschluss-pruefung ref="finalexam" :student="modelValue"></abschluss-pruefung>
</div>`
};
@@ -0,0 +1,777 @@
import {CoreFilterCmpt} from "../../../../filter/Filter.js";
import BsModal from "../../../../Bootstrap/Modal.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 AbschlusspruefungDropdown from "./AbschlusspruefungDropdown";
export default {
components: {
CoreFilterCmpt,
BsModal,
FormForm,
FormInput,
PvAutoComplete,
AbschlusspruefungDropdown
},
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.$fhcApi.factory.stv.abschlusspruefung.getAbschlusspruefung,
ajaxParams: () => {
return {
id: 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: "format_datum"},
{title: "uhrzeit", field: "uhrzeit"},
{title: "freigabe", field: "format_freigabedatum"},
{title: "pruefungsantritt", field: "antritt_bezeichnung"},
{title: "sponsion", field: "format_sponsion"},
{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('format_datum').component.updateDefinition({
title: this.$p.t('global', 'datum')
});
cm.getColumnByField('uhrzeit').component.updateDefinition({
title: this.$p.t('global', 'uhrzeit')
});
cm.getColumnByField('format_freigabedatum').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'freigabe')
});
cm.getColumnByField('antritt_bezeichnung').component.updateDefinition({
title: this.$p.t('abschlusspruefung', 'pruefungsantritt')
});
cm.getColumnByField('format_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
},
stgTyp: null,
stgKz: null,
}
},
watch: {
student(){
if (this.$refs.table) {
this.$refs.table.reloadTable();
}
this.getStudiengangsTyp();
}
},
methods: {
getStudiengangsTyp(){
this.stgTyp = '';
this.$fhcApi.factory.stv.abschlusspruefung.getTypStudiengang(this.stg_kz)
.then(result => this.stgTyp = result.data)
.catch(this.$fhcAlert.handleSystemError);
},
actionNewAbschlusspruefung() {
this.resetForm();
this.statusNew = true;
this.setDefaultFormData();
},
actionEditAbschlusspruefung(abschlusspruefung_id) {
this.resetForm();
this.statusNew = false;
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.factory.stv.abschlusspruefung.addNewAbschlusspruefung(dataToSend)
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
reload() {
this.$refs.table.reloadTable();
},
loadAbschlusspruefung(abschlusspruefung_id) {
return this.$fhcApi.factory.stv.abschlusspruefung.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.factory.stv.abschlusspruefung.updateAbschlusspruefung(dataToSend)
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
this.resetForm();
})
.catch(this.$fhcAlert.handleSystemError)
.finally(() => {
this.reload();
});
},
deleteAbschlusspruefung(abschlusspruefung_id) {
return this.$fhcApi.factory.stv.abschlusspruefung.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.$refs.formFinalExam.factory.stv.abschlusspruefung.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.$refs.formFinalExam.factory.stv.abschlusspruefung.getPruefer(event.query)
.then(result => {
this.filteredPruefer = result.data.retval;
});
},
setDefaultFormData() {
this.resetForm();
//TODO(Manu) test with uid in browser
//check lg: if no prüfungsnotizen
if (this.stgTyp === 'b') {
// if (this.stgTyp === 'b' || this.formData.pruefungstyp_kurzbz == 'Bachelor') {
this.formData.pruefungstyp_kurzbz = 'Bachelor';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgTyp === 'd' || this.stgTyp === 'm') {
this.formData.pruefungstyp_kurzbz = 'Diplom';
this.formData.protokoll = this.$p.t('abschlusspruefung', 'pruefungsnotizenMaster');
}
if (this.stgTyp === '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.$fhcApi.factory.stv.abschlusspruefung.getTypenAbschlusspruefung()
.then(result => {
this.arrTypen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$fhcApi.factory.stv.abschlusspruefung.getTypenAntritte()
.then(result => {
this.arrAntritte = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$fhcApi.factory.stv.abschlusspruefung.getBeurteilungen()
.then(result => {
this.arrBeurteilungen = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$fhcApi.factory.stv.abschlusspruefung.getNoten()
.then(result => {
this.arrNoten = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
this.$fhcApi.factory.stv.abschlusspruefung.getAkadGrade(this.student.studiengang_kz)
.then(result => {
this.arrAkadGrad = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
if (!this.student.length) {
this.$fhcApi.factory.stv.abschlusspruefung.getTypStudiengang(this.student.studiengang_kz)
.then(result => {
this.stgTyp = result.data;
this.setDefaultFormData();
})
.catch(this.$fhcAlert.handleSystemError);
} else
this.getStudiengangsTyp();
},
template: `
<div class="stv-details-abschlusspruefung h-100 pb-3">
<h4>{{this.$p.t('stv','tab_finalexam')}}</h4>
<div v-if="this.student.length">
<AbschlusspruefungDropdown
:showAllFormats="isBerechtigtDocAndOdt"
:studentUids="studentUids"
:showDropDownMulti="true"
:stgTyp="stgTyp"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></AbschlusspruefungDropdown>
</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>
<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('lehre', '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="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"
>
<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>
<div class="text-end mb-3">
<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>
</div>
</form-form>
<Teleport v-for="data in tabulatorData" :key="data.abschlusspruefung_id" :to="data.actionDiv">
<AbschlusspruefungDropdown
:showAllFormats="isBerechtigtDocAndOdt"
:showDropDownMulti="false"
:abschlusspruefung_id="data.abschlusspruefung_id"
:studentUids="data.student_uid"
:stgPrfgTyp="data.pruefungstyp_kurzbz"
:stgKz="stg_kz"
:cisRoot="cisRoot"
@linkGenerated="printDocument"
></AbschlusspruefungDropdown>
</Teleport>
</div>
`
}
@@ -0,0 +1,199 @@
export default {
inject: {
$reloadList: {
from: '$reloadList',
required: true
},
config: {
from: 'config',
required: true
},
},
emits: [
'reloadTable'
],
props: {
studentUids: {
type: Array,
required: true,
default: () => []
},
showDropDownMulti: {
type: Boolean,
required: true
},
stgTyp: {
type: String,
required: true
},
cisRoot: {
type: String,
required: true
},
stgKz: {
type: Number,
required: true
},
abschlusspruefung_id: {
type: Number,
required: true
},
stgPrfgTyp: {
type: String,
required: true
},
showAllFormats: {
type: Boolean,
required: true
}
},
data() {
return {
documentCategories: [
{ key: "pruefungsprotokoll", label: "Prüfungsprotokoll" },
{ key: "pruefungszeugnis", label: "Prüfungszeugnis" },
{ key: "urkunde", label: "Urkunde" },
],
languages: [
{ key: "de", label: "Deutsch" },
{ key: "en", label: "Englisch" },
],
formats:[
{ key: "pdf", label: "PDF" },
{ key: "odt", label: "ODT" },
{ key: "doc", label: "DOC" },
],
data: {}
};
},
methods: {
getLabel(documentKey) {
const labels = {
pruefungsprotokoll: "Prüfungsprotokoll",
pruefungszeugnis: "Prüfungszeugnis",
urkunde: "Urkunde",
};
return labels[documentKey] || documentKey;
},
checkUidsIfExistingFinalExams(uids) {
return this.$fhcApi.factory.stv.abschlusspruefung.checkForExistingExams(uids)
.catch(this.$fhcAlert.handleSystemError);
},
printDocument(document, lang, format) {
let xsl = '';
if (this.stgPrfgTyp == 'Bachelor' || this.stgTyp == 'b')
xsl = this.config.documents?.[document]?.[lang]?.Bakk;
else if (this.stgPrfgTyp == 'Diplom' || this.stgTyp == 'm')
xsl = this.config.documents?.[document]?.[lang]?.Master;
if(!format)
format = 'pdf';
let output= this.showAllFormats ? format : 'pdf';
this.checkUidsIfExistingFinalExams(this.studentUids);
let uids = "";
uids = !Array.isArray(this.studentUids) ? this.studentUids : this.studentUids.join(";");
let linkToPdf = this.showDropDownMulti
? this.cisRoot +
'content/pdfExport.php?xml=abschlusspruefung.rdf.php&xsl=' + xsl + '&uid=' + uids + '&xsl_stg_kz=' + this.stgKz + '&output=' + output
: this.cisRoot +
'content/pdfExport.php?xml=abschlusspruefung.rdf.php&xsl=' + xsl + '&abschlusspruefung_id=' + this.abschlusspruefung_id + '&uid=' + uids + '&xsl_stg_kz=' + this.stgKz + '&output=' + output;
this.$emit('linkGenerated', linkToPdf);
}
},
template: `
<div class="stv-abschlusspruefung-dropdown">
<div class="action-print-dropdown" ref="dropDown">
<div class="btn-group">
<button
v-if="!showDropDownMulti"
ref="toolbarButton"
type="button"
class="btn btn-secondary dropdown-toggle"
data-bs-toggle="dropdown"
data-bs-auto-close="outside"
aria-expanded="false"
@[\`show.bs.dropdown\`]="event => { if (event.target.closest('.tabulator-row')) event.target.closest('.tabulator-row').style.zIndex = 12 }"
@[\`hidden.bs.dropdown\`]="event => { if (event.target.closest('.tabulator-row')) event.target.closest('.tabulator-row').style.zIndex = '' }"
>
{{this.$p.t('tools','dokumente')}}
</button>
<button
v-else
ref="toolbarButton"
type="button"
class="btn btn-secondary dropdown-toggle"
data-bs-toggle="dropdown"
data-bs-auto-close="outside"
aria-expanded="false"
>
{{this.$p.t('tools','dokumente')}}
</button>
<!-- Version with permission to download as odt and doc, 2 levels-->
<ul v-if="showAllFormats" class="dropdown-menu dropdown-menu-right">
<template v-for="(documents, documentKey) in config.documents" :key="documentKey">
<div v-if="documents" class="dropend">
<!-- 1st level: documents and language -->
<div v-for="language in languages" :key="documentKey.key + '-' + language.key">
<a
class="dropdown-item dropdown-toggle d-flex justify-content-between align-items-center"
href="#"
aria-expanded="false"
data-bs-toggle="dropdown"
>
{{ getLabel(documentKey) }} {{ language.label }}
</a>
<!-- 2nd level: formats -->
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="format in formats" :key="format.key">
<a
class="dropdown-item"
href="#"
@click="printDocument(documentKey, language.key, format.key)"
>
{{format.label}}
</a>
</li>
</ul>
</div>
</div>
</template>
</ul>
<!-- Version without permissions, 2 levels-->
<ul v-else class="dropdown-menu dropdown-menu-right">
<template v-for="(documents, documentKey) in config.documents" :key="documentKey">
<div v-if="documents" class="dropend">
<a
class="dropdown-item dropdown-toggle d-flex justify-content-between align-items-center"
data-bs-toggle="dropdown"
aria-expanded="false"
href="#"
>
{{ getLabel(documentKey) }}
</a>
<ul class="dropdown-menu dropdown-menu-right">
<li v-for="(lang) in languages">
<a
class="dropdown-item"
@click="printDocument(documentKey, lang.key)"
href="#"
>
{{lang.label}}
</a>
</li>
</ul>
</div>
</template>
</ul>
</div>
</div>
</div>`
};
@@ -284,6 +284,8 @@ export default{
},
template: `
<div class="stv-details-kontakt-contact h-100 pt-3">
{{contactData}}
<!--Modal: contactModal-->
<BsModal ref="contactModal">
+282
View File
@@ -37660,6 +37660,288 @@ array(
)
),
// CIS4 phrases from legacy code end
// FHC4 Phrases Abschlusspruefung
array(
'app' => 'core',
'category' => 'stv',
'phrase' => 'tab_finalexam',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Abschlussprüfung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Final exam',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'abschlussbeurteilung',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Abschlussbeurteilung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Final assessment',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'pruefer1',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'PrüferIn 1',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'examiner 1',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'pruefer2',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'PrüferIn 2',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'examiner 2',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'pruefer3',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'PrüferIn 3',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'examiner 3',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'global',
'phrase' => 'uhrzeit',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Uhrzeit',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'time',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'freigabe',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Freigabe',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Approval',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'sponsion',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Sponsion',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Graduation',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'abschlusspruefung_id',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Abschlusspruefung ID',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Final Examination ID',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'ui',
'phrase' => 'loeschen',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Löschen',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Delete',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'vorsitz_header',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Vorsitz',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Chair',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'zurBeurteilung',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Zur Beurteilung',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'To the assessment',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'akadGrad',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Akademischer Grad',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Academic degree',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'abschlusspruefung',
'phrase' => 'error_studentOhneFinalExam',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Keine Abschlussprüfungen für Student_uid(s) {id} gefunden',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No final exams found for Student_uid(s) {id}',
'description' => '',
'insertvon' => 'system'
)
)
),
// FHC4 Phrases Abschlusspruefung End
array(
'app' => 'core',
'category' => 'gruppenmanagement',