@things-factory/reference-app 5.0.0-zeta.9 → 5.0.2
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/bootstrap.js +10 -10
- package/client/components/ocr-viewpart.js +1 -1
- package/client/editors/id-selector.js +1 -1
- package/client/menu.js +10 -5
- package/client/pages/data-entry/data-entry-form.js +117 -0
- package/client/pages/data-entry/data-entry-generator-popup.js +110 -0
- package/client/pages/data-set/data-item-list.js +277 -0
- package/client/pages/data-set/data-set-importer.js +103 -0
- package/client/pages/data-set/data-set-list-page.js +738 -0
- package/client/pages/ocr-page.js +1 -1
- package/client/pages/operation/operation-api.js +85 -0
- package/client/pages/operation/operation-master.js +432 -0
- package/client/pages/pending-job-page.js +1 -1
- package/client/pages/product/product-api.js +150 -0
- package/client/pages/product/product-master.js +888 -0
- package/client/pages/product-combination-settings-popup.js +395 -0
- package/client/pages/product-combinations-popup.js +372 -0
- package/client/pages/product-details-popup.js +744 -0
- package/client/pages/upload-page.js +1 -1
- package/client/route.js +12 -0
- package/db.sqlite +0 -0
- package/dist-server/constants/index.js +18 -0
- package/dist-server/constants/index.js.map +1 -0
- package/dist-server/constants/type-constants.js +26 -0
- package/dist-server/constants/type-constants.js.map +1 -0
- package/dist-server/controllers/create-data-sample-mockup.js +236 -0
- package/dist-server/controllers/create-data-sample-mockup.js.map +1 -0
- package/dist-server/controllers/index.js +17 -0
- package/dist-server/controllers/index.js.map +1 -1
- package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js +40 -0
- package/dist-server/service/data-sample-mockup/data-sample-mockup-mutation.js.map +1 -0
- package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js +28 -0
- package/dist-server/service/data-sample-mockup/data-sample-mockup-type.js.map +1 -0
- package/dist-server/service/data-sample-mockup/index.js +7 -0
- package/dist-server/service/data-sample-mockup/index.js.map +1 -0
- package/dist-server/service/index.js +5 -2
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/reference/reference-mutation.js +7 -3
- package/dist-server/service/reference/reference-mutation.js.map +1 -1
- package/dist-server/service/reference/reference-query.js +8 -4
- package/dist-server/service/reference/reference-query.js.map +1 -1
- package/logs/.08636eb59927f12972f6774f5947c8507b3564c2-audit.json +3 -28
- package/logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json +18 -48
- package/logs/application-2022-07-22-10.log +26 -0
- package/logs/{connections-2022-06-26-22.log → connections-2022-07-12-00.log} +0 -0
- package/logs/{connections-2022-06-26-23.log → connections-2022-07-14-14.log} +0 -0
- package/logs/{connections-2022-06-27-00.log → connections-2022-07-14-15.log} +0 -0
- package/logs/{connections-2022-06-28-21.log → connections-2022-07-14-16.log} +0 -0
- package/logs/{connections-2022-06-28-22.log → connections-2022-07-14-17.log} +0 -0
- package/logs/{connections-2022-06-29-08.log → connections-2022-07-22-10.log} +0 -0
- package/package.json +58 -56
- package/server/constants/index.ts +1 -0
- package/server/constants/type-constants.ts +24 -0
- package/server/controllers/create-data-sample-mockup.ts +268 -0
- package/server/controllers/index.ts +1 -0
- package/server/service/data-sample-mockup/data-sample-mockup-mutation.ts +18 -0
- package/server/service/data-sample-mockup/data-sample-mockup-type.ts +10 -0
- package/server/service/data-sample-mockup/index.ts +4 -0
- package/server/service/index.ts +5 -2
- package/server/service/reference/reference-mutation.ts +6 -3
- package/server/service/reference/reference-query.ts +9 -7
- package/things-factory.config.js +8 -0
- package/translations/en.json +6 -1
- package/translations/ko.json +7 -1
- package/logs/application-2022-06-28-21.log +0 -30
- package/logs/application-2022-06-28-22.log +0 -15
- package/logs/application-2022-06-29-08.log +0 -12
- package/logs/application-2022-06-29-09.log +0 -12
- package/logs/application-2022-06-29-10.log +0 -4
- package/logs/application-2022-06-29-12.log +0 -4
- package/logs/connections-2022-06-29-09.log +0 -0
- package/logs/connections-2022-06-29-10.log +0 -0
- package/logs/connections-2022-06-29-12.log +0 -0
|
@@ -6,64 +6,34 @@
|
|
|
6
6
|
"auditLog": "logs/.5e5d741d8b7784a2fbad65eedc0fd46946aaf6f2-audit.json",
|
|
7
7
|
"files": [
|
|
8
8
|
{
|
|
9
|
-
"date":
|
|
10
|
-
"name": "logs/connections-2022-
|
|
11
|
-
"hash": "
|
|
9
|
+
"date": 1657552236185,
|
|
10
|
+
"name": "logs/connections-2022-07-12-00.log",
|
|
11
|
+
"hash": "a32352468fe215d00f4c3726ad01e9414e4fd27205351af763cbfaa84546c7e8"
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
|
-
"date":
|
|
15
|
-
"name": "logs/connections-2022-
|
|
16
|
-
"hash": "
|
|
14
|
+
"date": 1657777492666,
|
|
15
|
+
"name": "logs/connections-2022-07-14-14.log",
|
|
16
|
+
"hash": "815013b26e333439f322a350e69bf48b503ff758205f45353b93f87f39f25c57"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"date":
|
|
20
|
-
"name": "logs/connections-2022-
|
|
21
|
-
"hash": "
|
|
19
|
+
"date": 1657778421667,
|
|
20
|
+
"name": "logs/connections-2022-07-14-15.log",
|
|
21
|
+
"hash": "f2a58d6d8922050168fca5805f86020162ac09d8d5fdaa82d3e1680695a67e30"
|
|
22
22
|
},
|
|
23
23
|
{
|
|
24
|
-
"date":
|
|
25
|
-
"name": "logs/connections-2022-
|
|
26
|
-
"hash": "
|
|
24
|
+
"date": 1657782207073,
|
|
25
|
+
"name": "logs/connections-2022-07-14-16.log",
|
|
26
|
+
"hash": "91c2de4b81560f62a3f4b66b0c7aaa3eb5903b8b68f2cb8faba52c2267f30584"
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
|
-
"date":
|
|
30
|
-
"name": "logs/connections-2022-
|
|
31
|
-
"hash": "
|
|
29
|
+
"date": 1657786119337,
|
|
30
|
+
"name": "logs/connections-2022-07-14-17.log",
|
|
31
|
+
"hash": "1b67797b50ccf90a96105835d3a2bf871678063e58a785c1948c797db5caeae8"
|
|
32
32
|
},
|
|
33
33
|
{
|
|
34
|
-
"date":
|
|
35
|
-
"name": "logs/connections-2022-
|
|
36
|
-
"hash": "
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
"date": 1656418966951,
|
|
40
|
-
"name": "logs/connections-2022-06-28-21.log",
|
|
41
|
-
"hash": "21c0c18ae8055601c1c31eacd85dda92915166a4da4e40b7152d8b035b4e71e2"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"date": 1656421278851,
|
|
45
|
-
"name": "logs/connections-2022-06-28-22.log",
|
|
46
|
-
"hash": "6da9a43325b4d224a68974120143adf8328ece2551afc421f52233bc8f6e5553"
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
"date": 1656459528243,
|
|
50
|
-
"name": "logs/connections-2022-06-29-08.log",
|
|
51
|
-
"hash": "e648257303d766b5c5ec2c6be6f802c1115232d7d5d4c424451eecceb5844a3d"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"date": 1656460848585,
|
|
55
|
-
"name": "logs/connections-2022-06-29-09.log",
|
|
56
|
-
"hash": "b69f133c7e8470b9241ce66b2c4e14afdb43efe47cf3bfbfbe5e368f2e9f6b09"
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
"date": 1656465102433,
|
|
60
|
-
"name": "logs/connections-2022-06-29-10.log",
|
|
61
|
-
"hash": "c9f9844ac598ba664064fc3c5e69ed05bbcc58cd2d961291dbc8e60bd7669690"
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
"date": 1656471924737,
|
|
65
|
-
"name": "logs/connections-2022-06-29-12.log",
|
|
66
|
-
"hash": "63d5164fb2ea63d96b2b41879b0c300bed3b480839c69a6dfe162d2c06217682"
|
|
34
|
+
"date": 1658452553880,
|
|
35
|
+
"name": "logs/connections-2022-07-22-10.log",
|
|
36
|
+
"hash": "148e96bfa4cf9866bd7cdcdbc546b4bfdab27e9807076c6ef11c17c1d0895c5a"
|
|
67
37
|
}
|
|
68
38
|
],
|
|
69
39
|
"hashType": "sha256"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
2022-07-22T10:15:52+09:00 info: File Storage is Ready.
|
|
2
|
+
2022-07-22T10:15:57+09:00 error: connect ECONNREFUSED 127.0.0.1:5432
|
|
3
|
+
2022-07-22T10:15:58+09:00 info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
4
|
+
2022-07-22T10:15:58+09:00 info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/graphql
|
|
5
|
+
2022-07-22T10:16:03+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
6
|
+
2022-07-22T10:16:09+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
7
|
+
2022-07-22T10:16:15+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
8
|
+
2022-07-22T10:16:22+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
9
|
+
2022-07-22T10:16:27+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
10
|
+
2022-07-22T10:16:35+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
11
|
+
2022-07-22T10:16:40+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
12
|
+
2022-07-22T10:16:46+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
13
|
+
2022-07-22T10:16:52+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
14
|
+
2022-07-22T10:16:59+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
15
|
+
2022-07-22T10:17:08+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
16
|
+
2022-07-22T10:17:23+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
17
|
+
2022-07-22T10:17:28+09:00 error: No repository for "Domain" was found. Looks like this entity is not registered in current "default" connection?
|
|
18
|
+
2022-07-22T10:18:30+09:00 info: File Storage is Ready.
|
|
19
|
+
2022-07-22T10:18:36+09:00 info: Database connection established
|
|
20
|
+
2022-07-22T10:18:37+09:00 info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
21
|
+
2022-07-22T10:18:37+09:00 info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/graphql
|
|
22
|
+
2022-07-22T10:25:36+09:00 error: update or delete on table "data_sets" violates foreign key constraint "FK_823511ff4d34651925528ec2863" on table "data_samples"
|
|
23
|
+
2022-07-22T10:38:39+09:00 info: File Storage is Ready.
|
|
24
|
+
2022-07-22T10:38:49+09:00 info: Database connection established
|
|
25
|
+
2022-07-22T10:38:52+09:00 info: 🚀 Server ready at http://0.0.0.0:3000/graphql
|
|
26
|
+
2022-07-22T10:38:52+09:00 info: 🚀 Subscriptions ready at ws://0.0.0.0:3000/graphql
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/reference-app",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -37,62 +37,64 @@
|
|
|
37
37
|
"docker:run": "docker run -it -p 4000:3000 hatiolab/reference-app:latest"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"@
|
|
42
|
-
"@operato/
|
|
43
|
-
"@operato/
|
|
44
|
-
"@operato/
|
|
45
|
-
"@operato/
|
|
46
|
-
"@operato/
|
|
47
|
-
"@operato/
|
|
48
|
-
"@operato/
|
|
49
|
-
"@operato/
|
|
50
|
-
"@operato/
|
|
51
|
-
"@operato/
|
|
52
|
-
"@operato/
|
|
53
|
-
"@operato/scene-
|
|
54
|
-
"@operato/scene-
|
|
55
|
-
"@operato/scene-
|
|
56
|
-
"@operato/scene-
|
|
57
|
-
"@operato/scene-
|
|
58
|
-
"@operato/scene-
|
|
59
|
-
"@operato/scene-
|
|
60
|
-
"@operato/scene-
|
|
61
|
-
"@operato/scene-
|
|
62
|
-
"@operato/scene-
|
|
63
|
-
"@operato/
|
|
64
|
-
"@operato/
|
|
65
|
-
"@
|
|
66
|
-
"@things-factory/
|
|
67
|
-
"@things-factory/
|
|
68
|
-
"@things-factory/
|
|
69
|
-
"@things-factory/
|
|
70
|
-
"@things-factory/board-
|
|
71
|
-
"@things-factory/
|
|
72
|
-
"@things-factory/
|
|
73
|
-
"@things-factory/
|
|
74
|
-
"@things-factory/
|
|
75
|
-
"@things-factory/
|
|
76
|
-
"@things-factory/export-ui": "^5.0.
|
|
77
|
-
"@things-factory/
|
|
78
|
-
"@things-factory/
|
|
79
|
-
"@things-factory/
|
|
80
|
-
"@things-factory/
|
|
81
|
-
"@things-factory/
|
|
82
|
-
"@things-factory/
|
|
83
|
-
"@things-factory/
|
|
84
|
-
"@things-factory/
|
|
85
|
-
"@things-factory/
|
|
86
|
-
"@things-factory/qc": "^5.0.
|
|
87
|
-
"@things-factory/resource-ui": "^5.0.
|
|
88
|
-
"@things-factory/
|
|
89
|
-
"@things-factory/setting-
|
|
90
|
-
"@things-factory/
|
|
91
|
-
"@things-factory/
|
|
92
|
-
"@things-factory/
|
|
40
|
+
"@material/mwc-checkbox": "^0.26.1",
|
|
41
|
+
"@operato/barcode": "^1.0.0",
|
|
42
|
+
"@operato/data-grist": "^1.0.1",
|
|
43
|
+
"@operato/ghost-print": "^1.0.0",
|
|
44
|
+
"@operato/graphql": "^1.0.0",
|
|
45
|
+
"@operato/help": "^1.0.1",
|
|
46
|
+
"@operato/i18n": "^1.0.0",
|
|
47
|
+
"@operato/input": "^1.0.1",
|
|
48
|
+
"@operato/layout": "^1.0.1",
|
|
49
|
+
"@operato/ocr": "^1.0.0",
|
|
50
|
+
"@operato/popup": "^1.0.0",
|
|
51
|
+
"@operato/pull-to-refresh": "^1.0.0",
|
|
52
|
+
"@operato/scene-chartjs": "^1.0.0",
|
|
53
|
+
"@operato/scene-clock": "^1.0.0",
|
|
54
|
+
"@operato/scene-form": "^1.0.0",
|
|
55
|
+
"@operato/scene-gauge": "^1.0.0",
|
|
56
|
+
"@operato/scene-half-roundrect": "^1.0.0",
|
|
57
|
+
"@operato/scene-indoor-map": "^1.0.0",
|
|
58
|
+
"@operato/scene-news-ticker": "^1.0.0",
|
|
59
|
+
"@operato/scene-progressbar": "^1.0.0",
|
|
60
|
+
"@operato/scene-random": "^1.0.0",
|
|
61
|
+
"@operato/scene-switch": "^1.0.0",
|
|
62
|
+
"@operato/scene-tab": "^1.0.0",
|
|
63
|
+
"@operato/shell": "^1.0.1",
|
|
64
|
+
"@operato/utils": "^1.0.1",
|
|
65
|
+
"@things-factory/api": "^5.0.1",
|
|
66
|
+
"@things-factory/apptool-ui": "^5.0.1",
|
|
67
|
+
"@things-factory/attachment-base": "^5.0.2",
|
|
68
|
+
"@things-factory/auth-ui": "^5.0.1",
|
|
69
|
+
"@things-factory/board-service": "^5.0.2",
|
|
70
|
+
"@things-factory/board-ui": "^5.0.1",
|
|
71
|
+
"@things-factory/ccp": "^5.0.2",
|
|
72
|
+
"@things-factory/context-ui": "^5.0.1",
|
|
73
|
+
"@things-factory/dashboard": "^5.0.2",
|
|
74
|
+
"@things-factory/dataset": "^5.0.2",
|
|
75
|
+
"@things-factory/export-ui": "^5.0.1",
|
|
76
|
+
"@things-factory/export-ui-excel": "^5.0.1",
|
|
77
|
+
"@things-factory/grist-ui": "^5.0.1",
|
|
78
|
+
"@things-factory/help": "^5.0.1",
|
|
79
|
+
"@things-factory/integration-ui": "^5.0.1",
|
|
80
|
+
"@things-factory/lite-menu": "^5.0.2",
|
|
81
|
+
"@things-factory/more-ui": "^5.0.1",
|
|
82
|
+
"@things-factory/notification": "^5.0.1",
|
|
83
|
+
"@things-factory/oauth2-client": "^5.0.1",
|
|
84
|
+
"@things-factory/print-ui": "^5.0.1",
|
|
85
|
+
"@things-factory/product-base": "^5.0.2",
|
|
86
|
+
"@things-factory/qc": "^5.0.2",
|
|
87
|
+
"@things-factory/resource-ui": "^5.0.1",
|
|
88
|
+
"@things-factory/routing-base": "^5.0.2",
|
|
89
|
+
"@things-factory/setting-base": "^5.0.1",
|
|
90
|
+
"@things-factory/setting-ui": "^5.0.1",
|
|
91
|
+
"@things-factory/shell": "^5.0.1",
|
|
92
|
+
"@things-factory/system-ui": "^5.0.1",
|
|
93
|
+
"@things-factory/work-shift": "^5.0.1",
|
|
94
|
+
"random-words": "^1.2.0"
|
|
93
95
|
},
|
|
94
96
|
"devDependencies": {
|
|
95
|
-
"@things-factory/builder": "^5.0.0
|
|
97
|
+
"@things-factory/builder": "^5.0.0"
|
|
96
98
|
},
|
|
97
|
-
"gitHead": "
|
|
99
|
+
"gitHead": "009cda6cb65e0930988fb2b1c1a309b9a7973383"
|
|
98
100
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './type-constants'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Inventory Type
|
|
3
|
+
*/
|
|
4
|
+
export const ROH_INVENTORY = 'ROH'
|
|
5
|
+
export const FINISHED_INVENTORY = 'FINISHED'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Product Type
|
|
9
|
+
*/
|
|
10
|
+
export const PRODUCT_TYPE = {
|
|
11
|
+
FERT: '완제품',
|
|
12
|
+
HALB: '반제품',
|
|
13
|
+
ROH: '원자재'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Warehouse Type
|
|
18
|
+
*/
|
|
19
|
+
export const WAREHOUSE_TYPE = {
|
|
20
|
+
FINISHED: '완제품',
|
|
21
|
+
HALF_COLD: '반제품(냉장)',
|
|
22
|
+
HALF_FROZEN: '반제품(냉동)',
|
|
23
|
+
ROH: '원자재'
|
|
24
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import moment from 'moment-timezone'
|
|
2
|
+
import { EntityManager } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { User } from '@things-factory/auth-base'
|
|
5
|
+
import { DataSet, DataSample, DataUseCase } from '@things-factory/dataset'
|
|
6
|
+
import { Product } from '@things-factory/product-base'
|
|
7
|
+
import { Operation } from '@things-factory/routing-base'
|
|
8
|
+
import { Domain } from '@things-factory/shell'
|
|
9
|
+
import { getWorkDateAndShift } from '@things-factory/work-shift'
|
|
10
|
+
|
|
11
|
+
import { DataSampleMockupInfo } from '../service/data-sample-mockup/data-sample-mockup-type'
|
|
12
|
+
|
|
13
|
+
const randomWords = require('random-words')
|
|
14
|
+
const debug = require('debug')('things-factory:reference-app:controller/create-data-sample-mockup')
|
|
15
|
+
|
|
16
|
+
// parse variable javascript string pattern
|
|
17
|
+
const replaceVariables = (keys, dic) => {
|
|
18
|
+
for (const k in keys) {
|
|
19
|
+
const matches = keys[k].match(/\$\{\w*\}/g)
|
|
20
|
+
matches &&
|
|
21
|
+
matches.forEach(m => {
|
|
22
|
+
keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
return keys
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// It is required UTC date for Partitioning File System like AWS S3 from Athena.
|
|
29
|
+
// ex) %YYYY, %MM, %DD
|
|
30
|
+
const formatDate = (keys, _moment) => {
|
|
31
|
+
for (const k in keys) {
|
|
32
|
+
const matches = keys[k].match(/%\w*/g)
|
|
33
|
+
matches &&
|
|
34
|
+
matches.forEach(m => {
|
|
35
|
+
keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
return keys
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Normal Distribution
|
|
43
|
+
* https://stackoverflow.com/questions/25582882/javascript-math-random-normal-distribution-gaussian-bell-curve
|
|
44
|
+
*/
|
|
45
|
+
function normal_dist(min, max, skew) {
|
|
46
|
+
let u = 0, v = 0;
|
|
47
|
+
while(u === 0) u = Math.random() //Converting [0,1) to (0,1)
|
|
48
|
+
while(v === 0) v = Math.random()
|
|
49
|
+
let num = Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )
|
|
50
|
+
|
|
51
|
+
num = num / 10.0 + 0.5 // Translate to 0 -> 1
|
|
52
|
+
if (num > 1 || num < 0)
|
|
53
|
+
num = normal_dist(min, max, skew) // resample between 0 and 1 if out of range
|
|
54
|
+
|
|
55
|
+
else{
|
|
56
|
+
num = Math.pow(num, skew) // Skew
|
|
57
|
+
num *= max - min // Stretch to fill range
|
|
58
|
+
num += min // offset to min
|
|
59
|
+
}
|
|
60
|
+
return num
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function randomIndex(max = 2) {
|
|
64
|
+
return Math.floor(Math.random() * max)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function fillColumns(prev, next, dict) {
|
|
68
|
+
let values = []
|
|
69
|
+
try {
|
|
70
|
+
const gap = 20
|
|
71
|
+
const timeFormat = 'HH:mm'
|
|
72
|
+
const dateFormat = 'YYYY-MM-DD'
|
|
73
|
+
const atFormat = 'YYYY-MM-DD HH:mm:ss'
|
|
74
|
+
const now = moment()
|
|
75
|
+
const { type, spec, quota } = next
|
|
76
|
+
const isValidSpec = spec && Object.keys(spec).length
|
|
77
|
+
const arr = Array.from(Array(quota).keys())
|
|
78
|
+
|
|
79
|
+
if(type == 'number') {
|
|
80
|
+
if (isValidSpec) { /* generate values refer to spec info. */
|
|
81
|
+
const { CCP: { criticalLimits: { minimum, maximum } } } = spec
|
|
82
|
+
while (values.length < quota) {
|
|
83
|
+
let value = 0
|
|
84
|
+
if (typeof minimum === 'number' && typeof maximum === 'number') {
|
|
85
|
+
value = Math.floor(normal_dist(minimum, maximum, 1))
|
|
86
|
+
} else if (typeof minimum === 'number' && typeof maximum !== 'number') {
|
|
87
|
+
const max = minimum + gap
|
|
88
|
+
value = Math.floor(normal_dist(minimum, max, 1))
|
|
89
|
+
} else if (typeof minimum !== 'number' && typeof maximum === 'number') {
|
|
90
|
+
const min = maximum - gap
|
|
91
|
+
value = Math.floor(normal_dist(min, maximum, 1))
|
|
92
|
+
}
|
|
93
|
+
values.push(value)
|
|
94
|
+
}
|
|
95
|
+
} else { /* random number */
|
|
96
|
+
const p = Math.random()
|
|
97
|
+
const q = () => randomIndex(10) + 1
|
|
98
|
+
// fixed
|
|
99
|
+
if (p > 0.33) {
|
|
100
|
+
values = Array(quota).fill(q())
|
|
101
|
+
} else if(p > 0.66) { /* or random */
|
|
102
|
+
values = arr.map(i => q())
|
|
103
|
+
|
|
104
|
+
} else { /* or incremental */
|
|
105
|
+
values = arr.reduce((prev, i) => {
|
|
106
|
+
prev.push(!!prev.length ? prev[0] + i: q())
|
|
107
|
+
return prev
|
|
108
|
+
}, [])
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} else if (type == 'select') {
|
|
112
|
+
const options = next['options']['options']
|
|
113
|
+
values = arr.map(i => options[randomIndex(options.length)]['value'])
|
|
114
|
+
} else if (type == 'boolean') {
|
|
115
|
+
values = arr.map(i => !!randomIndex())
|
|
116
|
+
} else if (next['tag'].toLowerCase().indexOf('time') >= 0) {
|
|
117
|
+
/* ex) startTime => 09:21 */
|
|
118
|
+
arr.reduce(curr => {
|
|
119
|
+
values.push(curr.format(timeFormat))
|
|
120
|
+
curr.add(randomIndex(60), 'minutes')
|
|
121
|
+
return curr
|
|
122
|
+
}, now)
|
|
123
|
+
} else if (next['tag'].indexOf('edAt') > 0) {
|
|
124
|
+
/* ex) createdAt => '2022-06-15 09:21:30 */
|
|
125
|
+
arr.reduce(curr => {
|
|
126
|
+
values.push(curr.format(atFormat))
|
|
127
|
+
curr.add(randomIndex(12), 'hours')
|
|
128
|
+
return curr
|
|
129
|
+
}, now)
|
|
130
|
+
} else if (next['tag'].toLowerCase().indexOf('date') > 0) {
|
|
131
|
+
/* ex) startDate => '2022-06-15 */
|
|
132
|
+
arr.reduce(curr => {
|
|
133
|
+
values.push(curr.format(dateFormat))
|
|
134
|
+
curr.add(randomIndex(7), 'days')
|
|
135
|
+
return curr
|
|
136
|
+
}, now)
|
|
137
|
+
} else if (dict.hasOwnProperty(next['tag'])) {
|
|
138
|
+
values = Array(quota).fill(dict[next['tag']])
|
|
139
|
+
} else {
|
|
140
|
+
if (type == 'text') {
|
|
141
|
+
values = randomWords(quota)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
} finally {
|
|
145
|
+
prev[next['tag']] = values
|
|
146
|
+
return prev
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
async function _generateMockupData(dataSources:any, tx:EntityManager) {
|
|
151
|
+
const { user, domain, dataSet, spec, products, operations } = dataSources
|
|
152
|
+
|
|
153
|
+
const collectedAt = new Date()
|
|
154
|
+
|
|
155
|
+
const timezone = dataSet.timezone || domain.timezone || 'UTC'
|
|
156
|
+
const format = 'YYYY-MM-DD'
|
|
157
|
+
|
|
158
|
+
// workDate ex) 2022-04-04
|
|
159
|
+
const { workDate, workShift } = await getWorkDateAndShift(domain, collectedAt, { timezone, format })
|
|
160
|
+
|
|
161
|
+
// local time dataSet timezone or domain timezone or default 'UTC'
|
|
162
|
+
|
|
163
|
+
// const collectedAt = dataSample.collectedAt || new Date()
|
|
164
|
+
const localDateTz = moment(collectedAt).tz(timezone)
|
|
165
|
+
const defaultPartitionKeys = {
|
|
166
|
+
domain: domain.subdomain,
|
|
167
|
+
datasetid: dataSet.id, /* It should not be 'data_set_id' as column name duplicated for Glue */
|
|
168
|
+
date: localDateTz.format(format), /* local time date */
|
|
169
|
+
workdate: workDate, /* working date */
|
|
170
|
+
workshift: workShift
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
var partitionKeys = {
|
|
174
|
+
...defaultPartitionKeys,
|
|
175
|
+
...dataSet.partitionKeys
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// get product, operation as a map
|
|
179
|
+
const oper = operations[Math.floor(Math.random() * operations.length)]
|
|
180
|
+
const prod = products[Math.floor(Math.random() * products.length)]
|
|
181
|
+
const dict = {
|
|
182
|
+
operation: oper['name'],
|
|
183
|
+
operationId: oper['id'],
|
|
184
|
+
product: prod['name'],
|
|
185
|
+
productId: prod['id']
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const sample = dataSet.dataItems.reduce((prev, next) => fillColumns(prev, next, dict), {})
|
|
189
|
+
debug('sample', sample)
|
|
190
|
+
|
|
191
|
+
partitionKeys = formatDate(partitionKeys, localDateTz)
|
|
192
|
+
partitionKeys = replaceVariables(partitionKeys, {
|
|
193
|
+
...sample
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const { ooc, oos, judgment } = DataUseCase.evaluate(dataSet, dataSet.dataItems, sample) || {}
|
|
197
|
+
const result = await tx.getRepository(DataSample).save({
|
|
198
|
+
name: dataSet.name,
|
|
199
|
+
description: dataSet.description,
|
|
200
|
+
useCase: dataSet.useCase,
|
|
201
|
+
dataSet: dataSet,
|
|
202
|
+
dataSetVersion: dataSet.version,
|
|
203
|
+
data: sample,
|
|
204
|
+
domain,
|
|
205
|
+
partitionKeys,
|
|
206
|
+
spec,
|
|
207
|
+
ooc,
|
|
208
|
+
oos,
|
|
209
|
+
judgment,
|
|
210
|
+
collectedAt,
|
|
211
|
+
workDate,
|
|
212
|
+
workShift,
|
|
213
|
+
creator: user,
|
|
214
|
+
updater: user
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
return true
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export async function generateMockupData(
|
|
221
|
+
params: DataSampleMockupInfo,
|
|
222
|
+
context: {
|
|
223
|
+
state: {
|
|
224
|
+
domain: Domain
|
|
225
|
+
user: User
|
|
226
|
+
tx: EntityManager
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
): Promise<Boolean> {
|
|
230
|
+
const { domain, user, tx } = context.state
|
|
231
|
+
|
|
232
|
+
const dataSet: DataSet = await tx.getRepository(DataSet).findOne({
|
|
233
|
+
where: { id: params.dataSetId }
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
const products = await tx.getRepository(Product).find({
|
|
237
|
+
select: [ 'id', 'name', 'description' ],
|
|
238
|
+
where: {
|
|
239
|
+
domain
|
|
240
|
+
}
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
const operations = await tx.getRepository(Operation).find({
|
|
244
|
+
select: [ 'id', 'name', 'description' ],
|
|
245
|
+
where: {
|
|
246
|
+
domain
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
const dataItems = dataSet.dataItems
|
|
251
|
+
|
|
252
|
+
const spec = dataItems.reduce((spec, dataItem) => {
|
|
253
|
+
spec[dataItem.tag] = {
|
|
254
|
+
...dataItem.spec,
|
|
255
|
+
name: dataItem.name, /* do we need ? */
|
|
256
|
+
hidden: dataItem.hidden
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
return spec
|
|
260
|
+
}, {})
|
|
261
|
+
|
|
262
|
+
const promises = Array(params.numSamples).fill(0).map(x => {
|
|
263
|
+
return _generateMockupData({ domain, user, dataSet, products, operations, spec }, tx)
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
await Promise.all(promises)
|
|
267
|
+
return true
|
|
268
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './create-data-sample-mockup'
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { DataSample } from '@things-factory/dataset'
|
|
4
|
+
|
|
5
|
+
import { generateMockupData } from '../../controllers/create-data-sample-mockup'
|
|
6
|
+
import { DataSampleMockupInfo } from './data-sample-mockup-type'
|
|
7
|
+
|
|
8
|
+
const debug = require('debug')('things-factory:dataset:data-sample:data-sample-mutation')
|
|
9
|
+
|
|
10
|
+
@Resolver(DataSample)
|
|
11
|
+
export class DataSampleMockupMutation {
|
|
12
|
+
@Directive('@privilege(category: "data-sample", privilege: "mutation", domainOwnerGranted: true)')
|
|
13
|
+
@Directive('@transaction')
|
|
14
|
+
@Mutation(returns => Boolean, { description: 'To generate data sample one' })
|
|
15
|
+
async generateMockupData(@Arg('params') params: DataSampleMockupInfo, @Ctx() context: any): Promise<Boolean> {
|
|
16
|
+
return await generateMockupData(params, context)
|
|
17
|
+
}
|
|
18
|
+
}
|
package/server/service/index.ts
CHANGED
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
/* IMPORT ENTITIES AND RESOLVERS */
|
|
4
4
|
import { entities as ReferenceEntities, resolvers as ReferenceResolvers } from './reference'
|
|
5
|
+
import { entities as DataSampleMockupEntities, resolvers as DataSampleMockupMutation } from './data-sample-mockup'
|
|
5
6
|
|
|
6
7
|
export const entities = [
|
|
7
8
|
/* ENTITIES */
|
|
8
|
-
...ReferenceEntities
|
|
9
|
+
...ReferenceEntities,
|
|
10
|
+
...DataSampleMockupEntities
|
|
9
11
|
]
|
|
10
12
|
|
|
11
13
|
export const schema = {
|
|
12
14
|
resolverClasses: [
|
|
13
15
|
/* RESOLVER CLASSES */
|
|
14
|
-
...ReferenceResolvers
|
|
16
|
+
...ReferenceResolvers,
|
|
17
|
+
...DataSampleMockupMutation
|
|
15
18
|
]
|
|
16
19
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import type { FileUpload } from 'graphql-upload/GraphQLUpload.js'
|
|
2
|
+
import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
|
|
3
|
+
import { Arg, Ctx, Mutation, Resolver, Root } from 'type-graphql'
|
|
4
|
+
|
|
5
|
+
import { Attachment, createAttachments } from '@things-factory/attachment-base'
|
|
3
6
|
import { publishProgress } from '@things-factory/shell'
|
|
4
7
|
import { sleep } from '@things-factory/utils'
|
|
5
|
-
import { Attachment, createAttachments } from '@things-factory/attachment-base'
|
|
6
8
|
|
|
7
9
|
@Resolver()
|
|
8
10
|
export class ReferenceMutation {
|
|
@@ -20,6 +22,7 @@ export class ReferenceMutation {
|
|
|
20
22
|
const attachments: Attachment[] = files.map(attachment => {
|
|
21
23
|
return {
|
|
22
24
|
file: attachment,
|
|
25
|
+
refType: 'Reference',
|
|
23
26
|
refBy: 100,
|
|
24
27
|
category: 'Reference'
|
|
25
28
|
}
|