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 75b8b02f7..7a65a5211 100644
--- a/application/controllers/api/frontend/v1/tempus/Kalender.php
+++ b/application/controllers/api/frontend/v1/tempus/Kalender.php
@@ -224,7 +224,7 @@ class Kalender extends FHCAPI_Controller
if (isError($result))
$this->terminateWithError(getError($result), $result->code);
- $this->terminateWithSuccess();
+ $this->terminateWithSuccess(getData($result));
}
public function getRaumvorschlag()
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/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 19c800e3f..3a531102f 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);
@@ -633,6 +647,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 +1005,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 +1180,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;
@@ -1115,7 +1217,7 @@ class KalenderLib
if (isError($result)) return $result;
}
- return success('Erfolgreich');
+ return success($result);
}
public function updateZeit($kalender_id, $start_date, $end_date)
@@ -1237,6 +1339,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')
)
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/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..682961cee 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($from, $to));
+ }
}
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/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
Keine freien Räume gefunden.
- -