@things-factory/product-base 8.0.0-beta.9 → 8.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/dist-server/service/product/product-mutation.js +1 -1
- package/dist-server/service/product/product-mutation.js.map +1 -1
- package/dist-server/service/product/product-query.d.ts +1 -1
- package/dist-server/service/product/product-query.js +5 -5
- package/dist-server/service/product/product-query.js.map +1 -1
- package/dist-server/service/product/product-types.d.ts +4 -2
- package/dist-server/service/product/product-types.js +10 -2
- package/dist-server/service/product/product-types.js.map +1 -1
- package/dist-server/service/product/product.d.ts +2 -1
- package/dist-server/service/product/product.js +6 -1
- package/dist-server/service/product/product.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/constants/index.ts +1 -0
- package/server/constants/product.ts +24 -0
- package/server/controllers/index.ts +0 -0
- package/server/index.ts +2 -0
- package/server/middlewares/index.ts +0 -0
- package/server/migrations/index.ts +9 -0
- package/server/service/index.ts +61 -0
- package/server/service/product/index.ts +6 -0
- package/server/service/product/product-mutation.ts +407 -0
- package/server/service/product/product-query.ts +336 -0
- package/server/service/product/product-types.ts +458 -0
- package/server/service/product/product.ts +548 -0
- package/server/service/product/validate-product.ts +42 -0
- package/server/service/product-bundle/index.ts +6 -0
- package/server/service/product-bundle/product-bundle-mutation.ts +140 -0
- package/server/service/product-bundle/product-bundle-query.ts +104 -0
- package/server/service/product-bundle/product-bundle-types.ts +51 -0
- package/server/service/product-bundle/product-bundle.ts +102 -0
- package/server/service/product-bundle-setting/index.ts +6 -0
- package/server/service/product-bundle-setting/product-bundle-setting-mutation.ts +168 -0
- package/server/service/product-bundle-setting/product-bundle-setting-query.ts +139 -0
- package/server/service/product-bundle-setting/product-bundle-setting-types.ts +41 -0
- package/server/service/product-bundle-setting/product-bundle-setting.ts +45 -0
- package/server/service/product-combination/index.ts +6 -0
- package/server/service/product-combination/product-combination-mutation.ts +148 -0
- package/server/service/product-combination/product-combination-query.ts +48 -0
- package/server/service/product-combination/product-combination-type.ts +50 -0
- package/server/service/product-combination/product-combination.ts +116 -0
- package/server/service/product-combination-setting/index.ts +6 -0
- package/server/service/product-combination-setting/product-combination-setting-mutation.ts +248 -0
- package/server/service/product-combination-setting/product-combination-setting-query.ts +176 -0
- package/server/service/product-combination-setting/product-combination-setting-type.ts +44 -0
- package/server/service/product-combination-setting/product-combination-setting.ts +77 -0
- package/server/service/product-detail/index.ts +6 -0
- package/server/service/product-detail/product-detail-mutation.ts +238 -0
- package/server/service/product-detail/product-detail-query.ts +213 -0
- package/server/service/product-detail/product-detail-types.ts +280 -0
- package/server/service/product-detail/product-detail.ts +388 -0
- package/server/service/product-detail-bizplace-setting/index.ts +6 -0
- package/server/service/product-detail-bizplace-setting/product-detail-bizplace-setting-mutation.ts +118 -0
- package/server/service/product-detail-bizplace-setting/product-detail-bizplace-setting-query.ts +90 -0
- package/server/service/product-detail-bizplace-setting/product-detail-bizplace-setting-types.ts +62 -0
- package/server/service/product-detail-bizplace-setting/product-detail-bizplace-setting.ts +104 -0
- package/server/service/product-set/index.ts +6 -0
- package/server/service/product-set/product-set-mutation.ts +149 -0
- package/server/service/product-set/product-set-query.ts +114 -0
- package/server/service/product-set/product-set-types.ts +45 -0
- package/server/service/product-set/product-set.ts +95 -0
- package/server/utils/index.ts +1 -0
- package/server/utils/product-util.ts +11 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
import { In, Repository } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
5
|
+
import { getRepository } from '@things-factory/shell'
|
|
6
|
+
|
|
7
|
+
import { PRODUCT_BUNDLE_STATUS } from '../../constants'
|
|
8
|
+
import { ProductBundle } from './product-bundle'
|
|
9
|
+
import { NewProductBundle, ProductBundlePatch } from './product-bundle-types'
|
|
10
|
+
|
|
11
|
+
@Resolver(ProductBundle)
|
|
12
|
+
export class ProductBundleMutation {
|
|
13
|
+
@Mutation(returns => ProductBundle)
|
|
14
|
+
async createProductBundle(
|
|
15
|
+
@Arg('productBundle') productBundle: NewProductBundle,
|
|
16
|
+
@Ctx() context: ResolverContext
|
|
17
|
+
): Promise<ProductBundle> {
|
|
18
|
+
const { domain, user } = context.state
|
|
19
|
+
|
|
20
|
+
return await getRepository(ProductBundle).save({
|
|
21
|
+
...productBundle,
|
|
22
|
+
domain,
|
|
23
|
+
creator: user,
|
|
24
|
+
updater: user
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Mutation(returns => ProductBundle)
|
|
29
|
+
async updateProductBundle(
|
|
30
|
+
@Arg('name') name: string,
|
|
31
|
+
@Arg('patch') patch: ProductBundlePatch,
|
|
32
|
+
@Ctx() context: ResolverContext
|
|
33
|
+
): Promise<ProductBundle> {
|
|
34
|
+
const { domain, user } = context.state
|
|
35
|
+
|
|
36
|
+
const repository = getRepository(ProductBundle)
|
|
37
|
+
const productBundle = await repository.findOne({
|
|
38
|
+
where: { domain: { id: domain.id }, name }
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
return await repository.save({
|
|
42
|
+
...productBundle,
|
|
43
|
+
...patch,
|
|
44
|
+
updater: user
|
|
45
|
+
})
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Mutation(returns => [ProductBundle])
|
|
49
|
+
async updateMultipleProductBundle(
|
|
50
|
+
@Arg('patches', type => [ProductBundlePatch]) patches: ProductBundlePatch[],
|
|
51
|
+
@Ctx() context: ResolverContext
|
|
52
|
+
): Promise<ProductBundle[]> {
|
|
53
|
+
const { domain, user } = context.state
|
|
54
|
+
|
|
55
|
+
let results = []
|
|
56
|
+
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
|
57
|
+
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
|
58
|
+
const productBundleRepo = getRepository(ProductBundle)
|
|
59
|
+
const bizplaceRepo = getRepository(Bizplace)
|
|
60
|
+
|
|
61
|
+
let bizplace: Bizplace
|
|
62
|
+
|
|
63
|
+
if (_createRecords.length > 0) {
|
|
64
|
+
for (let i = 0; i < _createRecords.length; i++) {
|
|
65
|
+
let newRecord = _createRecords[i]
|
|
66
|
+
let status = newRecord.status || ''
|
|
67
|
+
|
|
68
|
+
bizplace = await bizplaceRepo.findOne({ where: { name: domain.name } })
|
|
69
|
+
|
|
70
|
+
if (!newRecord.status || newRecord.status === '') {
|
|
71
|
+
newRecord.status = PRODUCT_BUNDLE_STATUS.INACTIVE
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const result = await productBundleRepo.save({
|
|
75
|
+
...newRecord,
|
|
76
|
+
domain,
|
|
77
|
+
bizplace,
|
|
78
|
+
status: newRecord.status.toUpperCase(),
|
|
79
|
+
creator: user,
|
|
80
|
+
updater: user
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
results.push({ ...result, cuFlag: '+' })
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (_updateRecords.length > 0) {
|
|
88
|
+
for (let i = 0; i < _updateRecords.length; i++) {
|
|
89
|
+
const newRecord = _updateRecords[i]
|
|
90
|
+
const productBundle = await productBundleRepo.findOneBy({ domain: { id: domain.id }, id: newRecord.id })
|
|
91
|
+
|
|
92
|
+
if (newRecord.status) {
|
|
93
|
+
newRecord.status = newRecord.status.toUpperCase()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const result = await productBundleRepo.save({
|
|
97
|
+
...productBundle,
|
|
98
|
+
...newRecord,
|
|
99
|
+
updater: user
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
results.push({ ...result, cuFlag: 'M' })
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return results
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Mutation(returns => Boolean)
|
|
110
|
+
async deleteProductBundle(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Boolean> {
|
|
111
|
+
const { domain, user } = context.state
|
|
112
|
+
|
|
113
|
+
await getRepository(ProductBundle).delete({ domain: { id: domain.id }, name })
|
|
114
|
+
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
@Mutation(returns => Boolean)
|
|
119
|
+
async deleteProductBundles(
|
|
120
|
+
@Arg('ids', type => [String]) ids: string[],
|
|
121
|
+
@Ctx() context: ResolverContext
|
|
122
|
+
): Promise<Boolean> {
|
|
123
|
+
const { tx, user } = context.state
|
|
124
|
+
const productBundleRepo: Repository<ProductBundle> = getRepository(ProductBundle) || tx.getRepository(ProductBundle)
|
|
125
|
+
|
|
126
|
+
let productBundles = await productBundleRepo.find({ where: { id: In(ids) } })
|
|
127
|
+
|
|
128
|
+
for (let i = 0; i < productBundles.length; i++) {
|
|
129
|
+
const product = productBundles[i]
|
|
130
|
+
|
|
131
|
+
const result = await productBundleRepo.save({
|
|
132
|
+
...product,
|
|
133
|
+
status: PRODUCT_BUNDLE_STATUS.DELETED,
|
|
134
|
+
updater: user
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return true
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
2
|
+
import { Brackets, SelectQueryBuilder } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { User } from '@things-factory/auth-base'
|
|
5
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
6
|
+
import { buildCondition, buildQuery, convertListParams, Domain, getRepository, ListParam } from '@things-factory/shell'
|
|
7
|
+
|
|
8
|
+
import { PRODUCT_BUNDLE_STATUS } from '../../constants'
|
|
9
|
+
import { ProductBundle } from './product-bundle'
|
|
10
|
+
import { ProductBundleList } from './product-bundle-types'
|
|
11
|
+
|
|
12
|
+
@Resolver(ProductBundle)
|
|
13
|
+
export class ProductBundleQuery {
|
|
14
|
+
@Query(returns => ProductBundleList)
|
|
15
|
+
async myBizplaceProductBundles(
|
|
16
|
+
@Args(type => ListParam) params: ListParam,
|
|
17
|
+
@Ctx() context: ResolverContext
|
|
18
|
+
): Promise<ProductBundleList> {
|
|
19
|
+
const { domain } = context.state
|
|
20
|
+
|
|
21
|
+
const qb: SelectQueryBuilder<ProductBundle> = getRepository(ProductBundle).createQueryBuilder()
|
|
22
|
+
|
|
23
|
+
const productBundleFilter = params.filters.find(x => x.name == 'product_info')
|
|
24
|
+
const productFilterColumns = ['sku', 'name', 'description']
|
|
25
|
+
let filters = params.filters.filter(x => x.name != 'product_info')
|
|
26
|
+
|
|
27
|
+
// add status filter to prevent user to see DELETED product bundles
|
|
28
|
+
filters = [...filters, { name: 'status', operator: 'noteq', value: PRODUCT_BUNDLE_STATUS.DELETED }]
|
|
29
|
+
|
|
30
|
+
if (!params.filters.find(filter => filter.name === 'bizplace_id')) {
|
|
31
|
+
let bizplace: Bizplace = await getRepository(Bizplace).findOne({ where: { domain: { id: domain.id } } })
|
|
32
|
+
params.filters = [...filters, { name: 'bizplace_id', operator: 'in', value: [bizplace.id] }]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
buildQuery(qb, params, context, { domainRef: false })
|
|
36
|
+
if (productBundleFilter) {
|
|
37
|
+
qb.andWhere(
|
|
38
|
+
new Brackets(qb2 => {
|
|
39
|
+
productFilterColumns.forEach(filter => {
|
|
40
|
+
const condition = buildCondition(
|
|
41
|
+
qb.alias,
|
|
42
|
+
filter,
|
|
43
|
+
productBundleFilter.operator,
|
|
44
|
+
productBundleFilter.value,
|
|
45
|
+
productBundleFilter.relation,
|
|
46
|
+
Object.keys(qb.getParameters()).length
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
qb2.orWhere(condition.clause, condition.parameters)
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const [items, total] = await qb
|
|
56
|
+
.leftJoinAndSelect('ProductBundle.productBundleSettings', 'ProductBundleSetting')
|
|
57
|
+
.leftJoinAndSelect('ProductBundleSetting.product', 'Product')
|
|
58
|
+
.leftJoinAndSelect('ProductBundleSetting.productDetail', 'ProductDetail')
|
|
59
|
+
.leftJoinAndSelect('ProductBundle.bizplace', 'Bizplace')
|
|
60
|
+
.leftJoinAndSelect('ProductBundle.creator', 'Creator')
|
|
61
|
+
.leftJoinAndSelect('ProductBundle.updater', 'Updater')
|
|
62
|
+
.getManyAndCount()
|
|
63
|
+
|
|
64
|
+
return { items, total }
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@Query(returns => ProductBundleList)
|
|
68
|
+
async productBundles(
|
|
69
|
+
@Args(type => ListParam) params: ListParam,
|
|
70
|
+
@Ctx() context: ResolverContext
|
|
71
|
+
): Promise<ProductBundleList> {
|
|
72
|
+
const convertedParams = convertListParams(params)
|
|
73
|
+
const [items, total] = await getRepository(ProductBundle).findAndCount({
|
|
74
|
+
...convertedParams
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
return { items, total }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Query(returns => ProductBundle)
|
|
81
|
+
async productBundle(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<ProductBundle> {
|
|
82
|
+
const { domain, user } = context.state
|
|
83
|
+
const repository = getRepository(ProductBundle)
|
|
84
|
+
|
|
85
|
+
return await repository.findOne({
|
|
86
|
+
where: { domain: { id: domain.id }, name }
|
|
87
|
+
})
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
@FieldResolver(type => Domain)
|
|
91
|
+
async domain(@Root() productBundle: ProductBundle): Promise<Domain> {
|
|
92
|
+
return await getRepository(Domain).findOneBy({ id: productBundle.domainId })
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
@FieldResolver(type => User)
|
|
96
|
+
async creator(@Root() productBundle: ProductBundle): Promise<User> {
|
|
97
|
+
return await getRepository(User).findOneBy({ id: productBundle.creatorId })
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@FieldResolver(type => User)
|
|
101
|
+
async updater(@Root() productBundle: ProductBundle): Promise<User> {
|
|
102
|
+
return await getRepository(User).findOneBy({ id: productBundle.updaterId })
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Field, InputType, Int, ObjectType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { ProductBundle } from './product-bundle'
|
|
4
|
+
|
|
5
|
+
@InputType()
|
|
6
|
+
export class NewProductBundle {
|
|
7
|
+
@Field()
|
|
8
|
+
name: string
|
|
9
|
+
|
|
10
|
+
@Field({ nullable: true })
|
|
11
|
+
description?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@ObjectType()
|
|
15
|
+
export class ProductBundleList {
|
|
16
|
+
@Field(type => [ProductBundle], { nullable: true })
|
|
17
|
+
items?: ProductBundle[]
|
|
18
|
+
|
|
19
|
+
@Field(type => Int, { nullable: true })
|
|
20
|
+
total?: number
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@InputType()
|
|
24
|
+
export class ProductBundlePatch {
|
|
25
|
+
@Field({ nullable: true })
|
|
26
|
+
id?: string
|
|
27
|
+
|
|
28
|
+
@Field({ nullable: true })
|
|
29
|
+
sku?: string
|
|
30
|
+
|
|
31
|
+
@Field({ nullable: true })
|
|
32
|
+
name?: string
|
|
33
|
+
|
|
34
|
+
@Field({ nullable: true })
|
|
35
|
+
description?: string
|
|
36
|
+
|
|
37
|
+
@Field({ nullable: true })
|
|
38
|
+
refCode?: string
|
|
39
|
+
|
|
40
|
+
@Field({ nullable: true })
|
|
41
|
+
type?: string
|
|
42
|
+
|
|
43
|
+
@Field({ nullable: true })
|
|
44
|
+
status?: string
|
|
45
|
+
|
|
46
|
+
@Field({ nullable: true })
|
|
47
|
+
packingType?: string
|
|
48
|
+
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
cuFlag?: string
|
|
51
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { User } from '@things-factory/auth-base'
|
|
2
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
3
|
+
import { Domain, roundTransformer } from '@things-factory/shell'
|
|
4
|
+
import { Field, ID, ObjectType } from 'type-graphql'
|
|
5
|
+
import {
|
|
6
|
+
Column,
|
|
7
|
+
CreateDateColumn,
|
|
8
|
+
Entity,
|
|
9
|
+
Index,
|
|
10
|
+
ManyToOne,
|
|
11
|
+
OneToMany,
|
|
12
|
+
PrimaryGeneratedColumn,
|
|
13
|
+
RelationId,
|
|
14
|
+
UpdateDateColumn
|
|
15
|
+
} from 'typeorm'
|
|
16
|
+
import { ProductBundleSetting } from '../product-bundle-setting/product-bundle-setting'
|
|
17
|
+
|
|
18
|
+
@Entity()
|
|
19
|
+
@Index('ix_product_bundle_0', (productBundle: ProductBundle) => [productBundle.domain, productBundle.id], {
|
|
20
|
+
unique: true
|
|
21
|
+
})
|
|
22
|
+
@ObjectType()
|
|
23
|
+
export class ProductBundle {
|
|
24
|
+
@PrimaryGeneratedColumn('uuid')
|
|
25
|
+
@Field(type => ID)
|
|
26
|
+
readonly id: string
|
|
27
|
+
|
|
28
|
+
@ManyToOne(type => Domain)
|
|
29
|
+
@Field(type => Domain)
|
|
30
|
+
domain: Domain
|
|
31
|
+
|
|
32
|
+
@RelationId((productBundle: ProductBundle) => productBundle.domain)
|
|
33
|
+
domainId: string
|
|
34
|
+
|
|
35
|
+
@ManyToOne(type => Bizplace, {
|
|
36
|
+
nullable: false
|
|
37
|
+
})
|
|
38
|
+
@Field({ nullable: true })
|
|
39
|
+
bizplace: Bizplace
|
|
40
|
+
|
|
41
|
+
@OneToMany(type => ProductBundleSetting, productBundleSetting => productBundleSetting.productBundle)
|
|
42
|
+
@Field(type => [ProductBundleSetting])
|
|
43
|
+
productBundleSettings: ProductBundleSetting[]
|
|
44
|
+
|
|
45
|
+
@Column()
|
|
46
|
+
@Field()
|
|
47
|
+
sku: string
|
|
48
|
+
|
|
49
|
+
@Column({ nullable: true })
|
|
50
|
+
@Field({ nullable: true })
|
|
51
|
+
refCode: string
|
|
52
|
+
|
|
53
|
+
@Column()
|
|
54
|
+
@Field()
|
|
55
|
+
name: string
|
|
56
|
+
|
|
57
|
+
@Column({ nullable: true })
|
|
58
|
+
@Field({ nullable: true })
|
|
59
|
+
description: string
|
|
60
|
+
|
|
61
|
+
@Column({ nullable: true })
|
|
62
|
+
@Field({ nullable: true })
|
|
63
|
+
type: string
|
|
64
|
+
|
|
65
|
+
@Column()
|
|
66
|
+
@Field()
|
|
67
|
+
status: string
|
|
68
|
+
|
|
69
|
+
@Column()
|
|
70
|
+
@Field()
|
|
71
|
+
packingType: string
|
|
72
|
+
|
|
73
|
+
@Column({ type: 'float', default: 1, transformer: roundTransformer })
|
|
74
|
+
@Field()
|
|
75
|
+
packingSize: number
|
|
76
|
+
|
|
77
|
+
@CreateDateColumn()
|
|
78
|
+
@Field({ nullable: true })
|
|
79
|
+
createdAt: Date
|
|
80
|
+
|
|
81
|
+
@UpdateDateColumn()
|
|
82
|
+
@Field({ nullable: true })
|
|
83
|
+
updatedAt: Date
|
|
84
|
+
|
|
85
|
+
@ManyToOne(type => User, {
|
|
86
|
+
nullable: true
|
|
87
|
+
})
|
|
88
|
+
@Field({ nullable: true })
|
|
89
|
+
creator: User
|
|
90
|
+
|
|
91
|
+
@RelationId((productBundle: ProductBundle) => productBundle.creator)
|
|
92
|
+
creatorId: string
|
|
93
|
+
|
|
94
|
+
@ManyToOne(type => User, {
|
|
95
|
+
nullable: true
|
|
96
|
+
})
|
|
97
|
+
@Field({ nullable: true })
|
|
98
|
+
updater: User
|
|
99
|
+
|
|
100
|
+
@RelationId((productBundle: ProductBundle) => productBundle.updater)
|
|
101
|
+
updaterId: string
|
|
102
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ProductBundleSetting } from './product-bundle-setting'
|
|
2
|
+
import { ProductBundleSettingMutation } from './product-bundle-setting-mutation'
|
|
3
|
+
import { ProductBundleSettingQuery } from './product-bundle-setting-query'
|
|
4
|
+
|
|
5
|
+
export const entities = [ProductBundleSetting]
|
|
6
|
+
export const resolvers = [ProductBundleSettingQuery, ProductBundleSettingMutation]
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
import { EntityManager, In, SelectQueryBuilder } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { getRepository } from '@things-factory/shell'
|
|
5
|
+
|
|
6
|
+
import { ProductBundleSetting } from './product-bundle-setting'
|
|
7
|
+
import { ProductBundleSettingPatch } from './product-bundle-setting-types'
|
|
8
|
+
|
|
9
|
+
const debug = require('debug')('things-factory:product-base:productBundle')
|
|
10
|
+
|
|
11
|
+
@Resolver(ProductBundleSetting)
|
|
12
|
+
export class ProductBundleSettingMutation {
|
|
13
|
+
@Mutation(returns => [ProductBundleSetting])
|
|
14
|
+
async updateMultipleProductBundleSetting(
|
|
15
|
+
@Arg('patches', type => [ProductBundleSettingPatch]) patches: ProductBundleSettingPatch[],
|
|
16
|
+
@Ctx() context: ResolverContext
|
|
17
|
+
): Promise<ProductBundleSetting[]> {
|
|
18
|
+
return await updateMultipleProductBundleSetting(patches)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@Mutation(returns => Boolean)
|
|
22
|
+
async deleteProductBundleSetting(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Boolean> {
|
|
23
|
+
await getRepository(ProductBundleSetting).delete({ id })
|
|
24
|
+
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@Mutation(returns => Boolean)
|
|
29
|
+
async deleteProductBundleSettings(
|
|
30
|
+
@Arg('ids', type => [String]) ids: string[],
|
|
31
|
+
@Ctx() context: ResolverContext
|
|
32
|
+
): Promise<Boolean> {
|
|
33
|
+
await getRepository(ProductBundleSetting).delete({
|
|
34
|
+
product: In(ids)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@Directive('@transaction')
|
|
41
|
+
@Mutation(returns => Boolean)
|
|
42
|
+
async linkProductBundle(
|
|
43
|
+
@Arg('productBundleId') productBundleId: string,
|
|
44
|
+
@Arg('patches', type => [ProductBundleSettingPatch]) patches: ProductBundleSettingPatch[],
|
|
45
|
+
@Ctx() context: ResolverContext
|
|
46
|
+
): Promise<Boolean> {
|
|
47
|
+
try {
|
|
48
|
+
const { domain, tx } = context.state
|
|
49
|
+
|
|
50
|
+
// const existingBundleLink: ProductBundleSetting[] = await tx.getRepository(ProductBundleSetting).find({
|
|
51
|
+
// where: { productBundle: productBundleId },
|
|
52
|
+
// relations: ['product', 'productDetail', 'productBundle']
|
|
53
|
+
// })
|
|
54
|
+
|
|
55
|
+
const qb: SelectQueryBuilder<ProductBundleSetting> = tx
|
|
56
|
+
.getRepository(ProductBundleSetting)
|
|
57
|
+
.createQueryBuilder('pbs')
|
|
58
|
+
.innerJoinAndSelect('pbs.product', 'prd')
|
|
59
|
+
.innerJoinAndSelect('pbs.productDetail', 'pd')
|
|
60
|
+
.innerJoinAndSelect('pbs.productBundle', 'pb')
|
|
61
|
+
.where('pb.id = :productBundleId', { productBundleId })
|
|
62
|
+
.andWhere('pb.domain_id = :domainId', { domainId: domain.id })
|
|
63
|
+
|
|
64
|
+
const existingBundleLink = await qb.getMany()
|
|
65
|
+
|
|
66
|
+
let newBundleLink: ProductBundleSetting[] = patches.reduce((acc, curr) => {
|
|
67
|
+
if (
|
|
68
|
+
!existingBundleLink.find(
|
|
69
|
+
item => item.product.id === curr.product.id && item.productDetail.id === curr.productDetail.id
|
|
70
|
+
)
|
|
71
|
+
) {
|
|
72
|
+
acc.push({
|
|
73
|
+
productBundle: { id: productBundleId },
|
|
74
|
+
product: { id: curr.product.id },
|
|
75
|
+
productDetail: { id: curr.productDetail.id },
|
|
76
|
+
bundleQty: curr.bundleQty,
|
|
77
|
+
cuFlag: '+'
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
// check if there is existing bundle link but changes in bundle qty
|
|
81
|
+
else if (
|
|
82
|
+
existingBundleLink.find(
|
|
83
|
+
item =>
|
|
84
|
+
item.product.id === curr.product.id &&
|
|
85
|
+
item.productDetail.id === curr.productDetail.id &&
|
|
86
|
+
item.bundleQty !== curr.bundleQty
|
|
87
|
+
)
|
|
88
|
+
) {
|
|
89
|
+
acc.push({
|
|
90
|
+
id: curr.id,
|
|
91
|
+
productBundle: { id: productBundleId },
|
|
92
|
+
product: { id: curr.product.id },
|
|
93
|
+
productDetail: { id: curr.productDetail.id },
|
|
94
|
+
bundleQty: curr.bundleQty,
|
|
95
|
+
cuFlag: 'M'
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
return acc
|
|
99
|
+
}, [])
|
|
100
|
+
|
|
101
|
+
let removeBundleLink: ProductBundleSetting[] = existingBundleLink.reduce((acc, curr) => {
|
|
102
|
+
if (!patches.find(item => item.id == curr.id)) {
|
|
103
|
+
acc.push({
|
|
104
|
+
id: curr.id,
|
|
105
|
+
productBundle: { id: productBundleId },
|
|
106
|
+
product: { id: curr.product.id },
|
|
107
|
+
productDetail: { id: curr.productDetail.id },
|
|
108
|
+
bundleQty: curr.bundleQty
|
|
109
|
+
})
|
|
110
|
+
}
|
|
111
|
+
return acc
|
|
112
|
+
}, [])
|
|
113
|
+
|
|
114
|
+
if (newBundleLink.length > 0) {
|
|
115
|
+
await updateMultipleProductBundleSetting(newBundleLink, tx)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (removeBundleLink.length > 0) {
|
|
119
|
+
await tx.getRepository(ProductBundleSetting).delete({
|
|
120
|
+
id: In(removeBundleLink.map(bundleLink => bundleLink.id))
|
|
121
|
+
})
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return true
|
|
125
|
+
} catch (error) {
|
|
126
|
+
debug('link-product-bundle', error)
|
|
127
|
+
throw error
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export async function updateMultipleProductBundleSetting(
|
|
133
|
+
patches: ProductBundleSettingPatch[],
|
|
134
|
+
tx?: EntityManager
|
|
135
|
+
): Promise<ProductBundleSetting[]> {
|
|
136
|
+
let results = []
|
|
137
|
+
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
|
138
|
+
const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
|
|
139
|
+
const productBundleSettingRepo = tx.getRepository(ProductBundleSetting)
|
|
140
|
+
|
|
141
|
+
if (_createRecords.length > 0) {
|
|
142
|
+
for (let i = 0; i < _createRecords.length; i++) {
|
|
143
|
+
const newRecord = _createRecords[i]
|
|
144
|
+
|
|
145
|
+
const result = await productBundleSettingRepo.save({
|
|
146
|
+
...newRecord
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
results.push({ ...result, cuFlag: '+' })
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (_updateRecords.length > 0) {
|
|
154
|
+
for (let i = 0; i < _updateRecords.length; i++) {
|
|
155
|
+
const newRecord = _updateRecords[i]
|
|
156
|
+
const productBundleSetting = await productBundleSettingRepo.findOneBy({ id: newRecord.id })
|
|
157
|
+
|
|
158
|
+
const result = await productBundleSettingRepo.save({
|
|
159
|
+
...productBundleSetting,
|
|
160
|
+
...newRecord
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
results.push({ ...result, cuFlag: 'M' })
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return results
|
|
168
|
+
}
|