REST Service for POPCORN - ILIAS
alex
2025-07-06 041c712a57550df0fcfd5d016ae6a8fb689d27a5
lib/db.js
@@ -1,4 +1,5 @@
const mysql = require("mysql2/promise")
const dayjs = require("dayjs")
const searchLib = require("./search")
const {host, port, user, database, password} = require("./../settings").db
@@ -40,11 +41,16 @@
   getKursTeilnehmer,
   getKursTeilnehmerCount,
   getUdf,
   getMemberRoleForCourse,
   setStatus,
}
/////////////////////////////////////////////////////////////////////////
function getUserSearchQuery (offset, limit, search) {
async function getUserSearchQuery (offset, limit, search) {
   const sel = `usr_id, login, firstname, lastname, gender, email, institution, street, city, zipcode, country, department, active`
   if (!search || search === '') {
      return `SELECT ${sel}
@@ -55,8 +61,11 @@
      `
   }
   else {
      const ids = searchLib.search(search)
      // if (!ids.length) return getUserSearchQuery(offset, limit) // nothing found
      const ids = await searchLib.search(search)
      if (!ids.length) {
         throw "nothing found"
         return await getUserSearchQuery(offset, limit)
      } // nothing found
      return `SELECT ${sel}
              FROM ${database}.usr_data AS ud
              WHERE login REGEXP '^[0-9]+$'
@@ -75,21 +84,30 @@
   const pool = await poolP
   let userSearchQuery = getUserSearchQuery(offset, limit, search)
   // console.log(userSearchQuery)
   const [results, fields] = await pool.query(userSearchQuery)
   const count = await getUserCount(offset, limit, search)
   return {
      total: count,
      offset, limit,
      data: results,
   try {
      let userSearchQuery = await getUserSearchQuery(offset, limit, search)
      // console.log(userSearchQuery)
      const [results, fields] = await pool.query(userSearchQuery)
      const count = await getUserCount(offset, limit, search)
      return {
         total: count,
         offset, limit,
         data: results,
      }
   } catch (ex) {
      return {
         total: 0,
         offset: 0,
         limit: 0,
         data: [],
      }
   }
}
async function getUserCount (offset, limit, search) {
   const pool = await poolP
   // const q = getUserSearchQuery(offset, limit, search)
   const q = getUserSearchQuery(0, 1000000, search) // hier darf kein Limit sein, offset=0
   const q = await getUserSearchQuery(0, 1000000, search) // hier darf kein Limit sein, offset=0
   const q2 = `SELECT COUNT(*) AS count
               FROM (${q}) AS X`
   const [results, fields] = await pool.query(q2)
@@ -243,29 +261,30 @@
async function getKursItems2 (ref_id) {
   const pool = await poolP
   const q = `
       WITH RECURSIVE tree (parent_id, obj_id, ref_id, title, type) AS (SELECT ci.parent_id,
                                                                               or2.obj_id,
                                                                               ci.obj_id as ref_id,
                                                                               od.title,
                                                                               od.type
                                                                        FROM ${database}.crs_items ci
                                                                                 INNER JOIN ${database}.object_reference or2 ON or2.ref_id = ci.obj_id
                                                                                 INNER JOIN ${database}.object_data od ON od.obj_id = or2.obj_id
                                                                        WHERE ci.obj_id = ${ref_id} -- Kurs ref_id
                                                                          AND or2.deleted is NULL
       WITH RECURSIVE tree (parent_id, obj_id, ref_id, title, type) AS
                          (SELECT ci.parent_id,
                                  or2.obj_id,
                                  ci.obj_id as ref_id,
                                  od.title,
                                  od.type
                           FROM ${database}.crs_items ci
                                    INNER JOIN ${database}.object_reference or2 ON or2.ref_id = ci.obj_id
                                    INNER JOIN ${database}.object_data od ON od.obj_id = or2.obj_id
                           WHERE ci.obj_id = ${ref_id} -- Kurs ref_id
                             AND or2.deleted is NULL
                                                                        UNION ALL
                           UNION ALL
                                                                        SELECT child.parent_id,
                                                                               or2.obj_id,
                                                                               child.obj_id as ref_id,
                                                                               od.title,
                                                                               od.type
                                                                        FROM ${database}.crs_items child
                                                                                 INNER JOIN ${database}.object_reference or2 ON or2.ref_id = child.obj_id
                                                                                 INNER JOIN ${database}.object_data od ON od.obj_id = or2.obj_id
                                                                                 JOIN tree ON child.parent_id = tree.ref_id
                                                                        WHERE or2.deleted is NULL)
                           SELECT child.parent_id,
                                  or2.obj_id,
                                  child.obj_id as ref_id,
                                  od.title,
                                  od.type
                           FROM ${database}.crs_items child
                                    INNER JOIN ${database}.object_reference or2 ON or2.ref_id = child.obj_id
                                    INNER JOIN ${database}.object_data od ON od.obj_id = or2.obj_id
                                    JOIN tree ON child.parent_id = tree.ref_id
                           WHERE or2.deleted is NULL)
       SELECT *
       FROM tree
       ORDER BY tree.ref_id
@@ -298,6 +317,7 @@
              WHERE (or2.ref_id = ${ref_id} OR parent_id = ${ref_id})
              ORDER BY usr_id
   `
   console.log(q)
   const [results] = await pool.query(q)
   return results
}
@@ -337,3 +357,101 @@
   const [results] = await pool.query(q)
   return results
}
/////// UDF ////////////////////////////////////////////////////////////////
async function getUdf () {
   const pool = await poolP
   const q = `SELECT field_id, field_name, field_type
              from ${database}.udf_definition;`
   const [results] = await pool.query(q)
   return results
}
/////// ROLLEN ////////////////////////////////////////////////////////////////
async function getMemberRoleForCourse (obj_id) {
   const pool = await poolP
   const q = `SELECT obj_id, title, description
              from object_data od
              WHERE type = "role" #AND title LIKE 'il_crs_member_157'
                AND od.description LIKE 'Member%${obj_id}'
   `
   const [results] = await pool.query(q)
   // darf nur einen Treffer ergeben
   if (results.length) {
      const {obj_id, title, description} = results[0]
      return obj_id
   }
   else {
      return null
   }
}
/////// STATUS ////////////////////////////////////////////////////////////////
/**
 * Zwei Möglichkeiten:
 * 1. es gibt schon einen Eintrag in ut_lp_marks, dann muss man diesen updaten
 * 2. es gibt noch keinen Eintrag in ut_lp_marks, dann muss erst einer erstellt werden (NEIN! Für neuen TN sind bereits beide Einträge vorhanden, kann also wegfallen)
 *
 * Weiterhin haben wir es mit zwei Tabellen zu tun:
 *    - obj_members (passed)
 *    - ut_lp_marks (status)
 *
 * UPDATE: Wir nehmen an, dass beide Einträge schon vorhanden sind!
 *
 * @param courseId
 * @param userId
 * @param passed
 * @param status
 * @returns {Promise<{status: string}>}
 */
async function setStatus (courseId, userId, passed = null, status = null) {
   const pool = await poolP
   // ACHTUNG Transactions funktioneren so nicht, erst mal ohne machen...
   const q = `
START TRANSACTION;
UPDATE ${database}.ut_lp_marks ulm
SET status = ${status}
WHERE ulm.usr_id = 31793 AND ulm.obj_id = 32212;
UPDATE ${database}.obj_members om
SET passed = ${passed}
WHERE om.usr_id = ${userId} AND om.obj_id = ${courseId};
COMMIT;
`
   let date = dayjs().format('YYYY-MM-DD HH:mm:ss')
   const q1 = `
       UPDATE ${database}.ut_lp_marks ulm
       SET status         = ${status},
           status_changed = "${date}"
       WHERE ulm.usr_id = ${userId}
         AND ulm.obj_id = ${courseId};
   `
   const q2 = `
       UPDATE ${database}.obj_members om
       SET passed = ${passed}
       WHERE om.usr_id = ${userId}
         AND om.obj_id = ${courseId};
   `
   const [results1] = await pool.query(q1)
   const [results2] = await pool.query(q2)
   const {affectedRows: affectedRows1} = results1
   const {affectedRows: affectedRows2} = results2
   if (affectedRows1 && affectedRows2) {
      return {status: "ok"}
   }
   else {
      throw {
         status: "error",
         reason: {affectedRows1, affectedRows2}
      }
   }
}