const _ = require("lodash") const dayjs = require("dayjs") ///////////////////////////////////////////////////////////////////////// module.exports = { alleAuswerten, auswerten, partitionDates, } ///////////////////////////////////////////////////////////////////////// /** * 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,login,firstname,lastname,status,status_changed]} */ function alleAuswerten(data) { const grouped = _.groupBy(data, "usr_id") const ret = [] for (const items of Object.values(grouped)) { const statusData = items.map(({status_changed, status}) => ({status_changed, status})) const newStatus = auswerten(statusData) 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) } return ret } /** * Neuen Status berechnen * @param {{status,status_changed}[]} statusData * @return {number} */ function auswerten(statusData) { // unter Status auswerten // 0 = noch nicht bearbeitet // 1 = in Bearbeitung // 2 = bestanden // 3 = nicht bestanden // Fall 1: keine Unterstatussse vorhanden -> 0 if (!statusData.length) { return 0 } const maxDate = dayjs(_.max(statusData.map(it => it.status_changed))) const {inside, outside} = partitionDates(maxDate, statusData) // Fall 2: eines nicht bestanden -> alles nicht bestanden // 0,1,2,3 -> 3 // hier kommt es nicht darauf an ob noch Daten in outside sind if (inside.map(it => it.status).some(u => u === 3)) { return 3 } // Fall 3: alle statusse gleich -> status // 0,0,0 1,1,1 2,2,2 3,3,3 // wenn outside nicht leer ist -> in Bearbeitung if (isAllSame(inside.map(it => it.status))) { // wenn keine Einträge in outside vorhanden sind einfach den Status zurückgeben if(!outside.length) return statusData[0].status // ansonsten in Bearbeitung return 1 } // Fall 4: wenn eines in Bearbeitung -> in Bearbeitung // 0,1,0 2,1,2 if (inside.map(it=>it.status).some(u => u === 1 || u === 2)) { return 1 } // Fall 5: sonst 0 return 0 } /** * @param {Date} maxDate * @param {{status, status_changed}[]} items */ function partitionDates(maxDate, items) { const [inside, outside] = _.partition(items, function (it) { return isInBallpark(maxDate, it.status_changed) }) return {inside, outside} } function isInBallpark(maxDate, date) { const ballpark = {value: 1, unit: "month"} const diff = maxDate.diff(date, ballpark.unit, true) return diff <= ballpark.value } function isAllSame(items) { if (!items.length) return false const first = items[0] return items.every(it => it === first) }