@things-factory/dataset 5.0.0-alpha.2 → 5.0.0-alpha.22

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.
Files changed (96) hide show
  1. package/README.md +13 -0
  2. package/assets/data-samples.jpg +0 -0
  3. package/client/bootstrap.js +16 -1
  4. package/client/pages/data-entry-form.js +84 -0
  5. package/client/pages/data-item-list.js +58 -16
  6. package/client/pages/data-ooc-view.js +182 -0
  7. package/client/pages/data-ooc.js +487 -0
  8. package/client/pages/data-sample-view.js +97 -0
  9. package/client/pages/data-sample.js +149 -56
  10. package/client/pages/data-sensor.js +8 -18
  11. package/client/pages/data-set.js +200 -75
  12. package/client/route.js +4 -0
  13. package/dist-server/controllers/create-data-sample.js +124 -0
  14. package/dist-server/controllers/create-data-sample.js.map +1 -0
  15. package/dist-server/controllers/data-use-case.js +57 -0
  16. package/dist-server/controllers/data-use-case.js.map +1 -0
  17. package/dist-server/controllers/index.js +17 -0
  18. package/dist-server/controllers/index.js.map +1 -1
  19. package/dist-server/index.js +2 -0
  20. package/dist-server/index.js.map +1 -1
  21. package/dist-server/routes.js +9 -24
  22. package/dist-server/routes.js.map +1 -1
  23. package/dist-server/service/data-item/data-item-mutation.js +5 -1
  24. package/dist-server/service/data-item/data-item-mutation.js.map +1 -1
  25. package/dist-server/service/data-item/data-item-type.js +14 -5
  26. package/dist-server/service/data-item/data-item-type.js.map +1 -1
  27. package/dist-server/service/data-item/data-item.js +20 -7
  28. package/dist-server/service/data-item/data-item.js.map +1 -1
  29. package/dist-server/service/data-ooc/data-ooc-mutation.js +92 -0
  30. package/dist-server/service/data-ooc/data-ooc-mutation.js.map +1 -0
  31. package/dist-server/service/data-ooc/data-ooc-query.js +115 -0
  32. package/dist-server/service/data-ooc/data-ooc-query.js.map +1 -0
  33. package/dist-server/service/data-ooc/data-ooc-subscription.js +65 -0
  34. package/dist-server/service/data-ooc/data-ooc-subscription.js.map +1 -0
  35. package/dist-server/service/data-ooc/data-ooc-type.js +107 -0
  36. package/dist-server/service/data-ooc/data-ooc-type.js.map +1 -0
  37. package/dist-server/service/data-ooc/data-ooc.js +237 -0
  38. package/dist-server/service/data-ooc/data-ooc.js.map +1 -0
  39. package/dist-server/service/data-ooc/index.js +10 -0
  40. package/dist-server/service/data-ooc/index.js.map +1 -0
  41. package/dist-server/service/data-sample/data-sample-mutation.js +3 -105
  42. package/dist-server/service/data-sample/data-sample-mutation.js.map +1 -1
  43. package/dist-server/service/data-sample/data-sample-type.js +13 -42
  44. package/dist-server/service/data-sample/data-sample-type.js.map +1 -1
  45. package/dist-server/service/data-sample/data-sample.js +40 -9
  46. package/dist-server/service/data-sample/data-sample.js.map +1 -1
  47. package/dist-server/service/data-set/data-set-mutation.js +1 -2
  48. package/dist-server/service/data-set/data-set-mutation.js.map +1 -1
  49. package/dist-server/service/data-set/data-set-query.js +12 -0
  50. package/dist-server/service/data-set/data-set-query.js.map +1 -1
  51. package/dist-server/service/data-set/data-set-type.js +19 -2
  52. package/dist-server/service/data-set/data-set-type.js.map +1 -1
  53. package/dist-server/service/data-set/data-set.js +22 -10
  54. package/dist-server/service/data-set/data-set.js.map +1 -1
  55. package/dist-server/service/data-spec/data-spec-manager.js +20 -0
  56. package/dist-server/service/data-spec/data-spec-manager.js.map +1 -0
  57. package/dist-server/service/data-spec/data-spec-query.js +48 -0
  58. package/dist-server/service/data-spec/data-spec-query.js.map +1 -0
  59. package/dist-server/service/data-spec/data-spec.js +78 -0
  60. package/dist-server/service/data-spec/data-spec.js.map +1 -0
  61. package/dist-server/service/data-spec/index.js +8 -0
  62. package/dist-server/service/data-spec/index.js.map +1 -0
  63. package/dist-server/service/index.js +12 -4
  64. package/dist-server/service/index.js.map +1 -1
  65. package/package.json +15 -12
  66. package/server/controllers/create-data-sample.ts +166 -0
  67. package/server/controllers/data-use-case.ts +85 -0
  68. package/server/controllers/index.ts +1 -0
  69. package/server/index.ts +3 -0
  70. package/server/routes.ts +17 -31
  71. package/server/service/data-item/data-item-mutation.ts +6 -1
  72. package/server/service/data-item/data-item-type.ts +11 -7
  73. package/server/service/data-item/data-item.ts +16 -6
  74. package/server/service/data-ooc/data-ooc-mutation.ts +150 -0
  75. package/server/service/data-ooc/data-ooc-query.ts +63 -0
  76. package/server/service/data-ooc/data-ooc-subscription.ts +51 -0
  77. package/server/service/data-ooc/data-ooc-type.ts +68 -0
  78. package/server/service/data-ooc/data-ooc.ts +204 -0
  79. package/server/service/data-ooc/index.ts +7 -0
  80. package/server/service/data-sample/data-sample-mutation.ts +6 -128
  81. package/server/service/data-sample/data-sample-type.ts +8 -29
  82. package/server/service/data-sample/data-sample.ts +36 -6
  83. package/server/service/data-set/data-set-mutation.ts +1 -4
  84. package/server/service/data-set/data-set-query.ts +8 -1
  85. package/server/service/data-set/data-set-type.ts +17 -6
  86. package/server/service/data-set/data-set.ts +18 -8
  87. package/server/service/data-spec/data-spec-manager.ts +21 -0
  88. package/server/service/data-spec/data-spec-query.ts +21 -0
  89. package/server/service/data-spec/data-spec.ts +44 -0
  90. package/server/service/data-spec/index.ts +5 -0
  91. package/server/service/index.ts +16 -8
  92. package/things-factory.config.js +4 -0
  93. package/translations/en.json +21 -0
  94. package/translations/ko.json +22 -1
  95. package/translations/ms.json +21 -0
  96. package/translations/zh.json +21 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/dataset",
3
- "version": "5.0.0-alpha.2",
3
+ "version": "5.0.0-alpha.22",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -24,16 +24,19 @@
24
24
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
25
25
  },
26
26
  "dependencies": {
27
- "@operato/data-grist": "^0.4.3",
28
- "@operato/graphql": "^0.4.3",
29
- "@operato/i18n": "^0.4.3",
30
- "@operato/layout": "^0.4.3",
31
- "@operato/shell": "^0.4.3",
32
- "@operato/styles": "^0.4.3",
33
- "@operato/utils": "^0.4.3",
34
- "@things-factory/auth-base": "^5.0.0-alpha.2",
35
- "@things-factory/env": "^5.0.0-alpha.2",
36
- "@things-factory/shell": "^5.0.0-alpha.2"
27
+ "@operato/app": "1.0.0-alpha.45",
28
+ "@operato/data-grist": "1.0.0-alpha.45",
29
+ "@operato/dataset": "1.0.0-alpha.45",
30
+ "@operato/graphql": "1.0.0-alpha.45",
31
+ "@operato/i18n": "1.0.0-alpha.45",
32
+ "@operato/layout": "1.0.0-alpha.45",
33
+ "@operato/shell": "1.0.0-alpha.45",
34
+ "@operato/styles": "1.0.0-alpha.45",
35
+ "@operato/utils": "1.0.0-alpha.45",
36
+ "@things-factory/auth-base": "^5.0.0-alpha.22",
37
+ "@things-factory/env": "^5.0.0-alpha.22",
38
+ "@things-factory/shell": "^5.0.0-alpha.22",
39
+ "moment": "^2.29.1"
37
40
  },
38
- "gitHead": "055536f981d229d51ae63f46585036b35fa86602"
41
+ "gitHead": "8e06de9c59237f1800b2ff4f1c53162a0228342a"
39
42
  }
@@ -0,0 +1,166 @@
1
+ import moment from 'moment'
2
+ import { EntityManager } from 'typeorm'
3
+
4
+ import { User } from '@things-factory/auth-base'
5
+ import { Domain, getRedirectSubdomainPath, pubsub } from '@things-factory/shell'
6
+
7
+ import { DataItem } from '../service/data-item/data-item'
8
+ import { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc'
9
+ import { DataSample } from '../service/data-sample/data-sample'
10
+ import { NewDataSample } from '../service/data-sample/data-sample-type'
11
+ import { DataSet } from '../service/data-set/data-set'
12
+ import { DataUseCase } from './data-use-case'
13
+
14
+ const debug = require('debug')('things-factory:dataset:controller/save-data-sample')
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
+ export async function createDataSample(
42
+ dataSample: NewDataSample,
43
+ context: {
44
+ state: {
45
+ domain: Domain
46
+ user: User
47
+ tx: EntityManager
48
+ }
49
+ }
50
+ ): Promise<DataSample> {
51
+ const { domain, user, tx } = context.state
52
+
53
+ const dataSet = await tx.getRepository(DataSet).findOne({
54
+ where: { id: dataSample.dataSet.id }
55
+ })
56
+
57
+ const dataItems = await tx.getRepository(DataItem).find({
58
+ where: {
59
+ domain,
60
+ dataSet
61
+ },
62
+ order: {
63
+ sequence: 'DESC'
64
+ }
65
+ })
66
+
67
+ const spec = dataItems.reduce((spec, dataItem) => {
68
+ spec[dataItem.tag] = {
69
+ ...dataItem.spec,
70
+ name: dataItem.name /* do we need ? */
71
+ }
72
+
73
+ return spec
74
+ }, {})
75
+
76
+ const collectedAt = dataSample.collectedAt || new Date()
77
+ const momentUtc = moment(collectedAt).utc()
78
+ const defaultPartitionKeys = {
79
+ domain: domain.subdomain,
80
+ datasetid: dataSample.dataSet.id /* It should not be 'data_set_id' as column name duplicated for Glue */,
81
+ year: momentUtc.format('Y'),
82
+ month: momentUtc.format('M'),
83
+ day: momentUtc.format('D')
84
+ }
85
+
86
+ var partitionKeys = {
87
+ ...defaultPartitionKeys,
88
+ ...dataSet.partitionKeys
89
+ }
90
+
91
+ partitionKeys = formatDate(partitionKeys, momentUtc)
92
+ partitionKeys = replaceVariables(partitionKeys, {
93
+ ...dataSample.data
94
+ })
95
+
96
+ const { ooc, oos } = DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {}
97
+
98
+ const result = await tx.getRepository(DataSample).save({
99
+ name: dataSet.name,
100
+ description: dataSet.description,
101
+ useCase: dataSet.useCase,
102
+ ...dataSample,
103
+ domain,
104
+ partitionKeys,
105
+ spec,
106
+ ooc,
107
+ oos,
108
+ collectedAt,
109
+ workDate: momentUtc.format('YYYY-MM-DD'),
110
+ workShift: 'DAY',
111
+ creator: user,
112
+ updater: user
113
+ })
114
+
115
+ if (ooc || oos) {
116
+ const dataOoc = await tx.getRepository(DataOoc).save({
117
+ name: dataSet.name,
118
+ description: dataSet.description,
119
+ useCase: dataSet.useCase,
120
+ dataSet,
121
+ dataSample: result,
122
+ data: dataSample.data,
123
+ domain,
124
+ partitionKeys,
125
+ spec,
126
+ ooc,
127
+ oos,
128
+ history: [
129
+ {
130
+ user: {
131
+ id: user.id,
132
+ name: user.name
133
+ },
134
+ state: DataOocStatus.CREATED,
135
+ timestamp: Date.now()
136
+ }
137
+ ],
138
+ state: DataOocStatus.CREATED,
139
+ workDate: momentUtc.format('YYYY-MM-DD'),
140
+ workShift: 'DAY',
141
+ collectedAt,
142
+ creator: user,
143
+ updater: user
144
+ })
145
+
146
+ debug('dataOoc is about to publish...', dataOoc)
147
+
148
+ pubsub.publish('data-ooc', {
149
+ dataOoc,
150
+ supervisoryRoleId: dataSet.supervisoryRoleId
151
+ })
152
+
153
+ pubsub.publish('notification', {
154
+ notification: {
155
+ domain,
156
+ type: 'error',
157
+ title: `Data OOC occurred on '${dataSet.name}'`,
158
+ body: `Data OOC occurred on '${dataSet.name}'`,
159
+ url: getRedirectSubdomainPath(context, domain.subdomain, `/data-ooc/${dataOoc.id}`),
160
+ timestamp: collectedAt
161
+ }
162
+ })
163
+ }
164
+
165
+ return result
166
+ }
@@ -0,0 +1,85 @@
1
+ import { DataItem, DataSet } from 'server/service'
2
+
3
+ export type DataItemSpec = {
4
+ type: string
5
+ label: string
6
+ name: string
7
+ property: { [option: string]: any }
8
+ }
9
+
10
+ export type DataItemSpecSet = {
11
+ name: string
12
+ description: string
13
+ specs: DataItemSpec[]
14
+ }
15
+
16
+ export type EvaluationResult = { oos: boolean; ooc: boolean }
17
+
18
+ export abstract class DataUseCase {
19
+ static registry: { [name: string]: DataUseCase } = {}
20
+
21
+ public static registerUseCase(name: string, provider: DataUseCase) {
22
+ DataUseCase.registry[name] = provider
23
+ }
24
+
25
+ public static getUseCaseNames() {
26
+ return Object.keys(DataUseCase.registry)
27
+ }
28
+
29
+ public static getUseCase(name: string): DataUseCase | undefined {
30
+ return DataUseCase.registry[name]
31
+ }
32
+
33
+ public static evaluate(dataSet: DataSet, dataItems: DataItem[], data: any): EvaluationResult {
34
+ var ooc = false
35
+ var oos = false
36
+
37
+ if (!dataSet.useCase) {
38
+ return { ooc, oos }
39
+ }
40
+
41
+ const useCaseNames = dataSet.useCase.split(',').map(useCaseName => useCaseName.trim())
42
+ const useCases = useCaseNames.map(useCaseName => DataUseCase.getUseCase(useCaseName)).filter(useCase => !!useCase)
43
+
44
+ for (let i = 0; i < dataItems.length; i++) {
45
+ const dataItem = dataItems[i]
46
+ const { active, tag } = dataItem
47
+ if (!active || !tag) {
48
+ continue
49
+ }
50
+
51
+ let values: any | any[] = data[tag]
52
+ if (typeof values === 'undefined') {
53
+ continue // TODO what if in case no value ?
54
+ }
55
+
56
+ if (!(values instanceof Array)) {
57
+ values = [values]
58
+ }
59
+
60
+ for (let j = 0; j < useCases.length; j++) {
61
+ const useCase = useCases[j]
62
+
63
+ const specs = dataItem.spec?.[dataSet.useCase]
64
+ if (!specs) {
65
+ continue
66
+ }
67
+
68
+ const result = useCase.evaluate(specs, values)
69
+
70
+ if (result) {
71
+ ooc ||= result.ooc
72
+ oos ||= result.oos
73
+ }
74
+
75
+ // if (ooc && oos) {
76
+ // return { ooc, oos }
77
+ // }
78
+ }
79
+ }
80
+
81
+ return { ooc, oos }
82
+ }
83
+
84
+ public abstract evaluate(specs: any, values: any[]): EvaluationResult
85
+ }
@@ -0,0 +1 @@
1
+ export * from './data-use-case'
package/server/index.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import './routes'
2
2
 
3
+ export * from './controllers'
3
4
  export * from './migrations'
4
5
  export * from './middlewares'
5
6
  export * from './service'
7
+
8
+ export * from './service/data-spec/data-spec-manager'
package/server/routes.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { getConnection } from 'typeorm'
2
2
 
3
- import { DataSample } from './service'
4
- import { DataItem } from './service/data-item/data-item'
3
+ import { User } from '@things-factory/auth-base'
4
+
5
+ import { createDataSample } from './controllers/create-data-sample'
5
6
  import { DataSensor } from './service/data-sensor/data-sensor'
6
7
 
7
8
  const debug = require('debug')('things-factory:dataset:routes')
@@ -47,41 +48,26 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
47
48
 
48
49
  const domain = sensor.domain
49
50
  const dataSet = sensor.dataSet
50
- const user = sensor.appliance
51
-
52
- const dataItems = await tx.getRepository(DataItem).find({
51
+ const user: User = await tx.getRepository(User).findOne({
53
52
  where: {
54
- domain,
55
- dataSet
56
- },
57
- order: {
58
- sequence: 'DESC'
53
+ reference: sensor.appliance.id,
54
+ userType: 'appliance'
59
55
  }
60
56
  })
61
57
 
62
- var spec = {} as any
63
-
64
- dataItems.forEach(dataItem => {
65
- spec[dataItem.name] = dataItem.spec
66
- })
67
-
68
- await tx.getRepository(DataSample).save({
69
- domain,
70
- name: dataSet.name,
71
- description: dataSet.description,
72
- partitionKeys: dataSet.partitionKeys,
73
- dataSet,
74
- data,
75
- rawData,
76
- spec,
77
- source: deviceId,
78
- collectedAt: new Date(timestamp),
79
- creator: user,
80
- updater: user
81
- })
58
+ return await createDataSample(
59
+ {
60
+ dataSet,
61
+ data,
62
+ rawData,
63
+ source: deviceId,
64
+ collectedAt: new Date(timestamp)
65
+ },
66
+ { state: { domain, user, tx } }
67
+ )
82
68
  })
83
69
 
84
- return 'OK'
70
+ context.status = 200
85
71
  })
86
72
  })
87
73
 
@@ -24,9 +24,14 @@ export class DataItemMutation {
24
24
  await dataItemRepo.delete({ domain, dataSet: dataSetId })
25
25
 
26
26
  for (let i = 0; i < patches.length; i++) {
27
+ const patch = patches[i]
28
+ if (!patch.options) {
29
+ patch.options = {}
30
+ }
31
+
27
32
  const result = await dataItemRepo.save({
28
33
  quota: 1,
29
- ...patches[i],
34
+ ...patch,
30
35
  sequence: i,
31
36
  dataSet,
32
37
  domain,
@@ -1,16 +1,14 @@
1
- import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
2
-
3
- import { ScalarObject } from '@things-factory/shell'
4
-
5
1
  import { DataItem, DataItemType } from './data-item'
2
+ import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'
3
+ import { ObjectRef, ScalarObject } from '@things-factory/shell'
6
4
 
7
5
  @InputType()
8
6
  export class DataItemPatch {
9
7
  @Field(type => ID, { nullable: true })
10
8
  id?: string
11
9
 
12
- @Field({ nullable: true })
13
- dataSetId?: string
10
+ @Field(type => ObjectRef, { nullable: true })
11
+ dataSet?: ObjectRef
14
12
 
15
13
  @Field({ nullable: true })
16
14
  name?: string
@@ -27,6 +25,12 @@ export class DataItemPatch {
27
25
  @Field(type => DataItemType, { nullable: true })
28
26
  type?: DataItemType
29
27
 
28
+ @Field(type => ScalarObject, { nullable: true })
29
+ options?: ScalarObject
30
+
31
+ @Field({ nullable: true })
32
+ unit?: string
33
+
30
34
  @Field(type => Int, { nullable: true })
31
35
  quota?: number
32
36
 
@@ -34,7 +38,7 @@ export class DataItemPatch {
34
38
  active?: boolean
35
39
 
36
40
  @Field(type => ScalarObject, { nullable: true })
37
- spec?: object
41
+ spec?: ScalarObject
38
42
 
39
43
  @Field({ nullable: true })
40
44
  cuFlag?: string
@@ -1,4 +1,3 @@
1
- import { Field, ID, Int, ObjectType, registerEnumType } from 'type-graphql'
2
1
  import {
3
2
  Column,
4
3
  CreateDateColumn,
@@ -9,17 +8,18 @@ import {
9
8
  RelationId,
10
9
  UpdateDateColumn
11
10
  } from 'typeorm'
12
-
13
- import { User } from '@things-factory/auth-base'
14
11
  import { Domain, ScalarObject } from '@things-factory/shell'
12
+ import { Field, ID, Int, ObjectType, registerEnumType } from 'type-graphql'
15
13
 
16
14
  import { DataSet } from '../data-set/data-set'
15
+ import { User } from '@things-factory/auth-base'
17
16
 
18
17
  export enum DataItemType {
19
18
  number = 'number',
20
19
  text = 'text',
21
20
  boolean = 'boolean',
22
- select = 'select'
21
+ select = 'select',
22
+ file = 'file'
23
23
  }
24
24
 
25
25
  registerEnumType(DataItemType, {
@@ -53,7 +53,7 @@ export class DataItem {
53
53
  description?: string
54
54
 
55
55
  @ManyToOne(type => DataSet, dataSet => dataSet.dataItems, { onDelete: 'CASCADE' })
56
- @Field(type => DataSet, { nullable: true })
56
+ @Field(type => DataSet, { nullable: false })
57
57
  dataSet?: DataSet
58
58
 
59
59
  @RelationId((dataItem: DataItem) => dataItem.dataSet)
@@ -81,6 +81,16 @@ export class DataItem {
81
81
  @Field({ nullable: true })
82
82
  type?: DataItemType
83
83
 
84
+ @Column('simple-json', { nullable: true })
85
+ @Field(type => ScalarObject, { nullable: true })
86
+ options?: ScalarObject
87
+
88
+ @Column({
89
+ nullable: true
90
+ })
91
+ @Field({ nullable: true })
92
+ unit?: string
93
+
84
94
  @Column({
85
95
  nullable: true
86
96
  })
@@ -89,7 +99,7 @@ export class DataItem {
89
99
 
90
100
  @Column('simple-json', { nullable: true })
91
101
  @Field(type => ScalarObject, { nullable: true })
92
- spec?: object
102
+ spec?: ScalarObject
93
103
 
94
104
  @CreateDateColumn()
95
105
  @Field({ nullable: true })
@@ -0,0 +1,150 @@
1
+ import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
+
3
+ import { DataOoc, DataOocStatus } from './data-ooc'
4
+ import { DataOocPatch, NewDataOoc } from './data-ooc-type'
5
+
6
+ @Resolver(DataOoc)
7
+ export class DataOocMutation {
8
+ @Directive('@privilege(category: "data-ooc", privilege: "mutation", domainOwnerGranted: true)')
9
+ @Directive('@transaction')
10
+ @Mutation(returns => DataOoc, { description: 'To create new DataOoc' })
11
+ async createDataOoc(@Arg('dataOoc') dataOoc: NewDataOoc, @Ctx() context: any): Promise<DataOoc> {
12
+ const { domain, user, tx } = context.state
13
+
14
+ const state = dataOoc.state || DataOocStatus.CREATED
15
+ const history = [
16
+ {
17
+ user: {
18
+ id: user.id,
19
+ name: user.name
20
+ },
21
+ state,
22
+ timestamp: Date.now()
23
+ }
24
+ ]
25
+
26
+ return await tx.getRepository(DataOoc).save({
27
+ ...dataOoc,
28
+ state,
29
+ domain,
30
+ history,
31
+ creator: user,
32
+ updater: user
33
+ })
34
+ }
35
+
36
+ @Directive('@privilege(category: "data-ooc", privilege: "mutation", domainOwnerGranted: true)')
37
+ @Directive('@transaction')
38
+ @Mutation(returns => DataOoc, { description: 'To modify DataOoc information' })
39
+ async updateDataOoc(@Arg('id') id: string, @Arg('patch') patch: DataOocPatch, @Ctx() context: any): Promise<DataOoc> {
40
+ const { domain, user, tx } = context.state
41
+
42
+ const repository = tx.getRepository(DataOoc)
43
+ const dataOoc = await repository.findOne({
44
+ where: { domain, id }
45
+ })
46
+
47
+ const state = patch.state || dataOoc.state
48
+
49
+ const history = dataOoc.history || []
50
+ history.push({
51
+ user: {
52
+ id: user.id,
53
+ name: user.name
54
+ },
55
+ state,
56
+ comment: patch.correctiveAction || '',
57
+ timestamp: Date.now()
58
+ })
59
+
60
+ const more = {} as any
61
+
62
+ if (dataOoc.state !== patch.state) {
63
+ if (patch.state === DataOocStatus.CORRECTED) {
64
+ more.corrector = user
65
+ } else {
66
+ more.corrector = null
67
+ }
68
+ }
69
+
70
+ return await repository.save({
71
+ ...dataOoc,
72
+ ...patch,
73
+ ...more,
74
+ state,
75
+ history,
76
+ updater: user
77
+ })
78
+ }
79
+
80
+ // @Directive('@privilege(category: "data-ooc", privilege: "mutation", domainOwnerGranted: true)')
81
+ // @Directive('@transaction')
82
+ // @Mutation(returns => [DataOoc], { description: "To modify multiple DataOoc' information" })
83
+ // async updateMultipleDataOoc(
84
+ // @Arg('patches', type => [DataOocPatch]) patches: DataOocPatch[],
85
+ // @Ctx() context: any
86
+ // ): Promise<DataOoc[]> {
87
+ // const { domain, user, tx } = context.state
88
+
89
+ // let results = []
90
+ // const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
91
+ // const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
92
+ // const dataOocRepo = tx.getRepository(DataOoc)
93
+
94
+ // if (_createRecords.length > 0) {
95
+ // for (let i = 0; i < _createRecords.length; i++) {
96
+ // const newRecord = _createRecords[i]
97
+
98
+ // const result = await dataOocRepo.save({
99
+ // ...newRecord,
100
+ // domain,
101
+ // creator: user,
102
+ // updater: user
103
+ // })
104
+
105
+ // results.push({ ...result, cuFlag: '+' })
106
+ // }
107
+ // }
108
+
109
+ // if (_updateRecords.length > 0) {
110
+ // for (let i = 0; i < _updateRecords.length; i++) {
111
+ // const newRecord = _updateRecords[i]
112
+ // const dataOoc = await dataOocRepo.findOne(newRecord.id)
113
+
114
+ // const result = await dataOocRepo.save({
115
+ // ...dataOoc,
116
+ // ...newRecord,
117
+ // updater: user
118
+ // })
119
+
120
+ // results.push({ ...result, cuFlag: 'M' })
121
+ // }
122
+ // }
123
+
124
+ // return results
125
+ // }
126
+
127
+ // @Directive('@privilege(category: "data-ooc", privilege: "mutation", domainOwnerGranted: true)')
128
+ // @Directive('@transaction')
129
+ // @Mutation(returns => Boolean, { description: 'To delete DataOoc' })
130
+ // async deleteDataOoc(@Arg('id') id: string, @Ctx() context: any): Promise<boolean> {
131
+ // const { domain, tx } = context.state
132
+
133
+ // await tx.getRepository(DataOoc).delete({ domain, id })
134
+ // return true
135
+ // }
136
+
137
+ // @Directive('@privilege(category: "data-ooc", privilege: "mutation", domainOwnerGranted: true)')
138
+ // @Directive('@transaction')
139
+ // @Mutation(returns => Boolean, { description: 'To delete multiple dataOocs' })
140
+ // async deleteDataOocs(@Arg('ids', type => [String]) ids: string[], @Ctx() context: any): Promise<boolean> {
141
+ // const { domain, tx } = context.state
142
+
143
+ // await tx.getRepository(DataOoc).delete({
144
+ // domain,
145
+ // id: In(ids)
146
+ // })
147
+
148
+ // return true
149
+ // }
150
+ }