Studierendenverwaltung Projektarbeit: added Verträge

This commit is contained in:
Alexei Karpenko
2025-06-13 16:19:53 +02:00
parent e26bce2cf7
commit d15d27b3e1
10 changed files with 457 additions and 64 deletions
@@ -127,7 +127,11 @@ class Config extends FHCAPI_Controller
$result['projektarbeit'] = [
'title' => $this->p->t('stv', 'tab_projektarbeit'),
'component' => './Stv/Studentenverwaltung/Details/Projektarbeit.js',
'config' => $config['projektarbeit']
'config' => array_merge(
$config['projektarbeit'],
['showVertragsdetails' =>
defined('FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN') && FAS_STUDIERENDE_PROJEKTARBEIT_VERTRAGSDETAILS_ANZEIGEN]
)
];
$result['mobility'] = [
@@ -98,7 +98,7 @@ class Projektbetreuer extends FHCAPI_Controller
$downloadLink = $value;
}
);
$pb->projektarbeitDownload = $downloadLink;
$pb->beurteilungDownloadLink = $downloadLink;
}
$this->terminateWithSuccess($this->_addFullNameToBetreuer($projektbetreuer));
@@ -0,0 +1,104 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
class Vertrag extends FHCAPI_Controller
{
public function __construct()
{
parent::__construct([
'getVertrag' => ['admin:r', 'assistenz:r'],
'cancelVertrag' => ['admin:r', 'assistenz:r']
]);
// Load Libraries
$this->load->library('form_validation');
// Load language phrases
$this->loadPhrases([
'ui',
'person',
'projektarbeit'
]);
// Load models
$this->load->model('accounting/Vertrag_model', 'VertragModel');
$this->load->model('education/Lehrveranstaltung_model', 'LehrveranstaltungModel');
$this->load->model('person/Benutzer_model', 'BenutzerModel');
// load libraries
$this->load->library('PermissionLib');
}
public function getVertrag()
{
$vertrag_id = $this->input->get('vertrag_id');
if (!isset($vertrag_id) || !is_numeric($vertrag_id))
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL);
$result = $this->VertragModel->getVertragById($vertrag_id);
if (isError($result))
{
$this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
}
if (!hasData($result)) $this->terminateWithSuccess([]);
$vertrag = getData($result)[0];
$this->terminateWithSuccess($vertrag);
}
public function cancelVertrag()
{
$vertrag_id = $this->input->post('vertrag_id');
$person_id = $this->input->post('person_id');
if (!isset($vertrag_id) || !is_numeric($vertrag_id))
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Vertrag ID']), self::ERROR_TYPE_GENERAL);
if (!isset($person_id) || !is_numeric($person_id))
$this->terminateWithError($this->p->t('ui', 'error_missingId', ['id'=> 'Person ID']), self::ERROR_TYPE_GENERAL);
// * first find lehrveranstaltung_id of the contracts lehrveranstaltung
$this->VertragModel->addSelect('lehrveranstaltung_id');
$this->VertragModel->addJoin('lehre.tbl_lehrveranstaltung', 'lehrveranstaltung_id', 'LEFT');
$result = $this->VertragModel->loadWhere(['vertrag_id' => $vertrag_id]);
if (isError($result)) $this->terminateWithError(getError($result), self::ERROR_TYPE_GENERAL);
if (!hasData($result)) $this->terminateWithSuccess([]);
$lehrveranstaltung_id = getData($result)[0]->lehrveranstaltung_id;
$allOe = $this->LehrveranstaltungModel->getAllOe($lehrveranstaltung_id);
if (isError($allOe)) $this->terminateWithError(getError($allOe), self::ERROR_TYPE_GENERAL);
$allOe = hasData($allOe) ? getData($allOe) : [];
$this->addMeta('oe', $allOe);
// * then check if the user has permissions to cancel the corresponding lv-organisational units
if (!$this->permissionlib->isBerechtigtMultipleOe('admin', $allOe, 'suid') &&
!$this->permissionlib->isBerechtigtMultipleOe('lehre/lehrauftrag_bestellen', $allOe, 'suid'))
{
return $this->_outputAuthError([$this->router->method => ['admin:rw', 'lehrauftrag_bestellen:rw']]);
}
$uidResult = $this->BenutzerModel->getFromPersonId($person_id);
if (isError($uidResult)) $this->terminateWithError(getError($uidResult), self::ERROR_TYPE_GENERAL);
if (!hasData($uidResult)) $this->terminateWithError("no user found", self::ERROR_TYPE_GENERAL);
$mitarbeiter_uid = getData($uidResult)[0]->uid;
$result = $this->VertragModel->cancelVertrag($vertrag_id, $mitarbeiter_uid);
$data = $this->getDataOrTerminateWithError($result);
$this->terminateWithSuccess($data);
}
}
@@ -402,6 +402,26 @@ class Vertrag_model extends DB_Model
return $this->loadWhere(array('mitarbeiter_uid' => $mitarbeiter_uid, 'lehreinheit_id' => $lehreinheit_id));
}
public function getVertragById($vertrag_id)
{
$this->addSelect(
'tbl_vertrag.vertrag_id, vertragstyp_kurzbz, vertragsstunden, vertragsstunden_studiensemester_kurzbz, status.vertragsstatus_kurzbz,
status.bezeichnung AS vertragsstatus, tbl_vertrag.betrag, lema.semesterstunden, lema.stundensatz'
);
$this->addJoin('lehre.tbl_lehreinheitmitarbeiter lema', 'tbl_vertrag.vertrag_id = lema.vertrag_id', 'LEFT');
$this->addJoin('
(
SELECT DISTINCT ON(vst.vertrag_id) vst.vertrag_id,
bezeichnung,
tbl_vertragsstatus.vertragsstatus_kurzbz
FROM lehre.tbl_vertrag_vertragsstatus vst
JOIN lehre.tbl_vertragsstatus USING(vertragsstatus_kurzbz)
ORDER BY vst.vertrag_id, datum DESC
) as status', 'status.vertrag_id = lehre.tbl_vertrag.vertrag_id', 'LEFT');
return $this->loadWhere(['tbl_vertrag.vertrag_id' => $vertrag_id]);
}
public function cancelVertrag($vertrag_id, $mitarbeiter_uid)
{
$vertrag = $this->load($vertrag_id);
+20
View File
@@ -0,0 +1,20 @@
export default {
getVertrag(vertrag_id)
{
return {
method: 'get',
url: 'api/frontend/v1/stv/vertrag/getVertrag',
params: { vertrag_id },
};
},
cancelVertrag(data)
{
return {
method: 'post',
url: '/api/frontend/v1/stv/vertrag/cancelVertrag/',
params: data
};
}
}
@@ -15,15 +15,13 @@ export default {
defaultSemester: {
from: 'defaultSemester'
}
//~ cisRoot: {
//~ from: 'cisRoot'
//~ },
//~ config: {
//~ from: 'config',
//~ required: true
//~ }
},
computed: {
// prepared Lehreinheiten (with compound Bezeichnung)
arrLes() {
let lehreinheiten = [];
if (this.formData.lehrveranstaltung_id) {
@@ -133,7 +131,6 @@ export default {
//~ //this.$fhcAlert.handleSystemError(promise_result);
//~ }
//~ //let data = promise_result.value.data;
//~ console.log(promise_result.status);
//~ });
//~ if (!hasError) {
@@ -214,6 +211,7 @@ export default {
lvChanged(event) {
this.formData.lehreinheit_id = null;
},
// enrich and modify data before sending
getPreparedFormData() {
let preparedFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy
@@ -30,29 +30,6 @@ export default {
from: '$reloadList',
required: true
}
//~ isBerechtigtDocAndOdt: {
//~ from: 'hasPermissionOutputformat',
//~ default: false
//~ }
},
computed: {
//~ studentUids() {
//~ if (this.student.uid)
//~ {
//~ return [this.student.uid];
//~ }
//~ return this.student.map(e => e.uid);
//~ },
//~ studentKzs(){
//~ if (this.student.uid)
//~ {
//~ return [this.student.studiengang_kz];
//~ }
//~ return this.student.map(e => e.studiengang_kz);
//~ },
//~ stg_kz(){
//~ return this.studentKzs.length > 0 ? this.studentKzs.length[0] : null;
//~ }
},
props: {
student: Object
@@ -271,7 +248,6 @@ export default {
actionEditProjektarbeit(projektarbeit_id, studiensemester_kurzbz, lehrveranstaltung_id, projekttyp_kurzbz) {
this.statusNew = false;
this.$refs.projektarbeitDetails.getFormData(this.statusNew, studiensemester_kurzbz, lehrveranstaltung_id);
// TODO: maybe preload projektarbeit? not just on edit?
this.$refs.projektarbeitDetails.loadProjektarbeit(projektarbeit_id);
this.$refs.projektbetreuer.getData(projektarbeit_id, studiensemester_kurzbz, projekttyp_kurzbz);
this.$refs.projektarbeitModal.show();
@@ -5,6 +5,7 @@ import FormInput from '../../../../Form/Input.js';
import PvAutoComplete from "../../../../../../../index.ci.php/public/js/components/primevue/autocomplete/autocomplete.esm.min.js";
import NewPerson from "../../List/New.js";
import Contact from "../Kontakt/Contact.js";
import Vertrag from "./Vertrag.js";
import ApiStvProjektbetreuer from '../../../../../api/factory/stv/projektbetreuer.js';
@@ -16,9 +17,13 @@ export default {
FormInput,
PvAutoComplete,
NewPerson,
Contact
Contact,
Vertrag
},
inject: {
provide() {
return {
configShowVertragsdetails: this.config.showVertragsdetails
}
},
computed: {
betreuerFormOpened() {
@@ -107,13 +112,13 @@ export default {
initialFormData: null,
defaultFormDataValues: {stunden: null, stundensatz: null},
projektarbeit_id: null,
statusNew: true,
editedBetreuerIdx: -1,
arrBetreuerart: [],
arrNoten: [],
filteredBetreuer: [],
autocompleteSelectedBetreuer: null,
projektarbeitDownload: null,
beurteilungDownloadLink: null,
vertragFieldsDisabled: false,
abortController: {
betreuer: null
}
@@ -122,19 +127,19 @@ export default {
methods: {
actionNewProjektbetreuer() {
this.resetForm();
this.statusNew = true;
this.newMode = !this.newMode;
this.editMode = false;
this.captureFormData();
},
actionEditProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) {
this.statusNew = false;
this.editMode = true;
this.newMode = false;
this.$api
.call(ApiStvProjektbetreuer.getDefaultStundensaetze(person_id, this.studiensemester_kurzbz))
.then(result => {
this.resetForm();
// get betreuer from tabulator list
let projektbetreuerListe = this.$refs.projektbetreuerTable.tabulator.getData();
const idx = projektbetreuerListe.findIndex(
betr =>
@@ -144,18 +149,29 @@ export default {
);
let betreuer = [];
if (idx >= 0) {
if (idx >= 0) { // if betreuer found
betreuer = projektbetreuerListe[idx];
// set currently edited betreuera
this.formData = betreuer;
if (betreuer.projektarbeitDownload) this.projektarbeitDownload = betreuer.projektarbeitDownload
// set download link
if (betreuer.beurteilungDownloadLink) this.beurteilungDownloadLink = betreuer.beurteilungDownloadLink
// set betreuer for autocomplete field
this.autocompleteSelectedBetreuer = {
person_id: this.formData.person_id,
name: this.formData.name,
vorname: this.formData.vorname,
nachname: this.formData.nachname
nachname: this.formData.nachname,
vertrag_id: this.formData.vertrag_id
};
}
// set default stundensatz (if no other is set yet)
if (this.formData.stundensatz == null) this.formData.stundensatz = result.data;
// capture initial form data for detecting changes
this.captureFormData();
})
.catch(this.$fhcAlert.handleSystemError);
@@ -167,10 +183,12 @@ export default {
? {projektarbeit_id, person_id, betreuerart_kurzbz}
: Promise.reject({handled: true}))
.then(result => {
return this.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz)
return this.$api
.call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz))
})
.then(result => {
this.$refs.projektbetreuerTable.tabulator.deleteRow(betreuer_id);
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError);
},
@@ -178,9 +196,12 @@ export default {
this.studiensemester_kurzbz = studiensemester_kurzbz;
// default Stundensätze from config
this.defaultFormDataValues.stunden = this.getDefaultStunden(projekttyp_kurzbz);
this.defaultFormDataValues.stundensatz = this.config.defaultProjektbetreuerStundensatz;
this.resetModes();
// get other initial data
this.$api
.call(ApiStvProjektbetreuer.getBetreuerarten())
.then(result => {
@@ -209,6 +230,7 @@ export default {
this.resetForm();
}
},
// confirming Betreuer means adding/updating him in list (but not yet saving in db)
confirmProjektbetreuer() {
if (!this.betreuerFormOpened) return;
@@ -217,11 +239,9 @@ export default {
this.$refs.projektbetreuerTable.tabulator.addData(this.addAutoCompleteBetreuerToFormData(this.formData));
} else {
this.$refs.projektbetreuerTable.tabulator.updateData([this.formData]);
this.statusNew = true;
}
this.newMode = false;
this.editMode = false;
this.resetModes();
},
confirmProjektbetreuerAfterValidation() {
//if (!this.formDataModified()) return;
@@ -239,14 +259,6 @@ export default {
ApiStvProjektbetreuer.saveProjektbetreuer(projektarbeit_id, this.$refs.projektbetreuerTable.tabulator.getData())
);
},
deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz) {
return this.$api
.call(ApiStvProjektbetreuer.deleteProjektbetreuer(projektarbeit_id, person_id, betreuerart_kurzbz))
.then(response => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
})
.catch(this.$fhcAlert.handleSystemError)
},
searchBetreuer(event) {
if (this.abortController.betreuer) {
this.abortController.betreuer.abort();
@@ -259,6 +271,7 @@ export default {
this.filteredBetreuer = result.data;
});
},
// validate betreuer for data
validateProjektbetreuer() {
let alleBetreuer = this.$refs.projektbetreuerTable.tabulator.getData();
@@ -270,10 +283,15 @@ export default {
},
resetForm() {
this.formData = this.getDefaultFormData();
this.projektarbeitDownload = null;
this.beurteilungDownloadLink = null;
this.autocompleteSelectedBetreuer = null;
this.initialFormData = null;
if (this.projekttyp_kurzbz) this.setDefaultStunden(this.projekttyp_kurzbz);
this.disableVertragFields(false);
},
resetModes() {
this.newMode = false;
this.editMode = false;
},
getDefaultFormData() {
let formData = {betreuerart_kurzbz : null, note: null};
@@ -287,6 +305,7 @@ export default {
captureFormData() {
this.initialFormData = JSON.parse(JSON.stringify(this.formData)); // deep copy
},
// add own betreuer ids to betreuer liste
addIds(betreuerListe) {
for (const idx in betreuerListe) {
@@ -298,6 +317,7 @@ export default {
}
return betreuerListe;
},
// add the betreuer selected in automomplete to betreuer liste
addAutoCompleteBetreuerToFormData() {
let preparedFormData = this.formData;
@@ -311,6 +331,7 @@ export default {
return preparedFormData;
},
// get default values for stunden
getDefaultStunden(projekttyp_kurzbz) {
let stunden = '0.0';
if (projekttyp_kurzbz == 'Bachelor') stunden = this.config.defaultProjektbetreuerStunden;
@@ -319,8 +340,10 @@ export default {
},
setDefaultStunden(projekttyp_kurzbz) {
this.projekttyp_kurzbz = projekttyp_kurzbz;
// if form data has not already been modified by user, set the default stunden
if (!this.formDataModified()) this.formData.stunden = this.getDefaultStunden(projekttyp_kurzbz);
},
// get a new betreuer id (max + 1)
getNewBetreuerId() {
let max = 0;
@@ -330,6 +353,7 @@ export default {
return max + 1;
},
// check if form data has been modified since initial data has been captured
formDataModified() {
if (this.autocompleteSelectedBetreuer != null) return true;
@@ -351,22 +375,27 @@ export default {
if (!this.autocompleteSelectedBetreuer) return;
this.$refs.kontaktdatenModal.show();
},
// stuff to do after new person has been saved
personSaved(result) {
this.$api
.call(ApiStvProjektbetreuer.getPerson(result.person_id))
.then(response => {
// set the new person in autocomplete field
this.autocompleteSelectedBetreuer = response.data;
})
.catch(this.$fhcAlert.handleSystemError)
},
// disable fields which are dependent on Vertrag status
disableVertragFields(disabled) {
this.vertragFieldsDisabled = disabled;
}
},
template: `
<div class="stv-details-projektbetreuer h-100 pb-3 row">
<div class="col-8">
<div :class="this.config.showVertragsdetails ? 'col-8' : 'col-12'">
<legend>{{this.$p.t('projektarbeit','betreuerGross')}}</legend>
<!-- <p v-if="statusNew">[{{$p.t('ui', 'neu')}}]</p> -->
<core-filter-cmpt
ref="projektbetreuerTable"
@@ -392,6 +421,7 @@ export default {
:suggestions="filteredBetreuer"
@complete="searchBetreuer"
:min-length="3"
:disabled="vertragFieldsDisabled"
>
</form-input>
</div>
@@ -448,6 +478,7 @@ export default {
type="text"
name="stunden"
:label="$p.t('projektarbeit', 'stunden')"
:disabled="vertragFieldsDisabled"
v-model="formData.stunden"
>
</form-input>
@@ -459,6 +490,7 @@ export default {
type="text"
name="stundensatz"
:label="$p.t('projektarbeit', 'stundensatz')"
:disabled="vertragFieldsDisabled"
v-model="formData.stundensatz"
>
</form-input>
@@ -469,11 +501,23 @@ export default {
<button class="btn btn-primary" v-show="betreuerFormOpened" @click="confirmProjektbetreuerAfterValidation">
{{ $p.t('projektarbeit', 'betreuerBestaetigen') }}
</button>
<div class = "mt-5">
<div class="mb-1">
<a :href="beurteilungDownloadLink" class="btn btn-primary d-block" :class="{ 'disabled' : !beurteilungDownloadLink || beurteilungDownloadLink == ''}">
{{ $p.t('projektarbeit', 'projektbeurteilungErstellen') }}
</a>
</div>
{{ autocompleteSelectedBetreuer?.person_id && (!beurteilungDownloadLink || beurteilungDownloadLink == '') ? $p.t('projektarbeit', 'projektarbeitNochNichtBeurteilt') : ''}}
</div>
</div>
<div class="col-4" v-if="projektarbeitDownload && projektarbeitDownload != ''">
<a :href="projektarbeitDownload" class="btn btn-primary">{{ $p.t('projektarbeit', 'projektbeurteilungErstellen') }}</a>
<div class="col-4">
<vertrag ref="vertrag"
:vertrag_id="autocompleteSelectedBetreuer?.vertrag_id"
:person_id="autocompleteSelectedBetreuer?.person_id"
:betreuerProjektarbeit="initialFormData"
@vertragsstatusChanged="disableVertragFields">
</vertrag>
</div>
</div>
@@ -485,8 +529,7 @@ export default {
<bs-modal
ref="kontaktdatenModal"
dialog-class="modal-xl modal-dialog-scrollable"
v-if="autocompleteSelectedBetreuer && autocompleteSelectedBetreuer.person_id"
>
v-if="autocompleteSelectedBetreuer && autocompleteSelectedBetreuer.person_id">
<template #title>
<p class="fw-bold mt-3">{{$p.t('projektarbeit', 'kontaktdatenBearbeiten')}}</p>
@@ -0,0 +1,168 @@
import CoreForm from '../../../../Form/Form.js';
import FormInput from '../../../../Form/Input.js';
import ApiVertrag from '../../../../../api/factory/stv/vertrag.js';
export default{
name: "ProjektarbeitVertrag",
components: {
CoreForm,
FormInput
},
emits: [
'canceledVertrag',
'vertragsstatusChanged'
],
props: {
vertrag_id: Number,
person_id: Number,
betreuerProjektarbeit: Object
},
inject: {
showVertragsdetails: {
from: 'configShowVertragsdetails',
default: false
}
},
data() {
return{
data: {
vertragsstatus: null,
vertragsstunden: null,
vertragsstunden_studiensemester_kurzbz: null
},
// status names for stages of Vertrag ("constants")
vertragsstatus_akzeptiert: 'Akzeptiert',
vertragsstatus_geaendert:'Geändert',
vertragsstatus_storniert: 'Storniert',
}
},
watch: {
vertrag_id:
{
//deep: true,
handler(newVal, oldVal) {
this.setDefaultData();
if (newVal !== null && newVal !== undefined) this.getVertrag();
}
},
},
computed: {
vertragsstatus() {
// not show Vertragsstatus if no data
if (!this.data?.vertragsstatus || !this.betreuerProjektarbeit?.betreuerart_kurzbz) return;
const betragVertrag = Number(this.data.betrag) || 0;
const stundenVertrag = Number(this.data.vertragsstunden) || 0;
const semStunden = Number(this.betreuerProjektarbeit.stunden) || 0;
const stundensatz = Number(this.betreuerProjektarbeit.stundensatz) || 0;
const kostenAktuell = semStunden * stundensatz;
// Vertragsstunden amount should be same as Semesterstunden amount, otherwise there has been a change
let vertragsstatus = (stundenVertrag !== semStunden || betragVertrag !== kostenAktuell)
? this.vertragsstatus_geaendert
: (this.data.vertragsstatus || '');
// vertragsstatus changed to "akzeptiert"
this.$emit('vertragsstatusChanged', vertragsstatus == this.vertragsstatus_akzeptiert);
return vertragsstatus;
},
},
methods: {
getVertrag() {
if (this.showVertragsdetails === false)
return;
if (!this.vertrag_id)
return;
this.$api.call(ApiVertrag.getVertrag(this.vertrag_id))
.then(result => {
this.data = result.data;
})
.catch(this.$fhcAlert.handleSystemError);
},
cancelVertrag() {
this.$fhcAlert
.confirmDelete()
.then(result => result
? {vertrag_id: this.vertrag_id, person_id: this.person_id}
: Promise.reject({handled: true}))
.then(result => {
this.$api.call(ApiVertrag.cancelVertrag({vertrag_id: this.vertrag_id, person_id: this.person_id}))
})
.then(result => {
this.setDefaultData();
this.$emit('canceledVertrag');
// vertragsstatus not "akzeptiert" anymore
this.$emit('vertragsstatusChanged', false);
})
.catch(this.$fhcAlert.handleSystemError);
},
setDefaultData() {
this.data.vertragsstatus = null;
this.data.vertragsstunden = null;
this.data.vertragsstunden_studiensemester_kurzbz = null;
}
},
template: `
<core-form ref="form">
<fieldset class="overflow-hidden" v-if="showVertragsdetails">
<legend>
{{$p.t('lehre', 'vertragsdetails')}}
</legend>
<div class="mb-3">
{{ betreuerProjektarbeit?.betreuerart_kurzbz && betreuerProjektarbeit?.vertrag_id == null ? ' '+$p.t('lehre', 'nochKeinVertrag') : '' }}
</div>
<div class="row align-items-end mb-3">
<form-input
:label="$p.t('lehre', 'vertragsstatus')"
type="text"
readonly
v-model="vertragsstatus"
:style="{fontWeight: vertragsstatus === this.vertragsstatus_geaendert ? 'bold' : 'normal'}"
name="vertragsstatus"
/>
</div>
{{$p.t('lehre', 'vertragurfassung')}}
<div class="row mb-3">
<form-input
:label="$p.t('lehre', 'semesterstunden')"
type="text"
readonly
v-model="data.vertragsstunden"
name="vertragsstunden"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
:label="$p.t('lehre', 'studiensemester')"
type="text"
readonly
v-model="data.vertragsstunden_studiensemester_kurzbz"
name="vertragsstunden_studiensemester_kurzbz"
>
</form-input>
</div>
<div class="row mb-3" v-if="data?.vertragsstatus">
<div class="col-12">
<button
type="button"
class="btn btn-outline-secondary"
:disabled="vertragsstatus == vertragsstatus_storniert"
@click="cancelVertrag"
>
{{ $p.t('lehre', 'stornieren') }}
</button>
</div>
</div>
</fieldset>
</core-form>
`
};
+64 -4
View File
@@ -43063,7 +43063,7 @@ and represent the current state of research on the topic. The prescribed citatio
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Betreuer',
'text' => 'BetreuerIn',
'description' => '',
'insertvon' => 'system'
),
@@ -43083,7 +43083,7 @@ and represent the current state of research on the topic. The prescribed citatio
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Betreuer',
'text' => 'BetreuerIn',
'description' => '',
'insertvon' => 'system'
),
@@ -43183,7 +43183,7 @@ and represent the current state of research on the topic. The prescribed citatio
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Betreuer bestätigen',
'text' => 'BetreuerIn bestätigen',
'description' => '',
'insertvon' => 'system'
),
@@ -43754,7 +43754,67 @@ and represent the current state of research on the topic. The prescribed citatio
'insertvon' => 'system'
)
)
)
),
array(
'app' => 'core',
'category' => 'projektarbeit',
'phrase' => 'projektarbeitNochNichtBeurteilt',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Projektarbeit ist noch nicht beurteilt',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Projekt work was not assessed yet',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'stornieren',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Stornieren',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'Cancel',
'description' => '',
'insertvon' => 'system'
)
)
),
array(
'app' => 'core',
'category' => 'lehre',
'phrase' => 'nochKeinVertrag',
'insertvon' => 'system',
'phrases' => array(
array(
'sprache' => 'German',
'text' => 'Noch kein Vertrag',
'description' => '',
'insertvon' => 'system'
),
array(
'sprache' => 'English',
'text' => 'No contract yet',
'description' => '',
'insertvon' => 'system'
)
)
),
);