From 875be59deb262cee488565f5a8b1746bc4660571 Mon Sep 17 00:00:00 2001
From: alex <alex@alexloehr.net>
Date: Thu, 23 Oct 2025 15:24:27 +0000
Subject: [PATCH] GS-2375
---
lib/db.js | 166 ++++++++++++++++++---------------
app.js | 5
vue/src/pages/KursDetailLp.vue | 51 ++++++++--
vue/src/lib/api.js | 6
lib/libLp.js | 72 ++++++++++++++
5 files changed, 211 insertions(+), 89 deletions(-)
diff --git a/app.js b/app.js
index acfd58f..1109749 100644
--- a/app.js
+++ b/app.js
@@ -193,7 +193,10 @@
.get("/api/kurs/:refId/lp", async function (req, res) {
const {refId} = req.params
const {obj_id: objId} = await db.getObjIdFromRefId(refId)
- let data = await db.getKursLp(objId)
+
+ const raw = req.query.raw
+ let data = await db.getKursLp(objId, raw)
+
if (data) {
return res.send(data)
} else {
diff --git a/lib/db.js b/lib/db.js
index 591b25f..f990051 100644
--- a/lib/db.js
+++ b/lib/db.js
@@ -406,93 +406,105 @@
return results
}
-async function getKursLp(obj_id) {
+async function getKursLp(obj_id, raw = false) {
const {ref_id} = await getRefIdFromObjId(obj_id)
- console.log(ref_id)
- const teilnehmer = await getKursTeilnehmer(ref_id)
const tnUnter = await getKursUnterobjektLp(obj_id)
- console.table(teilnehmer)
- console.table(tnUnter)
- /**
- * Die beiden Datensätze mergen
- *
- *
- */
-
- const idx = _.groupBy(tnUnter, "usr_id")
- for (const tn of teilnehmer) {
- delete tn.parent_id
- delete tn.type
- delete tn.active
-
- /** @type Array */
- const unter = idx[tn.usr_id]
- if (!unter) continue
-
- /**
- * wenn unter.status_changed neuer, wird unter tn.status_changed vorgezogen
- * wenn unter.status neuer, überscheibt es tn.status
- * tn.passed muss zurückgesetzt werden wenn tn.status überschrieben wird
- */
- tn.status_overwrite = false
-
- // max unter status_changed finden
- const unterStatusChanged = _.max(unter.map(u => u.status_changed))
-
- // es muss nur überschrieben werden wenn das Unterdatum größer ist
- if (unterStatusChanged > tn.status_changed) {
- // unter Status auswerten
- // 0 = noch nicht bearbeitet
- // 1 = in Bearbeitung
- // 2 = bestanden
- // 3 = nicht bestanden
-
- /** @type Array */
- const unterStatusse = unter.map(u => u.status)
- let newStatus = tn.status
- const allSame = function () {
- if (!unterStatusse.length) return false
- const first = unterStatusse[0]
- return unterStatusse.every(it => it === first)
- }()
- console.log({unterStatusse})
- // Fall 1: keine Unterstatussse vorhanden -> status vom Kurs
- if (!unterStatusse.length) {
- newStatus = tn.status
- }
- // Fall 2: eines nicht bestanden -> nicht bestanden // 0,1,2,3 -> 3
- if (unterStatusse.some(u => u === 3)) {
- newStatus = 3
- }
- // Fall 3: alle statusse gleich -> status // 0,0,0 1,1,1 2,2,2 3,3,3
- else if (allSame) {
- newStatus = unterStatusse[0]
- }
- // Fall 4: wenn eines in Bearbeitung -> in Bearbeitung // 0,1,0 2,1,2
- else if (unterStatusse.some(u => u === 1)) {
- newStatus = 1
- }
- // Fall 5: sonst in Bearbeitung
- else {
- // newStatus = Math.max.apply(this, unterStatusse)
- newStatus = 1
- }
- tn.status_changed = unterStatusChanged
- tn.status = newStatus
- tn.status_overwrite = true
- }
+ if (raw) {
+ return tnUnter
+ } else { // LP aller Unterobjekte zusammenfassen
+ const libLp = require("../lib/libLp")
+ const data = libLp.alleAuswerten(tnUnter)
+ return data
}
- return teilnehmer
+
+ // const teilnehmer = await getKursTeilnehmer(ref_id)
+ // const tnUnter = await getKursUnterobjektLp(obj_id)
+ // console.table(teilnehmer)
+ // console.table(tnUnter)
+ //
+ // /**
+ // * Die beiden Datensätze mergen
+ // * NEIN - es reicht der
+ // *
+ // */
+ //
+ // const idx = _.groupBy(tnUnter, "usr_id")
+ // for (const tn of teilnehmer) {
+ // delete tn.parent_id
+ // delete tn.type
+ // delete tn.active
+ //
+ // /** @type Array */
+ // const unter = idx[tn.usr_id]
+ // if (!unter) continue
+ //
+ // /**
+ // * wenn unter.status_changed neuer, wird unter tn.status_changed vorgezogen
+ // * wenn unter.status neuer, überscheibt es tn.status
+ // * tn.passed muss zurückgesetzt werden wenn tn.status überschrieben wird
+ // */
+ // tn.status_overwrite = false
+ //
+ // // max unter status_changed finden
+ // const unterStatusChanged = _.max(unter.map(u => u.status_changed))
+ //
+ // // es muss nur überschrieben werden wenn das Unterdatum größer ist
+ // if (unterStatusChanged > tn.status_changed) {
+ // // unter Status auswerten
+ // // 0 = noch nicht bearbeitet
+ // // 1 = in Bearbeitung
+ // // 2 = bestanden
+ // // 3 = nicht bestanden
+ //
+ // /** @type Array */
+ // const unterStatusse = unter.map(u => u.status)
+ // let newStatus = tn.status
+ // const allSame = function () {
+ // if (!unterStatusse.length) return false
+ // const first = unterStatusse[0]
+ // return unterStatusse.every(it => it === first)
+ // }()
+ // console.log({unterStatusse})
+ // // Fall 1: keine Unterstatussse vorhanden -> status vom Kurs
+ // if (!unterStatusse.length) {
+ // newStatus = tn.status
+ // }
+ // // Fall 2: eines nicht bestanden -> nicht bestanden // 0,1,2,3 -> 3
+ // if (unterStatusse.some(u => u === 3)) {
+ // newStatus = 3
+ // }
+ // // Fall 3: alle statusse gleich -> status // 0,0,0 1,1,1 2,2,2 3,3,3
+ // else if (allSame) {
+ // newStatus = unterStatusse[0]
+ // }
+ // // Fall 4: wenn eines in Bearbeitung -> in Bearbeitung // 0,1,0 2,1,2
+ // else if (unterStatusse.some(u => u === 1)) {
+ // newStatus = 1
+ // }
+ // // Fall 5: sonst in Bearbeitung
+ // else {
+ // // newStatus = Math.max.apply(this, unterStatusse)
+ // newStatus = 1
+ // }
+ // tn.status_changed = unterStatusChanged
+ // tn.status = newStatus
+ // tn.status_overwrite = true
+ // }
+ // }
+ // return teilnehmer
}
async function getKursUnterobjektLp(obj_id) {
const pool = await poolP
- const q = `SELECT ulc.obj_id,
+ const q = `SELECT ud.usr_id,
+ ud.login,
+ ud.firstname,
+ ud.lastname,
+ ulc.obj_id,
ulc.item_id,
ulc.lpmode,
t.obj_id as item_obj_id,
- ulm.usr_id,
ulm.status,
ulm.status_changed,
ulm.percentage,
@@ -500,9 +512,11 @@
FROM ${database}.ut_lp_collections ulc
INNER JOIN ${database}.object_reference t ON t.ref_id = ulc.item_id
INNER JOIN ${database}.ut_lp_marks ulm ON ulm.obj_id = t.obj_id
+ INNER JOIN ${database}.usr_data ud ON ud.usr_id = ulm.usr_id
WHERE ulc.obj_id = ${obj_id} # obj_id Kurs
AND ulc.active = 1
AND ulc.lpmode = 5 # nur mode 5
+ ORDER BY ud.usr_id
`
const [results] = await pool.query(q)
return results
diff --git a/lib/libLp.js b/lib/libLp.js
new file mode 100644
index 0000000..f5eac83
--- /dev/null
+++ b/lib/libLp.js
@@ -0,0 +1,72 @@
+const _ = require("lodash")
+
+/////////////////////////////////////////////////////////////////////////
+
+module.exports = {
+ alleAuswerten,
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+/**
+ * Unterobjekte auswerten und LF kombinieren pro user
+ * @param {[usr_id,login,firstname,lastname,obj_id,item_id,item_obj_id,status,status_changed]} data
+ * @return {[usr_id,firstname,lastname,status,status_changed]}
+ */
+function alleAuswerten(data) {
+ const grouped = _.groupBy(data, "usr_id")
+ const ret = []
+ for (const items of Object.values(grouped)) {
+ // console.log(items)
+ if (!items.length) continue
+ const unterStatusse = items.map(it => it.status)
+
+ const newStatus = auswerten(unterStatusse)
+ const status_changed = _.max(items.map(u => u.status_changed))
+
+ const {usr_id, login, firstname, lastname,} = items[0]
+ const newItem = {
+ usr_id, login, firstname, lastname, status: newStatus, status_changed
+ }
+ ret.push(newItem)
+ }
+ console.log(ret)
+ return ret
+}
+
+function auswerten(unterStatusse) {
+ // unter Status auswerten
+ // 0 = noch nicht bearbeitet
+ // 1 = in Bearbeitung
+ // 2 = bestanden
+ // 3 = nicht bestanden
+
+ // Fall 1: keine Unterstatussse vorhanden -> 0
+ if (!unterStatusse.length) {
+ return 0
+ }
+
+ // Fall 2: eines nicht bestanden -> alles nicht bestanden // 0,1,2,3 -> 3
+ if (unterStatusse.some(u => u === 3)) {
+ return 3
+ }
+
+ // Fall 3: alle statusse gleich -> status // 0,0,0 1,1,1 2,2,2 3,3,3
+ if (isAllSame(unterStatusse)) {
+ return unterStatusse[0]
+ }
+
+ // Fall 4: wenn eines in Bearbeitung -> in Bearbeitung // 0,1,0 2,1,2
+ if (unterStatusse.some(u => u === 1)) {
+ return 1
+ }
+
+ // Fall 5: sonst 0
+ return 0
+}
+
+function isAllSame(items) {
+ if (!items.length) return false
+ const first = items[0]
+ return items.every(it => it === first)
+}
diff --git a/vue/src/lib/api.js b/vue/src/lib/api.js
index 26ff72b..adffe89 100644
--- a/vue/src/lib/api.js
+++ b/vue/src/lib/api.js
@@ -53,8 +53,10 @@
return await resKurs.json()
}
-export async function getKursLp (kursId) {
- let resKursLp = await fetch(`${apiBase}/kurs/${kursId}/lp?token=${apiToken.value}`)
+export async function getKursLp (kursId, raw = false) {
+ let url = `${apiBase}/kurs/${kursId}/lp?token=${apiToken.value}`
+ if(raw) url += "&raw=1"
+ let resKursLp = await fetch(url)
return await resKursLp.json()
}
diff --git a/vue/src/pages/KursDetailLp.vue b/vue/src/pages/KursDetailLp.vue
index c47772e..cad8134 100644
--- a/vue/src/pages/KursDetailLp.vue
+++ b/vue/src/pages/KursDetailLp.vue
@@ -22,8 +22,9 @@
const kursId = route.params.kursId
document.title = `Kurs LP ${kursId} | globus-ilias-rest`
-const kurs = ref(null)
-const kursLp = ref(null)
+const kurs = ref([])
+const kursLp = ref([])
+const kursLpRaw = ref([])
const error = ref(null)
onMounted(init)
@@ -40,7 +41,10 @@
const dataKursLp = await getKursLp(kursId)
console.log({dataKursLp})
kursLp.value = dataKursLp
- // kursLp.value = [...dataKursLp,...dataKursLp,...dataKursLp]
+
+ const dataKursLpRaw = await getKursLp(kursId, true)
+ console.log({dataKursLpRaw})
+ kursLpRaw.value = dataKursLpRaw
}
</script>
@@ -77,12 +81,10 @@
<!-- <pre>{{ kursLp }}</pre>-->
+ <h2>Combined <small>{{kursLp?.length || 0}}</small></h2>
<table class="w100p">
<thead>
<tr>
-<!-- <th>ref_id</th>-->
-<!-- <th>obj_id</th>-->
- <!-- <th>title</th>-->
<th>usr_id</th>
<th>login</th>
<th>firstname</th>
@@ -95,9 +97,6 @@
</thead>
<tbody>
<tr v-for="item in kursLp">
-<!-- <td>{{ item.ref_id }}</td>-->
-<!-- <td>{{ item.obj_id }}</td>-->
- <!-- <td>{{item.title}}</td>-->
<td>
<RouterLink :to="`${routerBase}/ui/user/${item.usr_id}`">
{{ item.usr_id }}
@@ -106,7 +105,39 @@
<td>{{ item.login }}</td>
<td>{{ item.firstname }}</td>
<td>{{ item.lastname }}</td>
-<!-- <td>{{ item.passed }}</td>-->
+ <td>{{ item.status }}</td>
+ <td>{{ dayjs(item.status_changed).format("DD.MM.YYYY HH:mm:ss") }}</td>
+ <td>{{ item.status_overwrite }}</td>
+ </tr>
+ </tbody>
+ </table>
+
+ <br>
+
+ <h2>Raw <small>{{kursLpRaw?.length || 0}}</small></h2>
+ <table class="w100p">
+ <thead>
+ <tr>
+ <th>usr_id</th>
+ <th>login</th>
+ <th>firstname</th>
+ <th>lastname</th>
+<!-- <th>passed</th>-->
+ <th>status</th>
+ <th>status_changed</th>
+ <th>status_overwrite</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="item in kursLpRaw">
+ <td>
+ <RouterLink :to="`${routerBase}/ui/user/${item.usr_id}`">
+ {{ item.usr_id }}
+ </RouterLink>
+ </td>
+ <td>{{ item.login }}</td>
+ <td>{{ item.firstname }}</td>
+ <td>{{ item.lastname }}</td>
<td>{{ item.status }}</td>
<td>{{ dayjs(item.status_changed).format("DD.MM.YYYY HH:mm:ss") }}</td>
<td>{{ item.status_overwrite }}</td>
--
Gitblit v1.8.0