mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-06-01 20:29:29 +00:00
WIP noten/pruefung import
This commit is contained in:
@@ -31,9 +31,17 @@ class Benotungstool extends Auth_Controller
|
||||
|
||||
// TODO: check if related CIS config is also loaded when being routed in Cis4 by vuerouter
|
||||
// TODO: check if new benotungstool should be configurable the exact same way?
|
||||
|
||||
|
||||
$viewData = array(
|
||||
'uid'=>getAuthUID(),
|
||||
'CIS_GESAMTNOTE_UEBERSCHREIBEN' => CIS_GESAMTNOTE_UEBERSCHREIBEN
|
||||
'CIS_GESAMTNOTE_UEBERSCHREIBEN' => CIS_GESAMTNOTE_UEBERSCHREIBEN,
|
||||
'CIS_GESAMTNOTE_PRUEFUNG_KOMMPRUEF' => CIS_GESAMTNOTE_PRUEFUNG_KOMMPRUEF,
|
||||
'CIS_GESAMTNOTE_PRUEFUNG_TERMIN3' => CIS_GESAMTNOTE_PRUEFUNG_TERMIN3,
|
||||
'CIS_GESAMTNOTE_PRUEFUNG_TERMIN2' => CIS_GESAMTNOTE_PRUEFUNG_TERMIN2,
|
||||
'CIS_GESAMTNOTE_PRUEFUNG_MOODLE_LE_NOTE' => CIS_GESAMTNOTE_PRUEFUNG_MOODLE_LE_NOTE,
|
||||
'CIS_GESAMTNOTE_PUNKTE' => CIS_GESAMTNOTE_PUNKTE,
|
||||
'CIS_GESAMTNOTE_GEWICHTUNG' => CIS_GESAMTNOTE_GEWICHTUNG
|
||||
);
|
||||
|
||||
$this->load->view('CisRouterView/CisRouterView.php', ['viewData' => $viewData, 'route' => 'Benotungstool']);
|
||||
|
||||
@@ -35,7 +35,8 @@ class Noten extends FHCAPI_Controller
|
||||
'getNotenvorschlagStudent' => self::PERM_LOGGED,
|
||||
'saveNotenvorschlag' => self::PERM_LOGGED,
|
||||
'saveStudentPruefung' => self::PERM_LOGGED,
|
||||
'createPruefungen' => self::PERM_LOGGED
|
||||
'createPruefungen' => self::PERM_LOGGED,
|
||||
'saveNotenvorschlagBulk' => self::PERM_LOGGED
|
||||
]);
|
||||
|
||||
$this->load->library('AuthLib', null, 'AuthLib');
|
||||
@@ -108,6 +109,8 @@ class Noten extends FHCAPI_Controller
|
||||
}
|
||||
|
||||
// send $grades reference to moodle addon
|
||||
|
||||
// TODO: event getExterneNoten
|
||||
Events::trigger(
|
||||
'moodleGrades',
|
||||
function & () use (&$grades)
|
||||
@@ -556,6 +559,72 @@ class Noten extends FHCAPI_Controller
|
||||
|
||||
$this->terminateWithSuccess(array($ret, $lvgesamtnote));
|
||||
}
|
||||
|
||||
public function saveNotenvorschlagBulk() {
|
||||
$result = $this->getPostJSON();
|
||||
|
||||
if(!property_exists($result, 'lv_id') || !property_exists($result, 'sem_kurzbz') ||
|
||||
!property_exists($result, 'noten')) {
|
||||
$this->terminateWithError($this->p->t('global', 'missingParameters'), 'general');
|
||||
}
|
||||
|
||||
$lv_id = $result->lv_id;
|
||||
$sem_kurzbz = $result->sem_kurzbz;
|
||||
$noten = $result->noten;
|
||||
|
||||
$retLvNoten = [];
|
||||
$responseMsgs = [];
|
||||
|
||||
foreach($noten as $note)
|
||||
{
|
||||
$lvgesamtnote = new lvgesamtnote();
|
||||
if (!$lvgesamtnote->load($lv_id, $note->uid, $sem_kurzbz))
|
||||
{
|
||||
$lvgesamtnote->student_uid = $note->uid;
|
||||
$lvgesamtnote->lehrveranstaltung_id = $lv_id;
|
||||
$lvgesamtnote->studiensemester_kurzbz = $sem_kurzbz;
|
||||
$lvgesamtnote->note = trim($note->note);
|
||||
$lvgesamtnote->mitarbeiter_uid = getAuthUID();
|
||||
$lvgesamtnote->benotungsdatum = date("Y-m-d H:i:s");
|
||||
$lvgesamtnote->freigabedatum = null;
|
||||
$lvgesamtnote->freigabevon_uid = null;
|
||||
$lvgesamtnote->bemerkung = null;
|
||||
$lvgesamtnote->updateamum = null;
|
||||
$lvgesamtnote->updatevon = null;
|
||||
$lvgesamtnote->insertamum = date("Y-m-d H:i:s");
|
||||
$lvgesamtnote->insertvon = getAuthUID();
|
||||
$lvgesamtnote->punkte =// TODO: deprecated?
|
||||
$new = true;
|
||||
$response = "neu";
|
||||
}
|
||||
else
|
||||
{
|
||||
$lvgesamtnote->note = trim($note->note);
|
||||
$lvgesamtnote->punkte = null; // TODO: deprecated?
|
||||
$lvgesamtnote->benotungsdatum = date("Y-m-d H:i:s");
|
||||
$lvgesamtnote->updateamum = date("Y-m-d H:i:s");
|
||||
$lvgesamtnote->updatevon = getAuthUID();
|
||||
$new = false;
|
||||
if ($lvgesamtnote->freigabedatum)
|
||||
$response = "update_f";
|
||||
else
|
||||
$response = "update";
|
||||
}
|
||||
|
||||
if (!$lvgesamtnote->save($new))
|
||||
$responseMsgs[] = $lvgesamtnote->errormsg;
|
||||
else
|
||||
$responseMsgs[] = $response;
|
||||
|
||||
|
||||
$lvgesamtnote->load($lv_id, $note->uid, $sem_kurzbz);
|
||||
|
||||
$retLvNoten[] = $lvgesamtnote;
|
||||
}
|
||||
|
||||
$this->terminateWithSuccess(array($retLvNoten, $responseMsgs));
|
||||
|
||||
}
|
||||
|
||||
public function createPruefungen() {
|
||||
$result = $this->getPostJSON();
|
||||
|
||||
@@ -26,7 +26,8 @@ $includesArray = array(
|
||||
'vendor/npm-asset/primevue/accordion/accordion.js',
|
||||
'vendor/npm-asset/primevue/accordiontab/accordiontab.js',
|
||||
'vendor/npm-asset/primevue/password/password.js',
|
||||
'vendor/npm-asset/primevue/multiselect/multiselect.js'
|
||||
'vendor/npm-asset/primevue/multiselect/multiselect.js',
|
||||
'vendor/npm-asset/primevue/textarea/textarea.js'
|
||||
),
|
||||
'customJSModules' => array(
|
||||
'public/js/apps/Dashboard/Fhc.js'
|
||||
|
||||
@@ -57,4 +57,14 @@ export default {
|
||||
params: { uids, datum, lva_id, sem_kurzbz }
|
||||
};
|
||||
},
|
||||
saveNotenvorschlagBulk(lv_id, sem_kurzbz, noten) {
|
||||
return {
|
||||
method: 'post',
|
||||
url: '/api/frontend/v1/Noten/saveNotenvorschlagBulk',
|
||||
params: { lv_id, sem_kurzbz, noten }
|
||||
};
|
||||
},
|
||||
saveStudentPruefungBulk(lv_id, sem_kurzbz, pruefungen) {
|
||||
|
||||
}
|
||||
};
|
||||
@@ -12,6 +12,7 @@ export const Benotungstool = {
|
||||
CoreFilterCmpt,
|
||||
Dropdown: primevue.dropdown,
|
||||
Password: primevue.password,
|
||||
Textarea: primevue.textarea,
|
||||
Datepicker: VueDatePicker,
|
||||
Multiselect: primevue.multiselect
|
||||
},
|
||||
@@ -49,6 +50,7 @@ export const Benotungstool = {
|
||||
changedNotenCounter: 0,
|
||||
tabulatorUuid: Vue.ref(0),
|
||||
domain: '',
|
||||
importString: '',
|
||||
teilnoten: null,
|
||||
lv: null,
|
||||
studenten: null,
|
||||
@@ -107,6 +109,102 @@ export const Benotungstool = {
|
||||
]};
|
||||
},
|
||||
methods: {
|
||||
parseNote(rowParts, notenbulk) {
|
||||
const uid = rowParts[0]
|
||||
|
||||
const student = this.studenten.find(s => s.uid === uid)
|
||||
if(!student) return
|
||||
|
||||
const note = rowParts[1]
|
||||
|
||||
// find notenoption and check if its allowed to use in lehre
|
||||
const notenOption = this.notenOptions.find(n => n.note == note)
|
||||
if(!notenOption.lehre) return
|
||||
|
||||
notenbulk.push({uid, note})
|
||||
},
|
||||
parsePruefung(rowParts, notenbulk) {
|
||||
const uid = rowParts[0]
|
||||
|
||||
const student = this.studenten.find(s => s.uid === uid)
|
||||
if(!student) return
|
||||
|
||||
const datum = rowParts[1] // should be in 'YYYY.MM.DD'
|
||||
const datumObj = datum
|
||||
|
||||
const year = datumObj.getFullYear();
|
||||
const month = String(datumObj.getMonth() + 1).padStart(2, '0'); // Months are 0-based
|
||||
const day = String(datumObj.getDate()).padStart(2, '0');
|
||||
const dateStr = `${year}-${month}-${day}`
|
||||
|
||||
const note = rowParts[2]
|
||||
|
||||
// find notenoption and check if its allowed to use in lehre
|
||||
const notenOption = this.notenOptions.find(n => n.note == note)
|
||||
if(!notenOption.lehre) return
|
||||
},
|
||||
saveNotenBulk(notenbulk) {
|
||||
this.$api.call(ApiNoten.saveNotenvorschlagBulk(this.lv_id, this.sem_kurzbz, notenbulk)).then(res => {
|
||||
console.log(res)
|
||||
if(res.meta.status === 'success') {
|
||||
const lvNoten = res.data[0]
|
||||
|
||||
lvNoten.forEach(lvn => {
|
||||
// 1.) get relevant student row by uid
|
||||
const s = this.studenten.find(s => s.uid === lvn.uid)
|
||||
s.note_vorschlag = lvn.note // TODO: check if note_vorschlag should be changed by import
|
||||
|
||||
this.teilnoten[s.uid].note_lv = lvn.note
|
||||
s.freigabedatum = this.parseDate(lvn['freigabedatum'])
|
||||
s.benotungsdatum = this.parseDate(lvn['benotungsdatum'])
|
||||
|
||||
s.freigegeben = this.checkFreigabe(s.freigabedatum, s.benotungsdatum, s.uid);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// 2.) set note_vorschlag field
|
||||
|
||||
// 4.) update rows with note_lv = note_vorschlag & recalculate freigabestatus
|
||||
})
|
||||
},
|
||||
savePruefungBulk(pruefungenbulk) {
|
||||
this.$api.call(ApiNoten.saveStudentPruefungBulk(this.lv_id, this.sem_kurzbz, pruefungenbulk))
|
||||
.then((res)=> {
|
||||
if(res.meta.status === 'success') {
|
||||
|
||||
|
||||
|
||||
|
||||
this.$fhcAlert.alertInfo('Prüfungen gespeichert') // TODO: phrase
|
||||
}
|
||||
})
|
||||
},
|
||||
importNoten() {
|
||||
console.log('importNoten', this.importString)
|
||||
|
||||
// TODO: check for signs of notenimport or pruefung import
|
||||
|
||||
const rows = this.importString.split('\n')
|
||||
const bulk = []
|
||||
let mode = ''
|
||||
// read the lines
|
||||
rows.forEach(r => {
|
||||
const rowParts = r.split('\t')
|
||||
if(rowParts.length === 3) {
|
||||
this.parsePruefung(rowParts, bulk)
|
||||
mode = 'pruefung' // if line parts are not uniform we are in trouble
|
||||
} else if(rowParts.length === 2) {
|
||||
this.parseNote(rowParts, bulk)
|
||||
mode = 'note'
|
||||
}
|
||||
})
|
||||
|
||||
if(mode === 'note') this.saveNotenBulk(bulk)
|
||||
else if (mode === 'pruefung') this.savePruefungBulk(bulk)
|
||||
|
||||
this.$refs.modalContainerNotenImport.hide()
|
||||
},
|
||||
selectionArraysAreEqual(arr1, arr2) {
|
||||
if(arr1.length !== arr2.length) return false
|
||||
|
||||
@@ -408,7 +506,7 @@ export const Benotungstool = {
|
||||
const date = `${dateParts[2]}.${dateParts[1]}.${dateParts[0]}`
|
||||
|
||||
// First column (date)
|
||||
rowDiv.appendChild(createCol(date, 'col-4 d-flex align-items-center'));
|
||||
rowDiv.appendChild(createCol(date, 'col-4 d-flex justify-content-center align-items-center'));
|
||||
|
||||
const noteDefEntry = data.note ? this.notenOptions.find(n => n.note == data[field].note) : null
|
||||
|
||||
@@ -418,7 +516,7 @@ export const Benotungstool = {
|
||||
// no actions on kommPruef allowed
|
||||
// no actions on termin1 aka pruefung 0 aka ursprüngliche note erlaubt
|
||||
if(field === 'kommPruef' || colDef.originalNote) {
|
||||
rowDiv.appendChild(createCol('', 'col-4 d-flex justify-content-center align-items-center')); // append empty col4 to have formatting similar
|
||||
// rowDiv.appendChild(createCol('', 'col-4 d-flex justify-content-center align-items-center')); // append empty col4 to have formatting similar
|
||||
return rowDiv
|
||||
}
|
||||
|
||||
@@ -450,17 +548,22 @@ export const Benotungstool = {
|
||||
openPruefungModal(student, pruefung = null, field) {
|
||||
this.pruefungStudent = student
|
||||
this.pruefung = pruefung
|
||||
|
||||
const dateStr = this.pruefung?.datum ?? field
|
||||
|
||||
const pruefungDateParts = dateStr.split('-')
|
||||
|
||||
// does not work correctly
|
||||
|
||||
// new date obj so datepicker picks ob the change by ref
|
||||
const newDate = new Date()
|
||||
newDate.setFullYear(pruefungDateParts[0])
|
||||
newDate.setMonth(pruefungDateParts[1])
|
||||
newDate.setMonth(newDate.getMonth() - 1) // acount for js date month offset
|
||||
newDate.setDate(pruefungDateParts[2])
|
||||
// const newDate = new Date()
|
||||
// newDate.setFullYear(+pruefungDateParts[0])
|
||||
// newDate.setMonth(+pruefungDateParts[1])
|
||||
// // newDate.setMonth(newDate.getMonth() - 1) // acount for js date month offset
|
||||
// newDate.setDate(+pruefungDateParts[2])
|
||||
|
||||
// works correctly
|
||||
const newDate = new Date(+pruefungDateParts[0], +pruefungDateParts[1], +pruefungDateParts[2])
|
||||
newDate.setMonth(newDate.getMonth() - 1)
|
||||
this.selectedPruefungDate = newDate
|
||||
|
||||
|
||||
@@ -1037,6 +1140,9 @@ export const Benotungstool = {
|
||||
openNewPruefungsdatumModal() {
|
||||
this.$refs.modalContainerNeuesPruefungsdatum.show()
|
||||
},
|
||||
openNotenImportModal() {
|
||||
this.$refs.modalContainerNotenImport.show()
|
||||
},
|
||||
getOptionLabelNotePruefung(option) {
|
||||
return option.bezeichnung
|
||||
},
|
||||
@@ -1233,12 +1339,13 @@ export const Benotungstool = {
|
||||
return counter
|
||||
},
|
||||
getSaveBtnClass() {
|
||||
// return "btn btn-primary ml-2"
|
||||
return this.changedNoten?.length ? "btn btn-primary ml-2" : "btn btn-secondary ml-2"
|
||||
},
|
||||
getNewBtnClass() {
|
||||
return "btn btn-primary ml-2"
|
||||
// return !this.changedData.length ? "btn btn-secondary ml-2" : "btn btn-primary ml-2"
|
||||
},
|
||||
getNotenImportBtnClass() {
|
||||
return "btn btn-primary ml-2"
|
||||
},
|
||||
changedNoten() {
|
||||
const v = this.changedNotenCounter // hack to trigger computed
|
||||
@@ -1259,6 +1366,19 @@ export const Benotungstool = {
|
||||
this.setupMounted()
|
||||
},
|
||||
template: `
|
||||
<bs-modal ref="modalContainerNotenImport" class="bootstrap-prompt" dialogClass="modal-lg">
|
||||
<template v-slot:title>{{$p.t('benotungstool/c4notenImportieren')}}</template>
|
||||
<template v-slot:default>
|
||||
|
||||
<div class="row mt-4 justify-content-center">
|
||||
<Textarea v-model="importString" rows="5"></Textarea>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
<template v-slot:footer>
|
||||
<button type="button" class="btn btn-primary" @click="importNoten">{{ $p.t('benotungstool/c4import') }}</button>
|
||||
</template>
|
||||
</bs-modal>
|
||||
|
||||
<bs-modal ref="modalContainerNeuesPruefungsdatum" class="bootstrap-prompt" dialogClass="modal-lg">
|
||||
<template v-slot:title>{{$p.t('benotungstool/c4addNewPruefung')}}</template>
|
||||
@@ -1408,6 +1528,9 @@ export const Benotungstool = {
|
||||
<button @click="openNewPruefungsdatumModal" role="button" :class="getNewBtnClass">
|
||||
{{$p.t('benotungstool/c4addNewPruefung')}} <i class="fa fa-plus"></i>
|
||||
</button>
|
||||
<button @click="openNotenImportModal" role="button" :class="getNotenImportBtnClass">
|
||||
{{$p.t('benotungstool/c4notenImportieren')}} <i class="fa fa-file-import"></i>
|
||||
</button>
|
||||
</template>
|
||||
</core-filter-cmpt>
|
||||
</div>
|
||||
|
||||
@@ -42036,6 +42036,46 @@ and represent the current state of research on the topic. The prescribed citatio
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'benotungstool',
|
||||
'phrase' => 'c4notenImportieren',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Noten Import',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Import Grades',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'benotungstool',
|
||||
'phrase' => 'c4import',
|
||||
'insertvon' => 'system',
|
||||
'phrases' => array(
|
||||
array(
|
||||
'sprache' => 'German',
|
||||
'text' => 'Importieren',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
),
|
||||
array(
|
||||
'sprache' => 'English',
|
||||
'text' => 'Import',
|
||||
'description' => '',
|
||||
'insertvon' => 'system'
|
||||
)
|
||||
)
|
||||
),
|
||||
array(
|
||||
'app' => 'core',
|
||||
'category' => 'benotungstool',
|
||||
|
||||
Reference in New Issue
Block a user