mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-20 00:12:15 +00:00
Merge branch 'feature-30660/FHC4_StudierendenGUI_Prototyp' of github.com:FH-Complete/FHC-Core into feature-30660/FHC4_StudierendenGUI_Prototyp
This commit is contained in:
@@ -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,11 @@ class Konto extends FHCAPI_Controller
|
||||
{
|
||||
// TODO(chris): permissions
|
||||
parent::__construct([
|
||||
'get' => 'student/stammdaten:r'
|
||||
'get' => 'student/stammdaten:r',
|
||||
'getBuchungstypen' => 'student/stammdaten:r', // alle?
|
||||
'checkDoubles' => ['admin:r', 'assistenz:r'],
|
||||
'insert' => ['admin:w', 'assistenz:w'],
|
||||
'update' => ['admin:w', 'assistenz:w']
|
||||
]);
|
||||
|
||||
// Load models
|
||||
@@ -51,15 +57,21 @@ 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');
|
||||
|
||||
$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());
|
||||
|
||||
|
||||
$studiengang_kz = $this->input->post('studiengang_kz');
|
||||
|
||||
if ($this->input->post('only_open')) {
|
||||
$result = $this->KontoModel->getOffeneBuchungen($person_id, $studiengang_kz);
|
||||
@@ -95,4 +107,224 @@ 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function update()
|
||||
{
|
||||
$this->load->library('form_validation');
|
||||
|
||||
$this->form_validation->set_rules('buchungsnr', 'Buchungsnr', '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_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) {
|
||||
|
||||
@@ -38,7 +38,8 @@ class Students extends FHC_Controller
|
||||
* /(studiengang_kz)/(org_form)/(semester)/(verband)/(gruppe)
|
||||
* => getStudents
|
||||
* /uid/(student_uid) => getStudent
|
||||
* /prestudent/(prestudent_id) => getPrestudent
|
||||
* /prestudent/(prestudent_id) => getPrestudent
|
||||
* /person/(person_id) => getPerson
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $params (optional)
|
||||
@@ -75,6 +76,9 @@ class Students extends FHC_Controller
|
||||
if ($method == 'prestudent' && $count == 1)
|
||||
return $this->getPrestudent($params[0]);
|
||||
|
||||
if ($method == 'person' && $count == 1)
|
||||
return $this->getPerson($params[0]);
|
||||
|
||||
if (is_numeric($params[0])) {
|
||||
$sem = $params[0];
|
||||
if ($count == 3 && $params[1] == 'grp') {
|
||||
@@ -577,4 +581,77 @@ class Students extends FHC_Controller
|
||||
$this->outputJson(getData($result) ?: []);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param integer $person_id
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function getPerson($person_id)
|
||||
{
|
||||
$studiensemester_kurzbz = $this->variablelib->getVar('semester_aktuell');
|
||||
|
||||
$this->load->model('crm/Prestudent_model', 'PrestudentModel');
|
||||
|
||||
$this->PrestudentModel->addJoin('public.tbl_person p', 'person_id');
|
||||
$this->PrestudentModel->addJoin('public.tbl_student s', 'prestudent_id');
|
||||
$this->PrestudentModel->addJoin('public.tbl_benutzer b', 's.student_uid=b.uid');
|
||||
$this->PrestudentModel->addJoin(
|
||||
'public.tbl_studentlehrverband v',
|
||||
'v.student_uid=s.student_uid AND v.studiensemester_kurzbz=' . $this->PrestudentModel->escape($studiensemester_kurzbz),
|
||||
'LEFT'
|
||||
);
|
||||
|
||||
$this->PrestudentModel->addSelect('p.person_id');
|
||||
$this->PrestudentModel->addSelect('s.prestudent_id');
|
||||
$this->PrestudentModel->addSelect('b.uid');
|
||||
$this->PrestudentModel->addSelect('titelpre');
|
||||
$this->PrestudentModel->addSelect('titelpost');
|
||||
$this->PrestudentModel->addSelect('vorname');
|
||||
$this->PrestudentModel->addSelect('wahlname');
|
||||
$this->PrestudentModel->addSelect('vornamen');
|
||||
$this->PrestudentModel->addSelect('geschlecht');
|
||||
$this->PrestudentModel->addSelect('nachname');
|
||||
$this->PrestudentModel->addSelect('gebdatum');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.anmerkung');
|
||||
$this->PrestudentModel->addSelect('ersatzkennzeichen');
|
||||
$this->PrestudentModel->addSelect('svnr');
|
||||
$this->PrestudentModel->addSelect('s.matrikelnr');
|
||||
$this->PrestudentModel->addSelect('p.anmerkung AS anmerkungen');
|
||||
$this->PrestudentModel->addSelect('v.semester');
|
||||
$this->PrestudentModel->addSelect('v.verband');
|
||||
$this->PrestudentModel->addSelect('v.gruppe');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.studiengang_kz');
|
||||
$this->PrestudentModel->addSelect('aufmerksamdurch_kurzbz');
|
||||
$this->PrestudentModel->addSelect('mentor');
|
||||
$this->PrestudentModel->addSelect('b.aktiv AS bnaktiv');
|
||||
$this->PrestudentModel->addSelect(
|
||||
"(SELECT kontakt FROM public.tbl_kontakt WHERE kontakttyp='email' AND person_id=p.person_id AND zustellung LIMIT 1) AS email_privat",
|
||||
false
|
||||
);
|
||||
$this->PrestudentModel->addSelect(
|
||||
"(SELECT rt_gesamtpunkte AS punkte FROM public.tbl_prestudent WHERE prestudent_id=s.prestudent_id) AS punkte",
|
||||
false
|
||||
);
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.dual');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.reihungstest_id');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.anmeldungreihungstest');
|
||||
$this->PrestudentModel->addSelect('p.matr_nr');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.gsstudientyp_kurzbz');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.aufnahmegruppe_kurzbz');
|
||||
$this->PrestudentModel->addSelect('tbl_prestudent.priorisierung');
|
||||
$this->PrestudentModel->addSelect('p.zugangscode');
|
||||
$this->PrestudentModel->addSelect('p.bpk');
|
||||
|
||||
$result = $this->PrestudentModel->loadWhere([
|
||||
'p.person_id' => $person_id
|
||||
]);
|
||||
|
||||
if (isError($result)) {
|
||||
$this->output->set_status_header(REST_Controller::HTTP_INTERNAL_SERVER_ERROR);
|
||||
$this->outputJson(getError($result));
|
||||
} else {
|
||||
$this->outputJson(getData($result) ?: []);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,14 +449,52 @@ function is_valid_date($dateString)
|
||||
function has_write_permissions($value, $permissions = '')
|
||||
{
|
||||
if (!$permissions)
|
||||
$permissions = $value; // TODO(chris): ??
|
||||
$permissions = $value;
|
||||
$permissions = explode(',', $permissions);
|
||||
|
||||
$CI =& get_instance();
|
||||
$CI->load->library('AuthLib');
|
||||
$CI->load->library('PermissionLib');
|
||||
|
||||
return $CI->permissionlib->hasAtLeastOne(
|
||||
$permissions,
|
||||
'sometable',
|
||||
'w'
|
||||
PermissionLib::WRITE_RIGHT
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if has permissions for a studiengang_kz
|
||||
*/
|
||||
function has_permissions_for_stg($studiengang_kz, $permissions = '')
|
||||
{
|
||||
if (!$permissions)
|
||||
return false;
|
||||
$permissions = explode(',', $permissions);
|
||||
|
||||
$CI =& get_instance();
|
||||
$CI->load->library('AuthLib');
|
||||
$CI->load->library('PermissionLib');
|
||||
|
||||
foreach ($permissions as $perm) {
|
||||
if (strpos($perm, PermissionLib::PERMISSION_SEPARATOR) === false) {
|
||||
$CI->addError(
|
||||
'The given permission does not use the correct format',
|
||||
FHCAPI_Controller::ERROR_TYPE_GENERAL
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
list($perm, $accesstype) = explode(PermissionLib::PERMISSION_SEPARATOR, $perm);
|
||||
$at = '';
|
||||
if (strpos($accesstype, PermissionLib::READ_RIGHT) !== false)
|
||||
$at = PermissionLib::SELECT_RIGHT; // S
|
||||
if (strpos($accesstype, PermissionLib::WRITE_RIGHT) !== false)
|
||||
$at .= PermissionLib::REPLACE_RIGHT.PermissionLib::DELETE_RIGHT; // UID
|
||||
|
||||
if ($CI->permissionlib->isBerechtigt($perm, $at, $studiengang_kz))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
* @since Version 1.0.0
|
||||
* @filesource
|
||||
*/
|
||||
defined('BASEPATH') OR exit('No direct script access allowed');
|
||||
if (!defined('BASEPATH')) exit('No direct script access allowed');
|
||||
|
||||
$lang['form_validation_has_write_permissions'] = 'You have no rights to edit {field} field.';
|
||||
$lang['form_validation_is_valid_date'] = 'The date format is invalid or out of range.';
|
||||
$lang['form_validation_is_valid_date'] = 'The date format is invalid or out of range.';
|
||||
$lang['form_validation_has_permissions_for_stg'] = 'You have no rights for stg {field}.';
|
||||
|
||||
@@ -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))
|
||||
@@ -79,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
|
||||
*/
|
||||
|
||||
@@ -24,15 +24,15 @@ html {
|
||||
border-radius: 0!important;
|
||||
}
|
||||
|
||||
#main {
|
||||
.stv {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
#main > header {
|
||||
.stv > header {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
#main > div {
|
||||
.stv > div {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import konto from './stv/konto.js';
|
||||
|
||||
export default {
|
||||
konto
|
||||
};
|
||||
@@ -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');
|
||||
}
|
||||
};
|
||||
@@ -34,7 +34,8 @@ import(FHC_JS_DATA_STORAGE_OBJECT.app_root + FHC_JS_DATA_STORAGE_OBJECT.ci_route
|
||||
{ path: `/${ciPath}/studentenverwaltung`, component: FhcStudentenverwaltung },
|
||||
{ path: `/${ciPath}/studentenverwaltung/prestudent/:prestudent_id`, component: FhcStudentenverwaltung },
|
||||
{ path: `/${ciPath}/studentenverwaltung/prestudent/:prestudent_id/:tab`, component: FhcStudentenverwaltung },
|
||||
{ path: `/${ciPath}/studentenverwaltung/student/:id`, component: FhcStudentenverwaltung }
|
||||
{ path: `/${ciPath}/studentenverwaltung/student/:id`, component: FhcStudentenverwaltung },
|
||||
{ path: `/${ciPath}/studentenverwaltung/person/:person_id`, component: FhcStudentenverwaltung }
|
||||
]
|
||||
});
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ export default {
|
||||
document.body.appendChild(wrapper);
|
||||
});
|
||||
},
|
||||
template: `<div ref="modal" class="bootstrap-modal modal" tabindex="-1" @[\`hide.bs.modal\`]="$emit('hideBsModal')" @[\`hidden.bs.modal\`]="$emit('hiddenBsModal')" @[\`hidePrevented.bs.modal\`]="$emit('hidePreventedBsModal')" @[\`show.bs.modal\`]="$emit('showBsModal')" @[\`shown.bs.modal\`]="$emit('shownBsModal')">
|
||||
template: `<div ref="modal" class="bootstrap-modal modal" tabindex="-1" @[\`hide.bs.modal\`]="$emit('hideBsModal', $event)" @[\`hidden.bs.modal\`]="$emit('hiddenBsModal', $event)" @[\`hidePrevented.bs.modal\`]="$emit('hidePreventedBsModal', $event)" @[\`show.bs.modal\`]="$emit('showBsModal', $event)" @[\`shown.bs.modal\`]="$emit('shownBsModal', $event)">
|
||||
<div class="modal-dialog" :class="dialogClass">
|
||||
<div class="modal-content">
|
||||
<div v-if="$slots.title" class="modal-header">
|
||||
|
||||
@@ -25,7 +25,10 @@ export default {
|
||||
type: String,
|
||||
name: String,
|
||||
containerClass: [String, Array, Object],
|
||||
label: String
|
||||
label: String,
|
||||
// NOTE(chris): remove these from $attrs array to prevent doubled event listeners
|
||||
onInput: [Array, Function],
|
||||
'onUpdate:modelValue': [Array, Function]
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -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
|
||||
.factory.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,18 @@
|
||||
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): filter
|
||||
// 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
|
||||
CoreFilterCmpt,
|
||||
FormInput,
|
||||
KontoNew,
|
||||
KontoEdit
|
||||
},
|
||||
props: {
|
||||
modelValue: Object,
|
||||
@@ -17,10 +23,16 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
filter: 'alle'
|
||||
filter: false,
|
||||
studiengang_kz: false
|
||||
};
|
||||
},
|
||||
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;
|
||||
@@ -29,70 +41,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',
|
||||
ajaxParams: () => {
|
||||
const params = {
|
||||
person_id: this.modelValue.person_id || this.modelValue.map(e => e.person_id),
|
||||
only_open: (this.filter == 'offene')
|
||||
};
|
||||
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: [
|
||||
{
|
||||
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,
|
||||
selectable: true,
|
||||
selectableRangeMode: 'click',
|
||||
index: 'buchungsnr',
|
||||
}, this);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -103,23 +178,42 @@ export default {
|
||||
methods: {
|
||||
reload() {
|
||||
this.$refs.table.reloadTable();
|
||||
},
|
||||
updateData(data) {
|
||||
if (!data)
|
||||
return this.reload();
|
||||
this.$refs.table.tabulator.updateData(data);
|
||||
},
|
||||
actionNew() {
|
||||
this.$refs.new.open();
|
||||
}
|
||||
},
|
||||
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
|
||||
@@ -127,7 +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>`
|
||||
};
|
||||
@@ -0,0 +1,165 @@
|
||||
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
|
||||
.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 => {
|
||||
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"
|
||||
: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.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>`
|
||||
};
|
||||
@@ -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>`
|
||||
};
|
||||
@@ -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">
|
||||
|
||||
@@ -156,7 +156,6 @@ export default {
|
||||
const $fhcAlert = app.config.globalProperties.$fhcAlert;
|
||||
|
||||
if (form) {
|
||||
form.clearValidation();
|
||||
form.setFeedback(false, error.messages);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26532,6 +26532,47 @@ array(
|
||||
)
|
||||
)
|
||||
),
|
||||
// FHC-Core-SAP
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'sap',
|
||||
'phrase' => 'error_noBuchung',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Die Buchungsnr #{buchungsnr} is ungültig',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'The Buchungnr #{buchungsnr} is not valid',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'sap',
|
||||
'phrase' => 'error_buchungLocked',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Die Buchung wurde bereits übertragen und darf nicht geändert werden',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'The Buchung was already submitted and can not be changed',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user