new Core Component Function

- autocomplete and dropdown field for search oes and search functions with active and non active entries
- possibility to dynamic styling of display switch, newButton in Tabulator, different editLabels
- possibility to show/hide column company
- possibility to show/hide to save function as copy
This commit is contained in:
ma0068
2025-05-21 15:34:43 +02:00
parent 12415279d1
commit c26bb98960
12 changed files with 1891 additions and 608 deletions
@@ -0,0 +1,385 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
use \DateTime as DateTime;
class Funktionen extends FHCAPI_Controller
{
public function __construct()
{
//TODO(Manu) check permissions
parent::__construct(array(
'getAllFunctions' => ['admin:r', 'assistenz:r'],
'getContractFunctions' => ['admin:r', 'assistenz:r'],
'getCurrentFunctions' => ['admin:r', 'assistenz:r'],
'getAllUserFunctions' => ['admin:r', 'assistenz:r'],
'getOrgHeads' => ['admin:r', 'assistenz:r'],
'getOrgetsForCompany' => ['admin:r', 'assistenz:r'],
'loadAllOes' => ['admin:r', 'assistenz:r'],
'searchOes' => ['admin:r', 'assistenz:r'],
'searchFunctions' => ['admin:r', 'assistenz:r'],
'loadFunction' => ['admin:r', 'assistenz:r'],
'insertFunction' => ['admin:rw', 'assistenz:rw'],
'updateFunction' => ['admin:rw', 'assistenz:rw'],
'deleteFunction' => ['admin:rw', 'assistenz:rw'],
)
);
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
]);
// Load models
$this->load->model('extensions/FHC-Core-Personalverwaltung/Api_model', 'ApiModel');
$this->load->model('ressource/Funktion_model', 'FunktionModel');
$this->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel');
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
}
public function getOrgHeads()
{
$result = $this->OrganisationseinheitModel->getHeads();
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function getAllUserFunctions($uid)
{
if(!$uid)
{
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL);
}
$sql = "
SELECT
dv.dienstverhaeltnis_id,
un.bezeichnung || ' (' || TO_CHAR(dv.von, 'DD.MM.YYYY') || CASE WHEN dv.bis IS NOT NULL THEN ' - '
|| TO_CHAR(dv.bis, 'DD.MM.YYYY') ELSE '' END || ')' AS dienstverhaeltnis_unternehmen ,
'[' || oet.bezeichnung || '] ' || oe.bezeichnung AS funktion_oebezeichnung,
f.beschreibung AS funktion_beschreibung,
bf.*,
fb.bezeichnung AS fachbereich_bezeichnung,
CASE
WHEN
bf.datum_bis IS NOT NULL AND bf.datum_bis::date < now()::date
THEN
false
ELSE
true
END aktiv
FROM
public.tbl_benutzerfunktion bf
JOIN
public.tbl_organisationseinheit oe ON oe.oe_kurzbz = bf.oe_kurzbz
JOIN
public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz
JOIN
public.tbl_funktion f ON f.funktion_kurzbz = bf.funktion_kurzbz
LEFT JOIN
hr.tbl_vertragsbestandteil_funktion vf ON vf.benutzerfunktion_id = bf.benutzerfunktion_id
LEFT JOIN
hr.tbl_vertragsbestandteil v ON vf.vertragsbestandteil_id = v.vertragsbestandteil_id
LEFT JOIN
hr.tbl_dienstverhaeltnis dv ON v.dienstverhaeltnis_id = dv.dienstverhaeltnis_id
LEFT JOIN
public.tbl_organisationseinheit un ON dv.oe_kurzbz = un.oe_kurzbz
LEFT JOIN
public.tbl_fachbereich fb ON fb.fachbereich_kurzbz = bf.fachbereich_kurzbz
WHERE
bf.uid = ?
ORDER BY
f.beschreibung, bf.datum_von ASC";
$benutzerfunktionen = $this->BenutzerfunktionModel->execReadOnlyQuery($sql, array($uid));
$data = $this->getDataOrTerminateWithError($benutzerfunktionen);
$this->terminateWithSuccess($data);
}
//TODO(Manu) DELETE
public function DEPR_getCurrentFunctions($uid, $companyOrgetkurzbz)
{
$sql = "
SELECT
bf.benutzerfunktion_id, f.beschreibung || ', '
|| oe.bezeichnung || ' [' || oet.bezeichnung || '], '
|| COALESCE(to_char(bf.datum_von, 'dd.mm.YYYY'), 'n/a')
|| ' - ' || COALESCE(to_char(bf.datum_bis, 'dd.mm.YYYY'), 'n/a')
|| COALESCE(dvu.attachedtovb, '') AS label
FROM (
WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as
(
SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit
WHERE oe_kurzbz = ?
UNION ALL
SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes
WHERE o.oe_parent_kurzbz=oes.oe_kurzbz
)
SELECT oe_kurzbz
FROM oes
GROUP BY oe_kurzbz
) c
JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = c.oe_kurzbz
JOIN public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz
JOIN public.tbl_benutzerfunktion bf ON bf.oe_kurzbz = oe.oe_kurzbz
JOIN public.tbl_funktion f ON f.funktion_kurzbz = bf.funktion_kurzbz
LEFT JOIN (
SELECT
benutzerfunktion_id, ' [DV]' AS attachedtovb
FROM
hr.tbl_vertragsbestandteil_funktion
GROUP BY
benutzerfunktion_id
) dvu ON dvu.benutzerfunktion_id = bf.benutzerfunktion_id
WHERE bf.uid = ?
ORDER BY f.beschreibung ASC";
$benutzerfunktionen = $this->BenutzerfunktionModel->execReadOnlyQuery($sql, array( $companyOrgetkurzbz,$uid));
$data = $this->getDataOrTerminateWithError($benutzerfunktionen);
$this->terminateWithSuccess($data);
}
/*
* return list of child orgets for a given company orget_kurzbz
* as key value list to be used in select or autocomplete
*/
public function getOrgetsForCompany($companyOrgetkurzbz=null)
{
$sql = "
SELECT
oe.oe_kurzbz,
'[' || COALESCE(oet.bezeichnung, oet.organisationseinheittyp_kurzbz) ||
'] ' || COALESCE(oe.bezeichnung, oe.oe_kurzbz) AS label
FROM (
WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) as
(
SELECT oe_kurzbz, oe_parent_kurzbz FROM public.tbl_organisationseinheit
WHERE oe_kurzbz=?
UNION ALL
SELECT o.oe_kurzbz, o.oe_parent_kurzbz FROM public.tbl_organisationseinheit o, oes
WHERE o.oe_parent_kurzbz=oes.oe_kurzbz
)
SELECT oe_kurzbz
FROM oes
GROUP BY oe_kurzbz
) c
JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = c.oe_kurzbz
JOIN public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz
ORDER BY oet.bezeichnung ASC, oe.bezeichnung ASC";
$childorgets = $this->OrganisationseinheitModel->execReadOnlyQuery($sql, array($companyOrgetkurzbz));
$data = $this->getDataOrTerminateWithError($childorgets);
$this->terminateWithSuccess($data);
}
//TODO(Manu) DELETE
/*
* List of Oes for autocomplete field organisation unit
*/
public function DEPR_loadAllOes($filterStudent=false, $aktiv=true)
{
$sql = "
SELECT
oe_kurzbz,
CONCAT('[', organisationseinheittyp_kurzbz, '] ', bezeichnung) as label
FROM public.tbl_organisationseinheit
WHERE aktiv = ?";
if($filterStudent)
$sql .= " AND organisationseinheittyp_kurzbz in ('Studiengang','Lehrgang')";
$sql .= " ORDER BY organisationseinheittyp_kurzbz, bezeichnung";
$result = $this->OrganisationseinheitModel->execReadOnlyQuery($sql, array($aktiv));
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function searchOes($companyOrgetKurzbz, $searchString = null)
{
$result = $this->OrganisationseinheitModel->getAutocompleteSuggestionsWithCompany($companyOrgetKurzbz, $searchString);
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function searchFunctions($searchString = null)
{
$result = $this->FunktionModel->getAutocompleteSuggestions($searchString);
if (isError($result)) {
$this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
$this->terminateWithSuccess($result ?: []);
}
public function loadFunction($benutzerfunktion_id)
{
$this->BenutzerfunktionModel->addSelect("*");
$result = $this->BenutzerfunktionModel->loadWhere(
array('benutzerfunktion_id' => $benutzerfunktion_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess(current($data));
}
public function insertFunction()
{
$this->load->library('form_validation');
$authUID = getAuthUID();
$uid = $this->input->post('uid');
if(!$uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$datum_von = $formData['datum_von'] ?? null;
$datum_bis = $formData['datum_bis'] ?? null;
$formData['oe_kurzbz'] = is_array($formData['oe_kurzbz']) ? $formData['oe_kurzbz']['oe_kurzbz'] : $formData['oe_kurzbz'];
$formData['funktion_kurzbz'] = is_array($formData['funktion_kurzbz'])
? $formData['funktion_kurzbz']['funktion_kurzbz']
: $formData['funktion_kurzbz'];
$bezeichnung = $formData['bezeichnung'] ?? null;
$wochenstunden = $formData['wochenstunden'] ?? null;
$this->form_validation->set_data($formData);
$this->form_validation->set_rules('datum_von', '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('datum_bis', 'BisDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum'])
]);
$this->form_validation->set_rules('oe_kurzbz', 'Organisationseinheit', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Organisationseinheit'])
]);
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Funktion'])
]);
$this->form_validation->set_rules('wochenstunden', 'Wochenstunden', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Wochenstunden'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->BenutzerfunktionModel->insert([
'uid' => $uid,
'datum_von' => $datum_von,
'datum_bis' => $datum_bis ,
'oe_kurzbz' => $formData['oe_kurzbz'],
'funktion_kurzbz' => $formData['funktion_kurzbz'],
'bezeichnung' => $bezeichnung,
'wochenstunden' => $wochenstunden,
'insertamum' => date('c'),
'insertvon' => $authUID,
]);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function updateFunction()
{
$this->load->library('form_validation');
$authUID = getAuthUID();
$uid = $this->input->post('uid');
if(!$uid)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'UID']), self::ERROR_TYPE_GENERAL);
}
$benutzerfunktion_id = $this->input->post('benutzerfunktion_id');
if(!$benutzerfunktion_id)
{
return $this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Benutzerfunktion ID']), self::ERROR_TYPE_GENERAL);
}
$formData = $this->input->post('formData');
$datum_von = $formData['datum_von'] ?? null;
$datum_bis = $formData['datum_bis'] ?? null;
$formData['oe_kurzbz'] = is_array($formData['oe_kurzbz']) ? $formData['oe_kurzbz']['oe_kurzbz'] : $formData['oe_kurzbz'];
$formData['funktion_kurzbz'] = is_array($formData['funktion_kurzbz'])
? $formData['funktion_kurzbz']['funktion_kurzbz']
: $formData['funktion_kurzbz'];
$bezeichnung = $formData['bezeichnung'] ?? null;
$wochenstunden = $formData['wochenstunden'] ?? null;
$this->form_validation->set_data($formData);
$this->form_validation->set_rules('datum_von', '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('datum_bis', 'BisDatum', 'is_valid_date', [
'is_valid_date' => $this->p->t('ui', 'error_notValidDate', ['field' => 'BisDatum'])
]);
$this->form_validation->set_rules('oe_kurzbz', 'Organisationseinheit', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Organisationseinheit'])
]);
$this->form_validation->set_rules('funktion_kurzbz', 'Funktion', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Funktion'])
]);
$this->form_validation->set_rules('wochenstunden', 'Wochenstunden', 'numeric', [
'numeric' => $this->p->t('ui', 'error_fieldNotNumeric', ['field' => 'Wochenstunden'])
]);
if ($this->form_validation->run() == false)
{
$this->terminateWithValidationErrors($this->form_validation->error_array());
}
$result = $this->BenutzerfunktionModel->update(
[
'benutzerfunktion_id' => $benutzerfunktion_id,
],
[
'uid' => $uid,
'datum_von' => $datum_von,
'datum_bis' => $datum_bis ,
'oe_kurzbz' => $formData['oe_kurzbz'],
'funktion_kurzbz' => $formData['funktion_kurzbz'],
'bezeichnung' => $bezeichnung,
'wochenstunden' => $wochenstunden,
'updateamum' => date('c'),
'updatevon' => $authUID,
]
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
public function deleteFunction($benutzerfunktion_id)
{
$result = $this->BenutzerfunktionModel->delete(
array('benutzerfunktion_id' => $benutzerfunktion_id)
);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -132,6 +132,11 @@ class Config extends FHCAPI_Controller
'title' => $this->p->t('stv', 'tab_functions'),
'component' => './Stv/Studentenverwaltung/Details/Funktionen.js'
];
/* TODO(Manu) REMOVE just for Testing*/
$result['functions_composition'] = [
'title' => 'F_PV21',
'component' => './Stv/Studentenverwaltung/Details/FunktionenOld.js'
];
Events::trigger('stv_conf_student', function & () use (&$result) {
return $result;
@@ -217,4 +217,72 @@ class Organisationseinheit_model extends DB_Model
oe_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%'
");
}
/**
* Get OEs by eventQuery string and companyOrgetKurzbz
* Use with autocomplete event queries in Function Component
* @param $searchString String
* @param $companyOrgetKurzbz String oe_kurzbz of the company (gst vs gmbh)
* @return array
*/
public function getAutocompleteSuggestionsWithCompany($companyOrgetKurzbz, $searchString)
{
$sql = "
WITH RECURSIVE oes(oe_kurzbz, oe_parent_kurzbz) AS (
SELECT oe_kurzbz, oe_parent_kurzbz
FROM public.tbl_organisationseinheit
WHERE oe_kurzbz = ?
UNION ALL
SELECT o.oe_kurzbz, o.oe_parent_kurzbz
FROM public.tbl_organisationseinheit o
INNER JOIN oes ON o.oe_parent_kurzbz = oes.oe_kurzbz
)
SELECT
oe.oe_kurzbz, oe.aktiv,
'[' || COALESCE(oet.bezeichnung, oet.organisationseinheittyp_kurzbz) ||
'] ' || COALESCE(oe.bezeichnung, oe.oe_kurzbz) AS label
FROM (
SELECT oe_kurzbz FROM oes GROUP BY oe_kurzbz
) c
JOIN public.tbl_organisationseinheit oe ON oe.oe_kurzbz = c.oe_kurzbz
JOIN public.tbl_organisationseinheittyp oet ON oe.organisationseinheittyp_kurzbz = oet.organisationseinheittyp_kurzbz
";
$params = [$companyOrgetKurzbz];
if (!empty($searchString)) {
$escaped = $this->escapeLike($searchString);
$ilike = '%' . $escaped . '%';
$sql .= "
WHERE
oe.oe_kurzbz ILIKE ? OR
oe.bezeichnung ILIKE ? OR
oe.organisationseinheittyp_kurzbz ILIKE ?
";
$params[] = $ilike;
$params[] = $ilike;
$params[] = $ilike;
}
$sql .= " ORDER BY oet.bezeichnung ASC, oe.bezeichnung ASC";
$result = $this->execQuery($sql, $params);
return $result;
}
/**
* get highest organisation units
*/
public function getHeads()
{
$this->addSelect('*');
$this->addSelect('oe_kurzbz as head');
$result = $this->loadWhere(array('oe_parent_kurzbz' => null, 'aktiv' => true));
return $result;
}
}
@@ -11,4 +11,26 @@ class Funktion_model extends DB_Model
$this->dbTable = 'public.tbl_funktion';
$this->pk = 'funktion_kurzbz';
}
/**
* Get Functions by eventQuery string. Use with autocomplete event queries in Function Component
* @param $eventQuery String
* @return array
*/
public function getAutocompleteSuggestions($eventQuery)
{
$this->addSelect('funktion_kurzbz, beschreibung, aktiv');
$this->addSelect("beschreibung AS label");
$this->addOrder('beschreibung', 'ASC');
if($eventQuery === null)
{
return $this->load();
}
return $this->loadWhere("
funktion_kurzbz ILIKE '%". $this->escapeLike($eventQuery). "%'
OR beschreibung ILIKE '%". $this->escapeLike($eventQuery). "%'
");
}
}
+2 -1
View File
@@ -18,7 +18,8 @@
#datepicker fuer component functions
'public/css/components/vue-datepicker.css',
'public/css/components/primevue.css',
'public/css/Studentenverwaltung.css'
'public/css/Studentenverwaltung.css',
'public/css/components/function.css'
],
'customJSs' => [
'vendor/vuejs/vuedatepicker_js/vue-datepicker.iife.js'