@things-factory/id-rule-base 8.0.0-beta.9 → 8.0.0
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.ts +8 -0
- package/client/editors/grist-code-input-popup.ts +196 -0
- package/client/editors/grist-code-input.ts +121 -0
- package/client/index.ts +0 -0
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/server/constants/index.ts +1 -0
- package/server/constants/sequence-type.ts +3 -0
- package/server/controllers/id-generator.ts +75 -0
- package/server/controllers/index.ts +1 -0
- package/server/index.ts +6 -0
- package/server/migrations/index.ts +9 -0
- package/server/routes.ts +25 -0
- package/server/service/doc-number/doc-number-mutation.ts +121 -0
- package/server/service/doc-number/doc-number-query.ts +142 -0
- package/server/service/doc-number/doc-number-type.ts +115 -0
- package/server/service/doc-number/doc-number.ts +160 -0
- package/server/service/doc-number/index.ts +7 -0
- package/server/service/id-rule/id-rule-mutation.ts +34 -0
- package/server/service/id-rule/id-rule-query.ts +25 -0
- package/server/service/id-rule/id-rule-types.ts +20 -0
- package/server/service/id-rule/id-rule.ts +49 -0
- package/server/service/id-rule/index.ts +6 -0
- package/server/service/index.ts +16 -0
- package/server/service/sequence/index.ts +5 -0
- package/server/service/sequence/sequence-mutation.ts +56 -0
- package/server/service/sequence/sequence.ts +49 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/id-rule-base",
|
|
3
|
-
"version": "8.0.0
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@operato/data-grist": "^8.0.0
|
|
31
|
-
"@operato/input": "^8.0.0
|
|
32
|
-
"@things-factory/i18n-base": "^8.0.0
|
|
33
|
-
"@things-factory/setting-base": "^8.0.0
|
|
34
|
-
"@things-factory/shell": "^8.0.0
|
|
30
|
+
"@operato/data-grist": "^8.0.0",
|
|
31
|
+
"@operato/input": "^8.0.0",
|
|
32
|
+
"@things-factory/i18n-base": "^8.0.0",
|
|
33
|
+
"@things-factory/setting-base": "^8.0.0",
|
|
34
|
+
"@things-factory/shell": "^8.0.0",
|
|
35
35
|
"ses": "^1.5.0"
|
|
36
36
|
},
|
|
37
|
-
"gitHead": "
|
|
37
|
+
"gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
|
|
38
38
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './sequence-type'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { MoreThan } from 'typeorm'
|
|
2
|
+
import { Domain, getRepository } from '@things-factory/shell'
|
|
3
|
+
import { IdRule } from '../service/id-rule/id-rule'
|
|
4
|
+
import { Sequence } from '../service/sequence/sequence'
|
|
5
|
+
import 'ses'
|
|
6
|
+
|
|
7
|
+
type getNextArgs = {
|
|
8
|
+
domain: Domain
|
|
9
|
+
pattern: string
|
|
10
|
+
expirationDate?: Date
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function generateId({ domain, type, seed }) {
|
|
14
|
+
const idRuleRepo = getRepository(IdRule)
|
|
15
|
+
const rule = await idRuleRepo.findOne({
|
|
16
|
+
where: {
|
|
17
|
+
domain: { id: domain.id },
|
|
18
|
+
type
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
if (!rule) throw Error('Rule not found')
|
|
23
|
+
|
|
24
|
+
const compartment = new Compartment({
|
|
25
|
+
domain,
|
|
26
|
+
seed,
|
|
27
|
+
console
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
let evalFunc
|
|
31
|
+
try {
|
|
32
|
+
evalFunc = compartment.evaluate(`(async (domain, seed, getNext) => {
|
|
33
|
+
${rule.rule}
|
|
34
|
+
})`)
|
|
35
|
+
} catch (err) {
|
|
36
|
+
throw new Error(`Failed to evaluate rule: ${err.message}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const nextId = await evalFunc(domain, {
|
|
40
|
+
...seed,
|
|
41
|
+
},
|
|
42
|
+
getNext)
|
|
43
|
+
|
|
44
|
+
return nextId
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function getNext({ domain, pattern, expirationDate }: getNextArgs) {
|
|
48
|
+
const seqRepo = getRepository(Sequence)
|
|
49
|
+
const now = new Date()
|
|
50
|
+
let last = await seqRepo.findOneBy({
|
|
51
|
+
domain: { id: domain.id },
|
|
52
|
+
pattern,
|
|
53
|
+
expiresAt: MoreThan(now)
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
var expiresAt = expirationDate
|
|
57
|
+
if (!expirationDate) expiresAt = new Date(now.setMonth(now.getMonth() + 6))
|
|
58
|
+
|
|
59
|
+
if (last) {
|
|
60
|
+
last.seq++
|
|
61
|
+
last.expiresAt = expiresAt
|
|
62
|
+
await seqRepo.save(last)
|
|
63
|
+
} else {
|
|
64
|
+
if (!expirationDate) now.setMonth(now.getMonth() + 6)
|
|
65
|
+
|
|
66
|
+
last = await seqRepo.save({
|
|
67
|
+
domain,
|
|
68
|
+
pattern,
|
|
69
|
+
seq: 1,
|
|
70
|
+
expiresAt
|
|
71
|
+
})
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return last.seq
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './id-generator'
|
package/server/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const glob = require('glob')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
export var migrations = []
|
|
5
|
+
|
|
6
|
+
glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
|
|
7
|
+
if (file.indexOf('index.js') !== -1) return
|
|
8
|
+
migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
|
|
9
|
+
})
|
package/server/routes.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { generateId } from './controllers/id-generator'
|
|
2
|
+
|
|
3
|
+
process.on('bootstrap-module-domain-private-route' as any, (app, routes) => {
|
|
4
|
+
/*
|
|
5
|
+
* koa application에 routes 를 추가할 수 있다.
|
|
6
|
+
*
|
|
7
|
+
* ex) routes.get('/path', async(context, next) => {})
|
|
8
|
+
* ex) routes.post('/path', async(context, next) => {})
|
|
9
|
+
*/
|
|
10
|
+
routes.get('/get-next-pattern/:type/:domain', async (context, next) => {
|
|
11
|
+
const { type, domain } = context.params
|
|
12
|
+
|
|
13
|
+
var id = await generateId({
|
|
14
|
+
domain,
|
|
15
|
+
type,
|
|
16
|
+
seed: {
|
|
17
|
+
productId: 'ASUS',
|
|
18
|
+
receiver: 'LA'
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
context.status = 200
|
|
23
|
+
context.body = id
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
|
|
2
|
+
import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
|
|
3
|
+
import { In } from 'typeorm'
|
|
4
|
+
import { DocNumber } from './doc-number'
|
|
5
|
+
import { NewDocNumber, DocNumberPatch } from './doc-number-type'
|
|
6
|
+
import { Domain, getRepository } from '@things-factory/shell'
|
|
7
|
+
import { User } from '@things-factory/auth-base'
|
|
8
|
+
|
|
9
|
+
@Resolver(DocNumber)
|
|
10
|
+
export class DocNumberMutation {
|
|
11
|
+
@Directive('@transaction')
|
|
12
|
+
@Mutation(returns => DocNumber, { description: 'To create new DocNumber' })
|
|
13
|
+
async createDocNumber(@Arg('docNumber') docNumber: NewDocNumber, @Ctx() context: any): Promise<DocNumber> {
|
|
14
|
+
const { domain, user, tx } = context.state
|
|
15
|
+
|
|
16
|
+
return await tx.getRepository(DocNumber).save({
|
|
17
|
+
...docNumber,
|
|
18
|
+
domain,
|
|
19
|
+
creator: user,
|
|
20
|
+
updater: user
|
|
21
|
+
})
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Directive('@transaction')
|
|
25
|
+
@Mutation(returns => DocNumber, { description: 'To modify DocNumber information' })
|
|
26
|
+
async updateDocNumber(
|
|
27
|
+
@Arg('id') id: string,
|
|
28
|
+
@Arg('patch') patch: DocNumberPatch,
|
|
29
|
+
@Ctx() context: any
|
|
30
|
+
): Promise<DocNumber> {
|
|
31
|
+
const { domain, user, tx } = context.state
|
|
32
|
+
|
|
33
|
+
const repository = tx.getRepository(DocNumber)
|
|
34
|
+
const docNumber = await repository.findOne(
|
|
35
|
+
{
|
|
36
|
+
where: { domain: { id: domain.id }, id },
|
|
37
|
+
relations: ['domain','updater','creator']
|
|
38
|
+
}
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
return await repository.save({
|
|
42
|
+
...docNumber,
|
|
43
|
+
...patch,
|
|
44
|
+
updater: user
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Directive('@transaction')
|
|
49
|
+
@Mutation(returns => [DocNumber], { description: "To modify multiple DocNumbers' information" })
|
|
50
|
+
async updateMultipleDocNumber(
|
|
51
|
+
@Arg('patches', type => [DocNumberPatch]) patches: DocNumberPatch[],
|
|
52
|
+
@Ctx() context: any
|
|
53
|
+
): Promise<DocNumber[]> {
|
|
54
|
+
const { domain, user, tx } = context.state
|
|
55
|
+
|
|
56
|
+
let results = []
|
|
57
|
+
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
|
58
|
+
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
|
59
|
+
const docNumberRepo = tx.getRepository(DocNumber)
|
|
60
|
+
|
|
61
|
+
if (_createRecords.length > 0) {
|
|
62
|
+
for (let i = 0; i < _createRecords.length; i++) {
|
|
63
|
+
const newRecord = _createRecords[i]
|
|
64
|
+
|
|
65
|
+
const result = await docNumberRepo.save({
|
|
66
|
+
...newRecord,
|
|
67
|
+
domain,
|
|
68
|
+
creator: user,
|
|
69
|
+
updater: user
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
results.push({ ...result, cuFlag: '+' })
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (_updateRecords.length > 0) {
|
|
77
|
+
for (let i = 0; i < _updateRecords.length; i++) {
|
|
78
|
+
const updRecord = _updateRecords[i]
|
|
79
|
+
const docNumber = await docNumberRepo.findOne({
|
|
80
|
+
where: { domain: { id: domain.id }, id:updRecord.id },
|
|
81
|
+
relations: ['domain','updater','creator']
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
const result = await docNumberRepo.save({
|
|
85
|
+
...docNumber,
|
|
86
|
+
...updRecord,
|
|
87
|
+
updater: user
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
results.push({ ...result, cuFlag: 'M' })
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return results
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
@Directive('@transaction')
|
|
98
|
+
@Mutation(returns => Boolean, { description: 'To delete DocNumber' })
|
|
99
|
+
async deleteDocNumber(@Arg('id') id: string, @Ctx() context: any): Promise<boolean> {
|
|
100
|
+
const { domain, tx, user } = context.state
|
|
101
|
+
await tx.getRepository(DocNumber).remove({ domain, id, updater:user })
|
|
102
|
+
return true
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@Directive('@transaction')
|
|
106
|
+
@Mutation(returns => Boolean, { description: 'To delete multiple docNumbers' })
|
|
107
|
+
async deleteDocNumbers(
|
|
108
|
+
@Arg('ids', type => [String]) ids: string[],
|
|
109
|
+
@Ctx() context: any
|
|
110
|
+
): Promise<boolean> {
|
|
111
|
+
const { domain, tx, user } = context.state
|
|
112
|
+
|
|
113
|
+
let delEntitis = ids.map(id=>{
|
|
114
|
+
return {domain,id,updater:user}
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
await tx.getRepository(DocNumber).remove(delEntitis)
|
|
118
|
+
|
|
119
|
+
return true
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
|
|
2
|
+
import { ListParam, convertListParams, getRepository, getQueryBuilderFromListParams } from '@things-factory/shell'
|
|
3
|
+
import { DocNumber } from './doc-number'
|
|
4
|
+
import { DocNumberList } from './doc-number-type'
|
|
5
|
+
|
|
6
|
+
import { User } from '@things-factory/auth-base'
|
|
7
|
+
import { Domain } from '@things-factory/shell'
|
|
8
|
+
|
|
9
|
+
@Resolver(DocNumber)
|
|
10
|
+
export class DocNumberQuery {
|
|
11
|
+
@Query(returns => DocNumber, { description: 'To fetch a DocNumber' })
|
|
12
|
+
async docNumber(@Arg('id') id: string, @Ctx() context: any): Promise<DocNumber> {
|
|
13
|
+
const { domain } = context.state
|
|
14
|
+
return await getRepository(DocNumber).findOne({
|
|
15
|
+
where: { domain: { id: domain.id }, id }
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@Query(returns => DocNumberList, { description: 'To fetch multiple DocNumbers' })
|
|
20
|
+
async docNumbers(@Args(type => ListParam) params: ListParam, @Ctx() context: any): Promise<DocNumberList> {
|
|
21
|
+
const { domain } = context.state
|
|
22
|
+
|
|
23
|
+
const queryBuilder = getQueryBuilderFromListParams({
|
|
24
|
+
domain,
|
|
25
|
+
params,
|
|
26
|
+
repository: await getRepository(DocNumber),
|
|
27
|
+
searchables: ['code', 'description']
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const [items, total] = await queryBuilder.getManyAndCount()
|
|
31
|
+
return { items, total }
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Query(returns => DocNumber, { description: 'To generate a new DocNumber' })
|
|
35
|
+
async getNewDocNumber(@Arg('id') id: string, @Ctx() context: any): Promise<DocNumber> {
|
|
36
|
+
const { domain } = context.state
|
|
37
|
+
|
|
38
|
+
// 1. find one by id - TODO by Lock
|
|
39
|
+
let docNumber = await getRepository(DocNumber).findOne({
|
|
40
|
+
where: { domain: { id: domain.id }, id }
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
// 2. find one by code - TODO by Lock
|
|
44
|
+
if (docNumber == null) {
|
|
45
|
+
docNumber = await getRepository(DocNumber).findOne({
|
|
46
|
+
where: { domain: { id: domain.id }, code: id }
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// 3. TODO throw exception
|
|
51
|
+
if (docNumber == null) {
|
|
52
|
+
return null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// 4. 시퀀스 증가
|
|
56
|
+
let newDocNum = docNumber.currentNo
|
|
57
|
+
|
|
58
|
+
if (docNumber.useDbSeqFlag) {
|
|
59
|
+
// TODO DATABASE SEQUENCE 호출
|
|
60
|
+
newDocNum += 1
|
|
61
|
+
} else {
|
|
62
|
+
newDocNum = docNumber.currentNo ? docNumber.currentNo + 1 : 1
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// 5. 문서 번호 expression 구성
|
|
66
|
+
if (!docNumber.expression) {
|
|
67
|
+
docNumber.updateExpression()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let expression = docNumber.expression
|
|
71
|
+
|
|
72
|
+
// 6. 시퀀스 번호 사이클 처리
|
|
73
|
+
if (newDocNum > docNumber.endNo) {
|
|
74
|
+
newDocNum = docNumber.startNo
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 7. 자리수 설정
|
|
78
|
+
let newDocNoStr = newDocNum.toString()
|
|
79
|
+
let docNumLength = newDocNoStr.length
|
|
80
|
+
let docNoDigit = docNumber.seqDigitNum ? docNumber.seqDigitNum : 1
|
|
81
|
+
|
|
82
|
+
// 8. 시퀀스 번호가 시퀀스 번호 사이즈보다 작은 경우 앞에 0을 붙임
|
|
83
|
+
if (docNoDigit > docNumLength) {
|
|
84
|
+
let addZeroCnt = docNoDigit - docNumLength
|
|
85
|
+
for (let i = 0; i < addZeroCnt; i++) {
|
|
86
|
+
newDocNoStr = '0' + newDocNoStr
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 9. 문서 번호 구성
|
|
91
|
+
let newDocNumber = expression.replace('${SEQ}', newDocNoStr)
|
|
92
|
+
let docUpdateInterval = docNumber.updateInterval
|
|
93
|
+
if (docUpdateInterval && docUpdateInterval != 'NONE') {
|
|
94
|
+
const today = new Date()
|
|
95
|
+
let todayStr =
|
|
96
|
+
today.getFullYear() +
|
|
97
|
+
(today.getMonth() > 9 ? '' + today.getMonth() + 1 : '0' + today.getMonth() + 1) +
|
|
98
|
+
today.getDate()
|
|
99
|
+
let intervalVal = ''
|
|
100
|
+
|
|
101
|
+
if (docUpdateInterval == 'yy') {
|
|
102
|
+
intervalVal = todayStr.substring(2, 4)
|
|
103
|
+
} else if (docUpdateInterval == 'yyyy') {
|
|
104
|
+
intervalVal = todayStr.substring(0, 4)
|
|
105
|
+
} else if (docUpdateInterval == 'yyMM') {
|
|
106
|
+
intervalVal = todayStr.substring(2, 6)
|
|
107
|
+
} else if (docUpdateInterval == 'yyyyMM') {
|
|
108
|
+
intervalVal = todayStr.substring(0, 6)
|
|
109
|
+
} else if (docUpdateInterval == 'yyMMdd') {
|
|
110
|
+
intervalVal = todayStr.substring(2, 8)
|
|
111
|
+
} else if (docUpdateInterval == 'yyyyMMdd') {
|
|
112
|
+
intervalVal = todayStr
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
newDocNumber = newDocNumber.replace('${' + docUpdateInterval + '}', intervalVal)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 10. 현재 시퀀스 번호 저장
|
|
119
|
+
docNumber.domain = domain
|
|
120
|
+
docNumber.currentNo = newDocNum
|
|
121
|
+
docNumber.lastDocNumber = newDocNumber
|
|
122
|
+
await getRepository(DocNumber).save(docNumber)
|
|
123
|
+
|
|
124
|
+
// 11. 최종
|
|
125
|
+
return docNumber
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
@FieldResolver(type => Domain)
|
|
129
|
+
async domain(@Root() docNumber: DocNumber): Promise<Domain> {
|
|
130
|
+
return await getRepository(Domain).findOneBy({ id: docNumber.domainId })
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@FieldResolver(type => User)
|
|
134
|
+
async creator(@Root() docNumber: DocNumber): Promise<User> {
|
|
135
|
+
return await getRepository(User).findOneBy({ id: docNumber.creatorId })
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
@FieldResolver(type => User)
|
|
139
|
+
async updater(@Root() docNumber: DocNumber): Promise<User> {
|
|
140
|
+
return await getRepository(User).findOneBy({ id: docNumber.updaterId })
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
|
|
2
|
+
import { ObjectType, Field, InputType, Int, ID, Float, registerEnumType } from 'type-graphql'
|
|
3
|
+
import { DocNumber } from './doc-number'
|
|
4
|
+
|
|
5
|
+
@InputType()
|
|
6
|
+
export class NewDocNumber {
|
|
7
|
+
|
|
8
|
+
@Field({ nullable: false })
|
|
9
|
+
code: string
|
|
10
|
+
|
|
11
|
+
@Field({ nullable: false })
|
|
12
|
+
description: string
|
|
13
|
+
|
|
14
|
+
@Field(type => Int, { nullable: true })
|
|
15
|
+
startNo: number
|
|
16
|
+
|
|
17
|
+
@Field(type => Int, { nullable: true })
|
|
18
|
+
endNo: number
|
|
19
|
+
|
|
20
|
+
@Field(type => Int, { nullable: true })
|
|
21
|
+
currentNo?: number
|
|
22
|
+
|
|
23
|
+
@Field({ nullable:true })
|
|
24
|
+
prefix?: string
|
|
25
|
+
|
|
26
|
+
@Field({ nullable:true })
|
|
27
|
+
suffix?: string
|
|
28
|
+
|
|
29
|
+
@Field({ nullable: true })
|
|
30
|
+
updateInterval?: string
|
|
31
|
+
|
|
32
|
+
@Field({ nullable: true })
|
|
33
|
+
useDbSeqFlag?: boolean
|
|
34
|
+
|
|
35
|
+
@Field({ nullable: false })
|
|
36
|
+
seqName: string
|
|
37
|
+
|
|
38
|
+
@Field(type => Int, { nullable: true })
|
|
39
|
+
seqDigitNum?: number
|
|
40
|
+
|
|
41
|
+
@Field({ nullable: true })
|
|
42
|
+
separator?: string
|
|
43
|
+
|
|
44
|
+
@Field({ nullable: true })
|
|
45
|
+
expression?: string
|
|
46
|
+
|
|
47
|
+
@Field({ nullable: true })
|
|
48
|
+
lastDocNumber?: string
|
|
49
|
+
|
|
50
|
+
@Field({ nullable: true })
|
|
51
|
+
activeFlag?: boolean
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@InputType()
|
|
55
|
+
export class DocNumberPatch {
|
|
56
|
+
@Field(type => ID, { nullable: true })
|
|
57
|
+
id?: string
|
|
58
|
+
|
|
59
|
+
@Field({ nullable: true })
|
|
60
|
+
code?: string
|
|
61
|
+
|
|
62
|
+
@Field({ nullable: true })
|
|
63
|
+
description?: string
|
|
64
|
+
|
|
65
|
+
@Field(type => Int, { nullable: true })
|
|
66
|
+
startNo?: number
|
|
67
|
+
|
|
68
|
+
@Field(type => Int, { nullable: true })
|
|
69
|
+
endNo?: number
|
|
70
|
+
|
|
71
|
+
@Field(type => Int, { nullable: true })
|
|
72
|
+
currentNo?: number
|
|
73
|
+
|
|
74
|
+
@Field({ nullable:true })
|
|
75
|
+
prefix?: string
|
|
76
|
+
|
|
77
|
+
@Field({ nullable:true })
|
|
78
|
+
suffix?: string
|
|
79
|
+
|
|
80
|
+
@Field({ nullable: true })
|
|
81
|
+
updateInterval?: string
|
|
82
|
+
|
|
83
|
+
@Field({ nullable: true })
|
|
84
|
+
useDbSeqFlag?: boolean
|
|
85
|
+
|
|
86
|
+
@Field({ nullable: true })
|
|
87
|
+
seqName?: string
|
|
88
|
+
|
|
89
|
+
@Field(type => Int, { nullable: true })
|
|
90
|
+
seqDigitNum?: number
|
|
91
|
+
|
|
92
|
+
@Field({ nullable: true })
|
|
93
|
+
separator?: string
|
|
94
|
+
|
|
95
|
+
@Field({ nullable: true })
|
|
96
|
+
expression?: string
|
|
97
|
+
|
|
98
|
+
@Field({ nullable: true })
|
|
99
|
+
lastDocNumber?: string
|
|
100
|
+
|
|
101
|
+
@Field({ nullable: true })
|
|
102
|
+
activeFlag?: boolean
|
|
103
|
+
|
|
104
|
+
@Field()
|
|
105
|
+
cuFlag: string
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@ObjectType()
|
|
109
|
+
export class DocNumberList {
|
|
110
|
+
@Field(type => [DocNumber])
|
|
111
|
+
items: DocNumber[]
|
|
112
|
+
|
|
113
|
+
@Field(type => Int)
|
|
114
|
+
total: number
|
|
115
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateDateColumn,
|
|
3
|
+
UpdateDateColumn,
|
|
4
|
+
Entity,
|
|
5
|
+
Index,
|
|
6
|
+
Column,
|
|
7
|
+
RelationId,
|
|
8
|
+
ManyToOne,
|
|
9
|
+
PrimaryGeneratedColumn,
|
|
10
|
+
BeforeInsert
|
|
11
|
+
} from 'typeorm'
|
|
12
|
+
import { ObjectType, Field, Int, ID } from 'type-graphql'
|
|
13
|
+
|
|
14
|
+
import { User } from '@things-factory/auth-base'
|
|
15
|
+
import { Domain } from '@things-factory/shell'
|
|
16
|
+
|
|
17
|
+
@Entity('doc_numbers')
|
|
18
|
+
@Index('ix_doc_number_0', (docNumber: DocNumber) => [docNumber.domain, docNumber.code], { unique: true })
|
|
19
|
+
@ObjectType({ description: 'Entity for DocNumber' })
|
|
20
|
+
export class DocNumber {
|
|
21
|
+
@PrimaryGeneratedColumn('uuid')
|
|
22
|
+
@Field(type => ID)
|
|
23
|
+
readonly id: string
|
|
24
|
+
|
|
25
|
+
@Column()
|
|
26
|
+
@Field()
|
|
27
|
+
code: string
|
|
28
|
+
|
|
29
|
+
@Column()
|
|
30
|
+
@Field()
|
|
31
|
+
description: string
|
|
32
|
+
|
|
33
|
+
@Column({ nullable: true })
|
|
34
|
+
@Field({ nullable: true })
|
|
35
|
+
prefix?: string
|
|
36
|
+
|
|
37
|
+
@Column({ nullable: true })
|
|
38
|
+
@Field({ nullable: true })
|
|
39
|
+
suffix?: string
|
|
40
|
+
|
|
41
|
+
@Column({ type: 'integer', nullable: true })
|
|
42
|
+
@Field(type => Int, { nullable: true })
|
|
43
|
+
startNo?: number
|
|
44
|
+
|
|
45
|
+
@Column({ type: 'integer', nullable: true })
|
|
46
|
+
@Field(type => Int, { nullable: true })
|
|
47
|
+
endNo?: number
|
|
48
|
+
|
|
49
|
+
@Column({ type: 'integer', nullable: true })
|
|
50
|
+
@Field(type => Int, { nullable: true })
|
|
51
|
+
currentNo?: number
|
|
52
|
+
|
|
53
|
+
@Column({ nullable: true })
|
|
54
|
+
@Field({ nullable: true })
|
|
55
|
+
updateInterval?: string
|
|
56
|
+
|
|
57
|
+
@Column({ nullable: true, default: false })
|
|
58
|
+
@Field({ nullable: true })
|
|
59
|
+
useDbSeqFlag?: boolean
|
|
60
|
+
|
|
61
|
+
@Column({ nullable: true })
|
|
62
|
+
@Field({ nullable: true })
|
|
63
|
+
seqName?: string
|
|
64
|
+
|
|
65
|
+
@Column({ type: 'integer', nullable: false })
|
|
66
|
+
@Field(type => Int, { nullable: false })
|
|
67
|
+
seqDigitNum: number
|
|
68
|
+
|
|
69
|
+
@Column({ nullable: true })
|
|
70
|
+
@Field({ nullable: true })
|
|
71
|
+
separator?: string
|
|
72
|
+
|
|
73
|
+
@Column({ nullable: true })
|
|
74
|
+
@Field({ nullable: true })
|
|
75
|
+
expression?: string
|
|
76
|
+
|
|
77
|
+
@Column({ nullable: true })
|
|
78
|
+
@Field({ nullable: true })
|
|
79
|
+
lastDocNumber?: string
|
|
80
|
+
|
|
81
|
+
@Column({ type: 'boolean', nullable: true, default: false })
|
|
82
|
+
@Field({ nullable: true })
|
|
83
|
+
activeFlag?: boolean
|
|
84
|
+
|
|
85
|
+
@ManyToOne(type => Domain, { createForeignKeyConstraints: false, nullable: false })
|
|
86
|
+
@Field({ nullable: false })
|
|
87
|
+
domain: Domain
|
|
88
|
+
|
|
89
|
+
@RelationId((docNumber: DocNumber) => docNumber.domain)
|
|
90
|
+
domainId: string
|
|
91
|
+
|
|
92
|
+
@ManyToOne(type => User, { createForeignKeyConstraints: false, nullable: true })
|
|
93
|
+
@Field(type => User, { nullable: true })
|
|
94
|
+
creator?: User
|
|
95
|
+
|
|
96
|
+
@RelationId((docNumber: DocNumber) => docNumber.creator)
|
|
97
|
+
creatorId?: string
|
|
98
|
+
|
|
99
|
+
@ManyToOne(type => User, { createForeignKeyConstraints: false, nullable: true })
|
|
100
|
+
@Field(type => User, { nullable: true })
|
|
101
|
+
updater?: User
|
|
102
|
+
|
|
103
|
+
@RelationId((docNumber: DocNumber) => docNumber.updater)
|
|
104
|
+
updaterId?: string
|
|
105
|
+
|
|
106
|
+
@CreateDateColumn()
|
|
107
|
+
@Field({ nullable: true })
|
|
108
|
+
createdAt?: Date
|
|
109
|
+
|
|
110
|
+
@UpdateDateColumn()
|
|
111
|
+
@Field({ nullable: true })
|
|
112
|
+
updatedAt?: Date
|
|
113
|
+
|
|
114
|
+
@BeforeInsert()
|
|
115
|
+
updateExpression() {
|
|
116
|
+
if (!this.expression || this.expression.length == 0) {
|
|
117
|
+
if (!this.startNo || this.startNo < 1) {
|
|
118
|
+
this.startNo = 1
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (!this.endNo || this.endNo <= 1) {
|
|
122
|
+
let maxNo = ''
|
|
123
|
+
for (let i = 0; i < this.seqDigitNum; i++) {
|
|
124
|
+
maxNo = maxNo + '9'
|
|
125
|
+
}
|
|
126
|
+
this.endNo = Number(maxNo)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let expr = ''
|
|
130
|
+
|
|
131
|
+
if (this.prefix) {
|
|
132
|
+
expr = this.prefix
|
|
133
|
+
|
|
134
|
+
if (this.separator) {
|
|
135
|
+
expr += this.separator
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (this.updateInterval && this.updateInterval != 'NONE') {
|
|
140
|
+
expr += '${' + this.updateInterval + '}'
|
|
141
|
+
|
|
142
|
+
if (this.separator) {
|
|
143
|
+
expr += this.separator
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
expr += '${SEQ}'
|
|
148
|
+
|
|
149
|
+
if (this.suffix) {
|
|
150
|
+
if (this.separator) {
|
|
151
|
+
expr += this.separator
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
expr += this.suffix
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.expression = expr
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|