@things-factory/sales-base 4.3.769 → 4.3.771
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/draft-release-good/draft-release-good-create.js +138 -139
- package/dist-server/service/draft-release-good/draft-release-good-create.js.map +1 -1
- package/dist-server/service/index.js +16 -2
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/loading-package-items/index.js +9 -0
- package/dist-server/service/loading-package-items/index.js.map +1 -0
- package/dist-server/service/loading-package-items/loading-package-items-mutation.js +120 -0
- package/dist-server/service/loading-package-items/loading-package-items-mutation.js.map +1 -0
- package/dist-server/service/loading-package-items/loading-package-items-query.js +87 -0
- package/dist-server/service/loading-package-items/loading-package-items-query.js.map +1 -0
- package/dist-server/service/loading-package-items/loading-package-items-type.js +77 -0
- package/dist-server/service/loading-package-items/loading-package-items-type.js.map +1 -0
- package/dist-server/service/loading-package-items/loading-package-items.js +173 -0
- package/dist-server/service/loading-package-items/loading-package-items.js.map +1 -0
- package/dist-server/service/loading-packages/index.js +9 -0
- package/dist-server/service/loading-packages/index.js.map +1 -0
- package/dist-server/service/loading-packages/loading-packages-mutation.js +151 -0
- package/dist-server/service/loading-packages/loading-packages-mutation.js.map +1 -0
- package/dist-server/service/loading-packages/loading-packages-query.js +316 -0
- package/dist-server/service/loading-packages/loading-packages-query.js.map +1 -0
- package/dist-server/service/loading-packages/loading-packages-type.js +77 -0
- package/dist-server/service/loading-packages/loading-packages-type.js.map +1 -0
- package/dist-server/service/loading-packages/loading-packages.js +138 -0
- package/dist-server/service/loading-packages/loading-packages.js.map +1 -0
- package/dist-server/service/order-inventory/order-inventory.js +1 -0
- package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
- package/dist-server/service/release-good/release-good-mutation.js +48 -15
- package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +61 -3
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/dist-server/service/release-good/release-good-types.js +15 -1
- package/dist-server/service/release-good/release-good-types.js.map +1 -1
- package/dist-server/service/release-good/release-good.js +4 -0
- package/dist-server/service/release-good/release-good.js.map +1 -1
- package/dist-server/utils/inventory-util.js +6 -2
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/dist-server/utils/order-no-generator.js +8 -0
- package/dist-server/utils/order-no-generator.js.map +1 -1
- package/package.json +8 -8
- package/server/service/draft-release-good/draft-release-good-create.ts +201 -206
- package/server/service/index.ts +16 -2
- package/server/service/loading-package-items/index.ts +6 -0
- package/server/service/loading-package-items/loading-package-items-mutation.ts +112 -0
- package/server/service/loading-package-items/loading-package-items-query.ts +43 -0
- package/server/service/loading-package-items/loading-package-items-type.ts +45 -0
- package/server/service/loading-package-items/loading-package-items.ts +140 -0
- package/server/service/loading-packages/index.ts +6 -0
- package/server/service/loading-packages/loading-packages-mutation.ts +150 -0
- package/server/service/loading-packages/loading-packages-query.ts +272 -0
- package/server/service/loading-packages/loading-packages-type.ts +45 -0
- package/server/service/loading-packages/loading-packages.ts +110 -0
- package/server/service/order-inventory/order-inventory.ts +1 -0
- package/server/service/release-good/release-good-mutation.ts +49 -21
- package/server/service/release-good/release-good-query.ts +103 -36
- package/server/service/release-good/release-good-types.ts +9 -0
- package/server/service/release-good/release-good.ts +5 -1
- package/server/utils/inventory-util.ts +7 -2
- package/server/utils/order-no-generator.ts +12 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive, Int } from 'type-graphql'
|
|
2
|
+
import { getRepository, In, IsNull } from 'typeorm'
|
|
3
|
+
import { Domain, ListParam, convertListParams } from '@things-factory/shell'
|
|
4
|
+
import { User } from '@things-factory/auth-base'
|
|
5
|
+
import { ReleaseGood } from '../'
|
|
6
|
+
import { LoadingPackages } from './loading-packages'
|
|
7
|
+
import { LoadingPackagesList } from './loading-packages-type'
|
|
8
|
+
|
|
9
|
+
@Resolver(LoadingPackages)
|
|
10
|
+
export class LoadingPackagesQuery {
|
|
11
|
+
@Query(returns => LoadingPackages, { description: 'To fetch a LoadingPackages' })
|
|
12
|
+
async loadingPackage(@Arg('id') id: string, @Ctx() context: any): Promise<LoadingPackages> {
|
|
13
|
+
const { domain } = context.state
|
|
14
|
+
|
|
15
|
+
return await getRepository(LoadingPackages).findOne({
|
|
16
|
+
where: { domain, id, deletedAt: IsNull() }
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Query(returns => LoadingPackagesList, { description: 'To fetch multiple LoadingPackages' })
|
|
21
|
+
async loadingPackages(@Args() params: ListParam, @Ctx() context: any): Promise<LoadingPackagesList> {
|
|
22
|
+
const { domain } = context.state
|
|
23
|
+
|
|
24
|
+
const convertedParams = convertListParams(params, domain.id)
|
|
25
|
+
const [items, total] = await getRepository(LoadingPackages).findAndCount(convertedParams)
|
|
26
|
+
|
|
27
|
+
return { items, total }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Query(returns => [LoadingPackages], { description: 'To fetch LoadingPackages by releaseGoodNo' })
|
|
31
|
+
async loadingPackagesByReleaseGoodNo(@Arg('releaseGoodNo') releaseGoodNo: string, @Ctx() context: any): Promise<LoadingPackages[]> {
|
|
32
|
+
const { domain } = context.state
|
|
33
|
+
|
|
34
|
+
const releaseGood = await getRepository(ReleaseGood).findOne({
|
|
35
|
+
where: { domain, name: releaseGoodNo }
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
if (!releaseGood) {
|
|
39
|
+
return []
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return await getRepository(LoadingPackages).find({
|
|
43
|
+
where: { domain, releaseGood, deletedAt: IsNull() },
|
|
44
|
+
relations: [
|
|
45
|
+
'loadingPackageItems',
|
|
46
|
+
'loadingPackageItems.orderProduct',
|
|
47
|
+
'loadingPackageItems.orderProduct.product',
|
|
48
|
+
'loadingPackageItems.productDetail',
|
|
49
|
+
'releaseGood',
|
|
50
|
+
'bizplace'
|
|
51
|
+
],
|
|
52
|
+
order: { createdAt: 'ASC' }
|
|
53
|
+
})
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@Query(returns => [LoadingPackages], { description: 'To fetch LoadingPackages by multiple releaseGoodNos' })
|
|
57
|
+
async loadingPackagesByReleaseGoodNos(
|
|
58
|
+
@Arg('releaseGoodNos', type => [String]) releaseGoodNos: string[],
|
|
59
|
+
@Ctx() context: any
|
|
60
|
+
): Promise<LoadingPackages[]> {
|
|
61
|
+
const { domain } = context.state
|
|
62
|
+
|
|
63
|
+
// Step 1: Check if releaseGoodNos is empty
|
|
64
|
+
if (!releaseGoodNos || releaseGoodNos.length === 0) {
|
|
65
|
+
throw new Error('No release goods numbers provided')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Step 2: Make them into distinct values
|
|
69
|
+
const distinctReleaseGoodNos = [...new Set(releaseGoodNos.filter(no => no && no.trim()))]
|
|
70
|
+
|
|
71
|
+
if (distinctReleaseGoodNos.length === 0) {
|
|
72
|
+
throw new Error('No valid release goods numbers provided')
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Step 3: Use distinct array to search in the DB
|
|
76
|
+
const releaseGoods = await getRepository(ReleaseGood).find({
|
|
77
|
+
where: { domain, name: In(distinctReleaseGoodNos) }
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Step 4: Check if the length returned matches the distinct array
|
|
81
|
+
if (releaseGoods.length !== distinctReleaseGoodNos.length) {
|
|
82
|
+
const foundNames = releaseGoods.map(rg => rg.name)
|
|
83
|
+
const notFoundNames = distinctReleaseGoodNos.filter(name => !foundNames.includes(name))
|
|
84
|
+
throw new Error(`Release good number(s) not found: ${notFoundNames.join(', ')}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Step 5: Fetch loading packages and loading package items
|
|
88
|
+
const releaseGoodIds = releaseGoods.map(rg => rg.id)
|
|
89
|
+
|
|
90
|
+
return await getRepository(LoadingPackages)
|
|
91
|
+
.createQueryBuilder('lp')
|
|
92
|
+
.leftJoinAndSelect('lp.loadingPackageItems', 'lpi')
|
|
93
|
+
.leftJoinAndSelect('lpi.orderProduct', 'op')
|
|
94
|
+
.leftJoinAndSelect('op.product', 'product')
|
|
95
|
+
.leftJoinAndSelect('lpi.productDetail', 'pd')
|
|
96
|
+
.leftJoinAndSelect('lp.releaseGood', 'rg')
|
|
97
|
+
.leftJoinAndSelect('rg.bizplace', 'bizplace')
|
|
98
|
+
.where('lp.domain_id = :domainId', { domainId: domain.id })
|
|
99
|
+
.andWhere('lp.release_good_id IN (:...releaseGoodIds)', { releaseGoodIds })
|
|
100
|
+
.andWhere('lp.deleted_at IS NULL')
|
|
101
|
+
.andWhere('lpi.deleted_at IS NULL')
|
|
102
|
+
.orderBy('lp.release_good_id', 'ASC')
|
|
103
|
+
.addOrderBy('lp.created_at', 'ASC')
|
|
104
|
+
.getMany()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Query(returns => LoadingPackagesList, { description: 'To fetch printed LoadingPackages history with pagination' })
|
|
108
|
+
async printedLoadingPackagesHistory(@Args() params: ListParam, @Ctx() context: any): Promise<LoadingPackagesList> {
|
|
109
|
+
const { domain } = context.state
|
|
110
|
+
|
|
111
|
+
const convertedParams = convertListParams(params, domain.id)
|
|
112
|
+
|
|
113
|
+
// Extract filters from params
|
|
114
|
+
const orderNoFilter = params.filters?.find(f => f.name === 'releaseGood.name')
|
|
115
|
+
const displayNumberFilter = params.filters?.find(f => f.name === 'displayNumber')
|
|
116
|
+
|
|
117
|
+
// Build parameters for raw query
|
|
118
|
+
const queryParams: any[] = [domain.id]
|
|
119
|
+
let paramIndex = 2
|
|
120
|
+
|
|
121
|
+
// Build WHERE clauses for filters
|
|
122
|
+
let orderNoClause = ''
|
|
123
|
+
if (orderNoFilter?.value) {
|
|
124
|
+
orderNoClause = `AND (rg.name ILIKE $${paramIndex} OR rg.ref_no ILIKE $${paramIndex})`
|
|
125
|
+
queryParams.push(`%${orderNoFilter.value}%`)
|
|
126
|
+
paramIndex++
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
let displayNumberClause = ''
|
|
130
|
+
if (displayNumberFilter?.value) {
|
|
131
|
+
const displayNumber = parseInt(displayNumberFilter.value)
|
|
132
|
+
if (!isNaN(displayNumber)) {
|
|
133
|
+
displayNumberClause = `AND dn.display_number = $${paramIndex}`
|
|
134
|
+
queryParams.push(displayNumber)
|
|
135
|
+
paramIndex++
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Build sorting - map frontend column names to subquery column names
|
|
140
|
+
const columnMapping: Record<string, string> = {
|
|
141
|
+
releaseGood: 'rg_name',
|
|
142
|
+
refNo: 'rg_ref_no',
|
|
143
|
+
displayNumber: 'display_number',
|
|
144
|
+
printedAt: 'printed_at',
|
|
145
|
+
printedBy: 'user_name'
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
let orderByClause = 'ORDER BY dn.printed_at DESC'
|
|
149
|
+
if (convertedParams.order) {
|
|
150
|
+
const sortParts = Object.entries(convertedParams.order)
|
|
151
|
+
.map(([key, direction]) => {
|
|
152
|
+
const mappedColumn = columnMapping[key] || key
|
|
153
|
+
return `dn.${mappedColumn} ${direction}`
|
|
154
|
+
})
|
|
155
|
+
if (sortParts.length > 0) {
|
|
156
|
+
orderByClause = `ORDER BY ${sortParts.join(', ')}`
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Pagination
|
|
161
|
+
const skip = convertedParams.skip || 0
|
|
162
|
+
const take = convertedParams.take || 50
|
|
163
|
+
|
|
164
|
+
// Single query: Get all data with display numbers and total count using window functions
|
|
165
|
+
const query = `
|
|
166
|
+
SELECT
|
|
167
|
+
dn.id,
|
|
168
|
+
dn.name,
|
|
169
|
+
dn.printed_at as "printedAt",
|
|
170
|
+
dn.display_number as "displayNumber",
|
|
171
|
+
COUNT(*) OVER() as total_count,
|
|
172
|
+
dn.rg_id as "releaseGood_id",
|
|
173
|
+
dn.rg_name as "releaseGood_name",
|
|
174
|
+
dn.rg_ref_no as "releaseGood_refNo",
|
|
175
|
+
dn.user_id as "printedBy_id",
|
|
176
|
+
dn.user_name as "printedBy_name",
|
|
177
|
+
dn.user_description as "printedBy_description"
|
|
178
|
+
FROM (
|
|
179
|
+
SELECT
|
|
180
|
+
lp.id,
|
|
181
|
+
lp.name,
|
|
182
|
+
lp.printed_at,
|
|
183
|
+
ROW_NUMBER() OVER (PARTITION BY lp.release_good_id ORDER BY lp.created_at ASC) as display_number,
|
|
184
|
+
rg.id as rg_id,
|
|
185
|
+
rg.name as rg_name,
|
|
186
|
+
rg.ref_no as rg_ref_no,
|
|
187
|
+
u.id as user_id,
|
|
188
|
+
u.name as user_name,
|
|
189
|
+
u.description as user_description
|
|
190
|
+
FROM loading_packages lp
|
|
191
|
+
LEFT JOIN release_goods rg ON rg.id = lp.release_good_id
|
|
192
|
+
LEFT JOIN users u ON u.id = lp.printed_by_id
|
|
193
|
+
WHERE lp.domain_id = $1
|
|
194
|
+
AND lp.deleted_at IS NULL
|
|
195
|
+
AND lp.printed_at IS NOT NULL
|
|
196
|
+
${orderNoClause}
|
|
197
|
+
) dn
|
|
198
|
+
WHERE 1=1 ${displayNumberClause}
|
|
199
|
+
${orderByClause}
|
|
200
|
+
LIMIT ${take} OFFSET ${skip}
|
|
201
|
+
`
|
|
202
|
+
|
|
203
|
+
const results: any[] = await getRepository(LoadingPackages).query(query, queryParams)
|
|
204
|
+
|
|
205
|
+
if (results.length === 0) {
|
|
206
|
+
return { items: [], total: 0 }
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Get total from first row (same for all rows due to COUNT(*) OVER())
|
|
210
|
+
const total = parseInt(results[0]?.total_count) || 0
|
|
211
|
+
|
|
212
|
+
// Map raw results to entity structure
|
|
213
|
+
const items = results.map(row => ({
|
|
214
|
+
id: row.id,
|
|
215
|
+
name: row.name,
|
|
216
|
+
printedAt: row.printedAt,
|
|
217
|
+
displayNumber: parseInt(row.displayNumber) || 0,
|
|
218
|
+
releaseGood: row.releaseGood_id ? {
|
|
219
|
+
id: row.releaseGood_id,
|
|
220
|
+
name: row.releaseGood_name,
|
|
221
|
+
refNo: row.releaseGood_refNo
|
|
222
|
+
} : null,
|
|
223
|
+
printedBy: row.printedBy_id ? {
|
|
224
|
+
id: row.printedBy_id,
|
|
225
|
+
name: row.printedBy_name,
|
|
226
|
+
description: row.printedBy_description
|
|
227
|
+
} : null
|
|
228
|
+
})) as LoadingPackages[]
|
|
229
|
+
|
|
230
|
+
return { items, total }
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@Query(returns => Int, { description: 'To get the maximum packing label count across all release goods' })
|
|
234
|
+
async maxPackingLabelCount(@Ctx() context: any): Promise<number> {
|
|
235
|
+
const { domain } = context.state
|
|
236
|
+
|
|
237
|
+
const result = await getRepository(LoadingPackages)
|
|
238
|
+
.createQueryBuilder('lp')
|
|
239
|
+
.select('rg.id', 'releaseGoodId')
|
|
240
|
+
.addSelect('COUNT(lp.id)', 'count')
|
|
241
|
+
.leftJoin('lp.releaseGood', 'rg')
|
|
242
|
+
.where('lp.domain_id = :domainId', { domainId: domain.id })
|
|
243
|
+
.andWhere('lp.deleted_at IS NULL')
|
|
244
|
+
.andWhere('lp.printed_at IS NOT NULL')
|
|
245
|
+
.groupBy('rg.id')
|
|
246
|
+
.orderBy('count', 'DESC')
|
|
247
|
+
.limit(1)
|
|
248
|
+
.getRawOne()
|
|
249
|
+
|
|
250
|
+
return result ? parseInt(result.count) : 0
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@FieldResolver(type => Domain)
|
|
254
|
+
async domain(@Root() loadingPackages: LoadingPackages): Promise<Domain> {
|
|
255
|
+
return await getRepository(Domain).findOne(loadingPackages.domainId)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@FieldResolver(type => User)
|
|
259
|
+
async updater(@Root() loadingPackages: LoadingPackages): Promise<User> {
|
|
260
|
+
return await getRepository(User).findOne(loadingPackages.updaterId)
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@FieldResolver(type => User)
|
|
264
|
+
async creator(@Root() loadingPackages: LoadingPackages): Promise<User> {
|
|
265
|
+
return await getRepository(User).findOne(loadingPackages.creatorId)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
@FieldResolver(type => User)
|
|
269
|
+
async printedBy(@Root() loadingPackages: LoadingPackages): Promise<User> {
|
|
270
|
+
return await getRepository(User).findOne(loadingPackages.printedById)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { LoadingPackages } from './loading-packages'
|
|
4
|
+
|
|
5
|
+
@InputType()
|
|
6
|
+
export class NewLoadingPackages {
|
|
7
|
+
@Field()
|
|
8
|
+
name: string
|
|
9
|
+
|
|
10
|
+
@Field({ nullable: true })
|
|
11
|
+
description?: string
|
|
12
|
+
|
|
13
|
+
@Field({ nullable: true })
|
|
14
|
+
active?: boolean
|
|
15
|
+
|
|
16
|
+
@Field({ nullable: true })
|
|
17
|
+
params?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@InputType()
|
|
21
|
+
export class LoadingPackagesPatch {
|
|
22
|
+
@Field(type => ID, { nullable: true })
|
|
23
|
+
id?: string
|
|
24
|
+
|
|
25
|
+
@Field({ nullable: true })
|
|
26
|
+
name?: string
|
|
27
|
+
|
|
28
|
+
@Field({ nullable: true })
|
|
29
|
+
description?: string
|
|
30
|
+
|
|
31
|
+
@Field({ nullable: true })
|
|
32
|
+
active?: boolean
|
|
33
|
+
|
|
34
|
+
@Field()
|
|
35
|
+
cuFlag: string
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@ObjectType()
|
|
39
|
+
export class LoadingPackagesList {
|
|
40
|
+
@Field(type => [LoadingPackages])
|
|
41
|
+
items: LoadingPackages[]
|
|
42
|
+
|
|
43
|
+
@Field(type => Int)
|
|
44
|
+
total: number
|
|
45
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CreateDateColumn,
|
|
3
|
+
UpdateDateColumn,
|
|
4
|
+
Entity,
|
|
5
|
+
Index,
|
|
6
|
+
Column,
|
|
7
|
+
RelationId,
|
|
8
|
+
OneToMany,
|
|
9
|
+
ManyToOne,
|
|
10
|
+
PrimaryGeneratedColumn
|
|
11
|
+
} from 'typeorm'
|
|
12
|
+
import { ObjectType, Field, Int, ID, registerEnumType } from 'type-graphql'
|
|
13
|
+
|
|
14
|
+
import { Domain } from '@things-factory/shell'
|
|
15
|
+
import { User } from '@things-factory/auth-base'
|
|
16
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
17
|
+
import { ReleaseGood } from '../'
|
|
18
|
+
import { LoadingPackageItems } from '../loading-package-items/loading-package-items'
|
|
19
|
+
|
|
20
|
+
@Entity()
|
|
21
|
+
@Index('ix_loading_packages_0', (loadingPackages: LoadingPackages) => [loadingPackages.domain, loadingPackages.name], { unique: true })
|
|
22
|
+
@ObjectType({ description: 'Entity for LoadingPackages' })
|
|
23
|
+
export class LoadingPackages {
|
|
24
|
+
@PrimaryGeneratedColumn('uuid')
|
|
25
|
+
@Field(type => ID)
|
|
26
|
+
readonly id: string
|
|
27
|
+
|
|
28
|
+
@Column()
|
|
29
|
+
@Field()
|
|
30
|
+
name: string
|
|
31
|
+
|
|
32
|
+
@Column({ nullable: true })
|
|
33
|
+
@Field({ nullable: true })
|
|
34
|
+
status: string
|
|
35
|
+
|
|
36
|
+
@ManyToOne(type => Domain)
|
|
37
|
+
@Field({ nullable: true })
|
|
38
|
+
domain?: Domain
|
|
39
|
+
|
|
40
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.domain)
|
|
41
|
+
domainId?: string
|
|
42
|
+
|
|
43
|
+
@ManyToOne(type => Bizplace)
|
|
44
|
+
@Field(type => Bizplace, { nullable: true })
|
|
45
|
+
bizplace?: Bizplace
|
|
46
|
+
|
|
47
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.bizplace)
|
|
48
|
+
bizplaceId?: string
|
|
49
|
+
|
|
50
|
+
@ManyToOne(type => ReleaseGood)
|
|
51
|
+
@Field(type => ReleaseGood, { nullable: true })
|
|
52
|
+
releaseGood?: ReleaseGood
|
|
53
|
+
|
|
54
|
+
@OneToMany(type => LoadingPackageItems, loadingPackageItems => loadingPackageItems.loadingPackage)
|
|
55
|
+
@Field(type => [LoadingPackageItems], { nullable: true })
|
|
56
|
+
loadingPackageItems: LoadingPackageItems[]
|
|
57
|
+
|
|
58
|
+
@CreateDateColumn()
|
|
59
|
+
@Field({ nullable: true })
|
|
60
|
+
createdAt?: Date
|
|
61
|
+
|
|
62
|
+
@UpdateDateColumn()
|
|
63
|
+
@Field({ nullable: true })
|
|
64
|
+
updatedAt?: Date
|
|
65
|
+
|
|
66
|
+
@ManyToOne(type => User, {
|
|
67
|
+
nullable: true
|
|
68
|
+
})
|
|
69
|
+
@Field({ nullable: true })
|
|
70
|
+
creator?: User
|
|
71
|
+
|
|
72
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.creator)
|
|
73
|
+
creatorId?: string
|
|
74
|
+
|
|
75
|
+
@ManyToOne(type => User, {
|
|
76
|
+
nullable: true
|
|
77
|
+
})
|
|
78
|
+
@Field({ nullable: true })
|
|
79
|
+
updater?: User
|
|
80
|
+
|
|
81
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.updater)
|
|
82
|
+
updaterId?: string
|
|
83
|
+
|
|
84
|
+
@ManyToOne(type => User, {
|
|
85
|
+
nullable: true
|
|
86
|
+
})
|
|
87
|
+
@Field({ nullable: true })
|
|
88
|
+
printedBy?: User
|
|
89
|
+
|
|
90
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.printedBy)
|
|
91
|
+
printedById?: string
|
|
92
|
+
|
|
93
|
+
@Column({ nullable: true })
|
|
94
|
+
@Field({ nullable: true })
|
|
95
|
+
printedAt?: Date
|
|
96
|
+
|
|
97
|
+
@Column({ nullable: true })
|
|
98
|
+
@Field({ nullable: true })
|
|
99
|
+
deletedAt?: Date
|
|
100
|
+
|
|
101
|
+
@ManyToOne(type => User, { nullable: true })
|
|
102
|
+
@Field({ nullable: true })
|
|
103
|
+
deletedBy?: User
|
|
104
|
+
|
|
105
|
+
@RelationId((loadingPackages: LoadingPackages) => loadingPackages.deletedBy)
|
|
106
|
+
deletedById?: string
|
|
107
|
+
|
|
108
|
+
@Field(type => Int, { nullable: true })
|
|
109
|
+
displayNumber?: number
|
|
110
|
+
}
|
|
@@ -227,6 +227,7 @@ export class OrderInventory {
|
|
|
227
227
|
orderProduct: OrderProduct
|
|
228
228
|
|
|
229
229
|
@RelationId((orderInventory: OrderInventory) => orderInventory.orderProduct)
|
|
230
|
+
@Field({ nullable: true })
|
|
230
231
|
orderProductId: string
|
|
231
232
|
|
|
232
233
|
@OneToMany(type => OrderToteItem, orderToteItem => orderToteItem.orderInventory, { nullable: true })
|
|
@@ -476,14 +476,19 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
|
|
|
476
476
|
await Promise.all(
|
|
477
477
|
foundOIs.map(async (oi: OrderInventory) => {
|
|
478
478
|
if (oi?.inventory?.id) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
479
|
+
await tx
|
|
480
|
+
.getRepository(Inventory)
|
|
481
|
+
.createQueryBuilder()
|
|
482
|
+
.update(Inventory)
|
|
483
|
+
.set({
|
|
484
|
+
lockedQty: () => `GREATEST(COALESCE("locked_qty", 0) - :releaseQty::numeric, 0)`,
|
|
485
|
+
lockedUomValue: () => `GREATEST(COALESCE("locked_uom_value", 0) - :releaseUomValue::numeric, 0)`,
|
|
486
|
+
updater: user
|
|
487
|
+
})
|
|
488
|
+
.setParameter('releaseQty', oi.releaseQty)
|
|
489
|
+
.setParameter('releaseUomValue', oi.releaseUomValue)
|
|
490
|
+
.where('id = :id', { id: oi.inventory.id })
|
|
491
|
+
.execute()
|
|
487
492
|
}
|
|
488
493
|
|
|
489
494
|
await tx.getRepository(OrderInventory).delete({ id: oi.id })
|
|
@@ -505,9 +510,11 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
|
|
|
505
510
|
.createQueryBuilder()
|
|
506
511
|
.update(ProductDetailStock)
|
|
507
512
|
.set({
|
|
508
|
-
unassignedQty: () => `"unassigned_qty" -
|
|
509
|
-
unassignedUomValue: () => `"unassigned_uom_value" -
|
|
513
|
+
unassignedQty: () => `GREATEST("unassigned_qty" - :releaseQty::numeric, 0)`,
|
|
514
|
+
unassignedUomValue: () => `GREATEST("unassigned_uom_value" - :releaseUomValue::numeric, 0)`
|
|
510
515
|
})
|
|
516
|
+
.setParameter('releaseQty', op.releaseQty)
|
|
517
|
+
.setParameter('releaseUomValue', op.releaseUomValue)
|
|
511
518
|
.where({ productDetail: op.productDetail.id })
|
|
512
519
|
.execute()
|
|
513
520
|
|
|
@@ -1131,20 +1138,37 @@ export async function generateReleaseGoodFunction(
|
|
|
1131
1138
|
if (worksheetPickingAssignment?.value !== 'true' || oi.inventory?.id) {
|
|
1132
1139
|
await tx.getRepository(OrderInventory).save({ ...oi, name: OrderNoGenerator.orderInventory() })
|
|
1133
1140
|
|
|
1134
|
-
await tx
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1141
|
+
const lockResult = await tx
|
|
1142
|
+
.getRepository(Inventory)
|
|
1143
|
+
.createQueryBuilder()
|
|
1144
|
+
.update(Inventory)
|
|
1145
|
+
.set({
|
|
1146
|
+
lockedQty: () => `COALESCE("locked_qty", 0) + :releaseQty::numeric`,
|
|
1147
|
+
lockedUomValue: () => `COALESCE("locked_uom_value", 0) + :releaseUomValue::numeric`,
|
|
1148
|
+
updater: user
|
|
1149
|
+
})
|
|
1150
|
+
.setParameter('releaseQty', oi.releaseQty)
|
|
1151
|
+
.setParameter('releaseUomValue', oi.releaseUomValue)
|
|
1152
|
+
.where('id = :id AND qty >= COALESCE(locked_qty, 0) + :newQty', {
|
|
1153
|
+
id: oi.inventory.id,
|
|
1154
|
+
newQty: oi.releaseQty
|
|
1155
|
+
})
|
|
1156
|
+
.execute()
|
|
1157
|
+
|
|
1158
|
+
if (lockResult.affected === 0) {
|
|
1159
|
+
throw new Error(`Insufficient inventory for ${oi.product?.sku || 'unknown product'}`)
|
|
1160
|
+
}
|
|
1139
1161
|
} else {
|
|
1140
1162
|
await tx
|
|
1141
1163
|
.getRepository(ProductDetailStock)
|
|
1142
1164
|
.createQueryBuilder()
|
|
1143
1165
|
.update(ProductDetailStock)
|
|
1144
1166
|
.set({
|
|
1145
|
-
unassignedQty: () => `"unassigned_qty" +
|
|
1146
|
-
unassignedUomValue: () => `"unassigned_uom_value" +
|
|
1167
|
+
unassignedQty: () => `"unassigned_qty" + :releaseQty::numeric`,
|
|
1168
|
+
unassignedUomValue: () => `"unassigned_uom_value" + :releaseUomValue::numeric`
|
|
1147
1169
|
})
|
|
1170
|
+
.setParameter('releaseQty', oi.releaseQty)
|
|
1171
|
+
.setParameter('releaseUomValue', oi.releaseUomValue)
|
|
1148
1172
|
.where({ productDetail: oi.productDetail.id })
|
|
1149
1173
|
.execute()
|
|
1150
1174
|
}
|
|
@@ -1971,10 +1995,12 @@ export async function bulkGenerateReleaseGood(
|
|
|
1971
1995
|
.createQueryBuilder()
|
|
1972
1996
|
.update(Inventory)
|
|
1973
1997
|
.set({
|
|
1974
|
-
lockedQty: () => `COALESCE("locked_qty",0) +
|
|
1975
|
-
lockedUomValue: () => `COALESCE("locked_uom_value",0) +
|
|
1998
|
+
lockedQty: () => `COALESCE("locked_qty",0) + :releaseQty::numeric`,
|
|
1999
|
+
lockedUomValue: () => `COALESCE("locked_uom_value",0) + :releaseUomValue::numeric`,
|
|
1976
2000
|
updater: user
|
|
1977
2001
|
})
|
|
2002
|
+
.setParameter('releaseQty', generatedOI.releaseQty)
|
|
2003
|
+
.setParameter('releaseUomValue', generatedOI.releaseUomValue)
|
|
1978
2004
|
.where(`id = :id AND qty >= COALESCE(locked_qty,0) + :newQty`, {
|
|
1979
2005
|
id: oi.inventory.id,
|
|
1980
2006
|
newQty: generatedOI.releaseQty
|
|
@@ -1990,9 +2016,11 @@ export async function bulkGenerateReleaseGood(
|
|
|
1990
2016
|
.createQueryBuilder()
|
|
1991
2017
|
.update(ProductDetailStock)
|
|
1992
2018
|
.set({
|
|
1993
|
-
unassignedQty: () => `"unassigned_qty" +
|
|
1994
|
-
unassignedUomValue: () => `"unassigned_uom_value" +
|
|
2019
|
+
unassignedQty: () => `"unassigned_qty" + :releaseQty::numeric`,
|
|
2020
|
+
unassignedUomValue: () => `"unassigned_uom_value" + :releaseUomValue::numeric`
|
|
1995
2021
|
})
|
|
2022
|
+
.setParameter('releaseQty', generatedOI.releaseQty)
|
|
2023
|
+
.setParameter('releaseUomValue', generatedOI.releaseUomValue)
|
|
1996
2024
|
.where({ productDetail: oi.productDetail ? oi.productDetail.id : oi.productDetailId })
|
|
1997
2025
|
.execute()
|
|
1998
2026
|
}
|