Konto new

This commit is contained in:
cgfhtw
2024-04-16 12:56:12 +02:00
parent 63d7716a6c
commit e15f4981fb
8 changed files with 442 additions and 24 deletions
@@ -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',
+28
View File
@@ -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
*/
+5
View File
@@ -0,0 +1,5 @@
import konto from './stv/konto.js';
export default {
konto
};
+31
View File
@@ -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');
}
};
@@ -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;
})
@@ -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"
>
</core-filter-cmpt>
<konto-new ref="new" :config="config" @saved="updateData" :person-ids="personIds" :stg-kz="stg_kz"></konto-new>
<konto-edit ref="edit" :config="config" @saved="updateData"></konto-edit>
</div>`
};
@@ -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;
});
@@ -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: `
<core-form ref="form" class="stv-details-konto-edit" @submit.prevent="save">
<bs-modal ref="modal" @hide-bs-modal="preventCloseOnLoading">
<form-validation></form-validation>
<fieldset :disabled="loading">
<form-input
type="select"
v-model="data.buchungstyp_kurzbz"
name="buchungstyp_kurzbz"
label="Typ"
@update:model-value="checkDefaultBetrag"
>
<option v-for="typ in activeBuchungstypen" :key="typ.buchungstyp_kurzbz" :value="typ.buchungstyp_kurzbz" :class="typ.aktiv ? '' : 'text-decoration-line-through text-muted'">
{{ typ.beschreibung }}
</option>
</form-input>
<form-input
v-model="data.betrag"
name="betrag"
label="Betrag"
>
</form-input>
<form-input
type="DatePicker"
v-model="data.buchungsdatum"
name="buchungsdatum"
label="Buchungsdatum"
:enable-time-picker="false"
auto-apply
>
</form-input>
<form-input
v-model="data.buchungstext"
name="buchungstext"
label="Buchungstext"
>
</form-input>
<form-input
v-if="config.showMahnspanne"
v-model="data.mahnspanne"
name="mahnspanne"
label="Mahnspanne"
>
</form-input>
<form-input
type="select"
v-model="data.studiensemester_kurzbz"
name="studiensemester_kurzbz"
label="Studiensemester"
>
<option v-for="sem in reversedSems" :key="sem.studiensemester_kurzbz" :value="sem.studiensemester_kurzbz">
{{ sem.studiensemester_kurzbz }}
</option>
</form-input>
<form-input
v-if="config.showCreditpoints"
v-model="data.credit_points"
name="credit_points"
label="Credit Points"
>
</form-input>
<form-input
type="textarea"
v-model="data.anmerkung"
name="anmerkung"
label="Anmerkung"
>
</form-input>
</fieldset>
<template #title>
New Buchung
<template v-if="personIds.length > 1">
({{ personIds.length }} Studenten)
</template>
</template>
<template #footer>
<button type="submit" class="btn btn-primary" :disabled="loading">
<i v-if="loading" class="fa fa-spinner fa-spin"></i>
Speichern
</button>
</template>
</bs-modal>
</core-form>`
};