Compare commits

...

68 Commits

Author SHA1 Message Date
Ivymaster 48b836c466 BUG: add fix for room deletion with attached sub rooms 2026-05-20 13:18:16 +02:00
Ivymaster 363cb90019 Add dedicated room req class, add tabulator backend sortings and other stuff 2026-05-20 13:01:24 +02:00
Ivymaster eca9b22f7d Add tristate filter in Room manager table, add parent room short code in vilesci legacy code 2026-05-07 13:35:50 +02:00
Ivymaster 667726e23b BUG: add fix for orgUnit dropdown filtering on roomManager view 2026-05-07 11:35:53 +02:00
Ivymaster f3f960ccc4 Add permission change on RoomManager overview link in navigation 2026-05-06 12:50:41 +02:00
Ivymaster 86b4ffabc4 Add minor styling change in legacy vilesci room management view 2026-05-06 11:43:51 +02:00
Ivymaster 081703e0f8 Add navigation component to RoomManager 2026-05-06 11:41:10 +02:00
Ivymaster 05814383d4 Add pagination and backend filtering for rooms in RoomManagerOverview component 2026-05-05 15:16:25 +02:00
Ivymaster a44d0f65b3 Add components and endpoints for room type CRD and room to room type relation CRD 2026-05-04 16:28:09 +02:00
Ivymaster fe507e4185 Add new endpoint and vuejs components for room managment 2026-04-29 13:08:33 +02:00
Andreas Österreicher 552faefa51 Merge branch 'feature-76108/microdegree_abschlussurkunde' 2026-04-27 08:55:08 +02:00
Harald Bamberger 954397f028 Merge branch 'feature-70376/Lohnguide' 2026-04-22 18:52:51 +02:00
Harald Bamberger 80faa61c91 Merge branch 'master' into feature-70376/Lohnguide 2026-04-22 18:46:57 +02:00
Werner Masik 961ede66a9 lohnguide db update changed 2026-04-22 18:40:22 +02:00
Andreas Österreicher 6fec8382b5 Merge branch 'feature-76554/Personalmeldung_alt_bei_Lehre_nicht_melderelevant_rausfiltern' 2026-04-22 09:15:23 +02:00
Andreas Österreicher 4eb076d115 Fixed Saving of Entwicklungsteam 2026-04-21 17:34:36 +02:00
Harald Bamberger 7427aa87ea Merge branch 'feature-76545/findAbgabenNewOrUpdatedSinceByAbgabedatumFixTimestampDateComparison' 2026-04-21 17:01:04 +02:00
Johann Hoffmann 85043e57db added missing parenthesis 2026-04-21 17:00:07 +02:00
Johann Hoffmann 5beddbccb4 changed the where clause to a simpler = CURRENT_DATE comparison -> works the same if the job runs daily and fetches updates of one day/date; has to be changed back in case we want to find updates in a range larger than 1 day in an interval larger than 1 day; 2026-04-21 14:18:45 +02:00
kindlm e2ae9b88c8 Merge remote-tracking branch 'origin/master' 2026-04-21 12:56:30 +02:00
kindlm ca3abf9154 Small Style-Fix in Testtool
To make headings stand out more clearly from the buttons
2026-04-21 12:56:02 +02:00
Alexei Karpenko f863c6d728 personalmeldung legacy system: melderelevant is checked for lehre, bugfix: lehre is correctly added if studiengang already has sws 2026-04-20 18:24:30 +02:00
Harald Bamberger 92a2053b42 Merge branch 'feature-40870/BUG_Studstatus_unpause_order_should_be_DESC' 2026-04-20 17:30:14 +02:00
kindlm 70602be54e SaveSort und Filter-Reset in RaumÜbersicht 2026-04-20 11:30:17 +02:00
kindlm dac71f597a Spalte Anmeldedatum in RT-Übersicht
Spalte Frage_ID in RT-Administration
JQuery und Tabelsorter aus Include in Service_Uebersicht
2026-04-20 11:24:59 +02:00
Johann Hoffmann 3a646ffe77 adapt AbgabeJob relevant queries so they compare with the pgsql date function CURRENT_DATE instead of NOW() to avoid the cutoff from uploads the happened "yesterday but more than 24 hours ago"; also added another "abgabedatum < CURRENT_DATE" condition, to avoid sending this exact case as updates 2 days in a row; 2026-04-20 11:06:06 +02:00
Harald Bamberger 98a10a2f55 Merge branch 'feature-69389/AbmeldungSTGL_Anzeige_mit_Studiengangskuerzel' 2026-04-17 12:37:49 +02:00
Harald Bamberger e48b94b858 studiengangskuerzel statt kurzbzlang 2026-04-17 12:35:55 +02:00
Andreas Österreicher 0ff29ba6af Merge branch 'epic-56039/LV-Evaluierung' 2026-04-16 13:22:40 +02:00
Harald Bamberger ba543448ae Merge branch 'bug-76260/StudVW_Messages_TinyMCE_Cursor_Jumping_TextInput' 2026-04-16 11:26:32 +02:00
Harald Bamberger f121f9b5a2 deactivate pagination - since potentially msg threads are not shown completely 2026-04-16 11:23:57 +02:00
Harald Bamberger 88b22f5490 revert to v-if to not render element when not necessary and use Vue.nextTick for dependent code 2026-04-15 17:02:58 +02:00
Harald Bamberger 4b7ee9abe1 Merge branch 'feature-70376/Lohnguide' 2026-04-15 15:52:12 +02:00
Cristina d499619cf3 Added phrase endedatumMussInZukunftLiegen 2026-04-15 13:39:06 +02:00
Cristina f489153ff3 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-04-15 12:25:05 +02:00
Cristina 9b79a07fa2 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-04-15 12:24:44 +02:00
Harald Bamberger 6ce14a25d7 Merge branch 'master' into feature-70376/Lohnguide 2026-04-15 11:49:26 +02:00
Werner Masik c701d92779 fix db_update 2026-04-15 11:15:10 +02:00
Werner Masik 73e03ba901 Gehaltstyp Überstundenpauschale und Sachbezug PKW 2026-04-15 10:44:03 +02:00
ma0068 95a7797ae9 delete unused apicall for mode modal
add editor.setContent to function getReplyData
readd loadReplyData and use v-show for visibleDiv for mode inSamePage
2026-04-14 15:46:34 +02:00
ma0048 3ce3eff022 fehlendes mapping hinzugefuegt 2026-04-14 09:30:45 +02:00
Andreas Österreicher 3a91b12f31 Merge branch 'epic-56039/LV-Evaluierung' 2026-04-13 10:39:00 +02:00
ma0048 ea0a249612 micro degree abschlussdokumente hinzugefuegt 2026-04-13 09:14:27 +02:00
ma0068 843894405e changes for NewDiv
remove Watcher for formData Fields
add predefault settings for tabulator fields
add setContent for Editor
change text for closing window/tab
show alertSuccess for sending Message just in case of inSamePage
2026-04-10 13:03:24 +02:00
ma0068 8fddbc3a32 delete watcher for formData fields, add setContent for loading Vorlage 2026-04-10 09:15:34 +02:00
Harald Bamberger b2538075ee use STV_TAGS_ENABLED config when preparing sql statement for students list to query tags only if enabled 2026-04-07 10:35:06 +02:00
Werner Masik 5c463c0866 add vordienstzeit to lohnguide 2026-04-06 22:25:13 +02:00
Werner Masik 423bbd95a6 add vordienstzeit to lohnguide 2026-04-06 22:25:12 +02:00
Cristina 386cc779bf Merge branch 'master' into epic-56039/LV-Evaluierung 2026-04-02 15:49:20 +02:00
Cristina 08c6d58a50 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-04-02 14:24:39 +02:00
Cristina 3f53c5feba Added: method getKFLByUID to get Kompetenzfeldleitung by UID 2026-04-02 14:23:59 +02:00
Andreas Österreicher 2c057aad58 Updated Startup Dump to Final 3.3 Version 2026-04-01 13:00:50 +02:00
Harald Bamberger 627a52e3d1 Merge branch 'master' into feature-70376/Lohnguide 2026-03-25 09:36:27 +01:00
Harald Bamberger 059b13938e Merge branch 'master' into feature-70376/Lohnguide 2026-03-18 11:46:27 +01:00
Werner Masik 6b816def31 add lohnguide to vertragsbestandteil SQL 2026-03-05 15:34:51 +01:00
Werner Masik 5fbcf588ed fix vertragsbestandteil lohnguide 2026-03-05 14:29:56 +01:00
Werner Masik 41b2a6d1d4 added db migration for lohnguide 2026-03-04 10:53:30 +01:00
Werner Masik e054f1222b basic model and factory for lohnguide 2026-03-03 11:50:45 +01:00
Cristina c57eb1b8de Adapted method getLvLeitung: filter Dummy and allow only active Benutzer/Person 2026-03-02 11:00:05 +01:00
Cristina d1015956d1 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-02-25 10:54:29 +01:00
Cristina 726fce9fac Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-02-25 10:52:50 +01:00
Cristina 27a91de5f6 Added app lvevaluierung to system.tbl_app 2026-01-22 15:51:05 +01:00
Cristina 7ccc26c878 Added lvevaluierung phrasen for STGL Übersichtsseite 2026-01-22 15:41:25 +01:00
Cristina 9ebc847e8e Added lvevaluierung phrasen for Lektoren Übersichtsseite 2026-01-22 14:59:00 +01:00
Cristina 511b04c1f8 Merge branch 'master' into epic-56039/LV-Evaluierung 2026-01-21 18:01:55 +01:00
Cristina ec90d35e02 Merge branch 'master' of https://github.com/FH-Complete/FHC-Core 2026-01-21 18:01:24 +01:00
ma0068 38e8f91fdf add kurzbzlang to studentDropdown suggestion 2025-11-25 10:48:57 +01:00
cgfhtw d542cf7720 s&d 2024-08-14 16:20:47 +02:00
62 changed files with 11700 additions and 281 deletions
+17
View File
@@ -45,6 +45,14 @@ $config['navigation_header'] = array(
'expand' => true,
'sort' => 30,
'requiredPermissions' => 'admin:w'
),
'roomManagerOverview' => array(
'link' => site_url('RoomManager'),
'icon' => '',
'description' => 'Raumverwaltung',
'expand' => true,
'sort' => 40,
'requiredPermissions' => 'basis/ort:r'
)
)
),
@@ -383,3 +391,12 @@ $config['navigation_menu']['apps'] = [
'requiredPermissions' => array('lehre/lehrauftrag_bestellen:r', 'lehre/lehrauftrag_erteilen:r')
]
];
$config['navigation_menu']['RoomManager/index'] = array(
'lvTemplateUebersicht' => array(
'link' => site_url('RoomManager'),
'description' => 'Raumverwaltung übersicht',
'icon' => '',
'sort' => 1
)
);
+2
View File
@@ -122,6 +122,8 @@ $route['api/frontend/v1/stv/[sS]tudents/([WS]S[0-9]{4})/person/(:num)'] = 'api/f
// load routes from extensions, also look for environment-specific configs
$subdirs = ['application/config/extensions', 'application/config/' . ENVIRONMENT . '/extensions'];
$route['RoomManager/.*'] = 'RoomManager/index';
foreach($subdirs as $subdir)
{
if(is_dir($subdir))
+62
View File
@@ -0,0 +1,62 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
*/
class RoomManager extends Auth_Controller
{
private $_uid; // uid of the logged user
/**
* Constructor
*/
public function __construct()
{
parent::__construct(
array(
'index' => array('basis/ort:r')
)
);
$this->load->library('PermissionLib');
$this->load->library('AuthLib');
$this->loadPhrases(
array(
'ui',
'global',
'person',
'abschlusspruefung',
'password',
'lehre'
)
);
$this->_setAuthUID();
}
// -----------------------------------------------------------------------------------------------------------------
// Public methods
public function index()
{
return $this->load->view('room_manager/index', [
'permissions' => [
'basis/ort_w' => $this->permissionlib->isBerechtigt('basis/ort', 'suid'),
],
]);
}
// -----------------------------------------------------------------------------------------------------------------
// Private methods
/**
* Retrieve the UID of the logged user and checks if it is valid
*/
private function _setAuthUID()
{
$this->_uid = getAuthUID();
if (!$this->_uid) show_error('User authentification failed');
}
}
+320 -7
View File
@@ -31,21 +31,180 @@ class Ort extends FHCAPI_Controller
*/
public function __construct()
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
'getAllRooms' => array('basis/ort:r'),
'getRooms' => self::PERM_LOGGED,
'getTypes' => self::PERM_LOGGED,
'ContentID' => self::PERM_LOGGED,
'getOrtKurzbzContent' => self::PERM_LOGGED,
'getRooms' => self::PERM_LOGGED,
'getTypes' => self::PERM_LOGGED
'getRoom' => self::PERM_LOGGED,
'createRoom' => array('basis/ort:rw'),
'updateRoom' => array('basis/ort:rw'),
'deleteRoom' => array('basis/ort:rw'),
]);
$this->load->library('form_validation');
$this->load->library('requests/RoomRequest');
$this->load->model('ressource/Ort_model', 'OrtModel');
$this->load->model('ressource/Reservierung_model', 'ReservierungModel');
$this->config->load('raumsuche');
$this->loadPhrases([
'global',
'ui',
'lehre',
'gruppenmanagement',
'person',
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getAllRooms()
{
$paginationSize = $this->input->get('pagination[size]', TRUE);
$paginationPage = $this->input->get('pagination[page]', TRUE);
$filter = $this->input->get('filter', TRUE);
$filterData = [];
$query = "SELECT
COUNT(*) OVER() AS full_count,
public.tbl_ort.*,
org.bezeichnung as org_bezeichnung,
org.organisationseinheittyp_kurzbz as org_organisationseinheittyp_kurzbz
FROM public.tbl_ort
LEFT JOIN public.tbl_ort as pr ON pr.ort_kurzbz = public.tbl_ort.parent_ort_kurzbz
LEFT JOIN public.tbl_organisationseinheit as org ON org.oe_kurzbz = public.tbl_ort.oe_kurzbz";
$queryWhereFragments = [];
$searchableIdAttributes = ['standort_id', 'gebteil', 'oe_kurzbz'];
$searchableTextAttributes = ['ort_kurzbz', 'parent_ort_kurzbz', 'bezeichnung', 'planbezeichnung', 'oe_bezeichnung'];
$searchableBooleanAttributes = ['lehre', 'reservieren', 'aktiv'];
$searchableNumericAttributes = ['max_person', 'arbeitsplaetze', 'kosten', 'stockwerk'];
$searchableNumericSpanAttributes = ['m2'];
$searchableCustomAttributes = [
[
'raw_sql_fragment' => "CONCAT(public.tbl_ort.ort_kurzbz, ' - ', public.tbl_ort.bezeichnung)",
'filter_parameter' => 'ort_kurzbz_bezeichnung_concat',
],
[
'raw_sql_fragment' => "CONCAT('[', org.organisationseinheittyp_kurzbz, '] ', org.bezeichnung)",
'filter_parameter' => 'org_organisationseinheittyp_kurzbz_org_bezeichnung_concat',
]
];
foreach ($searchableIdAttributes as $attribute) {
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
$queryWhereFragments[] = "public.tbl_ort.$attribute = ?";
$filterData[] = trim($filter[$attribute]);
}
}
foreach ($searchableTextAttributes as $attribute) {
$tableAttribute = "public.tbl_ort.$attribute";
if ($attribute === 'oe_bezeichnung') {
$tableAttribute = "org.bezeichnung";
}
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
$queryWhereFragments[] = "$tableAttribute ILIKE ?";
$filterData[] = '%' . trim($filter[$attribute]) . '%';
}
}
foreach ($searchableBooleanAttributes as $attribute) {
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
$queryWhereFragments[] = "public.tbl_ort.$attribute = ?";
$filterData[] = $filter[$attribute] === 'true' ? true : false;
}
}
foreach ($searchableNumericAttributes as $attribute) {
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
$queryWhereFragments[] = "public.tbl_ort.$attribute = ?";
$filterData[] = trim($filter[$attribute]);
}
}
foreach ($searchableNumericSpanAttributes as $attribute) {
if (isset($filter[$attribute]) && $filter[$attribute] !== '') {
$queryWhereFragments[] = "public.tbl_ort.$attribute >= ? AND public.tbl_ort.$attribute <= ?";
$filterData[] = trim($filter[$attribute]) - 1;
$filterData[] = trim($filter[$attribute]) + 1;
}
}
foreach ($searchableCustomAttributes as $customAttribute) {
if (isset($filter[$customAttribute['filter_parameter']]) && $filter[$customAttribute['filter_parameter']] !== '') {
$queryWhereFragments[] = $customAttribute['raw_sql_fragment'] . " ILIKE ?";
$filterData[] = '%' . trim($filter[$customAttribute['filter_parameter']]) . '%';
}
}
if (count($queryWhereFragments) > 0) {
$query .= ' WHERE ' . implode(' AND ', $queryWhereFragments);
}
$sortableAttributes = ['ort_kurzbz', 'bezeichnung', 'planbezeichnung', 'max_person', 'arbeitsplaetze', 'm2', 'lehre', 'reservieren', 'aktiv', 'stockwerk', 'kosten', 'parent_ort_kurzbz', 'org_bezeichnung'];
$sortableConcatAttributes = [
[
'raw_sql_fragment' => "CONCAT('[', org.organisationseinheittyp_kurzbz, '] ', org.bezeichnung)",
'sort_parameter' => 'org_organisationseinheittyp_kurzbz_org_bezeichnung_concat',
]
];
$sorter = $this->input->get('sort', TRUE);
foreach ($sortableAttributes as $attribute) {
if (isset($sorter[$attribute]) && in_array(strtolower($sorter[$attribute]), ['asc', 'desc'])) {
if ($attribute === 'org_bezeichnung') {
$query .= " ORDER BY org.bezeichnung " . strtoupper($sorter[$attribute]);
} else {
$query .= " ORDER BY public.tbl_ort.$attribute " . strtoupper($sorter[$attribute]);
}
}
}
foreach ($sortableConcatAttributes as $customAttribute) {
if (isset($sorter[$customAttribute['sort_parameter']]) && in_array(strtolower($sorter[$customAttribute['sort_parameter']]), ['asc', 'desc'])) {
$query .= " ORDER BY " . $customAttribute['raw_sql_fragment'] . " " . strtoupper($sorter[$customAttribute['sort_parameter']]);
}
}
if (!isset($sorter)) {
$query .= ' ORDER BY public.tbl_ort.ort_kurzbz ASC';
}
if ($paginationSize && $paginationPage) {
$query .= " LIMIT ? OFFSET ?";
}
$queryData = array_merge($filterData);
if ($paginationSize && $paginationPage) {
$queryData = array_merge($filterData, [$paginationSize, ($paginationPage - 1) * $paginationSize]);
}
$result = $this->OrtModel->execReadOnlyQuery($query, $queryData);
$queryData = hasData($result) ? getData($result) : [];
if ($paginationSize && $paginationPage) {
$totalItems = count($queryData) > 0 ? $queryData[0]->full_count : 0;
$pageCount = ceil($totalItems / $paginationSize);
$this->addTabulatorPaginationData($pageCount);
}
$this->terminateWithSuccess($queryData);
}
/**
* Retrieves all Ort entries filtered by the provided parameters
*/
@@ -54,7 +213,7 @@ class Ort extends FHCAPI_Controller
$this->load->library('form_validation');
$this->form_validation->set_data($_GET);
$this->form_validation->set_rules('datum','Datum','required');
$this->form_validation->set_rules('von','Uhrzeit Von','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]');
$this->form_validation->set_rules('von','Uhrzeit Von','required|regexresponse_match[/^[0-9]{2}:[0-9]{2}$/]');
$this->form_validation->set_rules('bis','Uhrzeit Bis','required|regex_match[/^[0-9]{2}:[0-9]{2}$/]');
if($this->form_validation->run() == FALSE) {
$this->terminateWithValidationErrors($this->form_validation->error_array());
@@ -66,7 +225,6 @@ class Ort extends FHCAPI_Controller
$typ = $this->input->get('typ', TRUE);
$personenanzahl = $this->input->get('personenanzahl', TRUE);
$this->load->model('ressource/Mitarbeiter_model', 'MitarbeiterModel');
$isMitarbeiter = $this->MitarbeiterModel->isMitarbeiter(getAuthUID())->retval;
@@ -100,8 +258,7 @@ class Ort extends FHCAPI_Controller
)
";
$params = array_merge($params, [$datum, $vonStunde, $bisStunde, $datum, $vonStunde, $bisStunde]);
// $this->addMeta('qry', $qry);
// $this->addMeta('params', $params);
$result = $this->OrtModel->execReadOnlyQuery($qry, $params);
$this->terminateWithSuccess($result);
@@ -174,5 +331,161 @@ class Ort extends FHCAPI_Controller
$this->terminateWithSuccess($content);
}
public function getRoom($ort_kurzbz)
{
$result = $this->OrtModel->load($ort_kurzbz);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$result = hasData($result) ? current(getData($result)) : null;
return $this->terminateWithSuccess($result);
}
public function createRoom()
{
if (!$this->roomrequest->validate()) {
$this->terminateWithValidationErrors($this->roomrequest->errors());
return;
}
$this->db->trans_start();
$data = [
"parent_ort_kurzbz" => $this->input->post('parent_ort_kurzbz'),
"oe_kurzbz" => $this->input->post('oe_kurzbz'),
"content_id" => !empty($this->input->post('content_id')) ? $this->input->post('content_id') : null,
"standort_id" => $this->input->post('standort_id'),
"ort_kurzbz" => $this->input->post('ort_kurzbz'),
"bezeichnung" => $this->input->post('bezeichnung'),
"planbezeichnung" => $this->input->post('planbezeichnung'),
"aktiv" => $this->input->post('aktiv') ? true : false,
"lehre" => $this->input->post('lehre') ? true : false,
"reservieren" => $this->input->post('reservieren') ? true : false,
"max_person" => $this->input->post('max_person'),
"stockwerk" => $this->input->post('stockwerk'),
"lageplan" => $this->input->post('lageplan'),
"dislozierung" => $this->input->post('dislozierung'),
"kosten" => $this->input->post('kosten'),
"ausstattung" => $this->input->post('ausstattung'),
"telefonklappe" => $this->input->post('telefonklappe'),
"m2" => $this->input->post('m2'),
"gebteil" => $this->input->post('gebteil'),
"arbeitsplaetze" => $this->input->post('arbeitsplaetze'),
'insertamum' => date('c'),
'insertvon' => getAuthUid(),
'updateamum' => date('c'),
'updatevon' => getAuthUid()
];
$this->OrtModel->db->set($data);
$result = $this->OrtModel->db->insert($this->OrtModel->getDbTable());
$this->db->trans_complete();
return $this->terminateWithSuccess($result);
}
public function updateRoom($ort_kurzbz)
{
if (!$this->roomrequest->validate("update")) {
$this->terminateWithValidationErrors($this->roomrequest->errors());
return;
}
$this->db->trans_start();
$fields = [
"parent_ort_kurzbz",
"oe_kurzbz",
"content_id",
"standort_id",
"bezeichnung",
"planbezeichnung",
"aktiv",
"lehre",
"reservieren",
"max_person",
"stockwerk",
"lageplan",
"dislozierung",
"kosten",
"ausstattung",
"telefonklappe",
"m2",
"gebteil",
"arbeitsplaetze"
];
foreach ($fields as $field) {
if (array_key_exists($field, $this->input->post())) {
$data[$field] = $this->input->post($field);
}
}
$data['updateamum'] = date('c');
$data['updatevon'] = getAuthUid();
$this->OrtModel->db->set($data);
$this->OrtModel->db->where('ort_kurzbz', $ort_kurzbz);
$result = $this->OrtModel->db->update($this->OrtModel->getDbTable());
$this->db->trans_complete();
return $this->terminateWithSuccess($result);
}
public function deleteRoom($ort_kurzbz)
{
$this->db->trans_start();
$reservationsQuery = "SELECT COUNT(*) FROM campus.tbl_reservierung WHERE ort_kurzbz = ?";
$reservationsResult = $this->OrtModel->execReadOnlyQuery($reservationsQuery, [$ort_kurzbz]);
if (isError($reservationsResult)) {
$this->terminateWithError(getError($reservationsResult), self::ERROR_TYPE_GENERAL);
}
$reservationsCount = hasData($reservationsResult) ? getData($reservationsResult)[0]->count : 0;
if ($reservationsCount > 0) {
$this->terminateWithError($this->p->t('ui', 'error_existingReservationsForRoomsUponDeletion'), self::ERROR_TYPE_GENERAL);
}
$softwareImageOrtQuery = "SELECT COUNT(*) FROM extension.tbl_softwareimage_ort WHERE ort_kurzbz = ?";
$softwareImageOrtResult = $this->OrtModel->db->query($softwareImageOrtQuery, [$ort_kurzbz]);
if ($softwareImageOrtResult === false) {
$this->terminateWithError($this->p->t('ui', 'error_existingSoftwareImageForRoomTypeUponDeletion'), self::ERROR_TYPE_GENERAL);
}
$softwareImageOrtCount = $softwareImageOrtResult->row()->count;
if ($softwareImageOrtCount > 0) {
$this->terminateWithError($this->p->t('ui', 'error_existingSoftwareImageForRoomTypeUponDeletion'), self::ERROR_TYPE_GENERAL);
}
$subRoomsCountQuery = "SELECT COUNT(*) FROM public.tbl_ort WHERE parent_ort_kurzbz = ?";
$subRoomsCountQuery = $this->OrtModel->execReadOnlyQuery($subRoomsCountQuery, [$ort_kurzbz]);
$subRoomsCount = hasData($subRoomsCountQuery) ? getData($subRoomsCountQuery)[0]->count : 0;
if ($subRoomsCount > 0) {
$this->terminateWithError($this->p->t('ui', 'error_existingSubRoomsForRoomUponDeletion'), self::ERROR_TYPE_GENERAL);
}
$result = $this->OrtModel->delete([
"ort_kurzbz" => $ort_kurzbz
]);
if (isError($result)) {
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
$this->db->trans_complete();
return $this->terminateWithSuccess(true);
}
}
@@ -0,0 +1,123 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the SearchBarLib (back-end)
* Provides data to the ajax get calls about the searchbar component
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class RoomToRoomTypeApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
// NOTE(chris): additional permission checks will be done in SearchBarLib
parent::__construct([
'getRoomToRoomTypeRelationsByRoomShortCode' => array('basis/ort:r'),
'createRoomToRoomTypeRelation' => array('basis/ort:rw'),
'deleteRoomToRoomTypeRelation' => array('basis/ort:rw'),
]);
$this->load->library('form_validation');
$this->load->model('ressource/Ortraumtyp_model', 'OrtRoomTypeModel');
$this->loadPhrases([
'global',
'ui',
'lehre'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getRoomToRoomTypeRelationsByRoomShortCode($roomShortCode) {
$this->OrtRoomTypeModel->db->select('public.tbl_ortraumtyp.*, public.tbl_raumtyp.beschreibung as raumtyp_beschreibung');
$this->OrtRoomTypeModel->db->join('public.tbl_raumtyp', 'public.tbl_raumtyp.raumtyp_kurzbz = public.tbl_ortraumtyp.raumtyp_kurzbz', 'left');
$this->OrtRoomTypeModel->db->order_by('hierarchie', 'ASC');
$result = $this->OrtRoomTypeModel->loadWhere(['ort_kurzbz' => $roomShortCode]);
return $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
}
public function createRoomToRoomTypeRelation() {
$this->form_validation->set_rules('roomShortCode', 'roomShortCode', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'kurzbz')])
]);
$this->form_validation->set_rules('roomTypeShortCode', 'roomTypeShortCode', 'required', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'kurzbz')])
]);
$this->form_validation->set_rules('hierarchy', 'hierarchy', 'required|integer', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('ui', 'hierarchy')]),
'integer' => $this->p->t('ui', 'error_fieldInteger', ['field' => $this->p->t('ui', 'hierarchy')])
]);
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$existingRelationResponse = $this->OrtRoomTypeModel->loadWhere([
'ort_kurzbz' => $this->input->post('roomShortCode'),
'hierarchie' => $this->input->post('hierarchy'),
]);
if (hasData($existingRelationResponse)) {
$this->terminateWithError($this->p->t('ui', 'error_roomToRoomTypeRelationAlreadyExists'), self::ERROR_TYPE_GENERAL);
}
$data = [
'ort_kurzbz' => $this->input->post('roomShortCode'),
'raumtyp_kurzbz' => $this->input->post('roomTypeShortCode'),
'hierarchie' => $this->input->post('hierarchy'),
];
$this->OrtRoomTypeModel->db->set($data);
$result = $this->OrtRoomTypeModel->db->insert($this->OrtRoomTypeModel->getDbTable());
if ($result === false) {
return $this->terminateWithError($this->OrtRoomTypeModel->getLastError());
}
return $this->terminateWithSuccess(['message' => 'Room to Room Type relation created successfully.']);
}
public function deleteRoomToRoomTypeRelation() {
$this->form_validation->set_rules('roomShortCode', 'roomShortCode', 'required');
$this->form_validation->set_rules('roomTypeShortCode', 'roomTypeShortCode', 'required');
$this->form_validation->set_rules('hierarchy', 'hierarchy', 'required|integer');
if ($this->form_validation->run() === false) {
return $this->terminateWithError(validation_errors());
}
$result = $this->OrtRoomTypeModel->db->delete($this->OrtRoomTypeModel->getDbTable(), [
'ort_kurzbz' => $this->input->post('roomShortCode'),
'raumtyp_kurzbz' => $this->input->post('roomTypeShortCode'),
'hierarchie' => $this->input->post('hierarchy'),
]);
if ($result === false) {
return $this->terminateWithError($this->OrtRoomTypeModel->getLastError());
}
return $this->terminateWithSuccess(['message' => 'Room to Room Type relation deleted successfully.']);
}
}
@@ -0,0 +1,83 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
/**
* This controller operates between (interface) the JS (GUI) and the SearchBarLib (back-end)
* Provides data to the ajax get calls about the searchbar component
* This controller works with JSON calls on the HTTP GET and the output is always JSON
*/
class RoomTypeApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getAllRoomTypes' => array('basis/ort:r'),
'createRoomType' => array('basis/ort:rw'),
]);
$this->load->library('form_validation');
$this->load->model('ressource/Raumtyp_model', 'RoomTypeModel');
$this->loadPhrases([
'global',
'ui',
'lehre'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getAllRoomTypes() {
$this->RoomTypeModel->addOrder('raumtyp_kurzbz', 'ASC');
$result = $this->RoomTypeModel->load();
return $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
}
public function createRoomType() {
$this->form_validation->set_rules('kurzbezeichnung', 'kurzbezeichnung', 'required|max_length[255]|is_unique[tbl_raumtyp.raumtyp_kurzbz]', [
'required' => $this->p->t('ui', 'error_fieldRequired', ['field' => $this->p->t('lehre', 'kurzbz')]),
'is_unique' => $this->p->t('ui', 'error_fieldUnique', ['field' => $this->p->t('lehre', 'kurzbz')]),
]);
$this->form_validation->set_rules('beschreibung', 'beschreibung', 'max_length[255]');
if($this->form_validation->run() == FALSE) $this->terminateWithValidationErrors($this->form_validation->error_array());
$data = [
'raumtyp_kurzbz' => $this->input->post('kurzbezeichnung'),
'beschreibung' => $this->input->post('beschreibung'),
];
$this->RoomTypeModel->db->set($data);
$result = $this->RoomTypeModel->db->insert($this->RoomTypeModel->getDbTable());
if ($result === false) {
return $this->terminateWithError($this->RoomTypeModel->getLastError());
}
return $this->terminateWithSuccess();
}
}
@@ -42,14 +42,22 @@ class Messages extends FHCAPI_Controller
]);
}
public function getMessages($id, $type_id, $size, $page)
public function getMessages($id, $type_id, $size=null, $page=null)
{
if($type_id != 'person_id'){
$id = $this->_getPersonId($id, $type_id);
}
$offset = $size * ($page - 1);
$limit = $size;
if(!(is_null($size) && is_null($page)))
{
$offset = $size * ($page - 1);
$limit = $size;
}
else
{
$offset = null;
$limit = null;
}
$result = $this->MessageModel->getMessagesForTable($id, $offset, $limit);
@@ -0,0 +1,56 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class LocationApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getLocationsByCompanyType'=> self::PERM_LOGGED,
]);
$this->load->library('form_validation');
$this->load->model('organisation/standort_model', 'StandortModel');
$this->loadPhrases([
'global',
'ui',
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getLocationsByCompanyType() {
$companyType = $this->input->get('companyType');
if (!isset($companyType)) {
$this->terminateWithError('companyType parameter is required', REST_Controller::HTTP_BAD_REQUEST);
return;
}
$result = $this->StandortModel->getByCompanyType($companyType);
return $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
}
}
@@ -0,0 +1,55 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class OrganizationalUnitApi extends FHCAPI_Controller
{
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
'getAllOrganizationalUnits'=> array('basis/organisationseinheit:r'),
]);
$this->load->library('form_validation');
$this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
$this->loadPhrases([
'global'
]);
}
//------------------------------------------------------------------------------------------------------------------
// Public methods
public function getAllOrganizationalUnits()
{
$entitledOrganizationalUnitsShortCodes = $this->permissionlib->getOE_isEntitledFor('basis/organisationseinheit');
$this->OrganisationseinheitModel->db->where_in('oe_kurzbz', $entitledOrganizationalUnitsShortCodes);
$result = $this->OrganisationseinheitModel->load();
$organization_units_result = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($organization_units_result);
}
}
@@ -626,7 +626,7 @@ class Students extends FHCAPI_Controller
$this->addFilter($studiensemester_kurzbz);
$result = $this->PrestudentModel->loadWhere($where);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
@@ -851,40 +851,44 @@ class Students extends FHCAPI_Controller
$stdsemEsc = $studiensemester_kurzbz ? $this->PrestudentModel->escape($studiensemester_kurzbz) : 'NULL';
$this->load->config('stv');
$tags = $this->config->item('stv_prestudent_tags');
$whereTags = '';
if (is_array($tags) && !isEmptyArray($tags)) {
$tags = array_keys($tags);
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$tags = $this->config->item('stv_prestudent_tags');
foreach ($tags as $key => $tag) {
$tags[$key] = $this->db->escape($tag);
$whereTags = '';
if (is_array($tags) && !isEmptyArray($tags)) {
$tags = array_keys($tags);
foreach ($tags as $key => $tag) {
$tags[$key] = $this->db->escape($tag);
}
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
}
$whereTags = " AND nt.typ_kurzbz IN (" . implode(",", $tags) . ")";
$subQueryTag = "
(
SELECT
tag.prestudent_id,
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (n.notiz_id)
n.notiz_id AS id,
nt.typ_kurzbz,
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
n.text AS notiz,
nt.style,
n.erledigt AS done,
nz.prestudent_id
FROM public.tbl_notizzuordnung AS nz
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz "
. $whereTags .
"
) AS tag
GROUP BY tag.prestudent_id
) AS tag_data_agg
";
}
$subQueryTag = "
(
SELECT
tag.prestudent_id,
COALESCE(json_agg(tag ORDER BY tag.done), '[]'::json) AS tags
FROM (
SELECT DISTINCT ON (n.notiz_id)
n.notiz_id AS id,
nt.typ_kurzbz,
array_to_json(nt.bezeichnung_mehrsprachig)->>0 AS beschreibung,
n.text AS notiz,
nt.style,
n.erledigt AS done,
nz.prestudent_id
FROM public.tbl_notizzuordnung AS nz
JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id
JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz "
. $whereTags .
"
) AS tag
GROUP BY tag.prestudent_id
) AS tag_data_agg
";
$this->PrestudentModel->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT');
$this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
@@ -907,11 +911,17 @@ class Students extends FHCAPI_Controller
AND ps.studiensemester_kurzbz=public.get_stdsem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')
AND ps.ausbildungssemester=public.get_absem_prestudent(tbl_prestudent.prestudent_id, ' . $stdsemEsc . ')', 'LEFT');
$this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$this->PrestudentModel->addJoin($subQueryTag, 'tag_data_agg.prestudent_id = tbl_prestudent.prestudent_id', 'LEFT');
}
$this->PrestudentModel->addSelect("b.uid");
$this->PrestudentModel->addSelect('tag_data_agg.tags');
if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED)
{
$this->PrestudentModel->addSelect('tag_data_agg.tags');
}
$this->PrestudentModel->addSelect('titelpre');
$this->PrestudentModel->addSelect('nachname');
$this->PrestudentModel->addSelect('vorname');
+5
View File
@@ -154,6 +154,11 @@ class FHCAPI_Controller extends Auth_Controller
$this->returnObj['meta'][$key] = $value;
}
public function addTabulatorPaginationData($lastPage = 1)
{
$this->returnObj['last_page'] = $lastPage;
}
/**
* @param string $key
* @return mixed
+1 -1
View File
@@ -128,7 +128,7 @@ class AntragLib
return $this->_ci->StudierendenantragstatusModel->resumeAntraegeForAbmeldungStgl($antrag_id);
}
// NOTE(chris): get last status that is not pause
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum');
$this->_ci->StudierendenantragstatusModel->addOrder('insertamum', 'DESC');
$this->_ci->StudierendenantragstatusModel->addLimit(1);
$result = $this->_ci->StudierendenantragstatusModel->loadWhere([
'studierendenantrag_id' => $antrag_id,
@@ -0,0 +1,104 @@
<?php
/**
* FH-Complete
*
* @package FHC-Helper
* @author FHC-Team
* @copyright Copyright (c) 2022 fhcomplete.net
* @license GPLv3
*/
if (! defined('BASEPATH')) exit('No direct script access allowed');
class CustomFormValidationLib extends CI_Form_validation
{
public function __construct($rules = array())
{
parent::__construct($rules);
$this->_ci =& get_instance();
}
function explicit_integer($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if (filter_var($value, FILTER_VALIDATE_INT) !== false) {
return true;
}
return false;
}
function explicit_numeric($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if (is_numeric($value)) {
return true;
}
return false;
}
function explicit_boolean($value)
{
if ($value === null) {
return true;
}
if ($value === '') {
return false;
}
if ($value === 'true' || $value === 'false' || $value === true || $value === false || $value === 1 || $value === 0) {
return true;
}
return false;
}
function does_exist($value, $params)
{
if ($value === null ) {
return true;
}
if ($value === '') {
return false;
}
$parts = explode('.', $params);
if (count($parts) !== 3) {
return false;
}
$subDatabase = $parts[0];
$table = $parts[1];
$field = $parts[2];
$result = $this->_ci->db->select('COUNT(*) as count')
->from("$subDatabase.$table")
->where($field, $value)
->get();
if ($result === false) {
return false;
}
return $result->row()->count > 0;
}
}
@@ -0,0 +1,92 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class RoomRequest
{
protected $_ci;
public function __construct()
{
$this->_ci =& get_instance();
$this->_ci->load->library('CustomFormValidationLib');
}
public function validate($method = 'create')
{
if ($method === 'create') {
$this->_ci->customformvalidationlib->set_rules('ort_kurzbz', 'kurzbezeichnung', 'required|is_unique[tbl_ort.ort_kurzbz]|max_length[16]|regex_match[/^[a-zA-Z0-9_.]+$/]', [
'required' => $this->_ci->p->t('ui', 'error_fieldRequired', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')]),
'is_unique' => $this->_ci->p->t('ui', 'error_fieldUnique', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung'), 'max' => 16]),
'regex_match' => $this->_ci->p->t('ui', 'error_fieldInvalidFormat', ['field' => $this->_ci->p->t('gruppenmanagement', 'kurzbezeichnung')])
]);
}
$this->_ci->customformvalidationlib->set_rules('parent_ort_kurzbz', 'parent_ort_kurzbz', 'does_exist[public.tbl_ort.ort_kurzbz]|max_length[16]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('ui', 'parentRoom')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'parentRoom'), 'max' => 16])
]);
$this->_ci->customformvalidationlib->set_rules('oe_kurzbz', 'oe_kurzbz', 'does_exist[public.tbl_organisationseinheit.oe_kurzbz]|max_length[32]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('lehre', 'organisationseinheit')]),
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('lehre', 'organisationseinheit'), 'max' => 32])
]);
$this->_ci->customformvalidationlib->set_rules('standort_id', 'standort_id', 'explicit_integer|does_exist[public.tbl_standort.standort_id]', [
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('person', 'standort')]),
]);
$this->_ci->customformvalidationlib->set_rules('content_id', 'content_id', 'explicit_integer|does_exist[campus.tbl_content.content_id]', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'contentId')]),
'does_exist' => $this->_ci->p->t('ui', 'error_entryDoesExists', ['entry' => $this->_ci->p->t('ui', 'contentId')])
]);
$this->_ci->customformvalidationlib->set_rules('lehre', 'lehre', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('ui', 'lehre')])
]);
$this->_ci->customformvalidationlib->set_rules('reservieren', 'reservieren', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('ui', 'reservieren')])
]);
$this->_ci->customformvalidationlib->set_rules('aktiv', 'aktiv', 'explicit_boolean', [
'explicit_boolean' => $this->_ci->p->t('ui', 'error_fieldBoolean', ['field' => $this->_ci->p->t('person', 'aktiv')])
]);
$this->_ci->customformvalidationlib->set_rules('bezeichnung', 'bezeichnung', 'max_length[64]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'bezeichnung'), 'max' => 64])
]);
$this->_ci->customformvalidationlib->set_rules('planbezeichnung', 'planbezeichnung', 'max_length[8]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'planbezeichnung'), 'max' => 8])
]);
$this->_ci->customformvalidationlib->set_rules('max_person', 'maxPerson', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'maxPersons')])
]);
$this->_ci->customformvalidationlib->set_rules('stockwerk', 'stockwerk', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'stockwerk')])
]);
$this->_ci->customformvalidationlib->set_rules('m2', 'm2', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'quadratmeter')])
]);
$this->_ci->customformvalidationlib->set_rules('dislozierung', 'dislozierung', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'dislozierung')])
]);
$this->_ci->customformvalidationlib->set_rules('kosten', 'kosten', 'explicit_numeric', [
'explicit_numeric' => $this->_ci->p->t('ui', 'error_fieldNumeric', ['field' => $this->_ci->p->t('ui', 'kosten')])
]);
$this->_ci->customformvalidationlib->set_rules('telefonklappe', 'telefonklappe', 'max_length[8]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('person', 'telefonklappe'), 'max' => 8])
]);
$this->_ci->customformvalidationlib->set_rules('gebteil', 'gebteil', 'max_length[32]', [
'max_length' => $this->_ci->p->t('ui', 'error_fieldMaxLength', ['field' => $this->_ci->p->t('ui', 'gebaudeteil'), 'max' => 32])
]);
$this->_ci->customformvalidationlib->set_rules('arbeitsplaetze', 'arbeitsplaetze', 'explicit_integer', [
'explicit_integer' => $this->_ci->p->t('ui', 'error_fieldInteger', ['field' => $this->_ci->p->t('ui', 'arbeitsplaetze')])
]);
return $this->_ci->customformvalidationlib->run();
}
public function errors()
{
return $this->_ci->customformvalidationlib->error_array();
}
}
@@ -3,6 +3,7 @@ namespace vertragsbestandteil;
use Exception;
use vertragsbestandteil\VertragsbestandteilStunden;
use vertragsbestandteil\VertragsbestandteilLohnguide;
/**
* Description of VertragsbestandteilFactory
@@ -22,6 +23,7 @@ class VertragsbestandteilFactory
const VERTRAGSBESTANDTEIL_URLAUBSANSPRUCH = 'urlaubsanspruch';
const VERTRAGSBESTANDTEIL_ZEITAUFZEICHNUNG = 'zeitaufzeichnung';
const VERTRAGSBESTANDTEIL_LEHRE = 'lehre';
const VERTRAGSBESTANDTEIL_LOHNGUIDE = 'lohnguide';
public static function getVertragsbestandteil($data, $fromdb=false)
{
@@ -69,6 +71,11 @@ class VertragsbestandteilFactory
$vertragsbestandteil = new VertragsbestandteilZeitaufzeichnung();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
$vertragsbestandteil = new VertragsbestandteilLohnguide();
$vertragsbestandteil->hydrateByStdClass($data, $fromdb);
break;
default:
throw new Exception('Unknown vertragsbestandteiltyp_kurzbz '
@@ -127,6 +134,12 @@ class VertragsbestandteilFactory
$vertragsbestandteildbmodel = $CI->VertragsbestandteilZeitaufzeichnung_model;
break;
case self::VERTRAGSBESTANDTEIL_LOHNGUIDE:
$CI->load->model('vertragsbestandteil/VertragsbestandteilLohnguide_model',
'VertragsbestandteilLohnguide_model');
$vertragsbestandteildbmodel = $CI->VertragsbestandteilLohnguide_model;
break;
default:
throw new Exception('Unknown vertragsbestandteil_kurzbz '
. $vertragsbestandteil_kurzbz);
@@ -10,6 +10,7 @@ require_once __DIR__ . '/VertragsbestandteilKuendigungsfrist.php';
require_once __DIR__ . '/VertragsbestandteilUrlaubsanspruch.php';
require_once __DIR__ . '/VertragsbestandteilFreitext.php';
require_once __DIR__ . '/VertragsbestandteilKarenz.php';
require_once __DIR__ . '/VertragsbestandteilLohnguide.php';
require_once __DIR__ . '/VertragsbestandteilFactory.php';
require_once __DIR__ . '/OverlapChecker.php';
@@ -0,0 +1,155 @@
<?php
namespace vertragsbestandteil;
use vertragsbestandteil\Vertragsbestandteil;
use vertragsbestandteil\VertragsbestandteilFactory;
class VertragsbestandteilLohnguide extends Vertragsbestandteil
{
protected $stellenbezeichnung;
protected $vordienstzeit;
protected $fachrichtung_kurzbz;
protected $modellstelle_kurzbz;
protected $kommentar_person;
protected $kommentar_modellstelle;
public function __construct()
{
parent::__construct();
$this->setVertragsbestandteiltyp_kurzbz(
VertragsbestandteilFactory::VERTRAGSBESTANDTEIL_LOHNGUIDE);
}
public function getStellenbezeichnung()
{
return $this->stellenbezeichnung;
}
public function setStellenbezeichnung($stellenbezeichnung): self
{
$this->markDirty('stellenbezeichnung', $this->stellenbezeichnung, $stellenbezeichnung);
$this->stellenbezeichnung = $stellenbezeichnung;
return $this;
}
public function getVordienstzeit()
{
return $this->vordienstzeit;
}
public function setVordienstzeit($vordienstzeit): self
{
$this->markDirty('vordienstzeit', $this->vordienstzeit, $vordienstzeit);
$this->vordienstzeit = $vordienstzeit;
return $this;
}
public function getFachrichtung_kurzbz()
{
return $this->fachrichtung_kurzbz;
}
public function setFachrichtung_kurzbz($fachrichtung_kurzbz): self
{
$this->markDirty('fachrichtung_kurzbz', $this->fachrichtung_kurzbz, $fachrichtung_kurzbz);
$this->fachrichtung_kurzbz = $fachrichtung_kurzbz;
return $this;
}
public function getModellstelle_kurzbz()
{
return $this->modellstelle_kurzbz;
}
public function setModellstelle_kurzbz($modellstelle_kurzbz): self
{
$this->markDirty('modellstelle_kurzbz', $this->modellstelle_kurzbz, $modellstelle_kurzbz);
$this->modellstelle_kurzbz = $modellstelle_kurzbz;
return $this;
}
public function getKommentar_person()
{
return $this->kommentar_person;
}
public function setKommentar_person($kommentar_person): self
{
$this->markDirty('kommentar_person', $this->kommentar_person, $kommentar_person);
$this->kommentar_person = $kommentar_person;
return $this;
}
public function getKommentar_modellstelle()
{
return $this->kommentar_modellstelle;
}
public function setKommentar_modellstelle($kommentar_modellstelle): self
{
$this->markDirty('kommentar_modellstelle', $this->kommentar_modellstelle, $kommentar_modellstelle);
$this->kommentar_modellstelle = $kommentar_modellstelle;
return $this;
}
public function hydrateByStdClass($data, $fromdb=false)
{
parent::hydrateByStdClass($data, $fromdb);
$this->fromdb = $fromdb;
isset($data->fachrichtung_kurzbz) && $this->setFachrichtung_kurzbz($data->fachrichtung_kurzbz);
isset($data->stellenbezeichnung) && $this->setStellenbezeichnung($data->stellenbezeichnung);
isset($data->vordienstzeit) && $this->setVordienstzeit($data->vordienstzeit);
isset($data->modellstelle_kurzbz) && $this->setModellstelle_kurzbz($data->modellstelle_kurzbz);
isset($data->kommentar_person) && $this->setKommentar_person($data->kommentar_person);
isset($data->kommentar_modellstelle) && $this->setKommentar_modellstelle($data->kommentar_modellstelle);
$this->fromdb = false;
}
public function toStdClass(): \stdClass
{
$tmp = array(
'vertragsbestandteil_id' => $this->getVertragsbestandteil_id(),
'stellenbezeichnung' => $this->getStellenbezeichnung(),
'vordienstzeit' => $this->getVordienstzeit(),
'fachrichtung_kurzbz' => $this->getFachrichtung_kurzbz(),
'modellstelle_kurzbz' => $this->getModellstelle_kurzbz(),
'kommentar_person' => $this->getKommentar_person(),
'kommentar_modellstelle' => $this->getKommentar_modellstelle(),
);
$tmp = array_filter($tmp, function($k) {
return in_array($k, $this->modifiedcolumns);
}, ARRAY_FILTER_USE_KEY);
return (object) $tmp;
}
public function __toString()
{
$txt = <<<EOTXT
modellstelle_kurzbz: {$this->getModellstelle_kurzbz()}
EOTXT;
return parent::__toString() . $txt;
}
/* public function validate()
{
if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 1,
'max_range' => 50
)
)
)) ) {
$this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
}
return parent::validate();
} */
}
@@ -402,14 +402,17 @@ class Lehrveranstaltung_model extends DB_Model
SELECT
vorname, nachname, mitarbeiter_uid, lehrfunktion_kurzbz
FROM
lehre.tbl_lehreinheit
lehre.tbl_lehreinheit le
JOIN lehre.tbl_lehreinheitmitarbeiter lema USING (lehreinheit_id)
JOIN public.tbl_benutzer b ON b.uid = lema.mitarbeiter_uid
JOIN public.tbl_person p using (person_id)
WHERE
tbl_lehreinheit.lehrveranstaltung_id= ?
AND tbl_lehreinheit.studiensemester_kurzbz = ?
le.lehrveranstaltung_id= ?
AND le.studiensemester_kurzbz = ?
AND lehrfunktion_kurzbz = 'LV-Leitung'
AND lema.mitarbeiter_uid NOT like '_Dummy%'
AND b.aktiv = TRUE
AND p.aktiv = TRUE
ORDER BY
lema.insertamum DESC
LIMIT 1
@@ -79,10 +79,10 @@ class Paabgabe_model extends DB_Model
JOIN public.tbl_benutzer ON (public.tbl_benutzer.uid = student_uid)
JOIN public.tbl_person USING (person_id)
WHERE (campus.tbl_paabgabe.insertamum >= NOW() - INTERVAL ?
OR campus.tbl_paabgabe.updateamum >= NOW() - INTERVAL ?)
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
WHERE (campus.tbl_paabgabe.insertamum::date = CURRENT_DATE - INTERVAL ?
OR campus.tbl_paabgabe.updateamum::date = CURRENT_DATE - INTERVAL ?)
AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
return $this->execQuery($query, [$interval, $interval, $relevantTypes]);
}
@@ -108,7 +108,7 @@ class Paabgabe_model extends DB_Model
JOIN public.tbl_person ON (public.tbl_benutzer.person_id = public.tbl_person.person_id)
WHERE campus.tbl_paabgabe.abgabedatum IS NOT NULL
AND campus.tbl_paabgabe.abgabedatum >= NOW() - INTERVAL ?";
AND campus.tbl_paabgabe.abgabedatum = CURRENT_DATE - INTERVAL ?";
if($relevantTypes !== null) {
$query .= " AND campus.tbl_paabgabe.paabgabetyp_kurzbz IN ?";
@@ -35,5 +35,15 @@ class Standort_model extends DB_Model
return $this->loadWhere(array("firma_id" => $firma_id));
}
public function getByCompanyType($companyType)
{
$query = "SELECT s.* FROM public.tbl_standort s
JOIN public.tbl_firma f ON s.firma_id = f.firma_id
JOIN public.tbl_adresse a ON s.adresse_id = a.adresse_id
WHERE f.firmentyp_kurzbz = ?;";
return $this->execReadOnlyQuery($query, [$companyType]);
}
}
@@ -594,7 +594,10 @@ class Studiengang_model extends DB_Model
$this->addSelect('p.prestudent_id');
$this->addSelect('pers.vorname');
$this->addSelect('pers.nachname');
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', " . $this->dbTable . ".bezeichnung, ')') AS name");
$this->addSelect("CONCAT(UPPER(pers.nachname), ' ', pers.vorname, ' (', "
. $this->dbTable . ".bezeichnung, ', ', "
. "UPPER(" . $this->dbTable . ".typ), "
. "UPPER(" . $this->dbTable . ".kurzbz),')') AS name");
$this->addJoin('public.tbl_prestudent p', 'studiengang_kz');
$this->addJoin(
@@ -261,6 +261,42 @@ class Benutzerfunktion_model extends DB_Model
}
/**
* Get active Kompetenzfeldleitung bei UID.
*
* @param $uid
* @return array|stdClass|null
*/
public function getKFLByUID($uid)
{
$query = '
SELECT
bf.uid,
bf.oe_kurzbz,
oe.organisationseinheittyp_kurzbz
FROM
public.tbl_benutzerfunktion bf
JOIN public.tbl_organisationseinheit oe USING (oe_kurzbz)
JOIN public.tbl_benutzer b USING (uid)
WHERE
b.uid = ?
AND b.aktiv = TRUE
AND funktion_kurzbz = \'Leitung\'
AND organisationseinheittyp_kurzbz = \'Kompetenzfeld\'
AND (datum_von IS NULL OR datum_von <= now())
AND (datum_bis IS NULL OR datum_bis >= now())
';
$parameters_array = array();
if (is_string($uid))
{
$parameters_array[] = $uid;
}
return $this->execQuery($query, $parameters_array);
}
public function insertBenutzerfunktion($Json)
{
unset($Json['benutzerfunktion_id']);
+6 -4
View File
@@ -242,6 +242,7 @@ class Message_model extends DB_Model
*/
public function getMessagesForTable($person_id, $offset, $limit)
{
$limitoffset = (!is_null($offset) && !is_null($limit)) ? 'limit ? offset ?' : '';
$sql = <<<EOSQL
with filtered_messages as (
select
@@ -310,11 +311,12 @@ class Message_model extends DB_Model
public.tbl_person pr on pr.person_id = fm.recipient_id
order by
m.insertamum DESC
limit ?
offset ?;
{$limitoffset}
EOSQL;
$parametersArray = array($person_id, $person_id, $limit, $offset);
$parametersArray = $limitoffset
? array($person_id, $person_id, $limit, $offset)
: array($person_id, $person_id);
$count = 0;
$data = $this->execQuery($sql, $parametersArray);
@@ -325,7 +327,7 @@ EOSQL;
$data = getData($data);
if($data)
{
$count = ceil($data[0]->total_msgs / $limit);
$count = is_null($limit) ? 1 : ceil($data[0]->total_msgs / $limit);
}
return success(['data' => $data, 'count' => $count]);
@@ -0,0 +1,11 @@
<?php
class VertragsbestandteilLohnguide_model extends DB_Model
{
public function __construct()
{
parent::__construct();
$this->dbTable = 'hr.tbl_vertragsbestandteil_lohnguide';
$this->pk = 'vertragsbestandteil_id';
}
}
@@ -37,7 +37,8 @@ class Vertragsbestandteil_model extends DB_Model
kf.arbeitgeber_frist, kf.arbeitnehmer_frist,
s.wochenstunden, s.teilzeittyp_kurzbz,
u.tage,
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice
z.zeitaufzeichnung, z.azgrelevant, z.homeoffice,
lg.stellenbezeichnung, lg.vordienstzeit, lg.fachrichtung_kurzbz, lg.modellstelle_kurzbz, lg.kommentar_person, lg.kommentar_modellstelle
FROM
hr.tbl_vertragsbestandteil v
LEFT JOIN
@@ -63,6 +64,8 @@ class Vertragsbestandteil_model extends DB_Model
hr.tbl_vertragsbestandteil_urlaubsanspruch u USING(vertragsbestandteil_id)
LEFT JOIN
hr.tbl_vertragsbestandteil_zeitaufzeichnung z USING(vertragsbestandteil_id)
LEFT JOIN
hr.tbl_vertragsbestandteil_lohnguide lg USING(vertragsbestandteil_id)
EOSQL;
return $sql;
}
+41
View File
@@ -0,0 +1,41 @@
<?php
$includesArray = array(
'title' => ucfirst($this->p->t('ui', 'roomManagerPageTitle')),
'vue3' => true,
'axios027' => true,
'bootstrap5' => true,
'tabulator5' => true,
'fontawesome6' => true,
'primevue3' => true,
'navigationcomponent' => true,
'filtercomponent' => true,
'vuedatepicker11' => true,
'customJSs' => array(
'vendor/moment/luxonjs/luxon.min.js'
),
'customJSModules' => array(
'public/js/apps/RoomManagerApp.js'
),
'customCSSs' => array(
'public/css/components/primevue.css',
'public/css/components/verticalsplit.css',
'public/extensions/FHC-Core-Developer/css/FhcMain.css',
'public/css/components/calendar.css',
'public/css/components/vue-datepicker.css',
'public/css/roomManagerOverview.css'
)
);
$this->load->view('templates/FHC-Header', $includesArray);
?>
<div id="main">
<core-navigation-cmpt></core-navigation-cmpt>
<router-view
cis-root="<?= CIS_ROOT; ?>"
:permissions="<?= htmlspecialchars(json_encode($permissions)); ?>"
>
</router-view>
</div>
<?php $this->load->view('templates/FHC-Footer', $includesArray); ?>
+6 -4
View File
@@ -46,12 +46,13 @@ echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<link rel="stylesheet" href="../../../skin/tablesort.css" type="text/css"/>
<link rel="stylesheet" href="../../../skin/style.css.php" type="text/css">
<link rel="stylesheet" type="text/css" href="../../../skin/jquery-ui-1.9.2.custom.min.css">
<script type="text/javascript" src="../../../vendor/jquery/jquery1/jquery-1.12.4.min.js"></script>
<script type="text/javascript" src="../../../vendor/christianbach/tablesorter/jquery.tablesorter.min.js"></script>
<script type="text/javascript" src="../../../vendor/components/jqueryui/jquery-ui.min.js"></script>
<script type="text/javascript" src="../../../include/js/jquery.ui.datepicker.translation.js"></script>
<script type="text/javascript" src="../../../vendor/jquery/sizzle/sizzle.js"></script>';
include('../../../include/meta/jquery.php');
include('../../../include/meta/jquery-tablesorter.php');
const MOODLE_ADDON_KURZBZ = 'moodle';
// Load Addons to get Moodle_Path
@@ -71,7 +72,7 @@ echo '
$("#myTable").tablesorter(
{
sortList: [[0,0],[1,0]],
widgets: [\'zebra\']
widgets: [\'zebra\',\'filter\']
});
}
);
@@ -151,8 +152,9 @@ foreach($service->result as $row)
$person = new person();
$person->getPersonFromBenutzer($row->operativ_uid);
$operativ = $person->nachname.' '.$person->vorname;
$oeBez = new organisationseinheit($row->oe_kurzbz);
echo '<tr>';
echo '<td>',$row->oe_kurzbz,'</td>';
echo '<td>',$oeBez->bezeichnung,'</td>';
echo '<td><b>'.$row->bezeichnung.'</b></td>';
echo '<td>',$row->beschreibung,'</td>';
echo '<td><nobr><a href="../profile/index.php?uid='.$row->design_uid.'">',$design,'</a></nobr></td>';
+1 -1
View File
@@ -293,7 +293,7 @@ else if (isset($_SESSION['pruefling_id']))
}
$lastsemester = $row->semester;
echo '<table border="0" cellspacing="0" cellpadding="0" id="Gebiet" style="display: visible; border-collapse: separate; border-spacing: 0 3px;">';
echo '<table border="0" cellspacing="0" cellpadding="0" id="Gebiet" style="display: visible; border-collapse: separate; border-spacing: 0 3px; margin-top: 5px;">';
echo '<tr><td class="HeaderTesttool">'. ($row->semester == '1' ? $p->t('testtool/basisgebiete') : $p->t('testtool/quereinstiegsgebiete')).'</td></tr>';
}
@@ -342,6 +342,8 @@ echo '<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>';
<vbox>
<checkbox id="mitarbeiter-entwicklungsteam-detail-checkbox-neu" checked="true" hidden="true" />
<textbox id="mitarbeiter-entwicklungsteam-detail-textbox-studiengang" hidden="true" />
<textbox id="mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id" hidden="true" />
<groupbox id="mitarbeiter-entwicklungsteam-detail-groupbox" flex="1">
<caption label="Details" />
<grid id="mitarbeiter-entwicklungsteam-detail-grid" style="margin:4px;" flex="1">
@@ -1708,6 +1708,7 @@ function MitarbeiterEntwicklungsteamSelect()
document.getElementById('mitarbeiter-entwicklungsteam-detail-textbox-studiengang').value=studiengang_kz;
document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-beginn').value=beginn;
document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-ende').value=ende;
document.getElementById('mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id').value=entwicklungsteam_id;
MitarbeiterEntwicklungsteamDetailDisableFields(false);
}
@@ -1725,6 +1726,7 @@ function MitarbeiterEntwicklungsteamSpeichern()
studiengang_kz_old = document.getElementById('mitarbeiter-entwicklungsteam-detail-textbox-studiengang').value;
beginn = document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-beginn').value;
ende = document.getElementById('mitarbeiter-entwicklungsteam-detail-datum-ende').value;
entwicklungsteam_id = document.getElementById('mitarbeiter-entwicklungsteam-detail-entwicklungsteam_id').value;
if(studiengang_kz=='')
{
+8
View File
@@ -3555,6 +3555,14 @@ function StudentZeugnisDokumentArchivieren()
case 'microcredential_2':
case 'microcredential_3':
case 'microcredential_4':
case 'microdegree_1':
case 'microdegree_2':
case 'microdegree_3':
case 'microdegree_4':
case 'microdegreeabschluss_1':
case 'microdegreeabschluss_2':
case 'microdegreeabschluss_3':
case 'microdegreeabschluss_4':
xml = 'microcredential.xml.php';
break;
+3 -1
View File
@@ -364,9 +364,10 @@ class entwicklungsteam extends basis_db
$bismeldung_jahr = $datetime->format('Y');
//laden des Datensatzes
$qry = "SELECT *
$qry = "SELECT tbl_entwicklungsteam.*, tbl_besqual.*, tbl_studiengang.studiengang_kz, tbl_studiengang.melderelevant
FROM bis.tbl_entwicklungsteam
JOIN bis.tbl_besqual USING(besqualcode)
JOIN public.tbl_studiengang USING(studiengang_kz)
WHERE mitarbeiter_uid=".$this->db_add_param($mitarbeiter_uid)."
AND (beginn is NULL OR beginn <= make_date(". $this->db_add_param($bismeldung_jahr). "::INTEGER, 12, 31))
AND (ende is NULL OR ende >= make_date(". $this->db_add_param($bismeldung_jahr). "::INTEGER, 1, 1))";
@@ -394,6 +395,7 @@ class entwicklungsteam extends basis_db
$obj->insertvon = $row->insertvon;
$obj->ext_id = $row->ext_id;
$obj->besqual = $row->besqualbez;
$obj->melderelevant = $this->db_parse_bool($row->melderelevant);
$this->result[] = $obj;
}
+4 -2
View File
@@ -584,8 +584,9 @@ class lehreinheitmitarbeiter extends basis_db
$qry = '
WITH semester_sws_tbl AS (
SELECT DISTINCT lehreinheit_id, studiensemester_kurzbz, lema.semesterstunden,
stg.studiengang_kz, stg.melde_studiengang_kz, stg.lgartcode
SELECT
DISTINCT lehreinheit_id, studiensemester_kurzbz, lema.semesterstunden,
stg.studiengang_kz, stg.melde_studiengang_kz, stg.lgartcode, stg.melderelevant
FROM lehre.tbl_lehreinheitmitarbeiter lema
JOIN lehre.tbl_lehreinheit USING (lehreinheit_id)
JOIN lehre.tbl_lehrveranstaltung lv USING (lehrveranstaltung_id)
@@ -598,6 +599,7 @@ class lehreinheitmitarbeiter extends basis_db
AND ss.studiensemester_kurzbz IN ('.$this->implode4SQL($studiensemester_kurzbz_arr).')
-- nur lehre, die bisgemeldet wird
AND lema.bismelden
AND stg.melderelevant
-- keine lehreinheiten ohne semesterstunden
AND lema.semesterstunden != 0
)
+15 -5
View File
@@ -54,7 +54,7 @@ class ort extends basis_db
public $m2; // numeric(8,2)
public $gebteil; // varchar(32)
public $arbeitsplaetze; // integer
public $parent_ort_kurzbz; // varchar(16)
public $ort_kurzbz_old; // string
/**
@@ -117,6 +117,7 @@ class ort extends basis_db
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->gebteil = $row->gebteil;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
return true;
@@ -185,6 +186,7 @@ class ort extends basis_db
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->gebteil = $row->gebteil;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
return true;
@@ -232,6 +234,7 @@ class ort extends basis_db
$this->oe_kurzbz = $row->oe_kurzbz;
$this->m2 = $row->m2;
$this->arbeitsplaetze = $row->arbeitsplaetze;
$this->parent_ort_kurzbz = $row->parent_ort_kurzbz;
}
else
{
@@ -287,7 +290,7 @@ class ort extends basis_db
{
//Neuen Datensatz anlegen
$qry = 'INSERT INTO public.tbl_ort (ort_kurzbz, bezeichnung, planbezeichnung, max_person, aktiv, lehre, reservieren, lageplan,
dislozierung, kosten, stockwerk, standort_id, telefonklappe, insertamum, insertvon, updateamum, updatevon, content_id,ausstattung,m2,gebteil,oe_kurzbz,arbeitsplaetze) VALUES ('.
dislozierung, kosten, stockwerk, standort_id, telefonklappe, insertamum, insertvon, updateamum, updatevon, content_id,ausstattung,m2,gebteil,oe_kurzbz,arbeitsplaetze,parent_ort_kurzbz) VALUES ('.
$this->db_add_param($this->ort_kurzbz).', '.
$this->db_add_param($this->bezeichnung).', '.
$this->db_add_param($this->planbezeichnung).', '.
@@ -310,7 +313,8 @@ class ort extends basis_db
$this->db_add_param($this->m2).','.
$this->db_add_param($this->gebteil).','.
$this->db_add_param($this->oe_kurzbz).','.
$this->db_add_param($this->arbeitsplaetze).');';
$this->db_add_param($this->arbeitsplaetze).','.
$this->db_add_param($this->parent_ort_kurzbz).');';
}
else
{
@@ -337,7 +341,8 @@ class ort extends basis_db
'm2='.$this->db_add_param($this->m2).', '.
'gebteil='.$this->db_add_param($this->gebteil).', '.
'oe_kurzbz='.$this->db_add_param($this->oe_kurzbz).', '.
'arbeitsplaetze='.$this->db_add_param($this->arbeitsplaetze).' '.
'arbeitsplaetze='.$this->db_add_param($this->arbeitsplaetze).', '.
'parent_ort_kurzbz='.$this->db_add_param($this->parent_ort_kurzbz).' '.
'WHERE ort_kurzbz = '.$this->db_add_param(($this->ort_kurzbz_old!='')?$this->ort_kurzbz_old:$this->ort_kurzbz).';';
}
@@ -455,7 +460,8 @@ class ort extends basis_db
$ort_obj->gebteil = $row->gebteil;
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
return true;
@@ -523,6 +529,7 @@ class ort extends basis_db
$ort_obj->gebteil = $row->gebteil;
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
@@ -577,6 +584,8 @@ class ort extends basis_db
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->gebteil = $row->gebteil;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
return true;
@@ -634,6 +643,7 @@ class ort extends basis_db
$ort_obj->oe_kurzbz = $row->oe_kurzbz;
$ort_obj->gebteil = $row->gebteil;
$ort_obj->arbeitsplaetze = $row->arbeitsplaetze;
$ort_obj->parent_ort_kurzbz = $row->parent_ort_kurzbz;
$this->result[] = $ort_obj;
}
return true;
+41
View File
@@ -0,0 +1,41 @@
html {
font-size: .75em;
}
nav.navbar.navbar-header,
nav.navbar.navbar-left-side {
font-size: 18px
}
nav.navbar.navbar-left-side {
padding-top: 8px;
padding-bottom: 8px;
}
/* Relative sizing inside navbar */
nav.navbar .nav-item {
font-size: 18px
}
nav.navbar .navbar-brand-icon {
font-size: 16px
}
nav.navbar .left-side-menu-link-entry {
font-size: 14px !important;
}
nav.navbar .nav-link {
font-size: 18px;
padding-top: 15px;
padding-bottom: 8px;
}
nav.navbar .dropdown-menu {
padding: 8px 0px;
}
nav.navbar .dropdown-item {
font-size: 16px;
padding: 4px 16px;
}
+10
View File
@@ -0,0 +1,10 @@
export default {
getLocationsByCompanyType(companyType) {
return {
method: 'get',
url: '/api/frontend/v1/organisation/LocationApi/getLocationsByCompanyType',
params: { companyType }
};
}
};
+8 -5
View File
@@ -17,13 +17,16 @@
export default {
getMessages(params) {
let url = 'api/frontend/v1/messages/messages/getMessages'
+ '/' + params.id
+ '/' + params.type;
if(params.size && params.page) {
url += '/' + params.size
+ '/' + params.page;
}
return {
method: 'get',
url: 'api/frontend/v1/messages/messages/getMessages/'
+ params.id + '/'
+ params.type + '/'
+ params.size + '/'
+ params.page
url: url
};
},
getVorlagen(){
@@ -0,0 +1,8 @@
export default {
getAllOrganizationalUnits() {
return {
method: "get",
url: "api/frontend/v1/organisation/organizationalUnitApi/getAllOrganizationalUnits",
};
},
}
+69 -2
View File
@@ -16,11 +16,52 @@
*/
export default {
getContentID(ort_kurbz) {
getAllRooms(params) {
return {
method: 'get',
url: 'api/frontend/v1/Ort/getAllRooms',
params: {
"filter[oe_kurzbz]" : params?.organizationalUnitShortCode,
"filter[standort_id]" : params?.locationId,
"filter[gebteil]" : params?.buildingComponent,
"filter[lehre]" : params?.isForTrainingProgram,
"filter[reservieren]" : params?.isReservationNeeded,
"filter[aktiv]" : params?.isActive,
"filter[ort_kurzbz]" : params?.shortCode,
"filter[bezeichnung]" : params?.description,
"filter[planbezeichnung]" : params?.planDescription,
"filter[max_person]" : params?.maxPersons,
"filter[arbeitsplaetze]" : params?.workplace,
"filter[m2]" : params?.squareMeters,
"filter[org_organisationseinheittyp_kurzbz_org_bezeichnung_concat]" : params?.orgUnitConcatDescription,
"filter[kosten]" : params?.costs,
"filter[stockwerk]" : params?.floor,
"filter[parent_ort_kurzbz]" : params?.parentRoomShortCode,
"filter[ort_kurzbz_bezeichnung_concat]" : params?.ort_kurzbz_bezeichnung_concat,
"sort[ort_kurzbz]" : params?.sort?.ort_kurzbz,
"sort[bezeichnung]" : params?.sort?.bezeichnung,
"sort[planbezeichnung]" : params?.sort?.planbezeichnung,
"sort[max_person]" : params?.sort?.max_person,
"sort[arbeitsplaetze]" : params?.sort?.arbeitsplaetze,
"sort[m2]" : params?.sort?.m2,
"sort[org_organisationseinheittyp_kurzbz_org_bezeichnung_concat]" : params?.sort?.org_organisationseinheittyp_kurzbz_org_bezeichnung_concat,
"sort[lehre]" : params?.sort?.lehre,
"sort[reservieren]" : params?.sort?.reservieren,
"sort[aktiv]" : params?.sort?.aktiv,
"sort[kosten]" : params?.sort?.kosten,
"sort[stockwerk]" : params?.sort?.stockwerk,
"sort[parent_ort_kurzbz]" : params?.sort?.parent_ort_kurzbz,
"pagination[page]" : params?.pagination?.page,
"pagination[size]" : params?.pagination?.size,
}
}
},
getContentID(ort_kurzbz) {
return {
method: 'get',
url: '/api/frontend/v1/Ort/ContentID',
params: { ort_kurzbz: ort_kurbz }
params: { ort_kurzbz: ort_kurzbz }
};
},
getRooms(datum, von, bis, typ, personenanzahl = 0) {
@@ -30,11 +71,37 @@ export default {
params: { datum, von, bis, typ, personenanzahl }
};
},
getRoom(ort_kurzbz) {
return {
method: 'get',
url: '/api/frontend/v1/Ort/getRoom/' + ort_kurzbz,
};
},
getRoomTypes() {
return {
method: 'get',
url: '/api/frontend/v1/Ort/getTypes',
params: { }
};
},
createRoom(roomData) {
return {
method: 'post',
url: '/api/frontend/v1/Ort/createRoom',
params: roomData
}
},
updateRoom(roomId, roomData) {
return {
method: 'post',
url: '/api/frontend/v1/Ort/updateRoom/' + roomId,
params: roomData
}
},
deleteRoom(ort_kurzbz) {
return {
method: 'post',
url: '/api/frontend/v1/Ort/deleteRoom/' + ort_kurzbz,
}
}
};
+47
View File
@@ -0,0 +1,47 @@
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export default {
getRoomToRoomTypeRelationsByRoomShortCode(roomShortCode) {
return {
method: 'get',
url: `api/frontend/v1/RoomToRoomTypeApi/getRoomToRoomTypeRelationsByRoomShortCode/${roomShortCode}`,
}
},
createRoomToRoomTypeRelation(roomShortCode, roomTypeShortCode, hierarchy) {
return {
method: 'post',
url: `api/frontend/v1/RoomToRoomTypeApi/createRoomToRoomTypeRelation`,
params: {
roomShortCode,
roomTypeShortCode,
hierarchy
},
}
},
deleteRoomToRoomTypeRelation(roomShortCode, roomTypeShortCode, hierarchy) {
return {
method: 'post',
url: `api/frontend/v1/RoomToRoomTypeApi/deleteRoomToRoomTypeRelation`,
params: {
roomShortCode,
roomTypeShortCode,
hierarchy
},
}
}
};
+32
View File
@@ -0,0 +1,32 @@
/**
* Copyright (C) 2025 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
export default {
getAllRoomTypes() {
return {
method: 'get',
url: 'api/frontend/v1/RoomTypeApi/getAllRoomTypes',
}
},
createRoomType(roomTypeData) {
return {
method: 'post',
url: 'api/frontend/v1/RoomTypeApi/createRoomType',
params: roomTypeData,
}
},
};
+57
View File
@@ -0,0 +1,57 @@
/**
* Copyright (C) 2023 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import RoomManagerOverview from "../components/RoomManager/RoomManagerOverview.js";
import {CoreNavigationCmpt} from '../components/navigation/Navigation.js';
import FhcAlert from "../plugins/FhcAlert.js";
import Phrasen from "../plugins/Phrasen.js";
import FhcApi from "../plugins/Api.js";
import {capitalize} from "../helpers/StringHelpers.js";
const ciPath =
FHC_JS_DATA_STORAGE_OBJECT.app_root.replace(/(https:|)(^|\/\/)(.*?\/)/g, "") +
FHC_JS_DATA_STORAGE_OBJECT.ci_router;
const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes: [
{
name: "overview",
path: `/${ciPath}/RoomManager`,
component: RoomManagerOverview,
},
],
});
const app = Vue.createApp({
components: {
RoomManagerOverview,
CoreNavigationCmpt
},
});
app.config.globalProperties.$capitalize = capitalize;
app.use(router)
.use(primevue.config.default, { zIndex: { overlay: 9999 } })
.use(FhcAlert)
.use(Phrasen)
.use(FhcApi)
.mount("#main");
@@ -133,6 +133,7 @@ export default {
return this.$api
.call(ApiMessages.getDataVorlage(vorlage_kurzbz))
.then(response => {
this.editor.setContent(response.data.text);
this.formData.body = response.data.text;
this.formData.subject = response.data.subject;
}).catch(this.$fhcAlert.handleSystemError);
@@ -203,24 +204,6 @@ export default {
},
},
watch: {
'formData.body': {
handler(newVal) {
const tinymcsVal = this.editor.getContent();
if (newVal && tinymcsVal != newVal) {
//Inhalt des Editors aktualisieren
this.editor.setContent(newVal);
}
}
},
'formData.vorlage_kurzbz': {
handler(newVal){
if (newVal && newVal != null) {
this.formData.subject = newVal;
return this.getDataVorlage(newVal);
}
}
},
messageId: {
immediate: true,
handler: async function (newMessageId) {
@@ -231,6 +214,7 @@ export default {
this.replyData = result.data;
if (this.replyData.length > 0) {
this.editor.setContent(this.replyData[0].replyBody);
this.formData.subject = this.replyData[0].replySubject;
this.formData.body = this.replyData[0].replyBody;
this.formData.relationmessage_id = newMessageId;
@@ -290,19 +274,6 @@ export default {
})
.catch(this.$fhcAlert.handleSystemError);
//case of reply
if(this.messageId) {
this.$api
.call(ApiMessages.getReplyData(this.messageId))
.then(result => {
this.replyData = result.data;
this.formData.subject = this.replyData[0].replySubject;
this.formData.body = this.replyData[0].replyBody;
this.formData.relationmessage_id = this.messageId;
})
.catch(this.$fhcAlert.handleSystemError);
}
},
async mounted() {
this.initTinyMCE();
@@ -64,7 +64,16 @@ export default {
target: this.$refs.editor.$refs.input, //Important: not selector: to enable multiple import of component
//height: 800,
//plugins: ['lists'],
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify',
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | link',
plugins: 'link',
link_context_toolbar: true,
automatic_uploads: true,
default_link_target: "_blank",
link_title: true,
target_list: [
{ title: 'New tab', value: '_blank' },
{ title: 'Same tab', value: '_self' }
],
style_formats: [
{title: 'Blocks', block: 'div'},
{title: 'Paragraph', block: 'p'},
@@ -98,7 +107,8 @@ export default {
return this.$api
.call(ApiMessages.sendMessage(this.typeId, data))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent'));
if(this.openMode == "inSamePage")
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSent'));
this.hideTemplate();
this.resetForm();
this.messageSent = true;
@@ -114,19 +124,17 @@ export default {
return this.$api
.call(ApiMessages.getDataVorlage(vorlage_kurzbz))
.then(response => {
this.editor.setContent(response.data.text);
this.formData.body = response.data.text;
this.formData.subject = response.data.subject;
}).catch(this.$fhcAlert.handleSystemError);
},
getPreviewText(){
console.log("subj" + this.formData.subject);
const data = new FormData();
data.append('data', JSON.stringify(this.formData.body));
data.append('ids', JSON.stringify(this.id));
console.log("subj" + this.formData.subject);
return this.$api
.call(ApiMessages.getPreviewText(
this.typeId, data))
@@ -195,6 +203,7 @@ export default {
.call(ApiMessages.getReplyData(messageId))
.then(result => {
this.replyData = result.data;
this.editor.setContent(this.replyData[0].replyBody);
this.formData.subject = this.replyData[0].replySubject;
this.formData.body = this.replyData[0].replyBody;
this.formData.relationmessage_id = messageId;
@@ -202,27 +211,6 @@ export default {
.catch(this.$fhcAlert.handleSystemError);
}
},
watch: {
'formData.body': {
handler(newVal) {
const tinymcsVal = this.editor.getContent();
if (newVal && tinymcsVal != newVal) {
//Inhalt des Editors aktualisieren
this.editor.setContent(newVal);
}
}
},
'formData.vorlage_kurzbz': {
handler(newVal){
if (newVal && newVal != null) {
this.formData.subject = newVal;
return this.getDataVorlage(newVal);
}
}
},
},
created(){
const missingparamsmsgs = [];
if(!this.typeId)
@@ -291,17 +279,8 @@ export default {
.catch(this.$fhcAlert.handleSystemError);
//case of reply
if(this.messageId != null) {
if(this.messageId) {
this.loadReplyData(this.messageId);
/* this.$api
.call(ApiMessages.getReplyData(this.messageId))
.then(result => {
this.replyData = result.data;
this.formData.subject = this.replyData[0].replySubject;
this.formData.body = this.replyData[0].replyBody;
this.formData.relationmessage_id = this.messageId;
})
.catch(this.$fhcAlert.handleSystemError);*/
}
},
@@ -499,10 +478,10 @@ export default {
<div class="row">
<div class="col-6" style="border-right: 1px">
You can safely close this window.
You can safely close this window/tab.
</div>
<div class="col-6">
Sie können dieses Fenster schließen.
Fenster/Reiter kann geschlossen werden!
</div>
</div>
</div>
@@ -65,7 +65,14 @@ export default {
buildTreemap(messages) {
if (!messages || !messages.data || messages.data.length === 0)
{
return {data: [], last_page: 0};
if(this.tabulatorOptions.pagination)
{
return {data: [], last_page: 0};
}
else
{
return [];
}
}
const last_page = messages.meta.count;
@@ -106,7 +113,15 @@ export default {
// to avoid endless loop
if (iteration > messages.length) break;
}
return {data: messageNested, last_page: last_page};
if(this.tabulatorOptions.pagination)
{
return {data: messageNested, last_page: last_page};
}
else
{
return messageNested;
}
},
loadAjaxCall(url, config, params){
return this.$api.call(
@@ -252,7 +267,7 @@ export default {
frozen: true
}
],
pagination: true,
pagination: false,
paginationMode: "remote",
paginationSize: 15,
paginationInitialPage: 1,
+8 -6
View File
@@ -82,14 +82,16 @@ export default {
this.$refs.modalMsg.show();
}
else if (this.openMode == "inSamePage"){
console.log("in same Page");
this.isVisibleDiv = true;
if(messageId)
this.$refs.templateNewDivMessage.loadReplyData(messageId);
else
this.$refs.templateNewDivMessage.resetForm();
this.$refs.templateNewDivMessage.showTemplate();
this.$nextTick(() => {
if(messageId)
this.$refs.templateNewDivMessage.loadReplyData(messageId);
else
this.$refs.templateNewDivMessage.resetForm();
this.$refs.templateNewDivMessage.showTemplate();
});
}
else
console.log("no valid openMode");
@@ -0,0 +1,562 @@
import ApiRoom from "../../../js/api/factory/ort.js";
import ApiLocation from "../../../js/api/factory/location.js";
import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
import BsModal from "../Bootstrap/Modal.js";
import CoreForm from "../Form/Form.js";
import FormInput from "../Form/Input.js";
export default {
name: "RoomFormModal",
components: {
BsModal,
CoreForm,
FormInput,
},
props: {
isVisible: {
type: Boolean,
required: true,
},
editedRoomShortCode: {
type: String,
default: null,
},
},
emits: ["hideBsModal", "roomCreated", "roomUpdated"],
watch: {
isVisible(newValue) {
if (newValue) {
this.$refs.roomFormModal.show();
} else {
this.$refs.roomFormModal.hide();
}
},
editedRoomShortCode(newValue) {
if (newValue) {
this.editRoom(newValue);
} else {
this.resetRoomForm();
}
},
},
data: () => {
return {
isEditInProgress: false,
organizationalUnits: [],
filteredOrganizationalUnits: [],
locations: [],
rooms: [],
filteredRooms: [],
editedRoom: null,
roomFormData: {
aktiv: true,
},
};
},
computed: {
dropdownParsedOrganizationalUnits() {
return this.organizationalUnits.map((unit) => {
return {
label: `${unit.bezeichnung} (${unit.organisationseinheittyp_kurzbz})`,
value: unit.oe_kurzbz,
};
});
},
dropdownParsedRooms() {
return this.rooms.map((room) => {
let label = room.ort_kurzbz;
if (room.bezeichnung && room.bezeichnung !== '') {
label += ` - ${room.bezeichnung}`;
}
return {
label,
value: room.ort_kurzbz,
};
});
},
},
methods: {
filterOrganizationalUnits(event) {
let defaultItem = {
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
const query = event.query.toLowerCase();
if (!query) {
return (this.filteredOrganizationalUnits = [
defaultItem,
...this.dropdownParsedOrganizationalUnits,
]);
}
return (this.filteredOrganizationalUnits = [defaultItem].concat(
this.dropdownParsedOrganizationalUnits.filter((unit) => {
return unit.label.toLowerCase().includes(query);
}),
));
},
async filterRooms(event) {
this.rooms = await this.fetchRooms(event.query);
let defaultItem = {
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
const query = event.query.toLowerCase();
if (!query) {
return (this.filteredRooms = [
defaultItem,
...this.dropdownParsedRooms,
]);
}
return (this.filteredRooms = [defaultItem]
.concat(this.dropdownParsedRooms)
.filter((room) => {
return room.label?.toLowerCase().includes(query);
}));
},
createRoom() {
return this.$refs.roomForm
.call(ApiRoom.createRoom(this.getApiCallParsedRoomFormData()))
.then((response) => {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
this.$emit("roomCreated");
this.resetRoomForm();
this.hideRoomFormModal();
});
},
async editRoom(roomShortCode) {
let getLocationsResponse = await this.$api.call(
ApiRoom.getRoom(roomShortCode),
);
if (getLocationsResponse.meta.status === "success") {
this.editedRoom = getLocationsResponse.data;
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingRoomData"));
return;
}
this.isEditInProgress = true;
let orgUnitData = null;
let orgUnit = this.organizationalUnits.find(
(unit) => unit.oe_kurzbz === this.editedRoom.oe_kurzbz,
);
if (orgUnit) {
orgUnitData = {
label: `${orgUnit.bezeichnung} (${orgUnit.organisationseinheittyp_kurzbz})`,
value: orgUnit.oe_kurzbz,
};
}
let potentialParentRooms = await this.fetchRooms(
this.editedRoom.parent_ort_kurzbz,
);
let parentRoomData = null;
let parentRoom = potentialParentRooms.find(
(room) => room.ort_kurzbz === this.editedRoom.parent_ort_kurzbz,
);
if (parentRoom) {
this.rooms.push(parentRoom);
let label = parentRoom.ort_kurzbz;
if (parentRoom.bezeichnung && parentRoom.bezeichnung !== '') {
label += ` - ${parentRoom.bezeichnung}`;
}
parentRoomData = {
label,
value: parentRoom.ort_kurzbz,
};
}
this.roomFormData = {
parentRoom: parentRoomData,
locationId: this.editedRoom.standort_id,
organizationalUnit: orgUnitData,
contentId: this.editedRoom.content_id,
kurzbezeichnung: this.editedRoom.ort_kurzbz,
bezeichnung: this.editedRoom.bezeichnung,
planbezeichnung: this.editedRoom.planbezeichnung,
aktiv: this.editedRoom.aktiv,
lehre: this.editedRoom.lehre,
reservieren: this.editedRoom.reservieren,
maxPerson: this.editedRoom.max_person,
stockwerk: this.editedRoom.stockwerk,
lageplan: this.editedRoom.lageplan,
dislozierung: this.editedRoom.dislozierung,
kosten: this.editedRoom.kosten,
ausstattung: this.editedRoom.ausstattung,
telefonklappe: this.editedRoom.telefonklappe,
quadratmeter: this.editedRoom.m2,
gebaudeteil: this.editedRoom.gebteil,
arbeitsplaetze: this.editedRoom.arbeitsplaetze,
};
this.$refs.roomFormModal.show();
},
updateRoom() {
return this.$refs.roomForm
.call(
ApiRoom.updateRoom(
this.editedRoom.ort_kurzbz,
this.getApiCallParsedRoomFormData(),
),
)
.then((response) => {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
this.$emit("roomUpdated");
this.resetRoomForm();
this.hideRoomFormModal();
});
},
getApiCallParsedRoomFormData() {
return {
parent_ort_kurzbz: this.roomFormData.parentRoom?.value,
standort_id: this.roomFormData.locationId,
oe_kurzbz:
this.roomFormData.organizationalUnit?.value !== ""
? this.roomFormData.organizationalUnit?.value
: null,
content_id:
this.roomFormData.contentId !== ""
? this.roomFormData.contentId
: null,
ort_kurzbz: this.roomFormData.kurzbezeichnung,
bezeichnung: this.roomFormData.bezeichnung,
planbezeichnung: this.roomFormData.planbezeichnung,
aktiv: this.roomFormData.aktiv,
lehre: this.roomFormData.lehre,
reservieren: this.roomFormData.reservieren,
max_person:
this.roomFormData.maxPerson !== ""
? this.roomFormData.maxPerson
: null,
stockwerk:
this.roomFormData.stockwerk !== ""
? this.roomFormData.stockwerk
: null,
lageplan: this.roomFormData.lageplan,
dislozierung:
this.roomFormData.dislozierung === ""
? null
: this.roomFormData.dislozierung,
kosten:
this.roomFormData.kosten !== "" ? this.roomFormData.kosten : null,
ausstattung: this.roomFormData.ausstattung,
telefonklappe: this.roomFormData.telefonklappe,
m2:
this.roomFormData.quadratmeter !== ""
? this.roomFormData.quadratmeter
: null,
gebteil: this.roomFormData.gebaudeteil,
arbeitsplaetze:
this.roomFormData.arbeitsplaetze !== ""
? this.roomFormData.arbeitsplaetze
: null,
};
},
hideRoomFormModal() {
this.$refs.roomFormModal.hide();
this.$emit("hideBsModal");
this.resetRoomForm();
},
resetRoomForm() {
this.$refs.roomForm.clearValidation();
this.isEditInProgress = false;
this.editedRoom = null;
this.roomFormData = {
aktiv: true,
};
},
async fetchRooms(roomSearchTerm = "") {
let getRoomsResponse = await this.$api.call(
ApiRoom.getAllRooms({
ort_kurzbz_bezeichnung_concat: roomSearchTerm,
pagination: {
page: 1,
size: 100,
},
}),
);
if (getRoomsResponse.meta.status === "success") {
return getRoomsResponse.data;
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingRooms"));
}
return [];
},
setDefaultLocationOption() {
this.locations.unshift({
standort_id: null,
bezeichnung: this.$p.t("ui", "dropdownEmptyOption"),
});
},
},
async created() {
let getLocationsResponse = await this.$api.call(
ApiLocation.getLocationsByCompanyType("Intern"),
);
if (getLocationsResponse.meta.status === "success") {
this.locations = getLocationsResponse.data;
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingLocations"));
}
let getAllOrganizationalUnitsResponse = await this.$api.call(
ApiOrganizationalUnit.getAllOrganizationalUnits(),
);
if (getAllOrganizationalUnitsResponse.meta.status === "success") {
this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
(a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
);
} else {
this.$fhcAlert.alertError(
this.$p.t("ui", "errorLoadingOrganizationalUnits"),
);
}
this.rooms = await this.fetchRooms();
},
mounted() {
this.$p
.loadCategory([
"global",
"lehre",
"ui",
"gruppenmanagement",
"core",
"person",
])
.then(() => {
this.phrasesLoaded = true;
this.setDefaultLocationOption();
});
},
template: /* html */ `
<bs-modal ref="roomFormModal" size="sm" @hideBsModal="() => { $emit('hideBsModal'); resetRoomForm(); }" class="modal-lg">
<template #title>
<p v-if="!editedRoom" class="fw-bold mt-3">{{$capitalize($p.t('ui', 'createRoomModalTitle'))}}</p>
<p v-else class="fw-bold mt-3">{{$capitalize($p.t('ui', 'editRoomModalTitle'))}}</p>
</template>
<template #default>
<core-form ref="roomForm" class="row g-3 pb-3">
<div class="row mb-3">
<form-input
v-model="roomFormData.parentRoom"
:label="$capitalize($p.t('ui/parentRoom'))"
:suggestions="filteredRooms"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
:delay="500"
@complete="filterRooms"
dropdown
forceSelection
type="autocomplete"
name="parent_ort_kurzbz"
>
</form-input>
</div>
<div class="row mb-3">
<div class="col">
<form-input
v-model="roomFormData.organizationalUnit"
:label="$capitalize($p.t('lehre/organisationseinheit'))"
:suggestions="filteredOrganizationalUnits"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterOrganizationalUnits"
dropdown
forceSelection
type="autocomplete"
name="oe_kurzbz"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.locationId"
:label="$capitalize($p.t('person/standort'))"
type="select"
id="location"
name="standort_id"
>
<option
v-for="location in locations"
:key="location.standort_id"
:value="location.standort_id"
>
{{location.bezeichnung}}
</option>
</form-input>
</div>
</div>
<div class="row mb-3">
<div class="col">
<form-input
v-model="roomFormData.lehre"
:label="$capitalize($p.t('ui', 'lehre'))"
type="checkbox"
name="lehre"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.reservieren"
:label="$capitalize($p.t('ui', 'reservieren'))"
type="checkbox"
name="reservieren"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomFormData.aktiv"
:label="$capitalize($p.t('person', 'aktiv'))"
type="checkbox"
name="aktiv"
>
</form-input>
</div>
</div>
<div v-if='!this.editedRoom' class="row mb-3">
<form-input
v-model="roomFormData.kurzbezeichnung"
:label="$capitalize($p.t('gruppenmanagement', 'kurzbezeichnung'))"
type="text"
name="ort_kurzbz"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
v-model="roomFormData.bezeichnung"
:label="$capitalize($p.t('ui', 'bezeichnung'))"
type="text"
name="bezeichnung"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
v-model="roomFormData.planbezeichnung"
:label="$capitalize($p.t('ui', 'planbezeichnung'))"
type="text"
name="planbezeichnung"
>
</form-input>
</div>
<div class="row mb-3">
<div class="col">
<form-input
v-model.number="roomFormData.maxPerson"
:label="$capitalize($p.t('ui', 'maxPersons'))"
name="max_person"
>
</form-input>
</div>
<div class="col">
<form-input
v-model.number="roomFormData.stockwerk"
:label="$capitalize($p.t('ui', 'stockwerk'))"
name="stockwerk"
>
</form-input>
</div>
<div class="col">
<form-input
v-model.number="roomFormData.quadratmeter"
:label="$capitalize($p.t('ui', 'quadratmeter'))"
name="m2"
>
</form-input>
</div>
</div>
<div class="row mb-3">
<div class='col'>
<form-input
v-model="roomFormData.telefonklappe"
:label="$capitalize($p.t('person', 'telefonklappe'))"
name="telefonklappe"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model.number="roomFormData.arbeitsplaetze"
:label="$capitalize($p.t('ui', 'arbeitsplaetze'))"
name="arbeitsplaetze"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model="roomFormData.kosten"
:label="$capitalize($p.t('ui', 'kosten'))"
type="text"
name="kosten"
>
</form-input>
</div>
</div>
<div class="row mb-3">
<div class='col'>
<form-input
v-model="roomFormData.gebaudeteil"
:label="$capitalize($p.t('ui', 'gebaudeteil'))"
type="text"
name="gebteil"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model.number="roomFormData.contentId"
:label="$capitalize($p.t('ui', 'contentId'))"
name="content_id"
>
</form-input>
</div>
<div class='col'>
<form-input
v-model.number="roomFormData.dislozierung"
:label="$capitalize($p.t('ui', 'dislozierung'))"
name="dislozierung"
>
</form-input>
</div>
</div>
<div class="row mb-3">
<form-input
v-model="roomFormData.lageplan"
:label="$capitalize($p.t('ui', 'lageplan'))"
type="textarea"
name="lageplan"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
v-model="roomFormData.ausstattung"
:label="$capitalize($p.t('ui', 'ausstattung'))"
type="textarea"
name="ausstattung"
>
</form-input>
</div>
<div class="col d-flex justify-content-end gap-2">
<button type="button" class="btn btn-secondary" @click="hideRoomFormModal">{{$p.t('ui', 'abbrechen')}}</button>
<button type="button" class="btn btn-primary" @click="isEditInProgress ? updateRoom() : createRoom()">{{$p.t('ui', 'speichern')}}</button>
</div>
</core-form>
</template>
</bs-modal>
`,
};
@@ -0,0 +1,707 @@
import ApiRoom from "../../../js/api/factory/ort.js";
import ApiLocation from "../../../js/api/factory/location.js";
import ApiOrganizationalUnit from "../../../js/api/factory/organizationalUnit.js";
import { CoreFilterCmpt } from "../filter/Filter.js";
import CoreForm from "../Form/Form.js";
import FormInput from "../Form/Input.js";
import RoomFormModal from "./RoomFormModal.js";
import RoomTypeFormModal from "./RoomTypeFormModal.js";
export default {
name: "RoomManagerOverview",
components: {
CoreFilterCmpt,
CoreForm,
FormInput,
RoomFormModal,
RoomTypeFormModal,
},
props: {
permissions: Object,
},
provide() {
return {
cisRoot: this.cisRoot,
hasBasisOrtWPermission: this.permissions["basis/ort_w"] || false,
};
},
watch: {
filterData: {
handler(newValue) {
this.reloadTableData();
},
deep: true,
},
},
data() {
return {
phrasesLoaded: false,
filterData: {
locationId: null,
organizationalUnit: null,
buildingComponent: null,
isForTrainingProgram: null,
isReservationNeeded: null,
isActive: null,
},
locations: [],
organizationalUnits: [],
filteredOrganizationalUnits: [],
buildingComponents: [
{
label: "A",
value: "A",
},
{
label: "B",
value: "B",
},
{
label: "C",
value: "C",
},
{
label: "D",
value: "D",
},
{
label: "E",
value: "E",
},
{
label: "F",
value: "F",
},
],
isRoomFormModalVisible: false,
isRoomTypeFormModalVisible: false,
editedRoomShortCode: null,
editedRoomForRoomTypeManagement: null,
};
},
computed: {
hasBasisOrtWPermission() {
return this.permissions["basis/ort_w"] || false;
},
tabulatorOptions() {
const options = {
ajaxURL: "dummy",
ajaxRequestFunc: async (url, config, params) => {
let shortCodeFilter = params?.filter?.find(
(filter) => filter.field === "ort_kurzbz",
);
let descriptionFilter = params?.filter?.find(
(filter) => filter.field === "bezeichnung",
);
let planDescriptionFilter = params?.filter?.find(
(filter) => filter.field === "planbezeichnung",
);
let maxPersonsFilter = params?.filter?.find(
(filter) => filter.field === "max_person",
);
let workplaceFilter = params?.filter?.find(
(filter) => filter.field === "arbeitsplaetze",
);
let squareMetersFilter = params?.filter?.find(
(filter) => filter.field === "m2",
);
let orgUnitConcatFilter = params?.filter?.find(
(filter) => filter.field === "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat",
);
let isForTrainingProgramFilter = params?.filter?.find(
(filter) => filter.field === "lehre",
);
let reservationNeededFilter = params?.filter?.find(
(filter) => filter.field === "reservieren",
);
let isActiveFilter = params?.filter?.find(
(filter) => filter.field === "aktiv",
);
let costsFilter = params?.filter?.find(
(filter) => filter.field === "kosten",
);
let floorFilter = params?.filter?.find(
(filter) => filter.field === "stockwerk",
);
let parentRoomFilter = params?.filter?.find(
(filter) => filter.field === "parent_ort_kurzbz",
);
let isForTrainingProgramValue = null;
if (this.filterData.isForTrainingProgram === true) {
isForTrainingProgramValue = true;
} else {
if (isForTrainingProgramFilter?.value === true) {
isForTrainingProgramValue = true;
} else if (isForTrainingProgramFilter?.value === false) {
isForTrainingProgramValue = false;
}
}
let reservationNeededValue = null;
if (this.filterData.isReservationNeeded === true) {
reservationNeededValue = true;
} else {
if (reservationNeededFilter?.value === true) {
reservationNeededValue = true;
} else if (reservationNeededFilter?.value === false) {
reservationNeededValue = false;
}
}
let isActiveValue = null;
if (this.filterData.isActive === true) {
isActiveValue = true;
} else {
if (isActiveFilter?.value === true) {
isActiveValue = true;
} else if (isActiveFilter?.value === false) {
isActiveValue = false;
}
}
let shortCodeSorter = params?.sort?.find((sort) => sort.field === "ort_kurzbz");
let descriptionSorter = params?.sort?.find((sort) => sort.field === "bezeichnung");
let planDescriptionSorter = params?.sort?.find((sort) => sort.field === "planbezeichnung");
let maxPersonsSorter = params?.sort?.find((sort) => sort.field === "max_person");
let workplaceSorter = params?.sort?.find((sort) => sort.field === "arbeitsplaetze");
let squareMetersSorter = params?.sort?.find((sort) => sort.field === "m2");
let orgUnitConcatSorter = params?.sort?.find((sort) => sort.field === "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat");
let lehreSorter = params?.sort?.find((sort) => sort.field === "lehre");
let reservierenSorter = params?.sort?.find((sort) => sort.field === "reservieren");
let aktivSorter = params?.sort?.find((sort) => sort.field === "aktiv");
let costsSorter = params?.sort?.find((sort) => sort.field === "kosten");
let floorSorter = params?.sort?.find((sort) => sort.field === "stockwerk");
let parentRoomSorter = params?.sort?.find((sort) => sort.field === "parent_ort_kurzbz");
return this.$api.call(
ApiRoom.getAllRooms({
organizationalUnitShortCode:
this.filterData.organizationalUnit?.value,
locationId: this.filterData.locationId,
buildingComponent: this.filterData.buildingComponent,
isForTrainingProgram: isForTrainingProgramValue,
isReservationNeeded: reservationNeededValue,
isActive: isActiveValue,
shortCode: shortCodeFilter?.value,
description: descriptionFilter?.value,
planDescription: planDescriptionFilter?.value,
maxPersons: maxPersonsFilter?.value,
workplace: workplaceFilter?.value,
squareMeters: squareMetersFilter?.value,
orgUnitConcatDescription: orgUnitConcatFilter?.value,
costs: costsFilter?.value,
floor: floorFilter?.value,
parentRoomShortCode: parentRoomFilter?.value,
sort: {
ort_kurzbz: shortCodeSorter?.dir,
bezeichnung: descriptionSorter?.dir,
planbezeichnung: planDescriptionSorter?.dir,
max_person: maxPersonsSorter?.dir,
arbeitsplaetze: workplaceSorter?.dir,
m2: squareMetersSorter?.dir,
org_organisationseinheittyp_kurzbz_org_bezeichnung_concat: orgUnitConcatSorter?.dir,
lehre: lehreSorter?.dir,
reservieren: reservierenSorter?.dir,
aktiv: aktivSorter?.dir,
kosten: costsSorter?.dir,
stockwerk: floorSorter?.dir,
parent_ort_kurzbz: parentRoomSorter?.dir,
},
pagination: {
page: params.page,
size: params.size,
},
}),
);
},
ajaxResponse: (url, params, response) => response,
persistenceID: "room_manager_overview_table",
selectableRows: true,
index: "ort_kurzbz",
columns: [
{
title: this.$capitalize(
this.$p.t("gruppenmanagement", "kurzbezeichnung"),
),
field: "ort_kurzbz",
headerFilter: true,
width: 100,
},
{
title: this.$capitalize(
this.$p.t("gruppenmanagement", "bezeichnung"),
),
field: "bezeichnung",
headerFilter: true,
width: 200,
},
{
title: this.$capitalize(this.$p.t("ui", "planbezeichnung")),
field: "planbezeichnung",
headerFilter: true,
width: 150,
},
{
title: this.$capitalize(this.$p.t("ui", "maxPersons")),
field: "max_person",
headerFilter: true,
width: 80,
},
{
title: this.$capitalize(this.$p.t("ui", "arbeitsplaetze")),
field: "arbeitsplaetze",
headerFilter: true,
width: 80,
},
{
title: this.$capitalize(this.$p.t("ui", "quadratmeter")),
field: "m2",
headerFilter: true,
width: 100,
},
{
title: this.$capitalize(this.$p.t("lehre", "organisationseinheit")),
field: "org_organisationseinheittyp_kurzbz_org_bezeichnung_concat",
formatter: function (cell) {
let data = cell.getRow().getData();
let value = null;
if (data.org_organisationseinheittyp_kurzbz) {
value = `[${data.org_organisationseinheittyp_kurzbz}]`;
}
if (data.org_bezeichnung) {
value += ` ${data.org_bezeichnung}`;
}
return value;
},
sorter: function (a, b, aRow, bRow, column, dir, sorterParams) {
let aData = aRow.getData();
let bData = bRow.getData();
let aFull = (
aData.org_organisationseinheittyp_kurzbz +
" " +
aData.org_bezeichnung
).toLowerCase().trim();
let bFull = (
bData.org_organisationseinheittyp_kurzbz +
" " +
bData.org_bezeichnung
).toLowerCase().trim();
return aFull.localeCompare(bFull);
},
headerFilter: true,
width: 180,
},
{
title: this.$capitalize(this.$p.t("ui", "lehre")),
field: "lehre",
headerFilter: true,
headerFilterParams: {
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>',
},
},
{
title: this.$capitalize(this.$p.t("ui", "reservieren")),
field: "reservieren",
headerFilter: true,
headerFilterParams: {
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>',
},
},
{
title: this.$capitalize(this.$p.t("gruppenmanagement", "aktiv")),
field: "aktiv",
headerFilter: true,
headerFilterParams: {
tristate: true,
elementAttributes: { value: "true" },
},
formatter: "tickCross",
hozAlign: "center",
formatterParams: {
tickElement: '<i class="fa fa-check text-success"></i>',
crossElement: '<i class="fa fa-xmark text-danger"></i>',
},
},
{
title: this.$capitalize(this.$p.t("ui", "kosten")),
field: "kosten",
headerFilter: true,
},
{
title: this.$capitalize(this.$p.t("ui", "stockwerk")),
field: "stockwerk",
headerFilter: true,
},
{
title: this.$capitalize(this.$p.t("ui", "parentRoom")),
field: "parent_ort_kurzbz",
headerFilter: true,
width_: 120,
},
{
title: this.$capitalize(this.$p.t("global", "actions")),
field: "actions",
width: 120,
formatter: (cell, formatterParams, onRendered) => {
let container = document.createElement("div");
container.className = "d-flex gap-2 justify-content-center";
let roomTypeBtn = document.createElement("button");
roomTypeBtn.className = "btn btn-outline-secondary btn-action";
roomTypeBtn.innerHTML = '<i class="fa fa-layer-group"></i>';
roomTypeBtn.title = this.$capitalize(
this.$p.t("ui", "btn_editRoomType"),
);
roomTypeBtn.addEventListener("click", (event) =>
this.editRoomType(cell.getData().ort_kurzbz),
);
if (!this.hasBasisOrtWPermission) {
container.append(roomTypeBtn);
return container;
}
let button = document.createElement("button");
button = document.createElement("button");
button.className = "btn btn-outline-secondary btn-action";
button.innerHTML = '<i class="fa fa-edit"></i>';
button.title = this.$capitalize(this.$p.t("ui", "btn_editRoom"));
button.addEventListener("click", (event) =>
this.editRoom(cell.getData().ort_kurzbz),
);
container.append(button);
container.append(roomTypeBtn);
button = document.createElement("button");
button.className =
"btn btn-outline-secondary btn-action bg-danger";
button.innerHTML = '<i class="fa fa-xmark text-white"></i>';
button.title = this.$capitalize(
this.$p.t("ui", "btn_deleteRoom"),
);
button.addEventListener("click", () => {
let isDeletionConfirmed = confirm(
this.$p.t("ui", "deleteRoomConfirmation"),
);
if (!isDeletionConfirmed) return;
this.deleteRoom(cell.getData().ort_kurzbz);
});
container.append(button);
return container;
},
frozen: true,
},
],
layout: "fitColumns",
pagination: true,
paginationMode: "remote",
paginationSize: 100,
maxHeight: "700px",
filterMode: "remote",
sortMode: "remote",
};
return options;
},
tabulatorEvents() {
const events = [
{
event: "renderComplete",
handler: async () => {},
},
{
event: "cellClick",
handler: async (e, cell) => {
let updateableFieldsByClick = ["lehre", "reservieren", "aktiv"];
for (let field of updateableFieldsByClick) {
if (cell.getField() === field) {
let updatedValue = !cell.getValue();
this.$refs.roomManagerOverviewTable.tabulator.updateData([
{
ort_kurzbz: cell.getData().ort_kurzbz,
[field]: updatedValue,
},
]);
this.partialRoomUpdate(
cell.getData().ort_kurzbz,
field,
updatedValue,
);
this.$refs.roomManagerOverviewTable.tabulator.replaceData("/");
}
}
},
},
];
return events;
},
dropdownParsedOrganizationalUnits() {
return this.organizationalUnits
.map((unit) => {
return {
label: `[${unit.organisationseinheittyp_kurzbz}] ${unit.bezeichnung}`,
value: unit.oe_kurzbz,
};
})
.sort((a, b) => a.label.localeCompare(b.label));
},
},
methods: {
filterOrganizationalUnits(event) {
let defaultItem = {
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
const query = event.query.toLowerCase();
if (!query) {
return (this.filteredOrganizationalUnits = [
defaultItem,
...this.dropdownParsedOrganizationalUnits,
]);
}
return (this.filteredOrganizationalUnits = [defaultItem]
.concat(this.dropdownParsedOrganizationalUnits)
.filter((unit) => {
return unit.label.toLowerCase().includes(query);
}));
},
showRoomFormModal() {
this.isRoomFormModalVisible = true;
},
editRoom(roomShortCode) {
this.editedRoomShortCode = roomShortCode;
},
deleteRoom(roomShortCode) {
this.$api
.call(ApiRoom.deleteRoom(roomShortCode))
.then((response) => {
if (response.meta.status === "success") {
this.reloadTableData();
this.$fhcAlert.alertSuccess(
this.$p.t("ui", "roomDeletedSuccessfully"),
);
} else {
this.reloadTableData();
this.$fhcAlert.alertError(this.$p.t("ui", "errorDeletingRoom"));
}
})
.catch((error) => {
this.$fhcAlert.alertError(this.$p.t("ui", "errorDeletingRoom"));
});
},
showRoomTypeFormModal() {
this.isRoomTypeFormModalVisible = true;
},
editRoomType(roomShortCode) {
this.editedRoomForRoomTypeManagement = roomShortCode;
},
async reloadTableData() {
this.$refs.roomManagerOverviewTable.tabulator.replaceData("/");
},
handleRoomUpdated() {
this.editedRoomShortCode = null;
this.reloadTableData();
},
async partialRoomUpdate(roomShortCode, attribute, value) {
let response = await this.$api.call(
ApiRoom.updateRoom(roomShortCode, {
[attribute]: value,
}),
);
if (response.meta.status === "success") {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successUpdate"));
this.reloadTableData();
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorUpdatingRoom"));
}
},
setDefaultBuildingComponentOption() {
this.buildingComponents.unshift({
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
});
},
setDefaultLocationOption() {
this.locations.unshift({
standort_id: null,
bezeichnung: this.$p.t("ui", "dropdownEmptyOption"),
});
},
},
async created() {
let getLocationsResponse = await this.$api.call(
ApiLocation.getLocationsByCompanyType("Intern"),
);
if (getLocationsResponse.meta.status === "success") {
this.locations = getLocationsResponse.data;
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingLocations"));
}
let getAllOrganizationalUnitsResponse = await this.$api.call(
ApiOrganizationalUnit.getAllOrganizationalUnits(),
);
if (getAllOrganizationalUnitsResponse.meta.status === "success") {
this.organizationalUnits = getAllOrganizationalUnitsResponse.data.sort(
(a, b) => a.bezeichnung.localeCompare(b.bezeichnung),
);
} else {
this.$fhcAlert.alertError(
this.$p.t("ui", "errorLoadingOrganizationalUnits"),
);
}
},
mounted() {
this.$p
.loadCategory([
"global",
"lehre",
"ui",
"gruppenmanagement",
"core",
"person",
])
.then(() => {
this.phrasesLoaded = true;
this.setDefaultBuildingComponentOption();
this.setDefaultLocationOption();
});
},
template: /* html */ `
<div class="container mt-4">
<h1 class='mb-5'>{{ $capitalize($p.t("ui", "roomManagerOverviewHeading")) }}</h1>
<div v-if="hasBasisOrtWPermission" class="row mb-3">
<div class="col d-flex justify-content-between">
<a class="btn btn-primary mb-3" @click="showRoomFormModal">{{$capitalize($p.t('ui', 'addRoomButton'))}}</a>
</div>
</div>
<core-filter-cmpt
v-if="phrasesLoaded"
ref="roomManagerOverviewTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
>
<template #search>
<slot name="filterzuruecksetzen">
<core-form class="d-flex flex-column flex-md-row align-items-md-end gap-3">
<div>
<form-input
:label="$capitalize($p.t('lehre/organisationseinheit'))"
:suggestions="filteredOrganizationalUnits"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterOrganizationalUnits"
@itemSelect="(option) => { filterData.organizationalUnit = option.value; }"
dropdown
forceSelection
type="autocomplete"
name="organizationalUnitShortCode"
>
</form-input>
</div>
<div>
<form-input
v-model="filterData.locationId"
:label="$capitalize($p.t('person', 'standort'))"
type="select"
id="location"
name="location"
>
<option
v-for="location in locations"
:key="location.standort_id"
:value="location.standort_id"
>
{{location.bezeichnung}}
</option>
</form-input>
</div>
<div>
<form-input
v-model="filterData.buildingComponent"
:label="$capitalize($p.t('ui', 'buildingComponent'))"
type="select"
id="buildingComponent"
name="buildingComponent"
>
<option
v-for="component in buildingComponents"
:key="component"
:value="component.value"
>
{{component.label}}
</option>
</form-input>
</div>
<div>
<form-input
v-model="filterData.isForTrainingProgram"
:label="$capitalize($p.t('ui', 'lehre'))"
type="checkbox"
name="filterIsForTrainingProgram"
dropdown
></form-input>
</div>
<div>
<form-input
v-model="filterData.isReservationNeeded"
:label="$capitalize($p.t('ui', 'reservieren'))"
type="checkbox"
name="filterIsReservationNeeded"
dropdown
></form-input>
</div>
<div>
<form-input
v-model="filterData.isActive"
:label="$capitalize($p.t('person', 'aktiv'))"
type="checkbox"
name="filterIsActive"
dropdown
></form-input>
</div>
</core-form>
</slot>
</template>
</core-filter-cmpt>
<room-form-modal
:isVisible="isRoomFormModalVisible"
:editedRoomShortCode="editedRoomShortCode"
@hideBsModal="() => { isRoomFormModalVisible = false; editedRoomShortCode = null; }"
@roomCreated="handleRoomUpdated"
@roomUpdated="handleRoomUpdated"
/>
<room-type-form-modal
:isVisible="isRoomTypeFormModalVisible"
:editedRoomShortCode="editedRoomForRoomTypeManagement"
@hideBsModal="() => { isRoomTypeFormModalVisible = false; editedRoomForRoomTypeManagement = null; }"
/>
</div>
`,
};
@@ -0,0 +1,369 @@
import ApiRoomType from "../../../js/api/factory/roomType.js";
import ApiRoomToRoomType from "../../../js/api/factory/roomToRoomType.js";
import { CoreFilterCmpt } from "../filter/Filter.js";
import BsModal from "../Bootstrap/Modal.js";
import CoreForm from "../Form/Form.js";
import FormInput from "../Form/Input.js";
export default {
name: "RoomTypeFormModal",
components: {
BsModal,
CoreForm,
FormInput,
CoreFilterCmpt,
},
inject: ["hasBasisOrtWPermission"],
props: {
isVisible: {
type: Boolean,
required: true,
},
editedRoomShortCode: {
type: String,
default: null,
},
},
emits: [
"hideBsModal",
"roomTypeCreated",
"roomToRoomTypeCreated",
"roomToRoomTypeDeleted",
],
watch: {
isVisible(newValue) {
if (newValue) {
this.$refs.roomTypeFormModal.show();
} else {
this.$refs.roomTypeFormModal.hide();
}
},
async editedRoomShortCode(newValue) {
if (newValue) {
await this.$refs.roomTypesTable.reloadTable();
this.$refs.roomTypeFormModal.show();
} else {
this.resetRoomTypeForm();
}
},
},
data: () => {
return {
phrasesLoaded: false,
isEditInProgress: false,
editedRoom: null,
isRoomTypeFormVisible: false,
roomTypeFormData: {
aktiv: true,
},
roomToRoomTypeFormData: {},
roomTypes: [],
filteredRoomTypes: [],
};
},
computed: {
tabulatorOptions() {
const options = {
ajaxURL: "dummy",
ajaxRequestFunc: async () =>
this.$api.call(
ApiRoomToRoomType.getRoomToRoomTypeRelationsByRoomShortCode(
this.editedRoomShortCode,
),
),
ajaxResponse: (url, params, response) => response.data,
persistenceID: "room_type_assignment_table",
selectableRows: true,
columns: [
{
title: this.$capitalize(this.$p.t("ui", "roomType")),
field: "raumtyp_kurzbz",
width: 150,
},
{
title: this.$capitalize(this.$p.t("ui", "hierarchy")),
field: "hierarchie",
width: 50,
},
{
title: this.$capitalize(this.$p.t("gruppenmanagement", "beschreibung")),
field: "raumtyp_beschreibung",
},
{
title: this.$capitalize(this.$p.t("global", "actions")),
field: "actions",
width: 50,
formatter: (cell, formatterParams, onRendered) => {
if (!this.hasBasisOrtWPermission) return "";
let container = document.createElement("div");
container.className = "d-flex justify-content-center";
let button = document.createElement("button");
button = document.createElement("button");
button.className =
"btn btn-outline-secondary btn-action bg-danger";
button.innerHTML = '<i class="fa fa-xmark text-white"></i>';
button.title = this.$p.t(
"ui",
"btn_deleteRoomToRoomTypeRelation",
);
button.addEventListener("click", () => {
let isDeletionConfirmed = confirm(
this.$p.t("ui", "deleteRoomToRoomTypeRelationConfirmation"),
);
if (!isDeletionConfirmed) return;
this.deleteRoomToRoomTypeRelation(
cell.getData().ort_kurzbz,
cell.getData().raumtyp_kurzbz,
cell.getData().hierarchie,
);
});
container.append(button);
return container;
},
frozen: true,
visible: this.hasBasisOrtWPermission,
},
],
layout: "fitColumns",
};
return options;
},
tabulatorEvents() {
const events = [
{
event: "renderComplete",
handler: async () => {},
},
];
return events;
},
dropdownParsedRoomTypes() {
return this.roomTypes.map((roomType) => {
return {
label: `${roomType.raumtyp_kurzbz} - ${roomType.beschreibung}`,
value: roomType.raumtyp_kurzbz,
};
});
},
},
methods: {
filterRoomTypes(event) {
let defaultItem = {
label: this.$p.t("ui", "dropdownEmptyOption"),
value: null,
};
const query = event.query.toLowerCase();
if (!query) {
return (this.filteredRoomTypes = [
defaultItem,
...this.dropdownParsedRoomTypes,
]);
}
return (this.filteredRoomTypes = [defaultItem]
.concat(this.dropdownParsedRoomTypes)
.filter((roomType) => {
return roomType.label?.toLowerCase().includes(query);
}));
},
createRoomType() {
return this.$refs.roomTypeForm
.call(
ApiRoomType.createRoomType({
kurzbezeichnung: this.roomTypeFormData.shortCode,
beschreibung: this.roomTypeFormData.description,
}),
)
.then((response) => {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
this.$emit("roomTypeCreated");
this.resetRoomTypeForm();
this.isRoomTypeFormVisible = false;
this.fetchRoomTypes();
});
},
createRoomToRoomTypeRelation() {
return this.$refs.roomToRoomTypeForm
.call(
ApiRoomToRoomType.createRoomToRoomTypeRelation(
this.editedRoomShortCode,
this.roomToRoomTypeFormData.roomType?.value,
this.roomToRoomTypeFormData.hierarchy,
),
)
.then((response) => {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successSave"));
this.$emit("roomToRoomTypeCreated");
this.resetRoomTypeForm();
this.$refs.roomTypesTable.tabulator.replaceData("/");
});
},
deleteRoomToRoomTypeRelation(roomShortCode, roomTypeShortCode, hierarchy) {
return this.$api
.call(
ApiRoomToRoomType.deleteRoomToRoomTypeRelation(
roomShortCode,
roomTypeShortCode,
hierarchy
),
)
.then((response) => {
this.$fhcAlert.alertSuccess(this.$p.t("ui", "successDelete"));
this.$emit("roomToRoomTypeDeleted");
this.resetRoomTypeForm();
this.$refs.roomTypesTable.tabulator.replaceData("/");
});
},
hideRoomTypeFormModal() {
this.$refs.roomTypeFormModal.hide();
this.$emit("hideBsModal");
this.resetRoomTypeForm();
},
resetRoomTypeForm() {
this.$refs.roomTypeForm?.clearValidation();
this.isEditInProgress = false;
this.isRoomTypeFormVisible = false;
this.editedRoom = null;
this.roomTypeFormData = {
aktiv: true,
};
},
async fetchRoomTypes() {
let getRoomTypesResponse = await this.$api.call(
ApiRoomType.getAllRoomTypes(),
);
if (getRoomTypesResponse.meta.status === "success") {
this.roomTypes = getRoomTypesResponse.data;
} else {
this.$fhcAlert.alertError(this.$p.t("ui", "errorLoadingRoomTypes"));
}
},
},
async created() {
this.fetchRoomTypes();
this.$p
.loadCategory(["global", "lehre", "ui", "gruppenmanagement", "core", "person"])
.then(() => {
this.phrasesLoaded = true;
});
},
template: /* html */ `
<bs-modal
ref="roomTypeFormModal"
:bodyClass="'pt-4'"
@hideBsModal="() => { $emit('hideBsModal'); resetRoomTypeForm(); }"
size="sm"
class="modal-lg"
>
<template #title>
<p class="fw-bold mt-3">{{$capitalize($p.t('ui', 'assignRoomTypeToRoomModalTitle'))}}</p>
</template>
<template #default>
<div class="d-flex justify-content-end mb-1">
<a
v-if="!isRoomTypeFormVisible && hasBasisOrtWPermission"
:title='$capitalize($p.t("ui", "createRoomType"))'
@click.prevent="isRoomTypeFormVisible = !isRoomTypeFormVisible"
href="#"
class="btn btn-primary rounded-circle">
<i
class="fa fa-plus"
></i>
</a>
</div>
<div v-if="isRoomTypeFormVisible && hasBasisOrtWPermission" class="row g-3 pb-3">
<core-form ref="roomTypeForm">
<div class="row">
<div class="col">
<p class="fw-bold">{{$capitalize($p.t('ui', 'createRoomTypeFormTitle'))}}</p>
</div>
</div>
<div class="row mb-3">
<div class="col">
<form-input
v-model="roomTypeFormData.shortCode"
:label="$capitalize($p.t('gruppenmanagement', 'kurzbezeichnung'))"
type="text"
name="kurzbezeichnung"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomTypeFormData.description"
:label="$capitalize($p.t('gruppenmanagement', 'beschreibung'))"
type="text"
name="beschreibung"
>
</form-input>
</div>
</div>
<div class="col d-flex justify-content-end gap-2">
<button type="button" class="btn btn-secondary" @click="isRoomTypeFormVisible = false">{{$p.t('ui', 'abbrechen')}}</button>
<button type="button" class="btn btn-primary" @click="createRoomType()">{{$p.t('ui', 'speichern')}}</button>
</div>
</core-form>
</div>
<div v-if="!isRoomTypeFormVisible && hasBasisOrtWPermission" class="row g-3 pb-3">
<core-form ref="roomToRoomTypeForm">
<div class="row">
<div class="col-8">
<form-input
v-model="roomToRoomTypeFormData.roomType"
:label="$capitalize($p.t('ui/roomType'))"
:suggestions="filteredRoomTypes"
:optionValue="(option) => option.value"
:optionLabel="(option) => option.label"
@complete="filterRoomTypes"
dropdown
forceSelection
type="autocomplete"
name="roomTypeShortCode"
>
</form-input>
</div>
<div class="col">
<form-input
v-model="roomToRoomTypeFormData.hierarchy"
:label="$capitalize($p.t('ui', 'hierarchy'))"
type="number"
name="hierarchy"
>
</form-input>
</div>
<div class="col justify-content-end align-items-end d-flex">
<button type="button" class="btn btn-primary" @click="createRoomToRoomTypeRelation()">{{$p.t('ui', 'speichern')}}</button>
</div>
</div>
</core-form>
</div>
<hr v-if="hasBasisOrtWPermission" class="mb-3 mt-0" />
<div class="row my-1">
<div class="col">
<p class="fw-bold">{{$capitalize($p.t('ui', 'assignedRoomTypesTitle'))}}</p>
</div>
</div>
<core-filter-cmpt
v-if="phrasesLoaded"
ref="roomTypesTable"
table-only
:side-menu="false"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
>
</core-filter-cmpt>
</template>
</bs-modal>
`,
};
@@ -84,6 +84,14 @@ export default {
'microcredential_2',
'microcredential_3',
'microcredential_4',
'microdegree_1',
'microdegree_2',
'microdegree_3',
'microdegree_4',
'microdegreeabschluss_1',
'microdegreeabschluss_2',
'microdegreeabschluss_3',
'microdegreeabschluss_4',
]
},
documentDropdownObject: {}
+3 -3
View File
@@ -450,18 +450,18 @@ td.MarkLine
td.HeaderTesttool /*fuer die Button-Optik beim Testtool*/
{
color: #FFFFFF;
background-color: #00639C;
background-color: #71787D;
white-space:nowrap;
line-height: 25px;
box-shadow: inset 0 0 2px #FFFFFF;
padding: 10px;
padding: 0 10px;
width: 170px;
}
td.HeaderTesttoolSTG /*fuer die Button-Optik der Quereinstiegs-Studiengänge beim Testtool*/
{
color: white;
border: 2px solid #73a9d6;
padding: 10px;
padding: 0 10px;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
+5998 -107
View File
File diff suppressed because it is too large Load Diff
+7 -1
View File
@@ -93,7 +93,8 @@ require_once('dbupdate_3.4/62889_reihungstest_ueberwachung_mit_constructor.php')
require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php');
require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php');
require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php');
require_once('dbupdate_3.4/70376_lohnguide.php');
require_once('dbupdate_3.4/76663_tempus_rekursive_raum_struktur.php');
// *** Pruefung und hinzufuegen der neuen Attribute und Tabellen
echo '<H2>Pruefe Tabellen und Attribute!</H2>';
@@ -240,6 +241,11 @@ $tabellen=array(
"hr.tbl_valorisierung_instanz" => array("updateamum", "oe_kurzbz", "valorisierungsdatum", "valorisierung_kurzbz", "beschreibung", "ausgewaehlt", "updatevon", "valorisierung_instanz_id"),
"hr.tbl_valorisierung_instanz_methode" => array("valorisierung_instanz_id", "valorisierung_methode_kurzbz", "beschreibung", "valorisierung_methode_parameter"),
"hr.tbl_valorisierung_methode" => array("beschreibung", "valorisierung_methode_kurzbz"),
"hr.tbl_lohnguide_jobfamilie" => array("jobfamilie_kurzbz", "bezeichnung", "aktiv", "sort", "insertvon", "insertamum", "updatevon", "updateamum"),
"hr.tbl_lohnguide_modellfunktion" => array("modellfunktion_kurzbz", "bezeichnung", "jobfamilie_kurzbz", "aktiv", "sort", "insertvon", "insertamum", "updatevon", "updateamum"),
"hr.tbl_lohnguide_modellstelle" => array("modellstelle_kurzbz", "bezeichnung", "grade", "modellfunktion_kurzbz", "aktiv", "sort", "insertvon", "insertamum", "updatevon", "updateamum"),
"hr.tbl_lohnguide_fachrichtung" => array("fachrichtung_kurzbz", "bezeichnung", "aktiv", "insertvon", "insertamum", "updatevon", "updateamum"),
"hr.tbl_vertragsbestandteil_lohnguide" => array("vertragsbestandteil_id", "stellenbezeichnung", "vordienstzeit", "fachrichtung_kurzbz", "modellstelle_kurzbz", "kommentar_person", "kommentar_modellstelle"),
"lehre.tbl_abschlussbeurteilung" => array("abschlussbeurteilung_kurzbz","bezeichnung","bezeichnung_english","sort"),
"lehre.tbl_abschlusspruefung" => array("abschlusspruefung_id","student_uid","vorsitz","pruefer1","pruefer2","pruefer3","abschlussbeurteilung_kurzbz","akadgrad_id","pruefungstyp_kurzbz","datum","uhrzeit","sponsion","anmerkung","updateamum","updatevon","insertamum","insertvon","ext_id","note","protokoll","endezeit","pruefungsantritt_kurzbz","freigabedatum"),
"lehre.tbl_abschlusspruefung_antritt" => array("pruefungsantritt_kurzbz","bezeichnung","bezeichnung_english","sort"),
+14 -1
View File
@@ -1,6 +1,19 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
if ($result = @$db->db_query("SELECT 1 FROM system.tbl_app WHERE app='lvevaluierung' LIMIT 1"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "INSERT INTO system.tbl_app (app) VALUES ('lvevaluierung');";
if(!$db->db_query($qry))
echo '<strong>system.tbl_app: '.$db->db_last_error().'</strong><br>';
else
echo ' system.tbl_app: lvevaluierung hinzugefügt<br>';
}
}
//Add column evaluierung to lehre.tbl_lehrveranstaltung
if(!@$db->db_query("SELECT evaluierung FROM lehre.tbl_lehrveranstaltung LIMIT 1"))
{
@@ -12,4 +25,4 @@ if(!@$db->db_query("SELECT evaluierung FROM lehre.tbl_lehrveranstaltung LIMIT 1"
echo '<strong>lehre.tbl_lehrveranstaltung '.$db->db_last_error().'</strong><br>';
else
echo '<br>Spalte evaluierung zu Tabelle lehre.tbl_lehrveranstaltung hinzugefügt';
}
}
+357
View File
@@ -0,0 +1,357 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_lohnguide_jobfamilie' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
CREATE TABLE IF NOT EXISTS hr.tbl_lohnguide_jobfamilie (
jobfamilie_kurzbz character varying(32) NOT NULL,
bezeichnung varchar(64) NOT NULL,
aktiv boolean DEFAULT FALSE,
sort smallint,
insertvon character varying(32) NOT NULL,
insertamum timestamp without time zone DEFAULT now() NOT NULL,
updatevon character varying(32),
updateamum timestamp without time zone,
CONSTRAINT tbl_lohnguide_jobfamilie_pkey PRIMARY KEY (jobfamilie_kurzbz)
);
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hr.tbl_lohnguide_jobfamilie TO vilesci;
INSERT INTO hr.tbl_lohnguide_jobfamilie(jobfamilie_kurzbz, bezeichnung,aktiv, sort, insertvon, insertamum) VALUES
('FÜHRUNG','Führung',true,1,'system',NOW()),
('AKADEMIA','Akademia',true,2,'system',NOW()),
('VERWALTUNG','Verwaltung',true,3,'system',NOW()),
('TECHNIK','Technik',true,4,'system',NOW()),
('IT_SOFTWARE','IT & Software',true,5,'system',NOW()),
('TECHN_DIENSTE','Technische Dienste',true,6,'system',NOW())
ON CONFLICT (jobfamilie_kurzbz) DO NOTHING;
";
if (! $db->db_query($qry))
echo '<strong>Lohnguide Jobfamilie: ' . $db->db_last_error() . '</strong><br>';
else
echo 'hr.tbl_lohnguide_jobfamilie wurde neu erstellt<br>';
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_lohnguide_modellfunktion' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
CREATE TABLE IF NOT EXISTS hr.tbl_lohnguide_modellfunktion (
modellfunktion_kurzbz character varying(32) NOT NULL,
bezeichnung varchar(64) NOT NULL,
jobfamilie_kurzbz character varying(32) NOT NULL,
aktiv boolean DEFAULT FALSE,
sort smallint,
insertvon character varying(32) NOT NULL,
insertamum timestamp without time zone DEFAULT now() NOT NULL,
updatevon character varying(32),
updateamum timestamp without time zone,
CONSTRAINT tbl_lohnguide_modellfunktion_pkey PRIMARY KEY (modellfunktion_kurzbz),
CONSTRAINT tbl_lohnguide_modellfunktion_jobfamilie_fk FOREIGN KEY (jobfamilie_kurzbz) REFERENCES hr.tbl_lohnguide_jobfamilie (jobfamilie_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE
);
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hr.tbl_lohnguide_modellfunktion TO vilesci;
INSERT INTO hr.tbl_lohnguide_modellfunktion(modellfunktion_kurzbz, bezeichnung, jobfamilie_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('ABTEILUNGSLEITUNG','Abteilungsleitung','FÜHRUNG',true,1,'system',NOW()),
('GF','Geschäftsführung','FÜHRUNG',true,2,'system',NOW()),
('KOMPETENZFELDLEITER','Kompetenzfeldleiter*in','FÜHRUNG',true,3,'system',NOW()),
('DEPARTMENTSLEITER','Departmentsleiter*in','FÜHRUNG',true,4,'system',NOW()),
('FAKULTÄTSLEITER','Fakultätsleiter*in','FÜHRUNG',true,5,'system',NOW()),
/* Akademia */
('STUDENTISCHE_MA','Studentische MA','AKADEMIA',true,6,'system',NOW()),
('JUNIOR_LEC_RES','Junior Lecturer/Researcher','AKADEMIA',true,7,'system',NOW()),
('LEC_RES','Lecturer/Researcher','AKADEMIA',true,8,'system',NOW()),
('SEN_LEC_RES','Senior Lecturer/Researcher','AKADEMIA',true,9,'system',NOW()),
('STUDIENGANGSLEITUNG','Studiengangsleitung','AKADEMIA',true,10,'system',NOW()),
/* Verwaltung */
('FK_VERWALTUNG','Fachkraft Verwaltung','VERWALTUNG',true,11,'system',NOW()),
('SFK_VERWALTUNG','Spezial-Fachkraft Verwaltung','VERWALTUNG',true,12,'system',NOW()),
('SP_VERWALTUNG','Spezialist:in Verwaltung','VERWALTUNG',true,13,'system',NOW()),
('EXP_VERWALTUNG','Expert:in Verwaltung','VERWALTUNG',true,14,'system',NOW()),
/* Technik */
('FK_TECHNIK','Fachkraft Technik','TECHNIK',true,15,'system',NOW()),
/* IT & Software */
('FK_IT','Fachkraft IT & Software','IT_SOFTWARE',true,16,'system',NOW()),
('SFK_IT','Spezial-Fachkraft IT & Software','IT_SOFTWARE',true,17,'system',NOW()),
('SP_IT','Spezialist:in IT & Software','IT_SOFTWARE',true,18,'system',NOW()),
('EXP_IT','Expert:in IT & Software','IT_SOFTWARE',true,19,'system',NOW()),
/* Technische Dienste */
('HK_TECHN_DIENSTE','Hilfskraft Technische Dienste','TECHN_DIENSTE',true,20,'system',NOW()),
('FK_TECHN_DIENSTE','Fachkraft Technische Dienste','TECHN_DIENSTE',true,21,'system',NOW()),
('SFK_TECHN_DIENSTE','Spezial-Fachkraft Technische Dienste','TECHN_DIENSTE',true,22,'system',NOW())
ON CONFLICT (modellfunktion_kurzbz) DO NOTHING;
";
if (! $db->db_query($qry))
echo '<strong>Lohnguide Modellfunktion: ' . $db->db_last_error() . '</strong><br>';
else
echo 'hr.tbl_lohnguide_modellfunktion wurde neu erstellt<br>';
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_lohnguide_modellstelle' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
CREATE TABLE IF NOT EXISTS hr.tbl_lohnguide_modellstelle (
modellstelle_kurzbz character varying(32) NOT NULL,
bezeichnung varchar(128) NOT NULL,
code character varying(32) NOT NULL,
grade int NOT NULL,
modellfunktion_kurzbz character varying(32) NOT NULL,
aktiv boolean DEFAULT FALSE,
sort smallint,
insertvon character varying(32) NOT NULL,
insertamum timestamp without time zone DEFAULT now() NOT NULL,
updatevon character varying(32),
updateamum timestamp without time zone,
CONSTRAINT tbl_lohnguide_modellstelle_pkey PRIMARY KEY (modellstelle_kurzbz),
CONSTRAINT tbl_lohnguide_modellstelle_modellfunktion_fk FOREIGN KEY (modellfunktion_kurzbz) REFERENCES hr.tbl_lohnguide_modellfunktion (modellfunktion_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE
);
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hr.tbl_lohnguide_modellstelle TO vilesci;
-- FÜHRUNG
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz,bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('ABTL_1_4', 'Abteilungsleitung 1/4', '111', 16, 'ABTEILUNGSLEITUNG', true, 1, 'system', NOW()),
('ABTL_2A_4', 'Abteilungsleitung 2a/4', '112a', 17, 'ABTEILUNGSLEITUNG', true, 2, 'system', NOW()),
('ABTL_2B_4', 'Abteilungsleitung 2b/4', '112b', 17, 'ABTEILUNGSLEITUNG', true, 3, 'system', NOW()),
('ABTL_3A_4', 'Abteilungsleitung 3a/4', '113a', 18, 'ABTEILUNGSLEITUNG', true, 4, 'system', NOW()),
('ABTL_3B_4', 'Abteilungsleitung 3b/4', '113b', 18, 'ABTEILUNGSLEITUNG', true, 5, 'system', NOW()),
('ABTL_4_4', 'Abteilungsleitung 4/4', '114', 19, 'ABTEILUNGSLEITUNG', true, 6, 'system', NOW()),
('GF_1_2', 'Geschäftsführung 1/2', '121', 22, 'GF', true, 7, 'system', NOW()),
('GF_2_2', 'Geschäftsführung 2/2', '122', 23, 'GF', true, 8, 'system', NOW()),
('KOMFL_1_1', 'Kompetenzfeldleiter*in 1/1', '131', 15, 'KOMPETENZFELDLEITER', true, 9, 'system', NOW()),
('DEPL_1_1', 'Departmentleiter*in 1/1', '141', 18, 'DEPARTMENTSLEITER', true, 10, 'system', NOW()),
('FAKL_1_1', 'Fakultätsleiter*in 1/1', '151', 20, 'FAKULTÄTSLEITER', true, 11, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
-- AKADEMIA
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz, bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('STUDENTISCHE_MA_1_1', 'Studentische MA 1/1', '211', 5, 'STUDENTISCHE_MA', true, 12, 'system', NOW()),
('JUNIOR_LEC_RES_1_2', 'Junior Lecturer/Researcher 1/2', '221', 8, 'JUNIOR_LEC_RES', true, 13, 'system', NOW()),
('JUNIOR_LEC_RES_2_2', 'Junior Lecturer/Researcher 2/2', '222', 9, 'JUNIOR_LEC_RES', true, 14, 'system', NOW()),
('LEC_RES_1_2', 'Lecturer/Researcher 1/2', '231', 11, 'LEC_RES', true, 15, 'system', NOW()),
('LEC_RES_2_2', 'Lecturer/Researcher 2/2', '232', 12, 'LEC_RES', true, 16, 'system', NOW()),
('SEN_LEC_RES_1_2', 'Senior Lecturer/Researcher 1/2', '241', 13, 'SEN_LEC_RES', true, 17, 'system', NOW()),
('SEN_LEC_RES_2_2', 'Senior Lecturer/Researcher 2/2', '242', 14, 'SEN_LEC_RES', true, 18, 'system', NOW()),
('STGL_1_2', 'Studiengangsleitung 1/2', '251', 15, 'STUDIENGANGSLEITUNG', true, 19, 'system', NOW()),
('STGL_2_2', 'Studiengangsleitung 2/2', '252', 16, 'STUDIENGANGSLEITUNG', true, 20, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
-- VERWALTUNG
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz, bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('FK_VERWALTUNG_1_3', 'Fachkraft Verwaltung 1/3', '311', 4, 'FK_VERWALTUNG', true, 21, 'system', NOW()),
('FK_VERWALTUNG_2A_3', 'Fachkraft Verwaltung 2a/3', '312a', 5, 'FK_VERWALTUNG', true, 22, 'system', NOW()),
('FK_VERWALTUNG_2B_3', 'Fachkraft Verwaltung 2b/3', '312b', 5, 'FK_VERWALTUNG', true, 23, 'system', NOW()),
('FK_VERWALTUNG_3_3', 'Fachkraft Verwaltung 3/3', '313', 6, 'FK_VERWALTUNG', true, 24, 'system', NOW()),
('SFK_VERWALTUNG_1_4', 'Spezial-Fachkraft Verwaltung 1/4', '321', 7, 'SFK_VERWALTUNG', true, 25, 'system', NOW()),
('SFK_VERWALTUNG_2A_4', 'Spezial-Fachkraft Verwaltung 2a/4', '322a', 8, 'SFK_VERWALTUNG', true, 26, 'system', NOW()),
('SFK_VERWALTUNG_2B_4', 'Spezial-Fachkraft Verwaltung 2b/4', '322b', 8, 'SFK_VERWALTUNG', true, 27, 'system', NOW()),
('SFK_VERWALTUNG_3A_4', 'Spezial-Fachkraft Verwaltung 3a/4', '323a', 9, 'SFK_VERWALTUNG', true, 28, 'system', NOW()),
('SFK_VERWALTUNG_3B_4', 'Spezial-Fachkraft Verwaltung 3b/4', '323b', 9, 'SFK_VERWALTUNG', true, 29, 'system', NOW()),
('SFK_VERWALTUNG_4_4', 'Spezial-Fachkraft Verwaltung 4/4', '324', 10, 'SFK_VERWALTUNG', true, 30, 'system', NOW()),
('SP_VERWATLTUNG_1_4', 'Spezialist:in Verwaltung 1/4', '331', 11, 'SP_VERWALTUNG', true, 31, 'system', NOW()),
('SP_VERWATLTUNG_2A_4', 'Spezialist:in Verwaltung 2a/4', '332a', 12, 'SP_VERWALTUNG', true, 32, 'system', NOW()),
('SP_VERWATLTUNG_2B_4', 'Spezialist:in Verwaltung 2b/4', '332b', 12, 'SP_VERWALTUNG', true, 33, 'system', NOW()),
('SP_VERWATLTUNG_3A_4', 'Spezialist:in Verwaltung 3a/4', '333a', 13, 'SP_VERWALTUNG', true, 34, 'system', NOW()),
('SP_VERWATLTUNG_3B_4', 'Spezialist:in Verwaltung 3b/4', '333b', 13, 'SP_VERWALTUNG', true, 35, 'system', NOW()),
('SP_VERWATLTUNG_4_4', 'Spezialist:in Verwaltung 4/4', '334', 14, 'SP_VERWALTUNG', true, 36, 'system', NOW()),
('EXP_VERWALTUNG_1_1', 'Expert:in Verwaltung 1/1', '341', 15, 'EXP_VERWALTUNG', true, 37, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
-- TECHNIK
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz, bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('FK_TECHNIK_1_3', 'Fachkraft Technik 1/3', '311', 4, 'FK_TECHNIK', true, 38, 'system', NOW()),
('FK_TECHNIK_2a_3', 'Fachkraft Technik 2a/3', '312a', 5, 'FK_TECHNIK', true, 39, 'system', NOW()),
('FK_TECHNIK_2b_3','Fachkraft Technik 2b/3', '312b', 5, 'FK_TECHNIK', true, 40, 'system', NOW()),
('FK_TECHNIK_3_3', 'Fachkraft Technik 3/3', '313', 6, 'FK_TECHNIK', true, 41, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
-- IT & Software
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz, bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('FK_IT_1_2', 'Fachkraft IT & Software 1/2', '411', 5, 'FK_IT', true, 42, 'system', NOW()),
('FK_IT_2_2', 'Fachkraft IT & Software 2/2', '412', 6, 'FK_IT', true, 43, 'system', NOW()),
('SFK_IT_1_4', 'Spezial-Fachkraft IT & Software 1/4', '421', 7, 'SFK_IT', true, 44, 'system', NOW()),
('SFK_IT_2_4', 'Spezial-Fachkraft IT & Software 2/4', '422', 8, 'SFK_IT', true, 45, 'system', NOW()),
('SFK_IT_3_4', 'Spezial-Fachkraft IT & Software 3/4', '423', 9, 'SFK_IT', true, 46, 'system', NOW()),
('SFK_IT_4_4', 'Spezial-Fachkraft IT & Software 4/4', '424', 10, 'SFK_IT', true, 47, 'system', NOW()),
('SP_IT_1_4', 'Spezialist:in IT & Software 1/4', '431', 11, 'SP_IT', true, 48, 'system', NOW()),
('SP_IT_2A_4', 'Spezialist:in IT & Software 2a/4', '432a', 12, 'SP_IT', true, 49, 'system', NOW()),
('SP_IT_2B_4', 'Spezialist:in IT & Software 2b/4', '432b', 12, 'SP_IT', true, 50, 'system', NOW()),
('SP_IT_3A_4', 'Spezialist:in IT & Software 3a/4', '433a', 13, 'SP_IT', true, 51, 'system', NOW()),
('SP_IT_3B_4', 'Spezialist:in IT & Software 3b/4', '433b', 13, 'SP_IT', true, 52, 'system', NOW()),
('SP_IT_4_4', 'Spezialist:in IT & Software 4/4', '434', 14, 'SP_IT', true, 53, 'system', NOW()),
('EXP_IT_1_1', 'Expert:in IT & Software 1/1', '441', 15, 'EXP_IT', true, 54, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
-- TECHNISCHE DIENSTE
INSERT INTO hr.tbl_lohnguide_modellstelle(modellstelle_kurzbz, bezeichnung, code, grade, modellfunktion_kurzbz, aktiv, sort, insertvon, insertamum) VALUES
('HK_TECHN_DIENSTE_1_4', 'Hilfskraft Technische Dienste 1/4', '511', 1, 'HK_TECHN_DIENSTE', true, 55, 'system', NOW()),
('HK_TECHN_DIENSTE_2_4', 'Hilfskraft Technische Dienste 2/4', '512', 2, 'HK_TECHN_DIENSTE', true, 56, 'system', NOW()),
('HK_TECHN_DIENSTE_3_4', 'Hilfskraft Technische Dienste 3/4', '513', 3, 'HK_TECHN_DIENSTE', true, 57, 'system', NOW()),
('HK_TECHN_DIENSTE_4_4', 'Hilfskraft Technische Dienste 4/4', '514', 4, 'HK_TECHN_DIENSTE', true, 58, 'system', NOW()),
('FK_TECHN_DIENSTE_1_2', 'Fachkraft Technische Dienste 1/2', '521', 5, 'FK_TECHN_DIENSTE', true, 59, 'system', NOW()),
('FK_TECHN_DIENSTE_2_2', 'Fachkraft Technische Dienste 2/2', '522', 6, 'FK_TECHN_DIENSTE', true, 60, 'system', NOW()),
('SFK_TECHN_DIENSTE_1_4', 'Spezial-Fachkraft Technische Dienste 1/4', '531', 7, 'SFK_TECHN_DIENSTE', true, 61, 'system', NOW()),
('SFK_TECHN_DIENSTE_2_4', 'Spezial-Fachkraft Technische Dienste 2/4', '532', 8, 'SFK_TECHN_DIENSTE', true, 62, 'system', NOW()),
('SFK_TECHN_DIENSTE_3_4', 'Spezial-Fachkraft Technische Dienste 3/4', '533', 9, 'SFK_TECHN_DIENSTE', true, 63, 'system', NOW()),
('SFK_TECHN_DIENSTE_4_4', 'Spezial-Fachkraft Technische Dienste 4/4', '534', 10, 'SFK_TECHN_DIENSTE', true, 64, 'system', NOW())
ON CONFLICT (modellstelle_kurzbz) DO NOTHING;
";
if (! $db->db_query($qry))
echo '<strong>Lohnguide Modellstelle: ' . $db->db_last_error() . '</strong><br>';
else
echo 'hr.tbl_lohnguide_modellstelle wurde neu erstellt<br>';
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_lohnguide_fachrichtung' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
CREATE TABLE IF NOT EXISTS hr.tbl_lohnguide_fachrichtung (
fachrichtung_kurzbz character varying(32) NOT NULL,
bezeichnung varchar(32) NOT NULL,
aktiv boolean DEFAULT FALSE,
insertvon character varying(32) NOT NULL,
insertamum timestamp without time zone DEFAULT now() NOT NULL,
updatevon character varying(32),
updateamum timestamp without time zone,
CONSTRAINT tbl_lohnguide_fachrichtung_pkey PRIMARY KEY (fachrichtung_kurzbz)
);
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hr.tbl_lohnguide_fachrichtung TO vilesci;
INSERT INTO hr.tbl_lohnguide_fachrichtung(fachrichtung_kurzbz,bezeichnung,aktiv,insertvon,insertamum) VALUES
('FA00','Keine Berücksichtigung',true,'system',NOW())
ON CONFLICT (fachrichtung_kurzbz) DO NOTHING;
";
if (! $db->db_query($qry))
echo '<strong>Lohnguide Fachrichtung: ' . $db->db_last_error() . '</strong><br>';
else
echo 'hr.tbl_lohnguide_fachrichtung wurde neu erstellt<br>';
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.tables WHERE table_name='tbl_vertragsbestandteil_lohnguide' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
CREATE TABLE IF NOT EXISTS hr.tbl_vertragsbestandteil_lohnguide (
vertragsbestandteil_id integer NOT NULL,
vordienstzeit int,
stellenbezeichnung varchar(255),
fachrichtung_kurzbz character varying(32) NOT NULL,
modellstelle_kurzbz character varying(32) NOT NULL,
kommentar_person varchar(255),
kommentar_modellstelle varchar(255),
CONSTRAINT tbl_vertragsbestandteil_lohnguide_pk PRIMARY KEY (vertragsbestandteil_id),
CONSTRAINT tbl_vertragsbestandteil_fk FOREIGN KEY (vertragsbestandteil_id) REFERENCES hr.tbl_vertragsbestandteil (vertragsbestandteil_id) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT tbl_vertragsbestandteil_lohnguide_fachrichtung_fk FOREIGN KEY (fachrichtung_kurzbz) REFERENCES hr.tbl_lohnguide_fachrichtung (fachrichtung_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT tbl_vertragsbestandteil_modellstelle_fachrichtung_fk FOREIGN KEY (modellstelle_kurzbz) REFERENCES hr.tbl_lohnguide_modellstelle (modellstelle_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE
);
COMMENT ON TABLE hr.tbl_vertragsbestandteil_lohnguide IS E'Zuordnung für EU-Entgelttransparenzrichtlinie';
GRANT SELECT,INSERT,DELETE,UPDATE ON TABLE hr.tbl_vertragsbestandteil_lohnguide TO vilesci;
";
if (! $db->db_query($qry))
echo '<strong>Vertragsbestandteil Lohnguide: ' . $db->db_last_error() . '</strong><br>';
else
echo 'hr.tbl_vertragsbestandteil_lohnguide wurde neu erstellt<br>';
}
}
if($result = $db->db_query("SELECT 1 FROM hr.tbl_vertragsbestandteiltyp WHERE vertragsbestandteiltyp_kurzbz = 'lohnguide'"))
{
if($db->db_num_rows($result) === 0)
{
$qry = "insert into hr.tbl_vertragsbestandteiltyp (vertragsbestandteiltyp_kurzbz,bezeichnung,ueberlappend) values('lohnguide','Lohnguide',false)";
if(!$db->db_query($qry))
echo '<strong>Public Tabelle person: '.$db->db_last_error().'</strong><br>';
else
echo "<br>Vertragsbestandteiltyp 'lohnguide' hinzugefuegt";
}
}
if ($result = $db->db_query("SELECT * FROM information_schema.columns WHERE column_name='vordienstzeit' AND table_name='tbl_vertragsbestandteil_lohnguide' AND table_schema='hr'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
ALTER TABLE
hr.tbl_vertragsbestandteil_lohnguide
ADD COLUMN
vordienstzeit int;
";
if (! $db->db_query($qry))
echo '<strong>Lohnguide: ' . $db->db_last_error() . '</strong><br>';
else
echo 'Spalte vordienstzeit wurde in hr.tbl_vertragsbestandteil_lohnguide neu erstellt<br>';
}
}
if ($result = $db->db_query("SELECT * FROM hr.tbl_gehaltstyp WHERE gehaltstyp_kurzbz='ueberstundenpauschale'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
INSERT INTO hr.tbl_gehaltstyp
(gehaltstyp_kurzbz, bezeichnung, valorisierung, sort, aktiv, lvexport)
VALUES
('ueberstundenpauschale','Überstundenpauschale', true, 8, true, true);
";
if (! $db->db_query($qry))
echo '<strong>Gehaltstyp: ' . $db->db_last_error() . '</strong><br>';
else
echo 'Gehaltstyp "Überstundenpauschale" erstellt.<br />';
}
}
if ($result = $db->db_query("SELECT * FROM hr.tbl_gehaltstyp WHERE gehaltstyp_kurzbz='sachbezug_pkw'"))
{
if ($db->db_num_rows($result) == 0)
{
$qry = "
INSERT INTO hr.tbl_gehaltstyp
(gehaltstyp_kurzbz, bezeichnung, valorisierung, sort, aktiv, lvexport)
VALUES
('sachbezug_pkw','Sachbezug PKW', true, 9, true, true);
";
if (! $db->db_query($qry))
echo '<strong>Gehaltstyp: ' . $db->db_last_error() . '</strong><br>';
else
echo 'Gehaltstyp "Sachbezug PKW" erstellt.<br />';
}
}
@@ -0,0 +1,22 @@
<?php
if (! defined('DB_NAME')) exit('No direct script access allowed');
if(!$result = @$db->db_query("SELECT parent_ort_kurzbz FROM public.tbl_ort LIMIT 1;"))
{
$qry = 'ALTER TABLE public.tbl_ort ADD COLUMN parent_ort_kurzbz VARCHAR(16);';
if(!$db->db_query($qry))
echo '<strong>public.tbl_ort: '.$db->db_last_error().'</strong><br>';
else
echo ' public.tbl_ort: parent_ort_kurzbz added successfully.<br>';
}
$result = $db->db_query("SELECT constraint_name FROM information_schema.table_constraints
WHERE table_name='tbl_ort' AND constraint_type='FOREIGN KEY' AND constraint_name='fk_parent_ort_kurzbz'");
if($db->db_num_rows($result)==0)
{
$qry = "ALTER TABLE public.tbl_ort ADD CONSTRAINT fk_parent_ort_kurzbz FOREIGN KEY(parent_ort_kurzbz) REFERENCES public.tbl_ort(ort_kurzbz);";
if(!$db->db_query($qry))
echo '<strong>public.tbl_ort: '.$db->db_last_error().'</strong><br>';
else
echo '<br>Added foreign key constraint fk_parent_ort_kurzbz to public.tbl_ort';
}
File diff suppressed because it is too large Load Diff
+8 -7
View File
@@ -742,7 +742,7 @@ function _getFunktionscontainer_Funktionscode123456($bisfunktion_arr)
$has_oe_lehrgang = !($studiengang->studiengang_kz > 0 && $studiengang->studiengang_kz < 10000);
// STG, die nicht BIS-bemeldet werden, ueberspringen
if (in_array($studiengang->studiengang_kz, BIS_EXCLUDE_STG))
if (in_array($studiengang->studiengang_kz, BIS_EXCLUDE_STG) || !$studiengang->melderelevant)
{
continue;
}
@@ -825,6 +825,7 @@ function _addFunktionscontainer_Funktionscode7($uid, $funktion_arr, $stichtag)
$entwicklungsteam_arr = array_filter($entwicklungsteam_arr, function ($obj) {
return
!in_array($obj->studiengang_kz, BIS_EXCLUDE_STG) &&
$obj->melderelevant &&
$obj->studiengang_kz > 0 &&
$obj->studiengang_kz < 10000;
});
@@ -889,7 +890,7 @@ function _getLehrecontainer($sws_proStg_arr)
$kennzeichen_name = $is_lehrgang ? 'LehrgangNr' : 'StgKz';
// Lehreobjekt generieren
if (empty($lehre_arr) || !lehre_stg_exists($sws_proStg->studiengang_kz, $lehre_arr))
if (empty($lehre_arr) || !lehre_stg_exists($sws_proStg->melde_studiengang_kz, $lehre_arr))
{
$lehre_obj = new StdClass();
@@ -904,8 +905,8 @@ function _getLehrecontainer($sws_proStg_arr)
}
else // Lehrecontainer mit STG schon vorhanden
{
$lehre_obj_arr = array_filter($lehre_arr, function (&$obj) use ($sws_proStg) {
return $obj->StgKz == $sws_proStg->studiengang_kz;
$lehre_obj_arr = array_filter($lehre_arr, function (&$obj) use ($sws_proStg, $kennzeichen_name) {
return isset($obj->{$kennzeichen_name}) && $obj->{$kennzeichen_name} == $sws_proStg->melde_studiengang_kz;
});
// SWS ergaenzen
@@ -1359,15 +1360,15 @@ function verwendung_exists($bisverwendung, $verwendung_arr)
/**
* Prueft ob ein Studiengang bereits im Lehre Container vorhanden ist
* @param $studiengang_kz Studiengangskennzahl
* @param $melde_studiengang_kz Studiengangskennzahl
* @param $lehre_arr Array mit Lehre Objekten
* @return true wenn der Studiengang bereits existiert
*/
function lehre_stg_exists($studiengang_kz, $lehre_arr)
function lehre_stg_exists($melde_studiengang_kz, $lehre_arr)
{
foreach($lehre_arr as $row)
{
$kennzeichenName = $row->LehrgangNr ?? $row->StgKz;
$kennzeichenName = isset($row->LehrgangNr) ? 'LehrgangNr' : 'StgKz';
if(isset($row->{$kennzeichenName}) && $row->{$kennzeichenName} == $melde_studiengang_kz)
return true;
}
+6
View File
@@ -67,6 +67,7 @@
$gebteil='';
$m2='';
$arbeitsplaetze='';
$parent_ort_kurzbz = '';
$neu = "true";
@@ -93,6 +94,7 @@
$oe_kurzbz = $_POST["oe_kurzbz"];
$gebteil = $_POST["gebteil"];
$arbeitsplaetze = $_POST["arbeitsplaetze"];
$parent_ort_kurzbz = $_POST["parent_ort_kurzbz"];
$sg_update = new ort();
$sg_update->ort_kurzbz = $ort_kurzbz;
@@ -115,6 +117,7 @@
$sg_update->gebteil = $gebteil;
$sg_update->oe_kurzbz = $oe_kurzbz;
$sg_update->arbeitsplaetze = $arbeitsplaetze;
$sg_update->parent_ort_kurzbz = $parent_ort_kurzbz;
$sg_update->updateamum = date('Y-m-d H:i:s');
$sg_update->updatevon = $user;
@@ -161,6 +164,7 @@
$m2 = $sg->m2;
$oe_kurzbz = $sg->oe_kurzbz;
$arbeitsplaetze = $sg->arbeitsplaetze;
$parent_ort_kurzbz = $sg->parent_ort_kurzbz;
$neu = "false";
}
@@ -402,6 +406,8 @@
<td><input class="detail" type="text" name="telefonklappe" size="3" maxlength="8" value="'.$telefonklappe.'" onchange="submitable()"></td>
<td>Anz. Arbeitsplätze</td>
<td><input class="detail" type="text" name="arbeitsplaetze" size="3" maxlength="8" value="'.$arbeitsplaetze.'" onchange="submitable()"></td>
<td>Parent Raum Kurzbz</td>
<td><input type="text" name="parent_ort_kurzbz" size="10" onchange="submitable()" value="'.$parent_ort_kurzbz.'" /></td>
</tr>
<tr>
<td valign="top">Lageplan</td>
+14 -3
View File
@@ -227,7 +227,8 @@ if (isset($_GET['sendform']))
<table class="tablesorter" id="t1">
<thead>
<tr>
<th><span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
<th><button type="button" class="resetsaved" title="Reset Filter">Reset Filter</button>
<span class="tooltip"><img src="../../skin/images/information.png" height="20px" name="infoicon"/>
'.$tooltiptext.'
</span>
</th>
@@ -243,6 +244,7 @@ if (isset($_GET['sendform']))
<th>Aktiv</th>
<th>Kosten</th>
<th>Stockwerk</th>
<th>Parent Ort Kurzbz</th>
</tr>
</thead>
<tbody>';
@@ -286,6 +288,7 @@ if (isset($_GET['sendform']))
$htmlstr .= " <td>".$twraum->kosten."</td>\n";
$htmlstr .= " <td>".$twraum->stockwerk."</td>\n";
$htmlstr .= " <td><a href='raum_details.php?ort_kurzbz=".$twraum->parent_ort_kurzbz."' target='detail_raum'>".$twraum->parent_ort_kurzbz."</a></td>\n";
$htmlstr .= " </tr>\n";
}
@@ -364,9 +367,10 @@ if (isset($_GET['sendform']))
$("#t1").tablesorter(
{
sortList: [[3,0]],
widgets: ["zebra", "filter", "stickyHeaders"],
widgets: ["saveSort", "zebra", "filter", "stickyHeaders"],
headers: { 0: { filter: false, sorter: false }},
widgetOptions : { filter_functions : {
widgetOptions : { filter_saveFilters : true,
filter_functions : {
// Add select menu to this column
8 : {
"True" : function(e, n, f, i, $r, c, data) { return /t/.test(e); },
@@ -381,6 +385,13 @@ if (isset($_GET['sendform']))
"False" : function(e, n, f, i, $r, c, data) { return /f/.test(e); }
}
}}
});
$('.resetsaved').click(function()
{
$("#t1").trigger("filterReset");
location.reload(forceGet);
return false;
});
});
@@ -588,7 +588,9 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
{
if(is_numeric($_POST['prestudent_id']) && $_POST['prestudent_id']!='')
{
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level, tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte
$qry="SELECT nachname,vorname,person_id,prestudent_id,tbl_pruefling.pruefling_id,
tbl_pruefling_frage.begintime,bezeichnung,kurzbz,tbl_frage.nummer,level,
tbl_vorschlag.nummer as antwortnummer, tbl_vorschlag.punkte, tbl_frage.frage_id
FROM testtool.tbl_antwort
JOIN testtool.tbl_vorschlag USING(vorschlag_id)
JOIN testtool.tbl_frage USING (frage_id)
@@ -615,6 +617,7 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
<th>Level</th>
<th>Antwort #</th>
<th>Punkte</th>
<th>FrageID</th>
</tr>
</thead>
<tbody>';
@@ -632,6 +635,7 @@ if(isset($_POST['testergebnisanzeigen']) && isset($_POST['prestudent_id']))
echo "<td>$row->level</td>";
echo "<td>$row->antwortnummer</td>";
echo "<td>$row->punkte</td>";
echo "<td>$row->frage_id</td>";
echo '</tr>';
}
echo '</tbody></table>';
+29 -2
View File
@@ -837,6 +837,25 @@ if(isset($_GET['excel']))
<script src="../../vendor/fgelinas/timepicker/jquery.ui.timepicker.js" type="text/javascript" ></script>
<script type="text/javascript">
$.tablesorter.addParser({
id: "customDate",
is: function(s) {
//return false;
//use the above line if you don\'t want table sorter to auto detected this parser
// match dd.mm.yyyy e.g. 01.01.2001 as regex
//return /\d{1,4}-\d{1,2}-\d{1,2} \d{1,2}:\d{1,2} .*/.test(s);
return /\d{1,2}.\d{1,2}.\d{1,4}.*/.test(s);
},
// replace regex-wildcards and return new date
format: function(s) {
s = s.replace(/\-/g," ");
s = s.replace(/:/g," ");
s = s.replace(/\./g," ");
s = s.split(" ");
return $.tablesorter.formatFloat(new Date(s[2], s[1]-1, s[0]).getTime());
},
type: "numeric"
});
$(document).ready(function()
{
// Check, ob Räume zugeteilt sind oder max_teilnehmer gesetzt ist, wenn "öffentlich" gesetzt wird
@@ -1007,7 +1026,7 @@ if(isset($_GET['excel']))
{
widgets: ["zebra", "filter", "stickyHeaders"],
sortList: [[2,0],[3,0]],
headers: {0: { sorter: false}},
headers: {0: { sorter: false},10: { sorter: "customDate"},11: { sorter: "customDate"}},
widgetOptions: {filter_cssFilter: [
"filter_clm_null",
"filter_clm_prestudent_id",
@@ -1020,6 +1039,7 @@ if(isset($_GET['excel']))
"filter_clm_studienplan",
"filter_clm_einstiegssemester",
"filter_clm_geburtsdatum",
"filter_clm_anmeldedatum",
"filter_clm_email",
"filter_clm_absolviert"]}
});
@@ -1072,6 +1092,7 @@ if(isset($_GET['excel']))
'clm_studienplan',
'clm_einstiegssemester',
'clm_geburtsdatum',
"filter_clm_anmeldedatum",
'clm_email',
'clm_absolviert'];
for (var i in arr)
@@ -2697,7 +2718,8 @@ if($reihungstest_id!='')
WHERE prestudent_id = tbl_prestudent.prestudent_id
AND status_kurzbz = 'Interessent'
) LIMIT 1
) AS orgform_kurzbz
) AS orgform_kurzbz,
tbl_rt_person.anmeldedatum
FROM PUBLIC.tbl_rt_person
JOIN PUBLIC.tbl_person USING (person_id)
JOIN PUBLIC.tbl_reihungstest rt ON (rt_id = rt.reihungstest_id)
@@ -2786,6 +2808,7 @@ if($reihungstest_id!='')
echo '<div id="clm_studienplan" class="active" onclick="hideColumn(\'clm_studienplan\')">Studienplan</div>';
echo '<div id="clm_einstiegssemester" class="active" onclick="hideColumn(\'clm_einstiegssemester\')">Einstiegssemester</div>';
echo '<div id="clm_geburtsdatum" class="active" onclick="hideColumn(\'clm_geburtsdatum\')">Geburtsdatum</div>';
echo '<div id="clm_anmeldedatum" class="active" onclick="hideColumn(\'clm_anmeldedatum\')">Geburtsdatum</div>';
echo '<div id="clm_email" class="active" onclick="hideColumn(\'clm_email\')">EMail</div>';
echo '<div id="clm_absolviert" class="active" onclick="hideColumn(\'clm_absolviert\')">Absolvierte Tests <span class="wait"></span></div>';
//echo '<div id="clm_ergebnis" class="active" onclick="hideColumn(\'clm_ergebnis\')">Ergebnis <span class="wait"></span></div>';
@@ -2827,6 +2850,7 @@ if($reihungstest_id!='')
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
<th style="display: table-cell" class="clm_email">EMail</th>
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
@@ -2946,6 +2970,7 @@ if($reihungstest_id!='')
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>
</tr>';
@@ -3009,6 +3034,7 @@ if($reihungstest_id!='')
<th style="display: table-cell" class="clm_studienplan">Studienplan</th>
<th style="display: table-cell" class="clm_einstiegssemester">Einstiegssemester</th>
<th style="display: table-cell" class="clm_geburtsdatum">Geburtsdatum</th>
<th style="display: table-cell" class="clm_anmeldedatum">Anmeldedatum</th>
<th style="display: table-cell" class="clm_email">EMail</th>
<th style="display: table-cell" class="clm_absolviert">bereits absolvierte Verfahren</th>
<!--<th style="display: table-cell" class="clm_ergebnis">Ergebnis</th>
@@ -3128,6 +3154,7 @@ if($reihungstest_id!='')
<td style="display: table-cell" class="clm_studienplan">'.$db->convert_html_chars($studienplan_bezeichnung).' ('.$row->studienplan_id.')</td>
<td style="display: table-cell" class="clm_einstiegssemester">'.$db->convert_html_chars($row->ausbildungssemester).'</td>
<td style="display: table-cell" class="clm_geburtsdatum">'.$db->convert_html_chars($row->gebdatum!=''?$datum_obj->convertISODate($row->gebdatum):' ').'</td>
<td style="display: table-cell" class="clm_anmeldedatum">'.$db->convert_html_chars($row->anmeldedatum!=''?$datum_obj->convertISODate($row->anmeldedatum):' ').'</td>
<td style="display: table-cell; text-align: center" class="clm_email"><a href="mailto:'.$db->convert_html_chars($row->email).'"><img src="../../skin/images/button_mail.gif" name="mail"></a></td>
<td style="display: table-cell;" class="clm_absolviert">'.$rt_in_anderen_stg.'</td>';
/*echo '<td style="display: table-cell; align: right" class="clm_ergebnis">'.($rtergebnis==0?'-':number_format($rtergebnis,2,'.','')).' %</td>