@things-factory/dataset 9.1.19 → 9.2.13
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/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/activities/activity-data-review.js +5 -2
- package/dist-server/activities/activity-data-review.js.map +1 -1
- package/dist-server/activities/activity-ooc-review.js +4 -1
- package/dist-server/activities/activity-ooc-review.js.map +1 -1
- package/dist-server/controllers/create-data-ooc.js +2 -1
- package/dist-server/controllers/create-data-ooc.js.map +1 -1
- package/dist-server/controllers/create-data-sample.js +2 -2
- package/dist-server/controllers/create-data-sample.js.map +1 -1
- package/dist-server/controllers/issue-data-collection-task.js +9 -5
- package/dist-server/controllers/issue-data-collection-task.js.map +1 -1
- package/dist-server/controllers/issue-ooc-resolve.js +11 -6
- package/dist-server/controllers/issue-ooc-resolve.js.map +1 -1
- package/dist-server/controllers/issue-ooc-review.js +9 -6
- package/dist-server/controllers/issue-ooc-review.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/spec/integration/debug.spec.ts +42 -0
- package/spec/integration/ooc-lifecycle.spec.ts +484 -0
- package/spec/integration/ooc-workflow.spec.ts +276 -0
- package/spec/integration/simple.spec.ts +62 -0
- package/spec/unit/controllers/activity-callbacks.spec.ts +609 -0
- package/spec/unit/controllers/create-data-ooc.spec.ts +310 -0
- package/spec/unit/controllers/issue-ooc-resolve.spec.ts +431 -0
- package/spec/unit/controllers/issue-ooc-review.spec.ts +288 -0
- package/spec/unit/data-use-case.spec.ts +150 -0
- package/spec/unit/ooc-state-transition.spec.ts +233 -0
|
@@ -26,7 +26,8 @@ async function callback(activityInstance, addendum, context) {
|
|
|
26
26
|
const { judgment, instruction } = output;
|
|
27
27
|
if (judgment == 'abnormal') {
|
|
28
28
|
/* Review 결과가 Ooc 조치가 필요하다고 하면, DataOoc를 생성하고, DataOocResolve를 이슈한다. */
|
|
29
|
-
|
|
29
|
+
const dataSet = dataSample.dataSet;
|
|
30
|
+
var ooc = await (0, create_data_ooc_js_1.createDataOoc)(dataSample, dataSet, context);
|
|
30
31
|
ooc = await tx.getRepository(data_ooc_js_1.DataOoc).save({
|
|
31
32
|
...ooc,
|
|
32
33
|
reviewedAt: activityInstance.terminatedAt,
|
|
@@ -35,7 +36,9 @@ async function callback(activityInstance, addendum, context) {
|
|
|
35
36
|
reviewActivityInstance: activityInstance,
|
|
36
37
|
state: data_ooc_js_1.DataOocStatus.REVIEWED
|
|
37
38
|
});
|
|
38
|
-
|
|
39
|
+
// save() 후 dataSet relation이 손실되므로 다시 설정
|
|
40
|
+
ooc.dataSet = dataSet;
|
|
41
|
+
await (0, issue_ooc_resolve_js_1.issueOocResolve)(ooc, dataSet, instruction, context);
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-data-review.js","sourceRoot":"","sources":["../../server/activities/activity-data-review.ts"],"names":[],"mappings":";;;AAAA,uDAAwH;AAExH,iEAAwE;AACxE,0EAAkE;AAClE,0EAAiE;AACjE,8EAAqE;AAErE,KAAK,UAAU,QAAQ,CACrB,gBAAkC,EAClC,QAA6C,EAC7C,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IACpC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,gBAAgB,CAAA;IAEjD,IAAI,KAAK,IAAI,iCAAsB,CAAC,KAAK,EAAE,CAAC;QAC1C,MAAM,EAAE,YAAY,EAAE,GAAG,KAAK,IAAI,EAAE,CAAA;QAEpC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;QAC5D,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,2BAAU,CAAC,CAAC,OAAO,CAAC;YAC5D,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE;YACtD,SAAS,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;SACvD,CAAC,CAAA;QAEF,MAAM,EAAE,CAAC,aAAa,CAAC,2BAAU,CAAC,CAAC,IAAI,CAAC;YACtC,GAAG,UAAU;YACb,MAAM;YACN,KAAK,EAAE,2BAAa,CAAC,QAAQ;SAC9B,CAAC,CAAA;QAEF,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,MAAM,CAAA;QAExC,IAAI,QAAQ,IAAI,UAAU,EAAE,CAAC;YAC3B,uEAAuE;YACvE,IAAI,GAAG,GAAG,MAAM,IAAA,kCAAa,EAAC,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"activity-data-review.js","sourceRoot":"","sources":["../../server/activities/activity-data-review.ts"],"names":[],"mappings":"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","sourcesContent":["import { ActivityInstance, ActivityInstanceStatus, UpdateActivityInstanceStateAddendum } from '@things-factory/worklist'\n\nimport { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc.js'\nimport { DataSample } from '../service/data-sample/data-sample.js'\nimport { createDataOoc } from '../controllers/create-data-ooc.js'\nimport { issueOocResolve } from '../controllers/issue-ooc-resolve.js'\n\nasync function callback(\n activityInstance: ActivityInstance,\n addendum: UpdateActivityInstanceStateAddendum,\n context: ResolverContext\n) {\n const { domain, tx } = context.state\n const { input, output, state } = activityInstance\n\n if (state == ActivityInstanceStatus.Ended) {\n const { dataSampleId } = input || {}\n\n if (!dataSampleId) {\n throw new Error('Data sample ID is missing in the input.')\n }\n\n const dataSample = await tx.getRepository(DataSample).findOne({\n where: { domain: { id: domain.id }, id: dataSampleId },\n relations: ['domain', 'dataSet', 'creator', 'updater']\n })\n\n await tx.getRepository(DataSample).save({\n ...dataSample,\n output,\n state: DataOocStatus.REVIEWED\n })\n\n const { judgment, instruction } = output\n\n if (judgment == 'abnormal') {\n /* Review 결과가 Ooc 조치가 필요하다고 하면, DataOoc를 생성하고, DataOocResolve를 이슈한다. */\n const dataSet = dataSample.dataSet\n var ooc = await createDataOoc(dataSample, dataSet, context)\n\n ooc = await tx.getRepository(DataOoc).save({\n ...ooc,\n reviewedAt: activityInstance.terminatedAt,\n reviewer: activityInstance.updater,\n correctiveInstruction: instruction,\n reviewActivityInstance: activityInstance,\n state: DataOocStatus.REVIEWED\n })\n\n // save() 후 dataSet relation이 손실되므로 다시 설정\n ooc.dataSet = dataSet\n\n await issueOocResolve(ooc, dataSet, instruction, context)\n }\n }\n}\n\nexport const ActivityDataReview = {\n name: 'Data Review',\n description: 'Tasks for data review',\n release: '1.0.0',\n provider: 'hatiolab.com',\n category: 'quality',\n activityType: 'user',\n priority: 1,\n searchKeys: [\n {\n name: 'dataSetName',\n description: 'DataSet name',\n inputKey: 'dataSetName',\n tKey: 'data-set-name'\n }\n ],\n startingType: '',\n multiple: 'single',\n model: [\n {\n name: 'dataSetId',\n description: 'DataSet Id.',\n tag: 'dataSetId',\n hidden: true,\n mandatory: true,\n inout: 'in',\n type: 'string',\n options: {},\n unit: null,\n quantifier: [1],\n spec: {}\n },\n {\n name: 'dataSetName',\n description: 'DataSet name',\n tag: 'dataSetName',\n hidden: true,\n mandatory: true,\n inout: 'in',\n type: 'string',\n options: {},\n unit: null,\n quantifier: [1],\n spec: {}\n }\n ],\n uiType: 'custom-element',\n uiSource: 'activity-data-review-edit',\n viewType: 'custom-element',\n viewSource: 'activity-data-review-view',\n reportType: 'custom-element',\n reportSource: 'activity-data-review-view',\n thumbnail: '/assets/images/data-collect.png',\n standardTime: 24 * 60 * 60, // seconds\n callback /* Called when there is a change in the lifecycle of a task (activity-instance). */\n}\n"]}
|
|
@@ -18,6 +18,7 @@ async function callback(activityInstance, addendum, context) {
|
|
|
18
18
|
},
|
|
19
19
|
relations: ['dataSet']
|
|
20
20
|
});
|
|
21
|
+
const dataSet = dataOoc.dataSet;
|
|
21
22
|
/* dataOoc Review 결과를 dataOoc 엔티티에 반영한다. */
|
|
22
23
|
dataOoc = await tx.getRepository(data_ooc_js_1.DataOoc).save({
|
|
23
24
|
...dataOoc,
|
|
@@ -26,7 +27,9 @@ async function callback(activityInstance, addendum, context) {
|
|
|
26
27
|
correctiveInstruction,
|
|
27
28
|
state: data_ooc_js_1.DataOocStatus.REVIEWED
|
|
28
29
|
});
|
|
29
|
-
|
|
30
|
+
// save() 후 dataSet relation이 손실되므로 다시 설정
|
|
31
|
+
dataOoc.dataSet = dataSet;
|
|
32
|
+
await (0, issue_ooc_resolve_js_1.issueOocResolve)(dataOoc, dataSet, correctiveInstruction, context);
|
|
30
33
|
}
|
|
31
34
|
}
|
|
32
35
|
exports.ActivityOocReview = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-ooc-review.js","sourceRoot":"","sources":["../../server/activities/activity-ooc-review.ts"],"names":[],"mappings":";;;AAAA,uDAAwH;AAExH,iEAAwE;AACxE,8EAAqE;AAErE,KAAK,UAAU,QAAQ,CACrB,gBAAkC,EAClC,QAA6C,EAC7C,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAC1C,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAAA;IAC/D,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,IAAI,EAAE,CAAA;IAEnC,IAAI,KAAK,IAAI,iCAAsB,CAAC,KAAK,EAAE,CAAC;QAC1C,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAA;QAC3B,MAAM,qBAAqB,GAAG,MAAM,EAAE,WAAW,CAAA;QAEjD,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,qBAAO,CAAC,CAAC,OAAO,CAAC;YACpD,KAAK,EAAE;gBACL,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACzB,EAAE,EAAE,SAAS;aACd;YACD,SAAS,EAAE,CAAC,SAAS,CAAC;SACvB,CAAC,CAAA;QAEF,2CAA2C;QAC3C,OAAO,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,qBAAO,CAAC,CAAC,IAAI,CAAC;YAC7C,GAAG,OAAO;YACV,UAAU,EAAE,YAAY;YACxB,QAAQ,EAAE,IAAI;YACd,qBAAqB;YACrB,KAAK,EAAE,2BAAa,CAAC,QAAQ;SAC9B,CAAC,CAAA;QAEF,MAAM,IAAA,sCAAe,EAAC,OAAO,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"activity-ooc-review.js","sourceRoot":"","sources":["../../server/activities/activity-ooc-review.ts"],"names":[],"mappings":"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","sourcesContent":["import { ActivityInstance, ActivityInstanceStatus, UpdateActivityInstanceStateAddendum } from '@things-factory/worklist'\n\nimport { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc.js'\nimport { issueOocResolve } from '../controllers/issue-ooc-resolve.js'\n\nasync function callback(\n activityInstance: ActivityInstance,\n addendum: UpdateActivityInstanceStateAddendum,\n context: ResolverContext\n) {\n const { domain, user, tx } = context.state\n const { input, output, state, terminatedAt } = activityInstance\n const { causedBy } = addendum || {}\n\n if (state == ActivityInstanceStatus.Ended) {\n const { dataOocId } = input\n const correctiveInstruction = output?.instruction\n\n var dataOoc = await tx.getRepository(DataOoc).findOne({\n where: {\n domain: { id: domain.id },\n id: dataOocId\n },\n relations: ['dataSet']\n })\n\n const dataSet = dataOoc.dataSet\n\n /* dataOoc Review 결과를 dataOoc 엔티티에 반영한다. */\n dataOoc = await tx.getRepository(DataOoc).save({\n ...dataOoc,\n reviewedAt: terminatedAt,\n reviewer: user,\n correctiveInstruction,\n state: DataOocStatus.REVIEWED\n })\n\n // save() 후 dataSet relation이 손실되므로 다시 설정\n dataOoc.dataSet = dataSet\n\n await issueOocResolve(dataOoc, dataSet, correctiveInstruction, context)\n }\n}\n\nexport const ActivityOocReview = {\n name: 'OOC Review',\n description: 'Task to take remedial action based on Out Of Control data',\n release: '1.0.0',\n provider: 'hatiolab.com',\n category: 'quality',\n activityType: 'user',\n priority: 2,\n searchKeys: [\n {\n name: 'dataOocId',\n description: 'OOC Id.',\n inputKey: 'dataOocId',\n tKey: 'data-ooc-id'\n }\n ],\n startingType: '',\n multiple: 'single',\n model: [\n {\n name: 'dataOocId',\n description: 'OOC id',\n tag: 'dataOocId',\n hidden: true,\n mandatory: true,\n inout: 'in',\n type: 'string',\n options: {},\n unit: null,\n quantifier: [1],\n spec: {}\n },\n {\n name: 'Instruction',\n description: 'Instructions for preventing OOC',\n tag: 'instruction',\n hidden: false,\n mandatory: true,\n inout: 'out',\n type: 'textarea',\n options: {},\n unit: null,\n quantifier: [1],\n spec: {}\n }\n ],\n uiType: 'custom-element',\n uiSource: 'activity-ooc-review-edit',\n viewType: 'custom-element',\n viewSource: 'activity-ooc-review-view',\n reportType: 'custom-element',\n reportSource: 'data-ooc-report-page',\n thumbnail: '/assets/images/ooc.png',\n standardTime: 24 * 60 * 60, // seconds\n callback /* Called when there is a change in the lifecycle of a task (activity-instance). */\n}\n"]}
|
|
@@ -24,13 +24,14 @@ async function createDataOoc(dataSample, dataSet, context) {
|
|
|
24
24
|
dataSample: dataSample
|
|
25
25
|
});
|
|
26
26
|
if (dataSet.outlierScenarioId) {
|
|
27
|
-
|
|
27
|
+
var scenarios = await tx.getRepository(integration_base_1.Scenario).find({
|
|
28
28
|
where: {
|
|
29
29
|
domain: domain.parentId ? { id: (0, typeorm_1.In)([domain.id, domain.parentId]) } : { id: domain.id },
|
|
30
30
|
id: dataSet.outlierScenarioId
|
|
31
31
|
},
|
|
32
32
|
relations: ['domain', 'steps', 'updater']
|
|
33
33
|
});
|
|
34
|
+
const scenario = scenarios.find(s => s.domain.id === domain.id) || scenarios.find(s => s.domain.id === domain.parentId);
|
|
34
35
|
if (scenario) {
|
|
35
36
|
scenario.start({
|
|
36
37
|
instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-data-ooc.js","sourceRoot":"","sources":["../../server/controllers/create-data-ooc.ts"],"names":[],"mappings":";;AAQA,
|
|
1
|
+
{"version":3,"file":"create-data-ooc.js","sourceRoot":"","sources":["../../server/controllers/create-data-ooc.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { Scenario } from '@things-factory/integration-base'\n\nimport { DataSet } from '../service/data-set/data-set.js'\nimport { DataSample } from '../service/data-sample/data-sample.js'\nimport { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc.js'\n\nexport async function createDataOoc(\n dataSample: DataSample,\n dataSet: DataSet,\n context: ResolverContext\n): Promise<DataOoc> {\n const { domain, user, tx } = context.state\n const { collectedAt, data, ooc, oos, judgment, workDate, workShift } = dataSample\n\n const dataOoc = await tx.getRepository(DataOoc).save({\n ...dataSample,\n history: [\n {\n user: {\n id: user?.id,\n username: user?.username || user?.email,\n name: user?.name\n },\n state: DataOocStatus.ISSUED,\n timestamp: collectedAt\n }\n ],\n state: DataOocStatus.ISSUED,\n dataSample: dataSample\n })\n\n if (dataSet.outlierScenarioId) {\n var scenarios = await tx.getRepository(Scenario).find({\n where: {\n domain: domain.parentId ? { id: In([domain.id, domain.parentId]) } : { id: domain.id },\n id: dataSet.outlierScenarioId\n },\n relations: ['domain', 'steps', 'updater']\n })\n\n const scenario = scenarios.find(s => s.domain.id === domain.id) || scenarios.find(s => s.domain.id === domain.parentId)\n\n if (scenario) {\n scenario.start({\n instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,\n domain,\n user,\n variables: {\n dataOocId: dataOoc.id,\n dataSampleId: dataSample.id,\n dataSet: dataSet.id,\n data,\n ooc,\n oos,\n judgment,\n collectedAt,\n workDate,\n workShift,\n domain: {\n id: domain.id,\n subdomain: domain.subdomain,\n name: domain.name\n },\n updator: {\n id: user.id,\n username: user.username || user.email,\n email: user.email,\n name: user.name\n }\n }\n })\n } else {\n console.error(`Cannot find the set outlier-scenario for the dataset(${dataSet.name}).`)\n }\n }\n\n return dataOoc\n}\n"]}
|
|
@@ -308,8 +308,8 @@ async function createDataSample(newDataSample, context) {
|
|
|
308
308
|
threadsMax: 1,
|
|
309
309
|
approvalLine: dataSet.reviewApprovalLine
|
|
310
310
|
};
|
|
311
|
-
|
|
312
|
-
await (0, shell_1.getRepository)(data_sample_js_1.DataSample, tx).
|
|
311
|
+
const reviewActivityInstance = await (0, issue_1.issue)(activityInstance, context);
|
|
312
|
+
await (0, shell_1.getRepository)(data_sample_js_1.DataSample, tx).update({ id: dataSample.id }, { reviewActivityInstance });
|
|
313
313
|
try {
|
|
314
314
|
shell_1.pubsub.publish('notification', {
|
|
315
315
|
notification: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-data-sample.js","sourceRoot":"","sources":["../../server/controllers/create-data-sample.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { In } from 'typeorm'\n\nimport { Attachment, createAttachment } from '@things-factory/attachment-base'\nimport { Role } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { getRepository, getRedirectSubdomainPath, pubsub } from '@things-factory/shell'\nimport { getWorkDateAndShift } from '@things-factory/work-shift'\nimport { Scenario, publishData } from '@things-factory/integration-base'\nimport { Activity } from '@things-factory/worklist'\nimport { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'\n\nimport { DataSample } from '../service/data-sample/data-sample.js'\nimport { NewDataSample } from '../service/data-sample/data-sample-type.js'\nimport { DataSet } from '../service/data-set/data-set.js'\nimport { createDataOoc } from './create-data-ooc.js'\nimport { issueOocReview } from './issue-ooc-review.js'\nimport { DataUseCase } from './data-use-case.js'\nimport { isFileOrMediaType, validateMediaFile, isMediaType } from '../utils/index.js'\n\n// See README.md at ## Data Samples\nprocess.env.TZ = 'UTC'\n\nconst fillDataKeys = (dataKeySet, data = {}) => {\n const keys = dataKeySet?.dataKeyItems || []\n return keys.reduce((sum, key, index) => {\n const value = data[key.dataKey]\n if (value != null) {\n sum[`key0${index + 1}`] = value instanceof Array ? value[0] : value\n }\n return sum\n }, {})\n}\n\n// parse variable javascript string pattern\nconst replaceVariables = (keys, dic) => {\n for (const k in keys) {\n const matches = keys[k].match(/\\$\\{\\w*\\}/g)\n matches &&\n matches.forEach(m => {\n keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])\n })\n }\n return keys\n}\n\n// It is required UTC date for Partitioning File System like AWS S3 from Athena.\n// ex) %YYYY, %MM, %DD\nconst formatDate = (keys, _moment) => {\n for (const k in keys) {\n const matches = keys[k].match(/%\\w*/g)\n matches &&\n matches.forEach(m => {\n keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))\n })\n }\n return keys\n}\n\nexport async function createDataSample(newDataSample: NewDataSample, context: ResolverContext): Promise<DataSample> {\n const { domain, user, tx } = context.state\n\n const dataSet = await getRepository(DataSet, tx).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: newDataSample.dataSet.id },\n relations: ['dataKeySet']\n })\n\n const { dataItems = [], tag: publishTag, normalScenarioId, outlierScenarioId } = dataSet\n const collectedAt = newDataSample.collectedAt || new Date()\n\n const timezone = dataSet.timezone || domain.timezone || 'UTC'\n const format = 'YYYY-MM-DD'\n\n // workDate ex) 2022-04-04\n const { workDate, workShift } = await getWorkDateAndShift(domain, collectedAt, { timezone, format })\n\n // local time dataSet timezone or domain timezone or default 'UTC'\n\n const localDateTz = moment(collectedAt).tz(timezone)\n const defaultPartitionKeys = {\n domain: domain.subdomain,\n datasetid: newDataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,\n date: localDateTz.format(format) /* local time date */,\n workdate: workDate /* working date */,\n workshift: workShift\n }\n\n var partitionKeys = {\n ...defaultPartitionKeys,\n ...dataSet.partitionKeys\n }\n\n partitionKeys = formatDate(partitionKeys, localDateTz)\n partitionKeys = replaceVariables(partitionKeys, newDataSample.data)\n\n const dataKeys = fillDataKeys(dataSet?.dataKeySet, newDataSample.data)\n\n const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems, newDataSample.data) || {}\n\n const old = await getRepository(DataSample, tx).findOne({\n where: {\n domain: { id: domain.id },\n dataSet: { id: dataSet.id },\n collectedAt,\n ...dataKeys\n }\n })\n\n /*\n Pre-processing for file and media attachments.\n - file type: supports multiple files + quota (array processing)\n - media types (image, video, audio): single file only (like signature)\n - Validates MIME types for media files\n - Enforces options constraints (accept, maxSize, etc.)\n - Creates Attachment records for all uploaded files\n */\n\n const data = newDataSample.data\n const attachments = []\n\n for (let dataItem of dataItems) {\n const tag = dataItem.tag\n\n // Handle file type (multiple + quota support, array processing)\n if (dataItem.type === 'file') {\n const filesArray = data[tag]\n\n if (tag && filesArray && filesArray.length > 0) {\n let pathsArray = []\n\n for (let files of filesArray) {\n let paths = []\n\n if (files instanceof Array) {\n for (let file of files) {\n if (file) {\n const attachment = await createAttachment(\n null,\n {\n attachment: {\n file: file.file,\n refType: DataSample.name\n }\n },\n context\n )\n\n const fetched = await getRepository(Attachment, tx).findOneBy({ id: attachment.id })\n if (fetched) {\n attachments.push(fetched)\n paths.push({\n id: fetched.id,\n mimetype: fetched.mimetype,\n name: fetched.name,\n fullpath: fetched.fullpath\n })\n } else {\n throw `Failed to save file(${attachment.name})`\n }\n } else {\n paths.push(null)\n }\n }\n }\n\n pathsArray.push(paths)\n }\n\n data[tag] = pathsArray\n }\n }\n // Handle media types (image, video, audio): single file only\n else if (isMediaType(dataItem.type)) {\n let fileValue = data[tag]\n\n // Frontend sends as array, extract first element\n if (Array.isArray(fileValue)) {\n fileValue = fileValue[0]\n }\n\n if (tag && fileValue) {\n // Handle both File object directly and {file: File} structure\n const actualFile = fileValue.file || fileValue\n\n // Skip if file is already an attachment object (has fullpath)\n if (actualFile.fullpath) {\n continue\n }\n\n // Get MIME type from various possible property names\n const mimeType = actualFile.mimetype || actualFile.type || actualFile.contentType\n\n // Validate media file against options\n const validation = validateMediaFile(\n {\n mimetype: mimeType,\n size: actualFile.size,\n name: actualFile.filename || actualFile.name\n },\n dataItem.type,\n dataItem.options\n )\n\n if (!validation.valid) {\n throw new Error(\n `Media validation failed for '${tag}' (${dataItem.type}): ${validation.errors.join(', ')}`\n )\n }\n\n const attachment = await createAttachment(\n null,\n {\n attachment: {\n file: actualFile,\n refType: DataSample.name\n }\n },\n context\n )\n\n const fetched = await getRepository(Attachment, tx).findOneBy({ id: attachment.id })\n if (fetched) {\n attachments.push(fetched)\n // Store as single attachment object (like signature)\n data[tag] = {\n id: fetched.id,\n mimetype: fetched.mimetype,\n name: fetched.name,\n fullpath: fetched.fullpath\n }\n } else {\n throw `Failed to save file(${attachment.name})`\n }\n }\n }\n }\n\n const dataSample = await getRepository(DataSample, tx).save({\n ...old,\n name: dataSet.name,\n description: dataSet.description,\n useCase: dataSet.useCase,\n type: dataSet.type,\n ...newDataSample,\n ...dataKeys,\n dataSetVersion: dataSet.version,\n domain,\n partitionKeys,\n ooc,\n oos,\n judgment,\n collectedAt,\n workDate,\n workShift,\n creator: user,\n updater: user\n })\n\n if (publishTag) {\n publishData(publishTag, data, { domain, user })\n }\n\n /* post-process for for file attachment. */\n if (attachments.length > 0) {\n attachments.forEach(attachment => (attachment.refId = dataSample.id))\n getRepository(Attachment, tx).save(attachments)\n }\n\n if (ooc || oos) {\n const dataOoc = await createDataOoc(dataSample, dataSet, context)\n await issueOocReview(dataOoc, dataSet, context)\n\n try {\n pubsub.publish('notification', {\n notification: {\n domain,\n type: 'error',\n title: `[OOC] ${dataSet.name}`,\n body: `Data OOC occurred on '${dataSet.name}'`,\n url: getRedirectSubdomainPath(context, domain, `/data-ooc/${dataOoc.id}`),\n timestamp: collectedAt\n }\n })\n } catch (err) {\n logger.error('Notification', err)\n }\n } else {\n if (normalScenarioId) {\n const scenario = await getRepository(Scenario, tx).findOne({\n where: {\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: normalScenarioId\n },\n relations: ['domain', 'steps', 'updater']\n })\n\n if (scenario) {\n scenario.start({\n instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,\n domain,\n user,\n variables: {\n dataSampleId: dataSample.id,\n dataSet: dataSet.id,\n data,\n ooc,\n oos,\n judgment,\n collectedAt,\n workDate,\n workShift,\n domain: {\n id: domain.id,\n subdomain: domain.subdomain,\n name: domain.name\n },\n updator: {\n id: user.id,\n email: user.email,\n name: user.name\n }\n }\n })\n } else {\n console.error(`Cannot find the set normal-scenario for the dataset(${dataSet.name}).`)\n }\n }\n\n if (dataSet.requiresReview) {\n const activity = (await getRepository(Activity, tx).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n name: 'Data Review'\n })) as Activity\n\n if (activity) {\n const assigneeRole =\n dataSet.supervisoryRoleId &&\n (await getRepository(Role, tx).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: dataSet.supervisoryRoleId\n }))\n\n // const assignees = dataSet.supervisoryRoleId\n // ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assigneeRole }]\n // : []\n\n /* 해당 dataset의 supervisor로 하여금, data를 리뷰하고 instruction을 작성해서, approvalLine을 이용해서 승인을 한다. */\n if (assigneeRole) {\n dataSample.dataItems = dataItems\n const activityInstance = {\n name: `[Data 검토] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(collectedAt.getTime() + (activity.standardTime || 24 * 60 * 60) * 1000),\n input: {\n dataSampleId: dataSample.id\n },\n assigneeRole,\n threadsMin: 1,\n threadsMax: 1,\n approvalLine: dataSet.reviewApprovalLine\n }\n\n dataSample.reviewActivityInstance = await issue(activityInstance as any, context)\n await getRepository(DataSample, tx).save(dataSample)\n\n try {\n pubsub.publish('notification', {\n notification: {\n domain,\n type: 'info',\n title: `[Data Review] ${dataSet.name}`,\n body: `Data Review occurred on '${dataSet.name}'`,\n url: getRedirectSubdomainPath(context, domain, `/data-sample/${dataSample.id}`),\n timestamp: collectedAt\n }\n })\n } catch (err) {\n logger.error('Notification', err)\n }\n } else {\n console.error(\n `Assignees are not set. So Data Review task for ${dataSet.name}(${dataSet.id}) could not be issued.`\n )\n }\n } else {\n console.error('Data Review Activity not installed.')\n }\n }\n }\n\n return dataSample\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create-data-sample.js","sourceRoot":"","sources":["../../server/controllers/create-data-sample.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { In } from 'typeorm'\n\nimport { Attachment, createAttachment } from '@things-factory/attachment-base'\nimport { Role } from '@things-factory/auth-base'\nimport { logger } from '@things-factory/env'\nimport { getRepository, getRedirectSubdomainPath, pubsub } from '@things-factory/shell'\nimport { getWorkDateAndShift } from '@things-factory/work-shift'\nimport { Scenario, publishData } from '@things-factory/integration-base'\nimport { Activity } from '@things-factory/worklist'\nimport { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'\n\nimport { DataSample } from '../service/data-sample/data-sample.js'\nimport { NewDataSample } from '../service/data-sample/data-sample-type.js'\nimport { DataSet } from '../service/data-set/data-set.js'\nimport { createDataOoc } from './create-data-ooc.js'\nimport { issueOocReview } from './issue-ooc-review.js'\nimport { DataUseCase } from './data-use-case.js'\nimport { isFileOrMediaType, validateMediaFile, isMediaType } from '../utils/index.js'\n\n// See README.md at ## Data Samples\nprocess.env.TZ = 'UTC'\n\nconst fillDataKeys = (dataKeySet, data = {}) => {\n const keys = dataKeySet?.dataKeyItems || []\n return keys.reduce((sum, key, index) => {\n const value = data[key.dataKey]\n if (value != null) {\n sum[`key0${index + 1}`] = value instanceof Array ? value[0] : value\n }\n return sum\n }, {})\n}\n\n// parse variable javascript string pattern\nconst replaceVariables = (keys, dic) => {\n for (const k in keys) {\n const matches = keys[k].match(/\\$\\{\\w*\\}/g)\n matches &&\n matches.forEach(m => {\n keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])\n })\n }\n return keys\n}\n\n// It is required UTC date for Partitioning File System like AWS S3 from Athena.\n// ex) %YYYY, %MM, %DD\nconst formatDate = (keys, _moment) => {\n for (const k in keys) {\n const matches = keys[k].match(/%\\w*/g)\n matches &&\n matches.forEach(m => {\n keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))\n })\n }\n return keys\n}\n\nexport async function createDataSample(newDataSample: NewDataSample, context: ResolverContext): Promise<DataSample> {\n const { domain, user, tx } = context.state\n\n const dataSet = await getRepository(DataSet, tx).findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id: newDataSample.dataSet.id },\n relations: ['dataKeySet']\n })\n\n const { dataItems = [], tag: publishTag, normalScenarioId, outlierScenarioId } = dataSet\n const collectedAt = newDataSample.collectedAt || new Date()\n\n const timezone = dataSet.timezone || domain.timezone || 'UTC'\n const format = 'YYYY-MM-DD'\n\n // workDate ex) 2022-04-04\n const { workDate, workShift } = await getWorkDateAndShift(domain, collectedAt, { timezone, format })\n\n // local time dataSet timezone or domain timezone or default 'UTC'\n\n const localDateTz = moment(collectedAt).tz(timezone)\n const defaultPartitionKeys = {\n domain: domain.subdomain,\n datasetid: newDataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,\n date: localDateTz.format(format) /* local time date */,\n workdate: workDate /* working date */,\n workshift: workShift\n }\n\n var partitionKeys = {\n ...defaultPartitionKeys,\n ...dataSet.partitionKeys\n }\n\n partitionKeys = formatDate(partitionKeys, localDateTz)\n partitionKeys = replaceVariables(partitionKeys, newDataSample.data)\n\n const dataKeys = fillDataKeys(dataSet?.dataKeySet, newDataSample.data)\n\n const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataItems, newDataSample.data) || {}\n\n const old = await getRepository(DataSample, tx).findOne({\n where: {\n domain: { id: domain.id },\n dataSet: { id: dataSet.id },\n collectedAt,\n ...dataKeys\n }\n })\n\n /*\n Pre-processing for file and media attachments.\n - file type: supports multiple files + quota (array processing)\n - media types (image, video, audio): single file only (like signature)\n - Validates MIME types for media files\n - Enforces options constraints (accept, maxSize, etc.)\n - Creates Attachment records for all uploaded files\n */\n\n const data = newDataSample.data\n const attachments = []\n\n for (let dataItem of dataItems) {\n const tag = dataItem.tag\n\n // Handle file type (multiple + quota support, array processing)\n if (dataItem.type === 'file') {\n const filesArray = data[tag]\n\n if (tag && filesArray && filesArray.length > 0) {\n let pathsArray = []\n\n for (let files of filesArray) {\n let paths = []\n\n if (files instanceof Array) {\n for (let file of files) {\n if (file) {\n const attachment = await createAttachment(\n null,\n {\n attachment: {\n file: file.file,\n refType: DataSample.name\n }\n },\n context\n )\n\n const fetched = await getRepository(Attachment, tx).findOneBy({ id: attachment.id })\n if (fetched) {\n attachments.push(fetched)\n paths.push({\n id: fetched.id,\n mimetype: fetched.mimetype,\n name: fetched.name,\n fullpath: fetched.fullpath\n })\n } else {\n throw `Failed to save file(${attachment.name})`\n }\n } else {\n paths.push(null)\n }\n }\n }\n\n pathsArray.push(paths)\n }\n\n data[tag] = pathsArray\n }\n }\n // Handle media types (image, video, audio): single file only\n else if (isMediaType(dataItem.type)) {\n let fileValue = data[tag]\n\n // Frontend sends as array, extract first element\n if (Array.isArray(fileValue)) {\n fileValue = fileValue[0]\n }\n\n if (tag && fileValue) {\n // Handle both File object directly and {file: File} structure\n const actualFile = fileValue.file || fileValue\n\n // Skip if file is already an attachment object (has fullpath)\n if (actualFile.fullpath) {\n continue\n }\n\n // Get MIME type from various possible property names\n const mimeType = actualFile.mimetype || actualFile.type || actualFile.contentType\n\n // Validate media file against options\n const validation = validateMediaFile(\n {\n mimetype: mimeType,\n size: actualFile.size,\n name: actualFile.filename || actualFile.name\n },\n dataItem.type,\n dataItem.options\n )\n\n if (!validation.valid) {\n throw new Error(\n `Media validation failed for '${tag}' (${dataItem.type}): ${validation.errors.join(', ')}`\n )\n }\n\n const attachment = await createAttachment(\n null,\n {\n attachment: {\n file: actualFile,\n refType: DataSample.name\n }\n },\n context\n )\n\n const fetched = await getRepository(Attachment, tx).findOneBy({ id: attachment.id })\n if (fetched) {\n attachments.push(fetched)\n // Store as single attachment object (like signature)\n data[tag] = {\n id: fetched.id,\n mimetype: fetched.mimetype,\n name: fetched.name,\n fullpath: fetched.fullpath\n }\n } else {\n throw `Failed to save file(${attachment.name})`\n }\n }\n }\n }\n\n const dataSample = await getRepository(DataSample, tx).save({\n ...old,\n name: dataSet.name,\n description: dataSet.description,\n useCase: dataSet.useCase,\n type: dataSet.type,\n ...newDataSample,\n ...dataKeys,\n dataSetVersion: dataSet.version,\n domain,\n partitionKeys,\n ooc,\n oos,\n judgment,\n collectedAt,\n workDate,\n workShift,\n creator: user,\n updater: user\n })\n\n if (publishTag) {\n publishData(publishTag, data, { domain, user })\n }\n\n /* post-process for for file attachment. */\n if (attachments.length > 0) {\n attachments.forEach(attachment => (attachment.refId = dataSample.id))\n getRepository(Attachment, tx).save(attachments)\n }\n\n if (ooc || oos) {\n const dataOoc = await createDataOoc(dataSample, dataSet, context)\n await issueOocReview(dataOoc, dataSet, context)\n\n try {\n pubsub.publish('notification', {\n notification: {\n domain,\n type: 'error',\n title: `[OOC] ${dataSet.name}`,\n body: `Data OOC occurred on '${dataSet.name}'`,\n url: getRedirectSubdomainPath(context, domain, `/data-ooc/${dataOoc.id}`),\n timestamp: collectedAt\n }\n })\n } catch (err) {\n logger.error('Notification', err)\n }\n } else {\n if (normalScenarioId) {\n const scenario = await getRepository(Scenario, tx).findOne({\n where: {\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: normalScenarioId\n },\n relations: ['domain', 'steps', 'updater']\n })\n\n if (scenario) {\n scenario.start({\n instanceName: scenario.name + ':' + dataSet.name + ':' + dataSample.id,\n domain,\n user,\n variables: {\n dataSampleId: dataSample.id,\n dataSet: dataSet.id,\n data,\n ooc,\n oos,\n judgment,\n collectedAt,\n workDate,\n workShift,\n domain: {\n id: domain.id,\n subdomain: domain.subdomain,\n name: domain.name\n },\n updator: {\n id: user.id,\n email: user.email,\n name: user.name\n }\n }\n })\n } else {\n console.error(`Cannot find the set normal-scenario for the dataset(${dataSet.name}).`)\n }\n }\n\n if (dataSet.requiresReview) {\n const activity = (await getRepository(Activity, tx).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n name: 'Data Review'\n })) as Activity\n\n if (activity) {\n const assigneeRole =\n dataSet.supervisoryRoleId &&\n (await getRepository(Role, tx).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: dataSet.supervisoryRoleId\n }))\n\n // const assignees = dataSet.supervisoryRoleId\n // ? [{ type: 'Role', value: dataSet.supervisoryRoleId, assigneeRole }]\n // : []\n\n /* 해당 dataset의 supervisor로 하여금, data를 리뷰하고 instruction을 작성해서, approvalLine을 이용해서 승인을 한다. */\n if (assigneeRole) {\n dataSample.dataItems = dataItems\n const activityInstance = {\n name: `[Data 검토] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(collectedAt.getTime() + (activity.standardTime || 24 * 60 * 60) * 1000),\n input: {\n dataSampleId: dataSample.id\n },\n assigneeRole,\n threadsMin: 1,\n threadsMax: 1,\n approvalLine: dataSet.reviewApprovalLine\n }\n\n const reviewActivityInstance = await issue(activityInstance as any, context)\n await getRepository(DataSample, tx).update({ id: dataSample.id }, { reviewActivityInstance })\n\n try {\n pubsub.publish('notification', {\n notification: {\n domain,\n type: 'info',\n title: `[Data Review] ${dataSet.name}`,\n body: `Data Review occurred on '${dataSet.name}'`,\n url: getRedirectSubdomainPath(context, domain, `/data-sample/${dataSample.id}`),\n timestamp: collectedAt\n }\n })\n } catch (err) {\n logger.error('Notification', err)\n }\n } else {\n console.error(\n `Assignees are not set. So Data Review task for ${dataSet.name}(${dataSet.id}) could not be issued.`\n )\n }\n } else {\n console.error('Data Review Activity not installed.')\n }\n }\n }\n\n return dataSample\n}\n"]}
|
|
@@ -11,7 +11,7 @@ async function issueDataCollectionTask(domainId, dataSetId, context) {
|
|
|
11
11
|
if (!domain) {
|
|
12
12
|
throw new Error(`domain(${domainId}) not found`);
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
var dataSets = await tx.getRepository(data_set_js_1.DataSet).find({
|
|
15
15
|
where: {
|
|
16
16
|
domain: {
|
|
17
17
|
id: (0, typeorm_1.In)([domain.id, domain.parentId].filter(Boolean))
|
|
@@ -20,10 +20,14 @@ async function issueDataCollectionTask(domainId, dataSetId, context) {
|
|
|
20
20
|
},
|
|
21
21
|
relations: ['entryRole']
|
|
22
22
|
});
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
const dataSet = dataSets.find(ds => ds.domainId === domain.id) || dataSets.find(ds => ds.domainId === domain.parentId);
|
|
24
|
+
var activities = await tx.getRepository(worklist_1.Activity).find({
|
|
25
|
+
where: {
|
|
26
|
+
domain: { id: (0, typeorm_1.In)([domain.id, domain.parentId].filter(Boolean)) },
|
|
27
|
+
name: 'Collect Data'
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId);
|
|
27
31
|
if (activity) {
|
|
28
32
|
const { entryRole, timeLimit } = dataSet;
|
|
29
33
|
/* 해당 dataset에 대한 데이타 수집 태스크를 dataset entryRole에게 할당한다. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-data-collection-task.js","sourceRoot":"","sources":["../../server/controllers/issue-data-collection-task.ts"],"names":[],"mappings":";;AAOA,
|
|
1
|
+
{"version":3,"file":"issue-data-collection-task.js","sourceRoot":"","sources":["../../server/controllers/issue-data-collection-task.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\n\nimport { Domain, getDataSource } from '@things-factory/shell'\nimport { Activity, ActivityInstance, issue } from '@things-factory/worklist'\n\nimport { DataSet } from '../service/data-set/data-set.js'\n\nexport async function issueDataCollectionTask(\n domainId: string,\n dataSetId: string,\n context: ResolverContext\n): Promise<ActivityInstance | void> {\n return await getDataSource().transaction(async tx => {\n const domain = await tx.getRepository(Domain).findOneBy({ id: domainId })\n\n if (!domain) {\n throw new Error(`domain(${domainId}) not found`)\n }\n\n var dataSets = await tx.getRepository(DataSet).find({\n where: {\n domain: {\n id: In([domain.id, domain.parentId].filter(Boolean))\n },\n id: dataSetId\n },\n relations: ['entryRole']\n })\n\n const dataSet = dataSets.find(ds => ds.domainId === domain.id) || dataSets.find(ds => ds.domainId === domain.parentId)\n\n var activities = await tx.getRepository(Activity).find({\n where: {\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n name: 'Collect Data'\n }\n })\n\n const activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId)\n\n if (activity) {\n const { entryRole, timeLimit } = dataSet\n\n /* 해당 dataset에 대한 데이타 수집 태스크를 dataset entryRole에게 할당한다. */\n if (entryRole) {\n const activityInstance = {\n name: `[Data 수집] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(Date.now() + (timeLimit || activity.standardTime || 24 * 60 * 60) * 1000),\n input: {\n dataSetId: dataSet.id,\n dataSetName: dataSet.name\n },\n assigneeRole: entryRole,\n threadsMin: 1,\n threadsMax: 1\n }\n\n context.state = {\n ...context.state,\n domain,\n tx\n }\n\n return await issue(activityInstance, context)\n } else {\n throw new Error(\n `Data Entry Role not set. So Data Collect Activity for ${dataSet.name}($dataSet.id) could not be issued.`\n )\n }\n } else {\n throw new Error(`Data Collect Activity is not installed.`)\n }\n })\n}\n"]}
|
|
@@ -9,10 +9,15 @@ const data_ooc_js_1 = require("../service/data-ooc/data-ooc.js");
|
|
|
9
9
|
async function issueOocResolve(dataOoc, dataSet, correctiveInstruction, context) {
|
|
10
10
|
const { domain, user, tx } = context.state;
|
|
11
11
|
const { resolverRoleId, outlierApprovalLine } = dataSet;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
var activities = await tx.getRepository(worklist_1.Activity).find({
|
|
13
|
+
where: {
|
|
14
|
+
domain: domain.parentId ? (0, typeorm_1.In)([domain.id, domain.parentId]) : { id: domain.id },
|
|
15
|
+
name: 'OOC Resolve'
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// Prioritize the activity in the current domain
|
|
19
|
+
// Assumes that if both exist, the one in my domain is the intended customization or override
|
|
20
|
+
var activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId);
|
|
16
21
|
if (activity) {
|
|
17
22
|
const assigneeRole = resolverRoleId &&
|
|
18
23
|
(await tx.getRepository(auth_base_1.Role).findOneBy({
|
|
@@ -35,8 +40,8 @@ async function issueOocResolve(dataOoc, dataSet, correctiveInstruction, context)
|
|
|
35
40
|
threadsMax: 1,
|
|
36
41
|
approvalLine: outlierApprovalLine
|
|
37
42
|
};
|
|
38
|
-
|
|
39
|
-
await tx.getRepository(data_ooc_js_1.DataOoc).
|
|
43
|
+
const resolveActivityInstance = await (0, issue_1.issue)(activityInstance, context);
|
|
44
|
+
await tx.getRepository(data_ooc_js_1.DataOoc).update({ id: dataOoc.id }, { resolveActivityInstance });
|
|
40
45
|
}
|
|
41
46
|
else {
|
|
42
47
|
console.error(`Assignees are not set. So, Data OOC Resolve task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-ooc-resolve.js","sourceRoot":"","sources":["../../server/controllers/issue-ooc-resolve.ts"],"names":[],"mappings":";;AAQA,
|
|
1
|
+
{"version":3,"file":"issue-ooc-resolve.js","sourceRoot":"","sources":["../../server/controllers/issue-ooc-resolve.ts"],"names":[],"mappings":";;AAQA,0CAuDC;AA/DD,qCAA4B;AAC5B,uDAAmD;AACnD,oGAAgG;AAChG,yDAAgD;AAEhD,iEAAyD;AAGlD,KAAK,UAAU,eAAe,CACnC,OAAgB,EAChB,OAAgB,EAChB,qBAA6B,EAC7B,OAAwB;IAExB,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IAC1C,MAAM,EAAE,cAAc,EAAE,mBAAmB,EAAE,GAAG,OAAO,CAAA;IAEvD,IAAI,UAAU,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mBAAQ,CAAC,CAAC,IAAI,CAAC;QACrD,KAAK,EAAE;YACL,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;YAC9E,IAAI,EAAE,aAAa;SACpB;KACF,CAAC,CAAA;IAEF,gDAAgD;IAChD,6FAA6F;IAC7F,IAAI,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAA;IAErH,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,YAAY,GAChB,cAAc;YACd,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,gBAAI,CAAC,CAAC,SAAS,CAAC;gBACtC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE;gBAChE,EAAE,EAAE,cAAc;aACnB,CAAC,CAAC,CAAA;QAEL,8DAA8D;QAC9D,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,gBAAgB,GAAG;gBACvB,IAAI,EAAE,YAAY,OAAO,CAAC,IAAI,EAAE;gBAChC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACvB,KAAK,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;gBAC5E,KAAK,EAAE;oBACL,SAAS,EAAE,OAAO,CAAC,EAAE;oBACrB,WAAW,EAAE,qBAAqB;iBACnC;gBACD,YAAY;gBACZ,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,CAAC;gBACb,YAAY,EAAE,mBAAmB;aAClC,CAAA;YAED,MAAM,uBAAuB,GAAG,MAAM,IAAA,aAAK,EAAC,gBAAgB,EAAE,OAAO,CAAC,CAAA;YACtE,MAAM,EAAE,CAAC,aAAa,CAAC,qBAAO,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,uBAAuB,EAAE,CAAC,CAAA;QACzF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CACX,wDAAwD,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,wBAAwB,CAC3G,CAAA;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAA;IACtD,CAAC;AACH,CAAC","sourcesContent":["import { In } from 'typeorm'\nimport { Activity } from '@things-factory/worklist'\nimport { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'\nimport { Role } from '@things-factory/auth-base'\n\nimport { DataOoc } from '../service/data-ooc/data-ooc.js'\nimport { DataSet } from '../service/data-set/data-set.js'\n\nexport async function issueOocResolve(\n dataOoc: DataOoc,\n dataSet: DataSet,\n correctiveInstruction: string,\n context: ResolverContext\n): Promise<void> {\n const { domain, user, tx } = context.state\n const { resolverRoleId, outlierApprovalLine } = dataSet\n\n var activities = await tx.getRepository(Activity).find({\n where: {\n domain: domain.parentId ? In([domain.id, domain.parentId]) : { id: domain.id },\n name: 'OOC Resolve'\n }\n })\n\n // Prioritize the activity in the current domain\n // Assumes that if both exist, the one in my domain is the intended customization or override\n var activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId)\n\n if (activity) {\n const assigneeRole =\n resolverRoleId &&\n (await tx.getRepository(Role).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: resolverRoleId\n }))\n\n /* 해당 dataset의 작업 담당자(resolverRole)에게 OOC 해결을 위한 태스크를 지시한다. */\n if (assigneeRole) {\n const activityInstance = {\n name: `[OOC 조치] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(Date.now() + (activity.standardTime || 24 * 60 * 60) * 1000),\n input: {\n dataOocId: dataOoc.id,\n instruction: correctiveInstruction\n },\n assigneeRole,\n threadsMin: 1,\n threadsMax: 1,\n approvalLine: outlierApprovalLine\n }\n\n const resolveActivityInstance = await issue(activityInstance, context)\n await tx.getRepository(DataOoc).update({ id: dataOoc.id }, { resolveActivityInstance })\n } else {\n console.error(\n `Assignees are not set. So, Data OOC Resolve task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`\n )\n }\n } else {\n console.error('OOC Resolve Activity not installed.')\n }\n}\n"]}
|
|
@@ -9,10 +9,13 @@ const data_ooc_js_1 = require("../service/data-ooc/data-ooc.js");
|
|
|
9
9
|
async function issueOocReview(dataOoc, dataSet, context) {
|
|
10
10
|
const { domain, tx } = context.state;
|
|
11
11
|
const { collectedAt } = dataOoc;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
var activities = await tx.getRepository(worklist_1.Activity).find({
|
|
13
|
+
where: {
|
|
14
|
+
domain: domain.parentId ? (0, typeorm_1.In)([domain.id, domain.parentId]) : { id: domain.id },
|
|
15
|
+
name: 'OOC Review'
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
var activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId);
|
|
16
19
|
if (activity) {
|
|
17
20
|
const assigneeRole = dataSet.supervisoryRoleId &&
|
|
18
21
|
(await tx.getRepository(auth_base_1.Role).findOneBy({
|
|
@@ -33,8 +36,8 @@ async function issueOocReview(dataOoc, dataSet, context) {
|
|
|
33
36
|
threadsMax: 1,
|
|
34
37
|
approvalLine: []
|
|
35
38
|
};
|
|
36
|
-
|
|
37
|
-
await tx.getRepository(data_ooc_js_1.DataOoc).
|
|
39
|
+
const reviewActivityInstance = await (0, issue_1.issue)(activityInstance, context);
|
|
40
|
+
await tx.getRepository(data_ooc_js_1.DataOoc).update({ id: dataOoc.id }, { reviewActivityInstance });
|
|
38
41
|
}
|
|
39
42
|
else {
|
|
40
43
|
console.error(`Assignees are not set. So Data OOC Review task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"issue-ooc-review.js","sourceRoot":"","sources":["../../server/controllers/issue-ooc-review.ts"],"names":[],"mappings":";;AASA,
|
|
1
|
+
{"version":3,"file":"issue-ooc-review.js","sourceRoot":"","sources":["../../server/controllers/issue-ooc-review.ts"],"names":[],"mappings":";;AASA,wCA8CC;AAvDD,qCAA4B;AAE5B,yDAAgD;AAChD,uDAAmD;AACnD,oGAAgG;AAGhG,iEAAyD;AAElD,KAAK,UAAU,cAAc,CAAC,OAAgB,EAAE,OAAgB,EAAE,OAAwB;IAC/F,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;IACpC,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAA;IAE/B,IAAI,UAAU,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,mBAAQ,CAAC,CAAC,IAAI,CAAC;QACrD,KAAK,EAAE;YACL,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;YAC9E,IAAI,EAAE,YAAY;SACnB;KACF,CAAC,CAAA;IAEF,IAAI,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC,CAAA;IAErH,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,YAAY,GAChB,OAAO,CAAC,iBAAiB;YACzB,CAAC,MAAM,EAAE,CAAC,aAAa,CAAC,gBAAI,CAAC,CAAC,SAAS,CAAC;gBACtC,MAAM,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE;gBAChE,EAAE,EAAE,OAAO,CAAC,iBAAiB;aAC9B,CAAC,CAAC,CAAA;QAEL,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,gBAAgB,GAAG;gBACvB,IAAI,EAAE,YAAY,OAAO,CAAC,IAAI,EAAE;gBAChC,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,QAAQ,CAAC,EAAE;gBACvB,KAAK,EAAE,IAAI,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,YAAY,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;gBACvF,KAAK,EAAE;oBACL,SAAS,EAAE,OAAO,CAAC,EAAE;iBACtB;gBACD,YAAY;gBACZ,UAAU,EAAE,CAAC;gBACb,UAAU,EAAE,CAAC;gBACb,YAAY,EAAE,EAAE;aACjB,CAAA;YAED,MAAM,sBAAsB,GAAG,MAAM,IAAA,aAAK,EAAC,gBAAuB,EAAE,OAAO,CAAC,CAAA;YAC5E,MAAM,EAAE,CAAC,aAAa,CAAC,qBAAO,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,sBAAsB,EAAE,CAAC,CAAA;QACxF,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CACX,sDAAsD,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,wBAAwB,CACzG,CAAA;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;IACpD,CAAC;AACH,CAAC","sourcesContent":["import { In } from 'typeorm'\n\nimport { Role } from '@things-factory/auth-base'\nimport { Activity } from '@things-factory/worklist'\nimport { issue } from '@things-factory/worklist/dist-server/controllers/activity-instance/issue'\n\nimport { DataSet } from '../service/data-set/data-set.js'\nimport { DataOoc } from '../service/data-ooc/data-ooc.js'\n\nexport async function issueOocReview(dataOoc: DataOoc, dataSet: DataSet, context: ResolverContext): Promise<void> {\n const { domain, tx } = context.state\n const { collectedAt } = dataOoc\n\n var activities = await tx.getRepository(Activity).find({\n where: {\n domain: domain.parentId ? In([domain.id, domain.parentId]) : { id: domain.id },\n name: 'OOC Review'\n }\n })\n\n var activity = activities.find(a => a.domainId === domain.id) || activities.find(a => a.domainId === domain.parentId)\n\n if (activity) {\n const assigneeRole =\n dataSet.supervisoryRoleId &&\n (await tx.getRepository(Role).findOneBy({\n domain: { id: In([domain.id, domain.parentId].filter(Boolean)) },\n id: dataSet.supervisoryRoleId\n }))\n\n if (assigneeRole) {\n const activityInstance = {\n name: `[OOC 검토] ${dataSet.name}`,\n description: dataSet.description,\n activityId: activity.id,\n dueAt: new Date(collectedAt.getTime() + (activity.standardTime || 24 * 60 * 60) * 1000),\n input: {\n dataOocId: dataOoc.id\n },\n assigneeRole,\n threadsMin: 1,\n threadsMax: 1,\n approvalLine: []\n }\n\n const reviewActivityInstance = await issue(activityInstance as any, context)\n await tx.getRepository(DataOoc).update({ id: dataOoc.id }, { reviewActivityInstance })\n } else {\n console.error(\n `Assignees are not set. So Data OOC Review task for ${dataOoc.name}(${dataOoc.id}) could not be issued.`\n )\n }\n } else {\n console.warn('OOC Review Activity not installed.')\n }\n}\n"]}
|