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: `
+
+
+
+
+
+
+
+ New Buchung
+
+ ({{ personIds.length }} Studenten)
+
+
+
+
+
+
+ `
+};
\ No newline at end of file