@things-factory/sales-base 4.3.448 → 4.3.452
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/constants/order.js +3 -1
- package/dist-server/constants/order.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-create.js +587 -0
- package/dist-server/service/draft-release-good/draft-release-good-create.js.map +1 -0
- package/dist-server/service/draft-release-good/draft-release-good-mutation.js +3 -232
- package/dist-server/service/draft-release-good/draft-release-good-mutation.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-query.js +59 -28
- package/dist-server/service/draft-release-good/draft-release-good-query.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good-type.js +33 -1
- package/dist-server/service/draft-release-good/draft-release-good-type.js.map +1 -1
- package/dist-server/service/draft-release-good/draft-release-good.js +2 -7
- package/dist-server/service/draft-release-good/draft-release-good.js.map +1 -1
- package/dist-server/service/draft-release-good/index.js +4 -2
- package/dist-server/service/draft-release-good/index.js.map +1 -1
- package/dist-server/service/order-vas/order-vas-mutation.js +46 -23
- package/dist-server/service/order-vas/order-vas-mutation.js.map +1 -1
- package/dist-server/service/order-vas/order-vas-query.js +34 -0
- package/dist-server/service/order-vas/order-vas-query.js.map +1 -1
- package/dist-server/service/order-vas/order-vas-types.js +4 -0
- package/dist-server/service/order-vas/order-vas-types.js.map +1 -1
- package/dist-server/service/order-vas/order-vas.js +22 -1
- package/dist-server/service/order-vas/order-vas.js.map +1 -1
- package/dist-server/service/order-vas-item/order-vas-item-type.js +8 -0
- package/dist-server/service/order-vas-item/order-vas-item-type.js.map +1 -1
- package/dist-server/service/order-vas-item/order-vas-item.js +5 -0
- package/dist-server/service/order-vas-item/order-vas-item.js.map +1 -1
- package/dist-server/service/release-good/release-good-mutation.js +5 -3
- package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
- package/dist-server/service/release-good/release-good-query.js +4 -1
- package/dist-server/service/release-good/release-good-query.js.map +1 -1
- package/dist-server/service/release-good/release-good.js +9 -0
- package/dist-server/service/release-good/release-good.js.map +1 -1
- package/dist-server/service/vas/vas-mutation.js +5 -1
- package/dist-server/service/vas/vas-mutation.js.map +1 -1
- package/dist-server/utils/inventory-util.js +5 -3
- package/dist-server/utils/inventory-util.js.map +1 -1
- package/package.json +15 -15
- package/server/constants/order.ts +3 -1
- package/server/service/draft-release-good/draft-release-good-create.ts +715 -0
- package/server/service/draft-release-good/draft-release-good-mutation.ts +36 -288
- package/server/service/draft-release-good/draft-release-good-query.ts +109 -89
- package/server/service/draft-release-good/draft-release-good-type.ts +28 -2
- package/server/service/draft-release-good/draft-release-good.ts +2 -8
- package/server/service/draft-release-good/index.ts +4 -2
- package/server/service/order-vas/order-vas-mutation.ts +57 -29
- package/server/service/order-vas/order-vas-query.ts +43 -1
- package/server/service/order-vas/order-vas-types.ts +5 -8
- package/server/service/order-vas/order-vas.ts +19 -10
- package/server/service/order-vas-item/order-vas-item-type.ts +6 -0
- package/server/service/order-vas-item/order-vas-item.ts +4 -0
- package/server/service/release-good/release-good-mutation.ts +8 -2
- package/server/service/release-good/release-good-query.ts +7 -2
- package/server/service/release-good/release-good.ts +8 -0
- package/server/service/vas/vas-mutation.ts +4 -1
- package/server/utils/inventory-util.ts +29 -6
|
@@ -0,0 +1,715 @@
|
|
|
1
|
+
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
|
2
|
+
import { EntityManager, getConnection, getRepository, In, Repository } from 'typeorm'
|
|
3
|
+
|
|
4
|
+
import { Bizplace } from '@things-factory/biz-base'
|
|
5
|
+
import { logger } from '@things-factory/env'
|
|
6
|
+
import { ProductBundle } from '@things-factory/product-base'
|
|
7
|
+
import { PartnerSetting, Setting } from '@things-factory/setting-base'
|
|
8
|
+
import { Domain } from '@things-factory/shell'
|
|
9
|
+
|
|
10
|
+
// import { Location } from '@things-factory/warehouse-base'
|
|
11
|
+
import { bulkReleaseGoodsAvailableItemsFunction, DraftReleaseGood, DraftReleaseGoodInfos, OrderProduct } from '../'
|
|
12
|
+
import { DRAFT_RELEASE_ORDER_STATUS, ORDER_NUMBER_SETTING_KEY, ORDER_STATUS } from '../../constants'
|
|
13
|
+
import { ValidationError } from '../../errors'
|
|
14
|
+
import { InventoryUtil, OrderNoGenerator } from '../../utils'
|
|
15
|
+
import { ReleaseGood } from '../release-good/release-good'
|
|
16
|
+
import { SuccessReleasedDraftOrder } from './draft-release-good-type'
|
|
17
|
+
import { bulkGenerateReleaseGood, confirmReleaseGood, receiveReleaseGood } from '../release-good/release-good-mutation'
|
|
18
|
+
|
|
19
|
+
@Resolver(DraftReleaseGood)
|
|
20
|
+
export class DraftReleaseGoodCreate {
|
|
21
|
+
@Directive('@privilege(category: "order_customer", privilege: "mutation")')
|
|
22
|
+
@Directive('@transaction')
|
|
23
|
+
@Mutation(returns => [SuccessReleasedDraftOrder], {
|
|
24
|
+
nullable: true,
|
|
25
|
+
description: 'To generate Release Goods from Draft'
|
|
26
|
+
})
|
|
27
|
+
async generateReleaseGoodsfromDraft(
|
|
28
|
+
@Ctx() context: any,
|
|
29
|
+
@Arg('releaseInfo', type => [DraftReleaseGoodInfos]) releaseInfo: DraftReleaseGoodInfos[]
|
|
30
|
+
): Promise<SuccessReleasedDraftOrder[] | null> {
|
|
31
|
+
let results = []
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const _generatePartialReleaseGoodsRecord = releaseInfo.filter(
|
|
35
|
+
item => item.releaseType === 'partial' && item.id !== ''
|
|
36
|
+
)
|
|
37
|
+
const _generateReleaseGoodsRecord = releaseInfo.filter(item => item.releaseType === 'release' && item.id !== '')
|
|
38
|
+
|
|
39
|
+
if (_generateReleaseGoodsRecord.length > 0) {
|
|
40
|
+
const result = await generateReleaseGoods(_generateReleaseGoodsRecord, context)
|
|
41
|
+
results.push(...result)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (_generatePartialReleaseGoodsRecord.length > 0) {
|
|
45
|
+
const result = await generatePartialReleaseGoods(_generatePartialReleaseGoodsRecord, context)
|
|
46
|
+
results.push(...result)
|
|
47
|
+
}
|
|
48
|
+
return results
|
|
49
|
+
} catch (e) {
|
|
50
|
+
logger.error(e)
|
|
51
|
+
throw new Error('Failed Released Draft Orders')
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function generateReleaseGoods(_generateReleaseGoodsRecord, context: any) {
|
|
57
|
+
const { domain, user, tx } = context.state
|
|
58
|
+
try {
|
|
59
|
+
let ids = [] // Initialize the ids array outside the loop
|
|
60
|
+
ids = _generateReleaseGoodsRecord.map(item => item.id)
|
|
61
|
+
let releasedOrders = []
|
|
62
|
+
|
|
63
|
+
const updatableDraftOrders = await tx.getRepository(DraftReleaseGood).find({
|
|
64
|
+
where: {
|
|
65
|
+
domain,
|
|
66
|
+
id: In(ids),
|
|
67
|
+
status: In([DRAFT_RELEASE_ORDER_STATUS.DRAFT, DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED])
|
|
68
|
+
},
|
|
69
|
+
order: {
|
|
70
|
+
createdAt: 'ASC'
|
|
71
|
+
},
|
|
72
|
+
relations: [
|
|
73
|
+
'orderProducts',
|
|
74
|
+
'orderProducts.product',
|
|
75
|
+
'orderProducts.productBundle',
|
|
76
|
+
'orderProducts.productBundle.productBundleSettings',
|
|
77
|
+
'orderProducts.productBundle.productBundleSettings.product',
|
|
78
|
+
'orderProducts.productBundle.productBundleSettings.productDetail',
|
|
79
|
+
'shippingOrder',
|
|
80
|
+
'bizplace',
|
|
81
|
+
'bizplace.domain',
|
|
82
|
+
'domain',
|
|
83
|
+
'creator',
|
|
84
|
+
'updater',
|
|
85
|
+
'lastMileDelivery'
|
|
86
|
+
]
|
|
87
|
+
})
|
|
88
|
+
let failReleaseOrder = []
|
|
89
|
+
|
|
90
|
+
if (updatableDraftOrders.length > 0) {
|
|
91
|
+
const settingRepo: Repository<Setting> = tx?.getRepository(Setting) || getRepository(Setting)
|
|
92
|
+
|
|
93
|
+
const roNoSetting: Setting = await settingRepo.findOne({
|
|
94
|
+
where: {
|
|
95
|
+
domain,
|
|
96
|
+
name: ORDER_NUMBER_SETTING_KEY.RO_NUMBER_RULE
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
for (let index = 0; index < updatableDraftOrders.length; index++) {
|
|
101
|
+
await getConnection().transaction(async (tx: EntityManager) => {
|
|
102
|
+
|
|
103
|
+
const draftOrder = updatableDraftOrders[index]
|
|
104
|
+
|
|
105
|
+
let foundPermittedBizplace: Bizplace
|
|
106
|
+
let companyBizplace: Bizplace
|
|
107
|
+
|
|
108
|
+
if (draftOrder?.bizplace?.id) {
|
|
109
|
+
foundPermittedBizplace = await tx.getRepository(Bizplace).findOne(draftOrder.bizplace.id, {
|
|
110
|
+
relations: ['company', 'company.domain']
|
|
111
|
+
})
|
|
112
|
+
const companyDomain: Domain = foundPermittedBizplace.company.domain
|
|
113
|
+
companyBizplace = await tx.getRepository(Bizplace).findOne({ where: { domain: companyDomain } })
|
|
114
|
+
} else {
|
|
115
|
+
return false
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const bizplaces: Bizplace[] = [foundPermittedBizplace, companyBizplace]
|
|
119
|
+
|
|
120
|
+
let loggerJson = JSON.stringify({ refNo: draftOrder.refNo, bizplaceId: draftOrder.bizplace.id, domain })
|
|
121
|
+
try {
|
|
122
|
+
console.time(`creating_order:${loggerJson}`)
|
|
123
|
+
|
|
124
|
+
draftOrder.orderProducts = draftOrder.orderProducts.filter(op => op.status == 'DRAFT')
|
|
125
|
+
|
|
126
|
+
let productIds = []
|
|
127
|
+
|
|
128
|
+
for (let item of draftOrder.orderProducts) {
|
|
129
|
+
if (item && item.product) {
|
|
130
|
+
productIds.push(item.product.id)
|
|
131
|
+
}
|
|
132
|
+
if (item && item.productBundle) {
|
|
133
|
+
for (let bundleSetting of item.productBundle.productBundleSettings) {
|
|
134
|
+
productIds.push(bundleSetting.product.id)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let productInventory = await InventoryUtil.bizplaceProductInventory(
|
|
140
|
+
bizplaces,
|
|
141
|
+
{
|
|
142
|
+
filters: [
|
|
143
|
+
{
|
|
144
|
+
name: 'productId',
|
|
145
|
+
operator: 'in',
|
|
146
|
+
value: productIds
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
context,
|
|
151
|
+
tx
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
draftOrder.orderProducts = draftOrder.orderProducts.map(itm => {
|
|
155
|
+
let foundProductInv
|
|
156
|
+
if (itm.product) {
|
|
157
|
+
foundProductInv = productInventory.items.find(
|
|
158
|
+
i =>
|
|
159
|
+
(i.productDetailId == itm?.productDetailId || i.productId == itm?.productBundle?.id) &&
|
|
160
|
+
itm.releaseQty <= i.remainQty
|
|
161
|
+
)
|
|
162
|
+
if (!foundProductInv) {
|
|
163
|
+
failReleaseOrder.push(draftOrder.name)
|
|
164
|
+
}
|
|
165
|
+
} else {
|
|
166
|
+
itm.productBundle.productBundleSettings.map(pbs => {
|
|
167
|
+
foundProductInv = productInventory.items.find(
|
|
168
|
+
i =>
|
|
169
|
+
(i.productDetailId == pbs?.productDetail.id || i.productId == pbs?.product?.id) &&
|
|
170
|
+
itm.releaseQty <= i.remainQty
|
|
171
|
+
)
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
...itm,
|
|
176
|
+
releaseUomValue: (foundProductInv.remainUomValue / foundProductInv.remainQty) * itm.releaseQty,
|
|
177
|
+
status: foundProductInv ? 'suffice' : 'insufficient'
|
|
178
|
+
}
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
let insufficient = draftOrder.orderProducts.find(op => op.status == 'insufficient')
|
|
182
|
+
if (!insufficient) {
|
|
183
|
+
//create RO
|
|
184
|
+
let releaseGood = { ...draftOrder }
|
|
185
|
+
delete releaseGood.id
|
|
186
|
+
delete releaseGood.name
|
|
187
|
+
delete releaseGood.createdAt
|
|
188
|
+
delete releaseGood.createdBy
|
|
189
|
+
delete releaseGood.updatedAt
|
|
190
|
+
delete releaseGood.updatedBy
|
|
191
|
+
|
|
192
|
+
let orderInventories = []
|
|
193
|
+
|
|
194
|
+
for (let index = 0; index < draftOrder.orderProducts.length; index++) {
|
|
195
|
+
const itm: Partial<OrderProduct> = draftOrder.orderProducts[index]
|
|
196
|
+
let data = []
|
|
197
|
+
if (itm.productBundle) {
|
|
198
|
+
let bundle: ProductBundle = await tx.getRepository(ProductBundle).findOne({
|
|
199
|
+
where: { id: itm.productBundle.id },
|
|
200
|
+
relations: [
|
|
201
|
+
'productBundleSettings',
|
|
202
|
+
'productBundleSettings.productDetail',
|
|
203
|
+
'productBundleSettings.product'
|
|
204
|
+
]
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
for (let index2 = 0; index2 < bundle.productBundleSettings.length; index2++) {
|
|
208
|
+
const objProductBundleSetting = bundle.productBundleSettings[index2]
|
|
209
|
+
data.push({
|
|
210
|
+
sku: objProductBundleSetting.product.sku,
|
|
211
|
+
packingType: objProductBundleSetting.productDetail.packingType,
|
|
212
|
+
packingSize: objProductBundleSetting.productDetail.packingSize,
|
|
213
|
+
uom: objProductBundleSetting.productDetail.uom,
|
|
214
|
+
releaseQty: objProductBundleSetting.bundleQty * itm.releaseQty,
|
|
215
|
+
assignedQty: undefined,
|
|
216
|
+
assignedUomValue: undefined,
|
|
217
|
+
releaseUomValue: objProductBundleSetting.bundleQty * itm.releaseQty * itm.releaseUomValue
|
|
218
|
+
})
|
|
219
|
+
}
|
|
220
|
+
} else {
|
|
221
|
+
data = [
|
|
222
|
+
{
|
|
223
|
+
sku: itm.product.sku,
|
|
224
|
+
packingType: itm.packingType,
|
|
225
|
+
packingSize: itm.packingSize,
|
|
226
|
+
uom: itm.uom,
|
|
227
|
+
releaseQty: itm.releaseQty,
|
|
228
|
+
assignedQty: undefined,
|
|
229
|
+
assignedUomValue: undefined,
|
|
230
|
+
releaseUomValue: itm.releaseUomValue
|
|
231
|
+
}
|
|
232
|
+
]
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
data.forEach(data => {
|
|
236
|
+
let existingOI = orderInventories.find(
|
|
237
|
+
itm =>
|
|
238
|
+
itm.sku == data.sku &&
|
|
239
|
+
itm.packingType == data.packingType &&
|
|
240
|
+
itm.packingSize == data.packingSize &&
|
|
241
|
+
itm.uom == data.uom
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
if (existingOI) {
|
|
246
|
+
existingOI.releaseQty = existingOI.releaseQty + data.releaseQty
|
|
247
|
+
existingOI.releaseUomValue = existingOI.releaseUomValue + data.uomValue
|
|
248
|
+
existingOI.uomValue = existingOI.uomValue + data.uomValue
|
|
249
|
+
} else {
|
|
250
|
+
orderInventories.push({ ...data, orderProduct: itm })
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
await getConnection().transaction(async (tx: EntityManager) => {
|
|
256
|
+
let availableItems: any[] = await bulkReleaseGoodsAvailableItemsFunction(
|
|
257
|
+
orderInventories,
|
|
258
|
+
draftOrder.bizplace.id,
|
|
259
|
+
context,
|
|
260
|
+
tx
|
|
261
|
+
)
|
|
262
|
+
if (availableItems.some(item => !item.releaseQty || item.releaseQty > item.assignedQty))
|
|
263
|
+
throw new ValidationError({
|
|
264
|
+
...ValidationError.ERROR_CODES.INSUFFICIENT_STOCK,
|
|
265
|
+
detail: { data: JSON.stringify(availableItems) }
|
|
266
|
+
})
|
|
267
|
+
// update orderInventories if availableItems are valid
|
|
268
|
+
releaseGood.noOfItems = orderInventories.length
|
|
269
|
+
|
|
270
|
+
releaseGood.orderInventories = availableItems.map(itm => {
|
|
271
|
+
return {
|
|
272
|
+
...itm,
|
|
273
|
+
releaseQty: itm.releaseQty,
|
|
274
|
+
releaseUomValue: itm.releaseUomValue,
|
|
275
|
+
uomValue: itm.uomValue
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
let createdReleaseGood: ReleaseGood = await bulkGenerateReleaseGood(
|
|
279
|
+
releaseGood,
|
|
280
|
+
releaseGood.bizplace.id,
|
|
281
|
+
roNoSetting,
|
|
282
|
+
domain,
|
|
283
|
+
user,
|
|
284
|
+
draftOrder,
|
|
285
|
+
tx
|
|
286
|
+
)
|
|
287
|
+
await tx
|
|
288
|
+
.getRepository(DraftReleaseGood)
|
|
289
|
+
.update({ id: draftOrder.id }, { status: DRAFT_RELEASE_ORDER_STATUS.SUBMITTED })
|
|
290
|
+
|
|
291
|
+
const directReceiveSetting: Setting = await tx.getRepository(Setting).findOne({
|
|
292
|
+
where: { domain, category: 'id-rule', name: 'enable-direct-receive-release-order' }
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
const partnerDirectReceiveSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
|
|
296
|
+
where: { setting: directReceiveSetting, domain, partnerDomain: draftOrder.bizplace?.domain }
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
let settingValue
|
|
300
|
+
|
|
301
|
+
if (
|
|
302
|
+
!isNaN(partnerDirectReceiveSetting?.value) &&
|
|
303
|
+
!isNaN(parseFloat(partnerDirectReceiveSetting?.value))
|
|
304
|
+
) {
|
|
305
|
+
settingValue = parseFloat(partnerDirectReceiveSetting.value)
|
|
306
|
+
} else {
|
|
307
|
+
settingValue = parseFloat(directReceiveSetting.value)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
createdReleaseGood = await confirmReleaseGood(createdReleaseGood.name, context, tx)
|
|
311
|
+
|
|
312
|
+
if (settingValue > 1) {
|
|
313
|
+
createdReleaseGood = await receiveReleaseGood(createdReleaseGood.name, context, tx)
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
} else {
|
|
317
|
+
if (draftOrder.orderProducts.every(op => op.id === insufficient?.id)) {
|
|
318
|
+
failReleaseOrder.push(draftOrder?.name)
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
} catch (e) {
|
|
322
|
+
logger.error(`draft-release-good-mutation[generateReleaseGoodsFromDraft:${loggerJson}]: ${e?.message}`)
|
|
323
|
+
} finally {
|
|
324
|
+
console.timeEnd(`creating_order:${loggerJson}`)
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
releasedOrders = updatableDraftOrders.filter(drg => !drg.name.includes(failReleaseOrder))
|
|
330
|
+
releasedOrders = releasedOrders.map(item => {
|
|
331
|
+
return {
|
|
332
|
+
draftName: item.name
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
return releasedOrders
|
|
336
|
+
} catch (e) {
|
|
337
|
+
logger.error(`draft-release-good-mutation[generateReleaseGoodsFromDraft]: ${e?.message}`)
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export async function generatePartialReleaseGoods(_generatePartialReleaseGoodsRecord, context: any) {
|
|
342
|
+
const { domain, user, tx } = context.state
|
|
343
|
+
try {
|
|
344
|
+
let ids = []
|
|
345
|
+
ids = _generatePartialReleaseGoodsRecord.map(item => item.id)
|
|
346
|
+
const selectedStatus = [
|
|
347
|
+
DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED,
|
|
348
|
+
DRAFT_RELEASE_ORDER_STATUS.DRAFT,
|
|
349
|
+
DRAFT_RELEASE_ORDER_STATUS.TRANSFER
|
|
350
|
+
]
|
|
351
|
+
|
|
352
|
+
const value = _generatePartialReleaseGoodsRecord[0]
|
|
353
|
+
const updatableDraftOrders = await tx.getRepository(DraftReleaseGood).find({
|
|
354
|
+
where: {
|
|
355
|
+
domain,
|
|
356
|
+
id: In(ids),
|
|
357
|
+
status: In(selectedStatus)
|
|
358
|
+
},
|
|
359
|
+
order: {
|
|
360
|
+
createdAt: 'ASC',
|
|
361
|
+
status: 'ASC'
|
|
362
|
+
},
|
|
363
|
+
relations: [
|
|
364
|
+
'orderProducts',
|
|
365
|
+
'orderProducts.product',
|
|
366
|
+
'orderProducts.productDetail',
|
|
367
|
+
'orderProducts.productBundle',
|
|
368
|
+
'shippingOrder',
|
|
369
|
+
'bizplace',
|
|
370
|
+
'bizplace.domain',
|
|
371
|
+
'domain',
|
|
372
|
+
'creator',
|
|
373
|
+
'updater',
|
|
374
|
+
'lastMileDelivery'
|
|
375
|
+
]
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
if (updatableDraftOrders.length > 0) {
|
|
379
|
+
// let createdReleaseGoods: ReleaseGood[] = []
|
|
380
|
+
const settingRepo: Repository<Setting> = tx?.getRepository(Setting) || getRepository(Setting)
|
|
381
|
+
|
|
382
|
+
const roNoSetting: Setting = await settingRepo.findOne({
|
|
383
|
+
where: {
|
|
384
|
+
domain,
|
|
385
|
+
name: ORDER_NUMBER_SETTING_KEY.RO_NUMBER_RULE
|
|
386
|
+
}
|
|
387
|
+
})
|
|
388
|
+
|
|
389
|
+
for (let draftOrder of updatableDraftOrders) {
|
|
390
|
+
await getConnection().transaction(async (tx: EntityManager) => {
|
|
391
|
+
let foundPermittedBizplace: Bizplace
|
|
392
|
+
let companyBizplace: Bizplace
|
|
393
|
+
|
|
394
|
+
//remove op productBundle as there no support for partial release
|
|
395
|
+
|
|
396
|
+
if (draftOrder.orderProducts.some(itm => !itm.product)) {
|
|
397
|
+
draftOrder.orderProducts = draftOrder.orderProducts.filter(itm => itm.product)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (draftOrder?.bizplace?.id) {
|
|
401
|
+
foundPermittedBizplace = await tx.getRepository(Bizplace).findOne(draftOrder.bizplace.id, {
|
|
402
|
+
relations: ['company', 'company.domain']
|
|
403
|
+
})
|
|
404
|
+
const companyDomain: Domain = foundPermittedBizplace.company.domain
|
|
405
|
+
companyBizplace = await tx.getRepository(Bizplace).findOne({ where: { domain: companyDomain } })
|
|
406
|
+
} else {
|
|
407
|
+
return false
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const bizplaces: Bizplace[] = [foundPermittedBizplace, companyBizplace]
|
|
411
|
+
|
|
412
|
+
let loggerJson = JSON.stringify({ refNo: draftOrder.refNo, bizplaceId: draftOrder.bizplace.id, domain })
|
|
413
|
+
try {
|
|
414
|
+
console.time(`creating_order:${loggerJson}`)
|
|
415
|
+
|
|
416
|
+
let productInventory = await InventoryUtil.bizplaceProductInventory(
|
|
417
|
+
bizplaces,
|
|
418
|
+
{
|
|
419
|
+
filters: [
|
|
420
|
+
{
|
|
421
|
+
name: 'productId',
|
|
422
|
+
operator: 'in',
|
|
423
|
+
value: [
|
|
424
|
+
...draftOrder.orderProducts
|
|
425
|
+
.filter(itm => itm?.product)
|
|
426
|
+
.map(itm => {
|
|
427
|
+
return itm.product.id
|
|
428
|
+
}),
|
|
429
|
+
...draftOrder.orderProducts
|
|
430
|
+
.filter(itm => itm?.productBundle)
|
|
431
|
+
.map(itm => {
|
|
432
|
+
return itm.productBundle.id
|
|
433
|
+
})
|
|
434
|
+
]
|
|
435
|
+
}
|
|
436
|
+
]
|
|
437
|
+
},
|
|
438
|
+
context,
|
|
439
|
+
tx
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
draftOrder.orderProducts = draftOrder.orderProducts.filter(op => op.status == 'DRAFT')
|
|
443
|
+
|
|
444
|
+
if (!Array.isArray(draftOrder.orderProducts)) {
|
|
445
|
+
draftOrder.orderProducts = [draftOrder.orderProducts]
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// if (!foundItem)
|
|
449
|
+
let releaseOrderProducts = []
|
|
450
|
+
draftOrder.orderProducts = draftOrder.orderProducts.map((itm, idx) => {
|
|
451
|
+
let foundProductInv = productInventory.items.find(
|
|
452
|
+
i =>
|
|
453
|
+
(i.productDetailId == itm?.productDetailId || i.productId == itm?.productBundle?.id) &&
|
|
454
|
+
!(i.remainQty === 0)
|
|
455
|
+
)
|
|
456
|
+
if (foundProductInv) {
|
|
457
|
+
releaseOrderProducts.push({
|
|
458
|
+
...itm,
|
|
459
|
+
releaseUomValue:
|
|
460
|
+
itm.releaseQty > foundProductInv.remainQty
|
|
461
|
+
? (foundProductInv.remainUomValue / foundProductInv.remainQty) * foundProductInv.remainQty
|
|
462
|
+
: (foundProductInv.remainUomValue / foundProductInv.remainQty) * itm.releaseQty,
|
|
463
|
+
status: itm.releaseQty <= foundProductInv.remainQty ? 'suffice' : 'partial-release',
|
|
464
|
+
releaseQty: itm.releaseQty > foundProductInv.remainQty ? foundProductInv.remainQty : itm.releaseQty, //it will take the remainQty instead of releaseQty when remainQty < releaseQty
|
|
465
|
+
newReleaseQty:
|
|
466
|
+
itm.releaseQty > foundProductInv.remainQty ? itm.releaseQty - foundProductInv.remainQty : 0
|
|
467
|
+
})
|
|
468
|
+
}
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
let sufficient = releaseOrderProducts.filter(op => op.status == 'suffice' || op.status == 'partial-release')
|
|
472
|
+
|
|
473
|
+
//create RO
|
|
474
|
+
if (sufficient.length > 0) {
|
|
475
|
+
let releaseGood = { ...draftOrder }
|
|
476
|
+
delete releaseGood.id
|
|
477
|
+
delete releaseGood.name
|
|
478
|
+
delete releaseGood.createdAt
|
|
479
|
+
delete releaseGood.createdBy
|
|
480
|
+
delete releaseGood.updatedAt
|
|
481
|
+
delete releaseGood.updatedBy
|
|
482
|
+
|
|
483
|
+
let orderInventories = []
|
|
484
|
+
|
|
485
|
+
for (let index = 0; index < releaseOrderProducts.length; index++) {
|
|
486
|
+
const itm: Partial<OrderProduct> = releaseOrderProducts[index]
|
|
487
|
+
let data = []
|
|
488
|
+
if (itm.productBundle) {
|
|
489
|
+
let bundle: ProductBundle = await tx.getRepository(ProductBundle).findOne({
|
|
490
|
+
where: { id: itm.productBundle.id },
|
|
491
|
+
relations: [
|
|
492
|
+
'productBundleSettings',
|
|
493
|
+
'productBundleSettings.productDetail',
|
|
494
|
+
'productBundleSettings.product'
|
|
495
|
+
]
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
for (let index2 = 0; index2 < bundle.productBundleSettings.length; index2++) {
|
|
499
|
+
const objProductBundleSetting = bundle.productBundleSettings[index2]
|
|
500
|
+
data.push({
|
|
501
|
+
sku: objProductBundleSetting.product.sku,
|
|
502
|
+
packingType: objProductBundleSetting.productDetail.packingType,
|
|
503
|
+
packingSize: objProductBundleSetting.productDetail.packingSize,
|
|
504
|
+
uom: objProductBundleSetting.productDetail.uom,
|
|
505
|
+
releaseQty: objProductBundleSetting.bundleQty * itm.releaseQty,
|
|
506
|
+
assignedQty: undefined,
|
|
507
|
+
assignedUomValue: undefined,
|
|
508
|
+
releaseUomValue: objProductBundleSetting.bundleQty * itm.releaseQty * itm.releaseUomValue
|
|
509
|
+
})
|
|
510
|
+
}
|
|
511
|
+
} else {
|
|
512
|
+
data = [
|
|
513
|
+
{
|
|
514
|
+
sku: itm.product.sku,
|
|
515
|
+
packingType: itm.packingType,
|
|
516
|
+
packingSize: itm.packingSize,
|
|
517
|
+
uom: itm.uom,
|
|
518
|
+
releaseQty: itm.releaseQty,
|
|
519
|
+
assignedQty: undefined,
|
|
520
|
+
assignedUomValue: undefined,
|
|
521
|
+
releaseUomValue: itm.releaseUomValue
|
|
522
|
+
}
|
|
523
|
+
]
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
data.forEach(data => {
|
|
527
|
+
let existingOI = orderInventories.find(
|
|
528
|
+
itm =>
|
|
529
|
+
itm.sku == data.sku &&
|
|
530
|
+
itm.packingType == data.packingType &&
|
|
531
|
+
itm.packingSize == data.packingSize &&
|
|
532
|
+
itm.uom == data.uom
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
if (existingOI) {
|
|
536
|
+
existingOI.releaseQty = existingOI.releaseQty + data.releaseQty
|
|
537
|
+
existingOI.releaseUomValue = existingOI.releaseUomValue + data.uomValue
|
|
538
|
+
existingOI.uomValue = existingOI.uomValue + data.uomValue
|
|
539
|
+
} else {
|
|
540
|
+
orderInventories.push({ ...data, orderProduct: itm })
|
|
541
|
+
}
|
|
542
|
+
})
|
|
543
|
+
}
|
|
544
|
+
await getConnection().transaction(async (tx: EntityManager) => {
|
|
545
|
+
let availableItems: any[] = await bulkReleaseGoodsAvailableItemsFunction(
|
|
546
|
+
orderInventories,
|
|
547
|
+
draftOrder.bizplace.id,
|
|
548
|
+
context,
|
|
549
|
+
tx
|
|
550
|
+
)
|
|
551
|
+
|
|
552
|
+
// first condition for partial release (values use for generating release good)
|
|
553
|
+
if (draftOrder.id === value.id && value.releaseType === 'partial') {
|
|
554
|
+
releaseGood.orderInventories = availableItems.map(itm => {
|
|
555
|
+
return {
|
|
556
|
+
...itm,
|
|
557
|
+
releaseQty: itm.assignedQty,
|
|
558
|
+
releaseUomValue: itm.releaseUomValue,
|
|
559
|
+
uomValue: itm.uomValue
|
|
560
|
+
}
|
|
561
|
+
})
|
|
562
|
+
} else if (availableItems.some(item => !item.releaseQty || item.releaseQty > item.assignedQty)) {
|
|
563
|
+
throw new ValidationError({
|
|
564
|
+
...ValidationError.ERROR_CODES.INSUFFICIENT_STOCK,
|
|
565
|
+
detail: { data: JSON.stringify(availableItems) }
|
|
566
|
+
})
|
|
567
|
+
} else {
|
|
568
|
+
releaseGood.orderInventories = availableItems.map(itm => {
|
|
569
|
+
return {
|
|
570
|
+
...itm,
|
|
571
|
+
releaseQty: itm.releaseQty,
|
|
572
|
+
releaseUomValue: itm.releaseUomValue,
|
|
573
|
+
uomValue: itm.uomValue
|
|
574
|
+
}
|
|
575
|
+
})
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// update orderInventories if availableItems are valid
|
|
579
|
+
releaseGood.noOfItems = orderInventories.length
|
|
580
|
+
|
|
581
|
+
let createdReleaseGood: ReleaseGood = await bulkGenerateReleaseGood(
|
|
582
|
+
releaseGood,
|
|
583
|
+
releaseGood.bizplace.id,
|
|
584
|
+
roNoSetting,
|
|
585
|
+
domain,
|
|
586
|
+
user,
|
|
587
|
+
draftOrder,
|
|
588
|
+
tx
|
|
589
|
+
)
|
|
590
|
+
|
|
591
|
+
await tx
|
|
592
|
+
.getRepository(DraftReleaseGood)
|
|
593
|
+
.update({ id: draftOrder.id }, { status: DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED })
|
|
594
|
+
|
|
595
|
+
const directReceiveSetting: Setting = await tx.getRepository(Setting).findOne({
|
|
596
|
+
where: { domain, category: 'id-rule', name: 'enable-direct-receive-release-order' }
|
|
597
|
+
})
|
|
598
|
+
|
|
599
|
+
const partnerDirectReceiveSetting: PartnerSetting = await tx.getRepository(PartnerSetting).findOne({
|
|
600
|
+
where: { setting: directReceiveSetting, domain, partnerDomain: draftOrder.bizplace?.domain }
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
let settingValue
|
|
604
|
+
|
|
605
|
+
if (
|
|
606
|
+
!isNaN(partnerDirectReceiveSetting?.value) &&
|
|
607
|
+
!isNaN(parseFloat(partnerDirectReceiveSetting?.value))
|
|
608
|
+
) {
|
|
609
|
+
settingValue = parseFloat(partnerDirectReceiveSetting.value)
|
|
610
|
+
} else {
|
|
611
|
+
settingValue = parseFloat(directReceiveSetting.value)
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
createdReleaseGood = await confirmReleaseGood(createdReleaseGood.name, context, tx)
|
|
615
|
+
|
|
616
|
+
if (settingValue > 1) {
|
|
617
|
+
createdReleaseGood = await receiveReleaseGood(createdReleaseGood.name, context, tx)
|
|
618
|
+
|
|
619
|
+
for (let value = 0; value < releaseOrderProducts.length; value++) {
|
|
620
|
+
if (releaseOrderProducts[value].status == 'partial-release') {
|
|
621
|
+
let newOrderProduct = releaseOrderProducts.map(item => {
|
|
622
|
+
return {
|
|
623
|
+
...item,
|
|
624
|
+
name: OrderNoGenerator.orderProduct(),
|
|
625
|
+
draftReleaseGood: draftOrder,
|
|
626
|
+
releaseQty: item.newReleaseQty,
|
|
627
|
+
bizplace: draftOrder.bizplace,
|
|
628
|
+
domain: draftOrder.domain,
|
|
629
|
+
creator: user,
|
|
630
|
+
updater: user,
|
|
631
|
+
productDetail: item.productDetail,
|
|
632
|
+
status: ORDER_STATUS.DRAFT
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
|
|
636
|
+
delete newOrderProduct[value].id
|
|
637
|
+
delete newOrderProduct[value].releaseUomValue
|
|
638
|
+
|
|
639
|
+
let generatedOrderProduct = await tx.getRepository(OrderProduct).save(newOrderProduct[value])
|
|
640
|
+
|
|
641
|
+
console.log(generatedOrderProduct)
|
|
642
|
+
}
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
})
|
|
646
|
+
}
|
|
647
|
+
} catch (e) {
|
|
648
|
+
logger.error(`draft-release-good-mutation[generateReleaseGoodsFromDraft:${loggerJson}]: ${e?.message}`)
|
|
649
|
+
} finally {
|
|
650
|
+
console.timeEnd(`creating_order:${loggerJson}`)
|
|
651
|
+
}
|
|
652
|
+
})
|
|
653
|
+
}
|
|
654
|
+
}
|
|
655
|
+
const checkDraftOrders = await tx.getRepository(DraftReleaseGood).find({
|
|
656
|
+
where: {
|
|
657
|
+
domain,
|
|
658
|
+
id: In(ids),
|
|
659
|
+
status: In([DRAFT_RELEASE_ORDER_STATUS.DRAFT, DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED])
|
|
660
|
+
},
|
|
661
|
+
relations: ['bizplace', 'domain', 'orderProducts', 'orderProducts.product', 'orderProducts.productBundle']
|
|
662
|
+
})
|
|
663
|
+
|
|
664
|
+
let productBundleOrders = []
|
|
665
|
+
let failReleaseOrder = []
|
|
666
|
+
let releasedOrders = []
|
|
667
|
+
|
|
668
|
+
for (let index = 0; index < checkDraftOrders.length; index++) {
|
|
669
|
+
const allProductsAssignedOrPartialReleased = checkDraftOrders[index].orderProducts.every(itm =>
|
|
670
|
+
['ASSIGNED', DRAFT_RELEASE_ORDER_STATUS.PARTIAL_RELEASED].includes(itm.status)
|
|
671
|
+
)
|
|
672
|
+
if (allProductsAssignedOrPartialReleased) {
|
|
673
|
+
|
|
674
|
+
let draftOrderId = checkDraftOrders[index].id
|
|
675
|
+
await tx
|
|
676
|
+
.getRepository(DraftReleaseGood)
|
|
677
|
+
.update({ id: draftOrderId }, { status: DRAFT_RELEASE_ORDER_STATUS.SUBMITTED })
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
const commonOrders = checkDraftOrders[index].orderProducts.every(checkOrder => checkOrder.status === 'DRAFT')
|
|
681
|
+
const hasPB = checkDraftOrders[index].orderProducts.some(itm => !itm.product)
|
|
682
|
+
|
|
683
|
+
if (commonOrders) {
|
|
684
|
+
failReleaseOrder.push(checkDraftOrders[index].name)
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (hasPB) {
|
|
688
|
+
productBundleOrders.push(checkDraftOrders[index].name)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
if (failReleaseOrder.length > 0) {
|
|
693
|
+
releasedOrders = checkDraftOrders.filter(order => !failReleaseOrder.includes(order.name))
|
|
694
|
+
releasedOrders = releasedOrders.map(item => {
|
|
695
|
+
return {
|
|
696
|
+
draftName: item.name
|
|
697
|
+
}
|
|
698
|
+
})
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
if (productBundleOrders.length > 0) {
|
|
702
|
+
let productBundleOrder = productBundleOrders.map(item => {
|
|
703
|
+
return {
|
|
704
|
+
draftName: item,
|
|
705
|
+
isProductBundle: true
|
|
706
|
+
}
|
|
707
|
+
})
|
|
708
|
+
releasedOrders.push(...productBundleOrder)
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
return releasedOrders
|
|
712
|
+
} catch (e) {
|
|
713
|
+
logger.error(`draft-release-good-mutation[generateReleaseGoodsFromDraft]: ${e?.message}`)
|
|
714
|
+
}
|
|
715
|
+
}
|