@things-factory/sales-base 4.3.636 → 4.3.637

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 (58) hide show
  1. package/dist-server/service/arrival-notice/arrival-notice-mutation.js +34 -3
  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/inventory-check-item/inventory-check-item-types.js +48 -12
  8. package/dist-server/service/inventory-check-item/inventory-check-item-types.js.map +1 -1
  9. package/dist-server/service/inventory-check-item/inventory-check-item.js +56 -4
  10. package/dist-server/service/inventory-check-item/inventory-check-item.js.map +1 -1
  11. package/dist-server/service/order-inventory/order-inventory-query.js +5 -1
  12. package/dist-server/service/order-inventory/order-inventory-query.js.map +1 -1
  13. package/dist-server/service/order-inventory/order-inventory-types.js +12 -12
  14. package/dist-server/service/order-inventory/order-inventory-types.js.map +1 -1
  15. package/dist-server/service/order-inventory/order-inventory.js +189 -13
  16. package/dist-server/service/order-inventory/order-inventory.js.map +1 -1
  17. package/dist-server/service/order-package-item/order-package-item-types.js +14 -2
  18. package/dist-server/service/order-package-item/order-package-item-types.js.map +1 -1
  19. package/dist-server/service/order-package-item/order-package-item.js +28 -2
  20. package/dist-server/service/order-package-item/order-package-item.js.map +1 -1
  21. package/dist-server/service/order-product/order-product-types.js +18 -18
  22. package/dist-server/service/order-product/order-product-types.js.map +1 -1
  23. package/dist-server/service/order-product/order-product.js +104 -13
  24. package/dist-server/service/order-product/order-product.js.map +1 -1
  25. package/dist-server/service/order-tote-item/order-tote-item-types.js +2 -2
  26. package/dist-server/service/order-tote-item/order-tote-item-types.js.map +1 -1
  27. package/dist-server/service/order-tote-item/order-tote-item.js +13 -1
  28. package/dist-server/service/order-tote-item/order-tote-item.js.map +1 -1
  29. package/dist-server/service/others/other-types.js +4 -0
  30. package/dist-server/service/others/other-types.js.map +1 -1
  31. package/dist-server/service/release-good/release-good-mutation.js +35 -6
  32. package/dist-server/service/release-good/release-good-mutation.js.map +1 -1
  33. package/dist-server/service/release-good/release-good-query.js +24 -19
  34. package/dist-server/service/release-good/release-good-query.js.map +1 -1
  35. package/dist-server/service/release-good/release-good-types.js +1 -1
  36. package/dist-server/service/release-good/release-good-types.js.map +1 -1
  37. package/dist-server/utils/inventory-util.js +12 -8
  38. package/dist-server/utils/inventory-util.js.map +1 -1
  39. package/package.json +7 -7
  40. package/server/service/arrival-notice/arrival-notice-mutation.ts +40 -3
  41. package/server/service/arrival-notice/arrival-notice-query.ts +40 -68
  42. package/server/service/arrival-notice/arrival-notice-types.ts +4 -4
  43. package/server/service/inventory-check-item/inventory-check-item-types.ts +37 -10
  44. package/server/service/inventory-check-item/inventory-check-item.ts +52 -4
  45. package/server/service/order-inventory/order-inventory-query.ts +5 -0
  46. package/server/service/order-inventory/order-inventory-types.ts +12 -12
  47. package/server/service/order-inventory/order-inventory.ts +171 -13
  48. package/server/service/order-package-item/order-package-item-types.ts +12 -3
  49. package/server/service/order-package-item/order-package-item.ts +26 -2
  50. package/server/service/order-product/order-product-types.ts +18 -18
  51. package/server/service/order-product/order-product.ts +96 -12
  52. package/server/service/order-tote-item/order-tote-item-types.ts +3 -3
  53. package/server/service/order-tote-item/order-tote-item.ts +12 -1
  54. package/server/service/others/other-types.ts +3 -0
  55. package/server/service/release-good/release-good-mutation.ts +51 -9
  56. package/server/service/release-good/release-good-query.ts +89 -124
  57. package/server/service/release-good/release-good-types.ts +1 -1
  58. package/server/utils/inventory-util.ts +44 -54
@@ -1,62 +1,20 @@
1
- import {
2
- Arg,
3
- Args,
4
- Ctx,
5
- Directive,
6
- FieldResolver,
7
- Query,
8
- Resolver,
9
- Root
10
- } from 'type-graphql'
11
- import {
12
- EntityManager,
13
- getRepository,
14
- In,
15
- Repository,
16
- SelectQueryBuilder
17
- } from 'typeorm'
1
+ import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'
2
+ import { EntityManager, getRepository, In, Repository, SelectQueryBuilder } from 'typeorm'
18
3
 
19
4
  import { Attachment } from '@things-factory/attachment-base'
20
- import {
21
- checkUserBelongsDomain,
22
- User
23
- } from '@things-factory/auth-base'
24
- import {
25
- Bizplace,
26
- getCompanyBizplace,
27
- getMyBizplace,
28
- getPermittedBizplaceIds
29
- } from '@things-factory/biz-base'
5
+ import { checkUserBelongsDomain, User } from '@things-factory/auth-base'
6
+ import { Bizplace, getCompanyBizplace, getMyBizplace, getPermittedBizplaceIds } from '@things-factory/biz-base'
30
7
  import { logger } from '@things-factory/env'
31
- import {
32
- buildQuery,
33
- Domain,
34
- Filter,
35
- ListParam,
36
- Pagination,
37
- Sorting
38
- } from '@things-factory/shell'
39
- import {
40
- Inventory,
41
- LOCATION_TYPE
42
- } from '@things-factory/warehouse-base'
43
-
44
- import {
45
- ATTACHMENT_TYPE,
46
- ORDER_INVENTORY_STATUS,
47
- ORDER_STATUS,
48
- ORDER_VAS_STATUS
49
- } from '../../constants'
8
+ import { buildQuery, Domain, Filter, ListParam, Pagination, Sorting } from '@things-factory/shell'
9
+ import { Inventory, LOCATION_TYPE } from '@things-factory/warehouse-base'
10
+
11
+ import { ATTACHMENT_TYPE, ORDER_INVENTORY_STATUS, ORDER_STATUS, ORDER_VAS_STATUS } from '../../constants'
50
12
  import { convertExcelDateToISO } from '../../utils/datetime-util'
51
13
  import { OrderInventory } from '../order-inventory/order-inventory'
52
14
  import { OrderPackage } from '../order-package/order-package'
53
15
  import { ShippingOrder } from '../shipping-order/shipping-order'
54
16
  import { ReleaseGood } from './release-good'
55
- import {
56
- NewReleaseGood,
57
- ReleasableInventoryList,
58
- ReleaseGoodList
59
- } from './release-good-types'
17
+ import { NewReleaseGood, ReleasableInventoryList, ReleaseGoodList } from './release-good-types'
60
18
 
61
19
  @Resolver(ReleaseGood)
62
20
  export class ReleaseGoodQuery {
@@ -520,9 +478,9 @@ export class ReleaseGoodQuery {
520
478
  params.filters.splice(fromDateParamIdx, 1)
521
479
 
522
480
  params.filters.push({
523
- name: (typeFilter == 'b2c' || isReleaseDateSearch.value) ? 'releaseDate' : 'createdAt',
481
+ name: typeFilter == 'b2c' || isReleaseDateSearch.value ? 'releaseDate' : 'createdAt',
524
482
  operator: 'gte',
525
- value: (typeFilter == 'b2c' || isReleaseDateSearch.value) ? releaseDateFrom : fromDateVal.toISOString(),
483
+ value: typeFilter == 'b2c' || isReleaseDateSearch.value ? releaseDateFrom : fromDateVal.toISOString(),
526
484
  relation: false
527
485
  })
528
486
  }
@@ -534,15 +492,21 @@ export class ReleaseGoodQuery {
534
492
  params.filters.splice(toDateParamIdx, 1)
535
493
 
536
494
  params.filters.push({
537
- name: (typeFilter == 'b2c' || isReleaseDateSearch.value) ? 'releaseDate' : 'createdAt',
538
- operator: (typeFilter == 'b2c' || isReleaseDateSearch.value) ? 'lte' : 'lt',
495
+ name: typeFilter == 'b2c' || isReleaseDateSearch.value ? 'releaseDate' : 'createdAt',
496
+ operator: typeFilter == 'b2c' || isReleaseDateSearch.value ? 'lte' : 'lt',
539
497
  value:
540
- (typeFilter == 'b2c' || isReleaseDateSearch.value) ? releaseDateTo : new Date(toDateVal.setDate(toDateVal.getDate() + 1)).toISOString(),
498
+ typeFilter == 'b2c' || isReleaseDateSearch.value
499
+ ? releaseDateTo
500
+ : new Date(toDateVal.setDate(toDateVal.getDate() + 1)).toISOString(),
541
501
  relation: false
542
502
  })
543
503
  }
544
504
 
545
- if (!!isReleaseDateSearch) params.filters.splice(params.filters.findIndex(param => param.name == 'isReleaseDateSearch'), 1)
505
+ if (!!isReleaseDateSearch)
506
+ params.filters.splice(
507
+ params.filters.findIndex(param => param.name == 'isReleaseDateSearch'),
508
+ 1
509
+ )
546
510
 
547
511
  if (noOfItemsFilter && noOfItemsFilter.value == 1) {
548
512
  params.filters.find(param => param.name === 'noOfItems').operator = 'eq'
@@ -577,13 +541,9 @@ export class ReleaseGoodQuery {
577
541
 
578
542
  if (hasVas) {
579
543
  if (hasVas.value == true) {
580
- qb.andWhere(
581
- `ov.release_good_id notnull`
582
- )
544
+ qb.andWhere(`ov.release_good_id notnull`)
583
545
  } else if (hasVas.value == false && !vasStatusFilter) {
584
- qb.andWhere(
585
- `ov.release_good_id is null`
586
- )
546
+ qb.andWhere(`ov.release_good_id is null`)
587
547
  }
588
548
  }
589
549
 
@@ -601,7 +561,8 @@ export class ReleaseGoodQuery {
601
561
  release_goods rg2
602
562
  LEFT JOIN order_vass ov2 on ov2.release_good_id = rg2.id
603
563
  WHERE ov2.status = 'PENDING_APPROVE'
604
- )`, { vasStatus: vasStatusFilter.value}
564
+ )`,
565
+ { vasStatus: vasStatusFilter.value }
605
566
  )
606
567
  }
607
568
  }
@@ -718,12 +679,12 @@ export class ReleaseGoodQuery {
718
679
  platformCode: newPlatformCode ? newPlatformCode : item.platformCode,
719
680
  transporter: orderPackages?.length
720
681
  ? [
721
- ...new Set(
722
- orderPackages.map(op => {
723
- return op.transporter
724
- })
725
- )
726
- ].join(', ')
682
+ ...new Set(
683
+ orderPackages.map(op => {
684
+ return op.transporter
685
+ })
686
+ )
687
+ ].join(', ')
727
688
  : null,
728
689
  orderRemark: item?.remark ? true : false
729
690
  }
@@ -789,24 +750,27 @@ export class ReleaseGoodQuery {
789
750
  ${batchId ? `AND LOWER(${INV_ALIAS}.batch_id) LIKE '%${batchId.toLowerCase()}%'` : ''}
790
751
  ${packingType ? `AND LOWER(${INV_ALIAS}.packing_type) LIKE '%${packingType.toLowerCase()}%'` : ''}
791
752
  ${containerNo ? `AND LOWER(${GAN_ALIAS}.container_no) LIKE '%${containerNo.toLowerCase()}%'` : ''}
792
- ${product?.length > 0 && product[0]
793
- ? `AND ${PROD_ALIAS}.id IN (${product.map((id: string) => `'${id}'`).join(', ')})`
794
- : product[0] === null
795
- ? `AND ${PROD_ALIAS}.id isnull`
796
- : ''
797
- }
798
- ${inventory?.length > 0
799
- ? `
800
- AND (${INV_ALIAS}.batch_id, ${PROD_ALIAS}.id) ${filters.find((filter: { name: string; operator: string; value: any }) => filter.name === 'inventory')
801
- .operator
802
- } (
753
+ ${
754
+ product?.length > 0 && product[0]
755
+ ? `AND ${PROD_ALIAS}.id IN (${product.map((id: string) => `'${id}'`).join(', ')})`
756
+ : product[0] === null
757
+ ? `AND ${PROD_ALIAS}.id isnull`
758
+ : ''
759
+ }
760
+ ${
761
+ inventory?.length > 0
762
+ ? `
763
+ AND (${INV_ALIAS}.batch_id, ${PROD_ALIAS}.id) ${
764
+ filters.find((filter: { name: string; operator: string; value: any }) => filter.name === 'inventory')
765
+ .operator
766
+ } (
803
767
  ${inventory
804
- .map((inv: { batchId: string; productId: string }) => `('${inv.batchId}', '${inv.productId}')`)
805
- .join(', ')}
768
+ .map((inv: { batchId: string; productId: string }) => `('${inv.batchId}', '${inv.productId}')`)
769
+ .join(', ')}
806
770
  )
807
771
  `
808
- : ''
809
- }
772
+ : ''
773
+ }
810
774
  `
811
775
 
812
776
  // ${product?.length > 0 ? `AND ${PROD_ALIAS}.id IN (${product.map((id: string) => id ? `'${id}'` : null).join(', ')})` : ''}
@@ -996,7 +960,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
996
960
  packing_type VARCHAR(50),
997
961
  packing_size FLOAT,
998
962
  uom VARCHAR(10),
999
- release_qty INT
963
+ release_qty NUMERIC(15,3)
1000
964
  );
1001
965
  `
1002
966
  )
@@ -1053,9 +1017,11 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1053
1017
  AND oi.uom = i.uom
1054
1018
  AND oi.domain_id = $1
1055
1019
  AND oi.bizplace_id = $2
1056
- ), 0) as "remain_uom_value"
1020
+ ), 0) as "remain_uom_value",
1021
+ p.is_inventory_decimal
1057
1022
  FROM inventories i
1058
1023
  LEFT JOIN locations l ON i.location_id = l.id
1024
+ LEFT JOIN products p ON i.product_id = p.id
1059
1025
  INNER JOIN (
1060
1026
  SELECT rrg.product_id, rrg.product_detail_id, rrg.sku, rrg.product_info, rrg.packing_type, rrg.packing_size, rrg.uom
1061
1027
  FROM raw_release_goods rrg
@@ -1071,7 +1037,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1071
1037
  AND i.obsolete = false
1072
1038
  AND i.transfer_qty <= 0
1073
1039
  AND i.transfer_uom_value <= 0
1074
- GROUP BY i.product_id, foo.product_detail_id, foo.sku, foo.product_info, i.packing_type, i.packing_size, i.uom
1040
+ 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
1075
1041
  ${useDetailedQuery ? ', i.batch_id, i.carton_id, i.expiration_date' : ''}
1076
1042
  ORDER BY foo.sku, remain_qty DESC
1077
1043
  ) SELECT * FROM inv WHERE remain_qty > 0
@@ -1082,7 +1048,7 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1082
1048
  await tx.query(`DROP TABLE raw_release_goods`)
1083
1049
 
1084
1050
  availableItems = availableItems.map(item => {
1085
- return {
1051
+ const mappedItem = {
1086
1052
  productId: item.product_id,
1087
1053
  productDetailId: item.product_detail_id,
1088
1054
  productInfo: item.product_info,
@@ -1094,8 +1060,10 @@ export async function bulkReleaseGoodsAvailableItemsFunction(
1094
1060
  remainUomValue: item.remain_uom_value,
1095
1061
  batchId: item.batch_id ? item.batch_id : null,
1096
1062
  cartonId: item.carton_id ? item.carton_id : null,
1097
- expirationDate: item.expiration_date ? _getStdDateStr(new Date(item.expiration_date)) : null
1063
+ expirationDate: item.expiration_date ? _getStdDateStr(new Date(item.expiration_date)) : null,
1064
+ isInventoryDecimal: item.is_inventory_decimal === true
1098
1065
  }
1066
+ return mappedItem
1099
1067
  })
1100
1068
 
1101
1069
  return _extractData(rawReleaseGoods, availableItems)
@@ -1146,15 +1114,10 @@ function _extractData(rawData, validatedData) {
1146
1114
  // if sku is matched, assign qty and product id
1147
1115
  if (idx >= 0) {
1148
1116
  // assign qty to rawData as much as possible
1149
- releaseUomValue =
1150
- (Math.round((data[idx]?.remainUomValue / data[idx]?.remainQty) * 100) / 100) * raw.releaseQty
1117
+ releaseUomValue = (Math.round((data[idx]?.remainUomValue / data[idx]?.remainQty) * 1000) / 1000) * raw.releaseQty
1151
1118
 
1152
1119
  raw.assignedQty =
1153
- data[idx].remainQty >= raw.releaseQty
1154
- ? raw.releaseQty > 0
1155
- ? raw.releaseQty
1156
- : 0
1157
- : data[idx].remainQty
1120
+ data[idx].remainQty >= raw.releaseQty ? (raw.releaseQty > 0 ? raw.releaseQty : 0) : data[idx].remainQty
1158
1121
 
1159
1122
  raw.assignedUomValue =
1160
1123
  data[idx].remainUomValue >= releaseUomValue
@@ -1173,67 +1136,69 @@ function _extractData(rawData, validatedData) {
1173
1136
  raw.packingType = data[idx].packingType
1174
1137
  raw.packingSize = data[idx].packingSize
1175
1138
  raw.uom = data[idx].uom
1139
+ raw.isInventoryDecimal = data[idx].isInventoryDecimal === true
1176
1140
  } else {
1177
1141
  raw.assignedQty = 0
1178
1142
  raw.assignedUomValue = 0
1179
1143
  raw.productId = null
1180
1144
  }
1181
1145
 
1182
-
1183
1146
  const dateRegex = /^\d{4}-\d{2}-\d{2}$/
1184
1147
 
1185
1148
  return {
1186
1149
  ...raw,
1187
1150
  releaseUomValue,
1188
1151
  errorMsg: (() => {
1189
- const errors = [];
1152
+ const errors = []
1190
1153
 
1191
- if (errMsg){
1154
+ if (errMsg) {
1192
1155
  errors.push(errMsg)
1193
1156
  }
1194
1157
  if (!raw.productId || !raw.productDetailId) {
1195
- errors.push('inventory or product not found');
1158
+ errors.push('inventory or product not found')
1159
+ }
1160
+ if (raw.releaseQty <= 0) {
1161
+ errors.push('invalid release qty')
1196
1162
  }
1197
- if (raw.releaseQty <= 0 || raw.releaseQty % 1 !== 0) {
1198
- errors.push('invalid release qty');
1163
+ if (raw.releaseQty % 1 !== 0 && raw.isInventoryDecimal !== true) {
1164
+ errors.push('decimal quantities are not allowed for this product')
1199
1165
  }
1200
1166
  if (raw.assignedQty < raw.releaseQty) {
1201
- errors.push('insufficient stock');
1167
+ errors.push('insufficient stock')
1202
1168
  }
1203
- if(!dateRegex.test(raw.releaseDate)){
1204
- errors.push('invalid release date format. please use dd/mm/yyyy')
1169
+ if (!dateRegex.test(raw.releaseDate)) {
1170
+ errors.push('invalid release date format. please use yyyy-mm-dd')
1205
1171
  }
1206
1172
  if (raw.releaseDate === '') {
1207
- errors.push('release date is empty');
1173
+ errors.push('release date is empty')
1208
1174
  }
1209
1175
  if (raw.releaseDate < _getStdDateStr(new Date())) {
1210
- errors.push('backdate is not allowed');
1176
+ errors.push('backdate is not allowed')
1211
1177
  }
1212
1178
  if (!raw.refNo || raw.refNo === '') {
1213
- errors.push('ref no is empty');
1179
+ errors.push('ref no is empty')
1214
1180
  }
1215
- if (raw?.type === 'b2c') {
1216
- if (!raw.attentionTo) errors.push('attention to is empty');
1217
- if (!raw.postalCode) errors.push('postal code is empty');
1218
- if (!raw.country) errors.push('country is empty');
1219
- if (!raw.deliveryAddress1) errors.push('delivery address 1 is empty');
1220
- if (!raw.city) errors.push('city is empty');
1221
- if (!raw.phone1) errors.push('contact is empty');
1222
- if (!raw.state) errors.push('state is empty');
1181
+ if (raw?.type === 'b2c') {
1182
+ if (!raw.attentionTo) errors.push('attention to is empty')
1183
+ if (!raw.postalCode) errors.push('postal code is empty')
1184
+ if (!raw.country) errors.push('country is empty')
1185
+ if (!raw.deliveryAddress1) errors.push('delivery address 1 is empty')
1186
+ if (!raw.city) errors.push('city is empty')
1187
+ if (!raw.phone1) errors.push('contact is empty')
1188
+ if (!raw.state) errors.push('state is empty')
1223
1189
  if ((raw.codOption && !raw.paidAmount) || raw.paidAmount < 0 || raw.paidAmount == null) {
1224
- errors.push('invalid paid amount');
1190
+ errors.push('invalid paid amount')
1225
1191
  }
1226
- if(raw?.expirationDate != null && !dateRegex.test(raw?.expirationDate)){
1192
+ if (raw?.expirationDate != null && !dateRegex.test(raw?.expirationDate)) {
1227
1193
  errors.push('invalid expiration date format. please use dd/mm/yyyy')
1228
1194
  }
1229
1195
  if (raw.airwayBill && raw.lmdOption === true) {
1230
- errors.push('kindly remove AWB as LMD is marked as true');
1196
+ errors.push('kindly remove AWB as LMD is marked as true')
1231
1197
  }
1232
1198
  }
1233
- return errors.length > 0 ? errors.join(', ') : ''// Combine all errors into a single string
1234
- })(),
1235
- };
1236
-
1199
+ return errors.length > 0 ? errors.join(', ') : '' // Combine all errors into a single string
1200
+ })()
1201
+ }
1237
1202
  })
1238
1203
  }
1239
1204
 
@@ -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 })
@@ -1,29 +1,10 @@
1
- import {
2
- EntityManager,
3
- Equal,
4
- getRepository,
5
- In,
6
- Not,
7
- Raw,
8
- Repository,
9
- SelectQueryBuilder
10
- } from 'typeorm'
1
+ import { EntityManager, Equal, getRepository, In, Not, Raw, Repository, SelectQueryBuilder } from 'typeorm'
11
2
 
12
3
  import { User } from '@things-factory/auth-base'
13
4
  import { Bizplace } from '@things-factory/biz-base'
14
- import {
15
- Product,
16
- ProductBundle,
17
- ProductDetail
18
- } from '@things-factory/product-base'
19
- import {
20
- PartnerSetting,
21
- Setting
22
- } from '@things-factory/setting-base'
23
- import {
24
- Domain,
25
- ListParam
26
- } from '@things-factory/shell'
5
+ import { Product, ProductBundle, ProductDetail } from '@things-factory/product-base'
6
+ import { PartnerSetting, Setting } from '@things-factory/setting-base'
7
+ import { Domain, ListParam } from '@things-factory/shell'
27
8
  import {
28
9
  generateInventoryHistory,
29
10
  Inventory,
@@ -303,6 +284,7 @@ export const InventoryUtil = {
303
284
  COALESCE(p.sku, '') AS "productSKU",
304
285
  COALESCE(p.brand, '') AS "productBrand",
305
286
  p.id AS "productId",
287
+ p.is_inventory_decimal AS "isInventoryDecimal",
306
288
  i.product_detail_id AS "productDetailId",
307
289
  SUM(COALESCE(i.qty, 0)) - SUM(COALESCE(i.locked_qty, 0)) - MAX(COALESCE(bp.bundle_product_release_qty, 0)) - SUM(COALESCE(pds.unassigned_qty, 0)) AS "remainQty",
308
290
  SUM(COALESCE(i.uom_value, 0)) - SUM(COALESCE(i.locked_uom_value, 0)) - MAX(COALESCE(bp.bundle_product_release_uom_value, 0)) - SUM(COALESCE(pds.unassigned_uom_value, 0)) AS "remainUomValue",
@@ -330,8 +312,9 @@ export const InventoryUtil = {
330
312
  AND i.transfer_uom_value <= 0
331
313
  AND i.lock_inventory is not true
332
314
  AND CASE WHEN i.expiration_date IS NOT NULL AND p.min_outbound_shelf_life IS NOT NULL THEN CURRENT_DATE < i.expiration_date - p.min_outbound_shelf_life ELSE true END
333
- ${cycleCountFilter ?
334
- `AND i.id NOT IN (
315
+ ${
316
+ cycleCountFilter
317
+ ? `AND i.id NOT IN (
335
318
  SELECT DISTINCT(ici.inventory_id) FROM worksheets w
336
319
  INNER JOIN worksheet_details wd ON wd.worksheet_id = w.id
337
320
  INNER JOIN inventory_check_items ici ON wd.target_inventory_check_item_id = ici.id
@@ -339,8 +322,9 @@ export const InventoryUtil = {
339
322
  AND w.status != 'DONE'
340
323
  AND w.bizplace_id IN (${bizplaceIds})
341
324
  AND w.domain_id = '${domain.id}'
342
- )` :
343
- `AND true`}
325
+ )`
326
+ : `AND true`
327
+ }
344
328
  ${productWhereClause}
345
329
  GROUP BY
346
330
  i.product_detail_id,
@@ -361,6 +345,7 @@ export const InventoryUtil = {
361
345
  pb.sku AS "productSKU",
362
346
  'brand' AS "productBrand",
363
347
  id AS "productId",
348
+ false AS "isInventoryDecimal",
364
349
  pbs.product_detail_id AS "productDetailId",
365
350
  MIN(FLOOR(pbs."availableQty")) AS "remainQty",
366
351
  MIN(FLOOR(pbs."availableUomValue")) AS "remainUomValue",
@@ -430,7 +415,7 @@ export const InventoryUtil = {
430
415
  } OFFSET $1 LIMIT $2`,
431
416
  [(params.pagination.page - 1) * params.pagination.limit, params.pagination.limit]
432
417
  )
433
- }
418
+ }
434
419
 
435
420
  await trxMgr.query(`drop table temp_inventory_product_group`)
436
421
 
@@ -440,7 +425,12 @@ export const InventoryUtil = {
440
425
  }
441
426
  },
442
427
 
443
- async bizplaceInventoryProductGroupImport(bizplaces: Bizplace[], params: ListParam, context: any, trxMgr: EntityManager) {
428
+ async bizplaceInventoryProductGroupImport(
429
+ bizplaces: Bizplace[],
430
+ params: ListParam,
431
+ context: any,
432
+ trxMgr: EntityManager
433
+ ) {
444
434
  try {
445
435
  let filters = params.filters
446
436
  const { domain }: { domain: Domain } = context.state
@@ -463,6 +453,7 @@ export const InventoryUtil = {
463
453
  COALESCE(p.sku, '') AS "productSKU",
464
454
  COALESCE(p.brand, '') AS "productBrand",
465
455
  p.id AS "productId",
456
+ p.is_inventory_decimal AS "isInventoryDecimal",
466
457
  i.product_detail_id AS "productDetailId",
467
458
  p.picking_strategy AS "pickingStrategy",
468
459
  i.created_at AS "createdAt",
@@ -527,6 +518,7 @@ export const InventoryUtil = {
527
518
  'brand' AS "productBrand",
528
519
  id AS "productId",
529
520
  pbs.product_detail_id AS "productDetailId",
521
+ false AS "isInventoryDecimal",
530
522
  NULL AS "pickingStrategy",
531
523
  NULL AS "createdAt",
532
524
  NULL AS "expirationDate",
@@ -570,36 +562,37 @@ export const InventoryUtil = {
570
562
  })
571
563
 
572
564
  const getLocationSortingClause = (inventoryAssignmentSetting: any) => {
573
- let locationSortingRules: Array<{ name: string; desc: boolean }> = []
565
+ let locationSortingRules: Array<{ name: string; desc: boolean }> = []
574
566
 
575
- if (inventoryAssignmentSetting) {
576
- try {
577
- let locationSetting = JSON.parse(inventoryAssignmentSetting.value)
578
- for (const key in locationSetting) {
579
- locationSortingRules.push({ name: key, desc: locationSetting[key] !== 'ASC' })
567
+ if (inventoryAssignmentSetting) {
568
+ try {
569
+ let locationSetting = JSON.parse(inventoryAssignmentSetting.value)
570
+ for (const key in locationSetting) {
571
+ locationSortingRules.push({ name: key, desc: locationSetting[key] !== 'ASC' })
572
+ }
573
+ } catch (error) {
574
+ console.error('Invalid JSON in inventoryAssignmentSetting:', error)
580
575
  }
581
- } catch (error) {
582
- console.error("Invalid JSON in inventoryAssignmentSetting:", error)
583
576
  }
584
- }
585
577
 
586
- if (locationSortingRules.length) {
587
- return locationSortingRules
588
- .map(rule => `
578
+ if (locationSortingRules.length) {
579
+ return locationSortingRules
580
+ .map(
581
+ rule => `
589
582
  CASE
590
583
  WHEN "pickingStrategy" = 'LOCATION' THEN "${rule.name}"
591
584
  END ${rule.desc ? 'DESC' : 'ASC'}
592
- `)
593
- .join(',\n')
594
- }
585
+ `
586
+ )
587
+ .join(',\n')
588
+ }
595
589
 
596
- return `
590
+ return `
597
591
  CASE
598
592
  WHEN "pickingStrategy" = 'LOCATION' THEN "locationName"
599
593
  END ASC
600
594
  `
601
- }
602
-
595
+ }
603
596
 
604
597
  await trxMgr.query(queryStrings, [domain.id])
605
598
 
@@ -608,7 +601,6 @@ export const InventoryUtil = {
608
601
  let items: any[] = []
609
602
 
610
603
  if (!params?.pagination) {
611
-
612
604
  const orderByClause = `
613
605
  ORDER BY
614
606
  ${getLocationSortingClause(inventoryAssignmentSetting)},
@@ -629,9 +621,7 @@ export const InventoryUtil = {
629
621
  ELSE NULL
630
622
  END ASC
631
623
  `
632
- items = await trxMgr.query(
633
- `select * from temp_inventory_product_group ${orderByClause}`
634
- )
624
+ items = await trxMgr.query(`select * from temp_inventory_product_group ${orderByClause}`)
635
625
  }
636
626
 
637
627
  await trxMgr.query(`drop table temp_inventory_product_group`)
@@ -807,7 +797,7 @@ export const InventoryUtil = {
807
797
  )
808
798
 
809
799
  resultQb.forEach(itm => {
810
- if (itm.releaseQty > itm.availableQty) {
800
+ if (parseFloat(itm.releaseQty) > parseFloat(itm.availableQty)) {
811
801
  throw new ValidationError({
812
802
  ...ValidationError.ERROR_CODES.RELEASE_QTY_OVER_LIMIT,
813
803
  detail: { data: JSON.stringify(resultQb) }
@@ -1336,7 +1326,7 @@ export function _composeTargetInventories(
1336
1326
  let orderInventory: OrderInventory = new OrderInventory()
1337
1327
 
1338
1328
  if (inventory.remainQty > leftReleaseQty) {
1339
- const uomValuePerQty: number = Math.round((inventory.remainUomValue / inventory.remainQty) * 100) / 100
1329
+ const uomValuePerQty: number = Math.round((inventory.remainUomValue / inventory.remainQty) * 1000) / 1000
1340
1330
 
1341
1331
  compReleaseQty += leftReleaseQty
1342
1332
  compReleaseUomValue += leftReleaseUomValue
@@ -1344,7 +1334,7 @@ export function _composeTargetInventories(
1344
1334
  orderInventory = {
1345
1335
  ...orderInventory,
1346
1336
  releaseQty: leftReleaseQty,
1347
- releaseUomValue: Math.round(leftReleaseQty * uomValuePerQty * 100) / 100
1337
+ releaseUomValue: Math.round(leftReleaseQty * uomValuePerQty * 1000) / 1000
1348
1338
  }
1349
1339
  } else {
1350
1340
  compReleaseQty += inventory.remainQty