diff --git a/application/controllers/api/frontend/v1/tempus/Config.php b/application/controllers/api/frontend/v1/tempus/Config.php
index e20716226..30be2cc6f 100644
--- a/application/controllers/api/frontend/v1/tempus/Config.php
+++ b/application/controllers/api/frontend/v1/tempus/Config.php
@@ -32,7 +32,7 @@ class Config extends FHCAPI_Controller
{
$config = [];
- $result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['ignore_kollision', 'kollision_student', 'ignore_reservierung', 'ignore_zeitsperre']);
+ $result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['ignore_kollision', 'kollision_student', 'ignore_reservierung', 'ignore_zeitsperre', 'ignore_resources_collisions']);
$data = $this->getDataOrTerminateWithError($result);
$config['ignore_kollision'] = [
@@ -61,7 +61,11 @@ class Config extends FHCAPI_Controller
"value" => ($data['ignore_zeitsperre'] ?? 'false') === 'true'
];
-
+ $config['ignore_resources_collisions'] = [
+ "type" => "checkbox",
+ "label" => $this->p->t('ui', 'ignore_resources_collisions'),
+ "value" => ($data['ignore_resources_collisions'] ?? 'false') === 'true'
+ ];
$this->terminateWithSuccess($config);
}
@@ -108,6 +112,11 @@ class Config extends FHCAPI_Controller
'ignore_zeitsperre',
$this->input->post('ignore_zeitsperre') === true ? 'true' : 'false'
);
+ $this->_ci->VariableModel->setVariable(
+ getAuthUID(),
+ 'ignore_resources_collisions',
+ $this->input->post('ignore_resources_collisions') === true ? 'true' : 'false'
+ );
$this->terminateWithSuccess();
}
diff --git a/application/controllers/api/frontend/v1/tempus/Kalender.php b/application/controllers/api/frontend/v1/tempus/Kalender.php
index 833d0c0aa..aa2687126 100644
--- a/application/controllers/api/frontend/v1/tempus/Kalender.php
+++ b/application/controllers/api/frontend/v1/tempus/Kalender.php
@@ -20,6 +20,7 @@ class Kalender extends FHCAPI_Controller
'getPlan' => self::PERM_LOGGED,
'getPlanByOrt' => self::PERM_LOGGED,
'getRaumvorschlag' => self::PERM_LOGGED,
+ 'getLehreinheiten' => 'lehre/lvplan:rw',
'getHistory' => 'lehre/lvplan:rw',
'deleteEntry' => 'lehre/lvplan:rw',
'syncToLecturer' => 'lehre/lvplan:rw',
@@ -29,6 +30,8 @@ class Kalender extends FHCAPI_Controller
'getZeitwuensche' => self::PERM_LOGGED,
'getZeitsperren' => self::PERM_LOGGED,
'updateKalenderEvent' => 'lehre/lvplan:rw',
+ 'deleteOrtEntry' => 'lehre/lvplan:rw',
+ 'deleteFromKalenderEvent' => 'lehre/lvplan:rw',
'addKalenderEvent' => 'lehre/lvplan:rw',
'calculateMultiWeekPlan' => 'lehre/lvplan:rw',
'confirmMultiWeekPlan' => 'lehre/lvplan:rw',
@@ -225,7 +228,24 @@ class Kalender extends FHCAPI_Controller
if (isError($result))
$this->terminateWithError(getError($result), $result->code);
- $this->terminateWithSuccess();
+ $this->terminateWithSuccess(getData($result));
+ }
+
+ public function deleteOrtEntry()
+ {
+ $this->_ci->form_validation->set_data($_POST);
+ $this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $kalender_id = $this->_ci->input->post('kalender_id', TRUE);
+ $result = $this->_ci->kalenderlib->updateOrt($kalender_id, []);
+
+ if (isError($result))
+ $this->terminateWithError(getError($result), $result->code);
+
+ $this->terminateWithSuccess(getData($result));
}
public function getRaumvorschlag()
@@ -236,6 +256,19 @@ class Kalender extends FHCAPI_Controller
$this->terminateWithSuccess($this->_ci->raumvorschlaglib->getVorschlaege($filter->kalender_id));
}
+ public function getLehreinheiten()
+ {
+ $this->_ci->form_validation->set_data($_GET);
+ $this->_ci->form_validation->set_rules('kalender_id', "kalender_id", "required");
+ $kalender_id = $this->_ci->input->get('kalender_id', TRUE);
+ $result = $this->_ci->kalenderlib->getLehreinheiten($kalender_id);
+
+ if (isError($result))
+ $this->terminateWithError(getError($result));
+
+ $this->terminateWithSuccess(hasData($result) ? getData($result) : []);
+ }
+
public function getHistory()
{
$this->_ci->form_validation->set_data($_GET);
@@ -396,6 +429,27 @@ class Kalender extends FHCAPI_Controller
$this->terminateWithSuccess(getData($result));
}
+ public function deleteFromKalenderEvent()
+ {
+ $this->_ci->form_validation->set_data($_POST);
+ $this->_ci->form_validation->set_rules('kalender_id',"kalender_id","required");
+ $this->_ci->form_validation->set_rules('lehreinheit_ids[]',"lehreinheit_ids","required");
+
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $kalender_id = $this->_ci->input->post('kalender_id', TRUE);
+ $lehreinheit_ids = $this->_ci->input->post('lehreinheit_ids', TRUE);
+
+ $result = $this->_ci->kalenderlib->deleteFromKalenderEvent($kalender_id, $lehreinheit_ids);
+
+ if (isError($result))
+ $this->terminateWithError(getError($result));
+
+ $this->terminateWithSuccess(getData($result));
+ }
+
private function _checkFilter($filters)
{
diff --git a/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php
new file mode 100644
index 000000000..376a0fedc
--- /dev/null
+++ b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php
@@ -0,0 +1,84 @@
+ ['admin:r', 'assistenz:r'],
+ 'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w'],
+ 'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r'],
+ ]);
+
+ $this->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
+ $this->load->model('ressource/Betriebsmittel_model', 'BetriebsmittelModel');
+ $this->load->model('ressource/Kalender_model', 'KalenderModel');
+
+ $this->load->library('CollisionChecker');
+ $this->load->library('KalenderLib');
+ }
+
+ //------------------------------------------------------------------------------------------------------------------
+ // Public methods
+ public function getSchedulableResourcesByCalendar($calenderID)
+ {
+ if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'");
+
+ $result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
+ if (isError($result)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
+
+ $calender = $this->getDataOrTerminateWithError($result)[0];
+ if (!isset($calender)) $this->terminateWithError("Calendar with id '$calenderID' not found");
+
+ $result = $this->BetriebsmittelModel->getSchedulableEntriesByDatetimeInterval($calender->von, $calender->bis);
+ $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
+ }
+
+ public function getAssignedResourcesByCalender($calenderID)
+ {
+ if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'");
+
+ $result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
+ if (empty($result)) $this->terminateWithError("Calendar with id '$calenderID' not found");
+
+ $calenderGroupID = $this->getDataOrTerminateWithError($result)[0]->eindeutige_gruppen_id;
+ if (!isset($calenderGroupID)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
+
+
+ $this->BetriebsmittelKalenderModel->addSelect(['tbl_betriebsmittel_kalender.*', 'tbl_betriebsmittel.beschreibung', 'tbl_betriebsmittel.verplanen']);
+ $this->BetriebsmittelKalenderModel->addJoin('wawi.tbl_betriebsmittel', 'betriebsmittel_id');
+ $result = $this->BetriebsmittelKalenderModel->loadWhere([
+ 'eindeutige_kalender_gruppen_id' => $calenderGroupID,
+ 'tbl_betriebsmittel.verplanen' => true,
+ ]);
+
+ $this->terminateWithSuccess($this->getDataOrTerminateWithError($result));
+ }
+
+ public function storeResourcesToCalendarRelationship()
+ {
+ $calenderID = $this->input->post('kalender_id');
+ $assignedResources = $this->input->post('assignedResources');
+
+ if (!isset($calenderID)) $this->terminateWithError("Missing required parameter 'kalender_id'", 'general');
+ if (!isset($assignedResources)) $this->terminateWithError("Missing required parameter 'assignedResources'", 'general');
+
+ $result = $this->KalenderModel->loadWhere(['kalender_id' => $calenderID]);
+ if (empty($result)) $this->terminateWithError("Calendar with id '$calenderID' not found");
+
+ $calendar = $this->getDataOrTerminateWithError($result)[0];
+
+ $calenderGroupID = $calendar->eindeutige_gruppen_id;
+ if (!isset($calenderGroupID)) $this->terminateWithError("Calendar with id '$calenderID' does not have a valid group id");
+
+ $result = $this->kalenderlib->addOperationalResourcesToKalenderEvent($calendar, $assignedResources);
+ if (isError($result))
+ $this->terminateWithError(getError($result));
+
+ $this->terminateWithSuccess(['message' => 'Resources assigned successfully']);
+ }
+}
diff --git a/application/controllers/api/frontend/v1/tempus/Reservierung.php b/application/controllers/api/frontend/v1/tempus/Reservierung.php
index be22d96e9..1b1baa963 100644
--- a/application/controllers/api/frontend/v1/tempus/Reservierung.php
+++ b/application/controllers/api/frontend/v1/tempus/Reservierung.php
@@ -154,21 +154,23 @@ class Reservierung extends FHCAPI_Controller
}
public function addReservierung()
{
+ $this->_ci->form_validation->set_rules('titel', "titel", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
+ $this->_ci->form_validation->set_rules('beschreibung', "beschreibung", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
+ $this->_ci->form_validation->set_rules('start_date', "start_date", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
+ $this->_ci->form_validation->set_rules('end_date', "end_date", "required", ['required' => $this->p->t('ui', 'error_fieldRequired')]);
- $this->_ci->form_validation->set_data($_POST);
- $this->_ci->form_validation->set_rules('titel',"titel","required");
- $this->_ci->form_validation->set_rules('beschreibung',"beschreibung","required");
- $this->_ci->form_validation->set_rules('ort_kurzbz[]',"ort_kurzbz","required");
- $this->_ci->form_validation->set_rules('start_date',"start_date","required");
- $this->_ci->form_validation->set_rules('end_date',"end_date","required");
-
-
- if($this->_ci->form_validation->run() === FALSE)
+ if ($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+ $ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
+
+ if (empty($ort_kurzbz) || !is_array($ort_kurzbz))
+ {
+ $this->terminateWithValidationErrors(['ort_kurzbz' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Raum'])]);
+ }
+
$titel = $this->_ci->input->post('titel', TRUE);
$beschreibung = $this->_ci->input->post('beschreibung', TRUE);
- $ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
$start_date = $this->_ci->input->post('start_date', TRUE);
$end_date = $this->_ci->input->post('end_date', TRUE);
$teilnehmer = $this->_ci->input->post('teilnehmer', TRUE);
diff --git a/application/controllers/system/MigrateKalender.php b/application/controllers/system/MigrateKalender.php
index f9d7416e5..49e895dbc 100644
--- a/application/controllers/system/MigrateKalender.php
+++ b/application/controllers/system/MigrateKalender.php
@@ -264,7 +264,108 @@ class MigrateKalender extends CLI_Controller
}
}
+ public function migrateStundenplanBetriebsmittelEntries() {
+ $this->setKalendarEntriesGroupIDs();
+ $this->setKalendarEntriesGroupIDsForChildren();
+ $dbModel = new DB_Model();
+
+ $deleteOldImportedTempusEntriesQuery = "DELETE from lehre.tbl_betriebsmittel_kalender WHERE quelle != 'tempus_neu' OR quelle IS NULL;";
+ $createHelperTypeQuery = "DO $$
+ BEGIN
+ IF NOT EXISTS (
+ SELECT 1
+ FROM pg_type
+ WHERE typname = 'betriebsmittel_info'
+ ) THEN
+ CREATE TYPE betriebsmittel_info AS (
+ betriebsmittel_id bigint,
+ insertamum timestamp,
+ insertvon text
+ );
+ END IF;
+ END $$;";
+
+ $query = $deleteOldImportedTempusEntriesQuery .
+ $createHelperTypeQuery .
+ "WITH test AS (
+ SELECT
+ tk.eindeutige_gruppen_id AS eindeutige_gruppen_id,
+ array_agg(tk.kalender_id),
+ array_agg(
+ ROW(tsb.betriebsmittel_id, tsb.insertamum, tsb.insertvon)::betriebsmittel_info
+ ) AS betriebsmittel_data
+ FROM sync.tbl_stundenplandev_kalender AS sk
+ JOIN lehre.tbl_kalender tk ON tk.kalender_id = sk.kalender_id
+ JOIN lehre.tbl_stundenplan_betriebsmittel tsb ON tsb.stundenplandev_id = sk.stundenplandev_id
+ GROUP BY tk.eindeutige_gruppen_id
+ )
+ INSERT INTO lehre.tbl_betriebsmittel_kalender (
+ eindeutige_kalender_gruppen_id,
+ betriebsmittel_id,
+ insertamum,
+ insertvon
+ )
+ SELECT
+ t.eindeutige_gruppen_id,
+ bm.betriebsmittel_id,
+ bm.insertamum,
+ bm.insertvon
+ FROM test t
+ CROSS JOIN LATERAL unnest(t.betriebsmittel_data) AS bm
+ ON CONFLICT (eindeutige_kalender_gruppen_id, betriebsmittel_id) DO NOTHING;
+ ;";
+
+ $dbModel->db->query($query);
+ }
+
+ private function setKalendarEntriesGroupIDs() {
+ $dbModel = new DB_Model();
+
+ $query = "UPDATE lehre.tbl_kalender
+ SET eindeutige_gruppen_id = gen_random_uuid()
+ WHERE vorgaenger_kalender_id IS NULL
+ AND eindeutige_gruppen_id IS NULL;";
+
+ $dbModel->db->query($query);
+
+ }
+
+ private function setKalendarEntriesGroupIDsForChildren() {
+ $dbModel = new DB_Model();
+
+ $query = "WITH RECURSIVE tree AS
+ (
+ SELECT
+ kalender_id,
+ vorgaenger_kalender_id,
+ kalender_id AS root_id,
+ eindeutige_gruppen_id as root_eindeutige_gruppen_id
+ FROM lehre.tbl_kalender
+ WHERE vorgaenger_kalender_id IS NULL
+
+ UNION ALL
+
+ SELECT
+ i.kalender_id,
+ i.vorgaenger_kalender_id,
+ t.root_id,
+ t.root_eindeutige_gruppen_id
+ FROM lehre.tbl_kalender i
+ JOIN tree t
+ ON i.vorgaenger_kalender_id = t.kalender_id
+ where i.eindeutige_gruppen_id is NULL
+
+ )
+ UPDATE lehre.tbl_kalender k
+ SET eindeutige_gruppen_id = t.root_eindeutige_gruppen_id
+ FROM tree t
+ WHERE k.kalender_id = t.kalender_id
+ AND k.eindeutige_gruppen_id IS NULL;";
+
+ $dbModel->db->query($query);
+ }
+
private function _insertKalender($block, $typ)
{
$result = $this->KalenderModel->insert(
diff --git a/application/helpers/hlp_common_helper.php b/application/helpers/hlp_common_helper.php
index 06cfa1cfd..b9ce6b200 100644
--- a/application/helpers/hlp_common_helper.php
+++ b/application/helpers/hlp_common_helper.php
@@ -570,3 +570,13 @@ function buildDropdownEntryPrintArray($id, $name, $parameterurl, $uid=null, $ord
];
}
+
+function generateUUID()
+{
+ $data = openssl_random_pseudo_bytes(16);
+
+ $data[6] = chr(ord($data[6]) & 0x0f | 0x40);
+ $data[8] = chr(ord($data[8]) & 0x3f | 0x80);
+
+ return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
+}
\ No newline at end of file
diff --git a/application/libraries/CollisionChecker.php b/application/libraries/CollisionChecker.php
index b7921a6d9..ac9152d2b 100644
--- a/application/libraries/CollisionChecker.php
+++ b/application/libraries/CollisionChecker.php
@@ -18,10 +18,12 @@ class CollisionChecker
$this->_ci->load->library('collision/checks/LectureCollisionCheck');
$this->_ci->load->library('collision/checks/VerbandCollisionCheck');
$this->_ci->load->library('collision/checks/StudentCollisionCheck');
+ $this->_ci->load->library('collision/checks/ResourcesCollisionCheck');
$this->register($this->_ci->roomcollisioncheck);
$this->register($this->_ci->lecturecollisioncheck);
$this->register($this->_ci->verbandcollisioncheck);
$this->register($this->_ci->studentcollisioncheck);
+ $this->register($this->_ci->resourcescollisioncheck);
Events::trigger('collision_register', $this);
}
diff --git a/application/libraries/KalenderLib.php b/application/libraries/KalenderLib.php
index efc401ad1..174063819 100644
--- a/application/libraries/KalenderLib.php
+++ b/application/libraries/KalenderLib.php
@@ -14,6 +14,7 @@ class KalenderLib
$this->_ci->load->model('ressource/Kalender_Event_model', 'KalenderEventModel');
$this->_ci->load->model('ressource/Kalender_Event_Teilnehmer_model', 'KalenderEventTeilnehmerModel');
$this->_ci->load->model('ressource/Kalender_Ort_model', 'KalenderOrtModel');
+ $this->_ci->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
$this->_ci->load->model('education/Lehreinheit_model', 'LehreinheitModel');
$this->_ci->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->_ci->load->model('education/LehreinheitMitarbeiter_model', 'LehreinheitMitarbeiterModel');
@@ -38,6 +39,7 @@ class KalenderLib
$end_date = date('Y-m-d', strtotime($end_date . ' +1 day'));
$this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id,
+ tbl_kalender.eindeutige_gruppen_id,
tbl_kalender.status_kurzbz,
tbl_kalender.typ,
tbl_kalender.von,
@@ -134,6 +136,8 @@ class KalenderLib
$this->_ci->KalenderModel->db->where('tbl_kalender.von >=', $start_date);
$this->_ci->KalenderModel->db->where('tbl_kalender.bis <', $end_date);
+
+ $this->_ci->KalenderModel->addOrder('tbl_kalender.eindeutige_gruppen_id', 'DESC');
}
private function _mapEvents($data, $collisionCheck = true)
@@ -155,6 +159,7 @@ class KalenderLib
$bis = new DateTime($row->bis);
$events[$id] = (object) [
+ 'eindeutige_gruppen_id' => $row->eindeutige_gruppen_id,
'type' => $row->typ,
'beginn' => $von->format('H:i:s'),
'ende' => $bis->format('H:i:s'),
@@ -179,7 +184,8 @@ class KalenderLib
'titel' => isset($row->titel) ? $row->titel : '',
'beschreibung' => isset($row->beschreibung) ? $row->beschreibung : '',
'topic' => [],
- 'collisions' => false
+ 'collisions' => false,
+ 'has_assigned_resources' => isset($row->has_assigned_resources) ? $row->has_assigned_resources : false,
];
}
@@ -436,6 +442,14 @@ class KalenderLib
WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)', null, false);
$this->_ci->KalenderModel->db->where_not_in('status_kurzbz', array('deleted'));
+
+ $this->_ci->KalenderModel->addSelect([
+ "(
+ SELECT COUNT(*) FROM lehre.tbl_betriebsmittel_kalender
+ WHERE tbl_betriebsmittel_kalender.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_gruppen_id
+ ) AS has_assigned_resources"
+ ]);
+
$data = $this->_ci->KalenderModel->load();
return $this->_mapEvents($data);
@@ -579,9 +593,20 @@ class KalenderLib
public function addToKalenderEvent($target_kalender_id, $lehreinheit_id)
{
- $check = $this->_ci->KalenderLehreinheitModel->loadWhere(array('kalender_id' => $target_kalender_id, 'lehreinheit_id' => $lehreinheit_id));
+ $entryResult = $this->_loadKalenderEntry($target_kalender_id);
+ if (isError($entryResult)) return $entryResult;
- if (hasData($check))
+ $kalender_entry = getData($entryResult);
+
+ if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
+ 'errorCode' => 'entry_not_editable'
+ ]);
+ }
+
+ if (in_array($lehreinheit_id, $kalender_entry->lehreinheit_id))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'already_present'),
@@ -589,6 +614,12 @@ class KalenderLib
]);
}
+ $lehreinheit_ids = $kalender_entry->lehreinheit_id;
+ $lehreinheit_ids[] = $lehreinheit_id;
+
+ if (in_array($kalender_entry->status_kurzbz, array('live', 'preview')))
+ return success($this->_createHistoryEntry($kalender_entry, null, null, null, $lehreinheit_ids));
+
$kalenderlehreinheitresult = $this->_ci->KalenderLehreinheitModel->insert(
array(
'kalender_id' => $target_kalender_id,
@@ -602,6 +633,50 @@ class KalenderLib
return success($target_kalender_id);
}
+
+ public function deleteFromKalenderEvent($kalender_id, $lehreinheit_ids)
+ {
+ $entryResult = $this->_loadKalenderEntry($kalender_id);
+ if (isError($entryResult)) return $entryResult;
+
+ $kalender_entry = getData($entryResult);
+
+ if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
+ 'errorCode' => 'entry_not_editable'
+ ]);
+ }
+
+ $remaining_ids = array_values(array_diff($kalender_entry->lehreinheit_id, $lehreinheit_ids));
+
+ if (in_array($kalender_entry->status_kurzbz, array('live', 'preview')))
+ return success($this->_createHistoryEntry($kalender_entry, null, null, null, $remaining_ids));
+
+ $count = 0;
+ foreach ($lehreinheit_ids as $lehreinheit_id)
+ {
+ $check = $this->_ci->KalenderLehreinheitModel->loadWhere(array('kalender_id' => $kalender_id, 'lehreinheit_id' => $lehreinheit_id));
+
+ if (hasData($check))
+ {
+ $kalenderlehreinheitresult = $this->_ci->KalenderLehreinheitModel->delete(
+ array(
+ 'kalender_id' => $kalender_id,
+ 'lehreinheit_id' => $lehreinheit_id
+ )
+ );
+
+ if (isError($kalenderlehreinheitresult))
+ return $kalenderlehreinheitresult;
+
+ $count++;
+ }
+ }
+ return success($count);
+ }
+
private function _addWeeks($date_str, $weeks)
{
$d = new DateTime($date_str);
@@ -633,6 +708,7 @@ class KalenderLib
'bis' => $end_date,
'typ' => 'lehreinheit',
'status_kurzbz' => 'planning',
+ 'eindeutige_gruppen_id' => $this->_ci->KalenderModel->generateUniqueGroupId(),
'insertvon' => getAuthUID(),
'insertamum' => date('Y-m-d H:i:s')
)
@@ -990,6 +1066,81 @@ class KalenderLib
return $kalenderresult;
}
+ public function addOperationalResourcesToKalenderEvent($calendar, $assignedResources)
+ {
+ $checkerData = new stdClass();
+ $checkerData->kalender_id = $calendar->kalender_id;
+ $checkerData->betriebsmittel_ids = [];
+ $checkerData->von = $calendar->von;
+ $checkerData->bis = $calendar->bis;
+
+ foreach ($assignedResources as $assignedResource) {
+ array_push($checkerData->betriebsmittel_ids, $assignedResource['betriebsmittel_id']);
+ }
+
+ $errors = [];
+ $result = $this->_ci->collisionchecker->run($checkerData);
+ if (!empty($result))
+ {
+ $errors = $result;
+ }
+
+ if (!empty($errors)) {
+ return error($errors);
+ }
+
+ $this->_ci->db->trans_start();
+
+ $allowedResourceIDs = array_filter(array_map(
+ function ($resource) {
+ return $resource['betriebsmittel_id'] ?? null;
+ },
+ $assignedResources
+ ));
+
+ if (!empty($allowedResourceIDs)) {
+ $placeholders = implode(',', array_fill(0, count($allowedResourceIDs), '?'));
+
+ $query = "
+ DELETE FROM lehre.tbl_betriebsmittel_kalender
+ WHERE eindeutige_kalender_gruppen_id = ?
+ AND betriebsmittel_id NOT IN ($placeholders)
+ ";
+
+ $params = array_merge(
+ [$calendar->eindeutige_gruppen_id],
+ $allowedResourceIDs
+ );
+
+ $this->_ci->db->query($query, $params);
+ } else {
+ $this->_ci->db->where('eindeutige_kalender_gruppen_id', $calendar->eindeutige_gruppen_id);
+ $this->_ci->db->delete('lehre.tbl_betriebsmittel_kalender');
+ }
+
+ foreach ($assignedResources as $assignedResource) {
+ $data = [
+ 'eindeutige_kalender_gruppen_id' => $calendar->eindeutige_gruppen_id,
+ 'betriebsmittel_id' => $assignedResource['betriebsmittel_id'],
+ 'anmerkung' => $assignedResource['anmerkung'] ?? null,
+ 'quelle' => 'tempus_neu',
+ 'updateamum' => date('c'),
+ 'updatevon' => getAuthUid(),
+ ];
+ if (isset($assignedResource['betriebsmittel_kalender_id'])) {
+ $result = $this->_ci->BetriebsmittelKalenderModel->update($assignedResource['betriebsmittel_kalender_id'], $data);
+ } else {
+ $result = $this->_ci->BetriebsmittelKalenderModel->insert(array_merge($data, [
+ 'insertvon' => getAuthUid(),
+ 'updateamum' => date('c'),
+ ]));
+ }
+ }
+ $this->_ci->db->trans_complete();
+
+ return success('Operational resources added to calendar event successfully.');
+ }
+
private function _addTeilnehmerToEvent($kalender_id, $uid, $rolle)
{
return $this->_ci->KalenderEventTeilnehmerModel->insert(
@@ -1090,6 +1241,18 @@ class KalenderLib
$kalender_entry = getData($entryResult);
+ $calendarResources = $this->_ci->BetriebsmittelKalenderModel->loadWhere(['eindeutige_kalender_gruppen_id' => $kalender_entry->eindeutige_gruppen_id]);
+ if (isError($calendarResources)) return $calendarResources;
+
+ $calendarResourcesItems = getData($calendarResources);
+ $calendarResourcesIDs = [];
+ if (is_array($calendarResourcesItems)) {
+ $calendarResourcesIDs = array_map(function($resource) {
+ return $resource->betriebsmittel_id;
+ }, getData($calendarResources));
+ }
+
+ $kalender_entry->betriebsmittel_ids = $calendarResourcesIDs;
$kalender_entry->ort_kurzbz = !is_null($ort_kurzbz) ? (array) $ort_kurzbz : $kalender_entry->ort_kurzbz;
$kalender_entry->von = $start_time ?? $kalender_entry->von;
$kalender_entry->bis = $end_time ?? $kalender_entry->bis;
@@ -1098,7 +1261,9 @@ class KalenderLib
if (!empty($errors)) return error($errors);
- if (!is_null($ort_kurzbz) && !empty($ort_kurzbz))
+ $result = $kalender_entry;
+
+ if (!is_null($ort_kurzbz))
{
$result = $this->updateOrt($kalender_id, $ort_kurzbz);
if (isError($result)) return $result;
@@ -1115,7 +1280,7 @@ class KalenderLib
if (isError($result)) return $result;
}
- return success('Erfolgreich');
+ return success($result);
}
public function updateZeit($kalender_id, $start_date, $end_date)
@@ -1150,6 +1315,39 @@ class KalenderLib
);
}
+ public function getLehreinheiten($kalender_id)
+ {
+ $entryResult = $this->_loadKalenderEntry($kalender_id);
+ if (isError($entryResult)) return $entryResult;
+
+ $entryResult = getData($entryResult);
+
+ $result = [];
+
+ foreach ($entryResult->lehreinheit_id as $lehreinheit_id)
+ {
+ $this->_ci->LehreinheitModel->addSelect('lehrfach.kurzbz AS lehrfach_kurzbz,
+ tbl_lehreinheit.lehrform_kurzbz,
+ lehrfach.bezeichnung AS lehrfach_bezeichnung');
+ $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id', 'LEFT');
+ $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id', 'LEFT');
+ $lehreinheit = $this->_ci->LehreinheitModel->load($lehreinheit_id);
+
+ if (!hasData($lehreinheit))
+ return error('Lehreinheit nicht gefunden');
+ $lehreinheit = getData($lehreinheit)[0];
+
+ $topic = trim((isset($lehreinheit->lehrfach_kurzbz) ? $lehreinheit->lehrfach_kurzbz : '').' '.(isset($lehreinheit->lehrform_kurzbz) ? $lehreinheit->lehrform_kurzbz : ''));
+
+ $result[] = (object)[
+ 'lehreinheit_id' => $lehreinheit_id,
+ 'title' => $topic,
+ ];
+ }
+
+ return success($result);
+ }
+
public function updateOrt($kalender_id, $ort_kurzbz_array)
{
$ort_kurzbz_array = (array)$ort_kurzbz_array;
@@ -1226,7 +1424,7 @@ class KalenderLib
return success();
}
- private function _createHistoryEntry($kalender_entry, $start_date = null, $end_date = null, $ort_kurzbz_array = null)
+ private function _createHistoryEntry($kalender_entry, $start_date = null, $end_date = null, $ort_kurzbz_array = null, $lehreinheit_id_array = null)
{
$old_id = $kalender_entry->kalender_id;
@@ -1237,6 +1435,7 @@ class KalenderLib
'typ' => 'lehreinheit',
'status_kurzbz' => 'planning',
'vorgaenger_kalender_id' => $old_id,
+ 'eindeutige_gruppen_id' => $kalender_entry->eindeutige_gruppen_id,
'insertvon' => getAuthUID(),
'insertamum' => date('Y-m-d H:i:s')
)
@@ -1247,7 +1446,7 @@ class KalenderLib
$new_kalender_id = getData($kalenderresult);
- $lehreinheit_ids = (array) $kalender_entry->lehreinheit_id;
+ $lehreinheit_ids = !is_null($lehreinheit_id_array) ? $lehreinheit_id_array : $kalender_entry->lehreinheit_id;
foreach ($lehreinheit_ids as $lehreinheit_id)
{
@@ -1262,7 +1461,7 @@ class KalenderLib
return $kalenderlehreinheitresult;
}
- if (!empty($ort_kurzbz_array))
+ if (!is_null($ort_kurzbz_array))
{
$new_orte = (array) $ort_kurzbz_array;
$new_locations = array_fill(0, count($new_orte), null);
@@ -1289,7 +1488,6 @@ class KalenderLib
return success($new_kalender_id);
}
-
private function _loadKalenderEntry($kalender_id)
{
$this->_ci->KalenderModel->addSelect('
@@ -1447,7 +1645,7 @@ class KalenderLib
public function getHistory($kalender_id, $only_previous = false)
{
$dbModel = new DB_Model();
- $history_entries = $dbModel->execReadOnlyQuery('
+ $history_entries = $dbModel->execReadOnlyQuery("
WITH RECURSIVE
vorgaenger(kalender_id, vorgaenger_kalender_id) AS (
SELECT kalender_id, vorgaenger_kalender_id
@@ -1470,21 +1668,27 @@ class KalenderLib
SELECT k.kalender_id, k.vorgaenger_kalender_id
FROM lehre.tbl_kalender k
JOIN nachfolger ON k.vorgaenger_kalender_id = nachfolger.kalender_id
+ ),
+ orte AS (
+ SELECT kalender_id,
+ STRING_AGG(COALESCE(ort_kurzbz, location), ', ' ORDER BY ort_kurzbz) AS ort
+ FROM lehre.tbl_kalender_ort
+ GROUP BY kalender_id
)
SELECT tbl_kalender.*,
- TO_CHAR(von, \'DD.MM.YYYY HH24:MI:SS\') as von,
- TO_CHAR(bis, \'DD.MM.YYYY HH24:MI:SS\') as bis,
- COALESCE(tbl_kalender_ort.ort_kurzbz, location) as ort
+ TO_CHAR(von, 'DD.MM.YYYY HH24:MI:SS') as von,
+ TO_CHAR(bis, 'DD.MM.YYYY HH24:MI:SS') as bis,
+ orte.ort
FROM (
SELECT kalender_id FROM vorgaenger
UNION
SELECT kalender_id FROM nachfolger
) combined
JOIN lehre.tbl_kalender USING(kalender_id)
- LEFT JOIN lehre.tbl_kalender_ort USING(kalender_id)
+ LEFT JOIN orte USING(kalender_id)
ORDER BY kalender_id DESC
- ' . ($only_previous ? ' LIMIT 1' : ''), array($kalender_id, $kalender_id));
+ " . ($only_previous ? ' LIMIT 1' : ''), array($kalender_id, $kalender_id));
return $history_entries;
}
diff --git a/application/libraries/RaumvorschlagLib.php b/application/libraries/RaumvorschlagLib.php
index f36ef2cfa..8cb4aa8a4 100644
--- a/application/libraries/RaumvorschlagLib.php
+++ b/application/libraries/RaumvorschlagLib.php
@@ -62,6 +62,14 @@ class RaumvorschlagLib
$kandidaten = $this->_getRaumkandidaten($event);
if (empty($kandidaten)) return [];
+ $unique = [];
+
+ foreach ($kandidaten as $raum)
+ {
+ $unique[$raum->ort_kurzbz] = $raum;
+ }
+
+ $kandidaten = array_values($unique);
$ratings = [];
foreach ($kandidaten as $raum)
@@ -82,7 +90,7 @@ class RaumvorschlagLib
usort($ratings, function($a, $b)
{
- return $b['score'] - $a['score'];
+ return $b['score'] <=> $a['score'];
});
return $ratings;
@@ -213,21 +221,33 @@ class RaumvorschlagLib
private function _getRaumkandidaten($event)
{
- $lehreinheit = $this->_ci->LehreinheitModel->load($event->lehreinheit_id[0]);
- if (!hasData($lehreinheit)) return [];
- $lehreinheit = getData($lehreinheit)[0];
+ $raumtyp = null;
+ $raumtypalternativ = null;
+ if (!empty($event->lehreinheit_id))
+ {
+ $lehreinheit = $this->_ci->LehreinheitModel->load($event->lehreinheit_id[0]);
+ if (hasData($lehreinheit))
+ {
+ $lehreinheit = getData($lehreinheit)[0];
+ $raumtyp = $lehreinheit->raumtyp ?? null;
+ $raumtypalternativ = $lehreinheit->raumtypalternativ ?? null;
+ }
+ }
+
+ $this->_ci->KalenderModel->addDistinct('tbl_kalender_ort.ort_kurzbz');
$this->_ci->KalenderModel->addSelect('tbl_kalender_ort.ort_kurzbz');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id');
$this->_ci->KalenderModel->db->where('tbl_kalender.von <', $event->isoend);
$this->_ci->KalenderModel->db->where('tbl_kalender.bis >', $event->isostart);
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $event->kalender_id);
$this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['deleted']);
$this->_ci->KalenderModel->db->where('tbl_kalender_ort.ort_kurzbz IS NOT NULL', null, false);
$belegte = $this->_ci->KalenderModel->load();
$belegte_orte = hasData($belegte) ? array_column(getData($belegte), 'ort_kurzbz') : [];
- if (empty($lehreinheit->raumtyp))
+ if (empty($raumtyp))
{
$raeume = $this->_getFreieRaeume(null, $belegte_orte);
return hasData($raeume) ? getData($raeume) : [];
@@ -235,14 +255,14 @@ class RaumvorschlagLib
$vorschlaege = [];
- $raeume = $this->_getFreieRaeume($lehreinheit->raumtyp, $belegte_orte);
+ $raeume = $this->_getFreieRaeume($raumtyp, $belegte_orte);
if (hasData($raeume))
$vorschlaege = getData($raeume);
- if (count($vorschlaege) < 5 && !empty($lehreinheit->raumtypalternativ))
+ if (count($vorschlaege) < 5 && !empty($raumtypalternativ))
{
$bereits_gefunden = array_merge($belegte_orte, array_column($vorschlaege, 'ort_kurzbz'));
- $alternativ = $this->_getFreieRaeume($lehreinheit->raumtypalternativ, $bereits_gefunden);
+ $alternativ = $this->_getFreieRaeume($raumtypalternativ, $bereits_gefunden);
if (!isError($alternativ) && hasData($alternativ))
$vorschlaege = array_merge($vorschlaege, getData($alternativ));
@@ -255,7 +275,12 @@ class RaumvorschlagLib
{
$this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id');
$this->_ci->OrtModel->addJoin('public.tbl_ortraumtyp', 'ort_kurzbz');
- $this->_ci->OrtModel->db->where('raumtyp_kurzbz', $raumtyp);
+
+ if (!empty($raumtyp))
+ $this->_ci->OrtModel->db->where('raumtyp_kurzbz', $raumtyp);
+ else
+ $this->_ci->OrtModel->db->where('reservieren', true);
+
$this->_ci->OrtModel->db->where('aktiv', true);
$this->_ci->OrtModel->db->where("ort_kurzbz NOT LIKE '\_%'", null, false);
diff --git a/application/libraries/collision/checks/LectureCollisionCheck.php b/application/libraries/collision/checks/LectureCollisionCheck.php
index ff8303adb..21635e203 100644
--- a/application/libraries/collision/checks/LectureCollisionCheck.php
+++ b/application/libraries/collision/checks/LectureCollisionCheck.php
@@ -9,7 +9,7 @@ class LectureCollisionCheck implements ICollisionCheck
{
$this->_ci =& get_instance();
$this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
- $this->_ci->load->model('ressource/zeitsperre_model', 'ZeitsperreModel');
+ $this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
diff --git a/application/libraries/collision/checks/ResourcesCollisionCheck.php b/application/libraries/collision/checks/ResourcesCollisionCheck.php
new file mode 100644
index 000000000..0be789b7f
--- /dev/null
+++ b/application/libraries/collision/checks/ResourcesCollisionCheck.php
@@ -0,0 +1,85 @@
+_ci =& get_instance();
+ $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
+ $this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
+ $this->_ci->load->library('PhrasesLib', array('ui'));
+ }
+
+ public function getName()
+ {
+ return 'resources';
+ }
+
+ public function check($data)
+ {
+ if (!isset($data->betriebsmittel_ids, $data->von, $data->bis, $data->kalender_id)) return [];
+
+ if (empty($data->betriebsmittel_ids)) return [];
+
+ if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
+ if ($this->_ci->variablelib->getVar('ignore_resources_collisions') === 'true') return [];
+
+ $this->_ci->KalenderModel->addSelect('kalender_id, von, bis, bm.beschreibung AS betriebsmittel_beschreibung');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender bk', 'bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_gruppen_id');
+ $this->_ci->KalenderModel->addJoin('wawi.tbl_betriebsmittel bm', 'bm.betriebsmittel_id = bk.betriebsmittel_id');
+
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
+ $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
+ $this->_ci->KalenderModel->db->where_in('bk.betriebsmittel_id', $data->betriebsmittel_ids);
+
+
+ $result = $this->_ci->KalenderModel->loadWhere(array(
+ 'von <' => $data->bis,
+ 'bis >' => $data->von,
+ ));
+
+ if (isError($result)) return [];
+ if (!hasData($result)) return [];
+
+ return array_map(function($row)
+ {
+ return [
+ 'errorCode' => 'resource_collision',
+ 'message' => $this->_ci->phraseslib->t('ui', 'resource_collision') . ': ' . $row->betriebsmittel_beschreibung . ' (' . date('d.m.Y H:i', strtotime($row->von)) . ' - ' . date('d.m.Y H:i', strtotime($row->bis)) . ')'
+ ];
+ }, getData($result));
+ }
+
+ public function checkAll($kalender_ids)
+ {
+ if (empty($kalender_ids)) return [];
+
+ $this->_ci->KalenderModel->addSelect('DISTINCT ON (tbl_kalender.kalender_id) tbl_kalender.kalender_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender current_bk', 'current_bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_gruppen_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender other_bk', 'other_bk.betriebsmittel_id = current_bk.betriebsmittel_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_kalender other_kalender', 'other_kalender.eindeutige_gruppen_id = other_bk.eindeutige_kalender_gruppen_id');
+
+ $this->_ci->KalenderModel->db->where('other_kalender.kalender_id != tbl_kalender.kalender_id', null, false);
+ $this->_ci->KalenderModel->db->where('other_kalender.von < tbl_kalender.bis', null, false);
+ $this->_ci->KalenderModel->db->where('other_kalender.bis > tbl_kalender.von', null, false);
+ $this->_ci->KalenderModel->db->where_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete']);
+ $this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
+ $this->_ci->KalenderModel->db->where('other_kalender.kalender_id NOT IN (SELECT vorgaenger_kalender_id FROM lehre.tbl_kalender WHERE vorgaenger_kalender_id IS NOT NULL)', null, false);
+
+ $result = $this->_ci->KalenderModel->load();
+
+ if (isError($result) || !hasData($result)) return [];
+
+ $grouped = [];
+ foreach (getData($result) as $row)
+ {
+ $grouped[$row->kalender_id][] = true;
+ }
+
+ return $grouped;
+ }
+}
\ No newline at end of file
diff --git a/application/models/education/Lehreinheit_model.php b/application/models/education/Lehreinheit_model.php
index 4c17b581e..b1c50db2f 100644
--- a/application/models/education/Lehreinheit_model.php
+++ b/application/models/education/Lehreinheit_model.php
@@ -416,6 +416,9 @@ EOSQL;
JOIN lehre.tbl_kalender_lehreinheit USING(lehreinheit_id)
JOIN lehre.tbl_kalender USING(kalender_id)
WHERE tbl_lehreinheit.lehreinheit_id IN ($placeholders)
+ AND NOT EXISTS (SELECT 1 FROM lehre.tbl_kalender nachfolger
+ WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)
+ AND tbl_kalender.status_kurzbz NOT IN ('deleted', 'todelete', 'archived')
GROUP BY tbl_kalender_lehreinheit.lehreinheit_id, tbl_kalender.von, tbl_kalender.bis, tbl_kalender.kalender_id
),
raster AS (
diff --git a/application/models/ressource/BetriebsmittelKalender_model.php b/application/models/ressource/BetriebsmittelKalender_model.php
new file mode 100644
index 000000000..f9a519bbf
--- /dev/null
+++ b/application/models/ressource/BetriebsmittelKalender_model.php
@@ -0,0 +1,14 @@
+dbTable = 'lehre.tbl_betriebsmittel_kalender';
+ $this->pk = 'betriebsmittel_kalender_id';
+ }
+}
diff --git a/application/models/ressource/Betriebsmittel_model.php b/application/models/ressource/Betriebsmittel_model.php
index 290c3491d..cf974086d 100644
--- a/application/models/ressource/Betriebsmittel_model.php
+++ b/application/models/ressource/Betriebsmittel_model.php
@@ -31,4 +31,26 @@ class Betriebsmittel_model extends DB_Model
return $this->execQuery($qry);
}
+
+ public function getSchedulableEntriesByDatetimeInterval($from, $to)
+ {
+ $qry = "SELECT
+ *
+ FROM
+ wawi.tbl_betriebsmittel
+ WHERE
+ verplanen=true
+ AND
+ NOT EXISTS(
+ SELECT 1 FROM lehre.tbl_betriebsmittel_kalender
+ JOIN lehre.tbl_kalender ON tbl_kalender.eindeutige_gruppen_id = tbl_betriebsmittel_kalender.eindeutige_kalender_gruppen_id
+ WHERE
+ betriebsmittel_id=tbl_betriebsmittel.betriebsmittel_id
+ AND tbl_kalender.von < ?
+ AND tbl_kalender.bis > ?
+ )";
+
+
+ return $this->execQuery($qry, array($to, $from));
+ }
}
diff --git a/application/models/ressource/Kalender_model.php b/application/models/ressource/Kalender_model.php
index 2ca8e6ac1..d538b7313 100644
--- a/application/models/ressource/Kalender_model.php
+++ b/application/models/ressource/Kalender_model.php
@@ -11,4 +11,15 @@ class Kalender_model extends DB_Model
$this->dbTable = 'lehre.tbl_kalender';
$this->pk = 'kalender_id';
}
+
+ public function generateUniqueGroupId()
+ {
+ while (true) {
+ $uniqueGroupId = generateUUID();
+ $result = $this->loadWhere(['eindeutige_gruppen_id' => $uniqueGroupId]);
+ if (!hasData($result)) {
+ return $uniqueGroupId;
+ }
+ }
+ }
}
diff --git a/application/views/Tempus.php b/application/views/Tempus.php
index 0bd9cb697..438323eb3 100644
--- a/application/views/Tempus.php
+++ b/application/views/Tempus.php
@@ -24,9 +24,8 @@
'public/css/components/function.css'
],
'customJSs' => [
- #'vendor/npm-asset/primevue/tree/tree.min.js',
- #'vendor/npm-asset/primevue/toast/toast.min.js'
- 'vendor/moment/luxonjs/luxon.min.js'
+ 'vendor/moment/luxonjs/luxon.min.js',
+ 'vendor/npm-asset/primevue/listbox/listbox.min.js'
],
'customJSModules' => [
'public/js/apps/Tempus.js'
diff --git a/public/js/api/factory/operationalResourceToCalender.js b/public/js/api/factory/operationalResourceToCalender.js
new file mode 100644
index 000000000..618ab9e68
--- /dev/null
+++ b/public/js/api/factory/operationalResourceToCalender.js
@@ -0,0 +1,38 @@
+/**
+ * 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