diff --git a/application/controllers/api/frontend/v1/stv/Config.php b/application/controllers/api/frontend/v1/stv/Config.php
index ac1e132fb..bcea93fb5 100644
--- a/application/controllers/api/frontend/v1/stv/Config.php
+++ b/application/controllers/api/frontend/v1/stv/Config.php
@@ -83,6 +83,10 @@ class Config extends FHCAPI_Controller
'title' => 'Status',
'component' => './Stv/Studentenverwaltung/Details/MultiStatus.js'
];
+ $result['documents'] = [
+ 'title' => $this->p->t('stv', 'tab_dokumente'),
+ 'component' => './Stv/Studentenverwaltung/Details/Dokumente.js'
+ ];
$result['banking'] = [
'title' => $this->p->t('stv', 'tab_banking'),
'component' => './Stv/Studentenverwaltung/Details/Konto.js',
diff --git a/application/controllers/api/frontend/v1/stv/Dokumente.php b/application/controllers/api/frontend/v1/stv/Dokumente.php
new file mode 100644
index 000000000..2923f7204
--- /dev/null
+++ b/application/controllers/api/frontend/v1/stv/Dokumente.php
@@ -0,0 +1,553 @@
+ ['admin:r', 'assistenz:r'],
+ 'getDocumentsAccepted' => ['admin:r', 'assistenz:r'],
+ 'deleteZuordnung' => ['admin:rw', 'assistenz:rw'],
+ 'createZuordnung' => ['admin:rw', 'assistenz:rw'],
+ 'loadAkte' => ['admin:rw', 'assistenz:rw'],
+ 'deleteAkte' => ['admin:rw', 'assistenz:rw'],
+ 'updateAkte' => ['admin:rw', 'assistenz:rw'],
+ 'getDoktypen' => ['admin:r', 'assistenz:r'],
+ 'uploadDokument' => ['admin:rw', 'assistenz:rw'],
+ 'download' => ['admin:rw', 'assistenz:rw'],
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('form_validation');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui',
+ 'dokumente'
+ ]);
+
+ // Load models
+ $this->load->model('crm/Akte_model', 'AkteModel');
+ $this->load->model('crm/Dokument_model', 'DokumentModel');
+ $this->load->model('crm/Dokumentprestudent_model', 'DokumentprestudentModel');
+
+ //TODO(Manu) check additional Berechtigungen
+ //TODO(Manu) check if using dokument lib instead of dokument model?
+ }
+
+ public function getDocumentsUnaccepted($prestudent_id, $studiengang_kz)
+ {
+ if(!$prestudent_id)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if (!is_numeric($prestudent_id))
+ $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if(!$studiengang_kz)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL);
+
+ $person_id = $this->_getPersonId($prestudent_id);
+ $result = $this->DokumentModel->getUnacceptedDocuments($prestudent_id, $person_id);
+
+ $dataAkteUnaccepted = $this->getDataOrTerminateWithError($result);
+ $resultMd = $this->_getMissingDocuments($studiengang_kz, $prestudent_id);
+
+ $data = $this->_mergeDocuments($dataAkteUnaccepted, $resultMd);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getDocumentsAccepted($prestudent_id, $studiengang_kz)
+ {
+ if(!$prestudent_id)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if (!is_numeric($prestudent_id))
+ $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if(!$studiengang_kz)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL);
+
+ $resultPreDoc = $this->_getPrestudentDokumente($prestudent_id);
+
+ $arrayAccepted = [];
+ $person_id = $this->_getPersonId($prestudent_id);
+
+ $docNames = array_map(function ($item) {
+ return $item->dokument_kurzbz;
+ }, $resultPreDoc);
+
+ foreach($docNames as $doc)
+ {
+ $result = $this->AkteModel->getAktenFAS($person_id, $doc, $studiengang_kz, $prestudent_id, true);
+
+ if (isError($result))
+ {
+ return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
+ }
+ if (hasData($result))
+ {
+ $data = getData($result);
+ array_push($arrayAccepted, current($data));
+ }
+ }
+
+ //Merge with Data of Akte
+ $newDataMap = [];
+ //helper, lookupArray
+ foreach ($arrayAccepted as $item) {
+ $newDataMap[$item->dokument_kurzbz] = $item;
+ }
+
+ //add Data of Akte to PrestudentData
+ foreach ($resultPreDoc as $obj) {
+ if (isset($newDataMap[$obj->dokument_kurzbz])) {
+ $obj->akte_id = $newDataMap[$obj->dokument_kurzbz]->akte_id;
+ $obj->hochgeladenamum = $newDataMap[$obj->dokument_kurzbz]->hochgeladenamum;
+ $obj->titel_intern = $newDataMap[$obj->dokument_kurzbz]->titel_intern;
+ $obj->nachgereicht = $newDataMap[$obj->dokument_kurzbz]->nachgereicht;
+ $obj->akzeptiertamum = $newDataMap[$obj->dokument_kurzbz]->akzeptiertamum;
+ $obj->dms_id = $newDataMap[$obj->dokument_kurzbz]->dms_id;
+ $obj->infotext = $newDataMap[$obj->dokument_kurzbz]->infotext;
+ $obj->anmerkung_intern = $newDataMap[$obj->dokument_kurzbz]->anmerkung_intern;
+ $obj->nachgereicht_am = $newDataMap[$obj->dokument_kurzbz]->nachgereicht_am;
+ $obj->vorhanden = $newDataMap[$obj->dokument_kurzbz]->vorhanden;
+ }
+ }
+ $this->terminateWithSuccess($resultPreDoc);
+ }
+
+ public function deleteZuordnung($prestudent_id, $dokument_kurzbz)
+ {
+ if(!$prestudent_id)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if (!is_numeric($prestudent_id))
+ $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if(!$dokument_kurzbz)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Dokument_kurzbz']), self::ERROR_TYPE_GENERAL);
+
+ $result = $this->DokumentprestudentModel->delete(
+ [
+ 'prestudent_id' => $prestudent_id,
+ 'dokument_kurzbz' => $dokument_kurzbz
+ ]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function loadAkte($akte_id)
+ {
+ if (!$akte_id)
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL);
+
+ $this->AkteModel->addSelect('public.tbl_akte.*');
+ $this->AkteModel->addSelect("CONCAT(public.tbl_person.vorname, ' ' , public.tbl_person.nachname) AS namePerson");
+ $this->AkteModel->addJoin('public.tbl_person', 'person_id');
+ $result = $this->AkteModel->loadWhere(
+ [
+ 'akte_id' => $akte_id,
+ ]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+ $data = current($data);
+ $this->terminateWithSuccess($data);
+ }
+
+ public function updateAkte()
+ {
+ $this->form_validation->set_rules('akte_id', 'Akte ID', 'required', [
+ 'required' => $this->p->t('dokumente', 'err_updateNotAllowed')
+ ]);
+
+ $this->form_validation->set_rules('dokument_kurzbz', 'Dokumenttyp', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Dokumenttyp'])
+ ]);
+
+ $this->form_validation->set_rules('nachreichung_am', 'Nachreichung am', 'is_valid_date', [
+ 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'Nachreichung am'])
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $uid = getAuthUID();
+
+ $result = $this->AkteModel->update(
+ [
+ 'akte_id' => $this->input->post('akte_id'),
+ ],
+ [
+ 'dokument_kurzbz' => $this->input->post('dokument_kurzbz'),
+ 'anmerkung_intern' => $this->input->post('anmerkung_intern'),
+ 'titel_intern' => $this->input->post('titel_intern'),
+ 'nachgereicht_am' => $this->input->post('nachgereicht_am'),
+ 'updateamum' => date('c'),
+ 'updatevon' => $uid,
+ ]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess(current($data));
+ }
+
+ public function createZuordnung($prestudent_id, $dokument_kurzbz)
+ {
+ if (!$prestudent_id)
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Prestudent ID']), self::ERROR_TYPE_GENERAL);
+
+ if(!$dokument_kurzbz)
+ $this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Dokument_kurzbz']), self::ERROR_TYPE_GENERAL);
+
+ $uid = getAuthUid();
+
+ $result = $this->DokumentprestudentModel->insert(
+ [
+ 'prestudent_id' => $prestudent_id,
+ 'dokument_kurzbz' => $dokument_kurzbz,
+ 'mitarbeiter_uid' => $uid,
+ 'datum' => date('c'),
+ 'insertamum' => date('c'),
+ 'insertvon' => $uid,
+ ]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function deleteAkte($akte_id)
+ {
+ if (!$akte_id)
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL);
+
+ $result = $this->AkteModel->load($akte_id);
+ $dataAkte = $this->getDataOrTerminateWithError($result);
+
+ $logdata_akte = var_export($dataAkte, true);
+
+ $dms_id = current($dataAkte)->dms_id;
+ $nachgereicht = current($dataAkte)->nachgereicht;
+ $inhalt = current($dataAkte)->inhalt;
+ $inhaltVorhanden = $inhalt != '';
+ $uid = getAuthUid();
+
+ $this->db->trans_start();
+
+ if($dms_id)
+ {
+ $this->load->model('content/Dms_model', 'DmsModel');
+ $result = $this->DmsModel->load($dms_id);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $logdata_dms = (array)$data;
+ $logdata_dms = "Logdata: " . var_export($logdata_dms, true);
+
+ //delete from dmsLib
+ $this->load->library('DmsLib');
+ $person_id = current($dataAkte)->person_id;
+ $result = $this->dmslib->delete($person_id, $dms_id);
+ $this->getDataOrTerminateWithError($result);
+
+ //LOGGING Dms ID
+ $this->load->model('system/Log_model', 'LogModel');
+ $result = $this->LogModel->insert([
+ 'executetime' => date('c'),
+ 'mitarbeiter_uid' => $uid,
+ 'beschreibung' => "Löschen der DMS_ID ". $dms_id,
+ 'sql' => $logdata_dms
+ ]);
+ $this->getDataOrTerminateWithError($result);
+
+ //delete akte
+ $result = $this->AkteModel->delete(
+ [
+ 'akte_id' => $akte_id
+ ]
+ );
+ $data = $this->getDataOrTerminateWithError($result);
+
+ //Logging Deletion Akte
+ $result = $this->LogModel->insert([
+ 'executetime' => date('c'),
+ 'mitarbeiter_uid' => $uid,
+ 'beschreibung' => "Löschen der Akte ". $akte_id,
+ 'sql' => "DELETE FROM public.tbl_akte WHERE akte_id=" .$akte_id. " LogData: ". $logdata_akte
+ ]);
+ $this->getDataOrTerminateWithError($result);
+ $this->db->trans_complete();
+ $this->terminateWithSuccess($data);
+ }
+ elseif (!!$dms_id || ($nachgereicht && !$inhaltVorhanden))
+ {
+ $result = $this->AkteModel->delete(
+ [
+ 'akte_id' => $akte_id
+ ]
+ );
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $result = $this->LogModel->insert([
+ 'executetime' => date('c'),
+ 'mitarbeiter_uid' => $uid,
+ 'beschreibung' => "Löschen der Akte ". $akte_id,
+ 'sql' => "DELETE FROM public.tbl_akte WHERE akte_id=" .$akte_id. " LogData: ". $logdata_akte
+ ]);
+ $this->getDataOrTerminateWithError($result);
+
+ $this->db->trans_complete();
+ $this->terminateWithSuccess($data);
+ }
+ else
+ $this->terminateWithError($this->p->t('dokumente', 'err_deleteDokHere'), self::ERROR_TYPE_GENERAL);
+ }
+
+ public function uploadDokument()
+ {
+ $this->load->library('DmsLib');
+ $prestudent_id = $this->input->post('prestudent_id');
+ $anmerkung_intern = $this->input->post('anmerkung_intern');
+ $titel_intern = $this->input->post('titel_intern');
+ $dokument_kurzbz = $this->input->post('dokument_kurzbz');
+
+ $this->form_validation->set_rules('prestudent_id', 'Prestudent_id', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Prestudent ID'])
+ ]);
+
+ $this->form_validation->set_rules('dokument_kurzbz', 'Dokumenttyp', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Dokumenttyp'])
+ ]);
+
+ //validation if attachment was added
+ $this->form_validation->set_rules('anhang', 'Attachment', 'callback_file_check');
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $this->db->trans_start();
+ $uid = getAuthUID();
+
+ $dms = array(
+ 'kategorie_kurzbz' => 'Akte',
+ 'version' => 0,
+ 'name' => $_FILES['anhang']['name'],
+ 'mimetype' => $_FILES['anhang']['type'],
+ 'insertamum' => date('c'),
+ 'insertvon' => $uid
+ );
+
+ $result = $this->dmslib->upload($dms, 'anhang', array("jpg", "png", "pdf"));
+
+ if (isError($result))
+ {
+ return $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $dms_id = $result->retval['dms_id'];
+
+ $person_id = $this->_getPersonId($prestudent_id);
+
+ $result = $this->DokumentModel->load($dokument_kurzbz);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $bezeichnung = current($data)->bezeichnung;
+
+ //save entry in akte
+ if($dms_id)
+ {
+ $result = $this->AkteModel->insert([
+ 'person_id' => $person_id,
+ 'dms_id' => $dms_id,
+ 'dokument_kurzbz' => $dokument_kurzbz,
+ 'mimetype' => $_FILES['anhang']['type'],
+ 'insertamum' => date('c'),
+ 'erstelltam' => date('c'),
+ 'insertvon' => $uid,
+ 'anmerkung_intern' => $anmerkung_intern,
+ 'titel_intern' => $titel_intern,
+ 'bezeichnung' => $bezeichnung,
+ 'titel' => $_FILES['anhang']['name']
+ ]);
+
+ $data = $this->getDataOrTerminateWithError($result);
+ $this->db->trans_complete();
+ $this->terminateWithSuccess($data);
+ }
+ $this->db->trans_complete();
+ $this->terminateWithSuccess($data);
+ }
+
+ public function getDoktypen()
+ {
+ $this->DokumentModel->addSelect('dokument_kurzbz');
+ $this->DokumentModel->addSelect('bezeichnung');
+ $this->DokumentModel->addOrder('dokument_kurzbz', 'ASC');
+ $result = $this->DokumentModel->load();
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function download()
+ {
+ //TODO(Manu) check filetype, Decoding
+ $akte_id = $this->input->get('akte_id');
+
+ if(!$akte_id)
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Akte ID']), self::ERROR_TYPE_GENERAL);
+
+ if (!is_numeric($akte_id))
+ $this->terminateWithError($this->p->t('ui', 'error_valueNotNumeric', ['value' => 'Akte ID']), self::ERROR_TYPE_GENERAL);
+
+
+ $result = $this->AkteModel->load($akte_id);
+
+ if (!hasData($result)) $this->terminateWithError('Akte not found');
+
+ $data = getData($result)[0];
+
+ header('Content-Description: File Transfer');
+ header('Content-Type: '. $data->mimetype);
+ header('Content-Disposition: attachment; filename="'.$data->titel.'"');
+ header('Expires: 0');
+ header('Cache-Control: must-revalidate');
+ header('Pragma: public');
+ if (isset($data->inhalt) && !empty($data->inhalt)) {
+ $decodedContent = base64_decode($data->inhalt, true);
+
+ if ($decodedContent === false) {
+ die('Error: Base64-Dekodierung failed.');
+ }
+ echo $decodedContent;
+ }
+ die();
+ }
+
+ private function _getMissingDocuments($studiengang_kz, $prestudent_id)
+ {
+ $result = $this->DokumentModel->getMissingDocuments($studiengang_kz, $prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $data;
+ }
+
+ private function _getUnacceptedDocuments($prestudent_id)
+ {
+ $person_id = $this->_getPersonId($prestudent_id);
+ $result = $this->DokumentModel->getUnacceptedDocuments($prestudent_id, $person_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $data;
+ }
+
+ /**
+ * helper function for merging objects
+ * sorts object after merging according to dokument_kurzbz
+ * @param $original object of documents of akte
+ * @param object $toMerge documents to merge (of dokumentprestudent, dokumentstudiengang)
+ * @return Array mergedObject
+ */
+ private function _mergeDocuments($original, $toMerge)
+ {
+ $existingKurzbez = [];
+ foreach ($original as $doc) {
+ $existingKurzbez[$doc->dokument_kurzbz] = true;
+ }
+
+ foreach ($toMerge as $doc) {
+ if (!isset($existingKurzbez[$doc->dokument_kurzbz])) {
+ $original[] = $doc;
+ $existingKurzbez[$doc->dokument_kurzbz] = true;
+ }
+ else
+ {
+ foreach($original as $docOriginal)
+ {
+ if ($docOriginal->dokument_kurzbz == $doc->dokument_kurzbz)
+ {
+ $docOriginal->pflicht = $doc->pflicht;
+ $docOriginal->onlinebewerbung = $doc->onlinebewerbung;
+ }
+ }
+ }
+ }
+
+ usort($original, function ($a, $b) {
+ return strcmp($a->dokument_kurzbz, $b->dokument_kurzbz);
+ });
+
+ return $original;
+ }
+
+ private function _getDocumentsOfAkte($person_id)
+ {
+ $result = $this->AkteModel->getAktenFAS($person_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $data;
+ }
+
+ private function _getPrestudentDokumente($prestudent_id)
+ {
+ $result = $this->DokumentprestudentModel->getPrestudentDokumente($prestudent_id);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ return $data;
+ }
+
+ private function _getPersonId($prestudent_id)
+ {
+ $this->load->model('crm/Prestudent_model', 'PrestudentModel');
+ $result = $this->PrestudentModel->loadWhere(
+ ['prestudent_id' => $prestudent_id]
+ );
+
+ $data = $this->getDataOrTerminateWithError($result);
+ $person = current($data);
+
+ return $person->person_id;
+ }
+
+ public function file_check($str)
+ {
+ if (isset($_FILES['anhang']) && $_FILES['anhang']['size'] > 0)
+ {
+ $allowed_mime_types = ['image/jpeg', 'image/png', 'application/pdf'];
+ $mime = mime_content_type($_FILES['anhang']['tmp_name']);
+
+ if (in_array($mime, $allowed_mime_types))
+ {
+ return true;
+ } else
+ {
+ $this->form_validation->set_message('file_check', $this->p->t('dokumente', 'error_fileType'));
+ return false;
+ }
+ }
+ else
+ {
+ $this->form_validation->set_message('file_check', $this->p->t('dokumente', 'error_fileMissing'));
+ return false;
+ }
+ }
+}
diff --git a/application/models/crm/Akte_model.php b/application/models/crm/Akte_model.php
index 2fa69d5b0..601019d3a 100644
--- a/application/models/crm/Akte_model.php
+++ b/application/models/crm/Akte_model.php
@@ -92,7 +92,7 @@ class Akte_model extends DB_Model
a.anmerkung,
a.nachgereicht,
a.nachgereicht_am,
- CASE WHEN MAX(dp.dokument_kurzbz) IS NOT NULL THEN TRUE ELSE FALSE END AS accepted
+ CASE WHEN MAX(dp.dokument_kurzbz) IS NOT NULL THEN TRUE ELSE FALSE END AS accepted,
FROM public.tbl_akte a
INNER JOIN public.tbl_prestudent p USING(person_id)
LEFT JOIN public.tbl_dokumentprestudent dp USING(prestudent_id, dokument_kurzbz)
@@ -111,6 +111,61 @@ class Akte_model extends DB_Model
return $this->execQuery($query, $parametersArray);
}
+ /**
+ * getAktenAccepted FAS
+ */
+ public function getAktenFAS($person_id, $dokument_kurzbz = null, $stg_kz = null, $prestudent_id = null, $returnInhalt = false)
+ {
+ $query = 'SELECT
+ a.akte_id,
+ a.bezeichnung,
+ a.dokument_kurzbz,
+ a.titel_intern,
+ a.anmerkung_intern,
+ a.insertamum as hochgeladenamum,
+ a.updatevon, a.insertvon, a.uid,
+ a.dms_id, a.anmerkung as infotext,
+ a.nachgereicht,
+ CASE
+ WHEN inhalt IS NOT NULL OR a.dms_id IS NOT NULL
+ THEN true
+ ELSE false
+ END AS vorhanden,
+ a.nachgereicht_am,
+ ausstellungsnation, formal_geprueft_amum, archiv,
+ signiert, stud_selfservice, akzeptiertamum, inhalt
+ FROM public.tbl_akte a
+ WHERE a.person_id = ?';
+
+ $parametersArray = array($person_id);
+
+ if (!isEmptyString($dokument_kurzbz))
+ {
+ $query .= " AND dokument_kurzbz = ?
+ AND dokument_kurzbz NOT IN ('Zeugnis','DiplSupp','Bescheid')";
+ array_push($parametersArray, $dokument_kurzbz);
+ }
+
+ if($stg_kz != null && $prestudent_id != null)
+ {
+ $query.= " AND dokument_kurzbz not in (
+ SELECT dokument_kurzbz
+ FROM public.tbl_dokument
+ JOIN public.tbl_dokumentstudiengang USING(dokument_kurzbz)
+ WHERE studiengang_kz= ?
+ AND dokument_kurzbz NOT IN(
+ SELECT dokument_kurzbz FROM public.tbl_dokumentprestudent
+ JOIN public.tbl_dokument USING(dokument_kurzbz)
+ WHERE prestudent_id=?))";
+ array_push($parametersArray, $stg_kz);
+ array_push($parametersArray, $prestudent_id);
+ }
+
+ $query .= ' ORDER BY erstelltam';
+
+ return $this->execQuery($query, $parametersArray);
+ }
+
/**
* getAktenAcceptedDms
*/
diff --git a/application/models/crm/Dokument_model.php b/application/models/crm/Dokument_model.php
index 7ef2be716..8008202c1 100644
--- a/application/models/crm/Dokument_model.php
+++ b/application/models/crm/Dokument_model.php
@@ -11,4 +11,91 @@ class Dokument_model extends DB_Model
$this->dbTable = 'public.tbl_dokument';
$this->pk = 'dokument_kurzbz';
}
+
+ /**
+ * Loads all missing Documents of a Studiengang
+ * a Prestudent has not submitted
+ * @param integer studiengang_kz
+ * @param integer prestudent_id
+ * @param boolean archivdokumente
+ * Default: true.
+ * If false, documents that are archivable (tbl_vorlage.archivierbar e.g. certificate, notice, ...) not retrieved
+ * @return Array of Documents || error
+ */
+ public function getMissingDocuments($studiengang_kz, $prestudent_id = null, $archivdokumente = false, $person_id = null)
+ {
+ $parametersArray = array($studiengang_kz);
+
+ $qry = "SELECT
+ tbl_dokument.* ,
+ tbl_dokumentstudiengang.*
+ FROM public.tbl_dokument
+ JOIN public.tbl_dokumentstudiengang USING(dokument_kurzbz)
+ LEFT JOIN public.tbl_vorlage ON (tbl_dokument.dokument_kurzbz = tbl_vorlage.vorlage_kurzbz)
+ WHERE studiengang_kz = ? ";
+
+ if($prestudent_id)
+ {
+ array_push($parametersArray, $prestudent_id);
+ $qry.=" AND tbl_dokument.dokument_kurzbz NOT IN (
+ SELECT dokument_kurzbz FROM public.tbl_dokumentprestudent WHERE prestudent_id= ?)";
+ }
+
+ if(!$archivdokumente)
+ {
+ $qry.=" AND (tbl_vorlage.archivierbar = FALSE OR tbl_vorlage.archivierbar IS NULL)";
+ }
+
+ $qry.=" ORDER BY tbl_dokument.dokument_kurzbz;";
+
+ return $this->execQuery($qry, $parametersArray);
+ }
+
+ public function getUnacceptedDocuments($prestudent_id, $person_id)
+ {
+ $parametersArray = array($person_id, $prestudent_id);
+
+ $qry = " SELECT
+ a.akte_id,
+ a.bezeichnung,
+ a.dokument_kurzbz,
+ a.titel_intern,
+ a.anmerkung_intern,
+ a.insertamum as hochgeladenamum,
+ a.updatevon,
+ a.insertvon,
+ a.uid,
+ a.dms_id,
+ a.anmerkung as infotext,
+ a.nachgereicht,
+ CASE
+ WHEN inhalt IS NOT NULL
+ OR a.dms_id IS NOT NULL THEN true
+ ELSE false
+ END AS vorhanden,
+ a.nachgereicht_am,
+ ausstellungsnation,
+ formal_geprueft_amum,
+ archiv,
+ signiert,
+ stud_selfservice,
+ akzeptiertamum,
+ inhalt
+ FROM
+ public.tbl_akte a
+ WHERE
+ a.person_id = ?
+ AND a.dokument_kurzbz NOT IN (
+ SELECT
+ dokument_kurzbz
+ FROM
+ public.tbl_dokumentprestudent
+ WHERE
+ prestudent_id = ?
+ )
+ AND a.dokument_kurzbz NOT IN ('Zeugnis','DiplSupp','Bescheid')
+ ORDER BY a.dokument_kurzbz;";
+
+ return $this->execQuery($qry, $parametersArray);
+ }
}
diff --git a/application/models/crm/Dokumentprestudent_model.php b/application/models/crm/Dokumentprestudent_model.php
index 0a6669359..2415ee483 100644
--- a/application/models/crm/Dokumentprestudent_model.php
+++ b/application/models/crm/Dokumentprestudent_model.php
@@ -69,4 +69,39 @@ class Dokumentprestudent_model extends DB_Model
return $result;
}
+
+ /**
+ * Loads all Documents of Prestudent, already submitted
+ * @param integer prestudent_id
+ * @param boolean archivdokumente Default true. if false, archivable Documents (tbl_vorlage.archivierbar zB Zeugnis, Bescheid, ...) not retrieved
+ * @return Array of Documents || error
+ */
+ public function getPrestudentDokumente($prestudent_id, $archivdokumente = true)
+ {
+ $parametersArray = array($prestudent_id);
+
+ $qry = "SELECT
+ d.bezeichnung,
+ d.dokument_kurzbz,
+ dp.datum as Docdatum,
+ dp.mitarbeiter_uid as DocMitarbeiter_uid,
+ dp.insertamum as Docinsertamum,
+ dp.prestudent_id,
+ CONCAT(p.vorname, ' ', p.nachname) as insertvonma
+ FROM
+ public.tbl_dokumentprestudent dp
+ JOIN public.tbl_dokument d USING(dokument_kurzbz)
+ LEFT JOIN public.tbl_vorlage v ON (d.dokument_kurzbz = v.vorlage_kurzbz)
+ LEFT JOIN public.tbl_benutzer bn ON (bn.uid = dp.mitarbeiter_uid)
+ LEFT JOIN public.tbl_person p ON (p.person_id = bn.person_id)
+ WHERE
+ prestudent_id = ?";
+
+ if(!$archivdokumente)
+ {
+ $qry.=" AND (v.archivierbar = FALSE OR v.archivierbar IS NULL)";
+ }
+
+ return $this->execQuery($qry, $parametersArray);
+ }
}
diff --git a/public/js/api/factory/stv/documents.js b/public/js/api/factory/stv/documents.js
new file mode 100644
index 000000000..1898023cd
--- /dev/null
+++ b/public/js/api/factory/stv/documents.js
@@ -0,0 +1,76 @@
+/**
+ * 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 .
+ */
+
+export default {
+ getDocumentsUnaccepted(params) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/stv/dokumente/getDocumentsUnaccepted/' + params.id + '/' + params.studiengang_kz
+ };
+ },
+ getDocumentsAccepted(params) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/stv/dokumente/getDocumentsAccepted/' + params.id + '/' + params.studiengang_kz
+ };
+ },
+ deleteZuordnung(params){
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/dokumente/deleteZuordnung/' + params.prestudent_id + '/' + params.dokument_kurzbz
+ };
+ },
+ createZuordnung(params){
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/dokumente/createZuordnung/' + params.prestudent_id + '/' + params.dokument_kurzbz
+ };
+ },
+ loadAkte(akte_id){
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/stv/dokumente/loadAkte/' + akte_id
+ };
+ },
+ getDoktypen(){
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/stv/dokumente/getDoktypen/'
+ };
+ },
+ updateFile(akte_id, params){
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/dokumente/updateAkte/' + akte_id,
+ params
+ };
+ },
+ deleteFile(akte_id){
+ console.log("in deleteFile " + akte_id);
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/dokumente/deleteAkte/' + akte_id,
+ };
+ },
+ uploadFile(prestudent_id, params){
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/dokumente/uploadDokument/' + prestudent_id,
+ params
+ };
+ },
+}
\ No newline at end of file
diff --git a/public/js/api/stv.js b/public/js/api/stv.js
index 63e53f4fb..6120a5828 100644
--- a/public/js/api/stv.js
+++ b/public/js/api/stv.js
@@ -12,6 +12,7 @@ import abschlusspruefung from './stv/abschlusspruefung.js';
import grades from './stv/grades.js';
import mobility from './stv/mobility.js';
import archiv from './stv/archiv.js';
+import documents from './stv/documents.js';
export default {
verband,
@@ -28,6 +29,7 @@ export default {
grades,
mobility,
archiv,
+ documents,
configStudent() {
return this.$fhcApi.get('api/frontend/v1/stv/config/student');
},
diff --git a/public/js/api/stv/documents.js b/public/js/api/stv/documents.js
new file mode 100644
index 000000000..9934520fc
--- /dev/null
+++ b/public/js/api/stv/documents.js
@@ -0,0 +1,33 @@
+export default {
+ getDocumentsUnaccepted(url, config, params) {
+ return this.$fhcApi.get('api/frontend/v1/stv/dokumente/getDocumentsUnaccepted/' + params.id + '/' + params.studiengang_kz);
+ },
+ getDocumentsAccepted(url, config, params) {
+ return this.$fhcApi.get('api/frontend/v1/stv/dokumente/getDocumentsAccepted/' + params.id + '/' + params.studiengang_kz);
+ },
+ deleteZuordnung(params){
+ return this.$fhcApi.post('api/frontend/v1/stv/dokumente/deleteZuordnung/' + params.prestudent_id + '/' + params.dokument_kurzbz);
+ },
+ createZuordnung(params){
+ return this.$fhcApi.post('api/frontend/v1/stv/dokumente/createZuordnung/'
+ + params.prestudent_id + '/'
+ + params.dokument_kurzbz);
+ },
+ loadAkte(akte_id){
+ return this.$fhcApi.get('api/frontend/v1/stv/dokumente/loadAkte/' + akte_id);
+ },
+ getDoktypen(){
+ return this.$fhcApi.get('api/frontend/v1/stv/dokumente/getDoktypen/');
+ },
+ updateFile(akte_id, data){
+ return this.$fhcApi.post('api/frontend/v1/stv/dokumente/updateAkte/' + akte_id,
+ data);
+ },
+ deleteFile(akte_id){
+ return this.$fhcApi.post('api/frontend/v1/stv/dokumente/deleteAkte/' + akte_id);
+ },
+ uploadFile(prestudent_id, data){
+ return this.$fhcApi.post('api/frontend/v1/stv/dokumente/uploadDokument/' + prestudent_id,
+ data);
+ },
+}
\ No newline at end of file
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente.js
new file mode 100644
index 000000000..01ca2d373
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente.js
@@ -0,0 +1,18 @@
+import ViewDocuments from "./Dokumente/Dokumente.js";
+
+export default {
+ name:"TabDocuments",
+ components: {
+ ViewDocuments
+ },
+ props: {
+ modelValue: Object,
+ },
+ data(){
+ return {}
+ },
+ template: `
+
+
+
`
+};
\ No newline at end of file
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Dokumente.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Dokumente.js
new file mode 100644
index 000000000..be69ae70d
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Dokumente.js
@@ -0,0 +1,51 @@
+import DocumentsUnaccepted from './List/Unaccepted.js';
+import DocumentsAccepted from './List/Accepted.js';
+
+export default {
+ components: {
+ DocumentsUnaccepted,
+ DocumentsAccepted
+ },
+ props: {
+ student: Object
+ },
+ data(){
+ return {
+ listMissingDocuments: []
+ }
+ },
+ methods: {
+ reloadUnaccepted(){
+ this.$refs.tableUnaccepted.reload();
+ },
+ reloadAccepted(){
+ this.$refs.tableAccepted.reload();
+ },
+ },
+ template: `
+
+ `
+}
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Accepted.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Accepted.js
new file mode 100644
index 000000000..7790e12f8
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Accepted.js
@@ -0,0 +1,335 @@
+import {CoreFilterCmpt} from "../../../../../filter/Filter.js";
+import ModalEdit from "../Modal/Edit.js";
+import ModalUpload from "../Modal/Upload.js";
+
+import ApiStvDocuments from "../../../../../../api/factory/stv/documents.js";
+
+export default {
+ components: {
+ name: "AcceptedDocuments",
+ CoreFilterCmpt,
+ ModalEdit,
+ ModalUpload
+ },
+ props: {
+ prestudent_id: Number,
+ studiengang_kz: Number
+ },
+ data(){
+ return {
+ tabulatorOptions: {
+ ajaxURL: 'dummy',
+ ajaxRequestFunc: () => this.$api.call(
+ ApiStvDocuments.getDocumentsAccepted({
+ id: this.prestudent_id,
+ studiengang_kz: this.studiengang_kz})
+ ),
+ ajaxResponse: (url, params, response) => {
+ return response.data;
+ },
+ columns: [
+ {title: "Dokument", field: "bezeichnung"},
+ {title: "Akzeptiertdatum", field: "docdatum",
+ 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: "Akzeptiertvon", field: "insertvonma"},
+ {
+ title: "UploadDatum", field: "hochgeladenamum",
+ 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: "Kurzbz", field: "dokument_kurzbz", visible: false},
+ {title: "Prestudent ID", field: "prestudent_id", visible: false},
+ {title: "nachgereicht", field: "nachgereicht", visible: false,
+ formatter:"tickCross",
+ hozAlign:"center",
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ }},
+ {title: "infotext", field: "infotext"},
+ {title: "akte_id", field: "akte_id"},
+ {title: "dms_id", field: "dms_id", visible: false},
+ {title: "titel", field: "titel_intern"},
+ {title: "vorhanden", field: "vorhanden",
+ formatter:"tickCross",
+ hozAlign:"center",
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ }},
+ {title: "Anmerkung_intern", field: "anmerkung_intern", visible: false},
+ {title: "Nachreichung am", field: "nachgereicht_am",
+ 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: 'Aktionen', field: 'actions',
+ minWidth: 50,
+ maxWidth: 100,
+ formatter: (cell, formatterParams, onRendered) => {
+
+ let container = document.createElement('div');
+ container.className = "d-flex gap-2";
+
+ if(cell.getData().vorhanden){
+ let button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'downloadDok');
+ button.addEventListener('click', (event) =>
+ this.actionDownloadFile(cell.getData().akte_id)
+ );
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'editDokument');
+ button.addEventListener('click', (event) =>
+ this.actionEditDocument(cell.getData().akte_id)
+ );
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'deleteDokument');
+ button.addEventListener('click', () =>
+ this.actionDeleteFile(cell.getData().akte_id)
+ );
+ container.append(button);
+ }
+ else
+ {
+ let button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'uploadDokument');
+ button.addEventListener('click', () =>
+ this.actionUploadFile(cell.getData().dokument_kurzbz)
+ );
+ container.append(button);
+ }
+
+
+ return container;
+ },
+ frozen: true
+ },
+ ],
+ layout: 'fitColumns',
+ layoutColumnsOnNewData: false,
+ height: 300,
+ selectable: true,
+ selectableRangeMode: 'click',
+ persistenceID: 'core-details-documents-accepted',
+ listDocuments: [],
+ },
+ tabulatorEvents: [
+ {
+ event: 'tableBuilt',
+ handler: async () => {
+ await this.$p.loadCategory(['global', 'dokumente', 'ui', 'mobility', 'ampeln']);
+
+ let cm = this.$refs.table.tabulator.columnManager;
+
+ cm.getColumnByField('bezeichnung').component.updateDefinition({
+ title: this.$p.t('global', 'dokument')
+ });
+ cm.getColumnByField('docdatum').component.updateDefinition({
+ title: this.$p.t('dokumente', 'datumAkzeptiert')
+ });
+ cm.getColumnByField('dokument_kurzbz').component.updateDefinition({
+ title: this.$p.t('mobility', 'kurzbz')
+ });
+ cm.getColumnByField('insertvonma').component.updateDefinition({
+ title: this.$p.t('global', 'uploaddatum')
+ });
+ cm.getColumnByField('hochgeladenamum').component.updateDefinition({
+ title: this.$p.t('global', 'uploaddatum')
+ });
+ cm.getColumnByField('nachgereicht').component.updateDefinition({
+ title: this.$p.t('dokumente', 'nachgereicht')
+ });
+ cm.getColumnByField('vorhanden').component.updateDefinition({
+ title: this.$p.t('dokumente', 'vorhanden')
+ });
+ cm.getColumnByField('dms_id').component.updateDefinition({
+ title: this.$p.t('global', 'dms_id')
+ });
+ cm.getColumnByField('titel_intern').component.updateDefinition({
+ title: this.$p.t('global', 'titel')
+ });
+ cm.getColumnByField('anmerkung_intern').component.updateDefinition({
+ title: this.$p.t('global', 'anmerkung')
+ });
+ cm.getColumnByField('akte_id').component.updateDefinition({
+ title: this.$p.t('global', 'akte_id')
+ });
+ cm.getColumnByField('nachgereicht_am').component.updateDefinition({
+ title: this.$p.t('global', 'dokument')
+ });
+ }
+ }
+ ]
+ }
+ },
+ computed: {
+ tabulatorEvents() {
+ const events = [
+ {
+ event: "rowDblClick",
+ handler: (e, row) => {
+ this.actionDownloadFile(row.getData().akte_id);
+ }
+ }
+ ];
+ return events;
+ }
+ },
+ methods: {
+ actionDownloadFile(akte_id){
+ window.open(
+ FHC_JS_DATA_STORAGE_OBJECT.app_root
+ + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/api/frontend/v1/stv/dokumente/download?akte_id=' + encodeURIComponent(akte_id),
+ '_blank'
+ );
+ },
+ actionUploadFile(dokument_kurzbz){
+ this.$refs.modalUpload.open(this.prestudent_id, dokument_kurzbz);
+ },
+ actionEditDocument(akte_id){
+ this.$refs.modalEdit.open(akte_id);
+ },
+ actionDeleteFile(akte_id){
+ this.$fhcAlert
+ .confirmDelete()
+ .then(result => result
+ ? akte_id
+ : Promise.reject({handled: true}))
+ .then(this.deleteFile)
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ deleteFile(akte_id){
+ return this.$api
+ .call(ApiStvDocuments.deleteFile(akte_id))
+ .then(response => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
+ })
+ .catch(this.$fhcAlert.handleSystemError)
+ .finally(()=> {
+ this.reload();
+ });
+ },
+ deleteZuordnung(selected) {
+ Promise.allSettled(
+ selected.map(e =>
+ this.$api
+ .call(ApiStvDocuments.deleteZuordnung({
+ prestudent_id: this.prestudent_id,
+ dokument_kurzbz: e.dokument_kurzbz
+ }))
+ .then(() => ({
+ success: true,
+ dokument_bz: e.bezeichnung
+ }))
+ .catch(() => ({
+ success: false,
+ dokument_bz: e.bezeichnung
+ }))
+ )
+ ).then(results => {
+ const failed = results.filter(res => !res.value.success);
+ const suceeded = results.filter(res => res.value.success);
+ if (failed.length > 0) {
+ failed.forEach(res => {
+ this.$fhcAlert.alertError(this.$p.t('dokumente', 'errorUnaccepted',
+ {'dokument_kurzbz': res.value.dokument_bz}
+ ));
+ });
+ let countSuceeded = suceeded.length;
+ if(countSuceeded > 0)
+ this.$fhcAlert.alertSuccess(this.$p.t('dokumente', 'successCountUnaccepted',
+ {'count': countSuceeded}));
+
+ } else {
+ this.$fhcAlert.alertSuccess(this.$p.t('dokumente', 'successUnaccepted'));
+ }
+ this.reloadAll();
+ });
+ },
+
+ reload(){
+ this.$refs.table.reloadTable();
+ },
+ reloadAll(){
+ this.reload();
+ this.$emit('reloadUnaccepted');
+ }
+ },
+ template: `
+
+
{{$p.t('dokumente', 'accepted')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+}
\ No newline at end of file
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Unaccepted.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Unaccepted.js
new file mode 100644
index 000000000..6cc25cb6f
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/List/Unaccepted.js
@@ -0,0 +1,347 @@
+import {CoreFilterCmpt} from "../../../../../filter/Filter.js";
+import ModalEdit from "../Modal/Edit.js";
+import ModalUpload from "../Modal/Upload.js";
+
+import ApiStvDocuments from "../../../../../../api/factory/stv/documents.js";
+
+export default {
+ name: "UnacceptedDocuments",
+ components: {
+ CoreFilterCmpt,
+ ModalEdit,
+ ModalUpload
+ },
+ props: {
+ prestudent_id: Number,
+ studiengang_kz: Number
+ },
+ data(){
+ return {
+ tabulatorOptions: {
+ ajaxURL: 'dummy',
+ ajaxRequestFunc: () => this.$api.call(
+ ApiStvDocuments.getDocumentsUnaccepted({
+ id: this.prestudent_id,
+ studiengang_kz: this.studiengang_kz})
+ ),
+ ajaxResponse: (url, params, response) => response.data,
+ columns: [
+ {title: "Dokument", field: "bezeichnung"},
+ {title: "Kurzbz", field: "dokument_kurzbz", visible: false},
+ {
+ title: "UploadDatum", field: "hochgeladenamum",
+ 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: "nachgereicht", field: "nachgereicht", visible: false,
+ formatter:"tickCross",
+ hozAlign:"center",
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ }},
+ {title: "vorhanden",
+ field: "vorhanden",
+ formatter: function(cell, formatterParams, onRendered) {
+ let value = cell.getValue();
+ let rowData = cell.getRow().getData(); // Zugriff auf gesamte Zeile
+ let dueDate = rowData["nachgereicht_am"];
+ const date = new Date(dueDate);
+ let dateFormatted = date.toLocaleString("de-DE", {
+ day: "2-digit",
+ month: "2-digit",
+ year: "numeric",
+ hour12: false
+ });
+
+ let tickCrossIcon = value
+ ? ''
+ : '';
+
+ // if nachgereicht_am show datum
+ let pill = dueDate
+ ? `${dateFormatted}`
+ : '';
+
+ return `${tickCrossIcon} ${pill}`;
+ },
+ hozAlign: "center"
+ },
+ {title: "infotext", field: "infotext"},
+ {title: "akte_id", field: "akte_id"},
+ {title: "titel_intern", field: "titel_intern"},
+ {title: "Anmerkung_intern", field: "anmerkung_intern", visible: false},
+ {title: "Online", field: "onlinebewerbung",
+ formatter:"tickCross",
+ hozAlign:"center",
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ }},
+ {title: "Pflicht", field: "pflicht",
+ formatter:"tickCross",
+ hozAlign:"center",
+ formatterParams: {
+ tickElement: '',
+ crossElement: ''
+ }},
+ {title: "Nachreichung am", field: "nachgereicht_am",
+ 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: 'Aktionen', field: 'actions',
+ minWidth: 50,
+ maxWidth: 100,
+ formatter: (cell, formatterParams, onRendered) => {
+
+ let container = document.createElement('div');
+ container.className = "d-flex gap-2";
+
+ if(cell.getData().akte_id){
+ let button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'downloadDok');
+ button.addEventListener('click', (event) =>
+ this.actionDownloadFile(cell.getData().akte_id)
+ );
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'editDokument');
+ button.addEventListener('click', (event) =>
+ this.actionEditFile(cell.getData().akte_id)
+ );
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'deleteDokument');
+ button.addEventListener('click', () =>
+ this.actionDeleteFile(cell.getData().akte_id)
+ );
+ container.append(button);
+ }
+ else
+ {
+ let button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'uploadDokument');
+ button.addEventListener('click', () =>
+ this.actionUploadFile(cell.getData().dokument_kurzbz)
+ );
+ container.append(button);
+ }
+
+ return container;
+ },
+ frozen: true
+ },
+ ],
+ layout: 'fitColumns',
+ layoutColumnsOnNewData: false,
+ height: 300,
+ selectable: true,
+ selectableRangeMode: 'click',
+ persistenceID: 'core-details-documents-unaccepted',
+ listDocuments: [],
+ prestudentDocumentData: [],
+ },
+ tabulatorEvents: [
+ {
+ event: 'tableBuilt',
+ handler: async () => {
+ await this.$p.loadCategory(['global', 'dokumente', 'ui', 'mobility', 'ampeln']);
+
+ let cm = this.$refs.table.tabulator.columnManager;
+
+ cm.getColumnByField('bezeichnung').component.updateDefinition({
+ title: this.$p.t('global', 'dokument')
+ });
+ cm.getColumnByField('dokument_kurzbz').component.updateDefinition({
+ title: this.$p.t('mobility', 'kurzbz')
+ });
+ cm.getColumnByField('hochgeladenamum').component.updateDefinition({
+ title: this.$p.t('global', 'uploaddatum')
+ });
+ cm.getColumnByField('nachgereicht').component.updateDefinition({
+ title: this.$p.t('dokumente', 'nachgereicht')
+ });
+ cm.getColumnByField('vorhanden').component.updateDefinition({
+ title: this.$p.t('dokumente', 'vorhanden')
+ });
+ cm.getColumnByField('anmerkung_intern').component.updateDefinition({
+ title: this.$p.t('global', 'anmerkung')
+ });
+ cm.getColumnByField('akte_id').component.updateDefinition({
+ title: this.$p.t('global', 'akte_id')
+ });
+ cm.getColumnByField('pflicht').component.updateDefinition({
+ title: this.$p.t('ampeln', 'mandatory')
+ });
+ cm.getColumnByField('nachgereicht_am').component.updateDefinition({
+ title: this.$p.t('global', 'dokument')
+ });
+ }
+ }
+ ]
+ }
+ },
+ computed: {
+ tabulatorEvents() {
+ const events = [
+ {
+ event: "rowDblClick",
+ handler: (e, row) => {
+ this.actionDownloadFile(row.getData().akte_id);
+ }
+ }
+ ];
+
+ return events;
+ }
+ },
+ methods: {
+ actionDownloadFile(akte_id){
+ window.open(
+ FHC_JS_DATA_STORAGE_OBJECT.app_root
+ + FHC_JS_DATA_STORAGE_OBJECT.ci_router + '/api/frontend/v1/stv/dokumente/download?akte_id=' + encodeURIComponent(akte_id),
+ '_blank'
+ );
+ },
+ actionUploadFile(dokument_kurzbz){
+ this.$refs.modalUpload.open(this.prestudent_id, dokument_kurzbz);
+ },
+ actionDeleteFile(akte_id){
+ this.$fhcAlert
+ .confirmDelete()
+ .then(result => result
+ ? akte_id
+ : Promise.reject({handled: true}))
+ .then(this.deleteFile)
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ actionEditFile(akte_id){
+ this.$refs.modalEdit.open(akte_id);
+ },
+ acceptDocuments(selected){
+ Promise
+ .allSettled(
+ selected.map(e =>
+ this.$api
+ .call(ApiStvDocuments.createZuordnung({
+ prestudent_id: this.prestudent_id,
+ dokument_kurzbz: e.dokument_kurzbz
+ }))
+ .then(() => ({
+ success: true,
+ dokument_bz: e.bezeichnung
+ }))
+ .catch(() => ({
+ success: false,
+ dokument_bz: e.bezeichnung
+ }))
+ )
+ )
+ .then(results => {
+ const failed = results.filter(res => !res.value.success);
+ const suceeded = results.filter(res => res.value.success);
+ if (failed.length > 0) {
+ failed.forEach(res => {
+ this.$fhcAlert.alertError(this.$p.t('dokumente', 'errorAccepted',
+ {'dokument_kurzbz': res.value.dokument_bz}
+ ));
+ });
+ let countSuceeded = suceeded.length;
+ if(countSuceeded > 0)
+ this.$fhcAlert.alertSuccess(this.$p.t('dokumente', 'successCountAccepted',
+ {'count': countSuceeded}));
+
+ } else {
+ this.$fhcAlert.alertSuccess(this.$p.t('dokumente', 'successAccepted'));
+ }
+ this.reloadAll();
+ });
+ },
+ deleteFile(akte_id){
+ return this.$fhcApi.factory.stv.documents.deleteFile(akte_id)
+ .then(response => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
+ })
+ .catch(this.$fhcAlert.handleSystemError)
+ .finally(()=> {
+ this.reload();
+ });
+ },
+ reload(){
+ this.$refs.table.reloadTable();
+ },
+ reloadAll() {
+ this.reload();
+ this.$emit('reloadAccepted');
+ }
+ },
+ template: `
+
+
{{$p.t('dokumente', 'unaccepted')}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+}
\ No newline at end of file
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Edit.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Edit.js
new file mode 100644
index 000000000..29c98020e
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Edit.js
@@ -0,0 +1,141 @@
+import BsModal from "../../../../../Bootstrap/Modal.js";
+import FormForm from "../../../../../Form/Form.js";
+import FormInput from "../../../../../Form/Input.js";
+
+import ApiStvDocuments from "../../../../../../api/factory/stv/documents.js";
+
+export default {
+ name: "modalEditDocuments",
+ components: {
+ BsModal,
+ FormForm,
+ FormInput
+ },
+ data(){
+ return {
+ formData: [],
+ listDokTypen: []
+ }
+ },
+ methods: {
+ updateFile(akte_id){
+ this.$api
+ .call(ApiStvDocuments.updateFile(akte_id, this.formData))
+ .then(response => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
+ this.$refs.modalEditDocument.hide();
+ this.$emit('reload');
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ open(akte_id){
+ this.loadFormData(akte_id);
+ this.$refs.modalEditDocument.show();
+ },
+ loadFormData(akte_id){
+ return this.$api
+ .call(ApiStvDocuments.loadAkte(akte_id))
+ .then(result => {
+ this.formData = result.data;
+ return result;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ }
+ },
+ created(){
+ this.$api
+ .call(ApiStvDocuments.getDoktypen())
+ .then(result => {
+ this.listDokTypen = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ template: `
+
+
+ {{ $p.t('dokumente', 'dokDetails') }} {{formData.nameperson}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+}
diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Upload.js b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Upload.js
new file mode 100644
index 000000000..f6280a9cf
--- /dev/null
+++ b/public/js/components/Stv/Studentenverwaltung/Details/Dokumente/Modal/Upload.js
@@ -0,0 +1,127 @@
+import BsModal from "../../../../../Bootstrap/Modal.js";
+import FormForm from "../../../../../Form/Form.js";
+import FormInput from "../../../../../Form/Input.js";
+import FormUploadDms from "../../../../../Form/Upload/Dms.js";
+
+import ApiStvDocuments from "../../../../../../api/factory/stv/documents.js";
+
+export default {
+ name: "modalUploadDocuments",
+ components: {
+ BsModal,
+ FormForm,
+ FormInput,
+ FormUploadDms
+ },
+ data(){
+ return{
+ formData: {
+ dokument_kurzbz: null,
+ anhang: [],
+ anmerkung_intern: null
+ },
+ listDokTypen: []
+ }
+ },
+ methods:{
+ open(prestudent_id, dokument_kurzbz){
+ this.formData.dokument_kurzbz = dokument_kurzbz;
+ this.formData.prestudent_id = prestudent_id;
+ this.$refs.modalUploadFile.show();
+ },
+ uploadFile(){
+ // console.log(this.formData.anhang[0]);
+ return this.$api
+ .call(ApiStvDocuments.uploadFile(this.formData.prestudent_id, this.formData))
+ .then(result => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successUpload'));
+ this.resetModal();
+ this.$refs.modalUploadFile.hide();
+ this.$emit('reload');
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ resetModal(){
+ this.formData.dokument_kurzbz = null;
+ this.formData.anhang = [];
+ this.formData.anmerkung_intern = null;
+ this.formData.titel_intern = null;
+ }
+ },
+ created(){
+ this.$api
+ .call(ApiStvDocuments.getDoktypen())
+ .then(result => {
+ this.listDokTypen = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ template: `
+
+
+ Upload {{ $p.t('stv', 'tab_documents') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `,
+}
\ No newline at end of file
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php
index 53df09ca9..7ce22f0a0 100644
--- a/system/phrasesupdate.php
+++ b/system/phrasesupdate.php
@@ -42123,6 +42123,688 @@ and represent the current state of research on the topic. The prescribed citatio
),
/////////// FHC4 Phrases Messages END ///////////
+ // FHC4 Studierendenverwaltung Dokumente START
+ array(
+ 'app' => 'core',
+ 'category' => 'stv',
+ 'phrase' => 'tab_documents',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokumente',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Documents',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'uploadDokument',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokument hochladen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Upload document',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'deleteDokument',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokument löschen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Delete document',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'editDokument',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokument bearbeiten',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Edit document',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'title',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Titel',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'title',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'dokTyp',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokumententyp',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Document type',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'nachreichungAm',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Nachreichung am',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Submission on',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'dokDetails',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokumentendetails',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Document Details',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'anmerkung_person',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Anmerkung der Person',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Notes of the Person',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'successUpload',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokument erfolgreich hochgeladen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Dokumentupload successful',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'dokumentAccept',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptieren',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Accept',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'dokumentUnaccept',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Entakzeptieren',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Unaccept',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'accepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptiert',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Accepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'unaccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Nicht Akzeptiert',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Not Accepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'err_deleteDokHere',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dieses Dokument darf hier nicht gelöscht werden',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'This document may not be deleted here',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'err_updateNotAllowed',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Es können nur Eintraege geändert werden zu denen Dokumente hochgeladen wurden',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Only entries to which documents have been uploaded can be changed',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'downloadDok',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dokument herunterladen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Download Document',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'successAccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptieren erfolgreich',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Successfully set to accepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'successUnaccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Entakzeptieren erfolgreich',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Successfully set to unaccepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'successCountUnaccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Entakzeptieren von {count} Dokument(en) erfolgreich',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => '{count} Document(s) successfully set to unaccepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'successCountAccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptieren von {count} Dokument(en) erfolgreich',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => '{count} Document(s) successfully set to accepted',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'errorUnaccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Fehler beim Entakzeptieren von Dokument {dokument_kurzbz}',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Error unaccepting document {dokument_kurzbz}',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'errorAccepted',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Fehler beim Akzeptieren von Dokument {dokument_kurzbz}',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Error Accepting document {dokument_kurzbz}',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'errorMissingValue',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => '{value} fehlt',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => '{value} missing',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'error_valueNotNumeric',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => '{value} darf nur Ziffern enthalten.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => '{value} must contain only numbers.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'nachgereicht',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Nachgereicht',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Submitted later',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'vorhanden',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Vorhanden',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Available',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'global',
+ 'phrase' => 'akte_id',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akte ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'File ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'global',
+ 'phrase' => 'nachgereicht_am',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Nachgereicht am',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Submitted on',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'datumAkzeptiert',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptiertdatum',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Accepted on',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'akzeptiertVon',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Akzeptiert von',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Accepted by',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'global',
+ 'phrase' => 'dms_id',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Dms ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Dms ID',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'error_fileMissing',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Bitte eine Datei anhängen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Please attach a file',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'dokumente',
+ 'phrase' => 'error_fileType',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Nur Dateitypen JPEG, PNG oder PDF sind erlaubt',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Only JPEG, PNG, or PDF files are allowed.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ // FHC4 Studierendenverwaltung Dokumente END
);