@softwear/latestcollectioncore 1.0.95 → 1.0.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -81,24 +81,32 @@ function addTransactionToAggregations(beginTimestamp, endTimestamp, aggregateKey
81
81
  aggregateVector = new Float64Array(VECTOR_LENGTH);
82
82
  rawAggregations[aggregateKey] = aggregateVector;
83
83
  }
84
- const vector = transaction.vector;
84
+ const v = transaction.vector;
85
85
  if (transaction.type == '1' && transaction.time > aggregateVector[MAX_RECIEVE_TIMESTAMP])
86
86
  aggregateVector[MAX_RECIEVE_TIMESTAMP] = transaction.time;
87
87
  if (transaction.time <= beginTimestamp) {
88
- addVectors(aggregateVector, vector, BEGIN_STOCK_VECTOR_START, BEGIN_STOCK_VECTOR_END);
89
- addVectors(aggregateVector, vector, QTY_CONSIGNMENT, COSTPRICE_CONSIGNMENT + 1);
88
+ addVectors(aggregateVector, v, BEGIN_STOCK_VECTOR_START, BEGIN_STOCK_VECTOR_END);
89
+ addVectors(aggregateVector, v, QTY_CONSIGNMENT, COSTPRICE_PICKLIST + 1);
90
90
  return;
91
91
  }
92
92
  if (transaction.time > endTimestamp)
93
93
  return;
94
- addVectors(aggregateVector, vector, BEGIN_STOCK_VECTOR_END, vector.length);
94
+ addVectors(aggregateVector, v, BEGIN_STOCK_VECTOR_END, v.length);
95
95
  // Calculate derived fields
96
- aggregateVector[QTY_RETURN] += vector[QTY_SOLD] < 0 ? vector[QTY_SOLD] : 0;
97
- aggregateVector[AMOUNT_RETURN] += vector[AMOUNT_SOLD_EXCL] < 0 ? vector[AMOUNT_SOLD_EXCL] : 0;
96
+ aggregateVector[QTY_RETURN] += v[QTY_SOLD] < 0 ? v[QTY_SOLD] : 0;
97
+ aggregateVector[AMOUNT_RETURN] += v[AMOUNT_SOLD_EXCL] < 0 ? v[AMOUNT_SOLD_EXCL] : 0;
98
98
  aggregateVector[STOCK_TIME_PRODUCT] +=
99
- (vector[QTY_RECIEVED] || 0 + vector[QTY_TRANSIT] || 0 + vector[QTY_CHANGE] || 0 - vector[QTY_SOLD] || 0) * (endTimestamp - transaction.time);
99
+ ((v[QTY_RECIEVED] || 0) + (v[QTY_TRANSIT] || 0) + (v[QTY_CHANGE] || 0) - (v[QTY_SOLD] || 0) - (v[QTY_B2B_SOLD] || 0) - (v[QTY_B2B_RESOLD] || 0) + (v[QTY_B2B_RETURN] || 0)) *
100
+ (endTimestamp - transaction.time);
100
101
  aggregateVector[STOCKAMOUNT_TIME_PRODUCT] +=
101
- (vector[AMOUNT_RECIEVED] || 0 + vector[AMOUNT_TRANSIT] || 0 + vector[AMOUNT_CHANGE] || 0 - vector[COSTPRICE_SOLD] || 0) * (endTimestamp - transaction.time);
102
+ ((v[AMOUNT_RECIEVED] || 0) +
103
+ (v[AMOUNT_TRANSIT] || 0) +
104
+ (v[AMOUNT_CHANGE] || 0) -
105
+ (v[COSTPRICE_SOLD] || 0) -
106
+ (v[COSTPRICE_B2B_SOLD] || 0) -
107
+ (v[COSTPRICE_B2B_RESOLD] || 0) +
108
+ (v[COSTPRICE_B2B_RETURN] || 0)) *
109
+ (endTimestamp - transaction.time);
102
110
  }
103
111
  function buildAggregationEvaluator(aggregationExpression) {
104
112
  return (0, filtrex_1.compileExpression)(aggregationExpression, filtrexOptions);
@@ -173,9 +181,9 @@ function aggregator({ beginTimestamp, endTimestamp, filterExpression, aggregatio
173
181
  // Prepare joined values for derived fields
174
182
  if (transaction.type == '2') {
175
183
  const sku = globalRelations['sku'][transaction.ean];
176
- const vector = transaction.vector;
177
- vector[AMOUNT_SOLD_MAX] = ((sku === null || sku === void 0 ? void 0 : sku.price) || 0) * vector[QTY_SOLD];
178
- vector[AMOUNT_SOLD_DISCOUNT] = vector[AMOUNT_SOLD_MAX] - vector[AMOUNT_SOLD];
184
+ const v = transaction.vector;
185
+ v[AMOUNT_SOLD_MAX] = ((sku === null || sku === void 0 ? void 0 : sku.price) || 0) * v[QTY_SOLD];
186
+ v[AMOUNT_SOLD_DISCOUNT] = v[AMOUNT_SOLD_MAX] - v[AMOUNT_SOLD];
179
187
  }
180
188
  if (totals)
181
189
  addTransactionToAggregations(beginTimestamp, endTimestamp, '** TOTAL **', rawAggregations, transaction, maxRows);
@@ -250,28 +258,22 @@ function whichShardsToProcess(dateRange, granularity) {
250
258
  * Calculate all derived columns on a given vector.
251
259
  */
252
260
  function postAgg(v, timeFrame) {
253
- v[QTY_END_STOCK] = v[QTY_STOCK] + v[QTY_RECIEVED] - v[QTY_SOLD] + v[QTY_CHANGE] + v[QTY_TRANSIT] - v[QTY_B2B_SOLD] - v[QTY_B2B_RESOLD] + v[QTY_B2B_RETURN];
254
- v[AMOUNT_END_STOCK] =
255
- v[AMOUNT_STOCK] +
256
- v[AMOUNT_RECIEVED] -
257
- v[COSTPRICE_SOLD] +
258
- v[AMOUNT_CHANGE] +
259
- v[AMOUNT_TRANSIT] +
260
- v[AMOUNT_REVALUATE] -
261
- v[COSTPRICE_B2B_SOLD] -
262
- v[COSTPRICE_B2B_RESOLD] +
263
- v[COSTPRICE_B2B_RETURN];
261
+ const totalQtySold = v[QTY_SOLD] + v[QTY_B2B_SOLD] + v[QTY_B2B_RESOLD] - v[QTY_B2B_RETURN];
262
+ const totalAmountSold = v[AMOUNT_SOLD_EXCL] + v[AMOUNT_B2B_SOLD] + v[AMOUNT_B2B_RESOLD] - v[AMOUNT_B2B_RETURN];
263
+ const totalCostSold = v[COSTPRICE_SOLD] + v[COSTPRICE_B2B_SOLD] + v[COSTPRICE_B2B_RESOLD] - v[COSTPRICE_B2B_RETURN];
264
+ v[QTY_END_STOCK] = v[QTY_STOCK] + v[QTY_RECIEVED] + v[QTY_CHANGE] + v[QTY_TRANSIT] - totalQtySold;
265
+ v[AMOUNT_END_STOCK] = v[AMOUNT_STOCK] + v[AMOUNT_RECIEVED] + v[AMOUNT_CHANGE] + v[AMOUNT_TRANSIT] + v[AMOUNT_REVALUATE] - totalCostSold;
264
266
  v[QTY_END_SHELF_STOCK] = v[QTY_END_STOCK] - v[QTY_CONSIGNMENT] - v[QTY_PICKLIST];
265
267
  v[AMOUNT_END_SHELF_STOCK] = v[AMOUNT_END_STOCK] - v[COSTPRICE_CONSIGNMENT] - v[AMOUNT_PICKLIST];
266
- v[SELLOUT_PERCENTAGE] = (v[QTY_SOLD] / (v[QTY_SOLD] + v[QTY_END_STOCK])) * 100;
267
- v[ROI] = v[AMOUNT_SOLD_EXCL] - v[AMOUNT_RECIEVED] + v[AMOUNT_TRANSIT];
268
+ v[SELLOUT_PERCENTAGE] = (totalQtySold / (totalQtySold + v[QTY_END_STOCK])) * 100;
269
+ v[ROI] = totalAmountSold - v[AMOUNT_RECIEVED] + v[AMOUNT_TRANSIT];
268
270
  v[QTY_AVG_STOCK] = (v[QTY_STOCK] * timeFrame + v[STOCK_TIME_PRODUCT]) / timeFrame;
269
271
  v[VALUE_AVG_STOCK] = (v[AMOUNT_STOCK] * timeFrame + v[STOCKAMOUNT_TIME_PRODUCT]) / timeFrame;
270
- v[QTY_TURNOVER_VELOCITY] = ((v[QTY_SOLD] / v[QTY_AVG_STOCK]) * msYear) / timeFrame;
271
- v[AMOUNT_TURNOVER_VELOCITY] = ((v[COSTPRICE_SOLD] / v[VALUE_AVG_STOCK]) * msYear) / timeFrame;
272
- v[PROFIT] = v[AMOUNT_SOLD_EXCL] - v[COSTPRICE_SOLD];
273
- v[PROFITABILITY] = (v[PROFIT] / v[COSTPRICE_SOLD]) * v[QTY_TURNOVER_VELOCITY] * 100;
274
- v[MARGIN] = (v[PROFIT] / v[AMOUNT_SOLD_EXCL]) * 100;
272
+ v[QTY_TURNOVER_VELOCITY] = ((totalQtySold / v[QTY_AVG_STOCK]) * msYear) / timeFrame;
273
+ v[AMOUNT_TURNOVER_VELOCITY] = ((totalCostSold / v[VALUE_AVG_STOCK]) * msYear) / timeFrame;
274
+ v[PROFIT] = totalAmountSold - totalCostSold;
275
+ v[PROFITABILITY] = (v[PROFIT] / totalCostSold) * v[QTY_TURNOVER_VELOCITY] * 100;
276
+ v[MARGIN] = (v[PROFIT] / totalAmountSold) * 100;
275
277
  v[RETURN_PERCENTAGE] = (v[QTY_RETURN] / v[QTY_RECIEVED]) * 100;
276
278
  v[QTY_SOLD_BEFORE_RETURNS] = v[QTY_SOLD] + Math.abs(v[QTY_RETURN]);
277
279
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@softwear/latestcollectioncore",
3
- "version": "1.0.95",
3
+ "version": "1.0.97",
4
4
  "description": "Core functions for LatestCollections applications",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -128,25 +128,33 @@ function addTransactionToAggregations(beginTimestamp: number, endTimestamp: numb
128
128
  aggregateVector = new Float64Array(VECTOR_LENGTH)
129
129
  rawAggregations[aggregateKey] = aggregateVector
130
130
  }
131
- const vector = transaction.vector
131
+ const v = transaction.vector
132
132
  if (transaction.type == '1' && transaction.time > aggregateVector[MAX_RECIEVE_TIMESTAMP]) aggregateVector[MAX_RECIEVE_TIMESTAMP] = transaction.time
133
133
  if (transaction.time <= beginTimestamp) {
134
- addVectors(aggregateVector, vector, BEGIN_STOCK_VECTOR_START, BEGIN_STOCK_VECTOR_END)
135
- addVectors(aggregateVector, vector, QTY_CONSIGNMENT, COSTPRICE_CONSIGNMENT + 1)
134
+ addVectors(aggregateVector, v, BEGIN_STOCK_VECTOR_START, BEGIN_STOCK_VECTOR_END)
135
+ addVectors(aggregateVector, v, QTY_CONSIGNMENT, COSTPRICE_PICKLIST + 1)
136
136
  return
137
137
  }
138
138
  if (transaction.time > endTimestamp) return
139
- addVectors(aggregateVector, vector, BEGIN_STOCK_VECTOR_END, vector.length)
139
+ addVectors(aggregateVector, v, BEGIN_STOCK_VECTOR_END, v.length)
140
140
 
141
141
  // Calculate derived fields
142
142
 
143
- aggregateVector[QTY_RETURN] += vector[QTY_SOLD] < 0 ? vector[QTY_SOLD] : 0
144
- aggregateVector[AMOUNT_RETURN] += vector[AMOUNT_SOLD_EXCL] < 0 ? vector[AMOUNT_SOLD_EXCL] : 0
143
+ aggregateVector[QTY_RETURN] += v[QTY_SOLD] < 0 ? v[QTY_SOLD] : 0
144
+ aggregateVector[AMOUNT_RETURN] += v[AMOUNT_SOLD_EXCL] < 0 ? v[AMOUNT_SOLD_EXCL] : 0
145
145
 
146
146
  aggregateVector[STOCK_TIME_PRODUCT] +=
147
- (vector[QTY_RECIEVED] || 0 + vector[QTY_TRANSIT] || 0 + vector[QTY_CHANGE] || 0 - vector[QTY_SOLD] || 0) * (endTimestamp - transaction.time)
147
+ ((v[QTY_RECIEVED] || 0) + (v[QTY_TRANSIT] || 0) + (v[QTY_CHANGE] || 0) - (v[QTY_SOLD] || 0) - (v[QTY_B2B_SOLD] || 0) - (v[QTY_B2B_RESOLD] || 0) + (v[QTY_B2B_RETURN] || 0)) *
148
+ (endTimestamp - transaction.time)
148
149
  aggregateVector[STOCKAMOUNT_TIME_PRODUCT] +=
149
- (vector[AMOUNT_RECIEVED] || 0 + vector[AMOUNT_TRANSIT] || 0 + vector[AMOUNT_CHANGE] || 0 - vector[COSTPRICE_SOLD] || 0) * (endTimestamp - transaction.time)
150
+ ((v[AMOUNT_RECIEVED] || 0) +
151
+ (v[AMOUNT_TRANSIT] || 0) +
152
+ (v[AMOUNT_CHANGE] || 0) -
153
+ (v[COSTPRICE_SOLD] || 0) -
154
+ (v[COSTPRICE_B2B_SOLD] || 0) -
155
+ (v[COSTPRICE_B2B_RESOLD] || 0) +
156
+ (v[COSTPRICE_B2B_RETURN] || 0)) *
157
+ (endTimestamp - transaction.time)
150
158
  }
151
159
 
152
160
  function buildAggregationEvaluator(aggregationExpression: string): Function {
@@ -233,9 +241,9 @@ function aggregator({
233
241
  // Prepare joined values for derived fields
234
242
  if (transaction.type == '2') {
235
243
  const sku = globalRelations['sku'][transaction.ean]
236
- const vector = transaction.vector
237
- vector[AMOUNT_SOLD_MAX] = (sku?.price || 0) * vector[QTY_SOLD]
238
- vector[AMOUNT_SOLD_DISCOUNT] = vector[AMOUNT_SOLD_MAX] - vector[AMOUNT_SOLD]
244
+ const v = transaction.vector
245
+ v[AMOUNT_SOLD_MAX] = (sku?.price || 0) * v[QTY_SOLD]
246
+ v[AMOUNT_SOLD_DISCOUNT] = v[AMOUNT_SOLD_MAX] - v[AMOUNT_SOLD]
239
247
  }
240
248
 
241
249
  if (totals) addTransactionToAggregations(beginTimestamp, endTimestamp, '** TOTAL **', rawAggregations, transaction, maxRows)
@@ -315,28 +323,23 @@ function whichShardsToProcess(dateRange: any, granularity: 'year' | 'month'): an
315
323
  * Calculate all derived columns on a given vector.
316
324
  */
317
325
  function postAgg(v: any, timeFrame: number): void {
318
- v[QTY_END_STOCK] = v[QTY_STOCK] + v[QTY_RECIEVED] - v[QTY_SOLD] + v[QTY_CHANGE] + v[QTY_TRANSIT] - v[QTY_B2B_SOLD] - v[QTY_B2B_RESOLD] + v[QTY_B2B_RETURN]
319
- v[AMOUNT_END_STOCK] =
320
- v[AMOUNT_STOCK] +
321
- v[AMOUNT_RECIEVED] -
322
- v[COSTPRICE_SOLD] +
323
- v[AMOUNT_CHANGE] +
324
- v[AMOUNT_TRANSIT] +
325
- v[AMOUNT_REVALUATE] -
326
- v[COSTPRICE_B2B_SOLD] -
327
- v[COSTPRICE_B2B_RESOLD] +
328
- v[COSTPRICE_B2B_RETURN]
326
+ const totalQtySold = v[QTY_SOLD] + v[QTY_B2B_SOLD] + v[QTY_B2B_RESOLD] - v[QTY_B2B_RETURN]
327
+ const totalAmountSold = v[AMOUNT_SOLD_EXCL] + v[AMOUNT_B2B_SOLD] + v[AMOUNT_B2B_RESOLD] - v[AMOUNT_B2B_RETURN]
328
+ const totalCostSold = v[COSTPRICE_SOLD] + v[COSTPRICE_B2B_SOLD] + v[COSTPRICE_B2B_RESOLD] - v[COSTPRICE_B2B_RETURN]
329
+
330
+ v[QTY_END_STOCK] = v[QTY_STOCK] + v[QTY_RECIEVED] + v[QTY_CHANGE] + v[QTY_TRANSIT] - totalQtySold
331
+ v[AMOUNT_END_STOCK] = v[AMOUNT_STOCK] + v[AMOUNT_RECIEVED] + v[AMOUNT_CHANGE] + v[AMOUNT_TRANSIT] + v[AMOUNT_REVALUATE] - totalCostSold
329
332
  v[QTY_END_SHELF_STOCK] = v[QTY_END_STOCK] - v[QTY_CONSIGNMENT] - v[QTY_PICKLIST]
330
333
  v[AMOUNT_END_SHELF_STOCK] = v[AMOUNT_END_STOCK] - v[COSTPRICE_CONSIGNMENT] - v[AMOUNT_PICKLIST]
331
- v[SELLOUT_PERCENTAGE] = (v[QTY_SOLD] / (v[QTY_SOLD] + v[QTY_END_STOCK])) * 100
332
- v[ROI] = v[AMOUNT_SOLD_EXCL] - v[AMOUNT_RECIEVED] + v[AMOUNT_TRANSIT]
334
+ v[SELLOUT_PERCENTAGE] = (totalQtySold / (totalQtySold + v[QTY_END_STOCK])) * 100
335
+ v[ROI] = totalAmountSold - v[AMOUNT_RECIEVED] + v[AMOUNT_TRANSIT]
333
336
  v[QTY_AVG_STOCK] = (v[QTY_STOCK] * timeFrame + v[STOCK_TIME_PRODUCT]) / timeFrame
334
337
  v[VALUE_AVG_STOCK] = (v[AMOUNT_STOCK] * timeFrame + v[STOCKAMOUNT_TIME_PRODUCT]) / timeFrame
335
- v[QTY_TURNOVER_VELOCITY] = ((v[QTY_SOLD] / v[QTY_AVG_STOCK]) * msYear) / timeFrame
336
- v[AMOUNT_TURNOVER_VELOCITY] = ((v[COSTPRICE_SOLD] / v[VALUE_AVG_STOCK]) * msYear) / timeFrame
337
- v[PROFIT] = v[AMOUNT_SOLD_EXCL] - v[COSTPRICE_SOLD]
338
- v[PROFITABILITY] = (v[PROFIT] / v[COSTPRICE_SOLD]) * v[QTY_TURNOVER_VELOCITY] * 100
339
- v[MARGIN] = (v[PROFIT] / v[AMOUNT_SOLD_EXCL]) * 100
338
+ v[QTY_TURNOVER_VELOCITY] = ((totalQtySold / v[QTY_AVG_STOCK]) * msYear) / timeFrame
339
+ v[AMOUNT_TURNOVER_VELOCITY] = ((totalCostSold / v[VALUE_AVG_STOCK]) * msYear) / timeFrame
340
+ v[PROFIT] = totalAmountSold - totalCostSold
341
+ v[PROFITABILITY] = (v[PROFIT] / totalCostSold) * v[QTY_TURNOVER_VELOCITY] * 100
342
+ v[MARGIN] = (v[PROFIT] / totalAmountSold) * 100
340
343
  v[RETURN_PERCENTAGE] = (v[QTY_RETURN] / v[QTY_RECIEVED]) * 100
341
344
  v[QTY_SOLD_BEFORE_RETURNS] = v[QTY_SOLD] + Math.abs(v[QTY_RETURN])
342
345
  }
@@ -2,6 +2,99 @@ const core = require('../dist/index')
2
2
  const { expect } = require('chai')
3
3
 
4
4
  const articleStatus = core.articleStatus
5
+ const msYear = 24 * 3600 * 365 * 1000
6
+
7
+ const TRANSACTIONS = [
8
+ {
9
+ time: 1546297200000,
10
+ type: '0',
11
+ ean: '000558000143',
12
+ wh: '50',
13
+ vector: [10, 10, 49.5, 10, 49.5, 0, 0, 0, 0, 0, 0, 0, 10, 49.5],
14
+ row: 0,
15
+ },
16
+ {
17
+ time: 1546297200000,
18
+ type: '0',
19
+ ean: '000558000143',
20
+ wh: '54',
21
+ vector: [1, 1, 4.95, 1, 4.95, 0, 0, 0, 0, 0, 0, 0, 1, 4.95],
22
+ row: 1,
23
+ },
24
+ {
25
+ time: 1546297200000,
26
+ type: '0',
27
+ ean: '000558000143',
28
+ wh: '55',
29
+ vector: [1, 1, 4.95, 1, 4.95, 0, 0, 0, 0, 0, 0, 0, 1, 4.95],
30
+ row: 2,
31
+ },
32
+ {
33
+ time: 1546297200000,
34
+ type: '0',
35
+ ean: '000558000143',
36
+ wh: '56',
37
+ vector: [1, 1, 4.95, 1, 4.95, 0, 0, 0, 0, 0, 0, 0, 1, 4.95],
38
+ row: 3,
39
+ },
40
+ {
41
+ time: 1546297200000,
42
+ type: '0',
43
+ ean: '000558000143',
44
+ wh: '57',
45
+ vector: [5, 5, 24.75, 5, 24.75, 0, 0, 0, 0, 0, 0, 0, 5, 24.75],
46
+ row: 4,
47
+ },
48
+ {
49
+ time: 1569316409000,
50
+ type: '2',
51
+ ean: '000558000143',
52
+ agent: '96',
53
+ wh: '52',
54
+ custnr: '*zBXU',
55
+ docnr: '52-216-2515',
56
+ vector: [1, -1, -4.95, -1, -4.95, 0, 0, 0, 1, 10.95, 9.05, 4.95],
57
+ row: 5,
58
+ },
59
+ {
60
+ time: 1546297200000,
61
+ type: '0',
62
+ ean: '8700558000143',
63
+ wh: '57',
64
+ vector: [10, 10, 100, 10, 100, 0, 0, 0, 0, 0, 0, 0, 10, 100],
65
+ row: 6,
66
+ },
67
+ {
68
+ time: 1569316409000,
69
+ type: '2',
70
+ ean: '8700558000143',
71
+ agent: '96',
72
+ wh: '57',
73
+ custnr: '*zBXU',
74
+ docnr: '52-216-2515',
75
+ vector: [1, -1, -10, -1, -10, 0, 0, 0, 1, 25, 20, 10],
76
+ row: 7,
77
+ },
78
+ {
79
+ time: 1569316409000,
80
+ type: '93',
81
+ ean: '8700558000143',
82
+ agent: '96',
83
+ wh: '52',
84
+ custnr: '*zBXU',
85
+ docnr: '52-216-2515',
86
+ vector: [1, -1, -10, -1, -10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 20, 10],
87
+ row: 8,
88
+ },
89
+ ]
90
+ SKUS = {
91
+ '000558000143': {
92
+ brand: 'Mexx',
93
+ },
94
+ 8700558000143: {
95
+ brand: 'Gaastra',
96
+ },
97
+ }
5
98
  describe('#articleStatus', () => {
6
99
  describe('#constants', () => {
7
100
  it('QTY_SOLD_BEFORE_RETURNS should be 64', () => {
@@ -11,4 +104,140 @@ describe('#articleStatus', () => {
11
104
  expect(articleStatus.AMOUNT_RETURN).to.equal(49)
12
105
  })
13
106
  })
107
+ describe('#runQuery', () => {
108
+ it('should calculate aggregations, totals and subtotals', () => {
109
+ const rawAggregations = {}
110
+ articleStatus.runQuery(
111
+ { beginTimeStamp: 1569316408000, endTimeStamp: 1569316409000 + msYear },
112
+ rawAggregations,
113
+ true,
114
+ TRANSACTIONS,
115
+ ['transaction.ean'],
116
+ {},
117
+ {},
118
+ {},
119
+ true,
120
+ 'transaction.ean=="000558000143"',
121
+ false
122
+ )
123
+
124
+ const result = []
125
+ Object.entries(rawAggregations).map((oneAggregatedRow) => {
126
+ const vector = [].slice.call(oneAggregatedRow[1]) // vector is now a normal Array instead of a Float64Array so can be extended with additional fields
127
+ articleStatus.postAgg(vector, msYear)
128
+ result.push({ key: oneAggregatedRow[0], vector })
129
+ })
130
+ expect(result[0].key).to.equal('** TOTAL **')
131
+ expect(JSON.stringify(result[0].vector[articleStatus.QTY_STOCK])).to.equal('18')
132
+ expect(JSON.stringify(result[0].vector[articleStatus.AMOUNT_STOCK])).to.equal('89.10000000000001')
133
+ expect(JSON.stringify(result[0].vector[articleStatus.QTY_END_STOCK])).to.equal('17')
134
+ expect(JSON.stringify(result[0].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('84.15')
135
+ expect(JSON.stringify(result[0].vector[articleStatus.QTY_AVG_STOCK])).to.equal('17')
136
+ expect(JSON.stringify(result[0].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('84.15000000000002')
137
+
138
+ expect(result[1].key).to.equal(' Σ')
139
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_STOCK])).to.equal('18')
140
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_STOCK])).to.equal('89.10000000000001')
141
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_END_STOCK])).to.equal('17')
142
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('84.15')
143
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_AVG_STOCK])).to.equal('17')
144
+ expect(JSON.stringify(result[1].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('84.15000000000002')
145
+
146
+ expect(result[2].key).to.equal('000558000143')
147
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_STOCK])).to.equal('18')
148
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_STOCK])).to.equal('89.10000000000001')
149
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_END_STOCK])).to.equal('17')
150
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('84.15')
151
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_AVG_STOCK])).to.equal('17')
152
+ expect(JSON.stringify(result[2].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('84.15000000000002')
153
+ })
154
+
155
+ it('should calculate aggregations', () => {
156
+ const rawAggregations = {}
157
+ articleStatus.runQuery(
158
+ { beginTimeStamp: 1569316408000, endTimeStamp: 1569316408000 + msYear },
159
+ rawAggregations,
160
+ true,
161
+ TRANSACTIONS,
162
+ ['sku.brand'],
163
+ SKUS,
164
+ {},
165
+ {},
166
+ false,
167
+ '',
168
+ false
169
+ )
170
+
171
+ const result = []
172
+ Object.entries(rawAggregations).map((oneAggregatedRow) => {
173
+ const vector = [].slice.call(oneAggregatedRow[1]) // vector is now a normal Array instead of a Float64Array so can be extended with additional fields
174
+ articleStatus.postAgg(vector, msYear)
175
+ result.push({ key: oneAggregatedRow[0], vector })
176
+ })
177
+ expect(result[0].key).to.equal('** TOTAL **')
178
+ expect(JSON.stringify(result[0].vector[articleStatus.MARGIN])).to.equal('49.1335372069317')
179
+
180
+ expect(result[1].key).to.equal('Mexx')
181
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_STOCK])).to.equal('18')
182
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_STOCK])).to.equal('89.10000000000001')
183
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_END_STOCK])).to.equal('17')
184
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('84.15')
185
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_AVG_STOCK])).to.equal('17.000000031709792')
186
+ expect(JSON.stringify(result[1].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('84.15000015696349')
187
+ expect(JSON.stringify(result[1].vector[articleStatus.MARGIN])).to.equal('45.30386740331492')
188
+
189
+ expect(result[2].key).to.equal('Gaastra')
190
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_STOCK])).to.equal('10')
191
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_STOCK])).to.equal('100')
192
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_END_STOCK])).to.equal('8')
193
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('80')
194
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_AVG_STOCK])).to.equal('8.000000063419584')
195
+ expect(JSON.stringify(result[2].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('80.00000063419584')
196
+ expect(JSON.stringify(result[2].vector[articleStatus.MARGIN])).to.equal('50')
197
+ })
198
+
199
+ it('should calculate aggregations', () => {
200
+ const rawAggregations = {}
201
+ articleStatus.runQuery(
202
+ { beginTimeStamp: 1569316408000, endTimeStamp: 1569316408000 + msYear },
203
+ rawAggregations,
204
+ true,
205
+ TRANSACTIONS,
206
+ ['sku.brand'],
207
+ SKUS,
208
+ {},
209
+ {},
210
+ false,
211
+ 'transaction.wh=="57"',
212
+ false
213
+ )
214
+
215
+ const result = []
216
+ Object.entries(rawAggregations).map((oneAggregatedRow) => {
217
+ const vector = [].slice.call(oneAggregatedRow[1]) // vector is now a normal Array instead of a Float64Array so can be extended with additional fields
218
+ articleStatus.postAgg(vector, msYear)
219
+ result.push({ key: oneAggregatedRow[0], vector })
220
+ })
221
+ expect(result[0].key).to.equal('** TOTAL **')
222
+ expect(JSON.stringify(result[0].vector[articleStatus.MARGIN])).to.equal('50')
223
+
224
+ expect(result[1].key).to.equal('Mexx')
225
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_STOCK])).to.equal('5')
226
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_STOCK])).to.equal('24.75')
227
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_END_STOCK])).to.equal('5')
228
+ expect(JSON.stringify(result[1].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('24.75')
229
+ expect(JSON.stringify(result[1].vector[articleStatus.QTY_AVG_STOCK])).to.equal('5')
230
+ expect(JSON.stringify(result[1].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('24.75')
231
+ expect(JSON.stringify(result[1].vector[articleStatus.MARGIN])).to.equal('null')
232
+
233
+ expect(result[2].key).to.equal('Gaastra')
234
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_STOCK])).to.equal('10')
235
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_STOCK])).to.equal('100')
236
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_END_STOCK])).to.equal('9')
237
+ expect(JSON.stringify(result[2].vector[articleStatus.AMOUNT_END_STOCK])).to.equal('90')
238
+ expect(JSON.stringify(result[2].vector[articleStatus.QTY_AVG_STOCK])).to.equal('9.000000031709792')
239
+ expect(JSON.stringify(result[2].vector[articleStatus.VALUE_AVG_STOCK])).to.equal('90.00000031709791')
240
+ expect(JSON.stringify(result[2].vector[articleStatus.MARGIN])).to.equal('50')
241
+ })
242
+ })
14
243
  })