Compare commits

...

24 Commits

Author SHA1 Message Date
Harald Bamberger b0fea017f2 further progress on rendering partMenu 2026-05-29 08:42:02 +02:00
Harald Bamberger 861623750d Merge branch 'master' of github.com:FH-Complete/FHC-Core into bhdev_treemenu 2026-05-13 21:14:35 +02:00
Harald Bamberger cb7a0f7669 Merge branch 'feature-70376/Lohnguide' 2026-05-13 11:53:14 +02:00
Harald Bamberger 68d97a5e97 handle case where old value or new value and not both are null explicitly in markDirty Method 2026-05-13 11:42:25 +02:00
Harald Bamberger d27071528f revert change to comparision in markDirty Method 2026-05-13 11:16:18 +02:00
Harald Bamberger 17772c3738 Merge branch 'master' into feature-70376/Lohnguide 2026-05-13 11:15:07 +02:00
Harald Bamberger 51d73c862b treemenu trial 2026-05-11 16:42:48 +02:00
Harald Bamberger bbb4f8a01c Merge branch 'bug-76146/studvw_karteireiter_dokumente_akzeptiert_eintraege_ohne_vorhandenes_dokument' 2026-05-06 16:13:50 +02:00
Harald Bamberger fdbb93a5c5 bugfix download booking receipt failed. only fetch oehbeitrag from bis.tbl_oehbeitrag if a user is logged in 2026-05-05 14:36:07 +02:00
Harald Bamberger b7e48633ab Merge branch 'master' into bug-76146/studvw_karteireiter_dokumente_akzeptiert_eintraege_ohne_vorhandenes_dokument 2026-05-05 13:33:38 +02:00
Harald Bamberger 04dc1eb07b Merge branch 'bug-76519/StudVW_Messages_Table_column_Stati' 2026-05-05 13:04:58 +02:00
Harald Bamberger 50b229090b prefetch phrases and then render filter component instead of redrawing the table 2026-05-05 13:04:11 +02:00
Harald Bamberger 2d27a998c4 Merge branch 'bug-76109/VVW_Details_und_Status_not_Loading' 2026-05-05 11:17:49 +02:00
Harald Bamberger 090e535466 add header filters, increase height of tables, use correct category for phrase lehreinheit_id 2026-05-05 11:04:48 +02:00
Harald Bamberger c4d35181db Merge branch 'master' into bug-76109/VVW_Details_und_Status_not_Loading 2026-05-05 09:01:49 +02:00
Harald Bamberger 0ac6ef4599 Merge branch 'feature-62607/konto_oh_beitrag_betrag_aus_eigener_tabelle' 2026-05-05 08:46:22 +02:00
Werner Masik 7f13c128f1 allow null value for vordienstzeit; changed comparison in markDirty to !== (because of 0 vs. null issue) 2026-05-04 20:35:51 +02:00
Harald Bamberger cb60ddcc94 Merge branch 'master' into feature-62607/konto_oh_beitrag_betrag_aus_eigener_tabelle 2026-05-04 15:41:52 +02:00
Harald Bamberger bd4ced9559 bugfix: comma as decimal separator prevents saving booking, bugfix messages tinymce not resizeable 2026-05-04 14:39:19 +02:00
Werner Masik 58a921b500 changed lohnguide kommentar data type to text 2026-04-30 09:47:12 +02:00
ma0068 26db4a5e7a adding redraw tabulator and fallback to avoid empty column 2026-04-20 09:31:52 +02:00
ma0048 21d80905a2 akzeptierte dokumente anzeigen, auch wenn kein dokument vorhanden ist 2026-04-13 13:04:46 +02:00
ma0068 298dbbf400 use context vm for tabulator event, refactor function toggleRowClick, delete unused commented sections 2026-04-02 10:58:49 +02:00
ma0048 ba6224bc78 oeh betrag aus der eigener tabelle holen
studentenverwaltung bei jedem studiensemester wechsel
fas nur einmalig ueber die variable
2025-09-02 11:18:24 +02:00
22 changed files with 534 additions and 238 deletions
+45
View File
@@ -0,0 +1,45 @@
<?php
if (! defined('BASEPATH')) exit('No direct script access allowed');
$config['stv_menu'] = array(
'library' => 'treemenu/StvMenuLib',
'children' => array(
'stg' => array(
'library' => 'treemenu/StgLib',
/*
'children' => array(
'pre' => array(
'library' => 'treemenu/PrestudentLib'
),
'sem' => array(
'library' => 'treemenu/AusbSemesterLib',
'children' => array(
'vbd' => array(
'library' => 'treemenu/VerbandLib'
)
)
),
'orgform' => array(
'library' => 'treemenu/OrgFormLib',
'children' => array(
'pre' => array(
'library' => 'treemenu/PrestudentLib'
),
'sem' => array(
'library' => 'treemenu/AusbSemesterLib',
'children' => array(
'vbd' => array(
'library' => 'treemenu/VerbandLib'
)
)
)
)
)
)
*/
),
'inout' => array(
'library' => 'treemenu/InOutLib'
),
)
);
@@ -0,0 +1,109 @@
<?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 verbände
* This controller works with JSON calls on the HTTP GET or POST and the output is always JSON
*/
class TreeMenu extends FHCAPI_Controller
{
protected $treemenuconfig;
public function __construct()
{
parent::__construct([
'fullMenu' => ['admin:r', 'assistenz:r'],
'partMenu' => ['admin:r', 'assistenz:r'],
]);
}
public function fullMenu($treemenu=null)
{
if(is_null($treemenu))
{
$this->terminateWithError('missing parameter treemenu.');
}
$this->loadMenuConfig($treemenu);
$bhdebug = (object) array(
'treemenu' => $treemenu,
'treemenuconfig' => $this->treemenuconfig
);
$this->addMeta('bhdebug', $bhdebug);
$data = array();
$this->terminateWithSuccess($data);
}
public function partMenu($treemenu=null)
{
if(is_null($treemenu))
{
$this->terminateWithError('missing parameter treemenu.');
}
$this->loadMenuConfig($treemenu);
$startconfig = $this->findStartLib($this->treemenuconfig, array_keys($this->uri->uri_to_assoc(7)));
$libpath = $startconfig['library'];
$children = isset($startconfig['children']) ? $startconfig['children'] : array();
$libname = basename($startconfig['library']);
$this->load->library(
$libpath,
$children,
$libname
);
$bhdebug = (object) array(
'treemenu' => $treemenu,
'treemenuconfig' => $this->treemenuconfig,
'uri' => $this->uri->uri_to_assoc(7),
'libpath' => $libpath,
'libname' => $libname,
'children' => $children,
'startconfig' => $startconfig
);
$this->addMeta('bhdebug', $bhdebug);
//$this->addMeta('bhci', $this);
$data = $this->$libname->getSubMenu();
$this->terminateWithSuccess($data);
}
protected function findStartLib($config, $uri)
{
$level = array_shift($uri);
if(is_null($level)) {
return $config;
}
return $this->findStartLib($config['children'][$level], $uri);
}
protected function loadMenuConfig($treemenu)
{
$this->config->load('treemenu/' . $treemenu . '.php');
$this->treemenuconfig = $this->config->item($treemenu);
}
}
@@ -78,52 +78,32 @@ class Dokumente extends FHCAPI_Controller
$this->terminateWithError($this->p->t('ui', 'errorMissingValue', ['value' => 'Studiengang_kz']), self::ERROR_TYPE_GENERAL);
$resultPreDoc = $this->_getPrestudentDokumente($prestudent_id);
$arrayAccepted = [];
$person_id = $this->_getPersonId($prestudent_id);
$docNames = array_map(function ($item) {
return $item->dokument_kurzbz;
}, $resultPreDoc);
$mergedArray = [];
foreach($docNames as $doc)
foreach ($resultPreDoc as $pre)
{
$result = $this->AkteModel->getAktenFAS($person_id, $doc, $studiengang_kz, $prestudent_id, true);
$result = $this->AkteModel->getAktenFAS($person_id, $pre->dokument_kurzbz, $studiengang_kz, $prestudent_id, true);
if (isError($result))
{
return $this->terminateWithError($result, self::ERROR_TYPE_GENERAL);
}
if (hasData($result))
{
$data = getData($result);
foreach ($data as $value)
foreach (getData($result) as $doc)
{
array_push($arrayAccepted, $value);
$merged = clone $doc;
$merged->docdatum = $pre->docdatum;
$merged->insertvonma = $pre->insertvonma;
$merged->bezeichnung = $pre->bezeichnung;
$mergedArray[] = $merged;
}
}
}
//Mapping with document_kurzbz
$preDocMap = [];
foreach ($resultPreDoc as $pre) {
$preDocMap[$pre->dokument_kurzbz] = $pre;
}
$mergedArray = [];
foreach ($arrayAccepted as $doc) {
$merged = clone $doc;
if (isset($preDocMap[$doc->dokument_kurzbz])) {
$merged->docdatum = $preDocMap[$doc->dokument_kurzbz]->docdatum;
$merged->insertvonma = $preDocMap[$doc->dokument_kurzbz]->insertvonma;
$merged->bezeichnung = $preDocMap[$doc->dokument_kurzbz]->bezeichnung;
} else {
$merged->akzeptiertdatum = null;
$merged->akzeptiertvon = null;
else
{
$mergedArray[] = $pre;
}
$mergedArray[] = $merged;
}
$this->terminateWithSuccess($mergedArray);
@@ -48,7 +48,8 @@ class Konto extends FHCAPI_Controller
// Load language phrases
$this->loadPhrases([
'konto'
'konto',
'lehre'
]);
}
@@ -112,7 +113,7 @@ class Konto extends FHCAPI_Controller
*
* @return void
*/
public function getBuchungstypen()
public function getBuchungstypen($studiensemester_kurzbz = null)
{
$this->load->model('crm/Buchungstyp_model', 'BuchungstypModel');
@@ -122,6 +123,7 @@ class Konto extends FHCAPI_Controller
$data = $this->getDataOrTerminateWithError($result);
$this->_getOEHBeitrag($data, $studiensemester_kurzbz);
$this->terminateWithSuccess($data);
}
@@ -494,4 +496,43 @@ class Konto extends FHCAPI_Controller
$this->terminateWithSuccess();
}
private function _getOEHBeitrag(&$data, $studiensemester_kurzbz = null)
{
if (is_null($studiensemester_kurzbz))
{
$this->load->library('VariableLib', ['uid' => getAuthUID()]);
$studiensemester_akt = $this->variablelib->getVar('semester_aktuell');
}
else
{
$this->load->model('organisation/Studiensemester_model', 'StudiensemesterModel');
if ($this->StudiensemesterModel->isValidStudiensemester($studiensemester_kurzbz))
$studiensemester_akt = $studiensemester_kurzbz;
else
$this->terminateWithError($this->p->t('lehre', 'error_noStudiensemester'));
}
$this->load->model('codex/Oehbeitrag_model', 'OehbeitragModel');
$oehBeitrag = $this->OehbeitragModel->getByStudiensemester($studiensemester_akt);
$oehStandardbetrag = null;
if (hasData($oehBeitrag))
{
$oeh = getData($oehBeitrag)[0];
$summe = ($oeh->studierendenbeitrag + $oeh->versicherung) * -1;
$oehStandardbetrag = number_format((float)$summe, 2, '.', '');
}
if ($oehStandardbetrag !== null)
{
$data = array_map(function ($buchungstyp) use ($oehStandardbetrag) {
if (isset($buchungstyp->buchungstyp_kurzbz) && (strtolower($buchungstyp->buchungstyp_kurzbz) === 'oeh'))
{
$buchungstyp->standardbetrag = $oehStandardbetrag;
}
return $buchungstyp;
}, $data);
}
}
}
@@ -0,0 +1,42 @@
<?php
require_once APPPATH . 'libraries/treemenu/TreeMenuLib.php';
/**
* Description of InOutLib
*
* @author bambi
*/
class InOutLib extends TreeMenuLib
{
public function getNodes()
{
return [
[
'name' => 'International',
'link' => 'inout',
'children' => [
[
'name' => 'Incoming',
'link' => 'inout/incoming',
'leaf' => true
],
[
'name' => 'Outgoing',
'link' => 'inout/outgoing',
'leaf' => true
],
[
'name' => 'Gemeinsame Studien',
'link' => 'inout/gemeinsamestudien',
'leaf' => true
]
]
]
];
}
public function getSubMenu()
{
return [];
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
require_once APPPATH . 'libraries/treemenu/TreeMenuLib.php';
/**
* Description of InOutLib
*
* @author bambi
*/
class StgLib extends TreeMenuLib
{
public function getNodes()
{
$this->ci->load->model('organisation/Studiengang_model', 'StudiengangModel');
$res = $this->ci->StudiengangModel->loadWhere(array('aktiv' => true));
$stgs = hasData($res) ? getData($res) : array();
$this->ci->addMeta('bhstg', $stgs);
$nodes = array_map(
function($stg) {
return array(
'name' => strtoupper($stg->typ . $stg->kurzbz) . ' ' . $stg->bezeichnung,
'link' => 'stg/' . $stg->studiengang_kz,
'leaf' => false
);
},
$stgs
);
return $nodes;
}
public function getSubMenu()
{
return [
'StgLib' => 'test123'
];
}
}
@@ -0,0 +1,23 @@
<?php
require_once APPPATH . 'libraries/treemenu/TreeMenuLib.php';
/**
* Description of StvMenuLib
*
* @author bambi
*/
class StvMenuLib extends TreeMenuLib
{
public function getSubMenu()
{
$nodes = array();
foreach($this->children_config as $childconfig)
{
$childlib = basename($childconfig['library']);
$childnodes = $this->ci->$childlib->getNodes();
$nodes = array_merge($nodes, $childnodes);
}
return $nodes;
}
}
@@ -0,0 +1,39 @@
<?php
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Scripting/PHPClass.php to edit this template
*/
/**
* Description of InOutLib
*
* @author bambi
*/
abstract class TreeMenuLib
{
protected $ci;
protected $children_config;
public function __construct($children_config)
{
$this->ci =& get_instance();
$this->children_config = $children_config;
foreach($this->children_config as $child_config)
{
$grandchildren_config = isset($child_config['children']) ? $child_config['children'] : [];
$this->ci->load->library($child_config['library'], $grandchildren_config, basename($child_config['library']));
}
}
public function getNode($name)
{
$node = array(
'name' => $name
);
return $node;
}
public abstract function getSubMenu();
}
@@ -40,7 +40,9 @@ abstract class AbstractBestandteil implements IValidation
if( is_bool($new_value) && ($old_value !== $new_value) ) {
$this->modifiedcolumns[$columnname] = $columnname;
} else if($old_value != $new_value) {
} else if(is_null($old_value) xor is_null($new_value)) {
$this->modifiedcolumns[$columnname] = $columnname;
} else if($old_value != $new_value) {
$this->modifiedcolumns[$columnname] = $columnname;
}
}
@@ -137,19 +137,25 @@ EOTXT;
return parent::__toString() . $txt;
}
/* public function validate()
public function validate()
{
if( !(filter_var($this->tage, FILTER_VALIDATE_INT,
array(
'options' => array(
'min_range' => 1,
'max_range' => 50
)
)
)) ) {
$this->validationerrors[] = 'Urlaubsanspruch muss eine Tagesanzahl im Bereich 1 bis 50 sein.';
$value = $this->vordienstzeit;
if ($value === null || $value === '') {
$result = null; // allow null value
} else {
$result = filter_var($value, FILTER_VALIDATE_INT, [
'options' => [
'min_range' => 0,
'max_range' => 100
]
]);
if ($result === false) {
$this->validationerrors[] = 'Vordienstjahre muss eine ganze Zahl (0 bis 100) enthalten oder leer sein.';
}
}
return parent::validate();
} */
}
}
+49 -1
View File
@@ -25,6 +25,7 @@
*/
require_once(dirname(__FILE__).'/basis_db.class.php');
require_once(dirname(__FILE__).'/'.EXT_FKT_PATH.'/generateZahlungsreferenz.inc.php');
require_once(dirname(__FILE__).'/variable.class.php');
class konto extends basis_db
{
@@ -432,6 +433,8 @@ class konto extends basis_db
$qry.=" ORDER BY beschreibung";
$oehBeitrag = $this->_getOEHBeitrag();
if($this->db_query($qry))
{
while($row = $this->db_fetch_object())
@@ -440,7 +443,15 @@ class konto extends basis_db
$typ->buchungstyp_kurzbz = $row->buchungstyp_kurzbz;
$typ->beschreibung = $row->beschreibung;
$typ->standardbetrag = $row->standardbetrag;
if (strtolower($typ->buchungstyp_kurzbz) === 'oeh' && $oehBeitrag)
{
$typ->standardbetrag = $oehBeitrag;
}
else
{
$typ->standardbetrag = $row->standardbetrag;
}
$typ->standardtext = $row->standardtext;
$typ->credit_points = $row->credit_points;
$typ->aktiv = $this->db_parse_bool($row->aktiv);
@@ -990,6 +1001,43 @@ class konto extends basis_db
return false;
}
}
private function _getOEHBeitrag()
{
if(!is_user_logged_in())
{
return false;
}
$variablen_obj = new variable();
$variablen_obj->loadVariables(get_uid());
$qry = "WITH semstart AS (
SELECT start FROM public.tbl_studiensemester
WHERE studiensemester_kurzbz = '". $this->db_escape($variablen_obj->variable->semester_aktuell) . "'
)
SELECT * FROM bis.tbl_oehbeitrag oehb
JOIN public.tbl_studiensemester semvon ON oehb.von_studiensemester_kurzbz = semvon.studiensemester_kurzbz
LEFT JOIN public.tbl_studiensemester sembis ON oehb.bis_studiensemester_kurzbz = sembis.studiensemester_kurzbz
JOIN semstart ON semstart.start::date >= semvon.start::date AND (sembis.studiensemester_kurzbz IS NULL OR semstart.start::date <= sembis.start::date)
ORDER BY semvon.start
LIMIT 1";
if ($this->db_query($qry))
{
if($row = $this->db_fetch_object())
{
$summe = ($row->studierendenbeitrag + $row->versicherung) * -1;
return number_format((float)$summe, 2, '.', '');
}
return false;
}
else
{
$this->errormsg = 'Fehler bei der Abfrage aufgetreten';
return false;
}
}
}
?>
-4
View File
@@ -197,10 +197,6 @@ html.fs_huge {
margin-bottom: -1px;
}
.tiny-90 div.tox.tox-tinymce {
height: 90%;
}
/* slim begin */
.stv .form-label {
margin-bottom: .15rem;
+15 -3
View File
@@ -38,6 +38,10 @@ export default {
};
},
insert(params) {
if(params.betrag)
{
params.betrag = params.betrag.replace(',', '.');
}
return {
method: 'post',
url: 'api/frontend/v1/stv/konto/insert',
@@ -52,6 +56,10 @@ export default {
};
},
edit(params) {
if(params.betrag)
{
params.betrag = params.betrag.replace(',', '.');
}
return {
method: 'post',
url: 'api/frontend/v1/stv/konto/update',
@@ -65,10 +73,14 @@ export default {
params: { buchungsnr }
};
},
getBuchungstypen() {
getBuchungstypen(studiensemester_kurzbz) {
let url = 'api/frontend/v1/stv/konto/getBuchungstypen'
if (!!studiensemester_kurzbz)
url = url + '/' + encodeURIComponent(studiensemester_kurzbz);
return {
method: 'get',
url: 'api/frontend/v1/stv/konto/getBuchungstypen'
url: url
};
}
},
};
@@ -63,7 +63,7 @@ export default {
const vm = this;
tinymce.init({
target: this.$refs.editor.$refs.input, //Important: not selector: to enable multiple import of component
height: 700,
min_height: 300,
//plugins: ['lists'],
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | link',
plugins: 'link',
@@ -313,7 +313,7 @@ export default {
<div class="row">
<div class="col-sm-8">
<form-form class="row g-3 mt-2 h-100" ref="formMessage">
<form-form class="row g-3 mt-2 align-content-start" ref="formMessage">
<div class="row mb-3">
@@ -338,14 +338,14 @@ export default {
</div>
<!--Tiny MCE-->
<div class="row mb-3 h-100 tiny-90">
<div class="row mb-3 tiny-90">
<form-input
ref="editor"
:label="$p.t('global','nachricht') + ' *'"
type="textarea"
v-model="formData.body"
name="body"
rows="75"
rows="35"
cols="75"
>
</form-input>
@@ -62,7 +62,7 @@ export default {
const vm = this;
tinymce.init({
target: this.$refs.editor.$refs.input, //Important: not selector: to enable multiple import of component
//height: 800,
min_height: 300,
//plugins: ['lists'],
toolbar: 'styleselect | bold italic underline | alignleft aligncenter alignright alignjustify | link',
plugins: 'link',
@@ -30,6 +30,7 @@ export default {
personId: null,
layoutColumnsOnNewData: false,
height: '400',
arePhrasesLoaded: false
}
},
methods: {
@@ -195,7 +196,7 @@ export default {
],
formatter: (cell, formatterParams) => {
const key = formatterParams[cell.getValue()];
return this.$p.t('messages', key);
return this.$p?.t?.('messages', key) || key;
},
},
{
@@ -305,8 +306,6 @@ export default {
{
event: 'tableBuilt',
handler: async() => {
await this.$p.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz']);
const setHeader = (field, text) => {
const col = this.$refs.table.tabulator.getColumn(field);
if (!col) return;
@@ -357,6 +356,12 @@ export default {
});*/
},
created(){
this.$p
.loadCategory(['global', 'person', 'stv', 'messages', 'ui', 'notiz'])
.then(() => {
this.arePhrasesLoaded = true;
});
if(this.typeId != 'person_id' && Array.isArray(this.id) && this.id.length === 1) {
const params = {
id: this.id,
@@ -381,6 +386,7 @@ export default {
<!--table-->
<div class="col-sm-6 pt-1">
<core-filter-cmpt
v-if="arePhrasesLoaded"
ref="table"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
@@ -413,6 +419,7 @@ export default {
<div class="col-sm-12 pt-6">
<core-filter-cmpt
ref="table"
v-if="arePhrasesLoaded"
:tabulator-options="tabulatorOptions"
:tabulator-events="tabulatorEvents"
table-only
@@ -83,6 +83,8 @@ export default {
});
},
open() {
this.getBuchungstypen(this.currentSemester);
this.data = {
buchungstyp_kurzbz: '',
betrag: '-0.00',
@@ -105,7 +107,7 @@ export default {
const text = typ.standardtext || '';
const creditpoints = typ.credit_points || '';
if (!this.data.betrag || this.data.betrag == '-0.00')
if (!this.data.betrag || this.data.betrag == '-0.00' || this.data.betrag !== amount)
this.data.betrag = amount;
if (!this.data.buchungstext)
@@ -113,7 +115,18 @@ export default {
if (this.config.showCreditpoints && (this.data.credit_points == '0.00' || this.data.credit_points === null))
this.data.credit_points = creditpoints;
}
},
getBuchungstypen(studiensemester_kurzbz)
{
this.$api
.call(ApiKonto.getBuchungstypen(studiensemester_kurzbz))
.then(result => {
this.lists.buchungstypen = result.data;
if (this.data.buchungstyp_kurzbz)
this.checkDefaultBetrag(this.data.buchungstyp_kurzbz);
})
.catch(this.$fhcAlert.handleSystemError);
},
},
template: `
<core-form ref="form" class="stv-details-konto-edit" @submit.prevent="save">
@@ -166,6 +179,7 @@ export default {
<form-input
type="select"
v-model="data.studiensemester_kurzbz"
@change="getBuchungstypen(data.studiensemester_kurzbz)"
name="studiensemester_kurzbz"
:label="$p.t('lehre/studiensemester')"
>
+13 -13
View File
@@ -41,8 +41,8 @@ export default {
),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "Typ", field: "type"},
{title: "Betrag", field: "betrag",
{title: "Typ", field: "type", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{title: "Betrag", field: "betrag", headerFilter: true,
formatter: function(cell) {
let value = cell.getValue();
if (value == null) {
@@ -51,14 +51,14 @@ export default {
return parseFloat(value).toFixed(2);
}
},
{title: "Bezeichnung", field: "bezeichnung"},
{title: "Studiensemester", field: "studiensemester_kurzbz"},
{title: "Pruefung_id", field: "pruefung_id", visible: false},
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false},
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false},
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true},
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false},
{title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing
{title: "Bezeichnung", field: "bezeichnung", headerFilter: true},
{title: "Studiensemester", field: "studiensemester_kurzbz", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{title: "Pruefung_id", field: "pruefung_id", visible: false, headerFilter: true},
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true},
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true},
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true},
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true},
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing
{
title: 'Aktionen', field: 'actions',
minWidth: 50,
@@ -110,10 +110,10 @@ export default {
],
layout: 'fitColumns',
layoutColumnsOnNewData: false,
height: '200',
height: '250',
selectableRowsRangeMode: 'click',
selectableRows: true,
persistenceID: 'core-contracts-details-2026021701'
persistenceID: 'core-contracts-details-2026050501'
},
tabulatorEvents: [
{
@@ -137,7 +137,7 @@ export default {
setHeader('type', this.$p.t('global', 'typ'));
setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung'));
setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id'));
setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id'));
setHeader('betrag', this.$p.t('ui', 'betrag'));
setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester'));
setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid'));
+11 -8
View File
@@ -47,12 +47,13 @@ export default {
this.endpoint.getStatiOfContract(this.person_id, this.vertrag_id)
),
ajaxResponse: (url, params, response) => response.data,
persistenceID: 'core-contracts-status-2026021701',
persistenceID: 'core-contracts-status-2026050501',
columns: [
{title: "Status", field: "bezeichnung"},
{title: "Status", field: "bezeichnung", headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{
title: "Datum",
field: "datum",
headerFilter: true,
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr); // Convert to Date object
@@ -66,14 +67,15 @@ export default {
});
}
},
{title: "vertrag_id", field: "vertrag_id", visible: false},
{title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false},
{title: "User", field: "mitarbeiter_uid", visible: false},
{title: "insertvon", field: "insertvon", visible: false},
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true},
{title: "Vertragsstatus", field: "vertragsstatus_kurzbz", visible: false, headerFilter: true},
{title: "User", field: "mitarbeiter_uid", visible: false, headerFilter: true},
{title: "insertvon", field: "insertvon", visible: false, headerFilter: true},
{
title: "insertamum",
field: "insertamum",
visible: false,
headerFilter: true,
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr);
@@ -87,11 +89,12 @@ export default {
});
}
},
{title: "updatevon", field: "updatevon", visible: false},
{title: "updatevon", field: "updatevon", visible: false, headerFilter: true},
{
title: "updateamum",
field: "updateamum",
visible: false,
headerFilter: true,
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr);
@@ -148,7 +151,7 @@ export default {
],
layout: 'fitColumns',
layoutColumnsOnNewData: false,
height: '200',
height: '250',
selectableRowsRangeMode: 'click',
selectableRows: true,
},
@@ -30,10 +30,11 @@ export default {
),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "Typ", field: "type", width: 100},
{title: "Typ", field: "type", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{
title: "Betrag",
field: "betrag1",
headerFilter: true,
formatter: function(cell) {
let value = cell.getValue();
if (value == null) {
@@ -41,28 +42,29 @@ export default {
}
return parseFloat(value).toFixed(2);
}},
{title: "Bezeichnung", field: "bezeichnung", width: 150},
{title: "Studiensemester", field: "studiensemester_kurzbz", width: 160},
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false},
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false},
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true},
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false},
{title: "Vertragsstunden", field: "vertragsstunden", visible: false},
{title: "vertrag_id", field: "vertrag_id", visible: false}, //just for testing
{title: "Bezeichnung", field: "bezeichnung", width: 150, headerFilter: true},
{title: "Studiensemester", field: "studiensemester_kurzbz", width: 160, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{title: "mitarbeiter_uid", field: "mitarbeiter_uid", visible: false, headerFilter: true},
{title: "projektarbeit_id", field: "projektarbeit_id", visible: false, headerFilter: true},
{title: "lehreinheit_id", field: "lehreinheit_id", visible: true, headerFilter: true},
{title: "betreuerart_kurzbz", field: "betreuerart_kurzbz", visible: false, headerFilter: true},
{title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true},
{title: "vertrag_id", field: "vertrag_id", visible: false, headerFilter: true}, //just for testing
{
title: "VertragsstundenStudiensemester",
field: "vertragsstunden_studiensemester_kurzbz",
visible: false
visible: false,
headerFilter: true
},
],
layout: 'fitColumns',
layoutColumnsOnNewData: false,
height: 150,
height: 250,
selectableRowsRangeMode: 'click',
selectableRows: true,
selectableRowsRollingSelection: false, //only allow multiselect with STRG
index: "lehreinheit_id",
persistenceID: 'core-contracts-unassigned-2026021701'
persistenceID: 'core-contracts-unassigned-2026050501'
},
tabulatorEvents: [
{
@@ -100,7 +102,7 @@ export default {
setHeader('type', this.$p.t('global', 'typ'));
setHeader('bezeichnung', this.$p.t('ui', 'bezeichnung'));
setHeader('lehreinheit_id', this.$p.t('ui', 'lehreinheit_id'));
setHeader('lehreinheit_id', this.$p.t('lehre', 'lehreinheit_id'));
setHeader('betrag1', this.$p.t('ui', 'betrag'));
setHeader('studiensemester_kurzbz', this.$p.t('lehre', 'studiensemester'));
setHeader('mitarbeiter_uid', this.$p.t('ui', 'mitarbeiter_uid'));
+26 -137
View File
@@ -20,9 +20,6 @@ export default {
ContractStati
},
inject: {
/* cisRoot: {
from: 'cisRoot'
},*/
hasSchreibrechte: {
from: 'hasSchreibrechte',
default: false
@@ -54,9 +51,9 @@ export default {
),
ajaxResponse: (url, params, response) => response.data,
columns: [
{title: "Bezeichnung", field: "bezeichnung", width: 300},
{title: "Bezeichnung", field: "bezeichnung", width: 300, headerFilter: true},
{
title: "Betrag", field: "betrag", width: 100,
title: "Betrag", field: "betrag", width: 100, headerFilter: true,
formatter: function (cell) {
let value = cell.getValue();
@@ -66,12 +63,13 @@ export default {
return parseFloat(value).toFixed(2);
}
},
{title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125},
{title: "Status", field: "status", width: 100},
{title: "Vertragstyp", field: "vertragstyp_bezeichnung", width: 125, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{title: "Status", field: "status", width: 100, headerFilter: "list", headerFilterParams: {valuesLookup:true, listOnEmpty:true, autocomplete:true, sort:"asc"}},
{
title: "Vertragsdatum",
field: "vertragsdatum",
width: 128,
headerFilter: true,
formatter: function (cell) {
const dateStr = cell.getValue();
const date = new Date(dateStr);
@@ -82,11 +80,11 @@ export default {
});
}
},
{title: "VertragId", field: "vertrag_id", visible: false},
{title: "Vertragsstunden", field: "vertragsstunden", visible: false},
{title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false},
{title: "Anmerkung", field: "anmerkung", visible: false},
{title: "isAbgerechnet", field: "isabgerechnet", visible: false},
{title: "VertragId", field: "vertrag_id", visible: false, headerFilter: true},
{title: "Vertragsstunden", field: "vertragsstunden", visible: false, headerFilter: true},
{title: "VertragsstundenStudiensemester", field: "vertragsstunden_studiensemester_kurzbz", visible: false, headerFilter: true},
{title: "Anmerkung", field: "anmerkung", visible: false, headerFilter: true},
{title: "isAbgerechnet", field: "isabgerechnet", visible: false, headerFilter: true},
{
title: 'Aktionen', field: 'actions',
minWidth: 150,
@@ -140,11 +138,13 @@ export default {
columns: true,
filter: false //to avoids js errors
},
persistenceID: 'core-contracts-2026021701',
persistenceID: 'core-contracts-2026050501',
};
return options;
},
tabulatorEvents() {
const vm = this;
const events = [
{
event: 'tableBuilt',
@@ -177,28 +177,11 @@ export default {
setHeader('actions', this.$p.t('global', 'aktionen'));
}
},
/* {
//is just enabled for ADDON Injection KU: MultiprintHonorarvertrag
//(maybe enable also for ADDON FH Burgenland: MultiAccept later)
event: 'rowClick',
handler: (e, row) => {
if (this.dataPrintHonorar != null && this.dataPrintHonorar.multiselect != null) {
const selectedContract = row.getData().vertrag_id;
const status = row.getData().status;
const bezeichnung = row.getData().bezeichnung;
this.toggleRowClick(selectedContract, status, bezeichnung);
}
}
},*/
{
event: 'rowClick',
handler: (e, row) => {
if (!this.dataPrintHonorar?.multiselect) return;
handler: function (e, row) {
const { vertrag_id, status, bezeichnung, vertragstyp_bezeichnung } = row.getData();
this.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung);
vm.toggleRowClick(e, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung);
}
},
{
@@ -242,8 +225,6 @@ export default {
person_id() {
this.$refs.table.reloadTable();
this.arraySelectedContracts = [];
/* if(this.dataPrintHonorar?.multiselect)
this.dataPrintHonorar.multiselect = [];*/
},
},
methods: {
@@ -270,7 +251,6 @@ export default {
)
.then(result => {
this.$fhcAlert.alertSuccess(this.$p.t('ui', 'successDelete'));
//window.scrollTo(0, 0);
this.reload();
this.contractSelected.vertrag_id = null;
})
@@ -518,19 +498,9 @@ export default {
'content/pdfExport.php?xml=' + this.dataPrintHonorar.xml + '&xsl=' + this.dataPrintHonorar.xsl + '&mitarbeiter_uid=' + this.mitarbeiter_uid + vertragString + '&output=pdf&uid=' + this.mitarbeiter_uid;
window.open(linkToPdf, '_blank');
},
/* toggleRowClick(contractId, status, bezeichnung) {
const index = this.arraySelectedContracts.findIndex(
([id]) => id === contractId
);
if (index !== -1) {
this.arraySelectedContracts.splice(index, 1);
} else {
this.arraySelectedContracts.push([contractId, status, bezeichnung]);
}
},*/
toggleRowClick(event, vertrag_id, status, bezeichnung, vertragstyp_bezeichnung) {
if (!this.dataPrintHonorar?.multiselect) return;
const isMulti = this.dataPrintHonorar?.multiselect === true;
const isCtrl = event.ctrlKey || event.metaKey;
const entry = {
@@ -540,28 +510,29 @@ export default {
vertragstyp_bezeichnung
};
// Single click
if (!isCtrl) {
// allow MultiSelect just in case event multiActionPrintHonorarvertrag
const allowMultiClick = isMulti && isCtrl;
if (!allowMultiClick) {
this.arraySelectedContracts = [entry];
//just mark last selected row as selected
this.$refs.table.tabulator.deselectRow();
this.$refs.table.tabulator.selectRow(vertrag_id);
return;
}
// CTRL / CMD → toggle
const index = this.arraySelectedContracts.findIndex(
e => e.vertrag_id === vertrag_id
);
if (index === -1) {
this.arraySelectedContracts.push(entry);
//this.arraySelectedContracts.push([entry.vertrag_id, entry.status, entry.bezeichnung, entry.vertragstyp_bezeichnung]);
} else {
this.arraySelectedContracts.splice(index, 1);
}
},
/* clearSelection(){
this.arraySelectedContracts = [];
this.$refs.table.tabulator.deselectRow();
}*/
}
},
created() {
Promise.all([
@@ -587,88 +558,6 @@ export default {
});
this.getFormattedDate();
},
/*
TODO(Manu) delete after check
<div class="row mb-3">
<form-input
type="DatePicker"
:label="$p.t('vertrag/datum_vertrag')"
name="vertragsdatum"
v-model="formData.vertragsdatum"
auto-apply
:enable-time-picker="false"
format="dd.MM.yyyy"
preview-format="dd.MM.yyyy"
:teleport="true"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
type="text"
:label="$p.t('ui/bezeichnung')"
name="bezeichnung"
v-model="formData.bezeichnung"
>
</form-input>
</div>
<div class="row mb-3">
<form-input
type="select"
:label="$p.t('global/typ')"
v-model="formData.vertragstyp_kurzbz"
name="vertragstyp_kurzbz"
>
<option :value="null">-- {{$p.t('fehlermonitoring', 'keineAuswahl')}} --</option>
<option
v-for="entry in listContractTypes"
:key="entry.vertragstyp_kurzbz"
:value="entry.vertragstyp_kurzbz"
>
{{entry.bezeichnung}}
</option>
</form-input>
</div>
<div class="row mb-3">
<form-input
:label="$p.t('ui/betrag')"
name="betrag"
v-model="formData.betrag"
>
</form-input>
</div>
<div class="row mb-3" v-if="!statusNew">
<form-input
type="text"
:label="$p.t('ui/stunden') + ' (' + $p.t('vertrag/vertrag_urfassung')+ ')'"
name="vertragsstunden"
v-model="formData.vertragsstunden"
disabled
>
</form-input>
</div>
<div class="row mb-3" v-if="!statusNew">
<form-input
type="text"
:label="$p.t('lehre/studiensemester') + ' (' + $p.t('vertrag/vertrag_urfassung')+ ')'"
name="vertragsstunden_studiensemester_kurzbz"
v-model="formData.vertragsstunden_studiensemester_kurzbz"
disabled
>
</form-input>
</div>
<div class="row mb-3">
<form-input
type="textarea"
:label="$p.t('global/anmerkung')"
name="anmerkung"
v-model="formData.anmerkung"
>
</form-input>
</div>
*/
template: `
<div class="core-contracts h-100 d-flex flex-column">
+2 -2
View File
@@ -264,8 +264,8 @@ CREATE TABLE IF NOT EXISTS hr.tbl_vertragsbestandteil_lohnguide (
stellenbezeichnung varchar(255),
fachrichtung_kurzbz character varying(32) NOT NULL,
modellstelle_kurzbz character varying(32) NOT NULL,
kommentar_person varchar(255),
kommentar_modellstelle varchar(255),
kommentar_person text,
kommentar_modellstelle text,
CONSTRAINT tbl_vertragsbestandteil_lohnguide_pk PRIMARY KEY (vertragsbestandteil_id),
CONSTRAINT tbl_vertragsbestandteil_fk FOREIGN KEY (vertragsbestandteil_id) REFERENCES hr.tbl_vertragsbestandteil (vertragsbestandteil_id) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,
CONSTRAINT tbl_vertragsbestandteil_lohnguide_fachrichtung_fk FOREIGN KEY (fachrichtung_kurzbz) REFERENCES hr.tbl_lohnguide_fachrichtung (fachrichtung_kurzbz) MATCH FULL ON DELETE RESTRICT ON UPDATE CASCADE,