This commit is contained in:
cgfhtw
2024-04-12 10:38:06 +02:00
parent 8705341563
commit efebaeeb27
8 changed files with 572 additions and 110 deletions
@@ -16,7 +16,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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);
}
}
@@ -0,0 +1,72 @@
<?php
/**
* Copyright (C) 2024 fhcomplete.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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);
}
}
@@ -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) {
+23 -6
View File
@@ -1,4 +1,7 @@
<?php
use CI3_Events as Events;
class Konto_model extends DB_Model
{
@@ -14,14 +17,11 @@ class Konto_model extends DB_Model
/**
* Get all accounting entries for a person optionally filtered by Studiengang
* Adds additional fields to the Query
*
* @param integer|array $person_id
* @param string (optional) $studiengang_kz
*
* @return stdClass
* @return Konto_model
*/
public function getAlleBuchungen($person_id, $studiengang_kz = '')
public function withAdditionalInfo()
{
$this->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))
+46 -30
View File
@@ -15,7 +15,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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: `
<header class="navbar navbar-expand-lg navbar-dark bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3" :href="stvRoot">FHC 4.0</a>
<button class="navbar-toggler d-md-none m-1 collapsed" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<fhc-searchbar :searchoptions="searchbaroptions" :searchfunction="searchfunction" class="searchbar w-100"></fhc-searchbar>
</header>
<div class="container-fluid overflow-hidden">
<div class="row h-100">
<nav id="sidebarMenu" class="bg-light offcanvas offcanvas-start col-md p-md-0 h-100">
<div class="offcanvas-header justify-content-end px-1 d-md-none">
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<stv-verband @select-verband="onSelectVerband" class="col" style="height:0%"></stv-verband>
<stv-studiensemester :default="defaultSemester" @changed="studiensemesterChanged"></stv-studiensemester>
</nav>
<main class="col-md-8 ms-sm-auto col-lg-9 col-xl-10">
<vertical-split>
<template #top>
<stv-list ref="stvList" v-model:selected="selected" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></stv-list>
</template>
<template #bottom>
<stv-details ref="details" :students="selected"></stv-details>
</template>
</vertical-split>
</main>
<div class="stv">
<header class="navbar navbar-expand-lg navbar-dark bg-dark flex-md-nowrap p-0 shadow">
<a class="navbar-brand col-md-4 col-lg-3 col-xl-2 me-0 px-3" :href="stvRoot">FHC 4.0</a>
<button class="navbar-toggler d-md-none m-1 collapsed" type="button" data-bs-toggle="offcanvas" data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<core-searchbar :searchoptions="searchbaroptions" :searchfunction="searchfunction" class="searchbar w-100"></core-searchbar>
</header>
<div class="container-fluid overflow-hidden">
<div class="row h-100">
<nav id="sidebarMenu" class="bg-light offcanvas offcanvas-start col-md p-md-0 h-100">
<div class="offcanvas-header justify-content-end px-1 d-md-none">
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="Close"></button>
</div>
<stv-verband @select-verband="onSelectVerband" class="col" style="height:0%"></stv-verband>
<stv-studiensemester :default="defaultSemester" @changed="studiensemesterChanged"></stv-studiensemester>
</nav>
<main class="col-md-8 ms-sm-auto col-lg-9 col-xl-10">
<vertical-split>
<template #top>
<stv-list ref="stvList" v-model:selected="selected" :studiengang-kz="studiengangKz" :studiensemester-kurzbz="studiensemesterKurzbz"></stv-list>
</template>
<template #bottom>
<stv-details ref="details" :students="selected"></stv-details>
</template>
</vertical-split>
</main>
</div>
</div>
</div>`
};
@@ -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 = '<i class="fa fa-edit"></i>';
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: `
<div class="stv-details-konto h-100 d-flex flex-column">
{{config}}
<div class="row">
<div class="col-lg-2">
<select class="form-select" v-model="filter" @input="() => $nextTick($refs.table.reloadTable)">
<option value="alle">Alle</option>
<option value="offene">Offene</option>
</select>
<div class="row justify-content-end">
<div class="col-lg-3">
<form-input
container-class="form-switch"
type="checkbox"
label="Nur offene anzeigen"
v-model="filter"
@update:model-value="() => $nextTick($refs.table.reloadTable)"
>
</form-input>
</div>
<div class="col-lg-2">
<select class="form-select" v-model="studiengang_kz" @input="() => $nextTick($refs.table.reloadTable)">
<option value="">Alle</option>
<option :value="stg_kz">Aktuelle</option>
</select>
<div class="col-lg-3">
<form-input
container-class="form-switch"
type="checkbox"
label="Nur aktuellen Stg anzeigen"
v-model="studiengang_kz_intern"
:disabled="!stg_kz"
@update:model-value="() => $nextTick($refs.table.reloadTable)"
>
</form-input>
</div>
</div>
<core-filter-cmpt
@@ -129,5 +223,6 @@ export default {
:tabulator-options="tabulatorOptions"
>
</core-filter-cmpt>
<konto-edit ref="edit" :config="config" @saved="updateData"></konto-edit>
</div>`
};
@@ -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: `
<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
v-if="config.showBuchungsnr"
v-model="data.buchungsnr"
name="buchungsnr"
label="Buchungsnr"
disabled
>
</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"
>
</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.buchungstyp_kurzbz"
name="buchungstyp_kurzbz"
label="Typ"
>
<option v-for="typ in lists.buchungstypen" :key="typ.buchungstyp_kurzbz" :value="typ.buchungstyp_kurzbz" :class="typ.aktiv ? '' : 'text-decoration-line-through text-muted'">
{{ typ.beschreibung }}
</option>
</form-input>
<form-input
type="select"
v-model="data.studiensemester_kurzbz"
name="studiensemester_kurzbz"
label="Studiensemester"
>
<option v-for="sem in lists.studiensemester" :key="sem.studiensemester_kurzbz" :value="sem.studiensemester_kurzbz">
{{ sem.studiensemester_kurzbz }}
</option>
</form-input>
<form-input
type="select"
v-model="data.studiengang_kz"
name="studiengang_kz"
label="Studiengang"
>
<option v-for="stg in lists.stgs" :key="stg.studiengang_kz" :value="stg.studiengang_kz">
{{ stg.kuerzel }}
</option>
</form-input>
<form-input
v-if="config.showCreditpoints"
v-model="data.credit_points"
name="credit_points"
label="Credit Points"
>
</form-input>
<form-input
v-model="data.zahlungsreferenz"
name="zahlungsreferenz"
label="Zahlungsreferenz"
disabled
>
</form-input>
<form-input
type="textarea"
v-model="data.anmerkung"
name="anmerkung"
label="Anmerkung"
>
</form-input>
</fieldset>
<template #title>
Edit Buchung #{{data.buchungsnr}}
</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>`
};
@@ -600,7 +600,7 @@ export default {
name="studiengang_kz"
v-model="formDataStg"
>
<option v-for="stg in lists.stgs" :key="stg.studiengang_kz" :value="stg.studiengang_kz">{{stg.kuerzel}}</option>
<option v-for="stg in lists.active_stgs" :key="stg.studiengang_kz" :value="stg.studiengang_kz">{{stg.kuerzel}}</option>
</form-input>
</div>
<div class="col-sm-4 mb-3">