REST Service for POPCORN - ILIAS
alex
6 hours ago 6138ffe99d016cc311f250bc1555b5403b8b1216
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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)
}