diff --git a/application/controllers/Cis/Zeitsperren.php b/application/controllers/Cis/Zeitsperren.php
new file mode 100644
index 000000000..baa09b8c6
--- /dev/null
+++ b/application/controllers/Cis/Zeitsperren.php
@@ -0,0 +1,30 @@
+ ['basis/cis:r'],
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ }
+
+ /**
+ * index loads the view Zeitsperren
+ * @access public
+ * @return void
+ */
+ public function index()
+ {
+ $viewData = array(
+ 'uid'=>getAuthUID(),
+ );
+
+ $this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'zeitsperren']);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/Zeitsperren.php b/application/controllers/api/frontend/v1/Zeitsperren.php
new file mode 100644
index 000000000..66efa81a7
--- /dev/null
+++ b/application/controllers/api/frontend/v1/Zeitsperren.php
@@ -0,0 +1,367 @@
+ self::PERM_LOGGED,
+ 'getTypenZeitsperren' => self::PERM_LOGGED,
+ 'getTypenErreichbarkeit' => self::PERM_LOGGED,
+ 'getStunden' => self::PERM_LOGGED,
+ 'loadZeitsperre' => self::PERM_LOGGED,
+ 'add' => self::PERM_LOGGED,
+ 'update' => self::PERM_LOGGED,
+ 'delete' => self::PERM_LOGGED,
+ ]);
+
+ // Load Libraries
+ $this->load->library('VariableLib', ['uid' => getAuthUID()]);
+ $this->load->library('form_validation');
+
+ // Load language phrases
+ $this->loadPhrases([
+ 'ui',
+ 'person',
+ 'zeitsperren'
+ ]);
+
+ // Load models
+ $this->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
+ $this->load->model('ressource/Zeitsperretyp_model', 'ZeitsperretypModel');
+ $this->load->model('ressource/Erreichbarkeit_model', 'ErreichbarkeitModel');
+ $this->load->model('ressource/Stunde_model', 'StundeModel');
+ $this->load->model('ressource/Zeitaufzeichnung_model', 'ZeitaufzeichnungModel');
+ }
+
+ public function getZeitsperrenUser($uid)
+ {
+ //check if $uid is passedUser
+ $loggedInUser = getAuthUID();
+ if($loggedInUser != $uid) {
+ $this->load->library('PermissionLib');
+ $isAdmin = $this->permissionlib->isBerechtigt('admin');
+ if(!$isAdmin) {
+ $this->terminateWithError($this->p->t('ui', 'noAdmin'), self::ERROR_TYPE_GENERAL);
+ }
+ }
+
+ $result = $this->ZeitsperreModel->getZeitsperrenUser($uid);
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function getTypenZeitsperren()
+ {
+ $this->ZeitsperretypModel->addOrder('beschreibung', 'ASC');
+ $result = $this->ZeitsperretypModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function getTypenErreichbarkeit()
+ {
+ $result = $this->ErreichbarkeitModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function getStunden()
+ {
+ $this->StundeModel->addOrder('stunde', 'ASC');
+ $result = $this->StundeModel->load();
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function loadZeitsperre($zeitsperre_id)
+ {
+ $this->ZeitsperreModel->addSelect(
+ 'campus.tbl_zeitsperre.*, typ.*,
+ ma.person_id AS ma_person_id, ma.vorname AS ma_vorname, ma.nachname AS ma_nachname,
+ ma.titelpre AS ma_titelpre, ma.titelpost AS ma_titelpost'
+ );
+ $this->ZeitsperreModel->addJoin('campus.tbl_zeitsperretyp typ', 'ON (typ.zeitsperretyp_kurzbz = campus.tbl_zeitsperre.zeitsperretyp_kurzbz)');
+ $this->ZeitsperreModel->addJoin('public.tbl_benutzer ben', 'ON (ben.uid = campus.tbl_zeitsperre.vertretung_uid)', 'LEFT');
+ $this->ZeitsperreModel->addJoin('public.tbl_person ma', 'ON (ma.person_id = ben.person_id)', 'LEFT');
+ $result = $this->ZeitsperreModel->loadWhere(
+ array('zeitsperre_id' => $zeitsperre_id)
+ );
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((current(getData($result)) ?: []));
+ }
+
+ public function add($mitarbeiter_uid)
+ {
+ $loggedInUser = getAuthUID();
+
+ if($mitarbeiter_uid != $loggedInUser)
+ $this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
+
+ $this->form_validation->set_rules('zeitsperretyp_kurzbz', 'Grund Zeitsperre', 'required', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Grund Zeitsperre'])
+ ]);
+
+ $this->form_validation->set_rules('vondatum', 'VonDatum', 'required|is_valid_date', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'VonDatum']),
+ 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'VonDatum'])
+ ]);
+
+ $this->form_validation->set_rules('bisdatum', 'BisDatum', 'required|is_valid_date|callback_check_von_bis_datum|callback_check_diff_intval', [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'BisDatum']),
+ 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum']),
+ 'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
+ 'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
+ ]);
+
+ if ($this->form_validation->run() == false)
+ {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ $bezeichnung = $this->input->post('bezeichnung');
+ $vondatum = $this->input->post('vondatum');
+ $vonstunde = $this->input->post('vonstunde');
+ $bisdatum = $this->input->post('bisdatum');
+ $bisstunde = $this->input->post('bisstunde');
+ //$vonIso = $this->input->post('vonISO'); //Timestamp für Stunde
+ //$bisIso = $this->input->post('bisISO'); //Timestamp für Stunde
+ $erreichbarkeit_kurzbz = $this->input->post('erreichbarkeit_kurzbz');
+ $vertretung_uid = $this->input->post('vertretung_uid');
+ $zeitsperretyp_kurzbz = $this->input->post('zeitsperretyp_kurzbz');
+
+ //check if existing zeitsperre
+ $result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if(hasData($result))
+ {
+ $this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
+ }
+
+ //check if existing zeitaufzeichnung
+ if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
+ {
+ $result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
+
+ if(hasData($result))
+ $this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
+ }
+
+ $result = $this->ZeitsperreModel->insert(
+ [
+ 'mitarbeiter_uid' => $mitarbeiter_uid,
+ 'bezeichnung' => $bezeichnung,
+ 'vondatum' => $vondatum,
+ 'vonstunde' => $vonstunde,
+ 'bisdatum' => $bisdatum,
+ 'bisstunde' => $bisstunde,
+ 'erreichbarkeit_kurzbz' => $erreichbarkeit_kurzbz,
+ 'zeitsperretyp_kurzbz' => $zeitsperretyp_kurzbz,
+ 'vertretung_uid' => $vertretung_uid,
+ 'insertvon' => $loggedInUser,
+ 'insertamum' => date('c'),
+ ]
+ );
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+
+ public function update($zeitsperre_id)
+ {
+ //check if loggedin User is owner of the zeitsperre
+ $loggedInUser = getAuthUID();
+ $result = $this->ZeitsperreModel->load($zeitsperre_id);
+ $data = $this->getDataOrTerminateWithError($result);
+ $uid = current($data)->mitarbeiter_uid;
+
+ if($uid != $loggedInUser)
+ $this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
+
+ if(!$zeitsperre_id)
+ {
+ return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
+ }
+ //get current params
+ $array_update = [
+ 'bezeichnung',
+ 'vondatum',
+ 'vonstunde',
+ 'bisdatum',
+ 'bisstunde',
+ // 'vonISO', //Timestamp für Stunde
+ // 'bisISO', //Timestamp für Stunde
+ 'erreichbarkeit_kurzbz',
+ 'vertretung_uid',
+ 'zeitsperretyp_kurzbz',
+ 'mitarbeiter_uid',
+ ];
+ $post = $this->input->post();
+ $update = [];
+
+ foreach ($array_update as $prop)
+ {
+ if (array_key_exists($prop, $post))
+ {
+ $update[$prop] = $post[$prop];
+ }
+ }
+
+ // Validation
+ $rulesDefined = false; //necessary, otherwise CI validation will always be triggered, even without rules
+ foreach ($update as $key => $val) {
+ switch ($key) {
+ case 'zeitsperretyp_kurzbz':
+ $this->form_validation->set_rules(
+ $key,
+ 'Grund Zeitsperre',
+ 'required',
+ ['required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'Grund Zeitsperre'])]
+ );
+ $rulesDefined = true;
+ break;
+ case 'vondatum':
+ $this->form_validation->set_rules(
+ $key,
+ 'VonDatum',
+ 'required|is_valid_date',
+ [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'VonDatum']),
+ 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'VonDatum'])
+ ]
+ );
+ $rulesDefined = true;
+ break;
+ case 'bisdatum':
+ $rules = 'required|is_valid_date';
+ if (array_key_exists('vondatum', $update)) {
+ $rules .= '|callback_check_von_bis_datum|callback_check_diff_intval';
+ }
+ $this->form_validation->set_rules(
+ $key,
+ 'BisDatum',
+ $rules,
+ [
+ 'required' => $this->p->t('ui', 'error_fieldRequired', ['field'=>'BisDatum']),
+ 'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field'=>'BisDatum']),
+ 'check_von_bis_datum' => $this->p->t('zeitsperre', 'error_VonDatumGroesserAlsBisDatum'),
+ 'check_diff_intval' => $this->p->t('zeitsperre', 'error_zeitraumAuffallendHoch')
+ ]
+ );
+ $rulesDefined = true;
+ break;
+ }
+ }
+
+ if ($rulesDefined && $this->form_validation->run() == false) {
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+ }
+
+ if(array_key_exists('vondatum', $post) || array_key_exists('bisdatum', $post))
+ {
+ $result = $this->ZeitsperreModel->load($zeitsperre_id);
+ $data = $this->getDataOrTerminateWithError($result);
+ $data = current($data);
+
+ $mitarbeiter_uid = array_key_exists('mitarbeiter_uid', $post) ? $update['mitarbeiter_uid'] : $data->mitarbeiter_uid;
+ $vondatum = array_key_exists('vondatum', $post) ? $update['vondatum'] : $data->vondatum;
+ $bisdatum = array_key_exists('bisdatum', $post) ? $update['bisdatum'] : $data->bisdatum;
+ $vonstunde = array_key_exists('vonstunde', $post) ? $update['vonstunde'] : $data->vonstunde;
+ $zeitsperretyp_kurzbz = array_key_exists('zeitsperretyp_kurzbz', $post) ? $update['zeitsperretyp_kurzbz'] : $data->zeitsperretyp_kurzbz;
+
+ $result = $this->ZeitsperreModel->getSperreByDate($mitarbeiter_uid, $vondatum, $vonstunde, true);
+ $data = $this->getDataOrTerminateWithError($result);
+
+ if(hasData($result))
+ {
+ $this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitsperre', ['typ'=> current($data)->zeitsperretyp_kurzbz]), self::ERROR_TYPE_GENERAL);
+ }
+
+ //check if existing zeitaufzeichnung
+ if(in_array($zeitsperretyp_kurzbz, Zeitsperre_model::BLOCKIERENDE_ZEITSPERREN))
+ {
+ $result = $this->ZeitsperreModel->existsZeitaufzeichnung($mitarbeiter_uid, $vondatum, $bisdatum);
+
+ if(hasData($result))
+ $this->terminateWithError($this->p->t('zeitsperren', 'error_existingZeitaufzeichnung'), self::ERROR_TYPE_GENERAL);
+ }
+ }
+
+ if (!empty($update)) {
+ $update['updatevon'] = $loggedInUser;
+ $update['updateamum'] = date('c');
+ $result = $this->ZeitsperreModel->update($zeitsperre_id, $update);
+
+ $data = $this->getDataOrTerminateWithError($result);
+
+ $this->terminateWithSuccess($data);
+ }
+ else
+ $this->terminateWithSuccess("no update");
+ }
+
+ public function delete($zeitsperre_id)
+ {
+
+ if (!is_numeric($zeitsperre_id) || (int)$zeitsperre_id <= 0)
+ {
+ $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id' => 'Zeitsperre_id']), self::ERROR_TYPE_GENERAL);
+ }
+
+ //check if loggedin User is owner of the zeitsperre
+ $loggedInUser = getAuthUID();
+ $result = $this->ZeitsperreModel->load($zeitsperre_id);
+ $data = $this->getDataOrTerminateWithError($result);
+ $uid = current($data)->mitarbeiter_uid;
+
+ if($uid != $loggedInUser)
+ $this->terminateWithError($this->p->t('ui', 'noPermission'), self::ERROR_TYPE_GENERAL);
+
+ $result = $this->ZeitsperreModel->delete(
+ array('zeitsperre_id' => $zeitsperre_id)
+ );
+
+ if (isError($result)) {
+ $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
+ }
+ $this->terminateWithSuccess((getData($result) ?: []));
+ }
+
+ public function check_von_bis_datum($bisdatum)
+ {
+ $vondatum = $this->input->post('vondatum');
+
+ return $vondatum <= $bisdatum;
+ }
+
+ public function check_diff_intval($bisdatum)
+ {
+ $vondatum = $this->input->post('vondatum');
+
+ // Intervall in days
+ $vonTs = strtotime($vondatum);
+ $bisTs = strtotime($bisdatum);
+
+ $tage = ($bisTs - $vonTs) / 86400;
+
+ // if intervall > 14
+ return $tage <= 14;
+ }
+
+
+}
diff --git a/application/models/ressource/Zeitsperre_model.php b/application/models/ressource/Zeitsperre_model.php
index 078d29d8b..c7dc9dfff 100644
--- a/application/models/ressource/Zeitsperre_model.php
+++ b/application/models/ressource/Zeitsperre_model.php
@@ -12,6 +12,8 @@ class Zeitsperre_model extends DB_Model
$this->pk = 'zeitsperre_id';
}
+ const BLOCKIERENDE_ZEITSPERREN = ['Krank','Urlaub','ZA','DienstV','PflegeU','DienstF','CovidSB','CovidKS'];
+
/**
* Save or update Zeitsperre.
*
@@ -61,4 +63,128 @@ class Zeitsperre_model extends DB_Model
return $this->execQuery($qry);
}
+
+ /**
+ * get Zeitsperren of a user
+ *
+ * @param $uid mitarbeiteruid
+ * @param $bisgrenze @true show only entries of actual business year (1.9.- 31.8.)
+ *
+ * @return array
+ */
+ public function getZeitsperrenUser($uid, $bisgrenze = true)
+ {
+ $qry = "
+ SELECT
+ tbl_zeitsperre.*, tbl_zeitsperretyp.*, tbl_erreichbarkeit.farbe AS erreichbarkeit_farbe,
+ tbl_erreichbarkeit.beschreibung AS erreichbarkeit_beschreibung,
+ CONCAT (ps.vorname, ' ', ps.nachname) as vertretung
+ FROM (campus.tbl_zeitsperre JOIN campus.tbl_zeitsperretyp USING (zeitsperretyp_kurzbz))
+ LEFT JOIN campus.tbl_erreichbarkeit USING (erreichbarkeit_kurzbz)
+ LEFT JOIN public.tbl_benutzer ON campus.tbl_zeitsperre.vertretung_uid = public.tbl_benutzer.uid
+ LEFT JOIN public.tbl_person ps USING (person_id)
+ WHERE mitarbeiter_uid= ?
+ ";
+
+ if($bisgrenze)
+ {
+ $qry.="
+ AND (
+ (date_part('month',vondatum)>=9 AND date_part('year', vondatum)>='".(date('Y')-1)."')
+ OR
+ (date_part('month',vondatum)<9 AND date_part('year', vondatum)>='".(date('Y'))."')
+ )";
+ }
+
+ $qry.= " ORDER BY vondatum DESC";
+
+ return $this->execQuery($qry, array('mitarbeiter_uid' => $uid));
+ }
+
+ /**
+ * check a date for existing zeitsperre
+ *
+ * @param $uid mitarbeiteruid
+ * @param $datum datum to check
+ * @param $stunde stunde (default = null)
+ * @param bool $nurblockierend if only hr relevante zeitsperren have to be checked
+ *
+ * @return array
+ */
+ public function getSperreByDate($uid, $datum, $stunde = null, $nurblockierend = false)
+ {
+ $parametersArray = [$datum, $datum];
+
+ $qry = "
+ SELECT
+ *
+ FROM
+ campus.tbl_zeitsperre
+ WHERE
+ vondatum <= ?
+ AND bisdatum>= ?";
+
+ if($nurblockierend)
+ {
+ $qry .= " AND zeitsperretyp_kurzbz IN ('"
+ . implode("','", self::BLOCKIERENDE_ZEITSPERREN)
+ . "')";
+ }
+
+ if(!is_null($stunde))
+ {
+ $parametersArray = array_merge(
+ $parametersArray,
+ [$datum, $stunde, $datum, $datum, $stunde, $datum]
+ );
+
+ $qry.=" AND
+ ((vondatum= ? AND vonstunde<= ? OR vonstunde is null OR vondatum<> ?) AND
+ (bisdatum= ? AND bisstunde>= ? OR bisstunde is null OR bisdatum<> ?))";
+ }
+
+ array_push($parametersArray, $uid);
+
+ $qry .= "AND mitarbeiter_uid= ? ";
+
+ return $this->execQuery($qry, $parametersArray);
+ }
+
+ /**
+ * check a date for existing zeitsperre
+ *
+ * @param $uid mitarbeiteruid
+ * @param $vondatum datum in Format IS0
+ * @param $bisdatum datum in Format ISO
+ *
+ * @return array
+ */
+ public function existsZeitaufzeichnung($uid, $vonDay, $bisDay)
+ {
+ try {
+ $from = new DateTime($vonDay);
+ $to = new DateTime($bisDay);
+ } catch (Exception $e) {
+ throw new Exception("Invalid date format");
+ }
+
+ //remove hour stamps
+ $from->setTime(0, 0, 0);
+ $to->setTime(0, 0, 0)->modify('+1 day');
+
+ $fromSql = $from->format('Y-m-d');
+ $toSql = $to->format('Y-m-d');
+ $params = [$uid, $fromSql, $toSql];
+
+ $qry = "
+ SELECT *
+ FROM campus.tbl_zeitaufzeichnung
+ WHERE uid = ?
+ AND start >= ?
+ AND ende < ? ";
+
+ $result = $this->execQuery($qry, $params);
+
+ return $result;
+ }
}
diff --git a/application/views/CisRouterView/CisRouterView.php b/application/views/CisRouterView/CisRouterView.php
index e0b0e2bb3..1aa8c398e 100644
--- a/application/views/CisRouterView/CisRouterView.php
+++ b/application/views/CisRouterView/CisRouterView.php
@@ -25,7 +25,8 @@ $includesArray = array(
'public/css/components/abgabetool/abgabe.css',
'public/css/Cis4/Cms.css',
'public/css/Cis4/Studium.css',
- 'public/css/Cis4/Benotungstool.css'
+ 'public/css/Cis4/Benotungstool.css',
+ 'public/css/Cis4/Zeitsperren.css',
),
'customJSs' => array(
'vendor/npm-asset/primevue/accordion/accordion.min.js',
diff --git a/public/css/Cis4/Zeitsperren.css b/public/css/Cis4/Zeitsperren.css
new file mode 100644
index 000000000..dac3d3988
--- /dev/null
+++ b/public/css/Cis4/Zeitsperren.css
@@ -0,0 +1,39 @@
+/* Repositioning clear icon Datepicker for not being outside the textfield */
+/* Wrapper */
+.dp__input_wrap {
+ position: relative;
+}
+
+/* calender-Icon left */
+.dp__input_icon {
+ position: absolute;
+ left: 10px;
+ right: auto;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+/* Clear-Icon right */
+.dp__clear_icon {
+ position: absolute;
+ right: 10px;
+ left: auto;
+ top: 50%;
+ transform: translateY(-50%);
+}
+
+/* padding for Icons */
+.dp__input {
+ padding-left: 36px !important;
+ padding-right: 36px !important;
+}
+
+.info-feedback {
+ display: block;
+ font-size: 0.875em;
+ color: #0d6efd; /* Bootstrap primary */
+}
+
+.is-info {
+ border-color: #0d6efd;
+}
diff --git a/public/js/api/factory/cis/zeitsperren.js b/public/js/api/factory/cis/zeitsperren.js
new file mode 100644
index 000000000..2a73a5e79
--- /dev/null
+++ b/public/js/api/factory/cis/zeitsperren.js
@@ -0,0 +1,70 @@
+/**
+ * Copyright (C) 2026 fhcomplete.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+export default {
+ getTimelocksUser(uid) {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getZeitsperrenUser/' + uid
+ };
+ },
+ getTypenZeitsperren(){
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getTypenZeitsperren/'
+ };
+ },
+ getTypenErreichbarkeit(){
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getTypenErreichbarkeit/'
+ };
+ },
+ getStunden(){
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/getStunden/'
+ };
+ },
+ addZeitsperre(uid, params) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Zeitsperren/add/' + uid,
+ params
+ };
+ },
+ editZeitsperre(zeitsperre_id, params) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Zeitsperren/update/' + zeitsperre_id,
+ params
+ };
+ },
+ loadZeitsperre(zeitsperre_id) {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/Zeitsperren/loadZeitsperre/' + zeitsperre_id
+ };
+ },
+ deleteZeitsperre(zeitsperre_id) {
+ return {
+ method: 'post',
+ url: '/api/frontend/v1/Zeitsperren/delete/' + zeitsperre_id
+ };
+ }
+
+};
\ No newline at end of file
diff --git a/public/js/apps/Cis/Cis.js b/public/js/apps/Cis/Cis.js
index 58c8f4356..8885eb945 100644
--- a/public/js/apps/Cis/Cis.js
+++ b/public/js/apps/Cis/Cis.js
@@ -21,6 +21,7 @@ import StgOrgLvPlan from "../../components/Cis/LvPlan/StgOrg.js";
import OtherLvPlan from "../../components/Cis/LvPlan/OtherLvPlan.js";
import PaabgabeUebersicht from "../../components/Cis/ProjektabgabeUebersicht/ProjektabgabeUebersicht.js";
import Benotungstool from "../../components/Cis/Benotungstool/Benotungstool.js";
+import Zeitsperren from "../../components/Cis/Zeitsperren/Zeitsperren.js";
import ApiRouteInfo from '../../api/factory/routeinfo.js';
import {capitalize} from "../../helpers/StringHelpers.js";
@@ -260,6 +261,12 @@ const router = VueRouter.createRouter({
};
},
},
+ {
+ path: `/Cis/Zeitsperren`,
+ name: 'Zeitsperren',
+ component: Zeitsperren,
+ props: true
+ },
]
})
diff --git a/public/js/components/Cis/Zeitsperren/Zeitsperren.js b/public/js/components/Cis/Zeitsperren/Zeitsperren.js
new file mode 100644
index 000000000..489860970
--- /dev/null
+++ b/public/js/components/Cis/Zeitsperren/Zeitsperren.js
@@ -0,0 +1,673 @@
+import {CoreFilterCmpt} from "../../filter/Filter.js";
+import FormForm from '../../Form/Form.js';
+import FormInput from '../../Form/Input.js';
+import PvAutoComplete from '../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js';
+
+import ApiAuthinfo from '../../../api/factory/authinfo.js';
+import ApiTimelocks from "../../../api/factory/cis/zeitsperren.js";
+import ApiStvAbschlusspruefung from "../../../api/factory/stv/abschlusspruefung";
+
+export default {
+ name: 'ZeitsperrenComponent',
+ components: {
+ CoreFilterCmpt,
+ FormForm,
+ FormInput,
+ PvAutoComplete
+ },
+ data(){
+ return {
+ uid: null,
+ statusNew: true,
+ timeRecordingLockedUntil: '2015-08-31', //TODO(Manu) check if needed
+ typesTimeLocks: ["Urlaub", "PflegeU", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
+ typesHideStunden: ["Urlaub", "ZA", "Krank", "DienstF", "DienstV", "CovidSB", "CovidKS"],
+ listTypenZeitsperren: [],
+ listTypenErreichbarkeit: [],
+ listStunden: [],
+ tabulatorOptions: null,
+ tabulatorEvents: [],
+ originalData: {},
+ zeitsperreData: {
+ vondatum : new Date(),
+ bisdatum: new Date(),
+ vonISO : "00:00:00", //later
+ bisISO: "23:59:59", //later
+ erreichbarkeit_kurzbz: 'n',
+ zeitsperretyp_kurzbz: 'Arzt',
+ vonstunde: null,
+ bisstunde: null
+ },
+ changedData: {},
+ selectedVertretung: null,
+ filteredMitarbeiter: [],
+ abortController: {
+ mitarbeiter: null
+ },
+ };
+ },
+ computed: {
+ dienstverhinderungen() {
+ return {
+ "Eheschließung": "a) " + this.$p.t('zeitsperren', 'eheschliessung'),
+ "Geburt eigenes Kind": "b) " + this.$p.t('zeitsperren', 'geburt'),
+ "Heirat Kind/Geschwister": "c) " + this.$p.t('zeitsperren', 'heirat'),
+ "Eigene Sponsion/Promotion": "d) " + this.$p.t('zeitsperren', 'sponsion'),
+ "Lebensbedr. Erkrankung P/K/E": "e) " + this.$p.t('zeitsperren', 'erkrankung_lebensbedr'),
+ "Ableben P/K/E": "f) " + this.$p.t('zeitsperren', 'ableben'),
+ "Bestattung G/S/G": "g) " + this.$p.t('zeitsperren', 'bestattung'),
+ "Wohnungswechsel": "h) " + this.$p.t('zeitsperren', 'umzug'),
+ "Bundesheer": "i) " + this.$p.t('zeitsperren', 'bundesheer'),
+ "Volksschultag": "j) " + this.$p.t('zeitsperren', 'volksschultag')};
+ },
+ showInfo(){
+ return this.zeitsperreData.zeitsperretyp_kurzbz === 'DienstF';
+ },
+ },
+ methods: {
+ actionEditZeitsperre(zeitsperre_id){
+ this.statusNew = false;
+ return this.$api
+ .call(ApiTimelocks.loadZeitsperre(zeitsperre_id))
+ .then(response => {
+ this.originalData = structuredClone(response.data);
+ this.zeitsperreData = structuredClone(response.data);
+
+ this.selectedVertretung = {
+ label: this.getPersonLabel(this.zeitsperreData.ma_titelpre, this.zeitsperreData.ma_nachname, this.zeitsperreData.ma_vorname, this.zeitsperreData.ma_titelpost, this.zeitsperreData.vertretung_uid),
+ person_id: this.zeitsperreData.ma_person_id,
+ mitarbeiter_uid: this.zeitsperreData.vertretung_uid
+ };
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ actionDeleteZeitsperre(zeitsperre_id){
+ this.$fhcAlert
+ .confirmDelete()
+ .then(result => result
+ ? zeitsperre_id
+ : Promise.reject({ handled: true })
+ )
+ .then(() => this.deleteZeitsperre(zeitsperre_id))
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ saveZeitsperre(zeitsperreId = null) {
+ const isNew = !zeitsperreId;
+
+ let payload = isNew
+ ? { ...this.zeitsperreData } // add
+ : this.getChangedFields(this.originalData, // edit
+ this.zeitsperreData);
+
+ if (!isNew && Object.keys(payload).length === 0) {
+ return Promise.resolve();
+ }
+
+ const request = isNew
+ ? ApiTimelocks.addZeitsperre(this.uid, payload)
+ : ApiTimelocks.editZeitsperre(zeitsperreId, payload);
+
+ return this.$refs.dataZeitsperre
+ .call(request)
+ .then(() => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
+
+ this.reset();
+ this.reload();
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ deleteZeitsperre(zeitsperre_id){
+ return this.$api
+ .call(ApiTimelocks.deleteZeitsperre(zeitsperre_id))
+ .then(response => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
+ })
+ .catch(this.$fhcAlert.handleSystemError)
+ .finally(()=> {
+ this.reload();
+ });
+ },
+ searchMitarbeiter(event) {
+ if (this.abortController.mitarbeiter) {
+ this.abortController.mitarbeiter.abort();
+ }
+
+ this.abortController.mitarbeiter = new AbortController();
+
+ return this.$api
+ .call(ApiStvAbschlusspruefung.getMitarbeiter(event.query))
+ .then(result => {
+ this.filteredMitarbeiter = [];
+ for (let mitarbeiter of result.data.retval) {
+ this.filteredMitarbeiter.push(
+ {
+ label: this.getPersonLabel(
+ mitarbeiter.titelpre,
+ mitarbeiter.nachname,
+ mitarbeiter.vorname,
+ mitarbeiter.titelpost,
+ mitarbeiter.mitarbeiter_uid
+ ),
+ person_id: mitarbeiter.person_id,
+ mitarbeiter_uid: mitarbeiter.mitarbeiter_uid
+ }
+ );
+ }
+ });
+ },
+ getPersonLabel(titelpre, nachname, vorname, titelpost, uid) {
+ if(!uid)
+ return '';
+ return nachname + ' ' + vorname + (titelpre ? ' ' + titelpre : '') + (titelpost ? ' ' + titelpost : '') + (uid ? ' (' + uid + ')' : '');
+ },
+ reload() {
+ if (this.$refs.table)
+ this.$refs.table.reloadTable();
+ },
+ reset(){
+ this.statusNew = true;
+ this.selectedVertretung = null;
+ this.zeitsperreData = {
+ vondatum : new Date(),
+ bisdatum: new Date(),
+ vonISO : "00:00:00", //later
+ bisISO: "23:59:59", //later
+ erreichbarkeit_kurzbz: 'n',
+ zeitsperretyp_kurzbz: 'Arzt',
+ vonstunde: null,
+ bisstunde: null
+ };
+ this.originalData = {};
+ },
+ handleChangeVonStunde(){
+ let stunde = this.zeitsperreData.vonstunde;
+ const result = this.listStunden.find(item => item.stunde === stunde);
+ if (!result) {
+ this.zeitsperreData.vonISO = '00:00:00';
+ return;
+ }
+ this.zeitsperreData.vonISO = result.beginn;
+ },
+ handleChangeBisStunde(){
+ let stunde = this.zeitsperreData.bisstunde;
+ const result = this.listStunden.find(item => item.stunde === stunde);
+ if (!result) {
+ this.zeitsperreData.bisISO = '23:59:59';
+ return;
+ }
+ this.zeitsperreData.bisISO = result.ende;
+ },
+ handleStunden(){
+ if (this.typesHideStunden.includes(this.zeitsperreData.zeitsperretyp_kurzbz)){
+ this.zeitsperreData.vonstunde = null;
+ this.zeitsperreData.bisstunde = null;
+ this.zeitsperreData.vonISO = '00:00:00';
+ this.zeitsperreData.bisISO = '23:59:59';
+ }
+ },
+ copyDateForBis(){
+ this.zeitsperreData.bisdatum = this.zeitsperreData.vondatum;
+ },
+ getChangedFields(original, current) {
+ const diff = {};
+
+ Object.keys(current).forEach((key) => {
+ if (current[key] !== original[key]) {
+ diff[key] = current[key];
+ }
+ });
+ return diff;
+ },
+ },
+ watch: {
+ selectedVertretung(newVal) {
+ this.zeitsperreData.vertretung_uid = newVal?.mitarbeiter_uid || null;
+ },
+ 'zeitsperreData.zeitsperretyp_kurzbz'(newVal) {
+ if (newVal === 'DienstV') {
+ // set first key as default
+ if (!this.zeitsperreData.bezeichnung) {
+ const firstKey = Object.keys(this.dienstverhinderungen)[0];
+ this.zeitsperreData.bezeichnung = firstKey;
+ }
+ } else {
+ this.zeitsperreData.bezeichnung = '';
+ }
+ }
+ },
+ created() {
+ this.$api.call(ApiAuthinfo.getAuthUID()).then(res => {
+
+ //check if there is a user, passed via route
+ const urlUid = this.$route?.query?.uid;
+ this.uid = urlUid ? urlUid : res.data.uid;
+
+ this.tabulatorOptions = {
+ ajaxURL: 'dummy',
+ ajaxRequestFunc: () =>
+ this.$api.call(ApiTimelocks.getTimelocksUser(this.uid)),
+ ajaxResponse: (url, params, response) => response.data,
+ columns: [
+ {title:"bezeichnung", field:"bezeichnung"},
+ {title:"Grund", field:"beschreibung"},
+ {title:"Von", field:"vondatum",
+ 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",
+ });
+ }
+ },
+ {title:"Bis", field:"bisdatum",
+ 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",
+ });
+ }
+ },
+ {title:"vonstunde", field:"vonstunde", visible: false},
+ {title:"bisstunde", field:"bisstunde", visible: false},
+ {title:"Vertretung", field:"vertretung"},
+ {title:"Erreichbarkeit", field:"erreichbarkeit_beschreibung"},
+ {title:"zeitsperre_id", field:"zeitsperre_id", visible: false},
+ {title:"mitarbeiter_uid", field:"mitarbeiter_uid", visible: false},
+ {title:"freigabeamum", field:"freigabeamum", visible: false,
+ formatter: function (cell) {
+ const value = cell.getValue();
+ return value === null
+ ? ''
+ : '';
+ }
+ },
+ {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 = '';
+ button.title = this.$p.t('ui', 'bearbeiten');
+ button.addEventListener('click', (event) =>
+ this.actionEditZeitsperre(cell.getData().zeitsperre_id)
+ );
+ if(cell.getData().zeitsperretyp_kurzbz == 'DienstV' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
+ button.disabled = true;
+ }
+ //TODO(Manu) check if needed
+ if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
+ button.disabled = true;
+ }
+ container.append(button);
+
+ button = document.createElement('button');
+ button.className = 'btn btn-outline-secondary btn-action';
+ button.innerHTML = '';
+ button.title = this.$p.t('ui', 'loeschen');
+ button.addEventListener('click', () =>
+ //this.deleteZeitsperre(cell.getData().zeitsperre_id)
+ this.actionDeleteZeitsperre(cell.getData().zeitsperre_id)
+ );
+ if(cell.getData().zeitsperretyp_kurzbz == 'Urlaub' || cell.getData().zeitsperretyp_kurzbz == 'ZVerfueg'){
+ button.disabled = true;
+ }
+ //TODO(Manu) check if needed
+ if(this.typesTimeLocks.includes(cell.getData().zeitsperretyp_kurzbz) && (cell.getData().vondatum < this.timeRecordingLockedUntil)){
+ button.disabled = true;
+ }
+ container.append(button);
+
+ return container;
+ },
+ frozen: true
+ },
+ ]
+ };
+ this.tabulatorEvents = [
+ {
+ event: 'tableBuilt',
+ handler: async() => {
+ await this.$p.loadCategory(['global', 'person', 'zeitsperren', 'ui', 'abschlusspruefung']);
+
+ let cm = this.$refs.table.tabulator.columnManager;
+
+ cm.getColumnByField('bezeichnung').component.updateDefinition({
+ title: this.$p.t('person', 'grund')
+ });
+ cm.getColumnByField('beschreibung').component.updateDefinition({
+ title: this.$p.t('global', 'bezeichnung')
+ });
+ cm.getColumnByField('vondatum').component.updateDefinition({
+ title: this.$p.t('ui', 'von')
+ });
+ cm.getColumnByField('bisdatum').component.updateDefinition({
+ title: this.$p.t('global', 'bis')
+ });
+ cm.getColumnByField('vonstunde').component.updateDefinition({
+ title: this.$p.t('zeitsperren', 'stunde_von')
+ });
+ cm.getColumnByField('bisstunde').component.updateDefinition({
+ title: this.$p.t('zeitsperren', 'stunde_bis')
+ });
+ cm.getColumnByField('vertretung').component.updateDefinition({
+ title: this.$p.t('person', 'vertretung')
+ });
+
+ cm.getColumnByField('erreichbarkeit_beschreibung').component.updateDefinition({
+ title: this.$p.t('person', 'erreichbarkeit')
+ });
+ cm.getColumnByField('freigabeamum').component.updateDefinition({
+ title: this.$p.t('abschlusspruefung', 'freigabe')
+ });
+
+ /* cm.getColumnByField('actions').component.updateDefinition({
+ title: this.$p.t('global', 'aktionen')
+ });*/
+
+ }
+ }
+ ];
+ });
+
+ this.$api
+ .call(ApiTimelocks.getTypenZeitsperren())
+ .then(result => {
+ this.listTypenZeitsperren = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ this.$api
+ .call(ApiTimelocks.getTypenErreichbarkeit())
+ .then(result => {
+ this.listTypenErreichbarkeit = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ this.$api
+ .call(ApiTimelocks.getStunden())
+ .then(result => {
+ this.listStunden = result.data;
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+
+ },
+ template: /* html */`
+
+
{{$p.t('zeitsperren', 'header_zeitsperren')}} ({{uid}})
+
+
+
+
+
+
+
+
+ Dienstfreistellungen nur in Absprache mit HR Service eintragen!
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{$p.t('alert', 'attention')}}
+ {{$p.t('zeitsperren', 'info_zeitsperrenMoreDays')}}
+
+
+
+
+
+
+
+
+
+ `
+};
\ No newline at end of file
diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php
index 8a159dbdc..1ff99a819 100644
--- a/system/phrasesupdate.php
+++ b/system/phrasesupdate.php
@@ -60788,6 +60788,468 @@ I have been informed that I am under no obligation to consent to the transmissio
)
),
//**************************** Pruefungsprotokolle end
+ //// ### ZEITSPERREN START
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'eheschliessung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Eigene Eheschließung oder Verpartnerung (3 Tage)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Own marriage or civil partnership (3 days)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'geburt',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Geburt eines Kindes der Ehefrau/Lebensgefährtin (2 Tage)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Birth of a child of the wife/partner (2 days)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'heirat',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Eheschließung oder Verpartnerung eines Kindes/eigener Geschwister (1 Tag)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Marriage or civil partnership of a child or own sibling (1 day)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'sponsion',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Teilnahme an eigener Sponsion/Promotion (1 Tag)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Participation in own graduation/promotion ceremony (1 day)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'erkrankung_lebensbedr',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Lebensbedrohliche Erkrankung Partner/Kinder/Eltern (3 Tage)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Life-threatening illness of partner/children/parents (3 days)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'ableben',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Ableben Partner/Kinder/Elternteil (3 Tage)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Death of partner/children/parent (3 days)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'bestattung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Teilnahme an Bestattung Geschwister/Schwiegereltern/eigener Großeltern (1 Tag)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Attendance at the funeral of siblings/parents-in-law/own grandparents (1 day)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'umzug',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Wohnungswechsel in eigenen Haushalt (2 Tage)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Moving to your own home (2 days)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'bundesheer',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Einberufung Bundesheer',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Conscription of the Austrian Armed Forces',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'volksschultag',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'erster Volksschultag (1 Tag)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'First day of primary school (1 day)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'error_VonDatumGroesserAlsBisDatum',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'VonDatum ist größer als BisDatum',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'The start date is greater than the end date.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'error_zeitraumAuffallendHoch',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Achtung, eingegebener Zeitraum ist auffallend hoch. \nWollen Sie die Daten dennoch speichern?',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Attention, the entered time period is unusually long. Do you still want to save the data?',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'stunde',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Stunde(inklusive)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Hour(inclusive)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'stunde_von',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Stunde(von)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'hour(from)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'stunde_bis',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Stunde(bis)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'hour(to)',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'addZeitsperre',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Zeitsperre hinzufügen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'add Timelock',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'saveZeitsperre',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Zeitsperre speichern',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'save Timelock',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'noAdmin',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Für diese Aktion benötigen Sie Administratorenrechte',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'You need administrator rights to perform this action.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'ui',
+ 'phrase' => 'noPermission',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Sie haben keine Berechtigung, für einen anderen User einen Datensatz anzulegen, zu bearbeiten oder zu löschen',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'You do not have permission to create, edit, or delete a record for another user.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'info_zeitsperrenMoreDays',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Es werden alle eingegebenen Tage bei der Berechnung berücksichtigt. Daher müssen mehrtägige Zeitsperren an Unterbrechungen wie Wochenenden oder Feiertagen unterteilt werden!',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'All entered days will be included in the calculation. Therefore, multi-day time blocks must be broken down by breaks such as weekends or holidays!',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'header_zeitsperren',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Meine Zeitsperren',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'My timelocks',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'error_existingZeitaufzeichnung',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Es existiert mindestens eine Zeitaufzeichnung im angegebenen Zeitraum',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'At least one time recording exists within the specified period.',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ array(
+ 'app' => 'core',
+ 'category' => 'zeitsperren',
+ 'phrase' => 'error_existingZeitsperre',
+ 'insertvon' => 'system',
+ 'phrases' => array(
+ array(
+ 'sprache' => 'German',
+ 'text' => 'Zeitsperre vom Typ {typ} vorhanden',
+ 'description' => '',
+ 'insertvon' => 'system'
+ ),
+ array(
+ 'sprache' => 'English',
+ 'text' => 'Time lock of type {type} exists',
+ 'description' => '',
+ 'insertvon' => 'system'
+ )
+ )
+ ),
+ /// ### ZEITSPERREN END
);