@things-factory/sales-base 4.3.639 → 4.3.643

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 (64) 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/draft-release-good/draft-release-good-query.js +32 -26
  8. package/dist-server/service/draft-release-good/draft-release-good-query.js.map +1 -1
  9. package/dist-server/service/inventory-check-item/inventory-check-item-types.js +48 -12
  10. package/dist-server/service/inventory-check-item/inventory-check-item-types.js.map +1 -1
  11. package/dist-server/service/inventory-check-item/inventory-check-item.js +56 -4
  12. package/dist-server/service/inventory-check-item/inventory-check-item.js.map +1 -1
  13. package/dist-server/service/order-inventory/order-inventory-query.js +5 -1
  14. package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
  15. package/dist-server/service/order-inventory/order-inventory-types.js +12 -12
  16. package/dist-server/service/order-inventory/order-inventory-types.js.map +1 -1
  17. package/dist-server/service/order-inventory/order-inventory.js +189 -13
  18. package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
  19. package/dist-server/service/order-package-item/order-package-item-types.js +14 -2
  20. package/dist-server/service/order-package-item/order-package-item-types.js.map +1 -1
  21. package/dist-server/service/order-package-item/order-package-item.js +28 -2
  22. package/dist-server/service/order-package-item/order-package-item.js.map +1 -1
  23. package/dist-server/service/order-product/order-product-types.js +18 -18
  24. package/dist-server/service/order-product/order-product-types.js.map +1 -1
  25. package/dist-server/service/order-product/order-product.js +104 -13
  26. package/dist-server/service/order-product/order-product.js.map +1 -1
  27. package/dist-server/service/order-tote-item/order-tote-item-types.js +2 -2
  28. package/dist-server/service/order-tote-item/order-tote-item-types.js.map +1 -1
  29. package/dist-server/service/order-tote-item/order-tote-item.js +15 -1
  30. package/dist-server/service/order-tote-item/order-tote-item.js.map +1 -1
  31. package/dist-server/service/others/other-query.js +4 -4
  32. package/dist-server/service/others/other-query.js.map +1 -1
  33. package/dist-server/service/others/other-types.js +8 -4
  34. package/dist-server/service/others/other-types.js.map +1 -1
  35. package/dist-server/service/release-good/release-good-mutation.js +35 -6
  36. package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
  37. package/dist-server/service/release-good/release-good-query.js +23 -11
  38. package/dist-server/service/release-good/release-good-query.js.map +1 -1
  39. package/dist-server/service/release-good/release-good-types.js +1 -1
  40. package/dist-server/service/release-good/release-good-types.js.map +1 -1
  41. package/dist-server/utils/inventory-util.js +18 -14
  42. package/dist-server/utils/inventory-util.js.map +1 -1
  43. package/package.json +8 -8
  44. package/server/service/arrival-notice/arrival-notice-mutation.ts +39 -2
  45. package/server/service/arrival-notice/arrival-notice-query.ts +40 -68
  46. package/server/service/arrival-notice/arrival-notice-types.ts +4 -4
  47. package/server/service/draft-release-good/draft-release-good-query.ts +49 -42
  48. package/server/service/inventory-check-item/inventory-check-item-types.ts +37 -10
  49. package/server/service/inventory-check-item/inventory-check-item.ts +52 -4
  50. package/server/service/order-inventory/order-inventory-query.ts +5 -0
  51. package/server/service/order-inventory/order-inventory-types.ts +12 -12
  52. package/server/service/order-inventory/order-inventory.ts +171 -13
  53. package/server/service/order-package-item/order-package-item-types.ts +12 -3
  54. package/server/service/order-package-item/order-package-item.ts +26 -2
  55. package/server/service/order-product/order-product-types.ts +18 -18
  56. package/server/service/order-product/order-product.ts +96 -12
  57. package/server/service/order-tote-item/order-tote-item-types.ts +3 -3
  58. package/server/service/order-tote-item/order-tote-item.ts +14 -1
  59. package/server/service/others/other-query.ts +8 -8
  60. package/server/service/others/other-types.ts +7 -4
  61. package/server/service/release-good/release-good-mutation.ts +51 -9
  62. package/server/service/release-good/release-good-query.ts +30 -14
  63. package/server/service/release-good/release-good-types.ts +1 -1
  64. package/server/utils/inventory-util.ts +50 -60
@@ -70,11 +70,35 @@ export class OrderPackageItem {
70
70
  @Field({ nullable: true })
71
71
  status?: string
72
72
 
73
- @Column({ nullable: true })
73
+ @Column({
74
+ type: 'decimal',
75
+ scale: 3,
76
+ nullable: true,
77
+ transformer: {
78
+ to: (value: string | null) => value,
79
+ from: (value: string | null) => {
80
+ if (value === null || value === undefined) return null
81
+ const parsed = parseFloat(value)
82
+ return isNaN(parsed) ? null : parsed
83
+ }
84
+ }
85
+ })
74
86
  @Field({ nullable: true })
75
87
  releaseQty: number
76
88
 
77
- @Column({ nullable: true })
89
+ @Column({
90
+ type: 'decimal',
91
+ scale: 3,
92
+ nullable: true,
93
+ transformer: {
94
+ to: (value: string | null) => value,
95
+ from: (value: string | null) => {
96
+ if (value === null || value === undefined) return null
97
+ const parsed = parseFloat(value)
98
+ return isNaN(parsed) ? null : parsed
99
+ }
100
+ }
101
+ })
78
102
  @Field({ nullable: true })
79
103
  packedQty: number
80
104
 
@@ -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 })
@@ -66,6 +66,40 @@ import { ReleaseGood } from './release-good'
66
66
  import { bulkReleaseGoodsAvailableItemsFunction } from './release-good-query'
67
67
  import { getTmsService } from '@things-factory/integration-lmd'
68
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
+ }
102
+
69
103
  @Resolver(ReleaseGood)
70
104
  export class ReleaseGoodMutation {
71
105
  @Directive('@privilege(category: "order_customer", privilege: "mutation")')
@@ -445,8 +479,8 @@ export async function deleteReleaseGood(tx: EntityManager, name: string, user: U
445
479
 
446
480
  await tx.getRepository(Inventory).save({
447
481
  ...oi.inventory,
448
- lockedQty: oi.inventory.lockedQty - oi.releaseQty,
449
- lockedUomValue: oi.inventory.lockedUomValue - oi.releaseUomValue,
482
+ lockedQty: safeDecimalOperation(oi.inventory.lockedQty, oi.releaseQty, 'subtract'),
483
+ lockedUomValue: safeDecimalOperation(oi.inventory.lockedUomValue, oi.releaseUomValue, 'subtract'),
450
484
  updater: user
451
485
  })
452
486
  }
@@ -813,8 +847,12 @@ export async function generateReleaseGoodFunction(
813
847
  pbSettings.forEach(pbs => {
814
848
  splitOI = {
815
849
  ...oi,
816
- releaseQty: oi.releaseQty * pbs.bundleQty,
817
- 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
+ ),
818
856
  packingType: pbs.product.packingType,
819
857
  batchId: '',
820
858
  product: {
@@ -1414,8 +1452,8 @@ export async function rejectReleaseGood(
1414
1452
 
1415
1453
  await tx.getRepository(Inventory).save({
1416
1454
  ...oi.inventory,
1417
- lockedQty: oi.inventory.lockedQty - oi.releaseQty,
1418
- lockedUomValue: oi.inventory.lockedUomValue - oi.releaseUomValue,
1455
+ lockedQty: safeDecimalOperation(oi.inventory.lockedQty, oi.releaseQty, 'subtract'),
1456
+ lockedUomValue: safeDecimalOperation(oi.inventory.lockedUomValue, oi.releaseUomValue, 'subtract'),
1419
1457
  updater: user
1420
1458
  })
1421
1459
  }
@@ -1921,7 +1959,11 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
1921
1959
 
1922
1960
  // if there is duplicated SKU, merge them and sum up the releaseQty
1923
1961
  if (duplicateSkuIdx >= 0) {
1924
- 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
+ )
1925
1967
  } else {
1926
1968
  releaseGoods[idx].orderInventories.push({
1927
1969
  sku: item.sku,
@@ -1929,8 +1971,8 @@ function extractRawReleaseGoods(rawReleaseGoods): Partial<ReleaseGood[]> {
1929
1971
  packingType: item.packingType,
1930
1972
  packingSize: item.packingSize,
1931
1973
  uom: item.uom,
1932
- releaseQty: item.releaseQty,
1933
- releaseUomValue: item.releaseUomValue
1974
+ releaseQty: Math.round(parseFloat(item.releaseQty) * 1000) / 1000,
1975
+ releaseUomValue: Math.round(parseFloat(item.releaseUomValue) * 1000) / 1000,
1934
1976
  })
1935
1977
  }
1936
1978
  } else {
@@ -970,7 +970,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
970
970
  packing_type VARCHAR(50),
971
971
  packing_size FLOAT,
972
972
  uom VARCHAR(10),
973
- release_qty INT
973
+ release_qty NUMERIC(15,3)
974
974
  );
975
975
  `
976
976
  )
@@ -1027,9 +1027,11 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1027
1027
  AND oi.uom = i.uom
1028
1028
  AND oi.domain_id = $1
1029
1029
  AND oi.bizplace_id = $2
1030
- ), 0) as "remain_uom_value"
1030
+ ), 0) as "remain_uom_value",
1031
+ p.is_inventory_decimal
1031
1032
  FROM inventories i
1032
- LEFT JOIN locations l ON i.location_id = l.id
1033
+ INNER JOIN locations l ON i.location_id = l.id
1034
+ LEFT JOIN products p ON i.product_id = p.id
1033
1035
  INNER JOIN (
1034
1036
  SELECT rrg.product_id, rrg.product_detail_id, rrg.sku, rrg.product_info, rrg.packing_type, rrg.packing_size, rrg.uom
1035
1037
  FROM raw_release_goods rrg
@@ -1045,7 +1047,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1045
1047
  AND i.obsolete = false
1046
1048
  AND i.transfer_qty <= 0
1047
1049
  AND i.transfer_uom_value <= 0
1048
- GROUP BY i.product_id, foo.product_detail_id, foo.sku, foo.product_info, i.packing_type, i.packing_size, i.uom
1050
+ GROUP BY i.product_id, foo.product_detail_id, foo.sku, foo.product_info, i.packing_type, i.packing_size, i.uom, p.is_inventory_decimal
1049
1051
  ${useDetailedQuery ? ', i.batch_id, i.carton_id, i.expiration_date' : ''}
1050
1052
  ORDER BY foo.sku, remain_qty DESC
1051
1053
  ) SELECT * FROM inv WHERE remain_qty > 0
@@ -1056,7 +1058,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1056
1058
  await tx.query(`DROP TABLE raw_release_goods`)
1057
1059
 
1058
1060
  availableItems = availableItems.map(item => {
1059
- return {
1061
+ const mappedItem = {
1060
1062
  productId: item.product_id,
1061
1063
  productDetailId: item.product_detail_id,
1062
1064
  productInfo: item.product_info,
@@ -1068,8 +1070,10 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1068
1070
  remainUomValue: item.remain_uom_value,
1069
1071
  batchId: item.batch_id ? item.batch_id : null,
1070
1072
  cartonId: item.carton_id ? item.carton_id : null,
1071
- expirationDate: item.expiration_date ? _getStdDateStr(new Date(item.expiration_date)) : null
1073
+ expirationDate: item.expiration_date ? _getStdDateStr(new Date(item.expiration_date)) : null,
1074
+ isInventoryDecimal: item.is_inventory_decimal === true
1072
1075
  }
1076
+ return mappedItem
1073
1077
  })
1074
1078
 
1075
1079
  return _extractData(rawReleaseGoods, availableItems)
@@ -1120,17 +1124,25 @@ function _extractData(rawData, validatedData) {
1120
1124
  // if sku is matched, assign qty and product id
1121
1125
  if (idx >= 0) {
1122
1126
  // assign qty to rawData as much as possible
1123
- releaseUomValue = (Math.round((data[idx]?.remainUomValue / data[idx]?.remainQty) * 100) / 100) * raw.releaseQty
1127
+ releaseUomValue = (Math.round((data[idx]?.remainUomValue / data[idx]?.remainQty) * 1000) / 1000) * raw.releaseQty
1124
1128
 
1125
1129
  raw.assignedQty =
1126
- data[idx].remainQty >= raw.releaseQty ? (raw.releaseQty > 0 ? raw.releaseQty : 0) : data[idx].remainQty
1130
+ Math.round(
1131
+ (data[idx].remainQty >= raw.releaseQty
1132
+ ? raw.releaseQty > 0
1133
+ ? raw.releaseQty
1134
+ : 0
1135
+ : data[idx].remainQty) * 1000
1136
+ ) / 1000
1127
1137
 
1128
1138
  raw.assignedUomValue =
1129
- data[idx].remainUomValue >= releaseUomValue
1130
- ? releaseUomValue > 0
1131
- ? releaseUomValue
1132
- : 0
1133
- : data[idx].remainUomValue
1139
+ Math.round(
1140
+ (data[idx].remainUomValue >= releaseUomValue
1141
+ ? releaseUomValue > 0
1142
+ ? releaseUomValue
1143
+ : 0
1144
+ : data[idx].remainUomValue) * 1000
1145
+ ) / 1000
1134
1146
 
1135
1147
  // deduct qty & uomValue from validateData
1136
1148
  data[idx].remainQty -= raw.assignedQty
@@ -1142,6 +1154,7 @@ function _extractData(rawData, validatedData) {
1142
1154
  raw.packingType = data[idx].packingType
1143
1155
  raw.packingSize = data[idx].packingSize
1144
1156
  raw.uom = data[idx].uom
1157
+ raw.isInventoryDecimal = data[idx].isInventoryDecimal === true
1145
1158
  } else {
1146
1159
  raw.assignedQty = 0
1147
1160
  raw.assignedUomValue = 0
@@ -1162,9 +1175,12 @@ function _extractData(rawData, validatedData) {
1162
1175
  if (!raw.productId || !raw.productDetailId) {
1163
1176
  errors.push('inventory or product not found')
1164
1177
  }
1165
- if (raw.releaseQty <= 0 || raw.releaseQty % 1 !== 0) {
1178
+ if (raw.releaseQty <= 0) {
1166
1179
  errors.push('invalid release qty')
1167
1180
  }
1181
+ if (raw.releaseQty % 1 !== 0 && raw.isInventoryDecimal !== true) {
1182
+ errors.push('decimal quantities are not allowed for this product')
1183
+ }
1168
1184
  if (raw.assignedQty < raw.releaseQty) {
1169
1185
  errors.push('insufficient stock')
1170
1186
  }
@@ -99,7 +99,7 @@ export class InventoryInfos {
99
99
  @Field(type => Float, { nullable: true })
100
100
  packingSize?: number
101
101
 
102
- @Field(type => Int, { nullable: false })
102
+ @Field(type => Float, { nullable: false })
103
103
  qty?: number
104
104
 
105
105
  @Field(type => Float, { nullable: true })