@things-factory/sales-base 4.3.638 → 4.3.642

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.
Files changed (73) hide show
  1. package/dist-server/service/arrival-notice/arrival-notice-mutation.js +33 -2
  2. package/dist-server/service/arrival-notice/arrival-notice-mutation.js.map +1 -1
  3. package/dist-server/service/arrival-notice/arrival-notice-query.js +10 -3
  4. package/dist-server/service/arrival-notice/arrival-notice-query.js.map +1 -1
  5. package/dist-server/service/arrival-notice/arrival-notice-types.js +2 -2
  6. package/dist-server/service/arrival-notice/arrival-notice-types.js.map +1 -1
  7. package/dist-server/service/delivery-order/delivery-order-mutation.js +3 -1
  8. package/dist-server/service/delivery-order/delivery-order-mutation.js.map +1 -1
  9. package/dist-server/service/delivery-order/delivery-order-query.js +11 -0
  10. package/dist-server/service/delivery-order/delivery-order-query.js.map +1 -1
  11. package/dist-server/service/delivery-order/delivery-order.js +5 -0
  12. package/dist-server/service/delivery-order/delivery-order.js.map +1 -1
  13. package/dist-server/service/inventory-check-item/inventory-check-item-types.js +48 -12
  14. package/dist-server/service/inventory-check-item/inventory-check-item-types.js.map +1 -1
  15. package/dist-server/service/inventory-check-item/inventory-check-item.js +56 -4
  16. package/dist-server/service/inventory-check-item/inventory-check-item.js.map +1 -1
  17. package/dist-server/service/order-inventory/order-inventory-query.js +5 -1
  18. package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
  19. package/dist-server/service/order-inventory/order-inventory-types.js +12 -12
  20. package/dist-server/service/order-inventory/order-inventory-types.js.map +1 -1
  21. package/dist-server/service/order-inventory/order-inventory.js +189 -13
  22. package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
  23. package/dist-server/service/order-package-item/order-package-item-types.js +14 -2
  24. package/dist-server/service/order-package-item/order-package-item-types.js.map +1 -1
  25. package/dist-server/service/order-package-item/order-package-item.js +28 -2
  26. package/dist-server/service/order-package-item/order-package-item.js.map +1 -1
  27. package/dist-server/service/order-product/order-product-types.js +18 -18
  28. package/dist-server/service/order-product/order-product-types.js.map +1 -1
  29. package/dist-server/service/order-product/order-product.js +104 -13
  30. package/dist-server/service/order-product/order-product.js.map +1 -1
  31. package/dist-server/service/order-tote-item/order-tote-item-types.js +2 -2
  32. package/dist-server/service/order-tote-item/order-tote-item-types.js.map +1 -1
  33. package/dist-server/service/order-tote-item/order-tote-item.js +15 -1
  34. package/dist-server/service/order-tote-item/order-tote-item.js.map +1 -1
  35. package/dist-server/service/others/other-query.js +4 -4
  36. package/dist-server/service/others/other-query.js.map +1 -1
  37. package/dist-server/service/others/other-types.js +8 -4
  38. package/dist-server/service/others/other-types.js.map +1 -1
  39. package/dist-server/service/release-good/release-good-mutation.js +108 -16
  40. package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
  41. package/dist-server/service/release-good/release-good-query.js +33 -18
  42. package/dist-server/service/release-good/release-good-query.js.map +1 -1
  43. package/dist-server/service/release-good/release-good-types.js +1 -1
  44. package/dist-server/service/release-good/release-good-types.js.map +1 -1
  45. package/dist-server/service/release-good/release-good.js +15 -0
  46. package/dist-server/service/release-good/release-good.js.map +1 -1
  47. package/dist-server/utils/inventory-util.js +18 -14
  48. package/dist-server/utils/inventory-util.js.map +1 -1
  49. package/package.json +8 -7
  50. package/server/service/arrival-notice/arrival-notice-mutation.ts +39 -2
  51. package/server/service/arrival-notice/arrival-notice-query.ts +40 -68
  52. package/server/service/arrival-notice/arrival-notice-types.ts +4 -4
  53. package/server/service/delivery-order/delivery-order-mutation.ts +25 -67
  54. package/server/service/delivery-order/delivery-order-query.ts +24 -29
  55. package/server/service/delivery-order/delivery-order.ts +5 -1
  56. package/server/service/inventory-check-item/inventory-check-item-types.ts +37 -10
  57. package/server/service/inventory-check-item/inventory-check-item.ts +52 -4
  58. package/server/service/order-inventory/order-inventory-query.ts +5 -0
  59. package/server/service/order-inventory/order-inventory-types.ts +12 -12
  60. package/server/service/order-inventory/order-inventory.ts +171 -13
  61. package/server/service/order-package-item/order-package-item-types.ts +12 -3
  62. package/server/service/order-package-item/order-package-item.ts +26 -2
  63. package/server/service/order-product/order-product-types.ts +18 -18
  64. package/server/service/order-product/order-product.ts +96 -12
  65. package/server/service/order-tote-item/order-tote-item-types.ts +3 -3
  66. package/server/service/order-tote-item/order-tote-item.ts +14 -1
  67. package/server/service/others/other-query.ts +8 -8
  68. package/server/service/others/other-types.ts +7 -4
  69. package/server/service/release-good/release-good-mutation.ts +148 -22
  70. package/server/service/release-good/release-good-query.ts +112 -129
  71. package/server/service/release-good/release-good-types.ts +1 -1
  72. package/server/service/release-good/release-good.ts +12 -0
  73. package/server/utils/inventory-util.ts +50 -60
@@ -132,25 +132,25 @@ export class OrderProductPatch {
132
132
  @Field(type => Float, { nullable: true })
133
133
  unpackUomValue: number
134
134
 
135
- @Field(type => Int, { nullable: true })
135
+ @Field(type => Float, { nullable: true })
136
136
  packQty: number
137
137
 
138
- @Field(type => Int, { nullable: true })
138
+ @Field(type => Float, { nullable: true })
139
139
  adjustedPackQty: number
140
140
 
141
- @Field(type => Int, { nullable: true })
141
+ @Field(type => Float, { nullable: true })
142
142
  actualPackQty: number
143
143
 
144
- @Field(type => Int, { nullable: true })
144
+ @Field(type => Float, { nullable: true })
145
145
  unpackQty: number
146
146
 
147
- @Field(type => Int, { nullable: true })
147
+ @Field(type => Float, { nullable: true })
148
148
  palletQty: number
149
149
 
150
- @Field(type => Int, { nullable: true })
150
+ @Field(type => Float, { nullable: true })
151
151
  actualPalletQty: number
152
152
 
153
- @Field(type => Int, { nullable: true })
153
+ @Field(type => Float, { nullable: true })
154
154
  adjustedPalletQty: number
155
155
 
156
156
  @Field({ nullable: true })
@@ -162,7 +162,7 @@ export class OrderProductPatch {
162
162
  @Field({ nullable: true })
163
163
  totalUomValue: string
164
164
 
165
- @Field(type => Int, { nullable: true })
165
+ @Field(type => Float, { nullable: true })
166
166
  releaseQty: number
167
167
 
168
168
  @Field(type => Float, { nullable: true })
@@ -282,37 +282,37 @@ export class NewOrderProduct {
282
282
  @Field(type => Float, { nullable: true })
283
283
  unpackUomValue: number
284
284
 
285
- @Field(type => Int, { nullable: true })
285
+ @Field(type => Float, { nullable: true })
286
286
  packQty: number
287
287
 
288
- @Field(type => Int, { nullable: true })
288
+ @Field(type => Float, { nullable: true })
289
289
  adjustedPackQty: number
290
290
 
291
- @Field(type => Int, { nullable: true })
291
+ @Field(type => Float, { nullable: true })
292
292
  actualPackQty: number
293
293
 
294
- @Field(type => Int, { nullable: true })
294
+ @Field(type => Float, { nullable: true })
295
295
  unpackQty: number
296
296
 
297
- @Field(type => Int, { nullable: true })
297
+ @Field(type => Float, { nullable: true })
298
298
  palletQty: number
299
299
 
300
- @Field(type => Int, { nullable: true })
300
+ @Field(type => Float, { nullable: true })
301
301
  actualPalletQty: number
302
302
 
303
- @Field(type => Int, { nullable: true })
303
+ @Field(type => Float, { nullable: true })
304
304
  adjustedPalletQty: number
305
305
 
306
306
  @Field({ nullable: true })
307
- palletId: string
307
+ adjustedTotalUomValue: string
308
308
 
309
309
  @Field({ nullable: true })
310
- adjustedTotalUomValue: string
310
+ palletId: string
311
311
 
312
312
  @Field({ nullable: true })
313
313
  totalUomValue: string
314
314
 
315
- @Field(type => Int, { nullable: true })
315
+ @Field(type => Float, { nullable: true })
316
316
  releaseQty: number
317
317
 
318
318
  @Field(type => Float, { nullable: true })
@@ -254,25 +254,101 @@ export class OrderProduct {
254
254
  @Field({ nullable: true })
255
255
  adjustedUomValue: number
256
256
 
257
- @Column('float', { nullable: true })
257
+ @Column({
258
+ nullable: true,
259
+ type: 'decimal',
260
+ scale: 3,
261
+ transformer: {
262
+ to: (value: string | null) => value,
263
+ from: (value: string | null) => {
264
+ if (value === null || value === undefined) return null
265
+ const parsed = parseFloat(value)
266
+ return isNaN(parsed) ? null : parsed
267
+ }
268
+ }
269
+ })
270
+ @Field({ nullable: true })
271
+ unpackQty: number
272
+
273
+ @Column({
274
+ nullable: true,
275
+ type: 'decimal',
276
+ scale: 3,
277
+ transformer: {
278
+ to: (value: string | null) => value,
279
+ from: (value: string | null) => {
280
+ if (value === null || value === undefined) return null
281
+ const parsed = parseFloat(value)
282
+ return isNaN(parsed) ? null : parsed
283
+ }
284
+ }
285
+ })
258
286
  @Field({ nullable: true })
259
287
  unpackUomValue: number
260
288
 
261
- @Column()
262
- @Field()
289
+ @Column({
290
+ nullable: true,
291
+ type: 'decimal',
292
+ scale: 3,
293
+ transformer: {
294
+ to: (value: string | null) => value,
295
+ from: (value: string | null) => {
296
+ if (value === null || value === undefined) return null
297
+ const parsed = parseFloat(value)
298
+ return isNaN(parsed) ? null : parsed
299
+ }
300
+ }
301
+ })
302
+ @Field({ nullable: true })
263
303
  packQty: number
264
304
 
265
- @Column({ nullable: true })
305
+ @Column({
306
+ nullable: true,
307
+ type: 'decimal',
308
+ scale: 3,
309
+ transformer: {
310
+ to: (value: string | null) => value,
311
+ from: (value: string | null) => {
312
+ if (value === null || value === undefined) return null
313
+ const parsed = parseFloat(value)
314
+ return isNaN(parsed) ? null : parsed
315
+ }
316
+ }
317
+ })
266
318
  @Field({ nullable: true })
267
319
  adjustedPackQty: number
268
320
 
269
- @Column({ nullable: true })
321
+ @Column({
322
+ nullable: true,
323
+ type: 'decimal',
324
+ scale: 3,
325
+ transformer: {
326
+ to: (value: string | null) => value,
327
+ from: (value: string | null) => {
328
+ if (value === null || value === undefined) return null
329
+ const parsed = parseFloat(value)
330
+ return isNaN(parsed) ? null : parsed
331
+ }
332
+ }
333
+ })
270
334
  @Field({ nullable: true })
271
335
  actualPackQty: number
272
336
 
273
- @Column('float', { nullable: true })
337
+ @Column({
338
+ nullable: true,
339
+ type: 'decimal',
340
+ scale: 3,
341
+ transformer: {
342
+ to: (value: string | null) => value,
343
+ from: (value: string | null) => {
344
+ if (value === null || value === undefined) return null
345
+ const parsed = parseFloat(value)
346
+ return isNaN(parsed) ? null : parsed
347
+ }
348
+ }
349
+ })
274
350
  @Field({ nullable: true })
275
- unpackQty: number
351
+ releaseUomValue: number
276
352
 
277
353
  @Column('float', { nullable: true })
278
354
  @Field({ nullable: true })
@@ -326,14 +402,22 @@ export class OrderProduct {
326
402
  @Field({ nullable: true })
327
403
  adjustedTotalUomValue: string
328
404
 
329
- @Column({ nullable: true })
405
+ @Column({
406
+ nullable: true,
407
+ type: 'decimal',
408
+ scale: 3,
409
+ transformer: {
410
+ to: (value: string | null) => value,
411
+ from: (value: string | null) => {
412
+ if (value === null || value === undefined) return null
413
+ const parsed = parseFloat(value)
414
+ return isNaN(parsed) ? null : parsed
415
+ }
416
+ }
417
+ })
330
418
  @Field({ nullable: true })
331
419
  releaseQty: number
332
420
 
333
- @Column({ nullable: true, type: 'float' })
334
- @Field({ nullable: true })
335
- releaseUomValue: number
336
-
337
421
  @Column({ nullable: true })
338
422
  @Field({ nullable: true })
339
423
  remark: string
@@ -1,4 +1,4 @@
1
- import { Field, InputType, Int, ObjectType } from 'type-graphql'
1
+ import { Field, Float, InputType, Int, ObjectType } from 'type-graphql'
2
2
 
3
3
  import { ObjectRef } from '@things-factory/shell'
4
4
 
@@ -30,7 +30,7 @@ export class NewOrderToteItem {
30
30
  @Field(type => ObjectRef, { nullable: true })
31
31
  orderTote: ObjectRef
32
32
 
33
- @Field(type => Int)
33
+ @Field(type => Float, { nullable: true })
34
34
  qty: number
35
35
  }
36
36
 
@@ -51,6 +51,6 @@ export class OrderToteItemPatch {
51
51
  @Field(type => ObjectRef, { nullable: true })
52
52
  orderTote: ObjectRef
53
53
 
54
- @Field(type => Int)
54
+ @Field(type => Float, { nullable: true })
55
55
  qty: number
56
56
  }
@@ -47,7 +47,20 @@ export class OrderToteItem {
47
47
  @RelationId((orderToteItem: OrderToteItem) => orderToteItem.orderTote)
48
48
  orderToteId: string
49
49
 
50
- @Column('int')
50
+ @Column({
51
+ type: 'decimal',
52
+ scale: 3,
53
+ default: 0,
54
+ nullable: true,
55
+ transformer: {
56
+ to: (value: string | null) => value,
57
+ from: (value: string | null) => {
58
+ if (value === null || value === undefined) return null
59
+ const parsed = parseFloat(value)
60
+ return isNaN(parsed) ? null : parsed
61
+ }
62
+ }
63
+ })
51
64
  @Field({ nullable: true })
52
65
  qty?: number
53
66
 
@@ -212,11 +212,11 @@ export class OtherQuery {
212
212
  productDetail: availableItem ? { id: availableItem.productDetailId } : null,
213
213
  inventory: availableItem
214
214
  ? {
215
- ...availableItem,
216
- remainQty: availableItem ? availableItem.remainQty : null,
217
- remainUomValue: availableItem ? availableItem.remainUomValue : null,
218
- remainUomValueWithUom: availableItem ? availableItem.remainUomValueWithUom : ''
219
- }
215
+ ...availableItem,
216
+ remainQty: availableItem.remainQty,
217
+ remainUomValue: availableItem.remainUomValue,
218
+ remainUomValueWithUom: availableItem.remainUomValueWithUom || ''
219
+ }
220
220
  : null,
221
221
  productId: availableItem ? availableItem.productId : null,
222
222
  productDetailID: availableItem ? availableItem.productDetailId : null,
@@ -231,13 +231,13 @@ export class OtherQuery {
231
231
  packingType: availableItem ? availableItem.packingType : orderInventory.packingType,
232
232
  packingSize: availableItem ? availableItem.packingSize : 1,
233
233
  releaseQty: orderInventory.releaseQty
234
- ? Number.isInteger(orderInventory.releaseQty)
234
+ ? !Number.isNaN(orderInventory.releaseQty)
235
235
  ? orderInventory.releaseQty
236
236
  : null
237
237
  : null,
238
238
  releaseUomValue: availableItem
239
- ? Number.isInteger(orderInventory.releaseQty)
240
- ? parseFloat((orderInventory.releaseQty * packageUomValue).toFixed(2))
239
+ ? !Number.isNaN(orderInventory.releaseQty)
240
+ ? parseFloat((orderInventory.releaseQty * packageUomValue).toFixed(3))
241
241
  : null
242
242
  : null,
243
243
  groupType: availableItem ? availableItem.groupType : null,
@@ -37,22 +37,25 @@ export class InventoryProductGroup {
37
37
  @Field({ nullable: true })
38
38
  productBrand: string
39
39
 
40
+ @Field({ nullable: true })
41
+ isInventoryDecimal: boolean
42
+
40
43
  @Field({ nullable: true })
41
44
  packingType: string
42
45
 
43
46
  @Field(type => Float, { nullable: true })
44
47
  packingSize: number
45
48
 
46
- @Field(type => Int, { nullable: true })
49
+ @Field(type => Float, { nullable: true })
47
50
  packQty: number
48
51
 
49
- @Field(type => Int, { nullable: true })
52
+ @Field(type => Float, { nullable: true })
50
53
  totalQty: number
51
54
 
52
- @Field(type => Int, { nullable: true })
55
+ @Field(type => Float, { nullable: true })
53
56
  totalLockedQty: number
54
57
 
55
- @Field(type => Int, { nullable: true })
58
+ @Field(type => Float, { nullable: true })
56
59
  totalLockedUomValue: number
57
60
 
58
61
  @Field(type => Int, { nullable: true })
@@ -64,6 +64,41 @@ import { ShippingOrderPatch } from '../shipping-order/shipping-order-types'
64
64
  import { editVas } from '../vas'
65
65
  import { ReleaseGood } from './release-good'
66
66
  import { bulkReleaseGoodsAvailableItemsFunction } from './release-good-query'
67
+ import { getTmsService } from '@things-factory/integration-lmd'
68
+
69
+ // Utility function for safe decimal arithmetic
70
+ function safeDecimalOperation(value1: number, value2: number, operation: 'add' | 'subtract' | 'multiply'): number {
71
+ // Convert to string with fixed precision to avoid floating point issues
72
+ const num1 = parseFloat(value1.toFixed(3))
73
+ const num2 = parseFloat(value2.toFixed(3))
74
+
75
+ let result: number
76
+ switch (operation) {
77
+ case 'add':
78
+ result = num1 + num2
79
+ break
80
+ case 'subtract':
81
+ result = num1 - num2
82
+ break
83
+ case 'multiply':
84
+ result = num1 * num2
85
+ break
86
+ default:
87
+ throw new Error('Invalid operation')
88
+ }
89
+
90
+ // Ensure result is within valid range and has correct precision
91
+ if (result < 0) {
92
+ throw new Error('Decimal value cannot be negative')
93
+ }
94
+
95
+ // Check if result exceeds maximum precision (10 digits total with 3 decimal places)
96
+ if (result > 9999999.999) {
97
+ throw new Error('Decimal value exceeds maximum allowed precision')
98
+ }
99
+
100
+ return parseFloat(result.toFixed(3))
101
+ }
67
102
 
68
103
  @Resolver(ReleaseGood)
69
104
  export class ReleaseGoodMutation {
@@ -444,8 +479,8 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
444
479
 
445
480
  await tx.getRepository(Inventory).save({
446
481
  ...oi.inventory,
447
- lockedQty: oi.inventory.lockedQty - oi.releaseQty,
448
- lockedUomValue: oi.inventory.lockedUomValue - oi.releaseUomValue,
482
+ lockedQty: safeDecimalOperation(oi.inventory.lockedQty, oi.releaseQty, 'subtract'),
483
+ lockedUomValue: safeDecimalOperation(oi.inventory.lockedUomValue, oi.releaseUomValue, 'subtract'),
449
484
  updater: user
450
485
  })
451
486
  }
@@ -539,6 +574,11 @@ export async function generateReleaseGoodFunction(
539
574
  let warehouseDomain: Domain = domain
540
575
  let finalOrderInventories: OrderInventory[] = []
541
576
 
577
+ /** Validate for b2b order that uses LMD */
578
+ if (releaseGood.type === 'b2b' && !releaseGood.ownTransport) {
579
+ releaseGood = await validateB2BLmdOrder(releaseGood, warehouseDomain, tx, shippingOrderInfo)
580
+ }
581
+
542
582
  /** Validate user permitted Bizplace */
543
583
  if (releaseGood.warehouseId) {
544
584
  bizplace = await getOutletBizplace(releaseGood.warehouseId)
@@ -669,9 +709,10 @@ export async function generateReleaseGoodFunction(
669
709
  let lmd: any = null
670
710
  if (releaseGood?.lmdOption) {
671
711
  const geoCountryRepo: Repository<GeoCountry> = tx?.getRepository(GeoCountry) || getRepository(GeoCountry)
672
- let deliveryCountry: GeoCountry = releaseGood?.country
712
+ const countryNameOrDescription: string = releaseGood?.country || shippingOrderInfo?.country // shippingOrderInfo?.country when using lmd/tms for b2b orders
713
+ let deliveryCountry: GeoCountry = countryNameOrDescription
673
714
  ? await geoCountryRepo.findOne({
674
- where: [{ name: ILike(releaseGood?.country) }, { description: ILike(releaseGood?.country) }]
715
+ where: [{ name: ILike(countryNameOrDescription) }, { description: ILike(countryNameOrDescription) }]
675
716
  })
676
717
  : null
677
718
 
@@ -806,8 +847,12 @@ export async function generateReleaseGoodFunction(
806
847
  pbSettings.forEach(pbs => {
807
848
  splitOI = {
808
849
  ...oi,
809
- releaseQty: oi.releaseQty * pbs.bundleQty,
810
- releaseUomValue: oi.releaseUomValue * pbs.bundleQty * pbs.product.primaryValue,
850
+ releaseQty: safeDecimalOperation(oi.releaseQty, pbs.bundleQty, 'multiply'),
851
+ releaseUomValue: safeDecimalOperation(
852
+ safeDecimalOperation(oi.releaseUomValue, pbs.bundleQty, 'multiply'),
853
+ pbs.product.primaryValue,
854
+ 'multiply'
855
+ ),
811
856
  packingType: pbs.product.packingType,
812
857
  batchId: '',
813
858
  product: {
@@ -1313,6 +1358,16 @@ export async function receiveReleaseGood(name: string, context: any, tx: EntityM
1313
1358
  await tx.getRepository(OrderVas).save(foundOVs)
1314
1359
  }
1315
1360
 
1361
+ if (foundReleaseGood?.lmdOption && foundReleaseGood?.lastMileDelivery?.isTms) {
1362
+ const lastMileDeliveries: LastMileDelivery = foundReleaseGood.lastMileDelivery
1363
+
1364
+ let data = foundReleaseGood
1365
+
1366
+ const tmsService = getTmsService(lastMileDeliveries?.platform)
1367
+
1368
+ tmsService.createShipment([data])
1369
+ }
1370
+
1316
1371
  // notification logics
1317
1372
  // get Office Admin Users
1318
1373
  if (context?.state?.type != 'api') {
@@ -1397,8 +1452,8 @@ export async function rejectReleaseGood(
1397
1452
 
1398
1453
  await tx.getRepository(Inventory).save({
1399
1454
  ...oi.inventory,
1400
- lockedQty: oi.inventory.lockedQty - oi.releaseQty,
1401
- lockedUomValue: oi.inventory.lockedUomValue - oi.releaseUomValue,
1455
+ lockedQty: safeDecimalOperation(oi.inventory.lockedQty, oi.releaseQty, 'subtract'),
1456
+ lockedUomValue: safeDecimalOperation(oi.inventory.lockedUomValue, oi.releaseUomValue, 'subtract'),
1402
1457
  updater: user
1403
1458
  })
1404
1459
  }
@@ -1530,6 +1585,10 @@ export async function bulkGenerateReleaseGood(
1530
1585
  })
1531
1586
  : null
1532
1587
 
1588
+ if (releaseGood.type == 'b2b') {
1589
+ releaseGood = await validateB2BLmdOrder(releaseGood, domain, tx)
1590
+ }
1591
+
1533
1592
  let lmd: any = null
1534
1593
  if (releaseGood?.lmdOption) {
1535
1594
  //Assign LMD
@@ -1773,7 +1832,7 @@ export async function bulkConfirmOrReceiveReleaseGoods(
1773
1832
  ): Promise<ReleaseGood[]> {
1774
1833
  let foundReleaseGoods: ReleaseGood[] = await tx.getRepository(ReleaseGood).find({
1775
1834
  where: { name: In(releaseGoodsNo), status: ORDER_STATUS.PENDING },
1776
- relations: ['bizplace']
1835
+ relations: ['bizplace', 'lastMileDelivery']
1777
1836
  })
1778
1837
 
1779
1838
  if (!foundReleaseGoods.length) throw new Error(`release good order doesn't exists.`)
@@ -1837,16 +1896,27 @@ export async function bulkConfirmOrReceiveReleaseGoods(
1837
1896
  }
1838
1897
  }
1839
1898
 
1840
- return Promise.all(
1841
- foundReleaseGoods.map(async (releaseGood: ReleaseGood) => {
1842
- return {
1843
- ...releaseGood,
1844
- orderInventories: await tx.getRepository(OrderInventory).find({ where: releaseGood }),
1845
- status: orderStatus,
1846
- updater: user
1847
- }
1848
- })
1849
- )
1899
+ let roTMS: ReleaseGood[] = foundReleaseGoods.filter(rg => {
1900
+ rg.lastMileDelivery?.isTms && rg.lmdOption
1901
+ })
1902
+
1903
+ if (roTMS?.length) {
1904
+ const tmsService = getTmsService(roTMS[0].lastMileDelivery?.platform)
1905
+
1906
+ tmsService.createShipment(roTMS)
1907
+ }
1908
+
1909
+ if (foundReleaseGoods)
1910
+ return Promise.all(
1911
+ foundReleaseGoods.map(async (releaseGood: ReleaseGood) => {
1912
+ return {
1913
+ ...releaseGood,
1914
+ orderInventories: await tx.getRepository(OrderInventory).find({ where: releaseGood }),
1915
+ status: orderStatus,
1916
+ updater: user
1917
+ }
1918
+ })
1919
+ )
1850
1920
  }
1851
1921
 
1852
1922
  function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
@@ -1889,7 +1959,11 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
1889
1959
 
1890
1960
  // if there is duplicated SKU, merge them and sum up the releaseQty
1891
1961
  if (duplicateSkuIdx >= 0) {
1892
- releaseGoods[idx].orderInventories[duplicateSkuIdx].releaseQty += item.releaseQty
1962
+ releaseGoods[idx].orderInventories[duplicateSkuIdx].releaseQty = safeDecimalOperation(
1963
+ releaseGoods[idx].orderInventories[duplicateSkuIdx].releaseQty,
1964
+ item.releaseQty,
1965
+ 'add'
1966
+ )
1893
1967
  } else {
1894
1968
  releaseGoods[idx].orderInventories.push({
1895
1969
  sku: item.sku,
@@ -1897,8 +1971,8 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
1897
1971
  packingType: item.packingType,
1898
1972
  packingSize: item.packingSize,
1899
1973
  uom: item.uom,
1900
- releaseQty: item.releaseQty,
1901
- releaseUomValue: item.releaseUomValue
1974
+ releaseQty: Math.round(parseFloat(item.releaseQty) * 1000) / 1000,
1975
+ releaseUomValue: Math.round(parseFloat(item.releaseUomValue) * 1000) / 1000,
1902
1976
  })
1903
1977
  }
1904
1978
  } else {
@@ -2050,3 +2124,55 @@ async function autoAssignLmd(domain, countryId, postalCode, bizplace) {
2050
2124
 
2051
2125
  return lmdResult
2052
2126
  }
2127
+
2128
+ async function validateB2BLmdOrder(releaseGood, domain, tx, shippingOrderInfo?) {
2129
+ const tms: LastMileDelivery = await tx.getRepository(LastMileDelivery).find({
2130
+ where: { domain, status: 'active', isTms: true }
2131
+ })
2132
+
2133
+ if (tms.length > 0) {
2134
+ const checkShipmentFields = shippingOrderInfo => {
2135
+ if (
2136
+ !shippingOrderInfo?.deliveryAddress1 &&
2137
+ !shippingOrderInfo?.postalCode &&
2138
+ !shippingOrderInfo?.state &&
2139
+ !shippingOrderInfo?.city &&
2140
+ !shippingOrderInfo?.attentionTo &&
2141
+ !shippingOrderInfo?.phone1
2142
+ ) {
2143
+ throw new Error('please fill in the shipping information in shipment tab')
2144
+ }
2145
+
2146
+ if (!shippingOrderInfo?.attentionTo) {
2147
+ throw new Error('attention to is empty please fill in the data before proceed create order')
2148
+ }
2149
+
2150
+ if (!shippingOrderInfo?.postalCode) {
2151
+ throw new Error('zip/postal code is empty please fill in the data before proceed create order')
2152
+ }
2153
+
2154
+ if (!shippingOrderInfo?.state) {
2155
+ throw new Error('state is empty please fill in the data before proceed create order')
2156
+ }
2157
+
2158
+ if (!shippingOrderInfo?.city) {
2159
+ throw new Error('city is empty please fill in the data before proceed create order')
2160
+ }
2161
+
2162
+ if (!shippingOrderInfo?.deliveryAddress1) {
2163
+ throw new Error('delivery address is empty please fill in the data before proceed create order')
2164
+ }
2165
+
2166
+ if (!shippingOrderInfo?.phone1) {
2167
+ throw new Error('contact is empty please fill in the data before proceed create order')
2168
+ }
2169
+ }
2170
+
2171
+ checkShipmentFields(shippingOrderInfo)
2172
+ releaseGood.lmdOption = true
2173
+
2174
+ return releaseGood
2175
+ }
2176
+
2177
+ return releaseGood
2178
+ }