From efebaeeb27a3d91f35c856e6654c2460b41a291f Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Fri, 12 Apr 2024 10:38:06 +0200 Subject: [PATCH] Edit --- .../controllers/api/frontend/v1/stv/Konto.php | 94 +++++++- .../controllers/api/frontend/v1/stv/Lists.php | 72 ++++++ .../controllers/components/stv/Config.php | 21 +- application/models/crm/Konto_model.php | 29 ++- .../js/components/Stv/Studentenverwaltung.js | 76 +++--- .../Stv/Studentenverwaltung/Details/Konto.js | 225 +++++++++++++----- .../Studentenverwaltung/Details/Konto/Edit.js | 163 +++++++++++++ .../Stv/Studentenverwaltung/List/New.js | 2 +- 8 files changed, 572 insertions(+), 110 deletions(-) create mode 100644 application/controllers/api/frontend/v1/stv/Lists.php create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php index 7c242b2e2..782f28d00 100644 --- a/application/controllers/api/frontend/v1/stv/Konto.php +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -16,7 +16,9 @@ * along with this program. If not, see . */ -if (! defined('BASEPATH')) exit('No direct script access allowed'); +if (!defined('BASEPATH')) exit('No direct script access allowed'); + +use CI3_Events as Events; /** * This controller operates between (interface) the JS (GUI) and the back-end @@ -33,7 +35,9 @@ class Konto extends FHCAPI_Controller { // TODO(chris): permissions parent::__construct([ - 'get' => 'student/stammdaten:r' + 'get' => 'student/stammdaten:r', + 'getBuchungstypen' => 'student/stammdaten:r', // alle? + 'update' => ['admin:w', 'assistenz:w'] ]); // Load models @@ -51,15 +55,20 @@ class Konto extends FHCAPI_Controller /** * Get details for a prestudent * - * @param string $type - * @param string (optional) $studiengang_kz * @return void */ - public function get($type, $studiengang_kz = '') + public function get() { - // TODO(chris): validation + $this->load->library('form_validation'); + + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); $person_id = $this->input->post('person_id'); + $studiengang_kz = $this->input->post('studiengang_kz'); if ($this->input->post('only_open')) { $result = $this->KontoModel->getOffeneBuchungen($person_id, $studiengang_kz); @@ -95,4 +104,77 @@ class Konto extends FHCAPI_Controller $this->terminateWithSuccess(array_values($data)); } + + /** + * Get list of Buchungstypen + * + * @return void + */ + public function getBuchungstypen() + { + $this->load->model('crm/Buchungstyp_model', 'BuchungstypModel'); + + $result = $this->BuchungstypModel->load(); + + #$data = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $data = $result->retval; + + $this->terminateWithSuccess($data); + } + + /** + * Save Buchung + * + * @return void + */ + public function update() + { + $this->load->library('form_validation'); + + $this->form_validation->set_rules('buchungsnr', 'Buchungsnr', 'required'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'); + $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); + Events::trigger('konto_update_validation', $this->form_validation); + + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + $id = $this->input->post('buchungsnr'); + $allowed = [ + 'betrag', + 'buchungsdatum', + 'buchungstext', + 'mahnspanne', + 'buchungstyp_kurzbz', + 'studiensemester_kurzbz', + 'studiengang_kz', + 'credit_points', + 'anmerkung' + ]; + $data = [ + 'updateamum' => date('c'), + 'updatevon' => getAuthUID() + ]; + foreach ($allowed as $field) + if ($this->input->post($field) !== null) + $data[$field] = $this->input->post($field); + + $result = $this->KontoModel->update($id, $data); + + #$this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + + $result = $this->KontoModel->withAdditionalInfo()->load($id); + + #$result = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $result = $result->retval; + + $this->terminateWithSuccess($result); + } } diff --git a/application/controllers/api/frontend/v1/stv/Lists.php b/application/controllers/api/frontend/v1/stv/Lists.php new file mode 100644 index 000000000..2a8335b7e --- /dev/null +++ b/application/controllers/api/frontend/v1/stv/Lists.php @@ -0,0 +1,72 @@ +. + */ + +if (! defined('BASEPATH')) exit('No direct script access allowed'); + +/** + * This controller operates between (interface) the JS (GUI) and the back-end + * Provides data to the ajax get calls about generally used lists + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + */ +class Lists extends FHCAPI_Controller +{ + public function __construct() + { + // TODO(chris): permissions + parent::__construct([ + 'getStudiensemester' => ['admin:r', 'assistenz:r', 'student/stammdaten:r'], // alle? + 'getStgs' => ['admin:r', 'assistenz:r', 'student/stammdaten:r'] // alle? + ]); + } + + public function getStudiensemester() + { + $this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel'); + + $this->StudiensemesterModel->addOrder('ende'); + + $result = $this->StudiensemesterModel->load(); + + #$data = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $data = $result->retval; + + $this->terminateWithSuccess($data); + } + + public function getStgs() + { + $this->load->model('organisation/Studiengang_model', 'StudiengangModel'); + + $this->StudiengangModel->addSelect('*'); + $this->StudiengangModel->addSelect('UPPER(typ || kurzbz) AS kuerzel'); + + $this->StudiengangModel->addOrder('typ'); + $this->StudiengangModel->addOrder('kurzbz'); + + $result = $this->StudiengangModel->load(); + + #$data = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $data = $result->retval; + + $this->terminateWithSuccess($data); + } +} diff --git a/application/controllers/components/stv/Config.php b/application/controllers/components/stv/Config.php index e9ed7ec44..78089d519 100644 --- a/application/controllers/components/stv/Config.php +++ b/application/controllers/components/stv/Config.php @@ -6,10 +6,15 @@ use CI3_Events as Events; class Config extends FHC_Controller { + + public function __construct() { // TODO(chris): access! parent::__construct(); + + $this->load->library('AuthLib'); + $this->load->library('PermissionLib'); } public function student() @@ -39,7 +44,13 @@ class Config extends FHC_Controller $result['konto'] = [ 'title' => 'Konto', 'component' => './Stv/Studentenverwaltung/Details/Konto.js', - 'config' => ['ZAHLUNGSBESTAETIGUNG_ANZEIGEN' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN)] + 'config' => [ + 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN), + 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'), + 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true), + 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'), + 'additionalCols' => [] + ] ]; $result['betriebsmittel'] = [ 'title' => 'Betriebsmittel', @@ -64,7 +75,13 @@ class Config extends FHC_Controller $result['konto'] = [ 'title' => 'Konto', 'component' => './Stv/Studentenverwaltung/Details/Konto.js', - 'config' => ['ZAHLUNGSBESTAETIGUNG_ANZEIGEN' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN)] + 'config' => [ + 'showZahlungsbestaetigung' => (defined('ZAHLUNGSBESTAETIGUNG_ANZEIGEN') && ZAHLUNGSBESTAETIGUNG_ANZEIGEN), + 'showBuchungsnr' => $this->permissionlib->isBerechtigt('admin'), + 'showMahnspanne' => (!defined('FAS_KONTO_SHOW_MAHNSPANNE') || FAS_KONTO_SHOW_MAHNSPANNE===true), + 'showCreditpoints' => (defined('FAS_KONTO_SHOW_CREDIT_POINTS') && FAS_KONTO_SHOW_CREDIT_POINTS == 'true'), + 'additionalCols' => [] + ] ]; Events::trigger('stv_conf_students', function & () use (&$result) { diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php index 00a621d0e..85ac9234c 100644 --- a/application/models/crm/Konto_model.php +++ b/application/models/crm/Konto_model.php @@ -1,4 +1,7 @@ addSelect($this->dbTable . '.*'); $this->addSelect('UPPER(typ::varchar(1) || kurzbz) AS kuerzel'); @@ -35,6 +35,23 @@ class Konto_model extends DB_Model $this->addJoin('public.tbl_studiengang stg', 'studiengang_kz', 'LEFT'); $this->addJoin('public.tbl_person person', 'person_id', 'LEFT'); + Events::trigger('konto_query'); + + return $this; + } + + /** + * Get all accounting entries for a person optionally filtered by Studiengang + * + * @param integer|array $person_id + * @param string (optional) $studiengang_kz + * + * @return stdClass + */ + public function getAlleBuchungen($person_id, $studiengang_kz = '') + { + $this->withAdditionalInfo(); + $this->addOrder('buchungsdatum'); if (is_array($person_id)) diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index 6279f57b5..42e3cd5dd 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -15,7 +15,7 @@ * along with this program. If not, see . */ -import FhcSearchbar from "../searchbar/searchbar.js"; +import CoreSearchbar from "../searchbar/searchbar.js"; import VerticalSplit from "../verticalsplit/verticalsplit.js"; import StvVerband from "./Studentenverwaltung/Verband.js"; import StvList from "./Studentenverwaltung/List.js"; @@ -26,7 +26,7 @@ import {CoreRESTClient} from '../../RESTClient.js'; export default { components: { - FhcSearchbar, + CoreSearchbar, VerticalSplit, StvVerband, StvList, @@ -142,11 +142,11 @@ export default { this.lists.ausbildungen = result; }) .catch(this.$fhcAlert.handleSystemError); - CoreRESTClient - .get('components/stv/Lists/getStgs') - .then(result => CoreRESTClient.getData(result.data) || []) + this.$fhcApi + .get('api/frontend/v1/stv/lists/getStgs') .then(result => { - this.lists.stgs = result; + this.lists.stgs = result.data; + this.lists.active_stgs = this.lists.stgs.filter(stg => stg.aktiv); }) .catch(this.$fhcAlert.handleSystemError); CoreRESTClient @@ -156,40 +156,56 @@ export default { this.lists.orgforms = result; }) .catch(this.$fhcAlert.handleSystemError); + this.$fhcApi + .get('api/frontend/v1/stv/konto/getBuchungstypen') + .then(result => { + this.lists.buchungstypen = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); + this.$fhcApi + .get('api/frontend/v1/stv/lists/getStudiensemester') + .then(result => { + this.lists.studiensemester = result.data; + }) + .catch(this.$fhcAlert.handleSystemError); }, mounted() { if (this.$route.params.id) { this.$refs.stvList.updateUrl('components/stv/students/uid/' + this.$route.params.id, true); } else if (this.$route.params.prestudent_id) { this.$refs.stvList.updateUrl('components/stv/students/prestudent/' + this.$route.params.prestudent_id, true); + } else if (this.$route.params.person_id) { + this.$refs.stvList.updateUrl('components/stv/students/person/' + this.$route.params.person_id, true); } }, template: ` - -
-
- -
- - - - -
+
+ +
+
+ +
+ + + + +
+
` }; diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Konto.js b/public/js/components/Stv/Studentenverwaltung/Details/Konto.js index 99bb85c87..b6b71f50b 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Konto.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Konto.js @@ -1,12 +1,15 @@ import {CoreFilterCmpt} from "../../../filter/Filter.js"; +import FormInput from "../../../Form/Input.js"; +import KontoEdit from "./Konto/Edit.js"; -// TODO(chris): filter // TODO(chris): multi pers // TODO(chris): new header(multi pers), edit/row, gegenb.(date) multi, löschen multi, best. multi(recht) export default { components: { - CoreFilterCmpt + CoreFilterCmpt, + FormInput, + KontoEdit }, props: { modelValue: Object, @@ -17,7 +20,8 @@ export default { }, data() { return { - filter: 'alle' + filter: false, + studiengang_kz: false }; }, computed: { @@ -29,13 +33,133 @@ export default { return ''; return values[0]; }, + studiengang_kz_intern: { + get() { + if (this.stg_kz) + return this.studiengang_kz; + else + return false; + }, + set(value) { + this.studiengang_kz = value; + } + }, + tabulatorColumns() { + let columns = []; + + if (Array.isArray(this.modelValue)) { + columns.push({ + field: "person_id", + title: "Person ID" + }); + columns.push({ + field: "anrede", + title: "Anrede", + visible: false + }); + columns.push({ + field: "titelpost", + title: "Titelpost", + visible: false + }); + columns.push({ + field: "titelpre", + title: "Titelpre", + visible: false + }); + columns.push({ + field: "vorname", + title: "Vorname" + }); + columns.push({ + field: "vornamen", + title: "Vornamen", + visible: false + }); + columns.push({ + field: "nachname", + title: "Nachname" + }); + } + + columns = [...columns, ...[ + { + field: "buchungsdatum", + title: "Buchungsdatum" + }, + { + field: "buchungstext", + title: "Buchungstext" + }, + { + field: "betrag", + title: "Betrag" + }, + { + field: "studiensemester_kurzbz", + title: "StSem" + }, + { + field: "buchungstyp_kurzbz", + title: "Typ", + visible: false + }, + { + field: "buchungsnr", + title: "Buchungs Nr", + visible: false + }, + { + field: "insertvon", + title: "Angelegt von", + visible: false + }, + { + field: "insertamum", + title: "Anlagedatum", + visible: false + }, + { + field: "kuerzel", + title: "Studiengang", + visible: false + }, + { + field: "anmerkung", + title: "Anmerkung" + } + ]]; + + columns = [...columns, ...this.config.additionalCols]; + + columns.push({ + title: 'Actions', + formatter: cell => { + let container = document.createElement('div'); + container.className = "d-flex gap-2"; + + let button = document.createElement('button'); + button.className = 'btn btn-outline-secondary'; + button.innerHTML = ''; + button.addEventListener('click', () => + this.$refs.edit.open(cell.getData()) + ); + container.append(button); + + return container; + }, + frozen: true + }); + return columns; + }, tabulatorOptions() { return { - ajaxURL: 'api/frontend/v1/stv/konto/get/alle', + ajaxURL: 'api/frontend/v1/stv/konto/get', ajaxParams: () => { const params = { person_id: this.modelValue.person_id || this.modelValue.map(e => e.person_id), - only_open: (this.filter == 'offene') + only_open: this.filter, + studiengang_kz: this.studiengang_kz_intern ? this.stg_kz : '' }; return params; }, @@ -44,54 +168,8 @@ export default { }, ajaxResponse: (url, params, response) => response.data, dataTree: true, - columns: [ - { - field: "buchungsdatum", - title: "Buchungsdatum" - }, - { - field: "buchungstext", - title: "Buchungstext" - }, - { - field: "betrag", - title: "Betrag" - }, - { - field: "studiensemester_kurzbz", - title: "StSem" - }, - { - field: "buchungstyp_kurzbz", - title: "Typ", - visible: false - }, - { - field: "buchungsnr", - title: "buchungs_nr", - visible: false - }, - { - field: "insertvon", - title: "Angelegt von", - visible: false - }, - { - field: "insertamum", - title: "Anlagedatum", - visible: false - }, - { - field: "kuerzel", - title: "Studiengang", - visible: false - }, - { - field: "anmerkung", - title: "Anmerkung" - } - ], - index: 'buchungs_nr', + columns: this.tabulatorColumns, + index: 'buchungsnr', }; } }, @@ -103,23 +181,39 @@ export default { methods: { reload() { this.$refs.table.reloadTable(); + }, + updateData(data) { + if (!data) + return this.reload(); + this.$refs.table.tabulator.updateData(data); } }, + created() { + // TODO(chris): persist filter + studiengang_kz + }, template: `
- {{config}} -
-
- +
+
+ +
-
- +
+ +
+
` }; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js b/public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js new file mode 100644 index 000000000..9e65df428 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js @@ -0,0 +1,163 @@ +import BsModal from "../../../../Bootstrap/Modal.js"; +import CoreForm from "../../../../Form/Form.js"; +import FormValidation from "../../../../Form/Validation.js"; +import FormInput from "../../../../Form/Input.js"; + +// TODO(chris): Phrasen + +export default { + components: { + BsModal, + CoreForm, + FormValidation, + FormInput + }, + inject: { + lists: { + from: 'lists' + } + }, + props: { + config: { + type: Object, + default: {} + } + }, + data() { + return { + loading: false, + data: {} + }; + }, + methods: { + save() { + this.$refs.form.clearValidation(); + this.loading = true; + + this.$refs.form + .post('api/frontend/v1/stv/konto/update', this.data) + .then(result => { + this.$emit('saved', result.data); + this.loading = false; + this.$refs.modal.hide(); + this.$fhcAlert.alertSuccess('Daten wurden gespeichert'); + }) + .catch(error => {console.log(error); // TODO(chris): check if working with current fhcApi + this.$fhcAlert.handleSystemError(error); + this.loading = false; + }); + }, + open(data) { + this.data = {...data}; + this.$refs.modal.show(); + }, + preventCloseOnLoading(ev) { + if (this.loading) + ev.returnValue = false; + } + }, + template: ` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
` +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung/List/New.js b/public/js/components/Stv/Studentenverwaltung/List/New.js index acc9781de..f23245b7c 100644 --- a/public/js/components/Stv/Studentenverwaltung/List/New.js +++ b/public/js/components/Stv/Studentenverwaltung/List/New.js @@ -600,7 +600,7 @@ export default { name="studiengang_kz" v-model="formDataStg" > - +