diff --git a/application/controllers/api/frontend/v1/Abgabe.php b/application/controllers/api/frontend/v1/Abgabe.php index c0311426b..c962e4943 100644 --- a/application/controllers/api/frontend/v1/Abgabe.php +++ b/application/controllers/api/frontend/v1/Abgabe.php @@ -531,6 +531,7 @@ class Abgabe extends FHCAPI_Controller 'datum' => $datum, 'kurzbz' => $kurzbz, 'note' => $note, + 'fixtermin' => $fixtermin, 'beurteilungsnotiz' => $beurteilungsnotiz, 'upload_allowed' => $upload_allowed, 'updatevon' => getAuthUID(), @@ -543,6 +544,7 @@ class Abgabe extends FHCAPI_Controller 'datum' => $datum, 'kurzbz' => $kurzbz, 'note' => $note, + 'fixtermin' => $fixtermin, 'beurteilungsnotiz' => $beurteilungsnotiz, 'upload_allowed' => $upload_allowed, 'updatevon' => getAuthUID(), @@ -734,7 +736,7 @@ class Abgabe extends FHCAPI_Controller $result = $this->ProjektarbeitModel->getProjektbetreuerEmail($projektarbeit_id); $email = $this->getDataOrTerminateWithError($result); - return $email[0]->private_email ?? $email[0]->uid.'@'.DOMAIN; + return $email[0]->uid ? $email[0]->uid.'@'.DOMAIN : $email[0]->private_email; } @@ -787,7 +789,7 @@ class Abgabe extends FHCAPI_Controller $this->terminateWithError($this->p->t('abgabetool','c4userNichtGefunden'), 'general'); } - $subject = $this->p->t('abgabetool', 'c4qualgateNegativEmailSubject'); + $subject = $this->p->t('abgabetool', 'c4qualgateNegativEmailSubjectv2'); $tomail = $student_uid.'@'.DOMAIN; $datetime = new DateTime($paabgabe->datum); diff --git a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js index 38e9f9dd4..f084d9d5c 100644 --- a/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js +++ b/public/js/components/Cis/Abgabetool/AbgabeMitarbeiterDetail.js @@ -299,6 +299,14 @@ export const AbgabeMitarbeiterDetail = { const abgabedatum = new Date(termin.abgabedatum) termin.diffindays = this.dateDiffInDays(termin.datum) + + // TODO: load benotbar in every view or change status logic all together! + + // console.log('\n\n') + // console.log(termin) + // console.log(today) + // console.log(datum) + // console.log('\n\n') if(today > datum && termin.benotbar && !termin.note) return 'beurteilungerforderlich' if (termin.abgabedatum === null && termin.upload_allowed) { @@ -532,7 +540,7 @@ export const AbgabeMitarbeiterDetail = { }, getTooltipBeurteilungerforderlich() { return { - value: this.$p.t('abgabetool/c4tooltipBeurteilungerfolderlich'), + value: this.$p.t('abgabetool/c4tooltipBeurteilungerforderlich'), class: "custom-tooltip" } }, diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js index 8ca1b931e..739791ed4 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolAssistenz.js @@ -72,6 +72,7 @@ export const AbgabetoolAssistenz = { selectedStudiengangOption: null, studiengaengeOptions: null, detailIsFullscreen: false, + allConfigPromise: null, phrasenPromise: null, phrasenResolved: false, turnitin_link: null, @@ -90,6 +91,7 @@ export const AbgabetoolAssistenz = { }, kurzbz: '', fixtermin: false, + invertedFixtermin: true, upload_allowed: false }), showAll: false, @@ -285,7 +287,7 @@ export const AbgabetoolAssistenz = { } else if(qgate.upload_allowed == true && qgate.abgabedatum == null && projekt.qgate1StatusRank <= 2) { projekt.qgate1Status = this.$p.t('abgabetool/c4notSubmitted') projekt.qgate1StatusRank = 2 - } else if (qgate.upload_allowed == false && diffMs <= 0 && projekt.qgate1StatusRank <= 1) { + } else if (qgate.upload_allowed == false && qgate.diffMs <= 0 && projekt.qgate1StatusRank <= 1) { projekt.qgate1Status = this.$p.t('abgabetool/c4notHappenedYet') projekt.qgate1StatusRank = 1 } @@ -307,7 +309,7 @@ export const AbgabetoolAssistenz = { } else if(qgate.upload_allowed == true && qgate.abgabedatum == null && projekt.qgate2StatusRank <= 2) { projekt.qgate2Status = this.$p.t('abgabetool/c4notSubmitted') projekt.qgate2StatusRank = 2 - } else if (qgate.upload_allowed == false && diffMs <= 0 && projekt.qgate2StatusRank <= 1) { + } else if (qgate.upload_allowed == false && qgate.diffMs <= 0 && projekt.qgate2StatusRank <= 1) { projekt.qgate2Status = this.$p.t('abgabetool/c4notHappenedYet') projekt.qgate2StatusRank = 1 } @@ -582,6 +584,7 @@ export const AbgabetoolAssistenz = { addSeries() { const pids = this.selectedData?.map(projekt => projekt.projektarbeit_id) this.saving = true + this.serienTermin.fixtermin = !this.serienTermin.invertedFixtermin this.$api.call(ApiAbgabe.postSerientermin( this.serienTermin.datum.toISOString(), this.serienTermin.bezeichnung.paabgabetyp_kurzbz, @@ -896,6 +899,8 @@ export const AbgabetoolAssistenz = { this.tableBuiltPromise = new Promise(this.tableResolve) await this.tableBuiltPromise + await this.allConfigPromise + // called through notenOptionFilter/selectedStudiengangOption watcher on startup // this.loadProjektarbeiten() @@ -929,79 +934,74 @@ export const AbgabetoolAssistenz = { this.loading = true this.phrasenPromise = this.$p.loadCategory(['abgabetool', 'global']) this.phrasenPromise.then(()=> {this.phrasenResolved = true}) - // fetch config to avoid hard coded links - this.$api.call(ApiAbgabe.getConfig()).then(res => { - this.turnitin_link = res.data?.turnitin_link - this.old_abgabe_beurteilung_link = res.data?.old_abgabe_beurteilung_link - }).catch(e => { - this.loading = false - }) - - // fetch studiengänge options - this.$api.call(ApiAbgabe.getStudiengaenge()).then(res => { - this.studiengaengeOptions = res.data - if(this.studiengaengeOptions?.length) { - - // use this.stg_kz_prop as default selected in case of url param usage - - this.selectedStudiengangOption = this.stg_kz_prop ? res.data.find(stgOpt => stgOpt.studiengang_kz == this.stg_kz_prop) : res.data[0] - } - - }).catch(e => { - this.loading = false - }) - this.$api.call(ApiStudiensemester.getAllStudiensemesterAndAktOrNext()).then((res) => { - this.allSem = res.data[0] - const all = {studiensemester_kurzbz: this.$p.t('abgabetool/c4all')} - this.curSem = all // res.data[1] - - this.studiensemesterOptions = [all, ...this.allSem] - - }).catch(e => { - this.loading = false - }) - - // fetch noten options //TODO: SWITCH TO NOTEN API ONCE NOTENTOOL IS IN MASTER TO AVOID DUPLICATE API - this.$api.call(ApiAbgabe.getNoten()).then(res => { - if(res.meta.status == 'success') { - this.notenOptions = res.data[0] + const requests = [ + this.$api.call(ApiAbgabe.getConfig()), + this.$api.call(ApiAbgabe.getStudiengaenge()), + this.$api.call(ApiStudiensemester.getAllStudiensemesterAndAktOrNext()), + this.$api.call(ApiAbgabe.getNoten()), + this.$api.call(ApiAbgabe.getPaAbgabetypen()) + ]; - this.allowedNotenOptions = this.notenOptions.filter( - opt => res.data[1].includes(opt.note) - ) - } - - // allowedNotenOptions apply to quality gates abgabetermine - // this selection is about graded projektarbeiten, so take different options here - this.allowedNotenFilterOptions = [ - { - bezeichnung: Vue.computed(() => this.$p.t('abgabetool/keineNoteEingetragen')), - benotet: 0, - }, - { - bezeichnung: Vue.computed(() => this.$p.t('abgabetool/c4benotet')), - benotet: 1, - }, - { - bezeichnung: Vue.computed(() => this.$p.t('abgabetool/showAll')), - benotet: -1, - }, - ] - - this.notenOptionFilter = this.allowedNotenFilterOptions[0] - - }).catch(e => { - this.loading = false - }) + this.allConfigPromise = Promise.allSettled(requests) + .then((results) => { + // results is an array of { status: 'fulfilled'|'rejected', value?: any, reason?: any } - // fetch abgabetypen options - this.$api.call(ApiAbgabe.getPaAbgabetypen()).then(res => { - this.abgabeTypeOptions = res.data - }).catch(e => { - this.loading = false - }) + // 1. Config + if (results[0].status === 'fulfilled') { + const res = results[0].value; + this.turnitin_link = res.data?.turnitin_link; + this.old_abgabe_beurteilung_link = res.data?.old_abgabe_beurteilung_link; + } + + // 2. Studiengänge + if (results[1].status === 'fulfilled') { + const res = results[1].value; + this.studiengaengeOptions = res.data; + if (this.studiengaengeOptions?.length) { + this.selectedStudiengangOption = this.stg_kz_prop + ? res.data.find(stgOpt => stgOpt.studiengang_kz == this.stg_kz_prop) + : res.data[0]; + } + } + + // 3. Studiensemester + if (results[2].status === 'fulfilled') { + const res = results[2].value; + this.allSem = res.data[0]; + const all = { studiensemester_kurzbz: this.$p.t('abgabetool/c4all') }; + this.curSem = all; + this.studiensemesterOptions = [all, ...this.allSem]; + } + + // 4. Noten + if (results[3].status === 'fulfilled') { + const res = results[3].value; + if (res.meta?.status === 'success') { + this.notenOptions = res.data[0]; + this.allowedNotenOptions = this.notenOptions.filter( + opt => res.data[1].includes(opt.note) + ); + } + + this.allowedNotenFilterOptions = [ + { bezeichnung: Vue.computed(() => this.$p.t('abgabetool/keineNoteEingetragen')), benotet: 0 }, + { bezeichnung: Vue.computed(() => this.$p.t('abgabetool/c4benotet')), benotet: 1 }, + { bezeichnung: Vue.computed(() => this.$p.t('abgabetool/showAll')), benotet: -1 } + ]; + this.notenOptionFilter = this.allowedNotenFilterOptions[0]; + } + + // 5. Abgabetypen + if (results[4].status === 'fulfilled') { + const res = results[4].value; + this.abgabeTypeOptions = res.data; + } + }) + .finally(() => { + this.loading = false; + }); }, mounted() { this.setupMounted() @@ -1023,7 +1023,7 @@ export const AbgabetoolAssistenz = {
{{$capitalize( $p.t('abgabetool/c4fixterminv4') )}}
diff --git a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js index 05e20a966..2069e1275 100644 --- a/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js +++ b/public/js/components/Cis/Abgabetool/AbgabetoolStudent.js @@ -45,11 +45,19 @@ export const AbgabetoolStudent = { }; }, methods: { - dateDiffInDays(datum){ + dateDiffInDays(datumParam){ + let datum = datumParam + if(datumParam instanceof Date && !isNaN(datum.getTime())) + { + const year = datumParam.getFullYear(); + const month = datumParam.getMonth() + 1; // getMonth() is 0-indexed + const day = datumParam.getDate(); + const pad = (num) => String(num).padStart(2, '0'); + datum = `${year}-${pad(month)}-${pad(day)}` + } + const dateToday = luxon.DateTime.now().startOf('day'); - const dateDatum = luxon.DateTime.fromISO(datum).startOf('day'); - const duration = dateDatum.diff(dateToday, 'days'); return duration.values.days; @@ -60,6 +68,12 @@ export const AbgabetoolStudent = { termin.diffindays = this.dateDiffInDays(termin.datum) + // console.log('\n\n') + // console.log(termin) + // console.log(today) + // console.log(datum) + // console.log('\n\n') + if(today > datum && termin.benotbar && !termin.note) return 'beurteilungerforderlich' if (termin.abgabedatum === null && termin.upload_allowed) { if(datum < today) { diff --git a/system/phrasesupdate.php b/system/phrasesupdate.php index 9501bebf2..8d7d7e624 100644 --- a/system/phrasesupdate.php +++ b/system/phrasesupdate.php @@ -44855,12 +44855,12 @@ array( array( 'app' => 'core', 'category' => 'abgabetool', - 'phrase' => 'c4qualgateNegativEmailSubject', + 'phrase' => 'c4qualgateNegativEmailSubjectv2', 'insertvon' => 'system', 'phrases' => array( array( 'sprache' => 'German', - 'text' => "Quality Gate Negativ beurteilt", + 'text' => "Quality Gate negativ beurteilt", 'description' => '', 'insertvon' => 'system' ),