@things-factory/operato-hub 4.3.385 → 4.3.387

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 (26) hide show
  1. package/dist-server/graphql/resolvers/reports/index.js +2 -1
  2. package/dist-server/graphql/resolvers/reports/index.js.map +1 -1
  3. package/dist-server/graphql/resolvers/reports/shortage-report.js +115 -0
  4. package/dist-server/graphql/resolvers/reports/shortage-report.js.map +1 -0
  5. package/dist-server/graphql/types/reports/index.js +11 -1
  6. package/dist-server/graphql/types/reports/index.js.map +1 -1
  7. package/dist-server/graphql/types/reports/shortage-report-list.js +14 -0
  8. package/dist-server/graphql/types/reports/shortage-report-list.js.map +1 -0
  9. package/dist-server/graphql/types/reports/shortage-report-type.js +25 -0
  10. package/dist-server/graphql/types/reports/shortage-report-type.js.map +1 -0
  11. package/dist-server/routers/api/restful-apis/v1/utils/params.js +1 -0
  12. package/dist-server/routers/api/restful-apis/v1/utils/params.js.map +1 -1
  13. package/dist-server/routers/api/restful-apis/v1/warehouse/add-release-order.js +214 -198
  14. package/dist-server/routers/api/restful-apis/v1/warehouse/add-release-order.js.map +1 -1
  15. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-details.js +14 -2
  16. package/dist-server/routers/api/restful-apis/v1/warehouse/get-release-order-details.js.map +1 -1
  17. package/openapi/v1/outbound.yaml +16 -4
  18. package/package.json +4 -4
  19. package/server/graphql/resolvers/reports/index.ts +3 -1
  20. package/server/graphql/resolvers/reports/shortage-report.ts +132 -0
  21. package/server/graphql/types/reports/index.ts +11 -1
  22. package/server/graphql/types/reports/shortage-report-list.ts +8 -0
  23. package/server/graphql/types/reports/shortage-report-type.ts +19 -0
  24. package/server/routers/api/restful-apis/v1/utils/params.ts +1 -0
  25. package/server/routers/api/restful-apis/v1/warehouse/add-release-order.ts +253 -244
  26. package/server/routers/api/restful-apis/v1/warehouse/get-release-order-details.ts +13 -2
@@ -159,7 +159,7 @@ router.post(
159
159
  await checkExistingOrder(releaseGood, customerBizplace, bodyReq?.checkDuplicationValidation, context, tx)
160
160
 
161
161
  // massage data
162
- massagedData = await massageOrderItems(releaseGood, bodyReq.orderInventories, context)
162
+ massagedData = await massageOrderItems(releaseGood, bodyReq.orderInventories, context) //double check this function
163
163
 
164
164
  // validation
165
165
  await Promise.all(
@@ -202,6 +202,7 @@ router.post(
202
202
  console.log()
203
203
  })
204
204
  )
205
+ // use product id
205
206
 
206
207
  // assignment
207
208
  // console.time('assign')
@@ -612,7 +613,7 @@ async function massageOrderItems(
612
613
  //combine any repeated skus
613
614
  inputOrderProducts = inputOrderProducts.reduce((acc, itm, idx) => {
614
615
  let { sku, refCode } = itm.product
615
- let { packingType, packingSize, batchId, releaseQty, sellingPrice, paidAmount } = itm
616
+ let { packingType, packingSize, batchId, releaseQty, sellingPrice, paidAmount, uom } = itm
616
617
 
617
618
  if (!sku && !refCode) {
618
619
  throw new ApiError('E01', 'sku or refCode not found')
@@ -628,7 +629,8 @@ async function massageOrderItems(
628
629
  itm?.sku == sku?.trim() &&
629
630
  itm?.refCode == refCode?.trim() &&
630
631
  itm?.packingType == packingType?.trim() &&
631
- itm?.packingSize == packingSize
632
+ itm?.packingSize == packingSize &&
633
+ itm?.uom == uom
632
634
  )
633
635
 
634
636
  if (existingIndex >= 0 && releaseQty > 0) {
@@ -641,7 +643,8 @@ async function massageOrderItems(
641
643
  packingSize: packingSize,
642
644
  releaseQty: releaseQty,
643
645
  sellingPrice: sellingPrice,
644
- paidAmount: paidAmount
646
+ paidAmount: paidAmount,
647
+ uom: uom
645
648
  })
646
649
  }
647
650
 
@@ -652,6 +655,7 @@ async function massageOrderItems(
652
655
  await Promise.all(
653
656
  inputOrderProducts.map(async inputOrderItem => {
654
657
  const sku: string = inputOrderItem.sku
658
+ const uom: string = inputOrderItem?.uom
655
659
  const refCode: string = inputOrderItem.refCode
656
660
  const packingType: string = inputOrderItem.packingType
657
661
  const packingSize: string = inputOrderItem.packingSize
@@ -748,26 +752,26 @@ async function massageOrderItems(
748
752
  const foundProductBundle: ProductBundle = await qb.getOne()
749
753
 
750
754
  if (foundProductBundle) {
751
- let orderProduct: OrderProduct
752
-
753
- // to be further enhanced
754
- // let orderProduct = {
755
- // productBundle: foundProductBundle,
756
- // refCode,
757
- // packingType: foundProductBundle.packingType,
758
- // packingSize: packingSize || 1,
759
- // uom: inputOrderItem?.uom,
760
- // releaseQty: inputOrderItem.releaseQty,
761
- // releaseUomValue: inputOrderItem.releaseQty,
762
- // packQty: 0,
763
- // actualPackQty: 0,
764
- // palletQty: 0,
765
- // actualPalletQty: 0,
766
- // orderInventories: [],
767
- // type: 'RELEASE_OF_GOODS',
768
- // status: ORDER_PRODUCT_STATUS.ASSIGNED,
769
- // batchId: '-'
770
- // }
755
+ //let orderProduct: OrderProduct
756
+
757
+ //to be further enhanced
758
+ let orderProduct = {
759
+ productBundle: foundProductBundle,
760
+ refCode,
761
+ packingType: foundProductBundle.packingType,
762
+ packingSize: packingSize || 1,
763
+ uom: inputOrderItem?.uom,
764
+ releaseQty: inputOrderItem.releaseQty,
765
+ releaseUomValue: inputOrderItem.releaseQty,
766
+ packQty: 0,
767
+ actualPackQty: 0,
768
+ palletQty: 0,
769
+ actualPalletQty: 0,
770
+ orderInventories: [],
771
+ type: 'RELEASE_OF_GOODS',
772
+ status: ORDER_PRODUCT_STATUS.ASSIGNED,
773
+ batchId: '-'
774
+ }
771
775
 
772
776
  const bundleProductSettings: any[] = foundProductBundle.productBundleSettings
773
777
  bundleProductSettings.map(bundleProductSetting => {
@@ -793,22 +797,21 @@ async function massageOrderItems(
793
797
  status: ORDER_INVENTORY_STATUS.PENDING_WORKSHEET
794
798
  }
795
799
 
796
- orderProduct = Object.assign(new OrderProduct(), newOrderInventory)
800
+ // orderProduct = Object.assign(new OrderProduct(), newOrderInventory)
797
801
 
798
- orderProduct = {
799
- ...orderProduct,
800
- refCode,
801
- packingType: foundProductBundle.packingType,
802
- packingSize: packingSize || 1,
803
- orderInventories: [],
804
- status: ORDER_PRODUCT_STATUS.ASSIGNED,
805
- batchId: '-'
806
- }
802
+ // orderProduct = {
803
+ // ...orderProduct,
804
+ // refCode,
805
+ // packingType: foundProductBundle.packingType,
806
+ // packingSize: packingSize || 1,
807
+ // orderInventories: [],
808
+ // status: ORDER_PRODUCT_STATUS.ASSIGNED,
809
+ // batchId: '-'
810
+ // }
807
811
 
808
812
  orderProduct.orderInventories.push(newOrderInventory)
809
-
810
- orderProducts.push(orderProduct)
811
813
  })
814
+ orderProducts.push(orderProduct)
812
815
  } else {
813
816
  if (sku && refCode) {
814
817
  throw new ApiError('E04', t(`error.sku ${sku} and refCode ${refCode} not exist in product / bundle master`))
@@ -892,228 +895,234 @@ async function assignToInventory(
892
895
 
893
896
  let assignedOrderInventories = []
894
897
 
895
- const orderInventory = orderProduct.orderInventories[0]
898
+ const orderInventory = orderProduct.orderInventories
899
+ let productBundle = orderProduct?.productBundle
900
+
896
901
  let sortings: any = []
897
902
 
898
- if (worksheetPickingAssignment?.value !== 'true') {
899
- switch (orderInventory.product.pickingStrategy) {
900
- case 'LIFO':
901
- sortings.push({ name: 'iv.created_at', desc: true })
902
- if (pickingProductSetting?.value) {
903
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
904
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
903
+ for(let oiIdx = 0 ; oiIdx < orderInventory.length ; oiIdx++){
904
+ if (worksheetPickingAssignment?.value !== 'true') {
905
+ switch (orderInventory[oiIdx].product.pickingStrategy) {
906
+ case 'LIFO':
907
+ sortings.push({ name: 'iv.created_at', desc: true })
908
+ if (pickingProductSetting?.value) {
909
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
910
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
911
+ }
912
+ } else {
913
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
905
914
  }
906
- } else {
907
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
908
- }
909
-
910
- break
911
- case 'FEFO':
912
- sortings.push({ name: 'iv.expiration_date', desc: false }, { name: 'iv.created_at', desc: false })
913
- if (pickingProductSetting?.value) {
914
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
915
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
915
+
916
+ break
917
+ case 'FEFO':
918
+ sortings.push({ name: 'iv.expiration_date', desc: false }, { name: 'iv.created_at', desc: false })
919
+ if (pickingProductSetting?.value) {
920
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
921
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
922
+ }
923
+ } else {
924
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
916
925
  }
917
- } else {
918
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
919
- }
920
-
921
- break
922
- case 'FMFO':
923
- sortings.push({ name: 'iv.manufacture_date', desc: false }, { name: 'iv.created_at', desc: false })
924
- if (pickingProductSetting?.value) {
925
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
926
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
926
+
927
+ break
928
+ case 'FMFO':
929
+ sortings.push({ name: 'iv.manufacture_date', desc: false }, { name: 'iv.created_at', desc: false })
930
+ if (pickingProductSetting?.value) {
931
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
932
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
933
+ }
934
+ } else {
935
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
927
936
  }
928
- } else {
929
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
930
- }
931
-
932
- break
933
- case 'LOCATION':
934
- if (pickingProductSetting?.value) {
935
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
936
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
937
+
938
+ break
939
+ case 'LOCATION':
940
+ if (pickingProductSetting?.value) {
941
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
942
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
943
+ }
944
+ } else {
945
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
937
946
  }
938
- } else {
939
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false })
940
- }
941
-
942
- break
943
- //Every other case includes 'FIFO' will be applicable for this case
944
- default:
945
- sortings.push({ name: 'iv.created_at', desc: false })
946
- if (pickingProductSetting?.value) {
947
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
948
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
947
+
948
+ break
949
+ //Every other case includes 'FIFO' will be applicable for this case
950
+ default:
951
+ sortings.push({ name: 'iv.created_at', desc: false })
952
+ if (pickingProductSetting?.value) {
953
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
954
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false })
955
+ }
956
+ } else {
957
+ sortings.push({ name: 'loc.name', desc: false })
958
+ sortings.push({ name: 'iv.pallet_id', desc: false })
949
959
  }
950
- } else {
951
- sortings.push({ name: 'loc.name', desc: false })
952
- sortings.push({ name: 'iv.pallet_id', desc: false })
953
- }
954
- break
955
- }
956
-
957
- let queryFilters = []
958
-
959
- let queryStrings = queryFilters.reduce(
960
- (acc, itm, idx, arr) => {
961
- acc.values.push(itm.filters)
962
-
963
- switch (itm?.operator) {
964
- case 'notin':
965
- case 'in':
966
- acc.query.push(
967
- `${itm.query} ${itm.operator == 'notin' ? 'NOT IN' : 'IN'} (${itm.filtes
968
- .map((itm, idx) => {
969
- return `$${acc.values.length + 1}`
970
- })
971
- .join(',')})`
972
- )
973
- break
974
-
975
- default:
976
- acc.query.push(`${itm.query} ${itm?.operator ? itm.operator : '='} $${acc.values.length + 1}`)
977
- break
978
- }
979
- acc.query.push(`${itm.query} ${itm?.operator ? itm.operator : '='} $${acc.values.length + 1}`)
980
- },
981
- {
982
- query: [],
983
- values: []
960
+ break
984
961
  }
985
- )
986
-
987
- let sortQuery = sortings
988
- .map(itm => {
989
- return `${itm.name} ${itm.desc ? 'DESC' : 'ASC'}`
990
- })
991
- .join(`,`)
992
-
993
- let updatedInventories = await tx.getRepository(Inventory).query(
994
- `
995
- update inventories tgt set locked_qty = coalesce(locked_qty,0) + src.reserve_qty,
996
- locked_uom_value = coalesce(locked_uom_value,0) + src.reserve_uom_value,
997
- updated_at = NOW(),
998
- updater_id = $1
999
- from (
1000
- select "id", "pallet_id","carton_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year",
1001
- "reserve_qty", (("uom_value"/"qty") * "reserve_qty") as "reserve_uom_value" from (
1002
- select "sort_seq", "id", "pallet_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year", "carton_id", "uom_value", "locked_uom_value", "qty", "locked_qty", "created_at",
1003
- "release_qty", "release_uom_value", lock_amount,
1004
- case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end as "reserve_qty"
1005
- from (
1006
- select *,
1007
- (
1008
- case when (qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0)) < 0 then 0
1009
- else qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0) end
1010
- ) as available_qty,
1011
- sum(qty - locked_qty - release_qty - unassigned_qty) over (order by sort_seq asc rows between unbounded preceding and current row) as lock_amount
962
+
963
+ let queryFilters = []
964
+
965
+ let queryStrings = queryFilters.reduce(
966
+ (acc, itm, idx, arr) => {
967
+ acc.values.push(itm.filters)
968
+
969
+ switch (itm?.operator) {
970
+ case 'notin':
971
+ case 'in':
972
+ acc.query.push(
973
+ `${itm.query} ${itm.operator == 'notin' ? 'NOT IN' : 'IN'} (${itm.filtes
974
+ .map((itm, idx) => {
975
+ return `$${acc.values.length + 1}`
976
+ })
977
+ .join(',')})`
978
+ )
979
+ break
980
+
981
+ default:
982
+ acc.query.push(`${itm.query} ${itm?.operator ? itm.operator : '='} $${acc.values.length + 1}`)
983
+ break
984
+ }
985
+ acc.query.push(`${itm.query} ${itm?.operator ? itm.operator : '='} $${acc.values.length + 1}`)
986
+ },
987
+ {
988
+ query: [],
989
+ values: []
990
+ }
991
+ )
992
+
993
+ let sortQuery = sortings
994
+ .map(itm => {
995
+ return `${itm.name} ${itm.desc ? 'DESC' : 'ASC'}`
996
+ })
997
+ .join(`,`)
998
+
999
+ let updatedInventories = await tx.getRepository(Inventory).query(
1000
+ `
1001
+ update inventories tgt set locked_qty = coalesce(locked_qty,0) + src.reserve_qty,
1002
+ locked_uom_value = coalesce(locked_uom_value,0) + src.reserve_uom_value,
1003
+ updated_at = NOW(),
1004
+ updater_id = $1
1005
+ from (
1006
+ select "id", "pallet_id","carton_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year",
1007
+ "reserve_qty", (("uom_value"/"qty") * "reserve_qty") as "reserve_uom_value" from (
1008
+ select "sort_seq", "id", "pallet_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year", "carton_id", "uom_value", "locked_uom_value", "qty", "locked_qty", "created_at",
1009
+ "release_qty", "release_uom_value", lock_amount,
1010
+ case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end as "reserve_qty"
1012
1011
  from (
1013
- SELECT 0 as sort_seq, null as id, null as pallet_id, null as batch_id, null as batch_id_ref,
1014
- null as unit, '${orderInventory.uom}' as uom, '${orderInventory.packingType}' as packing_type, '${
1015
- orderInventory.packingSize
1016
- }' as packing_size,
1017
- null as manufacture_year, null as carton_id, 0 as uom_value, 0 as locked_uom_value, 0 as qty, 0 as locked_qty, 0 as unassigned_uom_value, 0 as unassigned_qty, null as created_at,
1018
- '${orderInventory.releaseQty}' as release_qty, '${orderInventory.releaseUomValue}' as release_uom_value
1019
- UNION
1012
+ select *,
1020
1013
  (
1021
- SELECT ROW_NUMBER() OVER(PARTITION BY iv.domain_id ORDER BY wiar.rank ${
1022
- sortQuery ? ', ' + sortQuery : ''
1023
- }) as sort_seq,
1024
- iv.id, iv.pallet_id, iv.batch_id, iv.batch_id_ref,
1025
- iv.unit, iv.uom, iv.packing_type, iv.packing_size,
1026
- iv.manufacture_year, iv.carton_id, iv.uom_value,
1027
- coalesce(iv.locked_uom_value,0) as locked_uom_value, iv.qty, greatest(coalesce(iv.locked_qty,0),0) as locked_qty, coalesce(pds.unassigned_uom_value,0) as unassigned_uom_value, greatest(coalesce(pds.unassigned_qty,0),0) as unassigned_qty,
1028
- iv.created_at, 0 as release_qty, 0 as release_uom_value
1029
- FROM "inventories" "iv"
1030
- LEFT JOIN "product_detail_stocks" "pds" ON "pds"."product_detail_id" = "iv"."product_detail_id"
1031
- INNER JOIN "locations" "loc" ON "loc"."id"="iv"."location_id"
1032
- INNER JOIN "products" "p" ON "p"."id"="iv"."product_id"
1033
- INNER JOIN "warehouse_inventory_assignment_rankings" "wiar" ON "wiar"."location_type"="loc"."type"
1034
- WHERE case when coalesce("iv"."locked_qty",0) < 0 then 0 else ("iv"."qty" - coalesce("iv"."locked_qty",0)) end > 0 AND
1035
- "iv"."domain_id" = $2 AND "iv"."bizplace_id" = $3 AND "iv"."packing_type" = $4 AND "iv"."packing_size" = $5 AND "iv"."product_id" = $6 AND "iv"."status" = $7 AND "loc"."type" NOT IN ($8, $9, $10)
1036
- AND "iv"."obsolete" = false AND case when "iv"."expiration_date" is not null and "p"."min_outbound_shelf_life" is not null then CURRENT_DATE < "iv"."expiration_date" - "p"."min_outbound_shelf_life" else true end
1037
- ${queryStrings.query.length > 0 ? `AND ${queryStrings.join(' AND ')}` : ''}
1038
- ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}
1039
- )
1040
- ) dt1
1041
- ) dt2 where case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end > 0
1042
- ) dt3 where sort_seq > 0
1043
- ) src where src.id = tgt.id
1044
- returning
1045
- tgt."id", tgt."qty", tgt."pallet_id", tgt."carton_id", tgt."batch_id", tgt."batch_id_ref", tgt."unit",
1046
- tgt."uom", tgt."packing_type", tgt."packing_size", tgt."manufacture_year",
1047
- tgt."locked_qty", tgt."uom_value", tgt."locked_uom_value", src."reserve_qty", src."reserve_uom_value";`,
1048
- [
1049
- user.id,
1050
- domain.id,
1051
- customerBizplace.id,
1052
- orderInventory.packingType,
1053
- orderInventory.packingSize,
1054
- orderInventory.product.id,
1055
- INVENTORY_STATUS.STORED,
1056
- LOCATION_TYPE.QUARANTINE,
1057
- LOCATION_TYPE.RESERVE,
1058
- LOCATION_TYPE.STORAGE,
1059
- ...queryStrings.values
1060
- ]
1061
- )
1062
-
1063
- console.log({
1064
- params: {
1065
- user: user.id || '',
1066
- domain: domain.id || '',
1067
- bizplace: customerBizplace.id || '',
1068
- packingType: orderInventory.packingType || '',
1069
- packingSize: orderInventory.packingSize || '',
1070
- productId: orderInventory.product.id || ''
1071
- },
1072
- result: updatedInventories[0] || '',
1073
- location: 'add-release-order unstable assignInventory',
1074
- time: new Date()
1075
- })
1076
-
1077
- let totalAssigned = updatedInventories[0].reduce((acc, inv) => {
1078
- return acc + inv.reserve_qty
1079
- }, 0)
1014
+ case when (qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0)) < 0 then 0
1015
+ else qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0) end
1016
+ ) as available_qty,
1017
+ sum(qty - locked_qty - release_qty - unassigned_qty) over (order by sort_seq asc rows between unbounded preceding and current row) as lock_amount
1018
+ from (
1019
+ SELECT 0 as sort_seq, null as id, null as pallet_id, null as batch_id, null as batch_id_ref,
1020
+ null as unit, '${orderInventory[oiIdx].uom}' as uom, '${orderInventory[oiIdx].packingType}' as packing_type, '${
1021
+ orderInventory[oiIdx].packingSize
1022
+ }' as packing_size,
1023
+ null as manufacture_year, null as carton_id, 0 as uom_value, 0 as locked_uom_value, 0 as qty, 0 as locked_qty, 0 as unassigned_uom_value, 0 as unassigned_qty, null as created_at,
1024
+ '${orderInventory[oiIdx].releaseQty}' as release_qty, '${orderInventory[oiIdx].releaseUomValue}' as release_uom_value
1025
+ UNION
1026
+ (
1027
+ SELECT ROW_NUMBER() OVER(PARTITION BY iv.domain_id ORDER BY wiar.rank ${
1028
+ sortQuery ? ', ' + sortQuery : ''
1029
+ }) as sort_seq,
1030
+ iv.id, iv.pallet_id, iv.batch_id, iv.batch_id_ref,
1031
+ iv.unit, iv.uom, iv.packing_type, iv.packing_size,
1032
+ iv.manufacture_year, iv.carton_id, iv.uom_value,
1033
+ coalesce(iv.locked_uom_value,0) as locked_uom_value, iv.qty, greatest(coalesce(iv.locked_qty,0),0) as locked_qty, coalesce(pds.unassigned_uom_value,0) as unassigned_uom_value, greatest(coalesce(pds.unassigned_qty,0),0) as unassigned_qty,
1034
+ iv.created_at, 0 as release_qty, 0 as release_uom_value
1035
+ FROM "inventories" "iv"
1036
+ LEFT JOIN "product_detail_stocks" "pds" ON "pds"."product_detail_id" = "iv"."product_detail_id"
1037
+ INNER JOIN "locations" "loc" ON "loc"."id"="iv"."location_id"
1038
+ INNER JOIN "products" "p" ON "p"."id"="iv"."product_id"
1039
+ INNER JOIN "warehouse_inventory_assignment_rankings" "wiar" ON "wiar"."location_type"="loc"."type"
1040
+ WHERE case when coalesce("iv"."locked_qty",0) < 0 then 0 else ("iv"."qty" - coalesce("iv"."locked_qty",0)) end > 0 AND
1041
+ "iv"."domain_id" = $2 AND "iv"."bizplace_id" = $3 AND "iv"."packing_type" = $4 AND "iv"."packing_size" = $5 AND "iv"."product_id" = $6 AND "iv"."status" = $7 AND "loc"."type" NOT IN ($8, $9, $10)
1042
+ AND "iv"."obsolete" = false AND case when "iv"."expiration_date" is not null and "p"."min_outbound_shelf_life" is not null then CURRENT_DATE < "iv"."expiration_date" - "p"."min_outbound_shelf_life" else true end
1043
+ ${queryStrings.query.length > 0 ? `AND ${queryStrings.join(' AND ')}` : ''}
1044
+ ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}
1045
+ )
1046
+ ) dt1
1047
+ ) dt2 where case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end > 0
1048
+ ) dt3 where sort_seq > 0
1049
+ ) src where src.id = tgt.id
1050
+ returning
1051
+ tgt."id", tgt."qty", tgt."pallet_id", tgt."carton_id", tgt."batch_id", tgt."batch_id_ref", tgt."unit",
1052
+ tgt."uom", tgt."packing_type", tgt."packing_size", tgt."manufacture_year",
1053
+ tgt."locked_qty", tgt."uom_value", tgt."locked_uom_value", src."reserve_qty", src."reserve_uom_value";`,
1054
+ [
1055
+ user.id,
1056
+ domain.id,
1057
+ customerBizplace.id,
1058
+ orderInventory[oiIdx].packingType,
1059
+ orderInventory[oiIdx].packingSize,
1060
+ orderInventory[oiIdx].product.id,
1061
+ INVENTORY_STATUS.STORED,
1062
+ LOCATION_TYPE.QUARANTINE,
1063
+ LOCATION_TYPE.RESERVE,
1064
+ LOCATION_TYPE.STORAGE,
1065
+ ...queryStrings.values
1066
+ ]
1067
+ )
1068
+
1069
+ console.log({
1070
+ params: {
1071
+ user: user.id || '',
1072
+ domain: domain.id || '',
1073
+ bizplace: customerBizplace.id || '',
1074
+ packingType: orderInventory[oiIdx].packingType || '',
1075
+ packingSize: orderInventory[oiIdx].packingSize || '',
1076
+ productId: orderInventory[oiIdx].product.id || ''
1077
+ },
1078
+ result: updatedInventories[0] || '',
1079
+ location: 'add-release-order unstable assignInventory',
1080
+ time: new Date()
1081
+ })
1082
+
1083
+ let totalAssigned = updatedInventories[0].reduce((acc, inv) => {
1084
+ return acc + inv.reserve_qty
1085
+ }, 0)
1080
1086
 
1081
- if (orderProduct.releaseQty != totalAssigned) {
1082
- throw new ApiError('E01', 'INSUFFICIENT_STOCK')
1083
- }
1087
+ let opReleaseQty = productBundle ? orderInventory[oiIdx].releaseQty : orderProduct.releaseQty
1084
1088
 
1085
- updatedInventories[0].forEach(inv => {
1086
- let oi = {
1087
- ...orderInventory,
1088
- inventory: { id: inv.id },
1089
- uom: inv.uom,
1090
- packingType: inv.packing_type,
1091
- batchId: inv.batch_id,
1092
- releaseQty: inv.reserve_qty,
1093
- releaseUomValue: inv.reserve_uom_value,
1094
- pickedQty: 0,
1095
- packedQty: 0,
1096
- type: ORDER_TYPES.RELEASE_OF_GOODS,
1097
- status: ORDER_INVENTORY_STATUS.PENDING_WORKSHEET,
1098
- domain: { id: domain.id },
1099
- bizplace: { id: customerBizplace.id }
1089
+ if (opReleaseQty != totalAssigned) {
1090
+ throw new ApiError('E01', 'INSUFFICIENT_STOCK')
1100
1091
  }
1101
-
1102
- assignedOrderInventories.push(oi)
1103
- })
1104
-
1105
- orderProducts[opIdx].orderInventories = assignedOrderInventories
1106
- } else {
1107
- await tx
1108
- .getRepository(ProductDetailStock)
1109
- .createQueryBuilder()
1110
- .update(ProductDetailStock)
1111
- .set({
1112
- unassignedQty: () => `"unassigned_qty" + ${orderInventory.releaseQty}`,
1113
- unassignedUomValue: () => `"unassigned_uom_value" + ${orderInventory.releaseUomValue}`
1092
+
1093
+ updatedInventories[0].forEach(inv => {
1094
+ let oi = {
1095
+ ...orderInventory[oiIdx],
1096
+ inventory: { id: inv.id },
1097
+ uom: inv.uom,
1098
+ packingType: inv.packing_type,
1099
+ batchId: inv.batch_id,
1100
+ releaseQty: inv.reserve_qty,
1101
+ releaseUomValue: inv.reserve_uom_value,
1102
+ pickedQty: 0,
1103
+ packedQty: 0,
1104
+ type: ORDER_TYPES.RELEASE_OF_GOODS,
1105
+ status: ORDER_INVENTORY_STATUS.PENDING_WORKSHEET,
1106
+ domain: { id: domain.id },
1107
+ bizplace: { id: customerBizplace.id }
1108
+ }
1109
+
1110
+ assignedOrderInventories.push(oi)
1114
1111
  })
1115
- .where({ productDetail: orderInventory.productDetail.id })
1116
- .execute()
1112
+
1113
+ orderProducts[opIdx].orderInventories = assignedOrderInventories
1114
+ } else {
1115
+ await tx
1116
+ .getRepository(ProductDetailStock)
1117
+ .createQueryBuilder()
1118
+ .update(ProductDetailStock)
1119
+ .set({
1120
+ unassignedQty: () => `"unassigned_qty" + ${orderInventory[oiIdx].releaseQty}`,
1121
+ unassignedUomValue: () => `"unassigned_uom_value" + ${orderInventory[oiIdx].releaseUomValue}`
1122
+ })
1123
+ .where({ productDetail: orderInventory[oiIdx].productDetail.id })
1124
+ .execute()
1125
+ }
1117
1126
  }
1118
1127
  }
1119
1128
 
@@ -35,6 +35,10 @@ router.get(
35
35
  'orderInventories',
36
36
  'orderInventories.product',
37
37
  'orderInventories.productDetail',
38
+ 'orderInventories.orderProduct',
39
+ 'orderInventories.orderProduct.productBundle',
40
+ 'orderProducts',
41
+ 'orderProducts.productBundle',
38
42
  'orderPackages',
39
43
  'orderPackages.orderPackageItems',
40
44
  'bizplace'
@@ -46,6 +50,7 @@ router.get(
46
50
  // create and format data response
47
51
  let orderInventories = []
48
52
  for (const orderInventory of releaseGood.orderInventories) {
53
+ let orderProduct = orderInventory.orderProduct
49
54
  const orderInventoriesDataPoint = {
50
55
  product: {
51
56
  sku: orderInventory.product.sku,
@@ -53,10 +58,16 @@ router.get(
53
58
  refCode: orderInventory.productDetail.refCode ? orderInventory.productDetail.refCode : null
54
59
  }
55
60
  },
61
+ orderProduct: {
62
+ productBundle: {
63
+ sku: orderProduct?.productBundle?.sku ? orderProduct?.productBundle?.sku : null
64
+ },
65
+ releaseQty: orderProduct.releaseQty ? orderProduct.releaseQty : null
66
+ },
56
67
  batchId: orderInventory.batchId,
57
68
  packingType: orderInventory.packingType,
58
- releaseQty: orderInventory.releaseQty,
59
- packingSize: orderInventory.packingSize
69
+ packingSize: orderInventory.packingSize,
70
+ releaseQty: orderInventory.releaseQty
60
71
  }
61
72
  orderInventories.push(orderInventoriesDataPoint)
62
73
  }