diff --git a/application/config/stv.php b/application/config/stv.php index 91d84658d..49f7da243 100644 --- a/application/config/stv.php +++ b/application/config/stv.php @@ -171,6 +171,8 @@ $config['stv_prestudent_tags'] = [ 'unterbrecher_auto' => ['readonly' => true], 'stbtr_erh_auto' => ['readonly' => true], 'jgv_auto' => ['readonly' => true], + 'in_auto' => ['readonly' => true], + 'preabbr_auto' => ['readonly' => true], ]; $config['userAutomatedTags'] = 'sftest'; diff --git a/application/core/Tag_Controller.php b/application/core/Tag_Controller.php index 9d2f4cf6a..c4b6edb81 100644 --- a/application/core/Tag_Controller.php +++ b/application/core/Tag_Controller.php @@ -349,16 +349,27 @@ class Tag_Controller extends FHCAPI_Controller public function rebuildTagsForTypeId() { - $id = $this->input->post('id'); + $ids = $this->input->post('ids'); $typeId = $this->input->post('typeId'); $semester = $this->input->post('sem'); - $result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester); + $idsSuccess = []; + $idsError = []; + $outputResult = []; - if (isError($result)) - return error ('Error occurred during updateAutomatedTags'); + foreach ($ids as $id) + { + $result = $this->taglib->rebuildTagsForTypeId($typeId, $id, $semester); - $this->terminateWithSuccess($result); + if (isError($result)) + $idsError[] = $id; + else + $idsSuccess[] = $id; + + $outputResult[] = $result; + } + + $this->terminateWithSuccess([$outputResult, $idsSuccess, $idsError]); } private function _setAuthUID() @@ -401,4 +412,4 @@ class Tag_Controller extends FHCAPI_Controller )); } -} \ No newline at end of file +} diff --git a/application/libraries/tags/CoreIncomingTagLib.php b/application/libraries/tags/CoreIncomingTagLib.php new file mode 100644 index 000000000..26d7dad0b --- /dev/null +++ b/application/libraries/tags/CoreIncomingTagLib.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->getIncomingsOfSemester($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->isPrestudentIncoming($semester, $prestudent_id); + + if (hasData($result)) { + return $result; + } + else + return null; + } + +} diff --git a/application/libraries/tags/CorePreabbrecherTagLib.php b/application/libraries/tags/CorePreabbrecherTagLib.php new file mode 100644 index 000000000..41712ac3b --- /dev/null +++ b/application/libraries/tags/CorePreabbrecherTagLib.php @@ -0,0 +1,80 @@ +ci = get_instance(); + $this->ci->load->model('education/Studierendenantrag_model', 'StudierendenantragModel'); + } + + public function getZuordnungIds(array $params) + { + if(!isset($params['studiensemester_kurzbz'])) + { + return (object) array( + 'idArray' => [] + ); + } + + $semester = $params['studiensemester_kurzbz']; + + $this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG); + $this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester); + $result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([ + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED + ]); + + $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->StudierendenantragModel->addSelect('prestudent_id'); + $this->ci->StudierendenantragModel->addSelect('start as von'); + $this->ci->StudierendenantragModel->addSelect('ende as bis'); + + $this->ci->StudierendenantragModel->addJoin('public.tbl_studiensemester', 'studiensemester_kurzbz'); + $this->ci->StudierendenantragModel->db->where_in('typ', self::TYP_ABMELDUNG); + $this->ci->StudierendenantragModel->db->where('studiensemester_kurzbz', $semester); + $this->ci->StudierendenantragModel->db->where('prestudent_id', $prestudent_id); + $result = $this->ci->StudierendenantragModel->getWithLastStatusWhere([ + 'studierendenantrag_statustyp_kurzbz' => Studierendenantragstatus_model::STATUS_CREATED + ]); + + 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 9a9fd37fb..972661c8b 100644 --- a/application/models/codex/Bisio_model.php +++ b/application/models/codex/Bisio_model.php @@ -73,6 +73,34 @@ class Bisio_model extends DB_Model return $this->execQuery($query, array($studiensemester_kurzbz)); } + /** + * Gets incoming students of certain Semester + * @param String studiensemester_kurzbz + * @return array of prestudent_ids + */ + public function getIncomingsOfSemester($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 nation_code = 'A' + 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 = " @@ -97,4 +125,29 @@ class Bisio_model extends DB_Model return $this->execQuery($query, array($studiensemester_kurzbz, $prestudent_id)); } + + public function isPrestudentIncoming($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 nation_code = 'A' + 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/views/templates/FHC-Footer.php b/application/views/templates/FHC-Footer.php index d2eb229f1..66ed4bd51 100644 --- a/application/views/templates/FHC-Footer.php +++ b/application/views/templates/FHC-Footer.php @@ -154,6 +154,7 @@ generateJSsInclude('vendor/npm-asset/primevue/confirmdialog/confirmdialog.min.js'); generateJSsInclude('vendor/npm-asset/primevue/confirmationservice/confirmationservice.min.js'); generateJSsInclude('vendor/npm-asset/primevue/tieredmenu/tieredmenu.min.js'); + generateJSsInclude('vendor/npm-asset/primevue/progressbar/progressbar.min.js'); } if($vuedatepicker11) generateJSsInclude('vendor/vuejs/vuedatepicker_js11/vue-datepicker.iife.js'); diff --git a/public/css/tags.css b/public/css/tags.css index 3b3377d5d..0634c5ce3 100644 --- a/public/css/tags.css +++ b/public/css/tags.css @@ -91,6 +91,15 @@ color: black; } +.tag_skyblue { + background-color: #90D5FF; + color: black; +} +.tag_blush { + background-color: #A83E3E; + color: white; +} + .tag_done { text-decoration: line-through; } diff --git a/public/js/components/DetailHeader/DetailHeader.js b/public/js/components/DetailHeader/DetailHeader.js index 2a5987a9b..396e1245a 100644 --- a/public/js/components/DetailHeader/DetailHeader.js +++ b/public/js/components/DetailHeader/DetailHeader.js @@ -323,8 +323,10 @@ export default { this.reload(); }, rebuildPrestudentTags(){ + const id = [this.headerData[0].prestudent_id]; + const params = { - id : this.headerData[0].prestudent_id, + ids: id, typeId: 'prestudent_id', sem: this.currentSemester }; diff --git a/public/js/components/Stv/Studentenverwaltung/List.js b/public/js/components/Stv/Studentenverwaltung/List.js index 095e34d3f..adeb36bec 100644 --- a/public/js/components/Stv/Studentenverwaltung/List.js +++ b/public/js/components/Stv/Studentenverwaltung/List.js @@ -11,6 +11,7 @@ import { } from "../../../tabulator/filters/extendedHeaderFilter.js"; import { addTagInTable, deleteTagInTable, updateTagInTable } from "../../../../js/helpers/TagHelper.js"; import { tagFormatter } from "../../../../js/tabulator/formatter/tags.js"; +import ModalLoading from "./List/ModalLoading.js"; import ApiTag from "../../../api/factory/stv/tag.js"; import ListFilter from './List/Filter.js'; @@ -30,7 +31,8 @@ export default { CoreFilterCmpt, ListNew, CoreTag, - ListFilter + ListFilter, + ModalLoading }, directives: { draggable @@ -218,7 +220,12 @@ export default { oldScrollUrl: '', oldScrollLeft: 0, oldScrollTop: 0, - allPrestudents: [] + allPrestudents: [], + rebuildData: [], + isLoading: false, + progress: -1, + total: -1, + processed: -1 } }, computed: { @@ -658,6 +665,73 @@ export default { this.oldScrollUrl = this.$refs.table.tabulator.getAjaxUrl(); } }, + async rebuild(selected){ + const maxbulksize = 25; + const minbulksize = 5; + let bulksize = minbulksize; + this.isLoading = true; + let prestudentIds = []; + if(!selected.length) + prestudentIds = this.$refs.table.tabulator + .getData() + .map(row => row.prestudent_id); + else + prestudentIds = selected.map(item => item.prestudent_id); + + this.progress = 0; + this.total = prestudentIds.length; + this.processed = 0; + this.rebuildData = [ + [], + [], + [] + ]; + + this.showModal(); + + while(this.processed < this.total) + { + let iteration_prestudentIds = prestudentIds.slice( + this.processed, + (this.processed + bulksize) + ); + const params = { + ids: iteration_prestudentIds, + typeId: 'prestudent_id', + sem: this.studiensemesterKurzbz + }; + + try + { + const result = await this.$api.call(ApiTag.rebuildTagsforTypeId(params)); + this.rebuildData[1] = [...this.rebuildData[1], ...result.data[1]]; + this.rebuildData[2] = [...this.rebuildData[2], ...result.data[2]]; + } + catch(error) { + this.$fhcAlert.handleSystemError(error); + }; + + this.processed += iteration_prestudentIds.length; + this.progress = Math.round(this.processed * 100 / this.total); + + bulksize = bulksize * 2; + if(bulksize > maxbulksize) bulksize = maxbulksize; + } + + if(this.rebuildData[1].length > 0) + { + this.$fhcAlert.alertSuccess(this.$p.t('tag', 'alertSuccessRebuild', { count: this.rebuildData[1].length })); + } + if(this.rebuildData[2].length > 0) + { + this.$fhcAlert.alertError(this.$p.t('tag', 'alertErrorRebuild') + this.rebuildData[2].toString()); + } + + this.isLoading = false; + }, + showModal(){ + this.$refs.modalLocked.open(); + }, }, created() { if (this.tagsEnabled) { @@ -690,6 +764,16 @@ export default { // TODO(chris): filter component column chooser has no accessibilty features template: /* html */`
+ + +
+ + +