@things-factory/dataset 6.2.86 → 6.2.87
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.
- package/client/pages/data-set/data-item-list.ts +12 -6
- package/client/pages/data-set/data-set-list-page.ts +1 -0
- package/dist-client/pages/data-set/data-item-list.js +12 -6
- package/dist-client/pages/data-set/data-item-list.js.map +1 -1
- package/dist-client/pages/data-set/data-set-list-page.js +1 -0
- package/dist-client/pages/data-set/data-set-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/finalize-data-collection.js +309 -0
- package/dist-server/controllers/finalize-data-collection.js.map +1 -0
- package/dist-server/controllers/query-data-summary-by-period.js +4 -9
- package/dist-server/controllers/query-data-summary-by-period.js.map +1 -1
- package/dist-server/service/data-set/data-item-type.js +16 -2
- package/dist-server/service/data-set/data-item-type.js.map +1 -1
- package/dist-server/service/data-set/data-set-mutation.js +2 -2
- package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
- package/dist-server/service/data-summary/data-summary-mutation.js +34 -5
- package/dist-server/service/data-summary/data-summary-mutation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/helps/dataset/ui/data-item-list.ko.md +17 -2
- package/package.json +2 -2
- package/server/controllers/{generate-data-summary.ts → finalize-data-collection.ts} +7 -39
- package/server/controllers/query-data-summary-by-period.ts +5 -18
- package/server/service/data-set/data-item-type.ts +18 -10
- package/server/service/data-set/data-set-mutation.ts +9 -31
- package/server/service/data-summary/data-summary-mutation.ts +24 -7
- package/translations/en.json +2 -1
- package/translations/ja.json +2 -1
- package/translations/ko.json +2 -1
- package/translations/ms.json +2 -1
- package/translations/zh.json +2 -1
@@ -0,0 +1,309 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.finalizeDataCollection = exports.finalizeLatestDataCollection = exports.getDataFinalizeCrontabSchedule = void 0;
|
4
|
+
const tslib_1 = require("tslib");
|
5
|
+
const statistics = require('simple-statistics');
|
6
|
+
const deepClone = require('lodash/cloneDeep');
|
7
|
+
const moment_timezone_1 = tslib_1.__importDefault(require("moment-timezone"));
|
8
|
+
const typeorm_1 = require("typeorm");
|
9
|
+
const shell_1 = require("@things-factory/shell");
|
10
|
+
const env_1 = require("@things-factory/env");
|
11
|
+
const work_shift_1 = require("@things-factory/work-shift");
|
12
|
+
const data_sample_1 = require("../service/data-sample/data-sample");
|
13
|
+
const data_set_1 = require("../service/data-set/data-set");
|
14
|
+
const data_summary_1 = require("../service/data-summary/data-summary");
|
15
|
+
const STAT_FUNCTION_MAP = {
|
16
|
+
sum: 'sum',
|
17
|
+
mean: 'mean',
|
18
|
+
stddev: 'standardDeviation',
|
19
|
+
variance: 'variance',
|
20
|
+
min: 'min',
|
21
|
+
max: 'max',
|
22
|
+
range: 'range',
|
23
|
+
median: 'median',
|
24
|
+
mode: 'mode'
|
25
|
+
};
|
26
|
+
const compareKeys = (dataKeyItems, summary, sample) => {
|
27
|
+
return dataKeyItems.every((item, index) => {
|
28
|
+
const prop = `key0${index + 1}`;
|
29
|
+
return sample[prop] === summary[prop];
|
30
|
+
});
|
31
|
+
};
|
32
|
+
const buildKeysFromSample = (dataKeyItems, sample) => {
|
33
|
+
return dataKeyItems.reduce((sum, item, index) => {
|
34
|
+
const prop = `key0${index + 1}`;
|
35
|
+
sum[prop] = sample[prop];
|
36
|
+
return sum;
|
37
|
+
}, {});
|
38
|
+
};
|
39
|
+
const buildKeySortingList = (dataKeyItems) => {
|
40
|
+
return dataKeyItems.reduce((sum, item, index) => {
|
41
|
+
const name = `key0${index + 1}`;
|
42
|
+
sum.push({ name, desc: true });
|
43
|
+
return sum;
|
44
|
+
}, []);
|
45
|
+
};
|
46
|
+
const calculateSummary = (dataItems, base) => {
|
47
|
+
return dataItems.reduce((summary, item) => {
|
48
|
+
const tag = item.tag;
|
49
|
+
const data = base[tag]
|
50
|
+
.flat(Infinity)
|
51
|
+
.map(Number)
|
52
|
+
.filter(item => !isNaN(item));
|
53
|
+
if (data.length > 0) {
|
54
|
+
try {
|
55
|
+
switch (item.stat) {
|
56
|
+
case 'range':
|
57
|
+
summary[tag] = statistics.max(data) - statistics.min(data);
|
58
|
+
break;
|
59
|
+
default:
|
60
|
+
const functionName = STAT_FUNCTION_MAP[item.stat];
|
61
|
+
summary[tag] = (functionName && statistics[functionName](data)) || '';
|
62
|
+
}
|
63
|
+
}
|
64
|
+
catch (err) {
|
65
|
+
summary[tag] = null;
|
66
|
+
console.error(err);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
else {
|
70
|
+
summary[tag] = null;
|
71
|
+
}
|
72
|
+
return summary;
|
73
|
+
}, {});
|
74
|
+
};
|
75
|
+
const fillSummaryResult = (dataSummary, dataItems, base) => {
|
76
|
+
const summary = calculateSummary(dataItems, base);
|
77
|
+
dataSummary.summary = summary;
|
78
|
+
dataItems.slice(0, 4).forEach((dataItem, idx) => {
|
79
|
+
const value = Number(summary[dataItem.tag]);
|
80
|
+
dataSummary[`data0${idx + 1}`] = isNaN(value) ? null : value;
|
81
|
+
});
|
82
|
+
};
|
83
|
+
async function getLatestTimesForPeriod(periodType, context) {
|
84
|
+
const { domain } = context.state;
|
85
|
+
const now = (0, moment_timezone_1.default)();
|
86
|
+
if (periodType == data_set_1.DataSetSummaryPeriodType.Hour) {
|
87
|
+
const begin = now.clone().subtract(1, 'hour').startOf('hour');
|
88
|
+
const end = now.clone().startOf('hour');
|
89
|
+
const date = begin.clone().tz(domain.timezone);
|
90
|
+
return {
|
91
|
+
date: date.format('YYYY-MM-DD'),
|
92
|
+
period: date.format('HH'),
|
93
|
+
range: [begin.toDate(), end.toDate()]
|
94
|
+
};
|
95
|
+
}
|
96
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.WorkShift) {
|
97
|
+
const { workDate, workShift, shiftRange } = await (0, work_shift_1.getLatestWorkDateAndShift)(domain, new Date());
|
98
|
+
return { date: workDate, period: workShift, range: shiftRange };
|
99
|
+
}
|
100
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.WorkDate) {
|
101
|
+
const { workDate, dateRange } = await (0, work_shift_1.getLatestWorkDateAndShift)(domain, new Date());
|
102
|
+
return { date: workDate, range: dateRange };
|
103
|
+
}
|
104
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.Day) {
|
105
|
+
const begin = now.clone().subtract(1, 'day').startOf('day');
|
106
|
+
const end = now.clone().startOf('day');
|
107
|
+
const date = begin.clone().tz(domain.timezone);
|
108
|
+
return {
|
109
|
+
date: date.format('YYYY-MM-DD'),
|
110
|
+
range: [begin.toDate(), end.toDate()]
|
111
|
+
};
|
112
|
+
}
|
113
|
+
}
|
114
|
+
async function getTimesForPeriod(periodType, date, period, context) {
|
115
|
+
const { domain } = context.state;
|
116
|
+
if (periodType == data_set_1.DataSetSummaryPeriodType.Hour) {
|
117
|
+
const theDate = moment_timezone_1.default.tz(`${date} ${period}:00:00`, 'YYYY-MM-DD HH:mm:ss', domain.timezone);
|
118
|
+
const begin = theDate.clone().startOf('hour').toDate();
|
119
|
+
const end = theDate.clone().add(+1, 'hour').startOf('hour').toDate();
|
120
|
+
return {
|
121
|
+
date,
|
122
|
+
period,
|
123
|
+
range: [begin, end]
|
124
|
+
};
|
125
|
+
}
|
126
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.WorkShift) {
|
127
|
+
const range = await (0, work_shift_1.getDateRangeForWorkShift)(domain, date, period);
|
128
|
+
return { date, period, range };
|
129
|
+
}
|
130
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.WorkDate) {
|
131
|
+
const range = await (0, work_shift_1.getDateRangeForWorkDate)(domain, date);
|
132
|
+
return { date, range };
|
133
|
+
}
|
134
|
+
else if (periodType == data_set_1.DataSetSummaryPeriodType.Day) {
|
135
|
+
const theDate = moment_timezone_1.default.tz(`${date} 00:00:00`, 'YYYY-MM-DD HH:mm:ss', domain.timezone);
|
136
|
+
const begin = theDate.clone().startOf('day').toDate();
|
137
|
+
const end = theDate.clone().add(1, 'day').startOf('day').toDate();
|
138
|
+
return {
|
139
|
+
date: (0, moment_timezone_1.default)(begin).tz(domain.timezone).format('YYYY-MM-DD'),
|
140
|
+
range: [begin, end]
|
141
|
+
};
|
142
|
+
}
|
143
|
+
}
|
144
|
+
async function getDataFinalizeCrontabSchedule(dataSet, context) {
|
145
|
+
const { domain, user, tx } = context.state;
|
146
|
+
try {
|
147
|
+
const { summaryPeriod } = dataSet;
|
148
|
+
if (summaryPeriod == data_set_1.DataSetSummaryPeriodType.Hour) {
|
149
|
+
return '0 5 * * * *';
|
150
|
+
}
|
151
|
+
else if (summaryPeriod == data_set_1.DataSetSummaryPeriodType.WorkShift) {
|
152
|
+
return await (0, work_shift_1.getSummaryScheduleForWorkShift)(domain);
|
153
|
+
}
|
154
|
+
else if (summaryPeriod == data_set_1.DataSetSummaryPeriodType.WorkDate) {
|
155
|
+
return await (0, work_shift_1.getSummaryScheduleForWorkDate)(domain);
|
156
|
+
}
|
157
|
+
else if (summaryPeriod == data_set_1.DataSetSummaryPeriodType.Day) {
|
158
|
+
return '0 10 0 * * *';
|
159
|
+
}
|
160
|
+
}
|
161
|
+
catch (err) {
|
162
|
+
console.error(err);
|
163
|
+
}
|
164
|
+
}
|
165
|
+
exports.getDataFinalizeCrontabSchedule = getDataFinalizeCrontabSchedule;
|
166
|
+
async function finalizeLatestDataCollection(dataSetId, context) {
|
167
|
+
var _a;
|
168
|
+
const { domain, user, tx } = context.state;
|
169
|
+
try {
|
170
|
+
const dataSet = await tx.getRepository(data_set_1.DataSet).findOne({
|
171
|
+
where: { domain: { id: (0, typeorm_1.In)([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId },
|
172
|
+
relations: ['dataKeySet']
|
173
|
+
});
|
174
|
+
const dataKeyItems = ((_a = dataSet.dataKeySet) === null || _a === void 0 ? void 0 : _a.dataKeyItems) || [];
|
175
|
+
const dataItems = dataSet.dataItems.filter(item => item.stat);
|
176
|
+
const initialSummary = dataItems.reduce((sum, item) => {
|
177
|
+
sum[item.tag] = [];
|
178
|
+
return sum;
|
179
|
+
}, {});
|
180
|
+
const { date, period, range } = await getLatestTimesForPeriod(dataSet.summaryPeriod, context);
|
181
|
+
const limit = 100;
|
182
|
+
var page = 1;
|
183
|
+
var summaries = [];
|
184
|
+
var summary;
|
185
|
+
do {
|
186
|
+
const samples = await (0, shell_1.getQueryBuilderFromListParams)({
|
187
|
+
repository: tx.getRepository(data_sample_1.DataSample),
|
188
|
+
domain,
|
189
|
+
params: {
|
190
|
+
filters: [{ name: 'dataSetId', operator: 'eq', value: dataSetId }],
|
191
|
+
pagination: { page, limit },
|
192
|
+
sortings: [...buildKeySortingList(dataKeyItems), { name: 'collectedAt', desc: true }]
|
193
|
+
},
|
194
|
+
alias: 'datasample'
|
195
|
+
})
|
196
|
+
// The 'Between' operator includes the 'to' time in the filtering, making it unsuitable for the desired use case.
|
197
|
+
// .andWhere({ collectedAt: Between.apply(null, range) })
|
198
|
+
.andWhere('datasample.collectedAt >= :from', { from: range[0] })
|
199
|
+
.andWhere('datasample.collectedAt < :to', { to: range[1] })
|
200
|
+
.getMany();
|
201
|
+
for (const sample of samples) {
|
202
|
+
if (!summary || !compareKeys(dataKeyItems, summary, sample)) {
|
203
|
+
if (summary) {
|
204
|
+
fillSummaryResult(summary, dataItems, summary.summary);
|
205
|
+
summaries.push(summary);
|
206
|
+
}
|
207
|
+
summary = Object.assign(Object.assign({ domain, name: dataSet.name, description: dataSet.description, date,
|
208
|
+
period,
|
209
|
+
dataSet }, buildKeysFromSample(dataKeyItems, sample)), { count: 0, countOoc: 0, countOos: 0, summary: deepClone(initialSummary), updater: user, creator: user });
|
210
|
+
}
|
211
|
+
summary.count++;
|
212
|
+
sample.ooc && summary.countOoc++;
|
213
|
+
sample.oos && summary.countOos++;
|
214
|
+
dataItems.forEach(item => {
|
215
|
+
summary.summary[item.tag].push(sample.data[item.tag]);
|
216
|
+
});
|
217
|
+
}
|
218
|
+
if (samples.length < limit) {
|
219
|
+
if (summary) {
|
220
|
+
fillSummaryResult(summary, dataItems, summary.summary);
|
221
|
+
summaries.push(summary);
|
222
|
+
}
|
223
|
+
break;
|
224
|
+
}
|
225
|
+
page++;
|
226
|
+
} while (true);
|
227
|
+
tx.getRepository(data_summary_1.DataSummary).upsert(summaries, ['domain', 'dataSet', 'key01', 'key02', 'key03', 'key04', 'key05', 'date', 'period']);
|
228
|
+
return true;
|
229
|
+
}
|
230
|
+
catch (e) {
|
231
|
+
env_1.logger.error(e);
|
232
|
+
}
|
233
|
+
return false;
|
234
|
+
}
|
235
|
+
exports.finalizeLatestDataCollection = finalizeLatestDataCollection;
|
236
|
+
async function finalizeDataCollection(dataSetId, date, period, context) {
|
237
|
+
var _a;
|
238
|
+
const { domain, user, tx } = context.state;
|
239
|
+
try {
|
240
|
+
const dataSet = dataSetId &&
|
241
|
+
(await tx.getRepository(data_set_1.DataSet).findOne({
|
242
|
+
where: { domain: (0, typeorm_1.In)([domain.id, domain.parentId].filter(Boolean)), id: dataSetId },
|
243
|
+
relations: ['dataKeySet']
|
244
|
+
}));
|
245
|
+
const dataKeyItems = ((_a = dataSet.dataKeySet) === null || _a === void 0 ? void 0 : _a.dataKeyItems) || [];
|
246
|
+
const dataItems = dataSet.dataItems.filter(item => item.stat);
|
247
|
+
const initialSummary = dataItems.reduce((sum, item) => {
|
248
|
+
sum[item.tag] = [];
|
249
|
+
return sum;
|
250
|
+
}, {});
|
251
|
+
const times = await getTimesForPeriod(dataSet.summaryPeriod, date, period, context);
|
252
|
+
const range = times.range;
|
253
|
+
period = times.period;
|
254
|
+
const limit = 100;
|
255
|
+
var page = 1;
|
256
|
+
var summaries = [];
|
257
|
+
var summary;
|
258
|
+
do {
|
259
|
+
const samples = await (0, shell_1.getQueryBuilderFromListParams)({
|
260
|
+
repository: tx.getRepository(data_sample_1.DataSample),
|
261
|
+
params: {
|
262
|
+
filters: [{ name: 'dataSetId', operator: 'eq', value: dataSetId }],
|
263
|
+
pagination: { page, limit },
|
264
|
+
sortings: [...buildKeySortingList(dataKeyItems), { name: 'collectedAt', desc: true }]
|
265
|
+
},
|
266
|
+
domain,
|
267
|
+
alias: 'datasample'
|
268
|
+
})
|
269
|
+
// The 'Between' operator includes the 'to' time in the filtering, making it unsuitable for the desired use case.
|
270
|
+
// .andWhere({ collectedAt: Between.apply(null, range) })
|
271
|
+
.andWhere('datasample.collectedAt >= :from', { from: range[0] })
|
272
|
+
.andWhere('datasample.collectedAt < :to', { to: range[1] })
|
273
|
+
.getMany();
|
274
|
+
for (const sample of samples) {
|
275
|
+
if (!summary || !compareKeys(dataKeyItems, summary, sample)) {
|
276
|
+
if (summary) {
|
277
|
+
fillSummaryResult(summary, dataItems, summary.summary);
|
278
|
+
summaries.push(summary);
|
279
|
+
}
|
280
|
+
summary = Object.assign(Object.assign({ domain, name: dataSet.name, description: dataSet.description, date,
|
281
|
+
period,
|
282
|
+
dataSet }, buildKeysFromSample(dataKeyItems, sample)), { count: 0, countOoc: 0, countOos: 0, summary: deepClone(initialSummary), updater: user, creator: user });
|
283
|
+
}
|
284
|
+
summary.count++;
|
285
|
+
sample.ooc && summary.countOoc++;
|
286
|
+
sample.oos && summary.countOos++;
|
287
|
+
dataItems.forEach(item => {
|
288
|
+
summary.summary[item.tag].push(sample.data[item.tag]);
|
289
|
+
});
|
290
|
+
}
|
291
|
+
if (samples.length < limit) {
|
292
|
+
if (summary) {
|
293
|
+
fillSummaryResult(summary, dataItems, summary.summary);
|
294
|
+
summaries.push(summary);
|
295
|
+
}
|
296
|
+
break;
|
297
|
+
}
|
298
|
+
page++;
|
299
|
+
} while (true);
|
300
|
+
tx.getRepository(data_summary_1.DataSummary).upsert(summaries, ['domain', 'dataSet', 'key01', 'key02', 'key03', 'key04', 'key05', 'date', 'period']);
|
301
|
+
return true;
|
302
|
+
}
|
303
|
+
catch (e) {
|
304
|
+
env_1.logger.error(e);
|
305
|
+
}
|
306
|
+
return false;
|
307
|
+
}
|
308
|
+
exports.finalizeDataCollection = finalizeDataCollection;
|
309
|
+
//# sourceMappingURL=finalize-data-collection.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"finalize-data-collection.js","sourceRoot":"","sources":["../../server/controllers/finalize-data-collection.ts"],"names":[],"mappings":"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","sourcesContent":["const statistics = require('simple-statistics')\nconst deepClone = require('lodash/cloneDeep')\n\nimport moment from 'moment-timezone'\nimport { In } from 'typeorm'\n\nimport { Sorting, getQueryBuilderFromListParams } from '@things-factory/shell'\nimport { logger } from '@things-factory/env'\nimport {\n getDateRangeForWorkDate,\n getDateRangeForWorkShift,\n getLatestWorkDateAndShift,\n getSummaryScheduleForWorkDate,\n getSummaryScheduleForWorkShift\n} from '@things-factory/work-shift'\n\nimport { DataSample } from '../service/data-sample/data-sample'\nimport { DataSet, DataSetSummaryPeriodType } from '../service/data-set/data-set'\n\nimport { DataSummary } from '../service/data-summary/data-summary'\nimport { DataKeyItem } from '../service/data-key-set/data-key-item-type'\n\nimport { DataItem } from 'service'\n\nconst STAT_FUNCTION_MAP = {\n sum: 'sum',\n mean: 'mean',\n stddev: 'standardDeviation',\n variance: 'variance',\n min: 'min',\n max: 'max',\n range: 'range',\n median: 'median',\n mode: 'mode'\n}\n\nconst compareKeys = (dataKeyItems: DataKeyItem[], summary: Partial<DataSummary>, sample: DataSample): boolean => {\n return dataKeyItems.every((item, index) => {\n const prop = `key0${index + 1}`\n return sample[prop] === summary[prop]\n })\n}\n\nconst buildKeysFromSample = (dataKeyItems: DataKeyItem[], sample: DataSample): Partial<DataSummary> => {\n return dataKeyItems.reduce((sum, item, index) => {\n const prop = `key0${index + 1}`\n sum[prop] = sample[prop]\n\n return sum\n }, {} as Partial<DataSummary>)\n}\n\nconst buildKeySortingList = (dataKeyItems: DataKeyItem[]): Sorting[] => {\n return dataKeyItems.reduce((sum, item, index) => {\n const name = `key0${index + 1}`\n sum.push({ name, desc: true })\n return sum\n }, [])\n}\n\nconst calculateSummary = (dataItems: DataItem[], base: { [tag: string]: any[] }) => {\n return dataItems.reduce((summary, item) => {\n const tag = item.tag\n\n const data = base[tag]\n .flat(Infinity)\n .map(Number)\n .filter(item => !isNaN(item))\n\n if (data.length > 0) {\n try {\n switch (item.stat) {\n case 'range':\n summary[tag] = statistics.max(data) - statistics.min(data)\n break\n\n default:\n const functionName = STAT_FUNCTION_MAP[item.stat]\n summary[tag] = (functionName && statistics[functionName](data)) || ''\n }\n } catch (err) {\n summary[tag] = null\n console.error(err)\n }\n } else {\n summary[tag] = null\n }\n\n return summary\n }, {})\n}\n\nconst fillSummaryResult = (dataSummary: Partial<DataSummary>, dataItems: DataItem[], base: { [tag: string]: any[] }): void => {\n const summary = calculateSummary(dataItems, base)\n\n dataSummary.summary = summary\n dataItems.slice(0, 4).forEach((dataItem, idx) => {\n const value = Number(summary[dataItem.tag])\n dataSummary[`data0${idx + 1}`] = isNaN(value) ? null : value\n })\n}\n\nasync function getLatestTimesForPeriod(periodType: DataSetSummaryPeriodType, context: ResolverContext): Promise<{ date?: string; period?: string; range: Date[] }> {\n const { domain } = context.state\n const now = moment()\n\n if (periodType == DataSetSummaryPeriodType.Hour) {\n const begin = now.clone().subtract(1, 'hour').startOf('hour')\n const end = now.clone().startOf('hour')\n const date = begin.clone().tz(domain.timezone)\n\n return {\n date: date.format('YYYY-MM-DD'),\n period: date.format('HH'),\n range: [begin.toDate(), end.toDate()]\n }\n } else if (periodType == DataSetSummaryPeriodType.WorkShift) {\n const { workDate, workShift, shiftRange } = await getLatestWorkDateAndShift(domain, new Date())\n\n return { date: workDate, period: workShift, range: shiftRange }\n } else if (periodType == DataSetSummaryPeriodType.WorkDate) {\n const { workDate, dateRange } = await getLatestWorkDateAndShift(domain, new Date())\n\n return { date: workDate, range: dateRange }\n } else if (periodType == DataSetSummaryPeriodType.Day) {\n const begin = now.clone().subtract(1, 'day').startOf('day')\n const end = now.clone().startOf('day')\n const date = begin.clone().tz(domain.timezone)\n\n return {\n date: date.format('YYYY-MM-DD'),\n range: [begin.toDate(), end.toDate()]\n }\n }\n}\n\nasync function getTimesForPeriod(\n periodType: DataSetSummaryPeriodType,\n date: string,\n period: string,\n context: ResolverContext\n): Promise<{ date?: string; period?: string; range: Date[] }> {\n const { domain } = context.state\n\n if (periodType == DataSetSummaryPeriodType.Hour) {\n const theDate = moment.tz(`${date} ${period}:00:00`, 'YYYY-MM-DD HH:mm:ss', domain.timezone)\n\n const begin = theDate.clone().startOf('hour').toDate()\n const end = theDate.clone().add(+1, 'hour').startOf('hour').toDate()\n\n return {\n date,\n period,\n range: [begin, end]\n }\n } else if (periodType == DataSetSummaryPeriodType.WorkShift) {\n const range = await getDateRangeForWorkShift(domain, date, period)\n\n return { date, period, range }\n } else if (periodType == DataSetSummaryPeriodType.WorkDate) {\n const range = await getDateRangeForWorkDate(domain, date)\n\n return { date, range }\n } else if (periodType == DataSetSummaryPeriodType.Day) {\n const theDate = moment.tz(`${date} 00:00:00`, 'YYYY-MM-DD HH:mm:ss', domain.timezone)\n\n const begin = theDate.clone().startOf('day').toDate()\n const end = theDate.clone().add(1, 'day').startOf('day').toDate()\n\n return {\n date: moment(begin).tz(domain.timezone).format('YYYY-MM-DD'),\n range: [begin, end]\n }\n }\n}\n\nexport async function getDataFinalizeCrontabSchedule(dataSet: DataSet, context: ResolverContext): Promise<string> {\n const { domain, user, tx } = context.state\n\n try {\n const { summaryPeriod } = dataSet\n\n if (summaryPeriod == DataSetSummaryPeriodType.Hour) {\n return '0 5 * * * *'\n } else if (summaryPeriod == DataSetSummaryPeriodType.WorkShift) {\n return await getSummaryScheduleForWorkShift(domain)\n } else if (summaryPeriod == DataSetSummaryPeriodType.WorkDate) {\n return await getSummaryScheduleForWorkDate(domain)\n } else if (summaryPeriod == DataSetSummaryPeriodType.Day) {\n return '0 10 0 * * *'\n }\n } catch (err) {\n console.error(err)\n }\n}\n\nexport async function finalizeLatestDataCollection(dataSetId: string, context: ResolverContext): Promise<boolean> {\n const { domain, user, tx } = context.state\n\n try {\n const dataSet = await tx.getRepository(DataSet).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: dataSetId },\n relations: ['dataKeySet']\n })\n\n const dataKeyItems = dataSet.dataKeySet?.dataKeyItems || []\n const dataItems = dataSet.dataItems.filter(item => item.stat)\n const initialSummary = dataItems.reduce((sum, item) => {\n sum[item.tag] = []\n return sum\n }, {})\n\n const { date, period, range } = await getLatestTimesForPeriod(dataSet.summaryPeriod, context)\n const limit = 100\n var page = 1\n\n var summaries: Partial<DataSummary>[] = []\n var summary: Partial<DataSummary>\n\n do {\n const samples = await getQueryBuilderFromListParams({\n repository: tx.getRepository(DataSample),\n domain,\n params: {\n filters: [{ name: 'dataSetId', operator: 'eq', value: dataSetId }],\n pagination: { page, limit },\n sortings: [...buildKeySortingList(dataKeyItems), { name: 'collectedAt', desc: true }]\n },\n alias: 'datasample'\n })\n // The 'Between' operator includes the 'to' time in the filtering, making it unsuitable for the desired use case.\n // .andWhere({ collectedAt: Between.apply(null, range) })\n .andWhere('datasample.collectedAt >= :from', { from: range[0] })\n .andWhere('datasample.collectedAt < :to', { to: range[1] })\n .getMany()\n\n for (const sample of samples) {\n if (!summary || !compareKeys(dataKeyItems, summary, sample)) {\n if (summary) {\n fillSummaryResult(summary, dataItems, summary.summary)\n summaries.push(summary)\n }\n\n summary = {\n domain,\n name: dataSet.name,\n description: dataSet.description,\n date,\n period,\n dataSet,\n ...buildKeysFromSample(dataKeyItems, sample),\n count: 0,\n countOoc: 0,\n countOos: 0,\n summary: deepClone(initialSummary),\n updater: user,\n creator: user\n }\n }\n\n summary.count++\n sample.ooc && summary.countOoc++\n sample.oos && summary.countOos++\n\n dataItems.forEach(item => {\n summary.summary[item.tag].push(sample.data[item.tag])\n })\n }\n\n if (samples.length < limit) {\n if (summary) {\n fillSummaryResult(summary, dataItems, summary.summary)\n summaries.push(summary)\n }\n break\n }\n\n page++\n } while (true)\n\n tx.getRepository(DataSummary).upsert(summaries, ['domain', 'dataSet', 'key01', 'key02', 'key03', 'key04', 'key05', 'date', 'period'])\n\n return true\n } catch (e) {\n logger.error(e)\n }\n\n return false\n}\n\nexport async function finalizeDataCollection(dataSetId: string, date: string, period: string, context: ResolverContext): Promise<boolean> {\n const { domain, user, tx } = context.state\n\n try {\n const dataSet =\n dataSetId &&\n (await tx.getRepository(DataSet).findOne({\n where: { domain: In([domain.id, domain.parentId].filter(Boolean)), id: dataSetId },\n relations: ['dataKeySet']\n }))\n\n const dataKeyItems = dataSet.dataKeySet?.dataKeyItems || []\n const dataItems = dataSet.dataItems.filter(item => item.stat)\n const initialSummary = dataItems.reduce((sum, item) => {\n sum[item.tag] = []\n return sum\n }, {})\n\n const times = await getTimesForPeriod(dataSet.summaryPeriod, date, period, context)\n const range = times.range\n period = times.period\n\n const limit = 100\n var page = 1\n\n var summaries: Partial<DataSummary>[] = []\n var summary: Partial<DataSummary>\n\n do {\n const samples = await getQueryBuilderFromListParams({\n repository: tx.getRepository(DataSample),\n params: {\n filters: [{ name: 'dataSetId', operator: 'eq', value: dataSetId }],\n pagination: { page, limit },\n sortings: [...buildKeySortingList(dataKeyItems), { name: 'collectedAt', desc: true }]\n },\n domain,\n alias: 'datasample'\n })\n // The 'Between' operator includes the 'to' time in the filtering, making it unsuitable for the desired use case.\n // .andWhere({ collectedAt: Between.apply(null, range) })\n .andWhere('datasample.collectedAt >= :from', { from: range[0] })\n .andWhere('datasample.collectedAt < :to', { to: range[1] })\n .getMany()\n\n for (const sample of samples) {\n if (!summary || !compareKeys(dataKeyItems, summary, sample)) {\n if (summary) {\n fillSummaryResult(summary, dataItems, summary.summary)\n summaries.push(summary)\n }\n\n summary = {\n domain,\n name: dataSet.name,\n description: dataSet.description,\n date,\n period,\n dataSet,\n ...buildKeysFromSample(dataKeyItems, sample),\n count: 0,\n countOoc: 0,\n countOos: 0,\n summary: deepClone(initialSummary),\n updater: user,\n creator: user\n }\n }\n\n summary.count++\n sample.ooc && summary.countOoc++\n sample.oos && summary.countOos++\n\n dataItems.forEach(item => {\n summary.summary[item.tag].push(sample.data[item.tag])\n })\n }\n\n if (samples.length < limit) {\n if (summary) {\n fillSummaryResult(summary, dataItems, summary.summary)\n summaries.push(summary)\n }\n break\n }\n\n page++\n } while (true)\n\n tx.getRepository(DataSummary).upsert(summaries, ['domain', 'dataSet', 'key01', 'key02', 'key03', 'key04', 'key05', 'date', 'period'])\n\n return true\n } catch (e) {\n logger.error(e)\n }\n\n return false\n}\n"]}
|
@@ -29,8 +29,7 @@ async function queryDataSummaryByPeriod(period, dataSetName, dataKeys, params, c
|
|
29
29
|
}
|
30
30
|
// limitations
|
31
31
|
const summaryPeriodType = dataSet.summaryPeriod;
|
32
|
-
if ((summaryPeriodType == data_set_1.DataSetSummaryPeriodType.Day || summaryPeriodType == data_set_1.DataSetSummaryPeriodType.WorkDate) &&
|
33
|
-
period == 'today') {
|
32
|
+
if ((summaryPeriodType == data_set_1.DataSetSummaryPeriodType.Day || summaryPeriodType == data_set_1.DataSetSummaryPeriodType.WorkDate) && period == 'today') {
|
34
33
|
throw new Error(t('error.summary not supported', { dataSetName, period: t(`label.period-${period}`) }));
|
35
34
|
}
|
36
35
|
// dataKeys 가 설정되지 않았다면, dataSet의 dataKeySet을 그대로 적용한다는 의미임.
|
@@ -46,7 +45,7 @@ async function queryDataSummaryByPeriod(period, dataSetName, dataKeys, params, c
|
|
46
45
|
.filter(Boolean)
|
47
46
|
: dataSet.dataKeySet.dataKeyItems;
|
48
47
|
const searchables = dataKeyItems.map((item, index) => `key0${index + 1}`);
|
49
|
-
const dataItems = dataSet.dataItems.filter(item => item.
|
48
|
+
const dataItems = dataSet.dataItems.filter(item => item.agg);
|
50
49
|
const { from, to } = await (0, shell_1.getTimesForPeriod)(period, context);
|
51
50
|
const selectPeriod = queryBuilder => {
|
52
51
|
if (period == 'today') {
|
@@ -68,7 +67,7 @@ async function queryDataSummaryByPeriod(period, dataSetName, dataKeys, params, c
|
|
68
67
|
const selectData = dataItems.map((item, index) => {
|
69
68
|
const aliasName = `data0${index + 1}`;
|
70
69
|
const columnName = `summary.${aliasName}`;
|
71
|
-
switch (item.
|
70
|
+
switch (item.agg) {
|
72
71
|
case STAT_FUNCTION_MAP.sum:
|
73
72
|
return `SUM(${columnName}) as ${aliasName}`;
|
74
73
|
case STAT_FUNCTION_MAP.mean:
|
@@ -94,11 +93,7 @@ async function queryDataSummaryByPeriod(period, dataSetName, dataKeys, params, c
|
|
94
93
|
return `AVG(${columnName}) as ${aliasName}`;
|
95
94
|
}
|
96
95
|
});
|
97
|
-
const groupByPeriod = period == 'today'
|
98
|
-
? 'summary.date, summary.period'
|
99
|
-
: ['this year', '12 months'].includes(period)
|
100
|
-
? 'SUBSTRING(summary.date, 1, 7)'
|
101
|
-
: 'summary.date';
|
96
|
+
const groupByPeriod = period == 'today' ? 'summary.date, summary.period' : ['this year', '12 months'].includes(period) ? 'SUBSTRING(summary.date, 1, 7)' : 'summary.date';
|
102
97
|
const groupByKeys = dataKeyItems
|
103
98
|
.map((item, index) => {
|
104
99
|
return `summary.key0${index + 1}`;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"query-data-summary-by-period.js","sourceRoot":"","sources":["../../server/controllers/query-data-summary-by-period.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport {\n getQueryBuilderFromListParams,\n getRepository,\n getTimesForPeriod,\n ListParam,\n Sorting\n} from '@things-factory/shell'\n\nimport { DataSet, DataSetSummaryPeriodType } from '../service/data-set/data-set'\nimport { DataSummary } from '../service/data-summary/data-summary'\n\nconst STAT_FUNCTION_MAP = {\n sum: 'sum',\n mean: 'mean',\n stddev: 'standardDeviation',\n variance: 'variance',\n min: 'min',\n max: 'max',\n range: 'range',\n median: 'median',\n mode: 'mode'\n}\n\nexport async function queryDataSummaryByPeriod(\n period: 'today' | 'this month' | '30 days' | 'this year' | '12 months',\n dataSetName: string,\n dataKeys: string[] | null,\n params: ListParam,\n context: ResolverContext\n): Promise<DataSummary[]> {\n const { domain, user, tx } = context.state\n const { t } = context\n\n const dataSet = await getRepository(DataSet).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, name: dataSetName },\n relations: ['dataKeySet']\n })\n\n if (!dataSet) {\n throw new Error(t('error.dataset not found', { dataSetName }))\n }\n\n // limitations\n const summaryPeriodType = dataSet.summaryPeriod\n if (\n (summaryPeriodType == DataSetSummaryPeriodType.Day || summaryPeriodType == DataSetSummaryPeriodType.WorkDate) &&\n period == 'today'\n ) {\n throw new Error(t('error.summary not supported', { dataSetName, period: t(`label.period-${period}`) }))\n }\n\n // dataKeys 가 설정되지 않았다면, dataSet의 dataKeySet을 그대로 적용한다는 의미임.\n // dataKeys == [] 라면, dataKeySet을 적용하지 않는다는 의미임.\n // dataKeys에는 dataKeySet의 dataKey 값을 따라야 한다.\n const dataKeyItems = !dataSet.dataKeySet?.dataKeyItems\n ? []\n : dataKeys\n ? dataKeys\n .map(dataKey => {\n return dataSet.dataKeySet.dataKeyItems.find(item => item.dataKey == dataKey)\n })\n .filter(Boolean)\n : dataSet.dataKeySet.dataKeyItems\n\n const searchables = dataKeyItems.map((item, index) => `key0${index + 1}`)\n const dataItems = dataSet.dataItems.filter(item => item.stat)\n\n const { from, to } = await getTimesForPeriod(period, context)\n\n const selectPeriod = queryBuilder => {\n if (period == 'today') {\n queryBuilder.addSelect('summary.date', 'date').addSelect('summary.period', 'period')\n } else if (['this year', '12 months'].includes(period)) {\n queryBuilder.addSelect('SUBSTRING(summary.date, 1, 7) AS month')\n } else {\n queryBuilder.addSelect('summary.date', 'date')\n }\n\n return queryBuilder\n }\n const selectKeys = dataKeyItems.map((item, index) => {\n const aliasName = `key0${index + 1}`\n const columnName = `summary.${aliasName}`\n\n return `${columnName} as ${aliasName}`\n }) as string[]\n const selectData = dataItems.map((item, index) => {\n const aliasName = `data0${index + 1}`\n const columnName = `summary.${aliasName}`\n\n switch (item.stat) {\n case STAT_FUNCTION_MAP.sum:\n return `SUM(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.mean:\n // 일차 mean 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `AVG(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.stddev:\n // 일차 stddev 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `STDDEV(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.variance:\n // 일차 variance 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `VARIANCE(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.min:\n return `MIN(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.max:\n return `MAX(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.range:\n // 일차 range 값들을 다시 계산하므로, 무의미할 수 있다.\n return `MAX(${columnName}) - MIN(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.mode:\n // not guaranteed\n return `MODE() WITHIN GROUP (ORDER BY ${columnName})`\n default:\n return `AVG(${columnName}) as ${aliasName}`\n }\n })\n\n const groupByPeriod =\n period == 'today'\n ? 'summary.date, summary.period'\n : ['this year', '12 months'].includes(period)\n ? 'SUBSTRING(summary.date, 1, 7)'\n : 'summary.date'\n const groupByKeys = dataKeyItems\n .map((item, index) => {\n return `summary.key0${index + 1}`\n })\n .join(', ')\n\n const desc = false\n var orderByPeriod: Sorting[] =\n period == 'today'\n ? [\n {\n name: 'date',\n desc\n },\n {\n name: 'period',\n desc\n }\n ]\n : ['this year', '12 months'].includes(period)\n ? [{ name: 'month', desc }]\n : [{ name: 'date', desc }]\n\n if (params?.sortings && params.sortings.length > 0) {\n orderByPeriod = params.sortings\n }\n\n var queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(DataSummary),\n params: {\n ...params,\n sortings: []\n },\n domain,\n alias: 'summary',\n searchables: searchables\n })\n .select('summary.dataSet')\n .addSelect(selectData)\n .addSelect('SUM(summary.count)', 'count')\n .addSelect('SUM(summary.countOoc)', 'countOoc')\n .addSelect('SUM(summary.countOos)', 'countOos')\n\n queryBuilder = selectPeriod(queryBuilder)\n .innerJoin('summary.dataSet', 'ds', 'ds.id = :dataSetName', {\n dataSetName: dataSet.id\n })\n .andWhere('summary.domain = :domain', { domain: domain.id })\n .andWhere('summary.date >= :from', { from })\n .andWhere('summary.date < :to', { to })\n .addGroupBy('summary.dataSet')\n .addGroupBy(groupByPeriod)\n\n if (dataKeyItems.length > 0) {\n queryBuilder.addSelect(selectKeys).addGroupBy(groupByKeys)\n }\n\n orderByPeriod.map(orderBy => {\n const { name: sort, desc } = orderBy\n queryBuilder.addOrderBy(sort, desc ? 'DESC' : 'ASC')\n })\n\n const items = await queryBuilder.getRawMany()\n\n return items\n}\n"]}
|
1
|
+
{"version":3,"file":"query-data-summary-by-period.js","sourceRoot":"","sources":["../../server/controllers/query-data-summary-by-period.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { getQueryBuilderFromListParams, getRepository, getTimesForPeriod, ListParam, Sorting } from '@things-factory/shell'\n\nimport { DataSet, DataSetSummaryPeriodType } from '../service/data-set/data-set'\nimport { DataSummary } from '../service/data-summary/data-summary'\n\nconst STAT_FUNCTION_MAP = {\n sum: 'sum',\n mean: 'mean',\n stddev: 'standardDeviation',\n variance: 'variance',\n min: 'min',\n max: 'max',\n range: 'range',\n median: 'median',\n mode: 'mode'\n}\n\nexport async function queryDataSummaryByPeriod(\n period: 'today' | 'this month' | '30 days' | 'this year' | '12 months',\n dataSetName: string,\n dataKeys: string[] | null,\n params: ListParam,\n context: ResolverContext\n): Promise<DataSummary[]> {\n const { domain, user, tx } = context.state\n const { t } = context\n\n const dataSet = await getRepository(DataSet).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, name: dataSetName },\n relations: ['dataKeySet']\n })\n\n if (!dataSet) {\n throw new Error(t('error.dataset not found', { dataSetName }))\n }\n\n // limitations\n const summaryPeriodType = dataSet.summaryPeriod\n if ((summaryPeriodType == DataSetSummaryPeriodType.Day || summaryPeriodType == DataSetSummaryPeriodType.WorkDate) && period == 'today') {\n throw new Error(t('error.summary not supported', { dataSetName, period: t(`label.period-${period}`) }))\n }\n\n // dataKeys 가 설정되지 않았다면, dataSet의 dataKeySet을 그대로 적용한다는 의미임.\n // dataKeys == [] 라면, dataKeySet을 적용하지 않는다는 의미임.\n // dataKeys에는 dataKeySet의 dataKey 값을 따라야 한다.\n const dataKeyItems = !dataSet.dataKeySet?.dataKeyItems\n ? []\n : dataKeys\n ? dataKeys\n .map(dataKey => {\n return dataSet.dataKeySet.dataKeyItems.find(item => item.dataKey == dataKey)\n })\n .filter(Boolean)\n : dataSet.dataKeySet.dataKeyItems\n\n const searchables = dataKeyItems.map((item, index) => `key0${index + 1}`)\n const dataItems = dataSet.dataItems.filter(item => item.agg)\n\n const { from, to } = await getTimesForPeriod(period, context)\n\n const selectPeriod = queryBuilder => {\n if (period == 'today') {\n queryBuilder.addSelect('summary.date', 'date').addSelect('summary.period', 'period')\n } else if (['this year', '12 months'].includes(period)) {\n queryBuilder.addSelect('SUBSTRING(summary.date, 1, 7) AS month')\n } else {\n queryBuilder.addSelect('summary.date', 'date')\n }\n\n return queryBuilder\n }\n const selectKeys = dataKeyItems.map((item, index) => {\n const aliasName = `key0${index + 1}`\n const columnName = `summary.${aliasName}`\n\n return `${columnName} as ${aliasName}`\n }) as string[]\n const selectData = dataItems.map((item, index) => {\n const aliasName = `data0${index + 1}`\n const columnName = `summary.${aliasName}`\n\n switch (item.agg) {\n case STAT_FUNCTION_MAP.sum:\n return `SUM(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.mean:\n // 일차 mean 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `AVG(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.stddev:\n // 일차 stddev 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `STDDEV(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.variance:\n // 일차 variance 된 값들을 다시 계산하므로, 무의미할 수 있다.\n return `VARIANCE(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.min:\n return `MIN(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.max:\n return `MAX(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.range:\n // 일차 range 값들을 다시 계산하므로, 무의미할 수 있다.\n return `MAX(${columnName}) - MIN(${columnName}) as ${aliasName}`\n case STAT_FUNCTION_MAP.mode:\n // not guaranteed\n return `MODE() WITHIN GROUP (ORDER BY ${columnName})`\n default:\n return `AVG(${columnName}) as ${aliasName}`\n }\n })\n\n const groupByPeriod =\n period == 'today' ? 'summary.date, summary.period' : ['this year', '12 months'].includes(period) ? 'SUBSTRING(summary.date, 1, 7)' : 'summary.date'\n const groupByKeys = dataKeyItems\n .map((item, index) => {\n return `summary.key0${index + 1}`\n })\n .join(', ')\n\n const desc = false\n var orderByPeriod: Sorting[] =\n period == 'today'\n ? [\n {\n name: 'date',\n desc\n },\n {\n name: 'period',\n desc\n }\n ]\n : ['this year', '12 months'].includes(period)\n ? [{ name: 'month', desc }]\n : [{ name: 'date', desc }]\n\n if (params?.sortings && params.sortings.length > 0) {\n orderByPeriod = params.sortings\n }\n\n var queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(DataSummary),\n params: {\n ...params,\n sortings: []\n },\n domain,\n alias: 'summary',\n searchables: searchables\n })\n .select('summary.dataSet')\n .addSelect(selectData)\n .addSelect('SUM(summary.count)', 'count')\n .addSelect('SUM(summary.countOoc)', 'countOoc')\n .addSelect('SUM(summary.countOos)', 'countOos')\n\n queryBuilder = selectPeriod(queryBuilder)\n .innerJoin('summary.dataSet', 'ds', 'ds.id = :dataSetName', {\n dataSetName: dataSet.id\n })\n .andWhere('summary.domain = :domain', { domain: domain.id })\n .andWhere('summary.date >= :from', { from })\n .andWhere('summary.date < :to', { to })\n .addGroupBy('summary.dataSet')\n .addGroupBy(groupByPeriod)\n\n if (dataKeyItems.length > 0) {\n queryBuilder.addSelect(selectKeys).addGroupBy(groupByKeys)\n }\n\n orderByPeriod.map(orderBy => {\n const { name: sort, desc } = orderBy\n queryBuilder.addOrderBy(sort, desc ? 'DESC' : 'ASC')\n })\n\n const items = await queryBuilder.getRawMany()\n\n return items\n}\n"]}
|
@@ -32,7 +32,7 @@ var DataItemStatType;
|
|
32
32
|
})(DataItemStatType = exports.DataItemStatType || (exports.DataItemStatType = {}));
|
33
33
|
(0, type_graphql_1.registerEnumType)(DataItemStatType, {
|
34
34
|
name: 'DataItemStatType',
|
35
|
-
description: 'stat type enumeration of a data-item'
|
35
|
+
description: 'stat/agg type enumeration of a data-item'
|
36
36
|
});
|
37
37
|
let DataItem = class DataItem {
|
38
38
|
};
|
@@ -77,10 +77,17 @@ tslib_1.__decorate([
|
|
77
77
|
tslib_1.__decorate([
|
78
78
|
(0, type_graphql_1.Field)({
|
79
79
|
nullable: true,
|
80
|
-
description: 'The grouping logic for data
|
80
|
+
description: 'The grouping logic for data finalize in the given field during periodic task deadlines.'
|
81
81
|
}),
|
82
82
|
tslib_1.__metadata("design:type", String)
|
83
83
|
], DataItem.prototype, "stat", void 0);
|
84
|
+
tslib_1.__decorate([
|
85
|
+
(0, type_graphql_1.Field)({
|
86
|
+
nullable: true,
|
87
|
+
description: 'Aggregation functions to be used in data summarizing logic for a given period.'
|
88
|
+
}),
|
89
|
+
tslib_1.__metadata("design:type", String)
|
90
|
+
], DataItem.prototype, "agg", void 0);
|
84
91
|
tslib_1.__decorate([
|
85
92
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The unit of measurement for the data item' }),
|
86
93
|
tslib_1.__metadata("design:type", String)
|
@@ -139,6 +146,13 @@ tslib_1.__decorate([
|
|
139
146
|
}),
|
140
147
|
tslib_1.__metadata("design:type", String)
|
141
148
|
], DataItemPatch.prototype, "stat", void 0);
|
149
|
+
tslib_1.__decorate([
|
150
|
+
(0, type_graphql_1.Field)({
|
151
|
+
nullable: true,
|
152
|
+
description: 'Aggregation functions to be used in data summarizing logic for a given period.'
|
153
|
+
}),
|
154
|
+
tslib_1.__metadata("design:type", String)
|
155
|
+
], DataItemPatch.prototype, "agg", void 0);
|
142
156
|
tslib_1.__decorate([
|
143
157
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The unit of measurement for the data item' }),
|
144
158
|
tslib_1.__metadata("design:type", String)
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"data-item-type.js","sourceRoot":"","sources":["../../../server/service/data-set/data-item-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAkF;AAElF,iDAAoD;AAEpD,IAAY,YAQX;AARD,WAAY,YAAY;IACtB,iCAAiB,CAAA;IACjB,6BAAa,CAAA;IACb,mCAAmB,CAAA;IACnB,iCAAiB,CAAA;IACjB,6BAAa,CAAA;IACb,qCAAqB,CAAA;IACrB,6BAAa,CAAA;AACf,CAAC,EARW,YAAY,GAAZ,oBAAY,KAAZ,oBAAY,QAQvB;AAED,IAAA,+BAAgB,EAAC,YAAY,EAAE;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EAAE,iCAAiC;CAC/C,CAAC,CAAA;AAEF,IAAY,gBAUX;AAVD,WAAY,gBAAgB;IAC1B,+BAAW,CAAA;IACX,iCAAa,CAAA;IACb,qCAAiB,CAAA;IACjB,yCAAqB,CAAA;IACrB,+BAAW,CAAA;IACX,+BAAW,CAAA;IACX,mCAAe,CAAA;IACf,qCAAiB,CAAA;IACjB,iCAAa,CAAA;AACf,CAAC,EAVW,gBAAgB,GAAhB,wBAAgB,KAAhB,wBAAgB,QAU3B;AAED,IAAA,+BAAgB,EAAC,gBAAgB,EAAE;IACjC,IAAI,EAAE,kBAAkB;IACxB,WAAW,EAAE,
|
1
|
+
{"version":3,"file":"data-item-type.js","sourceRoot":"","sources":["../../../server/service/data-set/data-item-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, InputType, Int, ObjectType, registerEnumType } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\nexport enum DataItemType {\n number = 'number',\n text = 'text',\n boolean = 'boolean',\n select = 'select',\n date = 'date',\n datetime = 'datetime',\n file = 'file'\n}\n\nregisterEnumType(DataItemType, {\n name: 'DataItemType',\n description: 'type enumeration of a data-item'\n})\n\nexport enum DataItemStatType {\n sum = 'sum',\n mean = 'mean',\n stddev = 'stddev',\n variance = 'variance',\n min = 'min',\n max = 'max',\n range = 'range',\n median = 'median',\n mode = 'mode'\n}\n\nregisterEnumType(DataItemStatType, {\n name: 'DataItemStatType',\n description: 'stat/agg type enumeration of a data-item'\n})\n\n@ObjectType({ description: 'Entity for DataItem' })\nexport class DataItem {\n @Field({ description: 'The name of the data item' })\n name: string\n\n @Field({ nullable: true, description: 'A description of the data item' })\n description?: string\n\n @Field({\n nullable: true,\n description: 'Specifies a key name to be used as a property in a JSON-like object, representing a subfield of a dataset record.'\n })\n tag?: string\n\n @Field({\n nullable: true,\n description: 'Specifies a grouping identifier for data items with related content, allowing them to be displayed as subgroups within the overall dataset.'\n })\n group?: string\n\n @Field({ nullable: true, description: 'Indicates if the data item is active' })\n active?: boolean\n\n @Field({ nullable: true, description: 'Indicates if the data item is hidden' })\n hidden?: boolean\n\n @Field({ nullable: true, description: 'The type of the data item' })\n type?: DataItemType\n\n @Field(type => ScalarObject, { nullable: true, description: 'Options associated with the data item type' })\n options?: { [option: string]: any }\n\n @Field({\n nullable: true,\n description: 'The grouping logic for data finalize in the given field during periodic task deadlines.'\n })\n stat?: DataItemStatType\n\n @Field({\n nullable: true,\n description: 'Aggregation functions to be used in data summarizing logic for a given period.'\n })\n agg?: DataItemStatType\n\n @Field({ nullable: true, description: 'The unit of measurement for the data item' })\n unit?: string\n\n @Field(type => Int, { nullable: true, description: 'The maximum number of data values allowed for this field' })\n quota?: number\n\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'Specifies the valid ranges and parameters for this data item.'\n })\n spec?: { [key: string]: any }\n}\n\n@InputType()\nexport class DataItemPatch {\n @Field({ nullable: true, description: 'The name of the data item' })\n name?: string\n\n @Field({ nullable: true, description: 'A description of the data item' })\n description?: string\n\n @Field({\n nullable: true,\n description: 'Specifies a key name to be used as a property in a JSON-like object, representing a subfield of a dataset record.'\n })\n tag?: string\n\n @Field({\n nullable: true,\n description: 'Specifies a grouping identifier for data items with related content, allowing them to be displayed as subgroups within the overall dataset.'\n })\n group?: string\n\n @Field(type => DataItemType, { nullable: true, description: 'The type of the data item' })\n type?: DataItemType\n\n @Field(type => ScalarObject, { nullable: true, description: 'Options associated with the data item type' })\n options?: { [option: string]: any }\n\n @Field({\n nullable: true,\n description: 'The grouping logic for data summarization in the given field during periodic task deadlines.'\n })\n stat?: DataItemStatType\n\n @Field({\n nullable: true,\n description: 'Aggregation functions to be used in data summarizing logic for a given period.'\n })\n agg?: DataItemStatType\n\n @Field({ nullable: true, description: 'The unit of measurement for the data item' })\n unit?: string\n\n @Field(type => Int, { nullable: true, description: 'The maximum number of data values allowed for this field' })\n quota?: number\n\n @Field({ nullable: true, description: 'Indicates if the data item is active' })\n active?: boolean\n\n @Field({ nullable: true, description: 'Indicates if the data item is hidden' })\n hidden?: boolean\n\n @Field(type => ScalarObject, {\n nullable: true,\n description: 'Specifies the valid ranges and parameters for this data item.'\n })\n spec?: { [key: string]: any }\n}\n"]}
|
@@ -7,7 +7,7 @@ const typeorm_1 = require("typeorm");
|
|
7
7
|
const attachment_base_1 = require("@things-factory/attachment-base");
|
8
8
|
const organization_1 = require("@things-factory/organization");
|
9
9
|
const scheduler_client_1 = require("@things-factory/scheduler-client");
|
10
|
-
const
|
10
|
+
const finalize_data_collection_1 = require("../../controllers/finalize-data-collection");
|
11
11
|
const data_set_1 = require("./data-set");
|
12
12
|
const data_set_type_1 = require("./data-set-type");
|
13
13
|
const crypto = require('crypto');
|
@@ -251,7 +251,7 @@ let DataSetMutation = class DataSetMutation {
|
|
251
251
|
dataSet: dataSetId
|
252
252
|
}));
|
253
253
|
}
|
254
|
-
const schedule = await (0,
|
254
|
+
const schedule = await (0, finalize_data_collection_1.getDataFinalizeCrontabSchedule)(dataSet, context);
|
255
255
|
try {
|
256
256
|
var handle = await (0, scheduler_client_1.registerSchedule)({
|
257
257
|
name: dataSet.name,
|