diff --git a/application/controllers/Tempus.php b/application/controllers/Tempus.php
index 139f0b690..f0e2623c3 100644
--- a/application/controllers/Tempus.php
+++ b/application/controllers/Tempus.php
@@ -16,25 +16,54 @@ class Tempus extends Auth_Controller
// Load Libraries
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
-
+
// Load Config
$this->load->config('calendar');
}
- /**
- * @return void
- */
- public function _remap()
+ public function index()
{
+ $this->_loadView();
+ }
+ public function sync()
+ {
+ $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
+ $this->load->model('organisation/Studienplan_model', 'StudienplanModel');
+ $this->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $this->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
+ $this->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
+
+ $this->OrganisationseinheitModel->addJoin('tbl_studiengang', 'oe_kurzbz', 'LEFT');
+
+ $this->OrganisationseinheitModel->addSelect('public.tbl_organisationseinheit.organisationseinheittyp_kurzbz,
+ public.tbl_organisationseinheit.bezeichnung,
+ public.tbl_studiengang.studiengang_kz,
+ public.tbl_organisationseinheit.oe_kurzbz,
+ tbl_studiengang.typ,
+ COALESCE(public.tbl_studiengang.bezeichnung, \'\') as stgbezeichnung');
+ $this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.aktiv', 'DESC');
+ $this->OrganisationseinheitModel->addOrder('tbl_organisationseinheit.organisationseinheittyp_kurzbz');
+ $organisationen = getData($this->OrganisationseinheitModel->loadWhere(array("tbl_organisationseinheit.aktiv" => true)));
+
+
+ $this->StudiensemesterModel->addOrder('start', 'DESC');
+ $studiensemestern = getData($this->StudiensemesterModel->load());
+
+ $this->_loadView(array('organisationen' => $organisationen, 'studiensemestern' => $studiensemestern));
+ }
+
+ private function _loadView($extraVariables = [])
+ {
$this->load->view('Tempus', [
'permissions' => [
- 'admin' => $this->permissionlib->isBerechtigt('admin')
+ 'admin' => $this->permissionlib->isBerechtigt('admin'),
+ 'stundenraster' => $this->permissionlib->isBerechtigt('basis/tempus_stundenraster'),
],
- 'variables' => [
+ 'variables' => array_merge([
'semester_aktuell' => $this->variablelib->getVar('semester_aktuell'),
'timezone' => $this->config->item('timezone')
- ]
+ ], $extraVariables)
]);
}
-}
+}
\ No newline at end of file
diff --git a/application/controllers/api/frontend/v1/tempus/Config.php b/application/controllers/api/frontend/v1/tempus/Config.php
index 30be2cc6f..69711d455 100644
--- a/application/controllers/api/frontend/v1/tempus/Config.php
+++ b/application/controllers/api/frontend/v1/tempus/Config.php
@@ -11,10 +11,10 @@ class Config extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
- 'get' => ['admin:r', 'assistenz:r'],
- 'getHeader' => ['admin:r', 'assistenz:r'],
- 'set' => ['admin:r', 'assistenz:r'],
- 'updateCollision' => ['admin:r', 'assistenz:r'],
+ 'get' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
+ 'getHeader' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
+ 'set' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
+ 'updateCollision' => ['admin:r', 'assistenz:rw', 'lehre/lvplan:rw'],
]);
// Load Phrases
@@ -32,7 +32,17 @@ class Config extends FHCAPI_Controller
{
$config = [];
- $result = $this->_ci->VariableModel->getVariables(getAuthUID(), ['ignore_kollision', 'kollision_student', 'ignore_reservierung', 'ignore_zeitsperre', 'ignore_resources_collisions']);
+ $var_array = array(
+ 'ignore_kollision',
+ 'kollision_student',
+ 'ignore_reservierung',
+ 'ignore_zeitsperre',
+ 'ignore_resources_collisions',
+ 'roomless_planning',
+ 'priority_room_planning',
+ 'dialog_room_planning'
+ );
+ $result = $this->_ci->VariableModel->getVariables(getAuthUID(), $var_array);
$data = $this->getDataOrTerminateWithError($result);
$config['ignore_kollision'] = [
@@ -67,6 +77,25 @@ class Config extends FHCAPI_Controller
"value" => ($data['ignore_resources_collisions'] ?? 'false') === 'true'
];
+ $config['roomless_planning'] = [
+ "type" => "checkbox",
+ "label" => $this->p->t('ui', 'roomless_planning'),
+ "value" => ($data['roomless_planning'] ?? 'false') === 'true'
+ ];
+
+ $config['priority_room_planning'] = [
+ "type" => "checkbox",
+ "label" => $this->p->t('ui', 'priority_room_planning'),
+ "value" => ($data['priority_room_planning'] ?? 'false') === 'true'
+ ];
+
+ $config['dialog_room_planning'] = [
+ "type" => "checkbox",
+ "label" => $this->p->t('ui', 'dialog_room_planning'),
+ "value" => ($data['dialog_room_planning'] ?? 'false') === 'true'
+ ];
+
+
$this->terminateWithSuccess($config);
}
public function getHeader()
@@ -92,31 +121,26 @@ class Config extends FHCAPI_Controller
public function set()
{
- $this->_ci->VariableModel->setVariable(
- getAuthUID(),
+ $configs = array(
'ignore_kollision',
- $this->input->post('ignore_kollision') === true ? 'true' : 'false'
- );
- $this->_ci->VariableModel->setVariable(
- getAuthUID(),
'kollision_student',
- $this->input->post('kollision_student') === true ? 'true' : 'false'
- );
- $this->_ci->VariableModel->setVariable(
- getAuthUID(),
'ignore_reservierung',
- $this->input->post('ignore_reservierung') === true ? 'true' : 'false'
- );
- $this->_ci->VariableModel->setVariable(
- getAuthUID(),
'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'
+ 'roomless_planning',
+ 'priority_room_planning',
+ 'dialog_room_planning'
);
+
+ foreach ($configs as $config)
+ {
+ $this->_ci->VariableModel->setVariable(
+ getAuthUID(),
+ $config,
+ $this->input->post($config) === true ? 'true' : 'false'
+ );
+ }
+
$this->terminateWithSuccess();
}
diff --git a/application/controllers/api/frontend/v1/tempus/Coursepicker.php b/application/controllers/api/frontend/v1/tempus/Coursepicker.php
index fd4ca5c75..28b10920f 100644
--- a/application/controllers/api/frontend/v1/tempus/Coursepicker.php
+++ b/application/controllers/api/frontend/v1/tempus/Coursepicker.php
@@ -5,11 +5,13 @@ if (! defined('BASEPATH')) exit('No direct script access allowed');
class Coursepicker extends FHCAPI_Controller
{
private $_ci;
+
+ const ALLOWED_COURSE_FILTER = ['uid', 'stg'];
+
public function __construct()
{
parent::__construct([
- 'search' => self::PERM_LOGGED,
- 'getByStg' => self::PERM_LOGGED
+ 'getCourses' => 'lehre/lvplan:rw',
]);
$this->_ci = &get_instance();
@@ -22,88 +24,40 @@ class Coursepicker extends FHCAPI_Controller
$this->loadPhrases(['ui']);
}
- public function search()
- {
- $query = $this->input->get('query');
- if (is_null($query))
- $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
-
- $query_words = explode(' ', $query);
-
- //TODO Where weiter anpassen z.B. Fachbereich
- $this->_ci->LehreinheitModel->addSelect('tbl_lehreinheit.lehreinheit_id,
- tbl_lehreinheit.lvnr,
- tbl_lehreinheit.lehrfach_id,
- lehrfach.kurzbz AS lehrfach,
- lehrfach.bezeichnung AS lehrfach_bez,
- lehrfach.farbe AS lehrfach_farbe,
- tbl_lehreinheit.lehrform_kurzbz AS lehrform,
- lema.mitarbeiter_uid AS lektor_uid,
- tbl_mitarbeiter.kurzbz AS lektor,
- tbl_studiengang.studiengang_kz,
- upper(tbl_studiengang.typ::character varying::text || tbl_studiengang.kurzbz::text) AS studiengang,
- lvb.semester,
- lvb.verband,
- lvb.gruppe,
- lvb.gruppe_kurzbz,
- tbl_lehreinheit.raumtyp,
- tbl_lehreinheit.raumtypalternativ,
- tbl_lehreinheit.stundenblockung,
- tbl_lehreinheit.wochenrythmus,
- lema.semesterstunden,
- lema.planstunden,
- tbl_lehreinheit.start_kw,
- tbl_lehreinheit.anmerkung,
- tbl_lehreinheit.studiensemester_kurzbz');
-
- $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_lehreinheit.lehreinheit_id = lema.lehreinheit_id');
- $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehreinheitgruppe lvb', 'tbl_lehreinheit.lehreinheit_id = lvb.lehreinheit_id');
- $this->_ci->LehreinheitModel->addJoin('public.tbl_studiengang', 'lvb.studiengang_kz = tbl_studiengang.studiengang_kz');
- $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung lehrfach', 'tbl_lehreinheit.lehrfach_id = lehrfach.lehrveranstaltung_id');
- $this->_ci->LehreinheitModel->addJoin('public.tbl_mitarbeiter', 'lema.mitarbeiter_uid = tbl_mitarbeiter.mitarbeiter_uid');
- $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrform', 'tbl_lehrform.lehrform_kurzbz = tbl_lehreinheit.lehrform_kurzbz');
-
- $this->_ci->MitarbeiterModel->db->group_start();
-
- foreach ($query_words as $word)
- {
- $this->_ci->LehreinheitModel->db->group_start();
- $this->_ci->LehreinheitModel->db->where('lema.mitarbeiter_uid ILIKE', "%" . $word . "%");
- $this->_ci->LehreinheitModel->db->or_where('lvb.gruppe_kurzbz ILIKE', "%" . $word . "%");
- $this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.kurzbzlang ILIKE', "%" . $word . "%");
- $this->_ci->LehreinheitModel->db->or_where('lvb.verband ILIKE', "%" . $word . "%");
- $this->_ci->LehreinheitModel->db->or_where('lvb.gruppe ILIKE', "%" . $word . "%");
- $this->_ci->LehreinheitModel->db->or_where('lehrfach.bezeichnung ILIKE', "%" . $word . "%");
-
- if (is_numeric($word))
- {
- $this->_ci->LehreinheitModel->db->or_where('tbl_studiengang.studiengang_kz', $word);
- $this->_ci->LehreinheitModel->db->or_where('lvb.semester', $word);
- }
- $this->_ci->LehreinheitModel->db->group_end();
-
- }
- $this->_ci->LehreinheitModel->db->group_end();
- $this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz = \'SS2025\'');
- $this->_ci->LehreinheitModel->db->where(array('tbl_lehrform.verplanen' => true));
-
- $result = $this->_ci->LehreinheitModel->load();
-
- $this->terminateWithSuccess(hasData($result) ? getData($result) : array());
- }
-
- public function getByStg()
+ public function getCourses()
{
$this->_ci->form_validation->set_data($_POST);
- $this->_ci->form_validation->set_rules('studiengaenge[]',"studiengaenge","required");
$this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
if($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
- $studiengaenge = $this->input->post('studiengaenge');
- $studiensemester_kurzbz = $this->input->post('studiensemester_kurzbz');
+ $studiensemester_kurzbz = $this->_ci->input->post('studiensemester_kurzbz', TRUE);
+ $filter = $this->_checkFilter(self::ALLOWED_COURSE_FILTER);
+
+ $this->_getBasePlan($studiensemester_kurzbz);
+
+ $this->_ci->LehreinheitModel->db->group_start();
+ if (isset($filter->stg))
+ $this->_addStgWhere($filter->stg);
+
+ if (isset($filter->uid))
+ {
+ $uid_array = (array) $filter->uid;
+ $this->_ci->LehreinheitModel->db->or_where_in('tbl_benutzer.uid', $uid_array);
+ }
+
+ $this->_ci->LehreinheitModel->db->group_end();
+
+ $this->_ci->LehreinheitModel->addOrder('lehreinheit_id');
+ $result = $this->_ci->LehreinheitModel->load();
+ $result = hasData($result) ? getData($result) : array();
+ $this->terminateWithSuccess($this->_mapEvents($result));
+ }
+
+ private function _getBasePlan($studiensemester_kurzbz)
+ {
$this->_ci->LehreinheitModel->addSelect('
tbl_lehreinheit.lehreinheit_id,
tbl_lehreinheit.lvnr,
@@ -142,6 +96,15 @@ class Coursepicker extends FHCAPI_Controller
$this->_ci->LehreinheitModel->addJoin('public.tbl_benutzer', 'ma.mitarbeiter_uid = tbl_benutzer.uid');
$this->_ci->LehreinheitModel->addJoin('public.tbl_person', 'tbl_benutzer.person_id = tbl_person.person_id');
+ $this->_ci->LehreinheitModel->db->group_start();
+ $this->_ci->LehreinheitModel->db->where('tbl_lehrform.verplanen', true);
+ $this->_ci->LehreinheitModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
+ $this->_ci->LehreinheitModel->db->group_end();
+
+ }
+
+ private function _addStgWhere($studiengaenge)
+ {
$this->_ci->LehreinheitModel->db->group_start();
$first = true;
foreach ($studiengaenge as $studiengang)
@@ -165,14 +128,10 @@ class Coursepicker extends FHCAPI_Controller
$this->_ci->LehreinheitModel->db->group_end();
}
$this->_ci->LehreinheitModel->db->group_end();
+ }
- $result = $this->_ci->LehreinheitModel->loadWhere(array(
- 'tbl_lehrform.verplanen' => true,
- 'tbl_lehreinheit.studiensemester_kurzbz' => $studiensemester_kurzbz
- ));
-
- $result = hasData($result) ? getData($result) : array();
-
+ private function _mapEvents($result)
+ {
$lehreinheit_ids = array_values(array_unique(array_column($result, 'lehreinheit_id')));
$offen_map = array();
@@ -281,10 +240,8 @@ class Coursepicker extends FHCAPI_Controller
$group->verplant = $this->_formatArr($group->verplant);
$group->offenestunden = $this->_formatArr($group->offenestunden);
}
-
- $this->terminateWithSuccess(array_values($grouped));
+ return array_values($grouped);
}
-
private function _formatArr($arr)
{
$values = array_values(array_unique($arr));
@@ -296,5 +253,24 @@ class Coursepicker extends FHCAPI_Controller
return $formatted;
}
+ private function _checkFilter($filters)
+ {
+ $filter_valid = false;
+ $filter_object = new stdClass();
+ foreach ($filters as $filter)
+ {
+ if ($this->_ci->input->post($filter))
+ {
+ $filter_valid = true;
+ $filter_object->$filter = $this->_ci->input->post($filter);
+ }
+ }
+
+ if (!$filter_valid)
+ $this->terminateWithError($this->p->t('ui', 'ungueltigeParameter'), self::ERROR_TYPE_GENERAL);
+
+ return $filter_object;
+ }
+
}
diff --git a/application/controllers/api/frontend/v1/tempus/Favorites.php b/application/controllers/api/frontend/v1/tempus/Favorites.php
index 94ee39707..3bfb5b9c1 100644
--- a/application/controllers/api/frontend/v1/tempus/Favorites.php
+++ b/application/controllers/api/frontend/v1/tempus/Favorites.php
@@ -7,8 +7,8 @@ class Favorites extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
- 'index' => self::PERM_LOGGED,
- 'set' => self::PERM_LOGGED
+ 'index' => 'lehre/lvplan:rw',
+ 'set' => 'lehre/lvplan:rw'
]);
// Load models
diff --git a/application/controllers/api/frontend/v1/tempus/Info.php b/application/controllers/api/frontend/v1/tempus/Info.php
index b8ab2b9b0..9ef71da3e 100644
--- a/application/controllers/api/frontend/v1/tempus/Info.php
+++ b/application/controllers/api/frontend/v1/tempus/Info.php
@@ -12,7 +12,7 @@ class Info extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
- 'getStudiengaenge' => self::PERM_LOGGED,
+ 'getStudiengaenge' => 'lehre/lvplan:rw',
]);
$this->_ci =& get_instance();
diff --git a/application/controllers/api/frontend/v1/tempus/Kalender.php b/application/controllers/api/frontend/v1/tempus/Kalender.php
index 0c7cbfc16..5ba48d13e 100644
--- a/application/controllers/api/frontend/v1/tempus/Kalender.php
+++ b/application/controllers/api/frontend/v1/tempus/Kalender.php
@@ -8,18 +8,19 @@ class Kalender extends FHCAPI_Controller
const ALLOWED_PLAN_FILTER = ['ort', 'uid', 'stg'];
const ALLOWED_ROOM_FILTER = ['lehreinheit_id', 'kalender_id'];
- const ALLOWED_TO_UPDATE = ['start_time', 'end_time', 'ort_kurzbz'];
+ const ALLOWED_TO_UPDATE = ['start_time', 'end_time', 'orte'];
/**
* Object initialization
*/
public function __construct()
{
parent::__construct([
- 'getStunden' => self::PERM_LOGGED,
- 'getCalendarHours' => self::PERM_LOGGED,
- 'getPlan' => self::PERM_LOGGED,
- 'getPlanByOrt' => self::PERM_LOGGED,
- 'getRaumvorschlag' => self::PERM_LOGGED,
+ 'getStunden' => 'lehre/lvplan:rw',
+ 'getCalendarHours' => 'lehre/lvplan:rw',
+ 'getPlan' => 'lehre/lvplan:rw',
+ 'getPlanByOrt' => 'lehre/lvplan:rw',
+ 'getRaumvorschlag' => 'lehre/lvplan:rw',
+ 'getRaumvorschlagSlots' => 'lehre/lvplan:rw',
'getLehreinheiten' => 'lehre/lvplan:rw',
'getHistory' => 'lehre/lvplan:rw',
'deleteEntry' => 'lehre/lvplan:rw',
@@ -27,8 +28,8 @@ class Kalender extends FHCAPI_Controller
'syncToStudent' => 'lehre/lvplan:rw',
'getPlanLecturer' =>'lehre/lvplan:rw',
'getPlanStudent' => 'lehre/lvplan:rw',
- 'getZeitwuensche' => self::PERM_LOGGED,
- 'getZeitsperren' => self::PERM_LOGGED,
+ 'getZeitwuensche' => 'lehre/lvplan:rw',
+ 'getZeitsperren' => 'lehre/lvplan:rw',
'updateKalenderEvent' => 'lehre/lvplan:rw',
'deleteOrtEntry' => 'lehre/lvplan:rw',
'deleteFromKalenderEvent' => 'lehre/lvplan:rw',
@@ -44,6 +45,7 @@ class Kalender extends FHCAPI_Controller
$this->_ci->load->library('LogLib');
$this->_ci->load->library('form_validation');
$this->_ci->load->library('KalenderLib');
+ $this->_ci->load->library('KalenderSyncLib');
$this->_ci->load->library('RaumvorschlagLib');
$this->loadPhrases([
'ui'
@@ -222,7 +224,7 @@ class Kalender extends FHCAPI_Controller
$updateFields = $this->_checkUpdate($this->_ci->input->post('updatedInfos', TRUE));
$kalender_id = $this->_ci->input->post('kalender_id', TRUE);
- $result = $this->_ci->kalenderlib->updateKalenderEvent($kalender_id, $updateFields->ort_kurzbz ?? null, $updateFields->start_time ?? null, $updateFields->end_time ?? null);
+ $result = $this->_ci->kalenderlib->updateKalenderEvent($kalender_id, $updateFields->orte ?? null, $updateFields->start_time ?? null, $updateFields->end_time ?? null, $updateFields->location ?? null);
if (isError($result))
$this->terminateWithError(getError($result), $result->code);
@@ -255,6 +257,22 @@ class Kalender extends FHCAPI_Controller
$this->terminateWithSuccess($this->_ci->raumvorschlaglib->getVorschlaege($filter->kalender_id));
}
+ public function getRaumvorschlagSlots()
+ {
+ $this->_ci->form_validation->set_data($_GET);
+ $this->_ci->form_validation->set_rules('lehreinheit_id',"lehreinheit_id","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)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $lehreinheit_id = $this->_ci->input->get('lehreinheit_id', TRUE);
+ $start_date = $this->_ci->input->get('start_date', TRUE);
+ $end_date = $this->_ci->input->get('end_date', TRUE);
+ $this->terminateWithSuccess(getData($this->_ci->raumvorschlaglib->getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)));
+ }
+
public function getLehreinheiten()
{
$this->_ci->form_validation->set_data($_GET);
@@ -306,7 +324,7 @@ class Kalender extends FHCAPI_Controller
public function sync()
{
- $result = $this->_ci->kalenderlib->sync();
+ $result = $this->_ci->kalendersynclib->sync();
$this->terminateWithSuccess(getData($result));
}
public function syncToLecturer()
diff --git a/application/controllers/api/frontend/v1/tempus/KalenderSync.php b/application/controllers/api/frontend/v1/tempus/KalenderSync.php
new file mode 100644
index 000000000..13e4cc012
--- /dev/null
+++ b/application/controllers/api/frontend/v1/tempus/KalenderSync.php
@@ -0,0 +1,304 @@
+ ['admin:r', 'assistenz:r'],
+ 'loadSync' => ['admin:r', 'assistenz:r'],
+ 'add' => ['admin:r', 'assistenz:r'],
+ 'start' => ['admin:r', 'assistenz:r'],
+ 'delete' => ['admin:r', 'assistenz:r'],
+ 'updateSync' => ['admin:r', 'assistenz:r'],
+ 'getStudienplan' => ['admin:r', 'assistenz:r'],
+ 'getSyncStatus' => ['admin:r', 'assistenz:r'],
+ ]);
+
+ $this->loadPhrases([
+ 'lehre',
+ ]);
+
+ $this->_ci = &get_instance();
+ $this->_ci->load->library('form_validation');
+ $this->_ci->load->model('organisation/Studienplan_model', 'StudienplanModel');
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
+ $this->_ci->load->model('ressource/Kalenderstatus_model', 'KalenderStatusModel');
+ $this->_ci->load->library('KalenderSyncLib');
+ }
+
+ public function getSyncs()
+ {
+ $this->_ci->form_validation->set_data($_GET);
+ $this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+ $studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
+
+ $language = getUserLanguage() == 'German' ? 0 : 1;
+
+ $this->_ci->KalenderStatusModel->addSelect('tbl_kalender_syncstatus.*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS sync_status, tbl_organisationseinheit.bezeichnung as oebezeichnung, tbl_studienplan.bezeichnung as studienplanbezeichnung');
+ $this->_ci->KalenderStatusModel->addJoin('lehre.tbl_kalender_status', 'tbl_kalender_syncstatus.sync_status_kurzbz = tbl_kalender_status.status_kurzbz');
+ $this->_ci->KalenderStatusModel->addJoin('public.tbl_organisationseinheit', 'tbl_kalender_syncstatus.oe_kurzbz = tbl_organisationseinheit.oe_kurzbz');
+ $this->_ci->KalenderStatusModel->addJoin('lehre.tbl_studienplan', 'tbl_kalender_syncstatus.studienplan_id = tbl_studienplan.studienplan_id', 'LEFT');
+ $this->_ci->KalenderStatusModel->addJoin('public.tbl_studiensemester', 'tbl_kalender_syncstatus.studiensemester_kurzbz = tbl_studiensemester.studiensemester_kurzbz');
+ $this->_ci->KalenderStatusModel->addOrder('public.tbl_studiensemester.start', 'DESC');
+
+
+ if ($studiensemester_kurzbz === 'all')
+ $data = $this->_ci->KalendersyncstatusModel->load();
+ else
+ $data = $this->_ci->KalendersyncstatusModel->loadWhere(array('tbl_kalender_syncstatus.studiensemester_kurzbz' => $studiensemester_kurzbz));
+
+ if (isError($data))
+ $this->terminateWithError(getError($data));
+
+ $this->terminateWithSuccess(getData($data));
+ }
+
+ public function delete()
+ {
+ $this->load->library('form_validation');
+
+ $this->form_validation->set_rules('kalender_syncstatus_id', 'kalender_syncstatus_id', 'required');
+
+ if (!$this->form_validation->run())
+ $this->terminateWithValidationErrors($this->form_validation->error_array());
+
+ $kalender_syncstatus_id = $this->input->post('kalender_syncstatus_id');
+
+ $result = $this->_ci->KalendersyncstatusModel->load($kalender_syncstatus_id);
+
+ if (isError($result))
+ $this->terminateWithError(getError($result));
+
+ if (!hasData($result))
+ $this->terminateWithError($this->p->t('lehre', 'errorDeleting'));
+
+ $del_result = $this->_ci->KalendersyncstatusModel->delete(getData($result)[0]->kalender_syncstatus_id);
+
+ if (isError($del_result))
+ $this->terminateWithError(getError($del_result));
+ $this->terminateWithSuccess($del_result);
+ }
+
+ public function loadSync()
+ {
+ $this->_ci->form_validation->set_data($_GET);
+ $this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+ $kalender_syncstatus_id = $this->_ci->input->get('kalender_syncstatus_id', TRUE);
+ $data = $this->_ci->KalendersyncstatusModel->loadWhere(array('kalender_syncstatus_id' => $kalender_syncstatus_id));
+ if (isError($data))
+ $this->terminateWithError(getError($data));
+
+ $this->terminateWithSuccess(getData($data)[0]);
+ }
+
+ public function getSyncStatus()
+ {
+ $language = getUserLanguage() == 'German' ? 0 : 1;
+
+ $this->_ci->KalenderStatusModel->addSelect('*, array_to_json(bezeichnung_mehrsprachig::varchar[])->>' . $language .' AS bezeichnung, status_kurzbz');
+ $this->_ci->KalenderStatusModel->db->where_in('status_kurzbz', self::ALLOWED_STATUS);
+ $data = $this->_ci->KalenderStatusModel->load();
+
+ if (isError($data))
+ $this->terminateWithError(getError($data));
+
+ $this->terminateWithSuccess(getData($data));
+ }
+
+
+ public function add()
+ {
+ $formData = $this->input->post('formData');
+
+ $this->_ci->form_validation->set_data($formData);
+
+ $this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
+ $this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
+ $this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
+ $studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
+
+ $existing = $this->_checkIfExist(
+ $formData['oe_kurzbz'],
+ $formData['studiensemester_kurzbz'],
+ $ausbildungssemester,
+ $studienplan_id
+ );
+
+ if (isError($existing))
+ $this->terminateWithError(getError($existing));
+
+ if (hasData($existing))
+ {
+ $this->terminateWithError('Es existiert bereits ein Eintrag.');
+ }
+
+ $result = $this->_ci->KalendersyncstatusModel->insert(
+ array(
+ 'oe_kurzbz' => $formData['oe_kurzbz'],
+ 'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
+ 'datum_bis' => $formData['datum_bis'],
+ 'studienplan_id' => $studienplan_id,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
+ 'mail' => $formData['mail'],
+ 'insertvon' => getAuthUID()
+ )
+ );
+
+ $this->terminateWithSuccess($result);
+ }
+
+
+ public function start()
+ {
+ $formData = $this->input->post('formData');
+
+ $this->_ci->form_validation->set_data($formData);
+
+ $this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
+ $this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
+ $this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $result = $this->_ci->kalendersynclib->runManual($formData['oe_kurzbz'], $formData['studiensemester_kurzbz'], $formData['ausbildungssemester'], $formData['studienplan_id'], $formData['mail'], $formData['datum_bis'], $formData['sync_status_kurzbz']);
+
+ if (isError($result))
+ $this->terminateWithError(getError($result));
+
+ $this->terminateWithSuccess($result);
+ }
+ public function updateSync()
+ {
+ $formData = $this->input->post('formData');
+
+ $this->_ci->form_validation->set_data($formData);
+
+ $this->_ci->form_validation->set_rules('kalender_syncstatus_id',"kalender_syncstatus_id","required");
+ $this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
+ $this->_ci->form_validation->set_rules('studiensemester_kurzbz',"studiensemester_kurzbz","required");
+ $this->_ci->form_validation->set_rules('sync_status_kurzbz',"sync_status_kurzbz","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $ausbildungssemester = isEmptyString($formData['ausbildungssemester']) ? null : $formData['ausbildungssemester'];
+ $studienplan_id = isEmptyString($formData['studienplan_id']) ? null : $formData['studienplan_id'];
+
+ $existing = $this->_checkIfExist(
+ $formData['oe_kurzbz'],
+ $formData['studiensemester_kurzbz'],
+ $ausbildungssemester,
+ $studienplan_id,
+ $formData['kalender_syncstatus_id']
+ );
+
+ if (isError($existing))
+ $this->terminateWithError(getError($existing));
+
+ if (hasData($existing))
+ {
+ $this->terminateWithError('Es existiert bereits ein Eintrag.');
+ }
+
+ $this->_ci->KalendersyncstatusModel->update(
+ array('kalender_syncstatus_id' => $formData['kalender_syncstatus_id']),
+ array(
+ 'oe_kurzbz' => $formData['oe_kurzbz'],
+ 'studiensemester_kurzbz' => $formData['studiensemester_kurzbz'],
+ 'datum_bis' => $formData['datum_bis'],
+ 'studienplan_id' => $studienplan_id,
+ 'ausbildungssemester' => $ausbildungssemester,
+ 'sync_status_kurzbz' => $formData['sync_status_kurzbz'],
+ 'mail' => $formData['mail'],
+ 'updatevon' => getAuthUID(),
+ 'updateamum' => date('c'),
+ )
+ );
+ }
+ public function getStudienplan()
+ {
+ $this->_ci->form_validation->set_data($_GET);
+ $this->_ci->form_validation->set_rules('oe_kurzbz',"oe_kurzbz","required");
+
+ if($this->_ci->form_validation->run() === FALSE)
+ $this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
+
+ $oe_kurzbz = $this->_ci->input->get('oe_kurzbz', TRUE);
+ $studiensemester_kurzbz = $this->_ci->input->get('studiensemester_kurzbz', TRUE);
+ $ausbildungssemester = $this->_ci->input->get('ausbildungssemester', TRUE);
+
+ $this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
+ $is_studiengang = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
+
+ if (hasData($is_studiengang) && !isEmptyString($studiensemester_kurzbz))
+ {
+ $studiengang = getData($is_studiengang)[0];
+
+ $studienplaene = $this->_ci->StudienplanModel->getStudienplaeneBySemester(
+ $studiengang->studiengang_kz,
+ $studiensemester_kurzbz,
+ isEmptyString($ausbildungssemester) ? null : $ausbildungssemester
+ );
+
+
+ $data = $this->getDataOrTerminateWithError($studienplaene);
+
+ $unique = array();
+ foreach ($data as $row)
+ {
+ $unique[$row->studienplan_id] = (object) array(
+ 'studienplan_id' => $row->studienplan_id,
+ 'studienordnung_id' => $row->studienordnung_id,
+ 'bezeichnung' => $row->bezeichnung,
+ 'orgform_kurzbz' => $row->orgform_kurzbz
+ );
+ }
+
+ $this->terminateWithSuccess(array_values($unique));
+ }
+ $this->terminateWithSuccess();
+ }
+
+ private function _checkIfExist($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester, $studienplan_id, $kalender_syncstatus_id = null)
+ {
+ $this->_ci->KalendersyncstatusModel->db->where('oe_kurzbz', $oe_kurzbz);
+ $this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
+
+ if (is_null($ausbildungssemester))
+ $this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester IS NULL', null, false);
+ else
+ $this->_ci->KalendersyncstatusModel->db->where('ausbildungssemester', $ausbildungssemester);
+
+ if (is_null($studienplan_id))
+ $this->_ci->KalendersyncstatusModel->db->where('studienplan_id IS NULL', null, false);
+ else
+ $this->_ci->KalendersyncstatusModel->db->where('studienplan_id', $studienplan_id);
+
+ if (!is_null($kalender_syncstatus_id))
+ $this->_ci->KalendersyncstatusModel->db->where('kalender_syncstatus_id !=', $kalender_syncstatus_id);
+ return $this->_ci->KalendersyncstatusModel->load();
+ }
+
+}
diff --git a/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php
index f5a09deff..76f6fd369 100644
--- a/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php
+++ b/application/controllers/api/frontend/v1/tempus/OperationalResourceToCalenderAPI.php
@@ -9,9 +9,9 @@ class OperationalResourceToCalenderAPI extends FHCAPI_Controller
public function __construct()
{
parent::__construct([
- 'getAssignedResourcesByCalender' => ['admin:r', 'assistenz:r'],
- 'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w'],
- 'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r'],
+ 'getAssignedResourcesByCalender' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
+ 'storeResourcesToCalendarRelationship' => ['admin:w', 'assistenz:w', 'lehre/lvplan:rw'],
+ 'getSchedulableResourcesByCalendar' => ['admin:r', 'assistenz:r', 'lehre/lvplan:rw'],
]);
$this->load->model('ressource/BetriebsmittelKalender_model', 'BetriebsmittelKalenderModel');
diff --git a/application/controllers/api/frontend/v1/tempus/Reservierung.php b/application/controllers/api/frontend/v1/tempus/Reservierung.php
index 1b1baa963..5a7067bcf 100644
--- a/application/controllers/api/frontend/v1/tempus/Reservierung.php
+++ b/application/controllers/api/frontend/v1/tempus/Reservierung.php
@@ -162,9 +162,9 @@ class Reservierung extends FHCAPI_Controller
if ($this->_ci->form_validation->run() === FALSE)
$this->terminateWithValidationErrors($this->_ci->form_validation->error_array());
- $ort_kurzbz = $this->_ci->input->post('ort_kurzbz', TRUE);
+ $orte = $this->_ci->input->post('orte', TRUE);
- if (empty($ort_kurzbz) || !is_array($ort_kurzbz))
+ if (empty($orte) || (empty($orte['ort_kurzbz']) && empty($orte['location'])))
{
$this->terminateWithValidationErrors(['ort_kurzbz' => $this->p->t('ui', 'error_fieldRequired', ['field' => 'Raum'])]);
}
@@ -189,7 +189,7 @@ class Reservierung extends FHCAPI_Controller
$teilnehmer[] = array('uid' => getAuthUID(), 'rolle' => 'organisator');
- $result = $this->_ci->kalenderlib->addReservierung($titel, $beschreibung, $ort_kurzbz, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups);
+ $result = $this->_ci->kalenderlib->addReservierung($titel, $beschreibung, $orte, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups);
if (isError($result))
diff --git a/application/controllers/system/MigrateKalender.php b/application/controllers/system/MigrateKalender.php
index 15b6d28ce..67de262dd 100644
--- a/application/controllers/system/MigrateKalender.php
+++ b/application/controllers/system/MigrateKalender.php
@@ -121,7 +121,14 @@ class MigrateKalender extends CLI_Controller
$ids = is_array($block->stundenplandev_ids) ? $block->stundenplandev_ids : explode(',', $block->stundenplandev_ids);
/*$ids = array_map('intval', $ids);*/
- $this->SyncModel->db->where_in('stundenplandev_id', $ids);
+ $this->SyncModel->db->group_start();
+ $where_ids_chunks = array_chunk($ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->SyncModel->db->or_where_in('stundenplandev_id', $where_ids);
+ }
+ $this->SyncModel->db->group_end();
+
$sync_result = $this->SyncModel->load();
if (!hasData($sync_result))
@@ -230,7 +237,14 @@ class MigrateKalender extends CLI_Controller
$ids = is_array($block->reservierung_ids) ? $block->reservierung_ids : explode(',', $block->reservierung_ids);
- $this->SyncReservierungModel->db->where_in('reservierung_id', $ids);
+ $this->SyncReservierungModel->db->group_start();
+ $where_ids_chunks = array_chunk($ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->SyncReservierungModel->db->or_where_in('reservierung_id', $where_ids);
+ }
+ $this->SyncReservierungModel->db->group_end();
+
$sync_result = $this->SyncReservierungModel->load();
if (!hasData($sync_result))
diff --git a/application/libraries/KalenderLib.php b/application/libraries/KalenderLib.php
index 86973662c..623784c9d 100644
--- a/application/libraries/KalenderLib.php
+++ b/application/libraries/KalenderLib.php
@@ -17,7 +17,6 @@ class KalenderLib
$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');
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
$this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
@@ -48,6 +47,7 @@ class KalenderLib
tbl_kalender.typ,
tbl_kalender.von,
tbl_kalender.bis,
+ tbl_kalender_ort.location,
tbl_kalender_ort.ort_kurzbz,
tbl_lehreinheit.lehreinheit_id,
tbl_lehreinheit.lehrveranstaltung_id,
@@ -91,7 +91,19 @@ class KalenderLib
tbl_lehreinheitgruppe.gruppe as le_gruppe,
le_gruppe.direktinskription as le_direktinskription,
tag_data_agg.tags as tags,
- resource_data_agg.resources as resources
+ resource_data_agg.resources as resources,
+ CASE
+ WHEN vonstunde.stunde IS NOT NULL AND bisstunde.stunde IS NOT NULL
+ THEN bisstunde.stunde - vonstunde.stunde + 1
+ ELSE ROUND(
+ COALESCE(
+ (
+ SELECT SUM(EXTRACT(EPOCH FROM (LEAST(stunde.ende, tbl_kalender.bis::time) - GREATEST(stunde.beginn, tbl_kalender.von::time))) / 60) / 45
+ FROM lehre.tbl_stunde stunde
+ WHERE stunde.beginn < tbl_kalender.bis::time AND stunde.ende > tbl_kalender.von::time)
+ ,0)
+ ,2
+ ) END AS verplante_stunden
');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'tbl_kalender.kalender_id = tbl_kalender_lehreinheit.kalender_id', 'LEFT');
@@ -201,6 +213,9 @@ class KalenderLib
// End of operational resources inclusion
+ $this->_ci->KalenderModel->db->join('lehre.tbl_stunde vonstunde', 'tbl_kalender.von::time = vonstunde.beginn', 'LEFT', FALSE);
+ $this->_ci->KalenderModel->db->join('lehre.tbl_stunde bisstunde', 'tbl_kalender.bis::time = bisstunde.ende', 'LEFT', FALSE);
+
$this->_ci->KalenderModel->db->where('tbl_kalender.von >=', $start_date);
$this->_ci->KalenderModel->db->where('tbl_kalender.bis <', $end_date);
@@ -238,11 +253,13 @@ class KalenderLib
'tooltip' => 'tip',
'status_kurzbz' => $row->status_kurzbz,
'ort_kurzbz' => [],
+ 'location' => null,
'lehrform' => isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : '',
'lehrfach' => isset($row->lehrfach_kurzbz) ? $row->lehrfach_kurzbz : '',
'lehrfach_bez' => isset($row->lehrfach_bezeichnung) ? $row->lehrfach_bezeichnung : '',
'farbe' => isset($row->farbe) ? $row->farbe : '',
'lehrveranstaltung_id' => $row->lehrveranstaltung_id,
+ 'verplante_stunden' => $row->verplante_stunden,
'organisationseinheit' => isset($row->oe_kurzbz) ? $row->oe_kurzbz : '',
'kalender_id' => $id,
'lehreinheit_id' => [],
@@ -266,6 +283,9 @@ class KalenderLib
if (isset($row->ort_kurzbz) && $row->ort_kurzbz !== '' && !in_array($row->ort_kurzbz, $events[$id]->ort_kurzbz))
$events[$id]->ort_kurzbz[] = $row->ort_kurzbz;
+ if (isset($row->location) && $row->location !== '' && is_null($events[$id]->location))
+ $events[$id]->location = $row->location;
+
$topic = trim((isset($row->lehrfach_kurzbz) ? $row->lehrfach_kurzbz : '').' '.(isset($row->lehrform_kurzbz) ? $row->lehrform_kurzbz : ''));
if ($topic !== '' && !in_array($topic, $events[$id]->topic))
$events[$id]->topic[] = $topic;
@@ -357,8 +377,6 @@ class KalenderLib
return $this->_mapEvents($data);
}
-
-
public function getForRaumvorschlag($start_date, $end_date, $lektor_uids = [], $gruppen_kurzbz = [], $lehrverband_gruppen = [])
{
$start_date = date('Y-m-d', strtotime($start_date));
@@ -384,6 +402,7 @@ class KalenderLib
foreach ($lehrverband_gruppen as $lvg)
{
+ $lvg = (array) $lvg;
$this->_ci->KalenderModel->db->or_group_start();
$this->_ci->KalenderModel->db->where('tbl_lehreinheitgruppe.studiengang_kz', $lvg['studiengang_kz']);
$this->_ci->KalenderModel->db->where('tbl_lehreinheitgruppe.semester', $lvg['semester']);
@@ -530,7 +549,7 @@ class KalenderLib
{
$this->_getBasePlan($start_date, $end_date);
- $this->_ci->KalenderModel->db->where('status_kurzbz', 'live');
+ $this->_ci->KalenderModel->db->where_in('status_kurzbz', array('live', 'to_delete_live'));
$data = $this->_ci->KalenderModel->load();
@@ -662,6 +681,17 @@ class KalenderLib
}
+ private function _checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz)
+ {
+ $checkerData = new stdClass();
+ $checkerData->von = $start_date;
+ $checkerData->bis = $end_date;
+ $checkerData->lehreinheit_id = $lehreinheit_id;
+ $checkerData->ort_kurzbz = $ort_kurzbz;
+
+ return $this->_ci->collisionchecker->run($checkerData);
+ }
+
public function addToKalenderEvent($target_kalender_id, $lehreinheit_id)
{
$entryResult = $this->_loadKalenderEntry($target_kalender_id);
@@ -669,7 +699,15 @@ class KalenderLib
$kalender_entry = getData($entryResult);
- if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
+ if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
@@ -712,7 +750,15 @@ class KalenderLib
$kalender_entry = getData($entryResult);
- if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
+ if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
@@ -804,16 +850,6 @@ class KalenderLib
return ['kalender_id' => $kalender_id, 'result' => $ortresult];
}
- $entryResult = $this->_loadKalenderEntry($kalender_id);
- if (isError($entryResult))
- return ['kalender_id' => $kalender_id, 'result' => $entryResult];
-
- $kalender_entry = getData($entryResult);
- $errors = $this->_ci->collisionchecker->run($kalender_entry);
-
- if (!empty($errors))
- return ['kalender_id' => $kalender_id, 'result' => error($errors)];
-
return ['kalender_id' => $kalender_id, 'result' => $kalenderlehreinheitresult];
}
@@ -878,8 +914,6 @@ class KalenderLib
'false'
);
- $this->_ci->KalenderModel->db->trans_start();
-
while ($rest > 0 && new DateTime($current_date) < $ende)
{
$max_skip = 52;
@@ -920,18 +954,9 @@ class KalenderLib
$start_str = $current_date . ' ' . $start_time;
$end_str = $current_date . ' ' . $end_time;
- $insert = $this->_insertKalenderEventRaw($start_str, $end_str, $lehreinheit_id, $ort_kurzbz);
- $kalender_id = $insert['kalender_id'];
- $insert_result = $insert['result'];
+ $collisions = $this->_checkCollisionForLehreinheit($start_str, $end_str, $lehreinheit_id, $ort_kurzbz);
- $collisions = isError($insert_result) ? getError($insert_result) : [];
-
- $raum_vorschlaege = [];
- if ($kalender_id)
- {
- $vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaege($kalender_id);
- $raum_vorschlaege = is_array($vorschlaege) ? $vorschlaege : [];
- }
+ $raum_vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaegeByLehreinheit($lehreinheit_id, $start_str, $end_str);
$plan[] = [
'datum' => $current_date,
@@ -940,14 +965,13 @@ class KalenderLib
'block' => $current_block,
'ort_kurzbz' => $ort_kurzbz,
'collisions' => $collisions,
- 'raum_vorschlaege' => $raum_vorschlaege,
+ 'raum_vorschlaege' => is_array($raum_vorschlaege) ? $raum_vorschlaege : [],
];
$rest -= $current_block;
$current_date = $this->_addWeeks($current_date, $wochenrythmus);
}
- $this->_ci->KalenderModel->db->trans_rollback();
$this->_ci->VariableModel->setVariable(
getAuthUID(),
@@ -1010,6 +1034,49 @@ class KalenderLib
public function addKalenderEvent($start_date, $end_date, $lehreinheit_id, $ort_kurzbz)
{
+ if (!$this->_checkPermission((array)$lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
+ if (isEmptyString($ort_kurzbz))
+ {
+ $errors = $this->_checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
+
+ if (!empty($errors))
+ return error($errors);
+
+ $raum_vorschlaege = $this->_ci->raumvorschlaglib->getVorschlaegeByLehreinheit($lehreinheit_id, $start_date, $end_date);
+
+ if (($this->_ci->variablelib->getVar('dialog_room_planning') ?? 'false') === 'true')
+ {
+ return success([
+ 'needs_room_selection' => true,
+ 'raum_vorschlaege' => is_array($raum_vorschlaege) ? $raum_vorschlaege : [],
+ ]);
+ }
+
+ if (($this->_ci->variablelib->getVar('priority_room_planning') ?? 'false') === 'true')
+ {
+ $ort_kurzbz = (is_array($raum_vorschlaege)) ? $raum_vorschlaege[0]['ort_kurzbz'] : null;
+ }
+ else if (!(($this->_ci->variablelib->getVar('roomless_planning') ?? 'false') === 'true'))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'roomless_planning_error'),
+ 'errorCode' => 'roomless_planning_error'
+ ]);
+ }
+ }
+
+ $errors = $this->_checkCollisionForLehreinheit($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
+
+ if (!empty($errors))
+ return error($errors);
+
$this->_ci->KalenderModel->db->trans_start();
$insert = $this->_insertKalenderEventRaw($start_date, $end_date, $lehreinheit_id, $ort_kurzbz);
@@ -1025,14 +1092,14 @@ class KalenderLib
return $result;
}
- public function addReservierung($titel, $beschreibung, $ort_kurzbz, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups)
+ public function addReservierung($titel, $beschreibung, $orte, $start_date, $end_date, $teilnehmer, $specialFinalGroups, $specialGroups, $groups)
{
- if (!is_null($ort_kurzbz))
+ if (!is_null($orte) && !isEmptyArray($orte['ort_kurzbz']))
{
$this->_ci->KalenderModel->addSelect('1');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
- $this->_ci->KalenderModel->db->where_in('ort_kurzbz', $ort_kurzbz);
+ $this->_ci->KalenderModel->db->where_in('ort_kurzbz', $orte['ort_kurzbz']);
$reservierung_vorhanden = $this->_ci->KalenderModel->load(array (
'von <=' => $end_date,
'bis >=' => $start_date,
@@ -1093,9 +1160,25 @@ class KalenderLib
}
}
- if (isSuccess($kalendereventresult) && !is_null($ort_kurzbz))
+ if (isSuccess($kalendereventresult) && !isEmptyArray($orte['ort_kurzbz']))
{
- $ortresult = $this->_addKalenderOrt($kalender_id, $ort_kurzbz);
+ $ortresult = $this->_addKalenderOrt($kalender_id, $orte['ort_kurzbz']);
+ if (isError($ortresult))
+ {
+ $this->_ci->KalenderModel->db->trans_rollback();
+ return $ortresult;
+ }
+ }
+
+ if (isSuccess($kalendereventresult) && !is_null($orte['location']))
+ {
+ $ortresult = $this->_ci->KalenderOrtModel->insert(
+ array (
+ 'kalender_id' => $kalender_id,
+ 'location' => $orte['location']
+ )
+ );
+
if (isError($ortresult))
{
$this->_ci->KalenderModel->db->trans_rollback();
@@ -1295,26 +1378,39 @@ class KalenderLib
return success();
}
- public function updateKalenderEvent($kalender_id, $ort_kurzbz = null, $start_time = null, $end_time = null)
+ public function updateKalenderEvent($kalender_id, $orte = null, $start_time = null, $end_time = null)
{
$entryResult = $this->_loadKalenderEntry($kalender_id);
if (isError($entryResult)) return $entryResult;
$kalender_entry = getData($entryResult);
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
$calendarResources = $this->_ci->BetriebsmittelKalenderModel->loadWhere(['eindeutige_kalender_gruppen_id' => $kalender_entry->eindeutige_kalender_gruppen_id]);
if (isError($calendarResources)) return $calendarResources;
-
+
$calendarResourcesItems = getData($calendarResources);
$calendarResourcesIDs = [];
- if (is_array($calendarResourcesItems)) {
+ 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;
+
+ if (!is_null($orte))
+ {
+ $kalender_entry->ort_kurbz = !isEmptyArray($orte['ort_kurzbz'] ?? null) ? (array) $orte['ort_kurzbz'] : $kalender_entry->ort_kurzbz;
+ $kalender_entry->location = array_key_exists('location', $orte) && !is_null($orte['location']) ? $orte['location'] : $kalender_entry->location;
+ }
$kalender_entry->von = $start_time ?? $kalender_entry->von;
$kalender_entry->bis = $end_time ?? $kalender_entry->bis;
@@ -1324,9 +1420,9 @@ class KalenderLib
$result = $kalender_entry;
- if (!is_null($ort_kurzbz))
+ if (!is_null($orte))
{
- $result = $this->updateOrt($kalender_id, $ort_kurzbz);
+ $result = $this->updateOrt($kalender_id, $orte);
if (isError($result)) return $result;
if (hasData($result))
@@ -1353,7 +1449,7 @@ class KalenderLib
if ($kalender_entry->typ === 'lehreinheit')
{
- if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
@@ -1409,9 +1505,11 @@ class KalenderLib
return success($result);
}
- public function updateOrt($kalender_id, $ort_kurzbz_array)
+ public function updateOrt($kalender_id, $orte_array)
{
- $ort_kurzbz_array = (array)$ort_kurzbz_array;
+ $ort_kurzbz_neu = (array)($orte_array['ort_kurzbz'] ?? []);
+ $location_neu = $orte_array['location'] ?? null;
+
$entryResult = $this->_loadKalenderEntry($kalender_id);
if (isError($entryResult)) return $entryResult;
@@ -1419,7 +1517,15 @@ class KalenderLib
if ($kalender_entry->typ === 'lehreinheit')
{
- if (in_array($kalender_entry->status_kurzbz, array('todelete', 'deleted')))
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
+ if (in_array($kalender_entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview', 'deleted')))
{
return error([
'message' => $this->_ci->phraseslib->t('ui', 'entry_not_editable'),
@@ -1428,14 +1534,30 @@ class KalenderLib
}
if (in_array($kalender_entry->status_kurzbz, array('live', 'preview')))
- return $this->_createHistoryEntry($kalender_entry, null, null, $ort_kurzbz_array);
+ return $this->_createHistoryEntry($kalender_entry, null, null, $orte_array);
}
$bestehende = $this->_ci->KalenderOrtModel->load(array('kalender_id' => $kalender_id));
- $alte_orte = hasData($bestehende) ? array_column(getData($bestehende), 'ort_kurzbz') : [];
+ $alte_orte = hasData($bestehende) ? getData($bestehende) : [];
- $zu_loeschen = array_diff($alte_orte, $ort_kurzbz_array);
- $neu_anzulegen = array_diff($ort_kurzbz_array, $alte_orte);
+
+ $alte_orte_kurzbz = array_values(array_filter(array_map(function ($ort) {
+ return $ort->ort_kurzbz;
+ }, $alte_orte)));
+
+ $alte_location = null;
+
+ foreach ($alte_orte as $ort)
+ {
+ if (!is_null($ort->location))
+ {
+ $alte_location = $ort->location;
+ break;
+ }
+ }
+
+ $zu_loeschen = array_diff($alte_orte_kurzbz, $ort_kurzbz_neu);
+ $neu_anzulegen = array_diff($ort_kurzbz_neu, $alte_orte_kurzbz);
if (!empty($zu_loeschen))
{
@@ -1444,12 +1566,34 @@ class KalenderLib
$this->_ci->KalenderOrtModel->db->delete('lehre.tbl_kalender_ort');
}
- foreach ($neu_anzulegen as $ort_kurzbz)
+ foreach ($neu_anzulegen as $ort)
{
- $result = $this->_addKalenderOrt($kalender_id, $ort_kurzbz);
+ $result = $this->_addKalenderOrt($kalender_id, $ort);
if (isError($result)) return $result;
}
+ if ($alte_location !== $location_neu)
+ {
+ if (!is_null($alte_location))
+ {
+ $this->_ci->KalenderOrtModel->db->where('kalender_id', $kalender_id);
+ $this->_ci->KalenderOrtModel->db->where('ort_kurzbz IS NULL', null, false);
+ $this->_ci->KalenderOrtModel->db->delete('lehre.tbl_kalender_ort');
+ }
+
+ if (!isEmptyString($location_neu))
+ {
+ $ortresult = $this->_ci->KalenderOrtModel->insert(
+ array (
+ 'kalender_id' => $kalender_id,
+ 'location' => $location_neu
+ )
+ );
+
+ if (isError($ortresult)) return $ortresult;
+ }
+ }
+
return success();
}
@@ -1460,6 +1604,14 @@ class KalenderLib
$kalender_entry = getData($entryResult);
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
+ {
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
+ }
+
$allowed = array(
'planning' => array('sync_preview', 'sync_live'),
'sync_preview' => array('sync_live'),
@@ -1524,22 +1676,21 @@ class KalenderLib
if (!is_null($ort_kurzbz_array))
{
- $new_orte = (array) $ort_kurzbz_array;
- $new_locations = array_fill(0, count($new_orte), null);
+ $new_orte = (array) ($ort_kurzbz_array['ort_kurzbz'] ?? []);
+ $new_locations = $ort_kurzbz_array['location'] ?? null;
}
else
{
$new_orte = (array) $kalender_entry->ort_kurzbz;
- $new_locations = (array) $kalender_entry->location;
+ $new_locations = $kalender_entry->location;
}
- foreach ($new_orte as $index => $ort)
+ foreach ($new_orte as $ort)
{
$ortresult = $this->_ci->KalenderOrtModel->insert(
array(
'kalender_id' => $new_kalender_id,
- 'ort_kurzbz' => $ort,
- 'location' => $new_locations[$index] ?? null
+ 'ort_kurzbz' => $ort
)
);
@@ -1547,6 +1698,19 @@ class KalenderLib
return $ortresult;
}
+ if (!is_null($new_locations))
+ {
+ $locresult = $this->_ci->KalenderOrtModel->insert(
+ array(
+ 'kalender_id' => $new_kalender_id,
+ 'location' => $new_locations
+ )
+ );
+
+ if (!isSuccess($locresult))
+ return $locresult;
+ }
+
return success($new_kalender_id);
}
private function _loadKalenderEntry($kalender_id)
@@ -1569,8 +1733,8 @@ class KalenderLib
$this->_ci->KalenderModel->addJoin(
'(SELECT kalender_id,
- array_agg(ort_kurzbz ORDER BY ort_kurzbz) AS ort_kurzbz,
- array_agg(location ORDER BY ort_kurzbz) AS location
+ array_agg(ort_kurzbz ORDER BY ort_kurzbz) FILTER(WHERE ort_kurzbz is NOT NULL) AS ort_kurzbz,
+ MAX(location) AS location
FROM lehre.tbl_kalender_ort
GROUP BY kalender_id) orte',
'tbl_kalender.kalender_id = orte.kalender_id',
@@ -1586,7 +1750,7 @@ class KalenderLib
$entry = getData($result)[0];
$entry->lehreinheit_id = $entry->lehreinheit_id ?? [];
$entry->ort_kurzbz = $entry->ort_kurzbz ?? [];
- $entry->location = $entry->location ?? [];
+ $entry->location = $entry->location ?? null;
return success($entry);
}
@@ -1641,44 +1805,76 @@ class KalenderLib
private function _deleteTypLehreinheit($entry)
{
- $result_lehreinheit = $this->_ci->KalenderLehreinheitModel->loadWhere(array('kalender_id' => $entry->kalender_id));
- if (isError($result_lehreinheit)) return $result_lehreinheit;
- $has_lehreinheit = hasData($result_lehreinheit) ? getData($result_lehreinheit)[0] : false;
+ $entryResult = $this->_loadKalenderEntry($entry->kalender_id);
- $result_ort = $this->_ci->KalenderOrtModel->loadWhere(array('kalender_id' => $entry->kalender_id));
- if (isError($result_ort)) return $result_ort;
- $has_ort = hasData($result_ort) ? getData($result_ort)[0] : false;
- if ($entry->status_kurzbz === 'planning')
+ if (isError($entryResult)) return $entryResult;
+
+ $kalender_entry = getData($entryResult);
+
+ if (!$this->_checkPermission($kalender_entry->lehreinheit_id))
{
- if ($has_ort)
- $this->_deleteOrtEntry($has_ort);
-
- if ($has_lehreinheit)
- $this->_deleteLehreinheitEntry($has_lehreinheit);
-
- $this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $entry->kalender_id));
+ return error([
+ 'message' => $this->_ci->phraseslib->t('ui', 'keineBerechtigung'),
+ 'errorCode' => 'not_allowed'
+ ]);
}
- else if ($entry->status_kurzbz === 'sync_preview' || $entry->status_kurzbz === 'sync_live')
+
+
+ if ($kalender_entry->status_kurzbz === 'sync_preview' || $kalender_entry->status_kurzbz === 'sync_live' || $kalender_entry->status_kurzbz === 'planning')
{
- $history = $this->getHistory($entry->kalender_id);
- $history = hasData($history) ? getData($history) : false;
+ $history = $this->getHistory($kalender_entry->kalender_id, false, false);
- if ($has_ort)
- $result = $this->_deleteOrtEntry($has_ort);
+ $history = hasData($history) && getData($history);
- if ($has_lehreinheit)
- $result = $this->_deleteLehreinheitEntry($has_lehreinheit);
+ if ($history)
+ {
+ $result = $this->_ci->KalenderModel->update(
+ array('kalender_id' => $kalender_entry->kalender_id),
+ array('status_kurzbz' => 'to_delete','status_kurzbz_max' => 'planning')
+ );
- $this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $entry->kalender_id));
+ if (isError($result))
+ return error($result);
+ }
+ else
+ {
+
+ if (!isEmptyArray($kalender_entry->ort_kurzbz))
+ {
+ $result = $this->_deleteOrtEntry($kalender_entry);
+ if (isError($result))
+ return error($result);
+ }
+
+
+ if (!isEmptyArray($kalender_entry->lehreinheit_id))
+ {
+ $result = $this->_deleteLehreinheitEntry($kalender_entry);
+ if (isError($result))
+ return error($result);
+ }
+
+ $result = $this->_ci->KalenderModel->delete(array('tbl_kalender.kalender_id' => $kalender_entry->kalender_id));
+
+ if (isError($result))
+ return error($result);
+ }
}
- else if ($entry->status_kurzbz === 'preview' || $entry->status_kurzbz === 'live')
+ else if ($kalender_entry->status_kurzbz === 'preview' || $kalender_entry->status_kurzbz === 'live')
{
- //TODO (david) überprüfen ob sinnvoll, verschwindet direkt in den ansichten (student, lecturer)
+ if ($kalender_entry->status_kurzbz === 'preview')
+ $new_status = 'to_delete_preview';
+ else
+ $new_status = 'to_delete_live';
+
$result = $this->_ci->KalenderModel->update(
- array('kalender_id' => $entry->kalender_id),
- array('status_kurzbz' => 'todelete')
+ array('kalender_id' => $kalender_entry->kalender_id),
+ array('status_kurzbz' => $new_status)
);
+
+ if (isError($result))
+ return error($result);
}
return success();
@@ -1703,11 +1899,11 @@ class KalenderLib
return $this->_ci->KalenderEventModel->delete(array('kalender_id' => $entry->kalender_id));
}
- public function getHistory($kalender_id, $only_previous = false)
+ public function getHistory($kalender_id, $only_previous = false, $include_self = true)
{
$dbModel = new DB_Model();
- $history_entries = $dbModel->execReadOnlyQuery("
- WITH RECURSIVE
+ $history_sql ="
+ WITH RECURSIVE
vorgaenger(kalender_id, vorgaenger_kalender_id) AS (
SELECT kalender_id, vorgaenger_kalender_id
FROM lehre.tbl_kalender
@@ -1746,97 +1942,48 @@ class KalenderLib
SELECT kalender_id FROM nachfolger
) combined
JOIN lehre.tbl_kalender USING(kalender_id)
- LEFT JOIN orte USING(kalender_id)
- ORDER BY kalender_id DESC
-
- " . ($only_previous ? ' LIMIT 1' : ''), array($kalender_id, $kalender_id));
+ LEFT JOIN orte USING(kalender_id)";
- return $history_entries;
+ $params = array($kalender_id, $kalender_id);
+
+ if (!$include_self)
+ {
+ $history_sql .= " WHERE kalender_id != ?";
+ $params[] = $kalender_id;
+ }
+
+ $history_sql .= " ORDER BY kalender_id DESC" . ($only_previous ? ' LIMIT 1' : '');
+
+ return $dbModel->execReadOnlyQuery($history_sql, $params);
}
- //TODO in eine eigen Lib?
- public function sync()
+ private function _checkPermission($lehreinheit_ids)
{
- $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
+ if (isEmptyArray($lehreinheit_ids))
+ return true;
- $this->_ci->KalenderModel->addSelect('tbl_kalender.*, tbl_kalender_ort.ort_kurzbz, tbl_kalender_ort.location');
- $this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
- $this->_ci->KalenderModel->db->where_in('status_kurzbz', array('sync_live', 'sync_preview', 'todelete', 'planning', 'preview'));
- $this->_ci->KalenderModel->addOrder('tbl_kalender.kalender_id', 'DESC');
- $to_update = $this->_ci->KalenderModel->load();
+ $allowed = false;
- if (!hasData($to_update))
- return success();
+ $this->_ci->LehreinheitModel->addSelect('studiengang_kz');
+ $this->_ci->LehreinheitModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
+ $this->_ci->LehreinheitModel->db->where_in('lehreinheit_id', $lehreinheit_ids);
- $mail_infos = [];
+ $lehreinheit = $this->_ci->LehreinheitModel->load();
+ if (!hasData($lehreinheit))
+ return error('Lehreinheit nicht gefunden');
- foreach (getData($to_update) as $entry)
+ $studiengaenge = array_unique(array_column(getData($lehreinheit), 'studiengang_kz'));
+
+ foreach ($studiengaenge as $studiengang_kz)
{
- if ($entry->status_kurzbz === 'todelete')
+ if ($this->_ci->permissionlib->isBerechtigt('lehre/lvplan', 'suid', $studiengang_kz))
{
- $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'deleted'));
- $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
- $mail_infos[] = array('entry' => $entry, 'new_status' => 'deleted', 'notify' => array('lektor', 'student'));
- }
-
- if ($entry->status_kurzbz === 'sync_preview')
- {
- $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'preview'));
- $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, true);
- $mail_infos[] = array('entry' => $entry, 'new_status' => 'preview', 'notify' => array('lektor'));
- }
-
- if ($entry->status_kurzbz === 'sync_live' || $entry->status_kurzbz === 'planning')
- {
- $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
- $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
- $mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
- }
-
- if ($entry->status_kurzbz === 'preview')
- {
- $current = getData($this->_ci->KalenderModel->load(array('kalender_id' => $entry->kalender_id)))[0];
- if ($current->status_kurzbz === 'archived')
- continue;
-
- $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
- $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
- $mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
+ $allowed = true;
+ break;
}
}
- $this->_ci->load->library('KalenderNotificationLib');
- $this->_ci->kalendernotificationlib->sendMails($mail_infos);
- return success();
-
- }
-
- private function _archiveVorgaenger($vorgaenger_kalender_id, $stop_at_live = false)
- {
- if (!$vorgaenger_kalender_id) return;
-
- $current_id = $vorgaenger_kalender_id;
-
- while ($current_id)
- {
- $vorgaenger = $this->_ci->KalenderModel->load(array('kalender_id' => $current_id));
- if (!hasData($vorgaenger)) return;
-
- $vorgaenger = getData($vorgaenger)[0];
-
- if ($stop_at_live && $vorgaenger->status_kurzbz === 'live')
- return;
-
- if (in_array($vorgaenger->status_kurzbz, array('preview', 'live')))
- {
- $this->_ci->KalenderModel->update(
- array('kalender_id' => $current_id),
- array('status_kurzbz' => 'archived')
- );
- }
-
- $current_id = $vorgaenger->vorgaenger_kalender_id;
- }
+ return $allowed;
}
private function getLanguageIndex()
diff --git a/application/libraries/KalenderNotificationLib.php b/application/libraries/KalenderNotificationLib.php
index d611eb247..acf14bae7 100644
--- a/application/libraries/KalenderNotificationLib.php
+++ b/application/libraries/KalenderNotificationLib.php
@@ -10,7 +10,7 @@ class KalenderNotificationLib
$this->_ci =& get_instance();
$this->_ci->load->library('MailLib');
$this->_ci->load->config('tempus');
-
+ $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
}
public function sendMails($mail_infos)
@@ -90,6 +90,7 @@ class KalenderNotificationLib
if (!empty($student_deleted))
$student_entries .= $this->_addToList($student_deleted, 'gelöscht') . '
';
+ //TODO (david) richtigen Empfänger
if (!empty($lektor_entries))
$this->_ci->maillib->send('', 'ma0048@technikum-wien.at', 'Lektor Tempus Update', $lektor_entries);
if (!empty($student_entries))
diff --git a/application/libraries/KalenderSyncLib.php b/application/libraries/KalenderSyncLib.php
new file mode 100644
index 000000000..fce0ecd5d
--- /dev/null
+++ b/application/libraries/KalenderSyncLib.php
@@ -0,0 +1,429 @@
+ array('planning', 'sync_preview'),
+ 'live' => array('planning', 'sync_preview', 'preview', 'sync_live')
+ );
+
+ public function __construct()
+ {
+ $this->_ci =& get_instance();
+
+ $this->_ci->load->model('ressource/Kalender_model', 'KalenderModel');
+ $this->_ci->load->model('ressource/Kalendersyncstatus_model', 'KalendersyncstatusModel');
+ $this->_ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
+ $this->_ci->load->model('organisation/Organisationseinheit_model', 'OrganisationseinheitModel');
+ $this->_ci->load->library('KalenderLib');
+ }
+
+ public function run($studiensemester_kurzbz)
+ {
+ $this->_ci->KalendersyncstatusModel->db->where('studiensemester_kurzbz', $studiensemester_kurzbz);
+
+ $configs = $this->_ci->KalendersyncstatusModel->load();
+
+ if (isError($configs))
+ return $configs;
+
+ if (!hasData($configs))
+ return success([]);
+
+ $results = [];
+ $mail_infos_gesamt = [];
+
+ foreach (getData($configs) as $config)
+ {
+
+ $ziel_status = isEmptyString($config->sync_status_kurzbz) ? 'live' : $config->sync_status_kurzbz;
+
+ $relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
+
+ $kalender_ids_result = $this->getKalenderIds(
+ $config->oe_kurzbz,
+ $config->studiensemester_kurzbz,
+ $relevante_stati,
+ $config->ausbildungssemester,
+ $config->studienplan_id,
+ $config->datum_bis
+ );
+
+ if (isError($kalender_ids_result))
+ return $kalender_ids_result;
+
+ $kalender_ids = getData($kalender_ids_result);
+
+ $sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
+
+ if (isError($sync_result))
+ return $sync_result;
+
+ $sync_data = getData($sync_result);
+
+ if ((bool) $config->mail)
+ $mail_infos_gesamt = array_merge($mail_infos_gesamt, $sync_data['mail_infos']);
+
+ $results[] = [
+ 'kalender_syncstatus_id' => $config->kalender_syncstatus_id,
+ 'oe_kurzbz' => $config->oe_kurzbz,
+ 'ausbildungssemester' => $config->ausbildungssemester,
+ 'studienplan_id' => $config->studienplan_id,
+ 'ziel_status' => $ziel_status,
+ 'mail' => (bool) $config->mail,
+ 'synced' => $sync_data['synced']
+ ];
+ }
+
+ if (!empty($mail_infos_gesamt))
+ {
+ $this->_ci->load->library('KalenderNotificationLib');
+ $this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
+ }
+
+ return success($results);
+ }
+
+ public function runManual($oe_kurzbz, $studiensemester_kurzbz, $ausbildungssemester = null, $studienplan_id = null, $mail = true, $datum_bis = null, $ziel_status = 'live')
+ {
+ $relevante_stati = array_merge($this->status_map[$ziel_status], array('to_delete', 'to_delete_live', 'to_delete_preview'));
+
+ $kalender_ids_result = $this->getKalenderIds(
+ $oe_kurzbz,
+ $studiensemester_kurzbz,
+ $relevante_stati,
+ $ausbildungssemester,
+ $studienplan_id,
+ $datum_bis
+ );
+
+ if (isError($kalender_ids_result))
+ return $kalender_ids_result;
+
+ $kalender_ids = getData($kalender_ids_result);
+
+ $sync_result = $this->_syncKalenderIds($kalender_ids, $ziel_status);
+
+ if (isError($sync_result))
+ return $sync_result;
+
+ $sync_data = getData($sync_result);
+
+ if ($mail && !empty($sync_data['mail_infos']))
+ {
+ $this->_ci->load->library('KalenderNotificationLib');
+ $this->_ci->kalendernotificationlib->sendMails($sync_data['mail_infos']);
+ }
+
+ return success(['synced' => $sync_data['synced']]);
+ }
+
+ public function sync()
+ {
+ $mail_infos_gesamt = [];
+ $synced_gesamt = 0;
+
+ $todelete_ids_result = $this->_getManuallySetStatus(array('to_delete', 'to_delete_live', 'to_delete_preview'));
+
+ if (isError($todelete_ids_result))
+ return $todelete_ids_result;
+
+ $todelete_result = $this->_syncKalenderIds(getData($todelete_ids_result), null);
+
+ if (isError($todelete_result))
+ return $todelete_result;
+
+ $todelete_data = getData($todelete_result);
+ $mail_infos_gesamt = array_merge($mail_infos_gesamt, $todelete_data['mail_infos']);
+ $synced_gesamt += $todelete_data['synced'];
+
+ $preview_ids_result = $this->_getManuallySetStatus(array('sync_preview'));
+
+ if (isError($preview_ids_result))
+ return $preview_ids_result;
+
+ $preview_result = $this->_syncKalenderIds(getData($preview_ids_result), 'preview');
+
+ if (isError($preview_result))
+ return $preview_result;
+
+ $preview_data = getData($preview_result);
+ $mail_infos_gesamt = array_merge($mail_infos_gesamt, $preview_data['mail_infos']);
+ $synced_gesamt += $preview_data['synced'];
+
+ $live_ids_result = $this->_getManuallySetStatus(array('sync_live'));
+
+ if (isError($live_ids_result))
+ return $live_ids_result;
+
+ $live_result = $this->_syncKalenderIds(getData($live_ids_result), 'live');
+
+ if (isError($live_result))
+ return $live_result;
+
+ $live_data = getData($live_result);
+ $mail_infos_gesamt = array_merge($mail_infos_gesamt, $live_data['mail_infos']);
+ $synced_gesamt += $live_data['synced'];
+
+ if (!empty($mail_infos_gesamt))
+ {
+ $this->_ci->load->library('KalenderNotificationLib');
+ $this->_ci->kalendernotificationlib->sendMails($mail_infos_gesamt);
+ }
+
+ return success(['synced' => $synced_gesamt]);
+ }
+
+ private function _getManuallySetStatus($status_kurzbz_list)
+ {
+ if (empty($status_kurzbz_list))
+ return success([]);
+
+ $this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
+ $this->_ci->KalenderModel->db->where_in('status_kurzbz', $status_kurzbz_list);
+ $result = $this->_ci->KalenderModel->load();
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return success([]);
+
+ return success(array_column(getData($result), 'kalender_id'));
+ }
+
+ public function getKalenderIds($oe_kurzbz, $studiensemester_kurzbz, $status_kurzbz_list, $ausbildungssemester = null, $studienplan_id = null, $datum_bis = null)
+ {
+ if (empty($status_kurzbz_list))
+ return success([]);
+
+ $studiengang_result = $this->_getStudiengang($oe_kurzbz);
+
+ if (isError($studiengang_result))
+ return $studiengang_result;
+
+ $studiengang_kz = getData($studiengang_result);
+
+ if (!hasData($studiengang_result))
+ {
+ $organisationseinheiten = $this->_ci->OrganisationseinheitModel->getChilds($oe_kurzbz);
+ $oe_kurzbz = hasData($organisationseinheiten) ? array_column(getData($organisationseinheiten), 'oe_kurzbz') : [];
+ }
+
+ $this->_ci->KalenderModel->addDistinct('tbl_kalender.kalender_id');
+ $this->_ci->KalenderModel->addSelect('tbl_kalender.kalender_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_lehreinheit', 'tbl_kalender.kalender_id = tbl_kalender_lehreinheit.kalender_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheit', 'tbl_kalender_lehreinheit.lehreinheit_id = tbl_lehreinheit.lehreinheit_id');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_lehrveranstaltung', 'tbl_lehreinheit.lehrveranstaltung_id = tbl_lehrveranstaltung.lehrveranstaltung_id');
+
+ if (!is_null($studiengang_kz))
+ {
+ $this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.studiengang_kz', $studiengang_kz);
+ }
+ else
+ {
+ $this->_ci->KalenderModel->db->where_in('tbl_lehrveranstaltung.oe_kurzbz', $oe_kurzbz);
+ }
+
+ $this->_ci->KalenderModel->db->where('tbl_lehreinheit.studiensemester_kurzbz', $studiensemester_kurzbz);
+ $this->_ci->KalenderModel->db->where_in('tbl_kalender.status_kurzbz', $status_kurzbz_list);
+
+ $this->_ci->KalenderModel->db->where('NOT EXISTS (
+ SELECT 1 FROM lehre.tbl_kalender nachfolger
+ WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id)', null, false);
+
+ if (!is_null($studienplan_id))
+ {
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_studienplan_lehrveranstaltung', 'tbl_lehrveranstaltung.lehrveranstaltung_id = tbl_studienplan_lehrveranstaltung.lehrveranstaltung_id');
+ $this->_ci->KalenderModel->db->where('tbl_studienplan_lehrveranstaltung.studienplan_id', $studienplan_id);
+ }
+
+ if (!is_null($ausbildungssemester))
+ $this->_ci->KalenderModel->db->where('tbl_lehrveranstaltung.semester', $ausbildungssemester);
+
+ if (!is_null($datum_bis))
+ {
+ $end_date = date('Y-m-d', strtotime($datum_bis . ' +1 day'));
+ $this->_ci->KalenderModel->db->where('tbl_kalender.von <', $end_date);
+ }
+
+ $result = $this->_ci->KalenderModel->load();
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return success([]);
+
+ return success(array_column(getData($result), 'kalender_id'));
+ }
+
+
+ private function _archiveVorgaenger($vorgaenger_kalender_id, $stop_at_live = false)
+ {
+ $return_array = array();
+ if (!$vorgaenger_kalender_id) return success($return_array);
+
+ $current_id = $vorgaenger_kalender_id;
+
+ while ($current_id)
+ {
+ $vorgaenger = $this->_ci->KalenderModel->load(array('kalender_id' => $current_id));
+ if (!hasData($vorgaenger)) return success($return_array);
+
+ $vorgaenger = getData($vorgaenger)[0];
+
+ if ($stop_at_live && $vorgaenger->status_kurzbz === 'live')
+ return success($return_array);
+
+ if (in_array($vorgaenger->status_kurzbz, array('preview', 'live')))
+ {
+ $this->_ci->KalenderModel->update(
+ array('kalender_id' => $current_id),
+ array('status_kurzbz' => 'archived', 'status_kurzbz_max' => $vorgaenger->status_kurzbz)
+ );
+
+ $return_array[] = $vorgaenger;
+ }
+
+ $current_id = $vorgaenger->vorgaenger_kalender_id;
+ }
+ return success($return_array);
+ }
+
+ private function _syncKalenderIds($kalender_ids, $ziel_status)
+ {
+ if (empty($kalender_ids))
+ return success(['synced' => 0, 'mail_infos' => []]);
+
+ $this->_ci->KalenderModel->addSelect('tbl_kalender.*, tbl_kalender_ort.ort_kurzbz, tbl_kalender_ort.location');
+ $this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'tbl_kalender.kalender_id = tbl_kalender_ort.kalender_id', 'LEFT');
+ $this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
+ $this->_ci->KalenderModel->addOrder('tbl_kalender.kalender_id', 'DESC');
+ $to_update = $this->_ci->KalenderModel->load();
+
+ if (isError($to_update))
+ return $to_update;
+
+ if (!hasData($to_update))
+ return success(['synced' => 0, 'mail_infos' => []]);
+
+ $mail_infos = [];
+ $synced = 0;
+
+ foreach (getData($to_update) as $entry)
+ {
+ if (in_array($entry->status_kurzbz, array('to_delete', 'to_delete_live', 'to_delete_preview')))
+ {
+ $notify = array();
+ if ($entry->status_kurzbz === 'to_delete_live')
+ {
+ $status_max = 'live';
+ $notify = array('lektor', 'student');
+ }
+ else if ($entry->status_kurzbz === 'to_delete_preview')
+ {
+ $status_max = 'preview';
+ $notify = array('lektor');
+ }
+ else if ($entry->status_kurzbz === 'to_delete')
+ {
+ $status_max = 'planning';
+ }
+
+ $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'deleted', 'status_kurzbz_max' => $status_max));
+ $mail_infos[] = array('entry' => $entry, 'new_status' => 'deleted', 'notify' => $notify);
+
+ $vorgaenger_array = $this->_archiveVorgaenger($entry->vorgaenger_kalender_id);
+
+
+
+ if (hasData($vorgaenger_array))
+ {
+ foreach(getData($vorgaenger_array) as $vorgaenger)
+ {
+ $archive_notify = array();
+
+ if ($vorgaenger->status_kurzbz === 'preview')
+ $archive_notify = array('lektor');
+ else if ($vorgaenger->status_kurzbz === 'live')
+ {
+ $archive_notify = array('student', 'lektor');
+
+ $history = $this->_ci->kalenderlib->getHistory($vorgaenger->kalender_id, false, false);
+ if (hasData($history))
+ {
+ $history = getData($history);
+
+ foreach ($history as $entry)
+ {
+ if ($entry->status_kurzbz === 'deleted' && $entry->status_kurzbz_max === 'preview')
+ {
+ $archive_notify = array('student');
+ break;
+ }
+ }
+ }
+ }
+
+ $mail_infos[] = array('entry' => $vorgaenger, 'new_status' => 'deleted', 'notify' => $archive_notify);
+ }
+ }
+
+ $synced++;
+ continue;
+ }
+
+ if ($ziel_status === 'preview' && in_array($entry->status_kurzbz, array('planning', 'sync_preview')))
+ {
+ $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'preview'));
+ $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, true);
+ $mail_infos[] = array('entry' => $entry, 'new_status' => 'preview', 'notify' => array('lektor'));
+ $synced++;
+ continue;
+ }
+
+ if ($ziel_status === 'live' && in_array($entry->status_kurzbz, array('planning', 'sync_preview', 'sync_live')))
+ {
+ $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
+ $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
+ $mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
+ $synced++;
+ continue;
+ }
+
+ if ($ziel_status === 'live' && $entry->status_kurzbz === 'preview')
+ {
+ $current = getData($this->_ci->KalenderModel->load(array('kalender_id' => $entry->kalender_id)))[0];
+ if ($current->status_kurzbz === 'archived')
+ continue;
+
+ $this->_ci->KalenderModel->update(array('kalender_id' => $entry->kalender_id), array('status_kurzbz' => 'live'));
+ $this->_archiveVorgaenger($entry->vorgaenger_kalender_id, false);
+ $mail_infos[] = array('entry' => $entry, 'new_status' => 'live', 'notify' => array('lektor', 'student'));
+ $synced++;
+ }
+ }
+
+ return success(['synced' => $synced, 'mail_infos' => $mail_infos]);
+ }
+
+
+ private function _getStudiengang($oe_kurzbz)
+ {
+ $this->_ci->StudiengangModel->addJoin('tbl_organisationseinheit', 'oe_kurzbz');
+ $result = $this->_ci->StudiengangModel->loadWhere(array('oe_kurzbz' => $oe_kurzbz));
+
+ if (isError($result))
+ return $result;
+
+ if (!hasData($result))
+ return success(null);
+
+ return success(getData($result)[0]->studiengang_kz);
+ }
+}
\ No newline at end of file
diff --git a/application/libraries/RaumvorschlagLib.php b/application/libraries/RaumvorschlagLib.php
index 8cb4aa8a4..2953de428 100644
--- a/application/libraries/RaumvorschlagLib.php
+++ b/application/libraries/RaumvorschlagLib.php
@@ -22,13 +22,14 @@ class RaumvorschlagLib
$this->_ci->load->model('ressource/Ort_model', 'OrtModel');
$this->_ci->load->model('organisation/gruppe_model', 'GruppeModel');
$this->_ci->load->model('organisation/Lehrverband_model', 'LehrverbandModel');
-
- $this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel');
+ $this->_ci->load->model('ressource/Zeitsperre_model', 'ZeitsperreModel');
+ $this->_ci->load->model('ressource/Stunde_model', 'StundeModel');
$this->_ci->load->model('education/Lehreinheitgruppe_model', 'LehreinheitgruppeModel');
$this->_ci->load->library('CollisionChecker');
$this->_ci->load->library('KalenderLib');
$this->_ci->load->library('PhrasesLib', array('ui'));
+ $this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
}
@@ -36,47 +37,295 @@ class RaumvorschlagLib
{
$event = $this->_ci->kalenderlib->getByKalenderId($kalender_id);
$event = $event[0];
+ return $this->_getVorschlaegeForEvent($event);
+ }
- $lektor_uids = array_column($event->lektor, 'mitarbeiter_uid');
- $gruppen_kurzbz = array_values(array_filter(array_column($event->gruppe, 'gruppe_kurzbz')));
+ public function getVorschlaegeByLehreinheit($lehreinheit_id, $von, $bis)
+ {
+ $teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
- $lehrverband_gruppen = array_values(array_filter($event->gruppe, function($gruppe)
+ $event = (object) [
+ 'kalender_id' => null,
+ 'lehreinheit_id' => [$lehreinheit_id],
+ 'isostart' => (new DateTime($von))->format('c'),
+ 'isoend' => (new DateTime($bis))->format('c'),
+ 'datum' => (new DateTime($von))->format('Y-m-d'),
+ 'lektor' => $teilnehmer->lektor_data,
+ 'gruppe' => $teilnehmer->gruppen_data,
+ ];
+
+ return $this->_getVorschlaegeForEvent($event);
+ }
+
+ public function getVorschlaegeSlots($lehreinheit_id, $start_date, $end_date)
+ {
+ $lehreinheit_result = $this->_ci->LehreinheitModel->load($lehreinheit_id);
+ if (!hasData($lehreinheit_result))
+ return error('Lehreinheit nicht gefunden');
+ $lehreinheit = getData($lehreinheit_result)[0];
+
+ $block = $lehreinheit->stundenblockung;
+ if ($block <= 0)
+ return error('Stundenblockung ist ungültig');
+
+ $this->_ci->StundeModel->addOrder('stunde', 'ASC');
+ $stunden_result = $this->_ci->StundeModel->load();
+ $stunden = hasData($stunden_result) ? array_values(getData($stunden_result)) : [];
+
+ if (empty($stunden))
+ return error('Kein Stunden-Raster gefunden');
+
+ $teilnehmer = $this->_getLehreinheitTeilnehmer($lehreinheit_id);
+ $grp = $this->_splitGruppen($teilnehmer->gruppen_data);
+ $lektor_uids = array_column($teilnehmer->lektor_data, 'mitarbeiter_uid');
+
+ $verplante_events = $this->_ci->kalenderlib->getForRaumvorschlag(
+ $start_date,
+ $end_date,
+ $lektor_uids,
+ $grp->gruppen_kurzbz,
+ $grp->lehrverband_gruppen
+ );
+
+ $start_day = strtotime($start_date);
+ $end_day = strtotime($end_date);
+
+ $moegliche_slots = array();
+
+ $verplante_zeitsperren = $this->_getZeitsperen($start_date, $end_date, $lektor_uids);
+ while ($start_day <= $end_day)
+ {
+ $tag = date('Y-m-d', $start_day);
+
+ $verplante_tages_events = array_values(array_filter($verplante_events, function($event) use ($tag)
+ {
+ return $event->datum === $tag;
+ }));
+
+ foreach ($stunden as $index => $start_stunde)
+ {
+ if (!isset($stunden[$index + $block - 1]))
+ continue;
+
+ $end_stunde = $stunden[$index + $block - 1];
+
+ $slot_start = $tag . ' ' . $start_stunde->beginn;
+ $slot_end = $tag . ' ' . $end_stunde->ende;
+
+ if (!$this->_isFrei($slot_start, $slot_end, $verplante_zeitsperren, $lektor_uids, 'lektor'))
+ continue;
+
+ if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $lektor_uids, 'lektor'))
+ continue;
+
+ if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->gruppen_kurzbz, 'gruppe'))
+ continue;
+
+ if (!$this->_isFrei($slot_start, $slot_end, $verplante_tages_events, $grp->lehrverband_gruppen_bezeichnung, 'lehrverband'))
+ continue;
+
+ $moegliche_slots[] = [
+ 'isostart' => (new DateTime($slot_start))->format('c'),
+ 'isoend' => (new DateTime($slot_end))->format('c'),
+ 'marker_isoend' => (new DateTime($tag . ' ' . $start_stunde->ende))->format('c'),
+ ];
+ }
+
+ $start_day = strtotime('+1 day', $start_day);
+ }
+
+
+ $slots = [];
+ foreach ($moegliche_slots as $slot)
+ {
+ $event_obj = (object) [
+ 'kalender_id' => null,
+ 'lehreinheit_id' => [$lehreinheit_id],
+ 'isostart' => $slot['isostart'],
+ 'isoend' => $slot['isoend'],
+ ];
+
+ $raumkandidaten = $this->_getRaumkandidaten($event_obj);
+
+ if (empty($raumkandidaten))
+ continue;
+
+ $ratings = $this->_getRatings($verplante_events, $slot, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
+ $best = $ratings[0];
+ $anzahl_weitere = count($ratings) - 1;
+
+ $slots[] = [
+ 'isostart' => $slot['isostart'],
+ 'isoend' => $slot['isoend'],
+ 'marker_isoend' => $slot['marker_isoend'],
+ 'rating' => $this->_scoreToRating($best['score']),
+ 'label' => $anzahl_weitere > 0 ? $best['ort_kurzbz'] . ' (' . $best['score'] . ') + ' . $anzahl_weitere . ' weitere' : $best['ort_kurzbz'] . ' (' . $best['score'] . ')',
+ 'raeume' => $ratings,
+ ];
+ }
+ return success($slots);
+ }
+
+ private function _getZeitsperen($start_date, $end_date, $uids)
+ {
+
+ if (empty($uids)) return [];
+
+ if (($this->_ci->variablelib->getVar('ignore_kollision') === 'true') || ($this->_ci->variablelib->getVar('ignore_zeitsperre') === 'true')) return [];
+
+
+ $this->_ci->ZeitsperreModel->addSelect('mitarbeiter_uid, vondatum, vonstunde_z.beginn as von_beginn, bisdatum, bisstunde_z.ende as bis_ende');
+ $this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde vonstunde_z', 'vonstunde_z.stunde = tbl_zeitsperre.vonstunde', 'LEFT');
+ $this->_ci->ZeitsperreModel->addJoin('lehre.tbl_stunde bisstunde_z', 'bisstunde_z.stunde = tbl_zeitsperre.bisstunde', 'LEFT');
+ $this->_ci->ZeitsperreModel->db->where('zeitsperretyp_kurzbz !=', 'ZVerfueg');
+ $this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp <', $end_date);
+ $this->_ci->ZeitsperreModel->db->where('(tbl_zeitsperre.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp >', $start_date);
+
+ $this->_ci->ZeitsperreModel->db->where_in('mitarbeiter_uid', $uids);
+ $result = $this->_ci->ZeitsperreModel->load();
+
+ if (!hasData($result)) return [];
+
+ $events = [];
+ foreach (getData($result) as $row)
+ {
+ $von = new DateTime($row->vondatum . ' ' . ($row->von_beginn ?? '00:00'));
+ $bis = new DateTime($row->bisdatum . ' ' . ($row->bis_ende ?? '23:59'));
+
+ $events[] = (object)[
+ 'isostart' => $von->format('c'),
+ 'isoend' => $bis->format('c'),
+ 'lektor' => [['mitarbeiter_uid' => $row->mitarbeiter_uid]]
+ ];
+ }
+ return $events;
+ }
+
+ private function _getLehreinheitTeilnehmer($lehreinheit_id)
+ {
+ $lektoren_result = $this->_ci->LehreinheitMitarbeiterModel->loadWhere(['lehreinheit_id' => $lehreinheit_id]);
+ $lektor_data = [];
+ if (hasData($lektoren_result))
+ {
+ $lektor_data = getData($lektoren_result);
+ }
+
+ $gruppen_result = $this->_ci->LehreinheitgruppeModel->getByLehreinheit($lehreinheit_id);
+ $gruppen_data = [];
+ if (hasData($gruppen_result))
+ {
+ $gruppen_rows = getData($gruppen_result);
+
+ foreach ($gruppen_rows as $gruppe)
+ {
+ $gruppen_data[] = (array) $gruppe;
+ }
+ }
+
+
+ return (object)[
+ 'lektor_data' => $lektor_data,
+ 'gruppen_data' => $gruppen_data,
+ ];
+
+ }
+
+ private function _splitGruppen($gruppen_data)
+ {
+ $gruppen_kurzbz = array_values(array_filter(array_column($gruppen_data, 'gruppe_kurzbz')));
+ $lehrverband_gruppen = array_values(array_filter($gruppen_data, function($gruppe)
{
return empty($gruppe['gruppe_kurzbz']);
}));
+ $lehrverband_gruppen_bezeichnung = array_column($lehrverband_gruppen, 'bezeichnung');
+
+ return (object)[
+ 'gruppen_kurzbz' => $gruppen_kurzbz,
+ 'lehrverband_gruppen' => $lehrverband_gruppen,
+ 'lehrverband_gruppen_bezeichnung' => $lehrverband_gruppen_bezeichnung
+ ];
+
+ }
+ //TODO (david) umbauen auf CollisionChecks
+ private function _isFrei($slot_start, $slot_end, $events, $check_array, $type)
+ {
+ if (empty($check_array)) return true;
+
+ $slot_start_ts = strtotime($slot_start);
+ $slot_end_ts = strtotime($slot_end);
+
+ foreach ($events as $event)
+ {
+ $event_start_ts = strtotime($event->isostart);
+ $event_end_ts = strtotime($event->isoend);
+
+ if ($event_end_ts <= $slot_start_ts || $event_start_ts >= $slot_end_ts)
+ continue;
+
+ $event_uids = $this->_getIds($event, $type);
+
+ if (!empty(array_intersect($event_uids, $check_array)))
+ return false;
+ }
+
+ return true;
+ }
+
+ private function _scoreToRating($score)
+ {
+ if ($score >= 90)
+ return 'good';
+ if ($score >= 60)
+ return 'mid';
+ return 'bad';
+ }
+ private function _getVorschlaegeForEvent($event)
+ {
+ $raumkandidaten = $this->_getRaumkandidaten($event);
+ if (empty($raumkandidaten)) return [];
+
+ $lektor_uids = array_column($event->lektor, 'mitarbeiter_uid');
+ $grp = $this->_splitGruppen($event->gruppe);
$tages_events = $this->_ci->kalenderlib->getForRaumvorschlag(
$event->datum,
$event->datum,
$lektor_uids,
- $gruppen_kurzbz,
- $lehrverband_gruppen
+ $grp->gruppen_kurzbz,
+ $grp->lehrverband_gruppen
);
- $lektor_davor = $this->_getEventDavor($tages_events, $event->isostart, $lektor_uids, 'lektor');
- $gruppen_davor = $this->_getEventDavor($tages_events, $event->isostart, $gruppen_kurzbz, 'gruppe');
+ return $this->_getRatings($tages_events, $event, $raumkandidaten, $lektor_uids, $grp->gruppen_kurzbz, $grp->lehrverband_gruppen_bezeichnung);
+ }
+ private function _getRatings($events, $event, $raumkandidaten, $lektor_uids, $gruppen_kurzbz, $lehrverband_gruppen_bezeichnung)
+ {
+ $event = (object)$event;
+ $lektor_davor = $this->_getEventDavor($events, $event->isostart, $lektor_uids, 'lektor');
+ $gruppen_davor = $this->_getEventDavor($events, $event->isostart, $gruppen_kurzbz, 'gruppe');
+ $lehrverband_davor = $this->_getEventDavor($events, $event->isostart, $lehrverband_gruppen_bezeichnung, 'lehrverband');
$lektor_davor_ort = $lektor_davor ? $this->_getOrtDetails($lektor_davor->ort_kurzbz) : null;
$gruppen_davor_ort = $gruppen_davor ? $this->_getOrtDetails($gruppen_davor->ort_kurzbz) : null;
-
- $kandidaten = $this->_getRaumkandidaten($event);
- if (empty($kandidaten)) return [];
+ $lehrverband_davor_ort = $lehrverband_davor ? $this->_getOrtDetails($lehrverband_davor->ort_kurzbz) : null;
$unique = [];
- foreach ($kandidaten as $raum)
+ foreach ($raumkandidaten as $raum)
{
$unique[$raum->ort_kurzbz] = $raum;
}
$kandidaten = array_values($unique);
+
$ratings = [];
foreach ($kandidaten as $raum)
{
- $rating = ['ort_kurzbz' => $raum->ort_kurzbz, 'score' => 100, 'details' => []];
+ $rating = ['ort_kurzbz' => $raum->ort_kurzbz, 'score' => 100, 'details' => [],
+ 'raumtyp_kurzbz' => $raum->raumtyp_kurzbz, 'max_person' => $raum->max_person];
$this->_rateLektor($rating, $raum, $lektor_davor_ort);
$this->_rateGruppen($rating, $raum, $gruppen_davor_ort);
+ $this->_rateGruppen($rating, $raum, $lehrverband_davor_ort);
Events::trigger('room_rating',
function & () use (&$rating) {
@@ -204,10 +453,7 @@ class RaumvorschlagLib
if (empty($event->ort_kurzbz))
continue;
- if ($type === 'lektor')
- $event_uids = array_column($event->lektor, 'mitarbeiter_uid');
- else
- $event_uids = array_column($event->gruppe, 'gruppe_kurzbz');
+ $event_uids = $this->_getIds($event, $type);
if (empty(array_intersect($event_uids, $uids)))
continue;
@@ -219,6 +465,20 @@ class RaumvorschlagLib
return $kandidat;
}
+ private function _getIds($event, $type)
+ {
+ $event_uids = array();
+
+ if ($type === 'lektor')
+ $event_uids = array_column($event->lektor, 'mitarbeiter_uid');
+ else if ($type === 'gruppe')
+ $event_uids = array_column($event->gruppe, 'gruppe_kurzbz');
+ else if ($type === 'lehrverband')
+ $event_uids = array_column($event->gruppe, 'bezeichnung');
+
+ return $event_uids;
+ }
+
private function _getRaumkandidaten($event)
{
$raumtyp = null;
@@ -240,9 +500,19 @@ class RaumvorschlagLib
$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']);
+ if (!is_null($event->kalender_id))
+ {
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $event->kalender_id);
+ }
+ $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', ['deleted', 'to_delete', 'to_delete_live', 'to_delete_preview', 'archived']);
$this->_ci->KalenderModel->db->where('tbl_kalender_ort.ort_kurzbz IS NOT NULL', null, false);
+ $this->_ci->KalenderModel->db->where(
+ 'NOT EXISTS (
+ SELECT 1 FROM lehre.tbl_kalender nachfolger
+ WHERE nachfolger.vorgaenger_kalender_id = tbl_kalender.kalender_id
+ )', null, false
+ );
+
$belegte = $this->_ci->KalenderModel->load();
$belegte_orte = hasData($belegte) ? array_column(getData($belegte), 'ort_kurzbz') : [];
@@ -273,7 +543,7 @@ class RaumvorschlagLib
private function _getFreieRaeume($raumtyp, $belegte_orte)
{
- $this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id');
+ $this->_ci->OrtModel->addSelect('ort_kurzbz, stockwerk, standort_id, max_person, raumtyp_kurzbz');
$this->_ci->OrtModel->addJoin('public.tbl_ortraumtyp', 'ort_kurzbz');
if (!empty($raumtyp))
@@ -290,11 +560,4 @@ class RaumvorschlagLib
return $this->_ci->OrtModel->load();
}
-
-
-
-
-
-
-
}
diff --git a/application/libraries/collision/checks/LectureCollisionCheck.php b/application/libraries/collision/checks/LectureCollisionCheck.php
index 21635e203..750f7c5ca 100644
--- a/application/libraries/collision/checks/LectureCollisionCheck.php
+++ b/application/libraries/collision/checks/LectureCollisionCheck.php
@@ -10,6 +10,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('education/Lehreinheitmitarbeiter_model', 'LehreinheitmitarbeiterModel');
$this->_ci->load->library('VariableLib', array('uid' => getAuthUID()));
$this->_ci->load->library('PhrasesLib', array('ui'));
@@ -22,11 +23,17 @@ class LectureCollisionCheck implements ICollisionCheck
public function check($data)
{
- if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
+ if (!isset($data->von, $data->bis)) return [];
+ if (empty($data->kalender_id) && empty($data->lehreinheit_id) && empty($data->uids)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
- $uids = $this->_getUids($data->kalender_id);
+ if (!empty($data->kalender_id))
+ $uids = $this->_getUids($data->kalender_id);
+ else if (!empty($data->lehreinheit_id))
+ $uids = $this->_getUidsFromLehreinheit($data->lehreinheit_id);
+ else
+ $uids = $data->uids;
if (empty($uids)) return [];
@@ -58,9 +65,17 @@ class LectureCollisionCheck implements ICollisionCheck
$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_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
- $this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
+
+ $this->_ci->KalenderModel->db->group_start();
+ $where_ids_chunks = array_chunk($kalender_ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
+ }
+ $this->_ci->KalenderModel->db->group_end();
+
$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
@@ -85,9 +100,17 @@ class LectureCollisionCheck implements ICollisionCheck
$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_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
- $this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
+
+ $this->_ci->KalenderModel->db->group_start();
+ $where_ids_chunks = array_chunk($kalender_ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
+ }
+ $this->_ci->KalenderModel->db->group_end();
+
$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
@@ -114,7 +137,13 @@ class LectureCollisionCheck implements ICollisionCheck
$this->_ci->KalenderModel->db->where('(z.vondatum + COALESCE(vonstunde_z.beginn, \'00:00\'))::timestamp < tbl_kalender.bis', null, false);
$this->_ci->KalenderModel->db->where('(z.bisdatum + COALESCE(bisstunde_z.ende, \'23:59\'))::timestamp > tbl_kalender.von', null, false);
$this->_ci->KalenderModel->db->where_not_in('current_lehreinheit_ma.mitarbeiter_uid', $kollisionsfreie_user);
- $this->_ci->KalenderModel->db->where_in('tbl_kalender.kalender_id', $kalender_ids);
+ $this->_ci->KalenderModel->db->group_start();
+ $where_ids_chunks = array_chunk($kalender_ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
+ }
+ $this->_ci->KalenderModel->db->group_end();
$result = $this->_ci->KalenderModel->load();
@@ -159,6 +188,20 @@ class LectureCollisionCheck implements ICollisionCheck
return array_unique(array_merge($mitarbeiter_uids, $event_teilnehmer));
}
+ private function _getUidsFromLehreinheit($lehreinheit_id)
+ {
+ $kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
+
+ $result = $this->_ci->LehreinheitmitarbeiterModel->loadWhere(array('lehreinheit_id' => $lehreinheit_id));
+
+ if (isError($result) || !hasData($result)) return [];
+
+ $uids = array_column(getData($result), 'mitarbeiter_uid');
+ $uids = array_diff(array_filter($uids), $kollisionsfreie_user);
+
+ return array_values(array_unique($uids));
+ }
+
private function _checkLehreinheit($uids, $data)
{
$kollisionsfreie_user = unserialize(KOLLISIONSFREIE_USER);
@@ -170,8 +213,9 @@ class LectureCollisionCheck implements ICollisionCheck
$this->_ci->KalenderModel->addJoin('lehre.tbl_lehreinheitmitarbeiter', 'lehreinheit_id', 'LEFT');
$this->_ci->KalenderModel->db->where_in('mitarbeiter_uid', $uids);
- $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
- $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete'));
+ if (!empty($data->kalender_id))
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
+ $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('mitarbeiter_uid', $kollisionsfreie_user);
$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)',
@@ -207,8 +251,9 @@ class LectureCollisionCheck implements ICollisionCheck
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_event_teilnehmer', 'tbl_kalender_event.kalender_id = tbl_kalender_event_teilnehmer.kalender_id', 'LEFT');
$this->_ci->KalenderModel->db->where_in('tbl_kalender_event_teilnehmer.uid', $uids);
- $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
- $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete'));
+ if (!empty($data->kalender_id))
+ $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
+ $this->_ci->KalenderModel->db->where_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_not_in('uid', $kollisionsfreie_user);
$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)',
diff --git a/application/libraries/collision/checks/ResourcesCollisionCheck.php b/application/libraries/collision/checks/ResourcesCollisionCheck.php
index 0c957965d..da163977e 100644
--- a/application/libraries/collision/checks/ResourcesCollisionCheck.php
+++ b/application/libraries/collision/checks/ResourcesCollisionCheck.php
@@ -20,7 +20,7 @@ class ResourcesCollisionCheck implements ICollisionCheck
public function check($data)
{
- if (!isset($data->betriebsmittel_ids, $data->von, $data->bis, $data->kalender_id)) return [];
+ if (!isset($data->betriebsmittel_ids, $data->von, $data->bis)) return [];
if (empty($data->betriebsmittel_ids)) return [];
@@ -31,9 +31,10 @@ class ResourcesCollisionCheck implements ICollisionCheck
$this->_ci->KalenderModel->addJoin('lehre.tbl_betriebsmittel_kalender bk', 'bk.eindeutige_kalender_gruppen_id = tbl_kalender.eindeutige_kalender_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);
+ if (!empty($data->kalender_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_not_in('tbl_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
$this->_ci->KalenderModel->db->where_in('bk.betriebsmittel_id', $data->betriebsmittel_ids);
@@ -66,8 +67,16 @@ class ResourcesCollisionCheck implements ICollisionCheck
$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_not_in('other_kalender.status_kurzbz', ['archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview']);
+
+ $this->_ci->KalenderModel->db->group_start();
+ $where_ids_chunks = array_chunk($kalender_ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
+ }
+ $this->_ci->KalenderModel->db->group_end();
+
$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();
diff --git a/application/libraries/collision/checks/RoomCollisionCheck.php b/application/libraries/collision/checks/RoomCollisionCheck.php
index b59d79028..6e25f3ef0 100644
--- a/application/libraries/collision/checks/RoomCollisionCheck.php
+++ b/application/libraries/collision/checks/RoomCollisionCheck.php
@@ -20,16 +20,17 @@ class RoomCollisionCheck implements ICollisionCheck
public function check($data)
{
- if (!isset($data->ort_kurzbz, $data->von, $data->bis, $data->kalender_id) || isEmptyArray($data->ort_kurzbz)) return [];
+ if (!isset($data->ort_kurzbz, $data->von, $data->bis) || isEmptyArray($data->ort_kurzbz)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
$this->_ci->KalenderModel->addSelect('kalender_id, ort_kurzbz, von, bis');
$this->_ci->KalenderModel->addJoin('lehre.tbl_kalender_ort', 'kalender_id');
- $this->_ci->KalenderModel->db->where('tbl_kalender.kalender_id !=', $data->kalender_id);
+ if (!empty($data->kalender_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_not_in('tbl_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
$this->_ci->KalenderModel->db->where_in('ort_kurzbz', $data->ort_kurzbz);
$result = $this->_ci->KalenderModel->loadWhere(array(
@@ -61,8 +62,16 @@ class RoomCollisionCheck implements ICollisionCheck
$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_not_in('other_kalender.status_kurzbz', array('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview'));
+
+ $this->_ci->KalenderModel->db->group_start();
+ $where_ids_chunks = array_chunk($kalender_ids,25);
+ foreach($where_ids_chunks as $where_ids)
+ {
+ $this->_ci->KalenderModel->db->or_where_in('tbl_kalender.kalender_id', $where_ids);
+ }
+ $this->_ci->KalenderModel->db->group_end();
+
$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();
diff --git a/application/libraries/collision/checks/StudentCollisionCheck.php b/application/libraries/collision/checks/StudentCollisionCheck.php
index 4ffeb071e..bb9ce10db 100644
--- a/application/libraries/collision/checks/StudentCollisionCheck.php
+++ b/application/libraries/collision/checks/StudentCollisionCheck.php
@@ -19,7 +19,8 @@ class StudentCollisionCheck implements ICollisionCheck
public function check($data)
{
- if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
+ if (!isset($data->von, $data->bis)) return [];
+ if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
if ($this->_ci->variablelib->getVar('kollision_student') !== 'true') return [];
@@ -30,7 +31,9 @@ class StudentCollisionCheck implements ICollisionCheck
$dbModel = new DB_Model();
- $qry1 = "
+ if (isset($data->kalender_id))
+ {
+ $qry1 = "
SELECT DISTINCT tbl_benutzergruppe.uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit USING(kalender_id)
@@ -60,13 +63,48 @@ class StudentCollisionCheck implements ICollisionCheck
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
WHERE tbl_kalender.kalender_id = ?
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
+ ";
- ";
+ $qry_1_param = $data->kalender_id;
+ }
+ else
+ {
+ $qry1 = "
+ SELECT DISTINCT tbl_benutzergruppe.uid
+ FROM lehre.tbl_lehreinheit
+ JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
+ JOIN public.tbl_gruppe
+ ON tbl_gruppe.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
+ AND tbl_gruppe.semester = tbl_lehreinheitgruppe.semester
+ AND tbl_gruppe.gruppe_kurzbz = tbl_lehreinheitgruppe.gruppe_kurzbz
+ JOIN public.tbl_benutzergruppe ON tbl_benutzergruppe.gruppe_kurzbz = tbl_gruppe.gruppe_kurzbz
+ AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
+
+ WHERE tbl_lehreinheit.lehreinheit_id = ?
+ AND tbl_benutzergruppe.uid NOT IN ($placeholders)
+
+ UNION ALL
+
+ SELECT DISTINCT tbl_studentlehrverband.student_uid AS uid
+ FROM lehre.tbl_lehreinheit
+ JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
+ JOIN public.tbl_studentlehrverband
+ ON tbl_studentlehrverband.studiengang_kz = tbl_lehreinheitgruppe.studiengang_kz
+ AND tbl_studentlehrverband.semester = tbl_lehreinheitgruppe.semester
+ AND tbl_studentlehrverband.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
+ AND (tbl_lehreinheitgruppe.verband = tbl_studentlehrverband.verband OR tbl_lehreinheitgruppe.verband IS NULL OR btrim(tbl_lehreinheitgruppe.verband::text) = '' OR tbl_studentlehrverband.verband IS NULL)
+ AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
+ WHERE tbl_lehreinheit.lehreinheit_id = ?
+ AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
+ ";
+
+ $qry_1_param = $data->lehreinheit_id;
+ }
$result1 = $dbModel->execReadOnlyQuery($qry1, array_merge(
- [$data->kalender_id],
+ [$qry_1_param],
$kollisionsfreie_user,
- [$data->kalender_id],
+ [$qry_1_param],
$kollisionsfreie_user
));
@@ -74,6 +112,9 @@ class StudentCollisionCheck implements ICollisionCheck
$curUids = array_flip(array_column(getData($result1), 'uid'));
+ $exclude_kalender = isset($data->kalender_id) ? "AND tbl_kalender.kalender_id != ?" : "";
+ $exclude_kalender_param = isset($data->kalender_id) ? [$data->kalender_id] : [];
+
$qry2 = "
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_benutzergruppe.uid
FROM lehre.tbl_kalender
@@ -88,8 +129,8 @@ class StudentCollisionCheck implements ICollisionCheck
AND tbl_benutzergruppe.studiensemester_kurzbz = tbl_lehreinheit.studiensemester_kurzbz
WHERE tbl_kalender.von < ?
AND tbl_kalender.bis > ?
- AND tbl_kalender.kalender_id != ?
- AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ $exclude_kalender
+ AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND tbl_benutzergruppe.uid NOT IN ($placeholders)
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
@@ -97,7 +138,7 @@ class StudentCollisionCheck implements ICollisionCheck
)
UNION ALL
-
+
SELECT DISTINCT tbl_kalender.kalender_id, tbl_kalender.von, tbl_kalender.bis, tbl_studentlehrverband.student_uid AS uid
FROM lehre.tbl_kalender
JOIN lehre.tbl_kalender_lehreinheit ON tbl_kalender_lehreinheit.kalender_id = tbl_kalender.kalender_id
@@ -111,8 +152,8 @@ class StudentCollisionCheck implements ICollisionCheck
AND (tbl_lehreinheitgruppe.gruppe = tbl_studentlehrverband.gruppe OR tbl_lehreinheitgruppe.gruppe IS NULL OR btrim(tbl_lehreinheitgruppe.gruppe::text) = '' OR tbl_studentlehrverband.gruppe IS NULL)
WHERE tbl_kalender.von < ?
AND tbl_kalender.bis > ?
- AND tbl_kalender.kalender_id != ?
- AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ $exclude_kalender
+ AND tbl_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND tbl_studentlehrverband.student_uid NOT IN ($placeholders)
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
@@ -121,10 +162,8 @@ class StudentCollisionCheck implements ICollisionCheck
";
$result2 = $dbModel->execReadOnlyQuery($qry2, array_merge(
- [$data->bis, $data->von, $data->kalender_id],
- $kollisionsfreie_user,
- [$data->bis, $data->von, $data->kalender_id],
- $kollisionsfreie_user
+ [$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user,
+ [$data->bis, $data->von], $exclude_kalender_param, $kollisionsfreie_user
));
if (isError($result2) || !hasData($result2)) return [];
@@ -175,7 +214,7 @@ class StudentCollisionCheck implements ICollisionCheck
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < current_kalender.bis
AND other_kalender.bis > current_kalender.von
- AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
@@ -213,7 +252,7 @@ class StudentCollisionCheck implements ICollisionCheck
ON other_kalender.kalender_id != current_kalender.kalender_id
AND other_kalender.von < current_kalender.bis
AND other_kalender.bis > current_kalender.von
- AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND NOT EXISTS (
SELECT 1 FROM lehre.tbl_kalender vorgaenger
WHERE vorgaenger.vorgaenger_kalender_id = other_kalender.kalender_id
diff --git a/application/libraries/collision/checks/VerbandCollisionCheck.php b/application/libraries/collision/checks/VerbandCollisionCheck.php
index 40baf38a2..98ae3efee 100644
--- a/application/libraries/collision/checks/VerbandCollisionCheck.php
+++ b/application/libraries/collision/checks/VerbandCollisionCheck.php
@@ -21,18 +21,58 @@ class VerbandCollisionCheck implements ICollisionCheck
public function check($data)
{
- if (!isset($data->von, $data->bis, $data->kalender_id)) return [];
+ if (!isset($data->von, $data->bis)) return [];
+ if (!isset($data->kalender_id) && !isset($data->lehreinheit_id)) return [];
if ($this->_ci->variablelib->getVar('ignore_kollision') === 'true') return [];
$kollision_student = $this->_ci->variablelib->getVar('kollision_student') === 'false';
$kollision_reservierung = $this->_ci->variablelib->getVar('ignore_reservierung') === 'false';
+ if (!isset($data->kalender_id)) $kollision_reservierung = false;
+
if (!$kollision_student && !$kollision_reservierung) return [];
$dbModel = new DB_Model();
$collisions = [];
+ $group_matching_qry = "
+ (
+ (
+ current_lehreinheitguppe.gruppe_kurzbz IS NULL
+ AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
+ AND (
+ current_lehreinheitguppe.verband IS NULL
+ OR (
+ current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
+ AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
+ )
+ )
+ )
+ OR
+ (
+ current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
+ AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
+ AND current_gruppe.direktinskription IS NOT TRUE
+ AND other_gruppe.direktinskription IS NOT TRUE
+ )
+ OR
+ (
+ (
+ current_lehreinheitguppe.gruppe_kurzbz IS NULL
+ AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
+ AND other_gruppe.direktinskription IS NOT TRUE
+ )
+ OR
+ (
+ current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
+ AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
+ AND current_gruppe.direktinskription IS NOT TRUE
+ )
+ )
+ )
+ ";
+
if ($kollision_student)
{
$union_event = "";
@@ -47,100 +87,111 @@ class VerbandCollisionCheck implements ICollisionCheck
";
}
- $sql_gruppen = "
- SELECT
- other_kalender.von,
- other_kalender.bis,
- COALESCE(
- other_lehreinheitguppe.gruppe_kurzbz,
- UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
- COALESCE(other_lehreinheitguppe.verband::text, '') ||
- COALESCE(other_lehreinheitguppe.gruppe::text, '')
- ) AS gruppenname
- FROM lehre.tbl_kalender current_kalender
+ $other_lehreinheitgruppe_subquery = "
+ SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
+ tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
+ FROM lehre.tbl_kalender_lehreinheit
+ JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
+ JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
+ ". $union_event ."
+ ";
- JOIN (
- SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
- tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
- FROM lehre.tbl_kalender_lehreinheit
- JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
- JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
- ". $union_event ."
- ) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
-
- LEFT JOIN public.tbl_gruppe current_gruppe
- ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
-
- JOIN lehre.tbl_kalender other_kalender
- ON other_kalender.kalender_id != current_kalender.kalender_id
- AND other_kalender.von < ?
- AND other_kalender.bis > ?
-
- JOIN (
- SELECT tbl_lehreinheitgruppe.studiengang_kz, tbl_lehreinheitgruppe.semester, tbl_lehreinheitgruppe.verband, tbl_lehreinheitgruppe.gruppe,
- tbl_lehreinheitgruppe.gruppe_kurzbz, tbl_kalender_lehreinheit.kalender_id
- FROM lehre.tbl_kalender_lehreinheit
- JOIN lehre.tbl_lehreinheit ON tbl_lehreinheit.lehreinheit_id = tbl_kalender_lehreinheit.lehreinheit_id
- JOIN lehre.tbl_lehreinheitgruppe ON tbl_lehreinheitgruppe.lehreinheit_id = tbl_lehreinheit.lehreinheit_id
- ". $union_event ."
- ) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
-
- LEFT JOIN public.tbl_gruppe other_gruppe
- ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
-
- LEFT JOIN public.tbl_studiengang stg
- ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
-
- WHERE current_kalender.kalender_id = ?
- AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
- AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
- AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
- AND (
- (
- current_lehreinheitguppe.gruppe_kurzbz IS NULL
- AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
- AND (
- current_lehreinheitguppe.verband IS NULL
- OR (
- current_lehreinheitguppe.verband = other_lehreinheitguppe.verband
- AND (current_lehreinheitguppe.gruppe IS NULL OR other_lehreinheitguppe.gruppe IS NULL OR current_lehreinheitguppe.gruppe = other_lehreinheitguppe.gruppe)
- )
- )
+ if (isset($data->kalender_id))
+ {
+ $sql_gruppen = "
+ SELECT
+ other_kalender.von,
+ other_kalender.bis,
+ COALESCE(
+ other_lehreinheitguppe.gruppe_kurzbz,
+ UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
+ COALESCE(other_lehreinheitguppe.verband::text, '') ||
+ COALESCE(other_lehreinheitguppe.gruppe::text, '')
+ ) AS gruppenname
+ FROM lehre.tbl_kalender current_kalender
+
+ JOIN (
+ ". $other_lehreinheitgruppe_subquery ."
+ ) current_lehreinheitguppe ON current_lehreinheitguppe.kalender_id = current_kalender.kalender_id
+
+ LEFT JOIN public.tbl_gruppe current_gruppe
+ ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
+
+ JOIN lehre.tbl_kalender other_kalender
+ ON other_kalender.kalender_id != current_kalender.kalender_id
+ AND other_kalender.von < ?
+ AND other_kalender.bis > ?
+
+ JOIN (
+ ". $other_lehreinheitgruppe_subquery ."
+ ) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
+
+ LEFT JOIN public.tbl_gruppe other_gruppe
+ ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
+
+ LEFT JOIN public.tbl_studiengang stg
+ ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
+
+ WHERE current_kalender.kalender_id = ?
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
+ AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
+ AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
+ AND ". $group_matching_qry ."
+ AND other_kalender.kalender_id NOT IN (
+ SELECT vorgaenger_kalender_id
+ FROM lehre.tbl_kalender
+ WHERE vorgaenger_kalender_id IS NOT NULL
)
- OR
- (
- current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
- AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
- AND current_gruppe.direktinskription IS NOT TRUE
- AND other_gruppe.direktinskription IS NOT TRUE
- )
- OR
- (
- (
- current_lehreinheitguppe.gruppe_kurzbz IS NULL
- AND other_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
- AND other_gruppe.direktinskription IS NOT TRUE
- )
- OR
- (
- current_lehreinheitguppe.gruppe_kurzbz IS NOT NULL
- AND other_lehreinheitguppe.gruppe_kurzbz IS NULL
- AND current_gruppe.direktinskription IS NOT TRUE
- )
- )
- )
- AND other_kalender.kalender_id NOT IN (
- SELECT vorgaenger_kalender_id
- FROM lehre.tbl_kalender
- WHERE vorgaenger_kalender_id IS NOT NULL
- )
- ";
+ ";
- $result = $dbModel->execReadOnlyQuery($sql_gruppen, [
- $data->bis,
- $data->von,
- $data->kalender_id,
- ]);
+ $params = [$data->bis, $data->von, $data->kalender_id];
+ }
+ else
+ {
+ $sql_gruppen = "
+ SELECT
+ other_kalender.von,
+ other_kalender.bis,
+ COALESCE(
+ other_lehreinheitguppe.gruppe_kurzbz,
+ UPPER(stg.typ::text || stg.kurzbz::text) || '-' || other_lehreinheitguppe.semester ||
+ COALESCE(other_lehreinheitguppe.verband::text, '') ||
+ COALESCE(other_lehreinheitguppe.gruppe::text, '')
+ ) AS gruppenname
+ FROM lehre.tbl_lehreinheitgruppe current_lehreinheitguppe
+ LEFT JOIN public.tbl_gruppe current_gruppe
+ ON current_gruppe.gruppe_kurzbz = current_lehreinheitguppe.gruppe_kurzbz
+
+ JOIN lehre.tbl_kalender other_kalender
+ ON other_kalender.von < ?
+ AND other_kalender.bis > ?
+
+ JOIN (
+ ". $other_lehreinheitgruppe_subquery ."
+ ) other_lehreinheitguppe ON other_lehreinheitguppe.kalender_id = other_kalender.kalender_id
+
+ LEFT JOIN public.tbl_gruppe other_gruppe
+ ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
+
+ LEFT JOIN public.tbl_studiengang stg
+ ON stg.studiengang_kz = other_lehreinheitguppe.studiengang_kz
+
+ WHERE current_lehreinheitguppe.lehreinheit_id = ?
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
+ AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
+ AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
+ AND ". $group_matching_qry ."
+ AND other_kalender.kalender_id NOT IN (
+ SELECT vorgaenger_kalender_id
+ FROM lehre.tbl_kalender
+ WHERE vorgaenger_kalender_id IS NOT NULL
+ )
+ ";
+
+ $params = [$data->bis, $data->von, $data->lehreinheit_id];
+ }
+
+ $result = $dbModel->execReadOnlyQuery($sql_gruppen, $params);
if (!isError($result) && hasData($result))
{
@@ -187,7 +238,7 @@ class VerbandCollisionCheck implements ICollisionCheck
WHERE current_event_teilnehmer.kalender_id = ?
AND current_event_teilnehmer.rolle_kurzbz = 'teilnehmer'
- AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_event_teilnehmer.studiengang_kz = other_event_teilnehmer.studiengang_kz
AND current_event_teilnehmer.semester = other_event_teilnehmer.semester
AND (
@@ -301,7 +352,7 @@ class VerbandCollisionCheck implements ICollisionCheck
ON other_gruppe.gruppe_kurzbz = other_lehreinheitguppe.gruppe_kurzbz
WHERE current_kalender.kalender_id IN ({$placeholders})
- AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete')
+ AND other_kalender.status_kurzbz NOT IN ('archived', 'deleted', 'to_delete', 'to_delete_live', 'to_delete_preview')
AND current_lehreinheitguppe.studiengang_kz = other_lehreinheitguppe.studiengang_kz
AND current_lehreinheitguppe.semester = other_lehreinheitguppe.semester
AND (
diff --git a/application/models/ressource/Kalendersyncstatus_model.php b/application/models/ressource/Kalendersyncstatus_model.php
new file mode 100644
index 000000000..f1cd8aedf
--- /dev/null
+++ b/application/models/ressource/Kalendersyncstatus_model.php
@@ -0,0 +1,14 @@
+dbTable = 'lehre.tbl_kalender_syncstatus';
+ $this->pk = 'kalender_syncstatus_id';
+ }
+}
diff --git a/application/views/Tempus.php b/application/views/Tempus.php
index 4469d83e1..db49c57db 100644
--- a/application/views/Tempus.php
+++ b/application/views/Tempus.php
@@ -7,12 +7,14 @@
'vue3' => true,
'primevue3' => true,
'tabulator5' => true,
+ 'filtercomponent' => true,
+ 'navigationcomponent' => true,
'vuedatepicker11' => true,
'tags' => true,
'phrases' => array(
'global',
'ui',
- 'notiz',
+ 'lehre'
),
'customCSSs' => [
'public/css/components/vue-datepicker.css',
diff --git a/public/css/Studentenverwaltung.css b/public/css/Studentenverwaltung.css
index 870a58bdf..470ea03e9 100644
--- a/public/css/Studentenverwaltung.css
+++ b/public/css/Studentenverwaltung.css
@@ -8,6 +8,8 @@
@import './components/Notiz.css';
@import './components/Messages.css';
@import './components/AppMenu.css';
+@import './components/horizontalsplit.css';
+
html {
font-size: .875em;
diff --git a/public/css/Tempus.css b/public/css/Tempus.css
index 3e32789e1..6ca71025b 100644
--- a/public/css/Tempus.css
+++ b/public/css/Tempus.css
@@ -110,15 +110,23 @@ body {
background-color: var(--event-bg);
}
-.parkingevent {
+.course-parker {
+ position: relative;
border: 1px dashed !important;
- border-color: #AAAAAA;
padding: 0.5rem;
- margin-bottom: 0.5rem;
- margin-left: 0.5rem;
- margin-right: 0.5rem;
+ margin: 0.5rem;
+ background-color: var(--event-bg);
+ color: var(--event-color, var(--fhc-calendar-color-event, #000));
}
+.unpark-btn {
+ position: absolute;
+ top: 2px;
+ right: 2px;
+ padding: 0 4px;
+ border: none;
+ background: transparent;
+}
:root{
--fhc-calendar-pane-height: calc(100vh - 120px);
}
@@ -171,6 +179,21 @@ body {
}
+.bg-raumvorschlag-slot {
+ opacity: .70;
+}
+
+.bg-raumvorschlag-slot.rating-good {
+ background-color: var(--bs-success);
+}
+.bg-raumvorschlag-slot.rating-mid {
+ background-color: var(--bs-warning);
+}
+.bg-raumvorschlag-slot.rating-bad {
+ background-color: var(--bs-danger);
+}
+
+
.wish-w--2 {
background-color: #FF2200;
}
@@ -185,3 +208,9 @@ body {
}
+.room-option {
+ display: grid;
+ grid-template-columns: 20px minmax(80px, 110px) minmax(100px, 1fr) auto 20px 50px;
+ align-items: center;
+ width: 100%;
+}
diff --git a/public/css/components/calendar/frame.css b/public/css/components/calendar/frame.css
index d17cc06b4..68b907179 100644
--- a/public/css/components/calendar/frame.css
+++ b/public/css/components/calendar/frame.css
@@ -68,9 +68,16 @@
/* Grid */
.fhc-calendar-base-grid {
--fhc-calendar-axis-collapsible: .2fr;
+ --fhc-calendar-axis-collapsible-manual: .1fr;
+
background-color: var(--fhc-calendar-bg-gap);
grid-gap: var(--fhc-calendar-gap-header, calc(var(--fhc-calendar-gap, 1px) * 2));
}
+
+.fhc-calendar-base-grid-line-collapsed {
+ overflow: hidden;
+}
+
.fhc-calendar-base-grid .grid-header {
background-color: var(--fhc-calendar-bg-header-gap, var(--fhc-calendar-bg-gap));
}
diff --git a/public/js/api/factory/tempus/coursepicker.js b/public/js/api/factory/tempus/coursepicker.js
index 92ff4fa6b..80b201a00 100644
--- a/public/js/api/factory/tempus/coursepicker.js
+++ b/public/js/api/factory/tempus/coursepicker.js
@@ -1,16 +1,9 @@
export default {
- search(query) {
- return {
- method: 'get',
- url: 'api/frontend/v1/tempus/coursepicker/search',
- params: { query }
- };
- },
- getByStg(studiengaenge, studiensemester_kurzbz) {
+ getCourses(filter, studiensemester_kurzbz) {
return {
method: 'post',
- url: 'api/frontend/v1/tempus/coursepicker/getByStg',
- params: { studiengaenge, studiensemester_kurzbz }
+ url: 'api/frontend/v1/tempus/coursepicker/getCourses',
+ params: { ...filter, studiensemester_kurzbz }
};
},
diff --git a/public/js/api/factory/tempus/kalender.js b/public/js/api/factory/tempus/kalender.js
index eb89542f6..c12bedd2f 100644
--- a/public/js/api/factory/tempus/kalender.js
+++ b/public/js/api/factory/tempus/kalender.js
@@ -8,6 +8,14 @@ export default {
params: { ...filter, start_date, end_date }
};
},
+ getRaumvorschlagSlots(lehreinheit_id, start_date, end_date)
+ {
+ return {
+ method: 'get',
+ url: '/api/frontend/v1/tempus/Kalender/getRaumvorschlagSlots',
+ params: { lehreinheit_id, start_date, end_date }
+ };
+ },
getPlanLecturer(start_date, end_date)
{
return {
diff --git a/public/js/api/factory/tempus/reservierung.js b/public/js/api/factory/tempus/reservierung.js
index 7f91a6817..d0aa76bb8 100644
--- a/public/js/api/factory/tempus/reservierung.js
+++ b/public/js/api/factory/tempus/reservierung.js
@@ -48,11 +48,11 @@ export default {
url: '/api/frontend/v1/tempus/Reservierung/getRollen',
};
},
- addReservierung(titel, beschreibung, ort_kurzbz, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups) {
+ addReservierung(titel, beschreibung, orte, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups) {
return {
method: 'post',
url: '/api/frontend/v1/tempus/Reservierung/addReservierung',
- params: { titel, beschreibung, ort_kurzbz, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups}
+ params: { titel, beschreibung, orte, start_date, end_date, teilnehmer, specialFinalGroups, specialGroups, groups}
};
},
diff --git a/public/js/api/factory/tempus/sync.js b/public/js/api/factory/tempus/sync.js
new file mode 100644
index 000000000..0dd8d9eb5
--- /dev/null
+++ b/public/js/api/factory/tempus/sync.js
@@ -0,0 +1,83 @@
+/**
+ * Copyright (C) 2026 fhcomplete.org
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+export default {
+ getSyncs(studiensemester_kurzbz) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/tempus/KalenderSync/getSyncs',
+ params: { studiensemester_kurzbz }
+ };
+ },
+ loadSync(kalender_syncstatus_id) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/tempus/KalenderSync/loadSync',
+ params: { kalender_syncstatus_id }
+ };
+ },
+ getSyncStatus() {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/tempus/KalenderSync/getSyncStatus',
+ };
+ },
+ add(formData) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/tempus/KalenderSync/add',
+ params: { formData }
+ };
+ },
+ delete(kalender_syncstatus_id) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/tempus/KalenderSync/delete',
+ params: { kalender_syncstatus_id }
+ };
+ },
+ start(formData) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/tempus/KalenderSync/start',
+ params: { formData }
+ };
+ },
+ updateSync(formData) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/tempus/KalenderSync/updateSync',
+ params: { formData }
+ };
+ },
+ getStudienplan(oe_kurzbz, studiensemester_kurzbz, ausbildungssemester) {
+ return {
+ method: 'get',
+ url: 'api/frontend/v1/tempus/KalenderSync/getStudienplan',
+ params: { oe_kurzbz, studiensemester_kurzbz, ausbildungssemester }
+ };
+ },
+
+ getMaxSemester(studiengang_kzs) {
+ return {
+ method: 'post',
+ url: 'api/frontend/v1/stv/status/getMaxSemester/',
+ params: { studiengang_kzs }
+ };
+ },
+
+};
\ No newline at end of file
diff --git a/public/js/apps/Tempus.js b/public/js/apps/Tempus.js
index 160aa3383..b1159da02 100644
--- a/public/js/apps/Tempus.js
+++ b/public/js/apps/Tempus.js
@@ -16,6 +16,7 @@
*/
import FhcTempus from "../components/Tempus/Tempus.js";
+import FhcTempusSync from "../components/Tempus/TempusSync.js";
import Phrasen from "../plugins/Phrasen.js";
import {capitalize} from "../helpers/StringHelpers.js";
@@ -27,6 +28,7 @@ const router = VueRouter.createRouter({
history: VueRouter.createWebHistory(),
routes: [
{ path: `/${ciPath}/Tempus`, component: FhcTempus },
+ { path: `/${ciPath}/Tempus/sync`, component: FhcTempusSync },
]
});
diff --git a/public/js/components/Calendar/Base.js b/public/js/components/Calendar/Base.js
index 85c64ac18..360c9afa2 100644
--- a/public/js/components/Calendar/Base.js
+++ b/public/js/components/Calendar/Base.js
@@ -137,12 +137,14 @@ export default {
"update:date",
"update:mode",
"update:range",
+ "update:date-range",
"drop"
],
data() {
return {
internalView: null,
internalDate: null,
+ pickedRangeEnd: null,
modalEvent: null
};
},
@@ -272,6 +274,10 @@ export default {
}
},
+ handleDateRange({ start, end }) {
+ this.pickedRangeEnd = end;
+ this.$emit('update:date-range', { start, end });
+ },
showEventModal(eventObj) {
this.modalEvent = eventObj;
this.$refs.modal.show();
@@ -300,6 +306,7 @@ export default {
class="card-header"
v-model:date="cDate"
v-model:mode="cMode"
+ @update:date-range="handleDateRange"
@prev="clickPrev"
@next="clickNext"
@click:mode="$emit('click:mode', $event)"
@@ -316,6 +323,7 @@ export default {
:is="modes ? modes[cMode] : null || 'div'"
ref="mode"
v-model:current-date="cDate"
+ :range-end="pickedRangeEnd"
@update:range="$emit('update:range', $event)"
@request-modal-open="showEventModal"
@request-modal-close="hideEventModal"
diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js
index d63a8d7e6..df322c151 100644
--- a/public/js/components/Calendar/Base/Grid.js
+++ b/public/js/components/Calendar/Base/Grid.js
@@ -61,7 +61,11 @@ export default {
flipAxis: Boolean,
allDayEvents: Boolean,
axisMainCollapsible: Boolean,
- snapToGrid: Boolean
+ snapToGrid: Boolean,
+ dayVisibility: {
+ type: Array,
+ default: null
+ }
},
data() {
return {
@@ -160,7 +164,17 @@ export default {
hasValidEvents() {
return this.events.find(e => e.length);
},
- styleGridCols() {
+ styleGridCols()
+ {
+ if (this.dayVisibility)
+ {
+ let anyVisible = this.dayVisibility.some(day => day);
+ if (anyVisible)
+ {
+ return this.axisMain.map((day, i) => this.isDayCollapsed(i) ? 'var(--fhc-calendar-axis-collapsible-manual, 0.1fr)' : '1fr').join(' ');
+ }
+ }
+
let cols = 'repeat(' + this.axisMain.length + ', 1fr)';
if (this.axisMainCollapsible) {
if (this.hasValidEvents)
@@ -479,6 +493,16 @@ export default {
}
});
},
+ isDayCollapsed(index)
+ {
+ if (this.dayVisibility)
+ {
+ let anyVisible = this.dayVisibility.some(day => day);
+ if (anyVisible)
+ return !this.dayVisibility[index];
+ }
+ return this.axisMainCollapsible && this.hasValidEvents && !this.events[index].length;
+ }
},
setup()
{
@@ -504,7 +528,7 @@ export default {
v-for="(date, index) in axisMain"
:key="index"
class="main-header"
- :class="{'collapsed-header': axisMainCollapsible && hasValidEvents && !events[index].length}"
+ :class="{'collapsed-header': isDayCollapsed(index)}"
:style="'grid-' + axisCol + ':' + (2+index)"
>
@@ -592,6 +616,7 @@ export default {
:date="date"
:events="eventsNormal[index]"
:backgrounds="backgrounds[index]"
+ :class="{ 'fhc-calendar-base-grid-line-collapsed': isDayCollapsed(index) }"
style="position:relative"
@resize-start="handleResizeStart"
:style="'grid-' + axisRow + ':1/-1;grid-' + axisCol + ':' + (1+index)"
diff --git a/public/js/components/Calendar/Base/Grid/Line/EventCard.js b/public/js/components/Calendar/Base/Grid/Line/EventCard.js
index 3851fea14..2a78ed348 100644
--- a/public/js/components/Calendar/Base/Grid/Line/EventCard.js
+++ b/public/js/components/Calendar/Base/Grid/Line/EventCard.js
@@ -9,6 +9,10 @@ export default {
event: { type: Object, required: true },
parked: Boolean
},
+ emits: [
+ 'select-kw',
+ 'unpark'
+ ],
computed: {
dragKalenderCollection() {
return this.event
@@ -16,21 +20,48 @@ export default {
topicString() {
return Array.isArray(this.event.orig.topic) ? this.event.orig.topic.join(', ') : this.event.orig.topic;
},
+ datum() {
+ return luxon.DateTime.fromISO(this.event.orig.datum).toFormat('dd.MM.yyyy')
+ },
+ kw() {
+ return luxon.DateTime.fromISO(this.event.orig.datum).startOf('week', { useLocaleWeeks: true }).localWeekNumber
+ },
},
+ methods: {
+ eventStyle(event) {
+ if (!event.farbe)
+ return undefined;
+ return '--event-bg:#' + event.farbe;
+ },
+ jumpToKw()
+ {
+ this.$emit('select-kw', this.kw);
+ },
+ unpark(evt)
+ {
+ this.$emit('unpark', this.event);
+ }
+ },
+
template: `
+
{{ topicString || event.orig.titel || event.orig.lehrfach }}
- {{ event.orig.datum }} {{ event.orig.beginn }}–{{ event.orig.ende }}
- · {{ event.orig.ort_kurzbz }}
+ KW: {{ kw }} {{ datum }}
+
+
+ {{ event.orig.beginn }}–{{ event.orig.ende }}
`
-};
+};
\ No newline at end of file
diff --git a/public/js/components/Calendar/Base/Header.js b/public/js/components/Calendar/Base/Header.js
index 39eea114b..7c3fcafcb 100644
--- a/public/js/components/Calendar/Base/Header.js
+++ b/public/js/components/Calendar/Base/Header.js
@@ -32,7 +32,8 @@ export default {
"prev",
"click:mode",
"update:date",
- "update:mode"
+ "update:mode",
+ "update:date-range"
],
data() {
return {
@@ -109,6 +110,7 @@ export default {
class="btn btn-outline-secondary border-0"
@click="$emit('prev')"
:disabled="open"
+ v-if="mode !== 'tableList'"
>
@@ -116,6 +118,7 @@ export default {
:mode="mode"
:date="date"
@update:date="$emit('update:date', $event)"
+ @update:date-range="$emit('update:date-range', $event)"
@open="open = true"
@closed="open = false"
:list-length="modeOptions.length"
@@ -124,6 +127,7 @@ export default {
class="btn btn-outline-secondary border-0"
@click="$emit('next')"
:disabled="open"
+ v-if="mode !== 'tableList'"
>
@@ -131,4 +135,4 @@ export default {
`
-}
+}
\ No newline at end of file
diff --git a/public/js/components/Calendar/Base/Header/Datepicker.js b/public/js/components/Calendar/Base/Header/Datepicker.js
index 98a26945b..3e2ec8327 100644
--- a/public/js/components/Calendar/Base/Header/Datepicker.js
+++ b/public/js/components/Calendar/Base/Header/Datepicker.js
@@ -24,8 +24,14 @@ export default {
}
},
emits: [
- "update:date"
+ "update:date",
+ "update:date-range"
],
+ data() {
+ return {
+ rangeEnd: null
+ };
+ },
computed: {
convertedDate() {
// convert to target TZ then strip TZ Information
@@ -34,34 +40,37 @@ export default {
},
current() {
switch (this.mode) {
- case "month":
- return {month: this.convertedDate.month-1, year: this.convertedDate.year};
- case "list":
- return [this.convertedDate.startOf('day').ts, this.convertedDate.startOf('day').plus({ days: this.listLength }).ts - 1];
- case "week":
- case "tableList":
- return [this.convertedDate.startOf('week', { useLocaleWeeks: true }).ts, this.convertedDate.endOf('week', { useLocaleWeeks: true }).ts];
- case "day":
- return this.convertedDate;
- default:
- return null;
+ case "month":
+ return {month: this.convertedDate.month-1, year: this.convertedDate.year};
+ case "list":
+ return [this.convertedDate.startOf('day').ts, this.convertedDate.startOf('day').plus({ days: this.listLength }).ts - 1];
+ case "week":
+ return [this.convertedDate.startOf('week', { useLocaleWeeks: true }).ts, this.convertedDate.endOf('week', { useLocaleWeeks: true }).ts];
+ case "tableList":
+ return [this.convertedDate.startOf('day').ts, (this.rangeEnd || this.convertedDate).endOf('day').ts];
+ case "day":
+ return this.convertedDate;
+ default:
+ return null;
}
},
title() {
switch (this.mode) {
- case "month":
- return this.date.toLocaleString({ month: 'long', year: 'numeric' });
- case "week":
- case "tableList":
- var year = this.date.localWeekYear;
- var week = this.date.toFormat('nn');
- return this.$p.t('calendar/year_kw', { year, week });
- case "list":
- return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + this.date.plus({ days: this.listLength - 1 }).toLocaleString(luxon.DateTime.DATE_FULL);
- case "day":
- return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
- default:
- return 'View not Supported';
+ case "month":
+ return this.date.toLocaleString({ month: 'long', year: 'numeric' });
+ case "week":
+ var year = this.date.localWeekYear;
+ var week = this.date.toFormat('nn');
+ return this.$p.t('calendar/year_kw', { year, week });
+ case "tableList":
+ const end = this.rangeEnd ? this.rangeEnd.setZone(this.timezone, { keepLocalTime: true }) : this.date;
+ return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + end.toLocaleString(luxon.DateTime.DATE_FULL);
+ case "list":
+ return this.date.toLocaleString(luxon.DateTime.DATE_FULL) + '-' + this.date.plus({ days: this.listLength - 1 }).toLocaleString(luxon.DateTime.DATE_FULL);
+ case "day":
+ return this.date.toLocaleString(luxon.DateTime.DATE_FULL);
+ default:
+ return 'View not Supported';
}
},
weekStart() {
@@ -72,20 +81,28 @@ export default {
update(value) {
let date;
switch (this.mode) {
- case "month":
- value.month++;
- date = luxon.DateTime.fromObject(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
- break;
- case "list":
- case "week":
- case "tableList":
- date = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
- break;
- case "day":
- date = luxon.DateTime.fromJSDate(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
- break;
- default:
- return; // Don't update if the value is invalid!
+ case "month":
+ value.month++;
+ date = luxon.DateTime.fromObject(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
+ break;
+ case "list":
+ case "week":
+ date = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
+ break;
+ case "tableList":
+ if (!Array.isArray(value) || !value[0] || !value[1])
+ return;
+ this.rangeEnd = luxon.DateTime.fromJSDate(value[1]);
+ const start = luxon.DateTime.fromJSDate(value[0]).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
+ const end = this.rangeEnd.setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
+ this.$emit('update:date', start);
+ this.$emit('update:date-range', { start, end });
+ return;
+ case "day":
+ date = luxon.DateTime.fromJSDate(value).setZone(this.timezone, { keepLocalTime: true }).setLocale(this.locale);
+ break;
+ default:
+ return; // Don't update if the value is invalid!
}
this.$emit("update:date", date);
},
@@ -99,8 +116,8 @@ export default {
@update:model-value="update"
:format="() => title"
:month-picker="mode == 'month'"
- :week-picker="mode == 'week' || mode == 'tableList'"
- :range="mode == 'list' ? { autoRange: listLength - 1 } : false"
+ :week-picker="mode == 'week'"
+ :range="mode == 'list' ? { autoRange: listLength - 1 } : (mode == 'tableList' ? { partialRange: false } : false)"
:text-input="mode == 'day'"
:week-start="weekStart"
:week-numbers="{ type: weekNumbers }"
diff --git a/public/js/components/Calendar/Mode/Table.js b/public/js/components/Calendar/Mode/Table.js
index 3676114af..529927d5f 100644
--- a/public/js/components/Calendar/Mode/Table.js
+++ b/public/js/components/Calendar/Mode/Table.js
@@ -1,109 +1,57 @@
-import BaseSlider from '../Base/Slider.js';
import TableView from './Table/View.js';
export default {
name: "ModeTable",
components: {
- BaseSlider,
TableView
},
props: {
currentDate: {
type: luxon.DateTime,
required: true
+ },
+ rangeEnd: {
+ type: luxon.DateTime,
+ default: null
}
},
emits: [
- "update:currentDate",
"update:range",
- "click",
- "requestModalOpen"
],
data() {
return {
focusDate: this.currentDate,
- rangeOffset: 0
+ focusEnd: this.rangeEnd || this.currentDate
};
},
computed: {
range() {
- let first = this.focusDate.startOf('week', { useLocaleWeeks: true });
- let last = this.focusDate.endOf('week', { useLocaleWeeks: true });
-
- if (this.rangeOffset != 0) {
- if (this.rangeOffset < 0) {
- first = first.plus({ weeks: this.rangeOffset });
- } else {
- last = last.plus({ weeks: this.rangeOffset });
- }
- }
-
- return luxon.Interval.fromDateTimes(first, last);
+ return luxon.Interval.fromDateTimes(this.focusDate.startOf('day'), this.focusEnd.endOf('day'));
}
},
watch: {
- currentDate() {
- if (this.currentDate.locale != this.focusDate.locale) {
- this.focusDate = this.currentDate;
- this.$emit('update:range', this.range);
- } else {
- this.rangeOffset = this.currentDate.startOf('week', { useLocaleWeeks: true }).diff(this.focusDate.startOf('week', { useLocaleWeeks: true }), 'weeks').weeks;
- if (this.rangeOffset) {
- this.$emit('update:range', this.range);
- this.$refs.slider.slidePages(this.rangeOffset).then(this.updatePage);
- }
- }
+ currentDate(newDate) {
+ this.focusDate = newDate;
+ if (!this.rangeEnd)
+ this.focusEnd = newDate;
+ this.$emit('update:range', this.range);
+ },
+ rangeEnd(newEnd) {
+ this.focusEnd = newEnd || this.focusDate;
+ this.$emit('update:range', this.range);
}
},
methods: {
- prevPage() {
- this.rangeOffset = this.$refs.slider.target - 1;
- this.$emit('update:range', this.range);
- this.$refs.slider.prevPage().then(this.updatePage);
- },
- nextPage() {
- this.rangeOffset = this.$refs.slider.target + 1;
- this.$emit('update:range', this.range);
- this.$refs.slider.nextPage().then(this.updatePage);
- },
- updatePage(weeks) {
- const newFocusDate = this.focusDate.plus({ weeks });
- this.focusDate = newFocusDate;
- this.rangeOffset = 0;
- this.$emit('update:currentDate', this.focusDate);
- this.$emit('update:range', this.range);
- },
- viewAttrs(weeks) {
- const day = this.focusDate.plus({ weeks });
- return { ...this.$attrs, day };
- },
- handleClickDefaults(evt) {
- switch (evt.detail.source) {
- case 'day':
- // default: Set current-date
- this.$emit('update:currentDate', evt.detail.value);
- break;
- case 'event':
- // default: Request Modal
- this.$emit('requestModalOpen', { event: evt.detail.value });
- break;
- }
- }
},
mounted() {
this.$emit('update:range', this.range);
},
template: `
-
-
-
-
-
-
+
`
-}
+}
\ No newline at end of file
diff --git a/public/js/components/Calendar/Mode/Table/View.js b/public/js/components/Calendar/Mode/Table/View.js
index cee1bfe7d..6f3553f7b 100644
--- a/public/js/components/Calendar/Mode/Table/View.js
+++ b/public/js/components/Calendar/Mode/Table/View.js
@@ -1,8 +1,6 @@
import {CoreFilterCmpt} from "../../../../components/filter/Filter.js";
import BsModal from '../../../Bootstrap/Modal.js';
import FormInput from "../../../Form/Input.js";
-import ApiDetails from "../../../../api/lehrveranstaltung/details.js";
-
export default {
name: "TableView",
@@ -20,6 +18,10 @@ export default {
day: {
type: luxon.DateTime,
required: true
+ },
+ end: {
+ type: luxon.DateTime,
+ required: true
}
},
data()
@@ -30,10 +32,13 @@ export default {
},
computed: {
start() {
- return this.day.startOf('week', { useLocaleWeeks: true });
+ return this.day.startOf('day');
+ },
+ tableEnd() {
+ return this.end.endOf('day');
},
preparedEvents() {
- const end = this.start.plus({ days: 7 });
+ const end = this.tableEnd;
return this.events
.filter(e => e.start < end && e.end > this.start)
.sort((a, b) => a.start.ts - b.start.ts)
@@ -112,15 +117,6 @@ export default {
this.$refs.tableViewTable?.tabulator?.setData(newData);
}
},
-/* mounted() {
-
- this.$api.call(ApiDetails.getRaumtyp())
- .then(result => {
- this.raumtyp_array = result.data;
- })
- .catch(this.$fhcAlert.handleSystemError);
-
- },*/
template: /* html */`
luxon.Duration.fromObject({ hours: i + start }));
}
+ },
+ dayVisibility() {
+ return this.axisMain.map(date => this.visibleDays[date.weekday -1])
}
},
methods: {
isToday(date) {
return date.hasSame(luxon.DateTime.now().setZone(this.timezone), 'day');
+ },
+ toggleDay(day)
+ {
+ this.visibleDays.splice(day, 1, !this.visibleDays[day])
+ localStorage.setItem('fhc-calender-visible-days', JSON.stringify(this.visibleDays))
}
},
template: /* html */`
@@ -60,9 +76,10 @@ export default {
:axis-main-collapsible="collapseEmptyDays"
:snap-to-grid="!!timeGrid"
all-day-events
+ :day-visibility="dayVisibility"
>
-
-
+
+
evt.detail.source = 'day'"
@@ -70,6 +87,13 @@ export default {
+
+
diff --git a/public/js/components/Calendar/Tempus.js b/public/js/components/Calendar/Tempus.js
index 174b9c963..64b5ef298 100644
--- a/public/js/components/Calendar/Tempus.js
+++ b/public/js/components/Calendar/Tempus.js
@@ -16,6 +16,10 @@ export default {
},
inject: {
renderers: {from: 'renderers'},
+ canToggleGrid: {
+ from: 'canToggleGrid',
+ default: false
+ },
appConfig: {
from: 'appConfig',
default: {
@@ -59,15 +63,21 @@ export default {
type: Array,
default: () => ['all']
},
+ showEvents: {
+ type: Boolean,
+ default: true
+ }
},
emits: [
"update:date",
"update:mode",
"update:range",
+ "update:date-range",
"drop",
"resize",
"event-hover",
- "event-unhover"
+ "event-unhover",
+ "open-reservierung"
],
data() {
@@ -146,9 +156,18 @@ export default {
return '--event-bg:#' + event.farbe;
},
updateRange(rangeInterval) {
+ if (this.currentMode === 'tableList')
+ return;
+
this.rangeInterval = rangeInterval;
this.$emit('update:range', rangeInterval);
},
+ handleDateRange({ start, end }) {
+ this.rangeInterval = luxon.Interval.fromDateTimes(start.startOf('day'), end.endOf('day'));
+ this.reset();
+ this.$emit('update:range', this.rangeInterval);
+ this.$emit('update:date-range', { start, end });
+ },
ondrop(payload){
this.$emit('drop', payload);
},
@@ -224,10 +243,11 @@ export default {
@update:date="(newDate, newMode) => $emit('update:date', newDate, newMode)"
@update:mode="(newMode, newDate) => { currentMode = newMode; $emit('update:mode', newMode, newDate) }"
@update:range="updateRange"
+ @update:date-range="handleDateRange"
>
Stundenraster
@@ -281,4 +302,4 @@ export default {
`
-}
\ No newline at end of file
+}
diff --git a/public/js/components/Tempus/Coursepicker.js b/public/js/components/Tempus/Coursepicker.js
index abf112356..0ce0c329a 100644
--- a/public/js/components/Tempus/Coursepicker.js
+++ b/public/js/components/Tempus/Coursepicker.js
@@ -14,19 +14,32 @@ export default {
type: Array,
default: [],
},
+ lecturers: {
+ type: Array,
+ default: [],
+ },
studiensemester: {
type: String,
default: null
},
+ previewLehreinheitId: {
+ type: [String, Number],
+ default: null
+ },
+ previewLoading: {
+ type: Boolean,
+ default: false
+ },
},
- emits: ['select-lecturer', 'select-kw'],
+ emits: ['select-lecturer', 'select-kw', 'preview-raumvorschlag'],
data() {
return {
searchparam: '',
allCourses: [],
sortBy: null,
multiWeekIds: new Set(),
- favorites: new Set()
+ favorites: new Set(),
+ filter: {}
}
},
computed: {
@@ -86,32 +99,45 @@ export default {
studiengaenge: {
deep: true,
handler(val) {
- this.searchparam = '';
- this.loadCoursesByStg(val);
+ this.loadCourses();
+ }
+ },
+ lecturers: {
+ deep: true,
+ handler() {
+ this.loadCourses();
}
},
studiensemester() {
if (this.studiengaenge)
- this.loadCoursesByStg(this.studiengaenge);
+ this.loadCourses();
},
},
methods: {
- async loadCoursesByStg(stg) {
- if (stg.length <= 0)
- {
- this.allCourses = [];
- return;
+ async loadCourses()
+ {
+ const hasLektoren = this.lecturers.length > 0;
+ const hasStg = this.studiengaenge.length > 0;
+
+ this.filter = {};
+ if (hasLektoren)
+ this.filter.uid = this.lecturers;
+
+ if (hasStg) {
+ this.filter.stg = this.studiengaenge.map(
+ ({ stg_kz, semester, orgform_kurzbz }) => ({
+ stg_kz,
+ semester,
+ orgform_kurzbz,
+ }),
+ );
}
- let payload = stg.map(({ stg_kz, semester, orgform_kurzbz }) => ({
- stg_kz,
- semester,
- orgform_kurzbz
- }));
-
- this.$api.call(ApiCoursePicker.getByStg(payload, this.studiensemester))
+ if (Object.keys(this.filter).length === 0)
+ return this.allCourses = [];
+ this.$api.call(ApiCoursePicker.getCourses(this.filter, this.studiensemester))
.then(result => {
- this.allCourses = result.data.map(e => ({
+ this.allCourses = result?.data?.map(e => ({
lehreinheit_id: e.lehreinheit_id,
lektoren: e.lektoren,
raumtyp: e.raumtyp,
@@ -177,7 +203,7 @@ export default {
},
reload()
{
- this.loadCoursesByStg(this.studiengaenge);
+ this.loadCourses();
},
toggleMultiWeek(course)
{
@@ -210,6 +236,17 @@ export default {
{
return this.favorites.has(course.lehreinheit_id);
},
+ selectRaumvorschlag(course)
+ {
+ if (this.isRaumvorschlagActive(course))
+ this.$emit('preview-raumvorschlag', null);
+ else
+ this.$emit('preview-raumvorschlag', course.orig);
+ },
+ isRaumvorschlagActive(course)
+ {
+ return this.previewLehreinheitId != null && this.previewLehreinheitId === course.lehreinheit_id;
+ },
},
mounted() {
this.favorites = new Set(JSON.parse(localStorage.getItem('tempus_coursepicker_favs') || '[]'));
@@ -253,7 +290,7 @@ export default {
-
+
{{$p.t('lehre', 'cptitleempty')}}
{{$p.t('lehre', 'cpempty')}}
@@ -264,7 +301,7 @@ export default {
style="cursor:grab"
:style="courseStyle(course)"
class="course-picker-row rounded-3 mb-2 p-2"
- :class="{ 'course-picker-row-pinned': isPinned(course) }"
+ :class="{ 'course-picker-row-pinned': isPinned(course), 'course-picker-row-preview': isRaumvorschlagActive(course) }"
v-draggable:move.noimage="dragLehreinheitCollection(course)"
tabindex="0"
>
@@ -284,6 +321,19 @@ export default {
v-tooltip="isMultiWeek(course) ? 'MultiWeek aktiv' : 'MultiWeek Verplanung aktivieren'"
@click.stop="toggleMultiWeek(course)"
>
+
+
diff --git a/public/js/components/Tempus/Filters/LectureSelection.js b/public/js/components/Tempus/Filters/LectureSelection.js
index a25856b86..d08a35774 100644
--- a/public/js/components/Tempus/Filters/LectureSelection.js
+++ b/public/js/components/Tempus/Filters/LectureSelection.js
@@ -47,6 +47,10 @@ export default {
Zeitwünsche
+
+
+ Course Picker
+
diff --git a/public/js/components/Tempus/Filters/searchbarOptions.js b/public/js/components/Tempus/Filters/searchbarOptions.js
index 42150ed41..8ca4fe7a5 100644
--- a/public/js/components/Tempus/Filters/searchbarOptions.js
+++ b/public/js/components/Tempus/Filters/searchbarOptions.js
@@ -43,6 +43,25 @@ export function getTempusSearchbarOptions(self)
self.addToFilter(data, 'mitarbeiter');
}
},
+ {
+ label: "zum Course Picker hinzufügen",
+ icon: "fas fa-plus",
+ type: "function",
+ action: (data) => {
+ self.addToCoursePicker(data);
+ }
+ },
+ {
+ label: "LVVerwaltung",
+ icon: "fas fa-up-right-from-square",
+ type: "function",
+ action: (data) => {
+ const link = FHC_JS_DATA_STORAGE_OBJECT.app_root +
+ FHC_JS_DATA_STORAGE_OBJECT.ci_router +
+ "/LVVerwaltung/stdsem/" + self.selectedStudiensemester + "/emp/" + data.uid;
+ window.open(link, "_blank");
+ }
+ },
]
},
}
diff --git a/public/js/components/Tempus/Header.js b/public/js/components/Tempus/Header.js
index 55c5983f1..d1dbc2dfa 100644
--- a/public/js/components/Tempus/Header.js
+++ b/public/js/components/Tempus/Header.js
@@ -20,11 +20,10 @@ export default {
required: true,
},
},
- emits: ["focus-searchbar", "language-changed"],
+ emits: ["language-changed"],
methods: {
focusSearchbar() {
this.$refs.searchbar?.$refs?.input?.focus();
- this.$emit("focus-searchbar");
},
},
template: /* html */ `
diff --git a/public/js/components/Tempus/Modal.js b/public/js/components/Tempus/Modal.js
new file mode 100644
index 000000000..8792a2eed
--- /dev/null
+++ b/public/js/components/Tempus/Modal.js
@@ -0,0 +1,353 @@
+import BsModal from '../Bootstrap/Modal.js';
+import CoreForm from '../Form/Form.js';
+import FormValidation from '../Form/Validation.js';
+import FormInput from '../Form/Input.js';
+
+import ApiTempusSync from '../../api/factory/tempus/sync.js';
+
+export default {
+ components: {
+ BsModal,
+ CoreForm,
+ FormValidation,
+ FormInput
+ },
+ props: {
+ config: Object,
+ stsem_kurzbz: String
+ },
+ emits: [
+ 'saved'
+ ],
+ data() {
+ return {
+ mode: 'new',
+ formData: {},
+ studienplaene: [],
+ max_semester: null,
+ syncStati: [],
+ loading: false
+ };
+ },
+ computed: {
+ semester() {
+ if (!this.max_semester)
+ return [];
+
+ return Array.from({length: this.max_semester}, (_, index) => index);
+ },
+ studienplanTrigger() {
+ return [
+ this.formData.oe_kurzbz,
+ this.formData.studiensemester_kurzbz,
+ this.formData.ausbildungssemester
+ ].join('|');
+ }
+ },
+ watch: {
+ 'formData.oe_kurzbz'(newOrganisation)
+ {
+ if (!newOrganisation) {
+ this.max_semester = null;
+ this.studienplaene = [];
+ return;
+ }
+
+ let filtered_org = (this.config.organisationen ?? []).filter(org => org.oe_kurzbz === newOrganisation)[0];
+
+ if (filtered_org && filtered_org.studiengang_kz)
+ this.getSemester(filtered_org.studiengang_kz);
+ else
+ this.max_semester = null;
+ },
+ studienplanTrigger() {
+ this.getStudienplan();
+ }
+ },
+ methods: {
+
+ openNew() {
+ this.$refs.modal.hide();
+
+ this.mode = 'new';
+ this.max_semester = null;
+ this.studienplaene = [];
+ this.formData = {
+ oe_kurzbz: null,
+ studiensemester_kurzbz: this.stsem_kurzbz ?? null,
+ datum_bis: null,
+ studienplan_id: null,
+ ausbildungssemester: null,
+ sync_status_kurzbz: null,
+ mail: false
+ };
+
+ this.$refs.form.clearValidation()
+ this.$refs.modal.show()
+ },
+ openEdit(entry) {
+ if (!entry || entry.kalender_syncstatus_id === undefined || entry.kalender_syncstatus_id === null)
+ {
+ return;
+ }
+
+ this.$refs.modal.hide();
+ this.mode = 'edit';
+
+ this.$api
+ .call(ApiTempusSync.loadSync(entry.kalender_syncstatus_id))
+ .then(result => {
+ this.formData = result.data;
+ return this.$refs.form.clearValidation();
+ })
+ .then(() => this.$refs.modal.show())
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+
+ openStart() {
+ this.$refs.modal.hide();
+
+ this.mode = 'start';
+ this.max_semester = null;
+ this.studienplaene = [];
+ this.formData = {
+ oe_kurzbz: null,
+ studiensemester_kurzbz: this.stsem_kurzbz ?? null,
+ datum_bis: null,
+ sync_status_kurzbz: null,
+ studienplan_id: null,
+ ausbildungssemester: null,
+ mail: false
+ };
+
+ this.$refs.form.clearValidation()
+ this.$refs.modal.show()
+ },
+ getSemester(stg_kz) {
+ this.$api.call(ApiTempusSync.getMaxSemester([stg_kz]))
+ .then(response => response.data)
+ .then(response => {
+ this.max_semester = response ?? null;
+
+ let found = this.semester.filter(semester => semester === this.formData.ausbildungssemester);
+ if (found.length === 0)
+ this.formData.ausbildungssemester = null;
+ })
+ .catch(error => {
+ this.$fhcAlert.handleSystemError(error);
+ });
+ },
+ getStudienplan() {
+ if (!this.formData.oe_kurzbz || !this.formData.studiensemester_kurzbz) {
+ this.studienplaene = [];
+ return;
+ }
+
+ this.$api.call(ApiTempusSync.getStudienplan(
+ this.formData.oe_kurzbz,
+ this.formData.studiensemester_kurzbz,
+ this.formData.ausbildungssemester ?? null
+ ))
+ .then(response => response.data)
+ .then(response => {
+ this.studienplaene = response ?? [];
+ let found = this.studienplaene.filter(plan => plan.studienplan_id === this.formData.studienplan_id);
+ if (found.length === 0)
+ this.formData.studienplan_id = null;
+ })
+ .catch(error => {
+ this.$fhcAlert.handleSystemError(error);
+ });
+ },
+ save() {
+ if (this.mode === 'start')
+ this.start();
+ else if (this.mode === 'new')
+ this.insert();
+ else
+ this.update();
+ },
+ insert() {
+ this.$refs.form
+ .call(ApiTempusSync.add(this.formData))
+ .then(() => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
+ this.$emit('saved', this.formData.studiensemester_kurzbz);
+ this.$refs.modal.hide();
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ update() {
+ this.$refs.form
+ .call(ApiTempusSync.updateSync(this.formData))
+ .then(() => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successSave'));
+ this.$emit('saved', this.formData.studiensemester_kurzbz);
+ this.$refs.modal.hide();
+ })
+ .catch(this.$fhcAlert.handleSystemError);
+ },
+ start(data) {
+ this.loading = true;
+ return this.$refs.form
+ .call(ApiTempusSync.start(data ?? this.formData))
+ .then(() => {
+ this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successStart'));
+ this.$refs.modal.hide();
+ this.loading = false;
+ })
+ .catch(this.$fhcAlert.handleSystemError)
+ .finally(() => {
+ this.loading = false;
+ });
+ },
+ hideModal()
+ {
+ this.formData = {}
+ }
+ },
+ created() {
+
+ this.$api
+ .call(ApiTempusSync.getSyncStatus())
+ .then(result => this.syncStati = result.data ?? [])
+ .catch(error => this.$fhcAlert.handleSystemError(error));
+ },
+ template: `
+
+
+ {{ $p.t('lehre', 'tempus_sync_new') }}
+ {{ $p.t('lehre', 'tempus_sync_edit') }}
+ {{ $p.t('lehre', 'tempus_sync_start') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `
+};
\ No newline at end of file
diff --git a/public/js/components/Tempus/ParkingSlot.js b/public/js/components/Tempus/ParkingSlot.js
index 6bc7bbf95..2016a925f 100644
--- a/public/js/components/Tempus/ParkingSlot.js
+++ b/public/js/components/Tempus/ParkingSlot.js
@@ -9,7 +9,7 @@ export default {
directives: {
drop
},
- emits: ['update:parkedKeys'],
+ emits: ['update:parkedKeys', 'select-kw'],
data() {
return {
parked: [],
@@ -66,11 +66,12 @@ export default {
>
diff --git a/public/js/components/Tempus/RaumauswahlModal.js b/public/js/components/Tempus/RaumauswahlModal.js
index 4e20e1c17..68c955992 100644
--- a/public/js/components/Tempus/RaumauswahlModal.js
+++ b/public/js/components/Tempus/RaumauswahlModal.js
@@ -1,11 +1,14 @@
import BsModal from "../Bootstrap/Modal.js";
import ApiKalender from "../../api/factory/tempus/kalender.js";
+import FormInput from "../../../js/components/Form/Input.js";
+
export default {
name: "RaumauswahlModal",
components: {
BsModal,
Listbox: primevue.listbox,
+ FormInput
},
emits: ["saved"],
data() {
@@ -14,6 +17,9 @@ export default {
selectedRooms: [],
event: null,
loading: false,
+ mode: 'edit',
+ pendingEvent: null,
+ location: null,
};
},
methods: {
@@ -22,10 +28,12 @@ export default {
if (!orig?.kalender_id)
return;
+ this.mode = 'edit';
this.event = orig;
this.loading = true;
this.entries = [];
this.selectedRooms = [];
+ this.location = this.event.location
this.$refs.modal.show();
@@ -53,13 +61,51 @@ export default {
},
hide() {
this.selectedRooms = [];
+ this.pendingEvent = null;
this.$refs.modal.hide();
},
- async confirm() {
- let ort_kurzbz = this.selectedRooms.map((room) => room.ort_kurzbz);
+ showForNew(lehreinheit_id, start_time, end_time, vorschlaege)
+ {
+ this.mode = 'new'
+ this.pendingEvent = {lehreinheit_id, start_time, end_time}
+ this.event = null;
+ this.loading = false;
+ this.entries = vorschlaege ?? [];
+ this.selectedRooms = [];
- if (ort_kurzbz.length < 1)
+ this.$refs.modal.show();
+ },
+
+ async confirm() {
+
+ if (this.mode === 'new')
+ {
+ const result = await this.$api.call(
+ ApiKalender.addKalenderEvent(
+ this.pendingEvent.lehreinheit_id,
+ this.selectedRooms.map((room) => room.ort_kurzbz),
+ this.pendingEvent.start_time,
+ this.pendingEvent.end_time
+ )
+ ).then((result) => result.data)
+
+ if (result.needs_room_selection)
+ {
+ this.showForNew(this.pendingEvent.lehreinheit_id, this.pendingEvent.start_time, this.pendingEvent.end_time, result.raum_vorschlaege);
+ return;
+ }
+
+ this.hide();
+ this.$emit('saved');
+ return;
+ }
+ let orte = {};
+
+ orte.ort_kurzbz = this.selectedRooms.map((room) => room.ort_kurzbz);
+ orte.location = this.location;
+
+ if (orte.ort_kurzbz.length < 1 && orte.location?.trim().length < 1)
{
await this.$api.call(
ApiKalender.deleteOrtEntry(this.event.kalender_id),
@@ -68,7 +114,7 @@ export default {
else
{
await this.$api.call(
- ApiKalender.updateKalenderEvent(this.event.kalender_id, {ort_kurzbz}),
+ ApiKalender.updateKalenderEvent(this.event.kalender_id, {orte}),
);
}
@@ -119,16 +165,38 @@ export default {
listStyle="max-height: 300px"
:emptyMessage="$p.t('ui', 'keineEintraegeGefunden')"
>
-
-
- {{ option.ort_kurzbz }}
- {{ option.score }}
-
-
+
+
+
+
+
+ [{{ option.raumtyp_kurzbz }}]
+
+
+
+ {{ option.ort_kurzbz }}
+
+
+ {{ option.max_person }} Pers.
+
+
+ {{ option.score }}
+
+
+
+
+
`,
-}
\ No newline at end of file
+}
diff --git a/public/js/components/Tempus/Renderer/Reservierungen/calendarEvent.js b/public/js/components/Tempus/Renderer/Reservierungen/calendarEvent.js
index 5a511a902..750efb417 100644
--- a/public/js/components/Tempus/Renderer/Reservierungen/calendarEvent.js
+++ b/public/js/components/Tempus/Renderer/Reservierungen/calendarEvent.js
@@ -83,7 +83,8 @@ export default {
.toISOTime({ suppressSeconds: true });
},
ortString() {
- return Array.isArray(this.event.ort_kurzbz) ? this.event.ort_kurzbz.join(', ') : this.event.ort_kurzbz;
+ let orte = [...(this.event.ort_kurzbz || []), this.event.location?.trim()].filter(Boolean)
+ return orte.join(', ')
},
topicString() {
return Array.isArray(this.event.titel) ? this.event.titel.join(', ') : this.event.titel;
diff --git a/public/js/components/Tempus/Renderer/Reservierungen/modalContent.js b/public/js/components/Tempus/Renderer/Reservierungen/modalContent.js
index 121c70935..69dbca70e 100644
--- a/public/js/components/Tempus/Renderer/Reservierungen/modalContent.js
+++ b/public/js/components/Tempus/Renderer/Reservierungen/modalContent.js
@@ -52,9 +52,6 @@ export default {
},
},
methods: {
- mehtodNumberPadding: function (number) {
- return numberPadding(number);
- },
methodFormatDate: function (d) {
return formatDate(d);
},
@@ -133,4 +130,4 @@ export default {
`,
-}
\ No newline at end of file
+}
diff --git a/public/js/components/Tempus/Reservierung.js b/public/js/components/Tempus/Reservierung.js
index c0fe64aba..0c39059d3 100644
--- a/public/js/components/Tempus/Reservierung.js
+++ b/public/js/components/Tempus/Reservierung.js
@@ -33,7 +33,8 @@ export default {
show_all_fields: false,
filteredUsers: [],
filteredGroups: [],
- abortController: null
+ abortController: null,
+ location: null
};
},
created()
@@ -141,11 +142,16 @@ export default {
},
save()
{
+
+ let orte = {
+ ort_kurzbz: this.selected_rooms.map(r => r.ort_kurzbz),
+ location: this.location
+ }
this.$api.call(
ApiReservierung.addReservierung(
this.titel,
this.beschreibung,
- this.selected_rooms.map(r => r.ort_kurzbz),
+ orte,
luxon.DateTime.fromFormat(this.start, 'yyyy-MM-dd HH:mm').toISO(),
luxon.DateTime.fromFormat(this.end, 'yyyy-MM-dd HH:mm').toISO(),
this.teilnehmer.filter(t => t.uid && t.rolle).map(nehmer => ({ uid: nehmer.uid, rolle: nehmer.rolle })),
@@ -220,6 +226,14 @@ export default {
+
+
+
[],
- },
- lecturers: {
- type: Array,
- required: true,
- },
- selectedStudiensemester: {
- type: String,
- required: true,
- },
- },
- emits: [
- "update:previewRole",
- "update:rooms",
- "update:studiengaenge",
- "update:parkedKeys",
- "update:selectedStudiensemester",
- "remove-lecturer",
- "select-lecturer",
- "select-kw",
- "sync",
- ],
- methods: {
- reloadCoursepicker() {
- return this.$refs.coursepicker?.reload();
- },
- isParked(id) {
- return this.$refs.parking?.isParked(id) ?? false;
- },
- park(items) {
- return this.$refs.parking?.park(null, items);
- },
- unpark(item) {
- return this.$refs.parking?.unpark(item);
- },
- },
- template: /* html */ `
+ name: 'TempusSidebarMenu',
+ components: {
+ FhcCoursepicker,
+ LectureSelection,
+ VerbandSelection,
+ RoomSelection,
+ ParkingSlot,
+ StvStudiensemester,
+ },
+ props: {
+ previewRole: {
+ type: String,
+ required: true,
+ },
+ rooms: {
+ type: Array,
+ required: true,
+ },
+ studiengaenge: {
+ type: Array,
+ required: true,
+ },
+ studiengaengeAll: {
+ type: Array,
+ default: () => [],
+ },
+ lecturers: {
+ type: Array,
+ required: true,
+ },
+ selectedStudiensemester: {
+ type: String,
+ required: true,
+ },
+ raumvorschlagPreview: {
+ type: Object,
+ default: null,
+ },
+ raumvorschlagLoading: {
+ type: Boolean,
+ default: false,
+ },
+ },
+ emits: [
+ 'update:previewRole',
+ 'update:rooms',
+ 'update:studiengaenge',
+ 'update:parkedKeys',
+ 'update:selectedStudiensemester',
+ 'remove-lecturer',
+ 'select-lecturer',
+ 'select-kw',
+ 'sync',
+ 'preview-raumvorschlag',
+ ],
+ methods: {
+ reloadCoursepicker() {
+ return this.$refs.coursepicker?.reload();
+ },
+ isParked(id) {
+ return this.$refs.parking?.isParked(id) ?? false;
+ },
+ park(items) {
+ return this.$refs.parking?.park(null, items);
+ },
+ unpark(item) {
+ return this.$refs.parking?.unpark(item);
+ },
+ },
+ computed: {
+ courseLecturers() {
+ if (!this.lecturers.length) return [];
+ return this.lecturers
+ .filter((lecture) => lecture.showCoursePicker)
+ .map((lecture) => lecture.uid);
+ },
+ },
+ template: /* html */ `