diff --git a/application/config/stv.php b/application/config/stv.php index 34a30a96e..3090e3f2e 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -133,13 +133,21 @@ $config['students_tab_order'] = [ $config['stv_prestudent_tags'] = [ 'prioone' => ['readonly' => false], - 'priotwo' => ['readonly' => true], + 'priotwo' => ['readonly' => false], 'hinweis' => ['readonly' => false], - 'hinweis_assistenz' => ['readonly' => true], - 'hinweis_kf' => ['readonly' => true], + 'hinweis_assistenz' => ['readonly' => false], + 'hinweis_kf' => ['readonly' => false], 'hinweis_lehrende' => ['readonly' => false], - 'hinweis_stg_kf' => ['readonly' => true], - 'finished_stg' => ['readonly' => true], - 'finished_kf' => ['readonly' => true], - 'inwork_kf' => ['readonly' => true], + 'hinweis_stg_kf' => ['readonly' => false], + 'finished_stg' => ['readonly' => false], + 'finished_kf' => ['readonly' => false], + 'inwork_kf' => ['readonly' => false], + 'dd_auto' => ['readonly' => true], + 'wh_auto' => ['readonly' => true], + 'prewh_auto' => ['readonly' => true], + 'out_auto' => ['readonly' => true], + 'zgv_auto' => ['readonly' => true], + 'unterbrecher_auto' => ['readonly' => true], + 'stbtr_erh_auto' => ['readonly' => true], + 'jgv_auto' => ['readonly' => true], ]; diff --git a/application/controllers/api/frontend/v1/stv/Students.php b/application/controllers/api/frontend/v1/stv/Students.php index ae83fa4ff..22e3da1d7 100644 --- a/application/controllers/api/frontend/v1/stv/Students.php +++ b/application/controllers/api/frontend/v1/stv/Students.php @@ -147,7 +147,7 @@ class Students extends FHCAPI_Controller $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -214,7 +214,7 @@ class Students extends FHCAPI_Controller $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -267,7 +267,7 @@ class Students extends FHCAPI_Controller $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -476,7 +476,7 @@ class Students extends FHCAPI_Controller $result = $this->PrestudentModel->loadWhere($where); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -631,10 +631,22 @@ class Students extends FHCAPI_Controller $result = $this->PrestudentModel->loadWhere($where); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } + protected function decodeTagsJsonInResult(&$data) + { + if(defined('STV_TAGS_ENABLED') && STV_TAGS_ENABLED) { + array_walk($data, function($item, $key) { + if(isset($item->tags)) + { + $item->tags = json_decode($item->tags); + } + }); + } + } + /** * @param string $prestudent_id * @@ -679,7 +691,7 @@ class Students extends FHCAPI_Controller ]); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -722,7 +734,7 @@ class Students extends FHCAPI_Controller ]); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -764,7 +776,7 @@ class Students extends FHCAPI_Controller ]); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -840,7 +852,7 @@ class Students extends FHCAPI_Controller $result = $this->PrestudentModel->load(); $data = $this->getDataOrTerminateWithError($result); - + $this->decodeTagsJsonInResult($data); $this->terminateWithSuccess($data); } @@ -882,12 +894,31 @@ class Students extends FHCAPI_Controller n.text AS notiz, nt.style, n.erledigt AS done, - nz.prestudent_id + nz.prestudent_id, + n.start, + n.ende FROM public.tbl_notizzuordnung AS nz JOIN public.tbl_notiz AS n ON nz.notiz_id = n.notiz_id JOIN public.tbl_notiz_typ AS nt ON n.typ = nt.typ_kurzbz " . $whereTags . " + WHERE + COALESCE(n.start, '1970-01-01') <= ( + SELECT + ende + FROM + public.tbl_studiensemester + WHERE + studiensemester_kurzbz = '{$studiensemester_kurzbz}' + ) + AND COALESCE(n.ende, '2170-12-31') >= ( + SELECT + start + FROM + public.tbl_studiensemester + WHERE + studiensemester_kurzbz = '{$studiensemester_kurzbz}' + ) ) AS tag GROUP BY tag.prestudent_id ) AS tag_data_agg diff --git a/application/controllers/api/frontend/v1/stv/Tags.php b/application/controllers/api/frontend/v1/stv/Tags.php index 3004a1f3b..e5af9becc 100644 --- a/application/controllers/api/frontend/v1/stv/Tags.php +++ b/application/controllers/api/frontend/v1/stv/Tags.php @@ -45,4 +45,5 @@ class Tags extends Tag_Controller { parent::doneTag($this->config->item('stv_prestudent_tags')); } + } diff --git a/application/controllers/jobs/TagJob.php b/application/controllers/jobs/TagJob.php new file mode 100644 index 000000000..d12231b06 --- /dev/null +++ b/application/controllers/jobs/TagJob.php @@ -0,0 +1,117 @@ +load->config('stv'); + + // Library + $this->load->library('TagLib'); + + // Load Models + $this->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + $this->load->model('system/Notiztyp_model', 'NotiztypModel'); + + $this->loadPhrases([ + 'lehre' + ]); + } + + public function rebuildAutomatedTags() + { + + + $automatedTagsRes = $this->NotiztypModel->loadWhere(array('automatisiert' => true, 'taglib IS NOT NULL' => null)); + $automatedTags = hasData($automatedTagsRes) ? getData($automatedTagsRes) : []; + + + $result = $this->StudiensemesterModel->getAktOrNextSemester(); + if (isError($result)) + { + $this->logInfo('Start Job rebuild Automated Tags'); + $this->logError('Error occurred during retrieving studiensemester'); + return $this->logInfo('End Job rebuild Automated Tags'); + } + + if (empty($result->retval) || !isset($result->retval[0])) { + $this->logInfo('Start Job rebuild Automated Tags'); + $this->logError('No Studiensemester found'); + return $this->logInfo('End Job rebuild Automated Tags'); + } + $studiensemester_kurzbz = $result->retval[0]->studiensemester_kurzbz ?? null; + $params = array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ); + + $this->logInfo('Start Job rebuild Automated Tags ' . $studiensemester_kurzbz); + foreach($automatedTags as $autoTag) + { + // getPath: must not be lost + $filePath = APPPATH . 'libraries/' . $autoTag->taglib . '.php'; // APPPATH = application/ + + if(file_exists($filePath)) { + require_once($filePath); + } else { + $this->logInfo("File not found: " . $filePath); + continue; + } + + $kurz_bz = $autoTag->typ_kurzbz; + // className without PATH (basename) + $className = basename($autoTag->taglib); + + $obj = new $className(); + + $outputArray = $obj->getZuordnungIds($params); + $typeId = $outputArray->typeId; + + $paramsTag = array( + 'studiensemester_kurzbz' => $studiensemester_kurzbz, + 'kurzbz' => $kurz_bz, + 'data' => $outputArray->data, + 'typeId' => $typeId + ); + + $result = $this->taglib->updateAutomatedTags($paramsTag); + + if (isError($result)) { + $this->logError('Error occurred during updateAutomatedTags ' . $kurz_bz); + continue; + } + + $data = is_array($result) ? $result['retval'] : $result->retval; + + //SUMMARY + $this->logInfo("Tag " . $result->retval['input']['tag'] . " | type_id " . $typeId . " --" + . " Count Recycled: " . $result->retval['summary']['recycled'] + . " Count Added: ". $result->retval['summary']['added'] + . " Count Deleted: ". $result->retval['summary']['deleted']); + + //DETAILS + if($result->retval['results']['newTags']) + $this->logInfo("Tag " . $result->retval['input']['tag'] . "New tag(s): " . implode(', ', $result->retval['results']['newTags'])); + if($result->retval['results']['deletedTagsIds']) + $this->logInfo("Tag " . $result->retval['input']['tag'] . "Deleted tags(s: " . implode(', ', $result->retval['results']['deletedTagsIds'])); + if ($result->retval['results']['retaggedIds']) + $this->logInfo("Tag " . $result->retval['input']['tag'] . "Recycled tag(s): " . implode(', ', $result->retval['results']['retaggedIds'])); + + } + $this->logInfo( "End Job rebuild Automated Tags"); + + } +} diff --git a/application/core/Tag_Controller.php b/application/core/Tag_Controller.php index 5b9bac6c5..fb14563ba 100644 --- a/application/core/Tag_Controller.php +++ b/application/core/Tag_Controller.php @@ -15,10 +15,11 @@ class Tag_Controller extends FHCAPI_Controller 'getTag' => self::BERECHTIGUNG_KURZBZ, 'getTags' => self::BERECHTIGUNG_KURZBZ, 'addTag' => self::BERECHTIGUNG_KURZBZ, - 'updateTag' => self::BERECHTIGUNG_KURZBZ, 'doneTag' => self::BERECHTIGUNG_KURZBZ, 'deleteTag' => self::BERECHTIGUNG_KURZBZ, + 'getAllTags' => self::BERECHTIGUNG_KURZBZ, + 'rebuildTagsForTypeId' => self::BERECHTIGUNG_KURZBZ, ]; $merged_permissions = array_merge($default_permissions, $permissions); @@ -26,6 +27,10 @@ class Tag_Controller extends FHCAPI_Controller parent::__construct($merged_permissions); $this->_setAuthUID(); + + // Library + $this->load->library('TagLib'); + $this->load->model('person/Notiz_model', 'NotizModel'); $this->load->model('system/Notiztyp_model', 'NotiztypModel'); $this->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); @@ -37,7 +42,6 @@ class Tag_Controller extends FHCAPI_Controller public function getTag($readonly_tags = null) { - $language = $this->_getLanguageIndex(); $id = $this->input->get('id'); if (is_array($readonly_tags) && !isEmptyArray($readonly_tags)) @@ -62,14 +66,17 @@ class Tag_Controller extends FHCAPI_Controller $this->NotizModel->addSelect( "tbl_notiz.titel, tbl_notiz.text, - array_to_json(bezeichnung_mehrsprachig::varchar[])->>". $language. " as bezeichnung, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung, tbl_notiz.notiz_id, tbl_notiz_typ.style, + tbl_notiz_typ.automatisiert, tbl_notiz.erledigt as done, tbl_notiz.insertamum, tbl_notiz.updateamum, (verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser, - (bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter + (bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter, + tbl_notiz.start, + tbl_notiz.ende " ); $this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz'); @@ -82,18 +89,22 @@ class Tag_Controller extends FHCAPI_Controller $notiz = $this->NotizModel->loadWhere(array('notiz_id' => $id)); + $this->terminateWithSuccess(hasData($notiz) ? getData($notiz)[0] : array()); } public function getTags($tags = null) { + $language = $this->_getLanguageIndex(); + $this->NotiztypModel->addSelect( - 'typ_kurzbz as tag_typ_kurzbz, + "typ_kurzbz as tag_typ_kurzbz, array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung, style, beschreibung, - tag - ' + tag, + automatisiert + " ); $this->NotiztypModel->addOrder('prioritaet'); @@ -271,6 +282,74 @@ class Tag_Controller extends FHCAPI_Controller $this->terminateWithSuccess($deleteNotiz); } + public function getAllTags($readonly_tags = false){ + $prestudent_id = $this->input->get('prestudent_id'); + + //TODO check for readonly: necessary? + if (is_array($readonly_tags) && !isEmptyArray($readonly_tags)) + { + $readonly_tags = $this->_filterTag($readonly_tags, true); + + foreach ($readonly_tags as $key => $tag) + { + $readonly_tags[$key] = $this->NotizModel->db->escape($tag); + } + $tags = '(' . implode(',', $readonly_tags) . ')'; + + $this->NotizModel->addSelect(" + CASE + WHEN tbl_notiz_typ.typ_kurzbz IN $tags + THEN TRUE + ELSE FALSE + END as readonly + "); + } + $this->NotizModel->addSelect( + "tbl_notiz.titel, + tbl_notiz.text, + array_to_json(bezeichnung_mehrsprachig::varchar[])->>0 as bezeichnung, + tbl_notiz.notiz_id, + tbl_notiz_typ.style, + tbl_notiz_typ.automatisiert, + tbl_notiz.erledigt as done, + tbl_notiz.insertamum, + tbl_notiz.updateamum, + (verfasserperson.vorname || ' ' || verfasserperson.nachname || ' ' || '(' || verfasserbenutzer.uid || ')') as verfasser, + (bearbeiterperson.vorname || ' ' || bearbeiterperson.nachname || ' ' || '(' || bearbeiterbenutzer.uid || ')') as bearbeiter, + tbl_notiz.start, + tbl_notiz.ende + " + ); + $this->NotizModel->addJoin('public.tbl_notiz_typ', 'public.tbl_notiz.typ = public.tbl_notiz_typ.typ_kurzbz'); + + $this->NotizModel->addJoin('public.tbl_benutzer verfasserbenutzer', 'tbl_notiz.verfasser_uid = verfasserbenutzer.uid', 'LEFT'); + $this->NotizModel->addJoin('public.tbl_person verfasserperson', 'verfasserbenutzer.person_id = verfasserperson.person_id', 'LEFT'); + + $this->NotizModel->addJoin('public.tbl_benutzer bearbeiterbenutzer', 'tbl_notiz.bearbeiter_uid = bearbeiterbenutzer.uid', 'LEFT'); + $this->NotizModel->addJoin('public.tbl_person bearbeiterperson', 'bearbeiterbenutzer.person_id = bearbeiterperson.person_id', 'LEFT'); + + $this->NotizModel->addJoin('public.tbl_notizzuordnung notizzuordnung', 'tbl_notiz.notiz_id = notizzuordnung.notiz_id'); + + $notiz = $this->NotizModel->loadWhere(array('prestudent_id' => $prestudent_id)); + + + $this->terminateWithSuccess(hasData($notiz) ? getData($notiz) : array()); + } + + public function rebuildTagsForTypeId() + { + $id = $this->input->post('id'); + $typeId = $this->input->post('typeId'); + $semester = $this->input->post('sem'); + + $result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester); + + if (isError($result)) + return error ('Error occurred during updateAutomatedTags'); + + $this->terminateWithSuccess($result); + } + private function _setAuthUID() { $this->_uid = getAuthUID(); diff --git a/application/helpers/hlp_header_helper.php b/application/helpers/hlp_header_helper.php index 27dfba5a1..53a5f5ba3 100644 --- a/application/helpers/hlp_header_helper.php +++ b/application/helpers/hlp_header_helper.php @@ -270,6 +270,28 @@ function absoluteJsImportUrl($relurl) return $url; } +/* + * Generate Css File Include if Extension contains file + * + * @param $relativeFilePath path relative to Extension public/css dir + */ +function generateCSSsIncludeIfExtensionCssExists($relativeFilePath) +{ + $fsiterator = new FilesystemIterator(FHCPATH . 'application/extensions'); + foreach ($fsiterator as $fsitem) + { + if(preg_match('/^FHC-Core-/', $fsitem->getBasename())) + { + $extensionfile = 'public/extensions/' . $fsitem->getBasename() + . '/css/' . $relativeFilePath; + if(is_readable(FHCPATH . $extensionfile)) + { + generateCSSsInclude($extensionfile); + } + } + } +} + /* * Manipulate CI views includes Array to load * - public/js/FhcApps.js via customJSs and diff --git a/application/libraries/TagLib.php b/application/libraries/TagLib.php new file mode 100644 index 000000000..a9322cd12 --- /dev/null +++ b/application/libraries/TagLib.php @@ -0,0 +1,392 @@ +_ci =& get_instance(); + + // Configs + $this->_ci->load->config('stv'); + + // Models + $this->_ci->load->model('person/Notiz_model', 'NotizModel'); + $this->_ci->load->model('system/Notiztyp_model', 'NotiztypModel'); + $this->_ci->load->model('person/Notizzuordnung_model', 'NotizzuordnungModel'); + $this->_ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + $this->_ci->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + // Libraries + $this->_ci->load->library('PermissionLib'); + $this->_ci->load->library('PrestudentLib'); + } + + public function updateAutomatedTags($paramsTag) + { + // --------------------------------- + // check params + // --------------------------------- + $required = ['kurzbz', 'data', 'typeId']; + + foreach ($required as $key) { + if (!isset($paramsTag[$key])) { + return error('Missing Parameter: ' . $key); + } + } + + $studiensemester_kurzbz = (isset ($paramsTag['studiensemester_kurzbz']) ? $paramsTag['studiensemester_kurzbz'] : null); + $tag = $paramsTag['kurzbz']; + $inputData = $paramsTag['data']; + $typeId = $paramsTag['typeId']; + + // --------------------------------- + // prepare input + // --------------------------------- + $zeitraum = []; + $arrayIds = []; + + foreach ($inputData as $item) { + $id = $item['id']; + $arrayIds[] = $id; + + $zeitraum[$id] = [ + 'von' => $item['von'] ?? null, + 'bis' => $item['bis'] ?? null + ]; + } + $arrayIds = array_unique($arrayIds); + + $result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz); + if (isError($result)) { + return $result; + } + $data = $result->retval[0] ?? null; + + $von = $data->start ?? null; + $bis = $data->ende ?? null; + + // --------------------------------- + // load existing tags + // --------------------------------- + $allTags = []; + $resultAllTags = $this->_ci->NotizModel->getAllTags($tag, $von, $bis); + if (isError($resultAllTags)) { + return $resultAllTags; + } + $allTagsData = getData($resultAllTags); + + if (!empty($allTagsData)) { + foreach ($allTagsData as $item) { + $allTags[$item->$typeId] = $item->notiz_id; + } + } + + // --------------------------------- + // map the data + // --------------------------------- + $toRecycle = []; + $toAdd = []; + $toDelete = []; + + foreach ($arrayIds as $id) { + if (isset($allTags[$id])) { + $toRecycle[$id] = $allTags[$id]; + } else { + $toAdd[] = $id; + } + } + + foreach ($allTags as $id => $notizId) { + if (!in_array($id, $arrayIds)) { + $toDelete[$id] = $notizId; + + } + } + + // --------------------------------- + // recycle (update existing) + // --------------------------------- + $countRecycled = 0; + $retagged = []; + + foreach ($toRecycle as $id => $notizId) + { + $this->_updateTag($notizId, $zeitraum[$id]['von'], $zeitraum[$id]['bis']); + + $countRecycled++; + $retagged[] = $id; + } + + // --------------------------------- + // ADD + // --------------------------------- + $countAdded = 0; + $tagged = []; + + foreach ($toAdd as $id) + { + $this->_insertTag($typeId, $id, $tag, $zeitraum[$id]['von'], $zeitraum[$id]['bis']); + $countAdded++; + + $tagged[] = $id; + } + + // --------------------------------- + // delete + // --------------------------------- + $countDeleted = 0; + $deleted = []; + + foreach ($toDelete as $id => $notizId) + { + $result = $this->_deleteTag($notizId); + + if (isError($result)) { + return $result; + } + + $countDeleted++; + $deleted[] = $id; + } + + // --------------------------------- + // return + // --------------------------------- + return success([ + 'input' => [ + 'tag' => $tag, + 'arrayIds' => $arrayIds + ], + 'summary' => [ + 'recycled' => $countRecycled, + 'added' => $countAdded, + 'deleted' => $countDeleted + ], + 'details' => [ + 'existingTags' => $allTags, + 'toAdd' => $toAdd, + 'toRecycle' => $toRecycle, + 'toDelete' => $toDelete + ], + 'results' => [ + 'retaggedIds' => $retagged, + 'newTags' => $tagged, + 'deletedTagsIds' => $deleted + ] + ]); + } + + public function updateAutomatedTagsForTypeId(array $params) + { + $return = null; + $notiz_id = null; + + $von = $params['von']; + $bis = $params['bis']; + $tag = $params['kurzbz']; + $id = $params['id']; + $typeId = $params['typeId']; + + $this->_ci->NotizModel->addSelect('nz.notiz_id'); + $this->_ci->NotizModel->addSelect($typeId); + $this->_ci->NotizModel->addJoin('public.tbl_notizzuordnung nz', 'notiz_id'); + $resultAllTags = $this->_ci->NotizModel->loadWhere([ + 'typ' => $tag, + $typeId => $id + ]); + if(hasData($resultAllTags)) + { + $notiz_id = $resultAllTags->retval[0]->notiz_id; + } + + //RECYCLE + if ($notiz_id !== null) + { + $resultUpdateNotiz = $this->_updateTag($notiz_id, $von, $bis); + $return = ['recycled' => $resultUpdateNotiz]; + } + else + //ADD + { + $resultInsertNotiz = $this->_insertTag($typeId, $id, $tag, $von, $bis); + $return = ['added' => $resultInsertNotiz]; + } + return success($return); + } + + /* + * main function for rebuild Tags for typeId + * */ + public function rebuildTagsForTypeId($typeId, $id, $studiensemester_kurzbz) + { + $automatedTagsRes = $this->_ci->NotiztypModel->loadWhere(array('automatisiert' => true, 'taglib IS NOT NULL' => null)); + $automatedTags = hasData($automatedTagsRes) ? getData($automatedTagsRes) : []; + + $result = $this->_ci->StudiensemesterModel->load($studiensemester_kurzbz); + if (isError($result)) + return error('Error occurred during retrieving studiensemester'); + if (empty($result->retval) || !isset($result->retval[0])) { + return error('No studiensemester found'); + } + + $startSem = $result->retval[0]->start ?? null; + $endeSem = $result->retval[0]->ende ?? null; + $return = []; + + foreach ($automatedTags as $autoTag) + { + // getPath: must not be lost + $filePath = APPPATH . 'libraries/' . $autoTag->taglib . '.php'; // APPPATH = application/ + + if (file_exists($filePath)) { + require_once($filePath); + } else { + echo "File not found: " . $filePath; + continue; + } + + $className = basename($autoTag->taglib); + $kurz_bz = $autoTag->typ_kurzbz; + + $obj = new $className(); + + $criteriaIsSet = $obj->isCriteriaSetFor([ + 'typeId' => $typeId, + 'id' => $id, + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); + + if (hasData($criteriaIsSet)) + { + $von = isset($criteriaIsSet->retval[0]->von) ? $criteriaIsSet->retval[0]->von : ''; + $bis = isset($criteriaIsSet->retval[0]->bis) ? $criteriaIsSet->retval[0]->bis : ''; + + $params = [ + 'von' => $von, + 'bis' => $bis, + 'kurzbz' => $autoTag->typ_kurzbz, + 'typeId' => $typeId, + 'id' => $id, + ]; + + $result = $this->updateAutomatedTagsForTypeId($params); + if (isError($result)) + return error('Error occurred during updateAutomatedTags' . $kurz_bz); + + $return[$kurz_bz] = $result; + } + else + { + //CHECK FOR DELETE + $params = [ + 'von' => $startSem, + 'bis' => $endeSem, + 'kurzbz' => $autoTag->typ_kurzbz, + 'typeId' => $typeId, + 'id' => $id, + ]; + $result = $this->_ci->NotizModel->checkIfExistingTag($kurz_bz, $typeId, $id, $startSem, $endeSem); + if (hasData($result)) + { + $notizId = $result->retval[0]->notiz_id; + $this->_deleteTag($notizId); + $return[$kurz_bz] = ['deleted' => $notizId]; + } + } + } + return success($return); + } + + private function _insertTag($typeId, $id, $tag, $von, $bis) + { + $resultInsert = $this->_ci->NotizModel->insert([ + 'titel' => 'TAG', + 'text' => 'AUTOMATED TAG', + 'verfasser_uid' => self::BATCHUSER, + 'erledigt' => false, + 'insertamum' => date('Y-m-d H:i:s'), + 'insertvon' => 'BatchJobTagAdd', + 'typ' => $tag, + 'start' => $von, + 'ende' => $bis + ]); + + if (isError($resultInsert)) { + return error('Error inserting tag for ' . $typeId . ': ' . $id); + } + + $notizId = $resultInsert->retval; + + $resultZuordnung = $this->_ci->NotizzuordnungModel->insert([ + 'notiz_id' => $notizId, + $typeId => $id + ]); + + if (isError($resultZuordnung)) { + return error('Error inserting relation for ' . $typeId . ': ' . $id); + } + + return $notizId; + } + + private function _updateTag($notiz_id, $von, $bis) + { + $resultUpdateNotiz = $this->_ci->NotizModel->update( + [ + 'notiz_id' => $notiz_id + ], + array( + 'updateamum' => date('Y-m-d H:i:s'), + 'updatevon' => 'BatchJobTagUpdate', + 'start' => $von, + 'ende' => $bis + )); + + + if (isError($resultUpdateNotiz)) + return error ('Error occurred during Update ' . $notiz_id); + + return $notiz_id; + } + + private function _deleteTag($notiz_id) + { + $result = $this->_ci->NotizzuordnungModel->delete([ + 'notiz_id' => $notiz_id + ]); + if (isError($result)) { + return error('Error occurred during delete Notizzuordnung ' . $notiz_id); + } + + $result = $this->_ci->NotizModel->delete([ + 'notiz_id' => $notiz_id + ]); + if (isError($result)) { + return error('Error occurred during delete Notiz ' . $notiz_id); + } + + return success([ + 'deleted' => $notiz_id + ]); + } + +} diff --git a/application/libraries/tags/CoreDoubleDegreeTagLib.php b/application/libraries/tags/CoreDoubleDegreeTagLib.php new file mode 100644 index 000000000..13b113a21 --- /dev/null +++ b/application/libraries/tags/CoreDoubleDegreeTagLib.php @@ -0,0 +1,81 @@ +ci = get_instance(); + $this->ci->load->model('codex/Mobilitaet_model', 'MobilitaetModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->MobilitaetModel->addJoin('bis.tbl_gsprogramm', 'gsprogramm_id'); + $this->ci->MobilitaetModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->MobilitaetModel-> loadWhere(array( + 'gsprogrammtyp_kurzbz' => 'Double', + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval; + + $doubledegree_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->start, + 'bis' => $item->ende + ]; + }, $data); + + return (object) array( + 'data' => $doubledegree_data, + 'typeId' => 'prestudent_id' + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->MobilitaetModel->addSelect('prestudent_id'); + $this->ci->MobilitaetModel->addSelect('start as von'); + $this->ci->MobilitaetModel->addSelect('ende as bis'); + + $this->ci->MobilitaetModel->addJoin('bis.tbl_gsprogramm', 'gsprogramm_id'); + $this->ci->MobilitaetModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->MobilitaetModel->loadWhere(array( + 'gsprogrammtyp_kurzbz' => 'Double', + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id + )); + + if(hasData($result)) + { + //array mit prestudent_id, von und bis + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreFiftyFiveTagLib.php b/application/libraries/tags/CoreFiftyFiveTagLib.php new file mode 100644 index 000000000..4e2738e8b --- /dev/null +++ b/application/libraries/tags/CoreFiftyFiveTagLib.php @@ -0,0 +1,81 @@ +ci = get_instance(); + $this->ci->load->model('person/Person_model', 'PersonModel'); + $this->ci-> load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'person_id' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $result = $this->ci->StudiensemesterModel->loadWhere(array( + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval[0]; + + $semVon = $data->start; + $semBis = $data->ende; + $result = $this->ci->PersonModel->getFiftyFivers($semVon, $semBis); + + $data = $result->retval; + $fiftyFiveData = array_map(function($item) { + return [ + 'id' => $item->person_id + ]; + }, $data); + + return (object) array( + 'data' => $fiftyFiveData, + 'typeId' => 'person_id' + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'person_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $person_id = $params['id']; + $typeId = $params['typeId']; + + + $result = $this->ci->StudiensemesterModel->loadWhere(array( + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval[0]; + + $semVon = $data->start; + $semBis = $data->ende; + $result = $this->ci->PersonModel->isFiftyFive($semVon, $semBis, $person_id); + + + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} + diff --git a/application/libraries/tags/CoreJgvTagLib.php b/application/libraries/tags/CoreJgvTagLib.php new file mode 100644 index 000000000..15e77dc98 --- /dev/null +++ b/application/libraries/tags/CoreJgvTagLib.php @@ -0,0 +1,64 @@ +ci = get_instance(); + $this->ci->load->model('person/Benutzerfunktion_model', 'BenutzerfunktionModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $result = $this->ci->BenutzerfunktionModel->getPrestudentsOfJgv($semester); + + $data = $result->retval; + + $jgv_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->datum_von, + 'bis' => $item->datum_bis + ]; + }, $data); + + return (object) array( + 'data' => $jgv_data, + 'typeId' => 'prestudent_id' + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $result = $this->ci->BenutzerfunktionModel->isJgv($semester, $prestudent_id); + + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreMissingZgvTagLib.php b/application/libraries/tags/CoreMissingZgvTagLib.php new file mode 100644 index 000000000..e25aed4cc --- /dev/null +++ b/application/libraries/tags/CoreMissingZgvTagLib.php @@ -0,0 +1,81 @@ +ci = get_instance(); + $this->ci->load->model('crm/Prestudent_model', 'PrestudentModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id'); + $this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id'); + $this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $result = $this->ci->PrestudentModel-> loadWhere(array( + 'bn.aktiv' => true, //check if necessary + 'zgvdatum' => null, + 'typ' => 'b', + 'studiensemester_kurzbz' => $semester + )); + + $data = $result->retval; + + $zgvmissing_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => null, + 'bis' => null + ]; + }, $data); + + return (object) array( + 'typeId' => 'prestudent_id', + 'data' => $zgvmissing_data + ); + + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->PrestudentModel->addJoin('public.tbl_prestudentstatus', 'prestudent_id'); + $this->ci->PrestudentModel->addJoin('public.tbl_benutzer bn', 'person_id'); + $this->ci->PrestudentModel->addJoin('public.tbl_studiengang', 'studiengang_kz'); + $result = $this->ci->PrestudentModel->loadWhere(array( + 'bn.aktiv' => true, //check if necessary + 'zgvdatum' => null, + 'typ' => 'b', + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id + )); + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreOutgoingTagLib.php b/application/libraries/tags/CoreOutgoingTagLib.php new file mode 100644 index 000000000..904839dee --- /dev/null +++ b/application/libraries/tags/CoreOutgoingTagLib.php @@ -0,0 +1,63 @@ +ci = get_instance(); + $this->ci->load->model('codex/Bisio_model', 'BisioModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $result = $this->ci->BisioModel->getOutgoingsOfSemester($semester); + + $data = $result->retval; + + $outgoing_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->von, + 'bis' => $item->bis + ]; + }, $data); + + return (object) array( + 'data' => $outgoing_data, + 'typeId' => 'prestudent_id', + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $result = $this->ci->BisioModel->isPrestudentOutgoing($semester, $prestudent_id); + + if (hasData($result)) { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CorePrewiederholerTagLib.php b/application/libraries/tags/CorePrewiederholerTagLib.php new file mode 100644 index 000000000..8b7037b07 --- /dev/null +++ b/application/libraries/tags/CorePrewiederholerTagLib.php @@ -0,0 +1,76 @@ +ci = get_instance(); + $this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $result = $this->ci->PrestudentstatusModel-> loadWhere(array( + 'statusgrund_id' => 15, + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval; + + $prewiederholer_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->start, + 'bis' => $item->ende + ]; + }, $data); + + return (object) array( + 'data' => $prewiederholer_data, + 'typeId' => 'prestudent_id', + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->PrestudentstatusModel->addSelect('prestudent_id'); + $this->ci->PrestudentstatusModel->addSelect('start as von'); + $this->ci->PrestudentstatusModel->addSelect('ende as bis'); + + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->PrestudentstatusModel->loadWhere(array( + 'statusgrund_id' => 15, + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id + )); + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreStbErhoehtTagLib.php b/application/libraries/tags/CoreStbErhoehtTagLib.php new file mode 100644 index 000000000..886aff468 --- /dev/null +++ b/application/libraries/tags/CoreStbErhoehtTagLib.php @@ -0,0 +1,79 @@ +ci = get_instance(); + $this->ci->load->model('crm/Konto_model', 'KontoModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->KontoModel->addJoin('public.tbl_prestudent', 'person_id'); + $this->ci->KontoModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->KontoModel-> loadWhere(array( + 'buchungstyp_kurzbz' => 'StudiengebuehrErhoeht', + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval; + + $konto_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->start, + 'bis' => $item->ende + ]; + }, $data); + + return (object) array( + 'data' => $konto_data, + 'typeId' => 'prestudent_id' + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->KontoModel->addSelect('prestudent_id'); + $this->ci->KontoModel->addSelect('start as von'); + $this->ci->KontoModel->addSelect('ende as bis'); + $this->ci->KontoModel->addJoin('public.tbl_prestudent', 'person_id'); + $this->ci->KontoModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->KontoModel-> loadWhere(array( + 'buchungstyp_kurzbz' => 'StudiengebuehrErhoeht', + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id + )); + + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreUnterbrecherTagLib.php b/application/libraries/tags/CoreUnterbrecherTagLib.php new file mode 100644 index 000000000..ddf8f33cd --- /dev/null +++ b/application/libraries/tags/CoreUnterbrecherTagLib.php @@ -0,0 +1,76 @@ +ci = get_instance(); + $this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->PrestudentstatusModel-> loadWhere(array( + 'status_kurzbz' => 'Unterbrecher', + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval; + + $unterbrecher_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->start, + 'bis' => $item->ende + ]; + }, $data); + + return (object) array( + 'data' => $unterbrecher_data, + 'typeId' => 'prestudent_id' + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->PrestudentstatusModel->addSelect('prestudent_id'); + $this->ci->PrestudentstatusModel->addSelect('start as von'); + $this->ci->PrestudentstatusModel->addSelect('ende as bis'); + + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $result = $this->ci->PrestudentstatusModel-> loadWhere(array( + 'status_kurzbz' => 'Unterbrecher', + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id + )); + + if(hasData($result)) + { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CoreWiederholerTagLib.php b/application/libraries/tags/CoreWiederholerTagLib.php new file mode 100644 index 000000000..8f4eb1dd7 --- /dev/null +++ b/application/libraries/tags/CoreWiederholerTagLib.php @@ -0,0 +1,76 @@ +ci = get_instance(); + $this->ci->load->model('crm/Prestudentstatus_model', 'PrestudentstatusModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $result = $this->ci->PrestudentstatusModel-> loadWhere(array( + 'statusgrund_id' => 16, + 'studiensemester_kurzbz' => $semester + )); + $data = $result->retval; + + $wiederholer_data = array_map(function($item) { + return [ + 'id' => $item->prestudent_id, + 'von' => $item->start, + 'bis' => $item->ende + ]; + }, $data); + + return (object) array( + 'typeId' => 'prestudent_id', + 'data' => $wiederholer_data + ); + } + + public function isCriteriaSetFor(array $params) + { + if ( !isset($params['id'], $params['studiensemester_kurzbz'], $params['typeId']) || $params['typeId'] !== 'prestudent_id') + return false; + + $semester = $params['studiensemester_kurzbz']; + $prestudent_id = $params['id']; + + $this->ci->PrestudentstatusModel->addSelect('prestudent_id'); + $this->ci->PrestudentstatusModel->addSelect('start as von'); + $this->ci->PrestudentstatusModel->addSelect('ende as bis'); + + $this->ci->PrestudentstatusModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + + $result = $this->ci->PrestudentstatusModel->loadWhere(array( + 'statusgrund_id' => 16, + 'studiensemester_kurzbz' => $semester, + 'prestudent_id' => $prestudent_id, + )); + + if(hasData($result)) + { + return $result; + } + else + return null; + } +} diff --git a/application/models/codex/Bisio_model.php b/application/models/codex/Bisio_model.php index 1cff1dc54..055b8e4ea 100644 --- a/application/models/codex/Bisio_model.php +++ b/application/models/codex/Bisio_model.php @@ -44,4 +44,56 @@ class Bisio_model extends DB_Model else return success("Bisio not found"); } + + /** + * Gets outgoing students of certain Semester + * @param String studiensemester_kurzbz + * @return array of prestudent_ids + */ + public function getOutgoingsOfSemester($studiensemester_kurzbz) + { + $query = " + SELECT DISTINCT ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis + FROM bis.tbl_bisio + JOIN public.tbl_student USING (student_uid) + JOIN public.tbl_prestudent ps USING (prestudent_id) + JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id) + JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz) + WHERE ss.studiensemester_kurzbz = ? + AND ( + tbl_bisio.von <= ss.ende + AND ( + tbl_bisio.bis >= ss.start + OR tbl_bisio.bis IS NULL + ) + ) + "; + + return $this->execQuery($query, array($studiensemester_kurzbz)); + } + + public function isPrestudentOutgoing($studiensemester_kurzbz, $prestudent_id) + { + $query = " + SELECT + ps.prestudent_id, tbl_bisio.von, tbl_bisio.bis + FROM bis.tbl_bisio + JOIN public.tbl_student USING (student_uid) + JOIN public.tbl_prestudent ps USING (prestudent_id) + JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id) + JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz) + WHERE ss.studiensemester_kurzbz = ? + --AND pss.status_kurzbz = 'Student' + AND ( + tbl_bisio.von <= ss.ende + AND ( + tbl_bisio.bis >= ss.start + OR tbl_bisio.bis IS NULL + ) + ) + AND ps.prestudent_id = ? + "; + + return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id)); + } } diff --git a/application/models/person/Benutzerfunktion_model.php b/application/models/person/Benutzerfunktion_model.php index dff422b7d..faf3592fd 100644 --- a/application/models/person/Benutzerfunktion_model.php +++ b/application/models/person/Benutzerfunktion_model.php @@ -350,5 +350,64 @@ class Benutzerfunktion_model extends DB_Model return success($funktionJson); } + /** + * Gets all Prestudents with details for a given Benutzerfunktion and optionally semester + * + * @param String $studiensemester_kurzbz + * @return object |null + */ + public function getPrestudentsOfJgv($semester) + { + $query = " + SELECT DISTINCT ps.prestudent_id, bf.datum_von, bf.datum_bis + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_benutzer bn USING (uid) + JOIN public.tbl_prestudent ps USING (person_id) + JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id) + JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz) + WHERE ss.studiensemester_kurzbz = ? + AND bf.funktion_kurzbz = 'jgv' + AND ( + bf.datum_von <= ss.ende + AND ( + bf.datum_bis >= ss.start + OR bf.datum_bis IS NULL + ) + ) + "; + + return $this->execQuery($query, array($semester)); + } + + /** + * Checks if a certain prestudent has the Benutzerfunktion jgv for a certain semester + * + * @param String $studiensemester_kurzbz + * @param $prestudent_id + * @return object |null + */ + public function isJgv($semester, $prestudent_id) + { + $query = " + SELECT ps.prestudent_id, ss.start as von, ss.ende as bis + FROM public.tbl_benutzerfunktion bf + JOIN public.tbl_benutzer bn USING (uid) + JOIN public.tbl_prestudent ps USING (person_id) + JOIN public.tbl_prestudentstatus pss ON (ps.prestudent_id = pss.prestudent_id) + JOIN public.tbl_studiensemester ss ON (pss.studiensemester_kurzbz = ss.studiensemester_kurzbz) + WHERE ss.studiensemester_kurzbz = ? + AND bf.funktion_kurzbz = 'jgv' + AND ( + bf.datum_von <= ss.ende + AND ( + bf.datum_bis >= ss.start + OR bf.datum_bis IS NULL + ) + ) + AND ps.prestudent_id = ? + "; + + return $this->execQuery($query, array($semester, $prestudent_id)); + } } diff --git a/application/models/person/Notiz_model.php b/application/models/person/Notiz_model.php index 64fce8944..1dc09caaf 100644 --- a/application/models/person/Notiz_model.php +++ b/application/models/person/Notiz_model.php @@ -296,4 +296,59 @@ class Notiz_model extends DB_Model return $this->loadWhere(array('anrechnung_id' => $anrechnung_id)); } + + /** + * check if a given Tag for a certain notizzuordnung id is valid + * + * @param $tag typ_kurzbz to check + * @param $typeId typeId to check + * @param $id id to check + * @param $von start of time period or NULL + * @param $bis end of time period or NULL + * + * @return array + */ + public function checkIfExistingTag($tag, $typeId, $id, $von=null, $bis=null) + { + $query = " + SELECT * + FROM public.tbl_notiz + JOIN public.tbl_notizzuordnung nz USING (notiz_id) + WHERE typ = ? + AND {$typeId} = ? + AND ( + start IS NULL + OR ende IS NULL + OR (start <= ? AND ende >= ?) + ) + "; + + return $this->execQuery($query, [$tag, $id, $bis, $von]); + } + + /** + * returns all existing tags of a certain tag within a time period + * + * @param $tag typ_kurzbz of tag + * @param $von start of time period or NULL + * @param $bis end of time period or NULL + * + * @return array + */ + public function getAllTags($tag, $von=null, $bis=null) + { + $query = " + SELECT * + FROM public.tbl_notiz + JOIN public.tbl_notizzuordnung nz USING (notiz_id) + WHERE typ = ? + AND ( + start IS NULL + OR ende IS NULL + OR (start <= ? AND ende >= ?) + ); + "; + + return $this->execQuery($query, array($tag, $bis, $von)); + } } diff --git a/application/models/person/Person_model.php b/application/models/person/Person_model.php index e02229624..c893c51de 100644 --- a/application/models/person/Person_model.php +++ b/application/models/person/Person_model.php @@ -453,4 +453,33 @@ class Person_model extends DB_Model return $this->execReadOnlyQuery($qry, [$person_id]); } + + //just a test function for a person_id tag + //alle personen die innerhalb dieses Zeitraumens 55 werden + public function getFiftyFivers($von, $bis) + { + $qry = " + SELECT + p.person_id + FROM public.tbl_person p + WHERE p.gebdatum >= DATE ? - INTERVAL '55 years' + AND p.gebdatum <= DATE ? - INTERVAL '55 years'; + "; + return $this->execReadOnlyQuery($qry, [$von, $bis]); + } + + //just a test function for a person_id tag + //check if Person gets 55 in this time + public function isFiftyFive($von, $bis, $person_id) + { + $qry = " + SELECT + p.person_id + FROM public.tbl_person p + WHERE p.gebdatum >= DATE ? - INTERVAL '55 years' + AND p.gebdatum <= DATE ? - INTERVAL '55 years' + AND p.persond_id = ?; + "; + return $this->execReadOnlyQuery($qry, [$von, $bis, $person_id]); + } } diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index 7b53cbf5d..4203aa571 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -132,7 +132,11 @@ if ($cis === true) generateCSSsInclude(defined('CIS4') ? 'public/css/cis4.css' : 'public/css/cis_bs5.css'); //Tags - if ($tags === true) generateCSSsInclude('public/css/tags.css'); + if ($tags === true) + { + generateCSSsInclude('public/css/tags.css'); + generateCSSsIncludeIfExtensionCssExists('tags.css'); + } $extapphelper = ExtendableAppsHelper::getInstance(); $extapphelper->init($customCSSs, $customJSs, $customJSModules); diff --git a/public/css/tags.css b/public/css/tags.css index e92f415b2..995a7d43a 100644 --- a/public/css/tags.css +++ b/public/css/tags.css @@ -75,6 +75,10 @@ text-decoration: line-through; } +.tag_auto { + border: 1px dashed white; +} + .display_all { background-color: darkgrey !important; border: none; diff --git a/public/js/api/factory/stv/tag.js b/public/js/api/factory/stv/tag.js index 29675f6d4..4a22a009e 100644 --- a/public/js/api/factory/stv/tag.js +++ b/public/js/api/factory/stv/tag.js @@ -51,4 +51,20 @@ export default { params: data }; }, + + getAllTagsPrestudent(prestudent_id){ + return { + method: 'get', + url: 'api/frontend/v1/stv/Tags/getAllTags', + params: prestudent_id + }; + }, + + rebuildTagsforTypeId(data){ + return { + method: 'post', + url: 'api/frontend/v1/stv/Tags/rebuildTagsForTypeId/', + params: data + }; + } }; \ No newline at end of file diff --git a/public/js/components/DetailHeader/DetailHeader.js b/public/js/components/DetailHeader/DetailHeader.js index ada6034fc..e129c843c 100644 --- a/public/js/components/DetailHeader/DetailHeader.js +++ b/public/js/components/DetailHeader/DetailHeader.js @@ -2,12 +2,16 @@ import ApiDetailHeader from "../../api/factory/detailHeader.js"; import ApiHandleFoto from "../../api/factory/fotoHandling.js"; import ModalUploadFoto from "./Modal/UploadFoto.js"; import PvSkeleton from "../../../../index.ci.php/public/js/components/primevue/skeleton/skeleton.esm.min.js"; +import CoreTag from "../Tag/Tag.js"; +import ApiTag from "../../api/factory/stv/tag.js"; +import { idTagFormatter } from "../Tag/tagFormatter.js"; export default { name: 'DetailHeader', components: { ModalUploadFoto, - PvSkeleton + PvSkeleton, + CoreTag }, props: { headerData: { @@ -50,6 +54,20 @@ export default { default: false } }, + inject: { + tagsEnabled: { + from: 'configStvTagsEnabled', + default: false + }, + currentSemester: { + from: 'currentSemester', + required: true + }, + lists: { + from: 'lists', + required: true + }, + }, computed: { appRoot() { return FHC_JS_DATA_STORAGE_OBJECT.app_root; @@ -70,6 +88,15 @@ export default { }, hasTileUIDSlot() { return !!this.$slots.uid + }, + prestudentIds() { + if (this.headerData[0].prestudent_id) + { + return [this.headerData[0].prestudent_id]; + } + }, + semesterDates(){ + return this.lists.studiensemester?.find(item => item.studiensemester_kurzbz === this.currentSemester) || {}; } }, created(){ @@ -77,6 +104,11 @@ export default { if (!this.headerData) { throw new Error('[DetailHeader] "headerData" is required.') } + + if(this.tagsEnabled) { + this.loadTagsAndRender(this.headerData[0].prestudent_id); + } + } else if (this.typeHeader === 'mitarbeiter') { if (!this.person_id || !this.mitarbeiter_uid || !this.domain) { throw new Error( @@ -100,7 +132,12 @@ export default { if (this.typeHeader === 'student' && newVal?.length) { this.getSemesterStati(newVal[0].prestudent_id); } + + if(this.tagsEnabled) { + this.loadTagsAndRender(this.headerData[0].prestudent_id); + } }, + deep: true, immediate: true }, }, @@ -114,7 +151,10 @@ export default { semesterStatiLoading: false, leitungOrgLoading: false, departmentDataLoading: false, - headerDataMaLoading: false + headerDataMaLoading: false, + tagEndpoint: ApiTag, + tagData: null, + rebuildData: null, }; }, methods: { @@ -239,7 +279,59 @@ export default { { this.noCurrentStatus = false; } - } + }, + //methods tags + async loadTagsAndRender(prestudent_id) { + await this.getAllTags(prestudent_id); + + const container = idTagFormatter( + prestudent_id, + this.tagData, + this.$refs.tagComponent, + 'prestudent_id', + this.semesterDates.start, + this.semesterDates.ende + ); + + this.$refs.tagWrapper.innerHTML = ''; + this.$refs.tagWrapper.appendChild(container); + }, + getAllTags(prestudent_id){ + return this.$api + .call(ApiTag.getAllTagsPrestudent({prestudent_id})) + .then(result => { + this.tagData = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + }, + addedTag(addedTag) + { + this.reload(); + }, + deletedTag(id) + { + this.reload(); + }, + updatedTag(updatedTag) + { + this.reload(); + }, + rebuildPrestudentTags(){ + const params = { + id : this.headerData[0].prestudent_id, + typeId: 'prestudent_id', + sem: this.currentSemester + }; + + return this.$api + .call(ApiTag.rebuildTagsforTypeId(params)) + .then(result => { + this.rebuildData = result.data; + console.log("Rebuild manually triggered"); + this.reload(); + }) + .catch(this.$fhcAlert.handleSystemError); + }, }, template: `
@@ -304,6 +396,25 @@ export default { , {{headerData[0].titelpost}} + +
+ + {{currentSemester}} +
unruly
@@ -353,6 +464,7 @@ export default { {{headerData[0].statusofsemester}} +
diff --git a/public/js/components/Stv/Studentenverwaltung/List.js b/public/js/components/Stv/Studentenverwaltung/List.js index 196ea1d8c..51c6faf5b 100644 --- a/public/js/components/Stv/Studentenverwaltung/List.js +++ b/public/js/components/Stv/Studentenverwaltung/List.js @@ -318,6 +318,7 @@ export default { }, }, created: function() { + if(this.tagsEnabled) { const coltags = { title: 'Tags', @@ -337,7 +338,7 @@ export default { if (n !== o && o !== undefined && this.$refs.table.tableBuilt) { this.translateTabulator(); } - } + }, }, methods: { translateTabulator() { @@ -423,10 +424,6 @@ export default { this.lastSelected = this.selected; this.$emit('update:selected', data); } - - //for tags - this.selectedRows = this.$refs.table.tabulator.getSelectedRows(); - this.selectedColumnValues = this.selectedRows.filter(row => row.getData().prestudent_id !== undefined && row.getData().prestudent_id).map(row => row.getData().prestudent_id); }, autoSelectRows(data) { if (Array.isArray(this.lastSelected) && this.lastSelected.length){ @@ -689,22 +686,23 @@ export default { @updated="updatedTag" zuordnung_typ="prestudent_id" > - - diff --git a/public/js/components/Tag/tagFormatter.js b/public/js/components/Tag/tagFormatter.js new file mode 100644 index 000000000..4040111b9 --- /dev/null +++ b/public/js/components/Tag/tagFormatter.js @@ -0,0 +1,111 @@ +export function idTagFormatter (id, tagData, tagComponent, typeId, semesterStart=null, semesterEnd=null) +{ + if (!id) return; + + const hasSemesterFilter = !!(semesterStart && semesterEnd); + + const semStart = hasSemesterFilter ? new Date(semesterStart) : null; + const semEnd = hasSemesterFilter ? new Date(semesterEnd) : null; + + const parsedTags = tagData.map(tag => ({ + id: tag.notiz_id, + typ_kurzbz: tag.titel?.toLowerCase(), + beschreibung: tag.bezeichnung, + notiz: tag.text || "", + style: tag.style, + done: tag.done, + automatisiert: tag.automatisiert, + typeId: id, + validFrom: tag.start ? new Date(tag.start) : null, + validTo: tag.ende ? new Date(tag.ende) : null + })); + + const isInSemester = (tag) => { + if (!hasSemesterFilter) return true; + + if (!tag.validFrom && !tag.validTo) return true; + + if (!tag.validFrom && !tag.validTo) return true; + + if (tag.validFrom && tag.validTo) { + return tag.validFrom <= semEnd && tag.validTo >= semStart; + } + + if (tag.validFrom && !tag.validTo) { + return tag.validFrom <= semEnd; + } + + if (!tag.validFrom && tag.validTo) { + return tag.validTo >= semStart; + } + + return false; + }; + + let container = document.createElement('div'); + container.className = "d-flex gap-1"; + + let maxVisibleTags = 5; + let expanded = false; + const renderTags = () => { + container.innerHTML = ''; + + let filtered = parsedTags + .filter(t => t != null) + .filter(isInSemester); + + filtered.sort((a, b) => { + let adone = a.done ? 1 : 0; + let bdone = b.done ? 1 : 0; + + if (adone !== bdone) return adone - bdone; + return b.id - a.id; + }); + + const tagsToShow = expanded + ? filtered + : filtered.slice(0, maxVisibleTags); + + tagsToShow.forEach(tag => { + let tagElement = document.createElement('span'); + + if(tag.automatisiert) + tagElement.innerHTML = " " + tag.beschreibung; + else + tagElement.innerText = tag.beschreibung; + tagElement.title = tag.notiz; + tagElement.className = "tag " + tag.style; + + if (tag.done) { + tagElement.className += " tag_done"; + } + if (tag.automatisiert) + tagElement.className += " tag_auto"; + + tagElement.addEventListener('click', (event) => { + event.stopPropagation(); + event.preventDefault(); + tagComponent.editTag(tag.id); + }); + + container.appendChild(tagElement); + }); + + if (filtered.length > maxVisibleTags) { + let toggle = document.createElement('button'); + toggle.innerText = (expanded ? '- ' : '+ ') + (filtered.length - maxVisibleTags); + toggle.className = "display_all"; + + toggle.addEventListener('click', () => { + expanded = !expanded; + renderTags(); + }); + + container.appendChild(toggle); + } + }; + + renderTags(); + + return container; +} \ No newline at end of file diff --git a/public/js/tabulator/formatter/tags.js b/public/js/tabulator/formatter/tags.js index 0d2f5004c..367a8a5fb 100644 --- a/public/js/tabulator/formatter/tags.js +++ b/public/js/tabulator/formatter/tags.js @@ -1,12 +1,24 @@ export function tagFormatter(cell, tagComponent) { + const mappedData = tagComponent.tags.map(tag => ({ + typ_kurzbz: tag.tag_typ_kurzbz, + automatisiert: tag.automatisiert + })); + + let tags = cell.getValue(); if (!tags) return; let container = document.createElement('div'); container.className = "d-flex gap-1"; - let parsedTags = JSON.parse(tags); + let parsedTags = []; + if (typeof tags === 'string') { + parsedTags = JSON.parse(tags); + } else if (Array.isArray(tags)) { + parsedTags = tags; + } + let maxVisibleTags = 2; const rowData = cell.getRow().getData(); @@ -38,10 +50,17 @@ export function tagFormatter(cell, tagComponent) tagElement.className = "tag " + tag.style; if (tag.done) tagElement.className += " tag_done"; + const tagDef = mappedData.find(t => t.typ_kurzbz === tag.typ_kurzbz); + + if (!tagDef && tag.typ_kurzbz?.includes("_auto") || tagDef?.automatisiert) { + tagElement.className += " tag_auto"; + tagElement.innerHTML = " " + tag.beschreibung; + } + tagElement.addEventListener('click', (event) => { event.stopPropagation(); event.preventDefault(); - tagComponent.editTag(tag.id); + tagComponent.editTag(tag.id) }); container.appendChild(tagElement); diff --git a/system/dbupdate_3.4.php b/system/dbupdate_3.4.php index 8b6af9f2d..4afdc8227 100644 --- a/system/dbupdate_3.4.php +++ b/system/dbupdate_3.4.php @@ -94,6 +94,7 @@ require_once('dbupdate_3.4/71399_dashboard_update_widget_paths.php'); require_once('dbupdate_3.4/71645_studvw_messagetab_ladezeit.php'); require_once('dbupdate_3.4/71566_studienordnungsdokument_neuer_organisationseinheitstyp_programm.php'); require_once('dbupdate_3.4/70376_lohnguide.php'); +require_once('dbupdate_3.4/75959_StudVw_Automatische_Tags.php'); // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; diff --git a/system/dbupdate_3.4/75959_StudVw_Automatische_Tags.php b/system/dbupdate_3.4/75959_StudVw_Automatische_Tags.php new file mode 100644 index 000000000..c75d0ce14 --- /dev/null +++ b/system/dbupdate_3.4/75959_StudVw_Automatische_Tags.php @@ -0,0 +1,125 @@ +db_query("SELECT taglib FROM public.tbl_notiz_typ LIMIT 1")) +{ + $qry = 'ALTER TABLE public.tbl_notiz_typ ADD COLUMN taglib character varying(32);'; + + if(!$db->db_query($qry)) + echo ' public.tbl_notiz_typ '.$db->db_last_error().'
'; + else + echo '
public.tbl_notiz_typ: Neue Spalte taglib hinzugefügt'; +} + +//automatic tags anlegen +$tags = [ + [ + 'typ_kurzbz' => 'wh_auto', + 'bezeichnung' => '{Wiederholer, repeater}', + 'style' => 'tag_dark_grey', + 'prioritaet' => 11, + 'taglib' => 'tags/CoreWiederholerTagLib' + ], + [ + 'typ_kurzbz' => 'dd_auto', + 'bezeichnung' => '{DoubleDegree, DoubleDegree}', + 'style' => 'tag_braun', + 'prioritaet' => 10, + 'taglib' => 'tags/CoreDoubleDegreeTagLib' + ], + [ + 'typ_kurzbz' => 'out_auto', + 'bezeichnung' => '{Outgoing, Outgoing}', + 'style' => 'tag_limette', + 'prioritaet' => 12, + 'taglib' => 'tags/CoreOutgoingTagLib' + ], + [ + 'typ_kurzbz' => 'prewh_auto', + 'bezeichnung' => '{Pre-Wiederholer, pre-repeater}', + 'style' => 'tag_light_grey', + 'prioritaet' => 13, + 'taglib' => 'tags/CorePrewiederholerTagLib' + ], + [ + 'typ_kurzbz' => 'zgv_auto', + 'bezeichnung' => '{ZGV offen, ZGV missing}', + 'style' => 'tag_lavendel', + 'prioritaet' => 14, + 'taglib' => 'tags/CoreMissingZgvTagLib' + ], + [ + 'typ_kurzbz' => 'unterbrecher_auto', + 'bezeichnung' => '{Unterbrecher, Interrupter}', + 'style' => 'tag_blau', + 'prioritaet' => 15, + 'taglib' => 'tags/CoreUnterbrecherTagLib' + ], + [ + 'typ_kurzbz' => 'stbtr_erh_auto', + 'bezeichnung' => '{erh.Studienbeitrag, Incr. Tuition Fees}', + 'style' => 'tag_pfirsich', + 'prioritaet' => 16, + 'taglib' => 'tags/CoreStbErhoehtTagLib' + ], + [ + 'typ_kurzbz' => 'jgv_auto', + 'bezeichnung' => '{JGV, Year Group Representative}', + 'style' => 'tag_gelb', + 'prioritaet' => 17, + 'taglib' => 'tags/CoreJgvTagLib' + ], + +]; + +foreach ($tags as $tag) { + + $checkQry = " + SELECT 1 + FROM public.tbl_notiz_typ + WHERE typ_kurzbz = '".$tag['typ_kurzbz']."' + "; + + if ($result = $db->db_query($checkQry)) { + + if ($db->db_num_rows($result) == 0) { + + $qry = " + INSERT INTO public.tbl_notiz_typ + ( + typ_kurzbz, + bezeichnung_mehrsprachig, + automatisiert, + aktiv, + tag, + style, + vorrueckung, + prioritaet, + taglib + ) + VALUES + ( + '".$tag['typ_kurzbz']."', + '".$tag['bezeichnung']."', + true, + true, + true, + '".$tag['style']."', + false, + '".$tag['prioritaet']."', + '".$tag['taglib']."' + ) + "; + + if (!$db->db_query($qry)) + { + echo 'public.tbl_notiz_typ: '. $tag['typ_kurzbz']. ' '. $db->db_last_error().'
'; + } + else + { + echo '
public.tbl_notiz_typ: Automatic Tag '.$tag['typ_kurzbz'].' hinzugefuegt'; + } + } + } +}