From e15f4981fbf08ec99e1015fd86239a4281f0da10 Mon Sep 17 00:00:00 2001 From: cgfhtw Date: Tue, 16 Apr 2024 12:56:12 +0200 Subject: [PATCH] Konto new --- .../controllers/api/frontend/v1/stv/Konto.php | 160 +++++++++++++- application/models/crm/Konto_model.php | 28 +++ public/js/api/stv.js | 5 + public/js/api/stv/konto.js | 31 +++ .../js/components/Stv/Studentenverwaltung.js | 2 +- .../Stv/Studentenverwaltung/Details/Konto.js | 37 ++-- .../Studentenverwaltung/Details/Konto/Edit.js | 4 +- .../Studentenverwaltung/Details/Konto/New.js | 199 ++++++++++++++++++ 8 files changed, 442 insertions(+), 24 deletions(-) create mode 100644 public/js/api/stv.js create mode 100644 public/js/api/stv/konto.js create mode 100644 public/js/components/Stv/Studentenverwaltung/Details/Konto/New.js diff --git a/application/controllers/api/frontend/v1/stv/Konto.php b/application/controllers/api/frontend/v1/stv/Konto.php index 782f28d00..12892d2f7 100644 --- a/application/controllers/api/frontend/v1/stv/Konto.php +++ b/application/controllers/api/frontend/v1/stv/Konto.php @@ -37,6 +37,8 @@ class Konto extends FHCAPI_Controller parent::__construct([ 'get' => 'student/stammdaten:r', 'getBuchungstypen' => 'student/stammdaten:r', // alle? + 'checkDoubles' => ['admin:r', 'assistenz:r'], + 'insert' => ['admin:w', 'assistenz:w'], 'update' => ['admin:w', 'assistenz:w'] ]); @@ -61,13 +63,14 @@ class Konto extends FHCAPI_Controller { $this->load->library('form_validation'); - $this->form_validation->set_rules('person_id', 'Person ID', 'required'); - + $person_id = $this->input->post('person_id'); + if (!$person_id || !is_array($person_id)) + $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')) { @@ -124,6 +127,146 @@ class Konto extends FHCAPI_Controller $this->terminateWithSuccess($data); } + /** + * Check double Buchungen + * + * @return void + */ + public function checkDoubles() + { + if (!defined('FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK') || !FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK) + $this->terminateWithSuccess(false); + + $this->load->library('form_validation'); + + $person_ids = $this->input->post('person_id'); + + if (!$person_ids || !is_array($person_ids)) { + $person_ids = [$person_ids]; + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + } + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required'); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $buchungstypen = unserialize(FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK); + $buchung = $this->input->post('buchungstyp_kurzbz'); + + if (!isset($buchungstypen[$buchung])) + $this->terminateWithSuccess(false); + + $result = $this->KontoModel->checkDoubleBuchung($person_ids, $this->input->post('studiensemester_kurzbz'), $buchungstypen[$buchung]); + + #$result = $this->getDataOrTerminateWithError($result); + if (isError($result)) + $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL); + $result = $result->retval; + + if (!$result) + $this->terminateWithSuccess(false); + + $persons = array_map(function ($row) { + return $row->nachname . ' ' . $row->vorname; + }, $result); + + // TODO(chris): Phrases + $result = $this->p->t('konto', 'buchung_vorhanden') . "\n"; + if (count($persons) > 10) { + $result .= "-" . implode("\n-", array_slice($persons, 0, 10)) . "\n"; + + if (count($persons) == 11) { + $result .= "\n" . $this->p->t('konto', 'and_1_additional_person'); + } else { + $result .= "\n" . $this->p->t('konto', 'and_x_additional_person', [ + 'x' => count($persons) - 10 + ]); + } + } else { + $result .= "-" . implode("\n-", $persons) . "\n"; + } + $result .= $this->p->t('konto', 'proceed'); + + $this->addError($result, 'confirm'); + + $this->terminateWithSuccess(true); + } + + + /** + * Save Buchung + * + * @return void + */ + public function insert() + { + $this->load->library('form_validation'); + + $person_ids = $this->input->post('person_id'); + + if (!$person_ids || !is_array($person_ids)) { + $person_ids = [$person_ids]; + $this->form_validation->set_rules('person_id', 'Person ID', 'required'); + } + $this->form_validation->set_rules('betrag', 'Betrag', 'numeric'); + $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); + $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]'); + $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'); + $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric'); + + Events::trigger('konto_insert_validation', $this->form_validation); + + if (!$this->form_validation->run()) + $this->terminateWithValidationErrors($this->form_validation->error_array()); + + + $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); + + if (defined('FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE') && isset(unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']])) { + $data['kostenstelle'] = unserialize(FAS_BUCHUNGSTYP_FIXE_KOSTENSTELLE)[$data['buchungstyp_kurzbz']]; + } + + $result = []; + foreach ($person_ids as $person_id) { + $id = $this->KontoModel->insert(array_merge($data, ['person_id' => $person_id])); + if (isError($id)) + $this->addError(getError($id), self::ERROR_TYPE_GENERAL); + else { + $data = $this->KontoModel->withAdditionalInfo()->load(getData($id)); + if (isError($data)) + $this->addError(getError($data), self::ERROR_TYPE_GENERAL); + else + $result[] = getData($data); + } + } + + if ($result) + $this->terminateWithSuccess($result); + // NOTE(chris): else there should already be error in the return object + } + /** * Save Buchung * @@ -134,14 +277,21 @@ class Konto extends FHCAPI_Controller $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('betrag', 'Betrag', 'numeric'); $this->form_validation->set_rules('buchungsdatum', 'Buchungsdatum', 'is_valid_date'); - Events::trigger('konto_update_validation', $this->form_validation); + $this->form_validation->set_rules('buchungstext', 'Buchungstext', 'max_length[256]'); + $this->form_validation->set_rules('mahnspanne', 'Mahnspanne', 'integer'); + $this->form_validation->set_rules('buchungstyp_kurzbz', 'Buchungstyp', 'required|max_length[32]'); + $this->form_validation->set_rules('studiensemester_kurzbz', 'Studiensemester', 'required|max_length[16]'); + $this->form_validation->set_rules('studiengang_kz', 'Studiengang', 'required|has_permissions_for_stg[admin:rw,assistenz:rw]'); + $this->form_validation->set_rules('credit_points', 'Credit Points', 'numeric'); + 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', diff --git a/application/models/crm/Konto_model.php b/application/models/crm/Konto_model.php index 85ac9234c..77ae04990 100644 --- a/application/models/crm/Konto_model.php +++ b/application/models/crm/Konto_model.php @@ -96,6 +96,34 @@ class Konto_model extends DB_Model return $this->getAlleBuchungen($person_id, $studiengang_kz); } + /** + * Check double Buchungen + * + * @param array $person_ids + * @param string $studiensemester_kurzbz + * @param array $buchungstyp_kurzbzs + * + * @return stdClass + */ + public function checkDoubleBuchung($person_ids, $studiensemester_kurzbz, $buchungstyp_kurzbzs) + { + $this->addSelect('vorname'); + $this->addSelect('nachname'); + + $this->addJoin('public.tbl_person', 'person_id'); + + $this->db->where_in('person_id', $person_ids); + $this->db->where_in('buchungstyp_kurzbz', $buchungstyp_kurzbzs); + + $this->addGroupBy('vorname, nachname'); + $this->addOrder('nachname'); + $this->addOrder('vorname'); + + return $this->loadWhere([ + 'studiensemester_kurzbz' => $studiensemester_kurzbz + ]); + } + /** * Sets a Payment as paid */ diff --git a/public/js/api/stv.js b/public/js/api/stv.js new file mode 100644 index 000000000..2a84ab0b7 --- /dev/null +++ b/public/js/api/stv.js @@ -0,0 +1,5 @@ +import konto from './stv/konto.js'; + +export default { + konto +}; \ No newline at end of file diff --git a/public/js/api/stv/konto.js b/public/js/api/stv/konto.js new file mode 100644 index 000000000..0e4069f2c --- /dev/null +++ b/public/js/api/stv/konto.js @@ -0,0 +1,31 @@ +export default { + tabulatorConfig(config, self) { + config.ajaxURL = 'api/frontend/v1/stv/konto/get'; + config.ajaxParams = () => { + const params = { + person_id: self.modelValue.person_id || self.modelValue.map(e => e.person_id), + only_open: self.filter, + studiengang_kz: self.studiengang_kz_intern ? self.stg_kz : '' + }; + return params; + }; + config.ajaxRequestFunc = (url, config, params) => this.$fhcApi.post(url, params, config); + config.ajaxResponse = (url, params, response) => response.data; + + return config; + }, + checkDoubles(data) { + return this.$fhcApi.post('api/frontend/v1/stv/konto/checkDoubles', data, { + confirmErrorHandler: error => true + }); + }, + insert(data) { + return this.$fhcApi.post('api/frontend/v1/stv/konto/insert', data); + }, + edit(data) { + return this.$fhcApi.post('api/frontend/v1/stv/konto/update', data); + }, + getBuchungstypen() { + return this.$fhcApi.get('api/frontend/v1/stv/konto/getBuchungstypen'); + } +}; \ No newline at end of file diff --git a/public/js/components/Stv/Studentenverwaltung.js b/public/js/components/Stv/Studentenverwaltung.js index 42e3cd5dd..57cfe998a 100644 --- a/public/js/components/Stv/Studentenverwaltung.js +++ b/public/js/components/Stv/Studentenverwaltung.js @@ -157,7 +157,7 @@ export default { }) .catch(this.$fhcAlert.handleSystemError); this.$fhcApi - .get('api/frontend/v1/stv/konto/getBuchungstypen') + .factory.stv.konto.getBuchungstypen() .then(result => { this.lists.buchungstypen = result.data; }) diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Konto.js b/public/js/components/Stv/Studentenverwaltung/Details/Konto.js index b6b71f50b..849754050 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Konto.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Konto.js @@ -1,14 +1,17 @@ import {CoreFilterCmpt} from "../../../filter/Filter.js"; import FormInput from "../../../Form/Input.js"; +import KontoNew from "./Konto/New.js"; import KontoEdit from "./Konto/Edit.js"; +// TODO(chris): Phrasen // TODO(chris): multi pers -// TODO(chris): new header(multi pers), edit/row, gegenb.(date) multi, löschen multi, best. multi(recht) +// TODO(chris): gegenb.(date) multi, löschen multi, best. multi(recht) export default { components: { CoreFilterCmpt, FormInput, + KontoNew, KontoEdit }, props: { @@ -25,6 +28,11 @@ export default { }; }, computed: { + personIds() { + if (this.modelValue.person_id) + return [this.modelValue.person_id]; + return this.modelValue.map(e => e.person_id); + }, stg_kz() { if (this.modelValue.studiengang_kz) return this.modelValue.studiengang_kz; @@ -153,24 +161,13 @@ export default { return columns; }, tabulatorOptions() { - return { - 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, - studiengang_kz: this.studiengang_kz_intern ? this.stg_kz : '' - }; - return params; - }, - ajaxRequestFunc: (url, config, params) => { - return this.$fhcApi.post(url, params, config); - }, - ajaxResponse: (url, params, response) => response.data, + return this.$fhcApi.factory.stv.konto.tabulatorConfig({ dataTree: true, columns: this.tabulatorColumns, + selectable: true, + selectableRangeMode: 'click', index: 'buchungsnr', - }; + }, this); } }, watch: { @@ -186,6 +183,9 @@ export default { if (!data) return this.reload(); this.$refs.table.tabulator.updateData(data); + }, + actionNew() { + this.$refs.new.open(); } }, created() { @@ -221,8 +221,13 @@ export default { table-only :side-menu="false" :tabulator-options="tabulatorOptions" + new-btn-show + new-btn-label="Buchung" + :new-btn-disabled="stg_kz === ''" + @click:new="actionNew" > + ` }; \ 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 index b3d33b116..d7b2976e3 100644 --- a/public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js +++ b/public/js/components/Stv/Studentenverwaltung/Details/Konto/Edit.js @@ -35,14 +35,14 @@ export default { this.loading = true; this.$refs.form - .post('api/frontend/v1/stv/konto/update', this.data) + .factory.stv.konto.edit(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 + .catch(error => { this.$fhcAlert.handleSystemError(error); this.loading = false; }); diff --git a/public/js/components/Stv/Studentenverwaltung/Details/Konto/New.js b/public/js/components/Stv/Studentenverwaltung/Details/Konto/New.js new file mode 100644 index 000000000..b47d03456 --- /dev/null +++ b/public/js/components/Stv/Studentenverwaltung/Details/Konto/New.js @@ -0,0 +1,199 @@ +import BsModal from "../../../../Bootstrap/Modal.js"; +import BsConfirm from "../../../../Bootstrap/Confirm.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' + }, + defaultSemester: { + from: 'defaultSemester' + } + }, + props: { + personIds: { + type: Array, + required: true + }, + stgKz: { + type: Number, + required: true + }, + config: { + type: Object, + default: {} + } + }, + data() { + return { + loading: false, + data: {} + }; + }, + computed: { + reversedSems() { + return this.lists.studiensemester.toReversed(); + }, + activeBuchungstypen() { + return this.lists.buchungstypen.filter(e => e.aktiv); + } + }, + methods: { + save() { + this.$refs.form.clearValidation(); + this.loading = true; + + const data = {...{ + person_id: this.personIds, + studiengang_kz: this.stgKz + }, ...this.data}; + + this.$refs.form + .factory.stv.konto.checkDoubles(data) + .then(result => result.data + ? Promise.all( + result.errors + .filter(e => e.type == 'confirm') + .map(e => BsConfirm.popup(Vue.h('div', {class:'text-preline'}, e.message))) + ) + : Promise.resolve()) + .then(() => data) + .then(this.$refs.form.factory.stv.konto.insert) + .then(result => { + this.$emit('saved', result.data); + this.loading = false; + this.$refs.modal.hide(); + this.$fhcAlert.alertSuccess('Daten wurden gespeichert'); + }) + .catch(error => { + if (error) + this.$fhcAlert.handleSystemError(error); + this.loading = false; + }); + }, + open() { + this.data = { + betrag: '-0.00', + mahnspanne: 30, + buchungsdatum: new Date(), + studiensemester_kurzbz: this.defaultSemester + }; + this.$refs.modal.show(); + }, + preventCloseOnLoading(ev) { + if (this.loading) + ev.returnValue = false; + }, + checkDefaultBetrag(ev) { + const typ = this.lists.buchungstypen.filter(e => e.buchungstyp_kurzbz == ev).pop(); + const amount = typ.standardbetrag || '-0.00'; + const text = typ.standardtext || ''; + const creditpoints = typ.credit_points || ''; + + if (!this.data.betrag || this.data.betrag == '-0.00') + this.data.betrag = amount; + + if (!this.data.buchungstext) + this.data.buchungstext = text; + + if (this.config.showCreditpoints && this.data.credit_points == '0.00') + this.data.credit_points = creditpoints; + } + }, + template: ` + + + + +
+ + + + + + + + + + + + + + + + + + +
+ + + +
+
` +}; \ No newline at end of file