@things-factory/operato-hub 3.7.9 → 3.7.13

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.
@@ -1,5 +1,5 @@
1
1
  import gql from 'graphql-tag'
2
- import { getRepository, SelectQueryBuilder } from 'typeorm'
2
+ import { EntityManager, getConnection, SelectQueryBuilder } from 'typeorm'
3
3
 
4
4
  import { restfulApiRouter as router } from '@things-factory/api'
5
5
  import { Bizplace, getCompanyBizplace } from '@things-factory/biz-base'
@@ -12,394 +12,485 @@ import { WorksheetDetail } from '@things-factory/worksheet-base'
12
12
  import { businessMiddleware } from '../../../../middlewares/business-middleware'
13
13
  import { warehouseMiddleware } from '../../../../middlewares/warehouse-middleware'
14
14
 
15
- const debug = require('debug')('things-factory:operato-hub:restful-api:v2:add-release-order')
15
+ const debug = require('debug')('things-factory:operato-hub:restful-api:unstable:add-release-order')
16
16
 
17
17
  router.post(
18
18
  '/v2/warehouse/:warehouseId/add-release-order',
19
19
  businessMiddleware,
20
20
  warehouseMiddleware,
21
21
  async (context, next) => {
22
- const { client, domain } = context.state
23
- const { warehouseId: customerBizplaceId } = context.params
24
- const { t } = context
22
+ return await getConnection().transaction(async (tx: EntityManager) => {
23
+ const { client, domain } = context.state
24
+ const { warehouseId: customerBizplaceId } = context.params
25
+ const { t } = context
25
26
 
26
- if (!customerBizplaceId) context.throw(404, t('error.warehouse id not found'))
27
+ if (!customerBizplaceId) context.throw(404, t('error.warehouse id not found'))
27
28
 
28
- let bodyReq = context.request.body
29
- if (typeof bodyReq === undefined || !Object.keys(bodyReq)?.length) {
30
- context.throw(400, t('error.invalid body request format'))
31
- }
32
- debug('post:/add-release-order request.body', bodyReq)
33
- await checkMandatoryKey(context, bodyReq)
29
+ let bodyReq = context.request.body
30
+ if (typeof bodyReq === undefined || !Object.keys(bodyReq)?.length) {
31
+ context.throw(400, t('error.invalid body request format'))
32
+ }
33
+ debug('post:/add-release-order request.body', bodyReq)
34
+ await checkMandatoryKey(context, bodyReq)
34
35
 
35
- // get customer company's bizplace
36
- const custCompanyBizplace: Bizplace = await getCompanyBizplace(null, null, customerBizplaceId)
37
- const customerBizplace: Bizplace = await getRepository(Bizplace).findOne({
38
- where: { id: customerBizplaceId }
39
- })
36
+ const isAutoAssign: Boolean = bodyReq.hasOwnProperty('isAutoAssign') ? bodyReq.isAutoAssign : true
40
37
 
41
- const pickingProductSetting: Setting = await getRepository(Setting).findOne({
42
- where: { domain, name: 'rule-for-picking-product' }
43
- })
38
+ // get customer company's bizplace
39
+ const custCompanyBizplace: Bizplace = await getCompanyBizplace(null, null, customerBizplaceId, tx)
40
+ const customerBizplace: Bizplace = await tx.getRepository(Bizplace).findOne({
41
+ where: { id: customerBizplaceId }
42
+ })
43
+
44
+ const pickingProductSetting: Setting = await tx.getRepository(Setting).findOne({
45
+ where: { domain, name: 'rule-for-picking-product' }
46
+ })
44
47
 
45
- let locationSortingRules = []
46
- if (pickingProductSetting) {
47
- let locationSetting = JSON.parse(pickingProductSetting.value)
48
- for (const key in locationSetting) {
49
- locationSortingRules.push({ name: key, desc: locationSetting[key] == 'ASC' ? false : true })
48
+ let locationSortingRules = []
49
+ if (pickingProductSetting) {
50
+ let locationSetting = JSON.parse(pickingProductSetting.value)
51
+ for (const key in locationSetting) {
52
+ locationSortingRules.push({ name: key, desc: locationSetting[key] == 'ASC' ? false : true })
53
+ }
50
54
  }
51
- }
52
55
 
53
- const orderInventories: OrderInventory[] = bodyReq.orderInventories
54
- let newOrderInventories: OrderInventory[] = []
56
+ const orderInventories: OrderInventory[] = bodyReq.orderInventories
57
+ let newOrderInventories: OrderInventory[] = []
55
58
 
56
- await Promise.all(
57
- orderInventories.map(async orderInventory => {
58
- const sku: string = orderInventory.product?.sku
59
- const refCode: string = orderInventory.product?.refCode
60
- const packingType: string = orderInventory.packingType
59
+ await Promise.all(
60
+ orderInventories.map(async orderInventory => {
61
+ const sku: string = orderInventory.product?.sku
62
+ const refCode: string = orderInventory.product?.refCode
63
+ const packingType: string = orderInventory.packingType
61
64
 
62
- const qb: SelectQueryBuilder<ProductDetail> = getRepository(ProductDetail)
63
- .createQueryBuilder('PD')
64
- .innerJoinAndSelect('PD.product', 'PROD')
65
- .where('PROD.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id })
65
+ const qb: SelectQueryBuilder<ProductDetail> = tx
66
+ .getRepository(ProductDetail)
67
+ .createQueryBuilder('PD')
68
+ .innerJoinAndSelect('PD.product', 'PROD')
69
+ .where('PROD.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id })
66
70
 
67
- if (sku) {
68
- qb.andWhere('PROD.sku = :sku', { sku })
71
+ if (!sku && !refCode) {
72
+ context.throw(404, t('error.sku or refCode not found'))
73
+ }
69
74
 
70
- if (packingType) {
71
- qb.andWhere('PD.packing_type = :packingType', { packingType })
75
+ if (refCode) {
76
+ qb.andWhere('PD.ref_code = :refCode', { refCode })
72
77
  }
73
- }
74
78
 
75
- if (refCode) {
76
- qb.andWhere('PD.ref_code = :refCode', { refCode })
79
+ if (sku) {
80
+ qb.andWhere('PROD.sku = :sku', { sku })
81
+ }
77
82
 
78
83
  if (packingType) {
79
84
  qb.andWhere('PD.packing_type = :packingType', { packingType })
80
85
  }
81
- }
82
-
83
- const productDetail: ProductDetail = await qb.getOne()
84
86
 
85
- if (productDetail) {
86
- let newOrderInventory: OrderInventory = Object.assign({}, orderInventory)
87
+ const productDetail: ProductDetail = await qb.getOne()
87
88
 
88
- newOrderInventory.product.sku = productDetail.product.sku
89
- newOrderInventory.product = productDetail.product
90
- newOrderInventory.packingType = productDetail.packingType
91
- newOrderInventory.uomValue = productDetail.uomValue
92
- newOrderInventories.push(newOrderInventory)
93
- }
89
+ if (productDetail) {
90
+ let newOrderInventory: OrderInventory = Object.assign({}, orderInventory)
94
91
 
95
- if (!productDetail) {
96
- const qb: SelectQueryBuilder<ProductDetail> = getRepository(ProductBundle)
97
- .createQueryBuilder('PB')
98
- .innerJoinAndSelect('PB.productBundleSetting', 'PBS')
99
- .innerJoinAndSelect('PBS.productDetail', 'PBD')
100
- .innerJoinAndSelect('PBD.product', 'PROD')
101
- .where('PB.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id })
92
+ newOrderInventory.product.sku = productDetail.product.sku
93
+ newOrderInventory.product = productDetail.product
94
+ newOrderInventory.packingType = productDetail.packingType
95
+ newOrderInventory.uomValue = productDetail.uomValue
96
+ newOrderInventories.push(newOrderInventory)
97
+ }
102
98
 
103
- if (sku) {
104
- qb.andWhere('PB.sku = :sku', { sku })
99
+ if (!productDetail) {
100
+ const qb: SelectQueryBuilder<ProductDetail> = tx
101
+ .getRepository(ProductBundle)
102
+ .createQueryBuilder('PB')
103
+ .innerJoinAndSelect('PB.productBundleSettings', 'PBS')
104
+ .innerJoinAndSelect('PBS.productDetail', 'PBD')
105
+ .innerJoinAndSelect('PBD.product', 'PROD')
106
+ .where('PB.bizplace_id = :bizplaceId', { bizplaceId: custCompanyBizplace.id })
107
+
108
+ if (!sku && !refCode) {
109
+ context.throw(404, t('error.sku or refCode not found'))
110
+ }
105
111
 
106
- if (packingType) {
107
- qb.andWhere('PB.packing_type = :packingType', { packingType })
112
+ if (refCode) {
113
+ qb.andWhere('PB.ref_code = :refCode', { refCode })
108
114
  }
109
- }
110
115
 
111
- if (refCode) {
112
- qb.andWhere('PB.ref_code = :refCode', { refCode })
116
+ if (sku) {
117
+ qb.andWhere('PB.sku = :sku', { sku })
118
+ }
113
119
 
114
120
  if (packingType) {
115
121
  qb.andWhere('PB.packing_type = :packingType', { packingType })
116
122
  }
117
- }
118
123
 
119
- const foundProductBundle: ProductBundle = await qb.getOne()
120
-
121
- if (foundProductBundle) {
122
- const bundleProductSettings: any[] = foundProductBundle.productBundleSettings
123
- bundleProductSettings.map(bundleProductSetting => {
124
- const productDetailBundle: ProductDetail = bundleProductSetting.productDetail
125
-
126
- let newOrderInventory: OrderInventory = Object.assign({}, orderInventory)
127
- newOrderInventory.product.sku = productDetailBundle.product.sku
128
- newOrderInventory.packingType = productDetailBundle.packingType
129
- newOrderInventory.uomValue = productDetailBundle.uomValue
130
- newOrderInventory.releaseQty = orderInventory.releaseQty * bundleProductSetting.bundleQty
131
- newOrderInventory.product = productDetailBundle.product
132
- newOrderInventories.push(newOrderInventory)
133
- })
134
- } else {
135
- context.throw(404, t(`error.${orderInventory.product?.sku} not exist in product / bundle master`))
136
- }
137
- }
138
- })
139
- )
140
-
141
- let finalOrderInventories: OrderInventory[] = []
142
-
143
- // Case 1. Every order inventories has specified batch id
144
- if (newOrderInventories.every((orderInventory: OrderInventory) => orderInventory.batchId)) {
145
- finalOrderInventories = await Promise.all(
146
- newOrderInventories.map(async (orderInventory: OrderInventory) => {
147
- let filters: any = [
148
- {
149
- name: 'batchId',
150
- operator: 'eq',
151
- value: orderInventory.batchId
152
- },
153
- {
154
- name: 'productName',
155
- operator: 'eq',
156
- value: orderInventory.product.sku
157
- },
158
- {
159
- name: 'bizplace',
160
- operator: 'in',
161
- value: [customerBizplaceId]
124
+ const foundProductBundle: ProductBundle = await qb.getOne()
125
+
126
+ if (foundProductBundle) {
127
+ const bundleProductSettings: any[] = foundProductBundle.productBundleSettings
128
+ bundleProductSettings.map(bundleProductSetting => {
129
+ const productDetailBundle: ProductDetail = bundleProductSetting.productDetail
130
+
131
+ let newOrderInventory: OrderInventory = Object.assign({}, orderInventory)
132
+ newOrderInventory.product.sku = productDetailBundle.product.sku
133
+ newOrderInventory.packingType = productDetailBundle.packingType
134
+ newOrderInventory.uomValue = productDetailBundle.uomValue
135
+ newOrderInventory.releaseQty = orderInventory.releaseQty * bundleProductSetting.bundleQty
136
+ newOrderInventory.product = productDetailBundle.product
137
+ newOrderInventories.push(newOrderInventory)
138
+ })
139
+ } else {
140
+ if (sku) {
141
+ context.throw(404, t(`error.sku ${sku} not exist in product / bundle master`))
142
+ } else if (refCode) {
143
+ context.throw(404, t(`error.refCode ${refCode} not exist in product / bundle master`))
144
+ }
162
145
  }
163
- ]
164
-
165
- // 2. get all inventory data according to SKU and batchId
166
- const response = await client.query({
167
- query: gql`
168
- query inventoriesByPallet($filters: [Filter]) {
169
- inventoriesByPallet(filters: $filters) {
170
- items {
171
- product {
172
- id
173
- name
174
- description
146
+ }
147
+ })
148
+ )
149
+
150
+ let finalOrderInventories: OrderInventory[] = []
151
+
152
+ // Case 1. Every order inventories has specified batch id
153
+ if (newOrderInventories.every((orderInventory: OrderInventory) => orderInventory.batchId)) {
154
+ finalOrderInventories = await Promise.all(
155
+ newOrderInventories.map(async (orderInventory: OrderInventory) => {
156
+ let filters: any = [
157
+ {
158
+ name: 'batchId',
159
+ operator: 'eq',
160
+ value: orderInventory.batchId
161
+ },
162
+ {
163
+ name: 'productName',
164
+ operator: 'eq',
165
+ value: orderInventory.product.sku
166
+ },
167
+ {
168
+ name: 'bizplace',
169
+ operator: 'in',
170
+ value: [customerBizplaceId]
171
+ }
172
+ ]
173
+
174
+ // 2. get all inventory data according to SKU and batchId
175
+ const response = await client.query({
176
+ query: gql`
177
+ query inventoriesByPallet($filters: [Filter]) {
178
+ inventoriesByPallet(filters: $filters) {
179
+ items {
180
+ product {
181
+ id
182
+ name
183
+ description
184
+ }
185
+ batchId
186
+ packingType
187
+ remainQty
188
+ remainWeight
189
+ remainUomValue
175
190
  }
176
- batchId
177
- packingType
178
- remainQty
179
- remainWeight
180
- remainUomValue
191
+ total
181
192
  }
182
- total
193
+ }
194
+ `,
195
+ variables: { filters, locationSortingRules },
196
+ context: {
197
+ ...context,
198
+ state: {
199
+ ...context.state,
200
+ bizplace: customerBizplace,
201
+ domain
183
202
  }
184
203
  }
185
- `,
186
- variables: { filters, locationSortingRules },
187
- context: {
188
- ...context,
189
- state: {
190
- ...context.state,
191
- bizplace: customerBizplace,
192
- domain
193
- }
204
+ } as any)
205
+
206
+ if (!response.errors) {
207
+ const items = response.data.inventoriesByPallet.items || []
208
+ if (!items?.length)
209
+ context.throw(
210
+ 404,
211
+ t(
212
+ `error.no inventories found for ${orderInventory.product?.sku} with batch ID ${orderInventory?.batchId}`
213
+ )
214
+ )
215
+
216
+ items.forEach(item => {
217
+ if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
218
+ context.throw(404, t(`error.invalid release qty for ${orderInventory.product?.sku}`))
219
+ }
220
+
221
+ // 3. add more information to orderInventory
222
+ orderInventory.product.id = item.product.id
223
+ orderInventory.packingType = item.packingType
224
+ orderInventory.batchId = item.batchId
225
+ orderInventory.type = ORDER_TYPES.RELEASE_OF_GOODS
226
+ orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue
227
+ orderInventory.uom = item.uom
228
+ })
229
+
230
+ return orderInventory
231
+ } else context.throw(404, t('error.failed to fetch inventory'))
232
+ })
233
+ )
234
+ } else {
235
+ // Case 2. Some of order inventories doesn't have specified batch id
236
+ // MMS order doesn't have batch ID field.
237
+ // To cover this case first result of found inventory will be a target of RO
238
+
239
+ for (let i: number = 0; i < newOrderInventories.length; i++) {
240
+ const orderInventory: OrderInventory = newOrderInventories[i]
241
+ const product: Product = orderInventory.product
242
+ const packingType: string = orderInventory.packingType
243
+
244
+ if (isAutoAssign) {
245
+ let qb: SelectQueryBuilder<Inventory> = tx.getRepository(Inventory).createQueryBuilder('iv')
246
+ qb.leftJoinAndSelect('iv.location', 'loc')
247
+ .andWhere('"iv"."domain_id" = :domainId')
248
+ .andWhere('"iv"."bizplace_id" = :bizplaceId')
249
+ .andWhere('"iv"."packing_type" = :packingType')
250
+ .andWhere('"iv"."product_id" = :productId')
251
+ .andWhere('"iv"."status" = :status')
252
+ .setParameters({
253
+ domainId: domain.id,
254
+ bizplaceId: customerBizplace.id,
255
+ packingType: packingType,
256
+ productId: product.id,
257
+ status: INVENTORY_STATUS.STORED
258
+ })
259
+
260
+ if (locationSortingRules?.length > 0) {
261
+ locationSortingRules.forEach((rule: { name: string; desc: boolean }, idx: number) => {
262
+ idx === 0
263
+ ? qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
264
+ : qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
265
+ })
266
+ } else {
267
+ qb.addOrderBy('"iv"."created_at"', 'ASC')
194
268
  }
195
- } as any)
196
269
 
197
- if (!response.errors) {
198
- const items = response.data.inventoriesByPallet.items || []
199
- if (!items?.length)
200
- context.throw(
201
- 404,
202
- t(
203
- `error.no inventories found for ${orderInventory.product?.sku} with batch ID ${orderInventory?.batchId}`
204
- )
205
- )
270
+ let inventories: Inventory[] = await qb.getMany()
271
+ if (!inventories?.length) context.throw(404, t(`error.no inventories found for ${product.sku}`))
206
272
 
207
- items.forEach(item => {
208
- if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
209
- context.throw(404, t(`error.invalid release qty for ${orderInventory.product?.sku}`))
273
+ inventories = inventories.map(inventory => {
274
+ return {
275
+ ...inventory,
276
+ remainQty: inventory.qty - inventory.lockedQty,
277
+ remainUomValue: inventory.uomValue - inventory.lockedUomValue
210
278
  }
279
+ })
211
280
 
212
- // 3. add more information to orderInventory
213
- orderInventory.product.id = item.product.id
214
- orderInventory.packingType = item.packingType
215
- orderInventory.batchId = item.batchId
216
- orderInventory.type = ORDER_TYPES.RELEASE_OF_GOODS
217
- orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue
218
- orderInventory.uom = item.uom
281
+ const targetInventories: WorksheetDetail[] = _composeTargetInventories(
282
+ context,
283
+ product,
284
+ orderInventory,
285
+ inventories
286
+ )
287
+ targetInventories.map(item => {
288
+ finalOrderInventories.push(item.targetInventory)
219
289
  })
290
+ } else {
291
+ let filters: any = [
292
+ {
293
+ name: 'productName',
294
+ operator: 'eq',
295
+ value: orderInventory.product.sku
296
+ },
297
+ {
298
+ name: 'bizplace_id',
299
+ operator: 'eq',
300
+ value: customerBizplaceId
301
+ }
302
+ ]
303
+
304
+ // 2. get all inventory data according to SKU and batchId
305
+ const response = await client.query({
306
+ query: gql`
307
+ query inventoryProductGroup($filters: [Filter]) {
308
+ inventoryProductGroup(filters: $filters) {
309
+ items {
310
+ productId
311
+ productSKU
312
+ productName
313
+ batchId
314
+ packingType
315
+ remainQty
316
+ remainWeight
317
+ remainUomValue
318
+ }
319
+ total
320
+ }
321
+ }
322
+ `,
323
+ variables: { filters },
324
+ context: {
325
+ ...context,
326
+ state: {
327
+ ...context.state,
328
+ bizplace: customerBizplace,
329
+ domain
330
+ }
331
+ }
332
+ } as any)
333
+
334
+ if (!response.errors) {
335
+ const items = response.data.inventoryProductGroup.items || []
336
+ if (!items?.length)
337
+ context.throw(
338
+ 404,
339
+ t(
340
+ `error.no inventories found for ${orderInventory.product?.sku} with batch ID ${orderInventory?.batchId}`
341
+ )
342
+ )
220
343
 
221
- return orderInventory
222
- } else context.throw(404, t('error.failed to fetch inventory'))
223
- })
224
- )
225
- } else {
226
- // Case 2. Some of order inventories doesn't have specified batch id
227
- // MMS order doesn't have batch ID field.
228
- // To cover this case first result of found inventory will be a target of RO
229
-
230
- for (let i: number = 0; i < newOrderInventories.length; i++) {
231
- const orderInventory: OrderInventory = newOrderInventories[i]
232
- const product: Product = orderInventory.product
233
- const packingType: string = orderInventory.packingType
234
-
235
- let qb: SelectQueryBuilder<Inventory> = getRepository(Inventory).createQueryBuilder('iv')
236
- qb.leftJoinAndSelect('iv.location', 'loc')
237
- .andWhere('"iv"."domain_id" = :domainId')
238
- .andWhere('"iv"."bizplace_id" = :bizplaceId')
239
- .andWhere('"iv"."packing_type" = :packingType')
240
- .andWhere('"iv"."product_id" = :productId')
241
- .andWhere('"iv"."status" = :status')
242
- .setParameters({
243
- domainId: domain.id,
244
- bizplaceId: customerBizplace.id,
245
- packingType: packingType,
246
- productId: product.id,
247
- status: INVENTORY_STATUS.STORED
248
- })
344
+ items.forEach(item => {
345
+ if (orderInventory.releaseQty > item.remainQty || orderInventory.releaseQty <= 0) {
346
+ context.throw(404, t(`error.invalid release qty for ${orderInventory.product?.sku}`))
347
+ }
249
348
 
250
- if (locationSortingRules?.length > 0) {
251
- locationSortingRules.forEach((rule: { name: string; desc: boolean }, idx: number) => {
252
- idx === 0
253
- ? qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
254
- : qb.addOrderBy(`loc.${rule.name}`, rule.desc ? 'DESC' : 'ASC')
255
- })
256
- } else {
257
- qb.addOrderBy('"iv"."created_at"', 'ASC')
349
+ // 3. add more information to orderInventory
350
+ orderInventory.product = { id: item.productId }
351
+ orderInventory.packingType = item.packingType
352
+ orderInventory.batchId = item.batchId
353
+ orderInventory.type = ORDER_TYPES.RELEASE_OF_GOODS
354
+ orderInventory.releaseUomValue = orderInventory.releaseQty * orderInventory.uomValue
355
+ orderInventory.uom = item.uom
356
+ })
357
+
358
+ delete orderInventory.uomValue
359
+ finalOrderInventories.push(orderInventory)
360
+ } else context.throw(404, t('error.failed to fetch inventory'))
361
+ }
258
362
  }
259
-
260
- const inventories: Inventory[] = await qb.getMany()
261
- if (!inventories?.length) context.throw(404, t(`error.no inventories found for ${product.sku}`))
262
-
263
- const targetInventories: WorksheetDetail[] = _composeTargetInventories(
264
- context,
265
- product,
266
- orderInventory,
267
- inventories
268
- )
269
- targetInventories.map(item => {
270
- finalOrderInventories.push(item.targetInventory)
271
- })
272
363
  }
273
- }
274
364
 
275
- context.body = {
276
- result: (
277
- await client.mutate({
278
- mutation: gql`
279
- mutation addReleaseGood($releaseGood: NewReleaseGood, $shippingOrder: ShippingOrderPatch, $file: Upload) {
280
- addReleaseGood(releaseGood: $releaseGood, shippingOrder: $shippingOrder, file: $file) {
281
- id
282
- name
283
- refNo
284
- status
285
- truckNo
286
- ownTransport
287
- crossDocking
288
- marketplaceOrderStatus
289
- billingAddress
290
- deliveryAddress1
291
- deliveryAddress2
292
- deliveryAddress3
293
- deliveryAddress4
294
- deliveryAddress5
295
- attentionTo
296
- attentionCompany
297
- city
298
- state
299
- postalCode
300
- country
301
- phone1
302
- phone2
303
- email
304
- transporter
305
- trackingNo
306
- airwayBill
307
- invoice
308
- type
309
- arrivalNotice {
365
+ context.body = {
366
+ result: (
367
+ await client.mutate({
368
+ mutation: gql`
369
+ mutation addReleaseGood($releaseGood: NewReleaseGood, $shippingOrder: ShippingOrderPatch, $file: Upload) {
370
+ addReleaseGood(releaseGood: $releaseGood, shippingOrder: $shippingOrder, file: $file) {
371
+ id
310
372
  name
311
- }
312
- exportOption
313
- releaseDate
314
- collectionOrderNo
315
- bizplace {
316
- name
317
- }
318
- orderInventories {
319
- product {
320
- sku
373
+ refNo
374
+ status
375
+ truckNo
376
+ ownTransport
377
+ crossDocking
378
+ marketplaceOrderStatus
379
+ billingAddress
380
+ deliveryAddress1
381
+ deliveryAddress2
382
+ deliveryAddress3
383
+ deliveryAddress4
384
+ deliveryAddress5
385
+ attentionTo
386
+ attentionCompany
387
+ city
388
+ state
389
+ postalCode
390
+ country
391
+ phone1
392
+ phone2
393
+ email
394
+ transporter
395
+ trackingNo
396
+ airwayBill
397
+ invoice
398
+ type
399
+ arrivalNotice {
321
400
  name
322
- description
323
401
  }
324
- batchId
325
- packingType
326
- packingSize
327
- releaseQty
328
- releaseUomValue
329
- }
330
- orderVass {
331
- vas {
402
+ exportOption
403
+ releaseDate
404
+ collectionOrderNo
405
+ bizplace {
332
406
  name
333
- operationGuide
334
- operationGuideType
335
407
  }
336
- set
337
- targetType
338
- targetBatchId
339
- targetProduct {
340
- name
408
+ orderInventories {
409
+ product {
410
+ sku
411
+ name
412
+ description
413
+ }
414
+ batchId
415
+ packingType
416
+ packingSize
417
+ releaseQty
418
+ releaseUomValue
419
+ }
420
+ orderVass {
421
+ vas {
422
+ name
423
+ operationGuide
424
+ operationGuideType
425
+ }
426
+ set
427
+ targetType
428
+ targetBatchId
429
+ targetProduct {
430
+ name
431
+ description
432
+ }
433
+ packingType
434
+ qty
435
+ uomValue
436
+ otherTarget
341
437
  description
438
+ remark
439
+ status
440
+ operationGuide
342
441
  }
343
- packingType
344
- qty
345
- uomValue
346
- otherTarget
347
- description
348
- remark
349
- status
350
- operationGuide
351
442
  }
352
443
  }
444
+ `,
445
+ variables: {
446
+ releaseGood: {
447
+ customerBizplaceId: customerBizplace.id,
448
+ courierOption: bodyReq.courierOption,
449
+ collectionOrderNo: bodyReq.collectionOrderNo,
450
+ exportOption: bodyReq.exportOption,
451
+ orderInventories: finalOrderInventories,
452
+ ownTransport: bodyReq.ownTransport,
453
+ packingOption: bodyReq.packingOption,
454
+ refNo: bodyReq.refNo,
455
+ refNo2: bodyReq?.refNo2,
456
+ releaseDate: bodyReq.releaseDate,
457
+ type: bodyReq.type,
458
+ marketplaceOrderStatus: bodyReq?.marketplaceOrderStatus,
459
+ billingAddress: bodyReq?.billTo?.billingAddress || null,
460
+ deliveryAddress1: bodyReq?.deliverTo?.deliveryAddress1 || null,
461
+ deliveryAddress2: bodyReq?.deliverTo?.deliveryAddress2 || null,
462
+ deliveryAddress3: bodyReq?.deliverTo?.deliveryAddress3 || null,
463
+ deliveryAddress4: bodyReq?.deliverTo?.deliveryAddress4 || null,
464
+ deliveryAddress5: bodyReq?.deliverTo?.deliveryAddress5 || null,
465
+ attentionTo: bodyReq?.deliverTo?.attentionTo || null,
466
+ attentionCompany: bodyReq?.deliverTo?.attentionCompany || null,
467
+ city: bodyReq?.deliverTo?.city || null,
468
+ state: bodyReq?.deliverTo?.state || null,
469
+ postalCode: bodyReq?.deliverTo?.postalCode || null,
470
+ country: bodyReq?.deliverTo?.country || null,
471
+ phone1: bodyReq?.deliverTo?.phone1 || null,
472
+ phone2: bodyReq?.deliverTo?.phone2 || null,
473
+ email: bodyReq?.deliverTo?.email || null,
474
+ transporter: bodyReq?.transporter,
475
+ trackingNo: bodyReq?.trackingNo,
476
+ airwayBill: bodyReq?.airwayBill,
477
+ invoice: bodyReq?.invoice
478
+ }
479
+ },
480
+ context: {
481
+ ...context,
482
+ hasUpload: true,
483
+ state: {
484
+ ...context.state,
485
+ customerBizplace,
486
+ domain,
487
+ type: 'api'
488
+ }
353
489
  }
354
- `,
355
- variables: {
356
- releaseGood: {
357
- customerBizplaceId: customerBizplace.id,
358
- courierOption: bodyReq.courierOption,
359
- collectionOrderNo: bodyReq.collectionOrderNo,
360
- exportOption: bodyReq.exportOption,
361
- orderInventories: finalOrderInventories,
362
- ownTransport: bodyReq.ownTransport,
363
- packingOption: bodyReq.packingOption,
364
- refNo: bodyReq.refNo,
365
- refNo2: bodyReq?.refNo2,
366
- releaseDate: bodyReq.releaseDate,
367
- type: bodyReq.type,
368
- marketplaceOrderStatus: bodyReq?.marketplaceOrderStatus,
369
- billingAddress: bodyReq?.billTo?.billingAddress || null,
370
- deliveryAddress1: bodyReq?.deliverTo?.deliveryAddress1 || null,
371
- deliveryAddress2: bodyReq?.deliverTo?.deliveryAddress2 || null,
372
- deliveryAddress3: bodyReq?.deliverTo?.deliveryAddress3 || null,
373
- deliveryAddress4: bodyReq?.deliverTo?.deliveryAddress4 || null,
374
- deliveryAddress5: bodyReq?.deliverTo?.deliveryAddress5 || null,
375
- attentionTo: bodyReq?.deliverTo?.attentionTo || null,
376
- attentionCompany: bodyReq?.deliverTo?.attentionCompany || null,
377
- city: bodyReq?.deliverTo?.city || null,
378
- state: bodyReq?.deliverTo?.state || null,
379
- postalCode: bodyReq?.deliverTo?.postalCode || null,
380
- country: bodyReq?.deliverTo?.country || null,
381
- phone1: bodyReq?.deliverTo?.phone1 || null,
382
- phone2: bodyReq?.deliverTo?.phone2 || null,
383
- email: bodyReq?.deliverTo?.email || null,
384
- transporter: bodyReq?.transporter,
385
- trackingNo: bodyReq?.trackingNo,
386
- airwayBill: bodyReq?.airwayBill,
387
- invoice: bodyReq?.invoice
388
- }
389
- },
390
- context: {
391
- ...context,
392
- hasUpload: true,
393
- state: {
394
- ...context.state,
395
- customerBizplace,
396
- domain,
397
- type: 'api'
398
- }
399
- }
400
- } as any)
401
- ).data
402
- }
490
+ } as any)
491
+ ).data
492
+ }
493
+ })
403
494
  }
404
495
  )
405
496
 
@@ -430,9 +521,18 @@ export async function checkMandatoryKey(context, params) {
430
521
  }
431
522
 
432
523
  if ('orderInventories' in params) {
433
- if (params.orderInventories.filter(record => !record.releaseQty || !record.product).length) {
434
- noparams.push('orderInventories')
435
- }
524
+ params.orderInventories.forEach((param, key) => {
525
+ let noSubParams = []
526
+
527
+ if (!param?.releaseQty) noSubParams.push('releaseQty')
528
+
529
+ if (!param?.product) noSubParams.push('product')
530
+
531
+ if (noSubParams?.length)
532
+ context.throw(400, context.t('error.required param x not found', { x: `${noSubParams.join(', ')}` }))
533
+ })
534
+ } else {
535
+ noparams.push('orderInventories')
436
536
  }
437
537
 
438
538
  if (noparams?.length) {
@@ -451,7 +551,7 @@ export function _composeTargetInventories(context, product, record, inventories)
451
551
  let totalInventoryQty: number = 0
452
552
 
453
553
  inventories.map(inventory => {
454
- totalInventoryQty += inventory.qty
554
+ totalInventoryQty += inventory.remainQty
455
555
  })
456
556
 
457
557
  if (totalInventoryQty < record.releaseQty) {
@@ -463,7 +563,7 @@ export function _composeTargetInventories(context, product, record, inventories)
463
563
  while (compReleaseQty < record.releaseQty) {
464
564
  const inv = inventories[idx]
465
565
 
466
- if (inv.qty > leftReleaseQty) {
566
+ if (inv.remainQty > leftReleaseQty) {
467
567
  compReleaseQty += leftReleaseQty
468
568
  compReleaseUomValue += leftReleaseUomValue
469
569
 
@@ -480,18 +580,18 @@ export function _composeTargetInventories(context, product, record, inventories)
480
580
  }
481
581
  })
482
582
  } else {
483
- compReleaseQty += inv.qty
484
- compReleaseUomValue += inv.uomValue
485
- leftReleaseQty -= inv.qty
486
- leftReleaseUomValue -= inv.uomValue
583
+ compReleaseQty += inv.remainQty
584
+ compReleaseUomValue += inv.remainUomValue
585
+ leftReleaseQty -= inv.remainQty
586
+ leftReleaseUomValue -= inv.remainUomValue
487
587
 
488
588
  targetInventories.push({
489
589
  targetInventory: {
490
590
  inventory: { id: inv.id },
491
591
  packingType: inv.packingType,
492
592
  batchId: inv.batchId,
493
- releaseQty: inv.qty,
494
- releaseUomValue: inv.uomValue,
593
+ releaseQty: inv.remainQty,
594
+ releaseUomValue: inv.remainUomValue,
495
595
  uom: inv.uom,
496
596
  product: { id: product.id },
497
597
  type: ORDER_TYPES.RELEASE_OF_GOODS