@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
@@ -120,7 +120,7 @@ api_1.restfulApiRouter.post(`/${apiVersion}/warehouse/add-release-order`, middle
120
120
  // check existing order
121
121
  await checkExistingOrder(releaseGood, customerBizplace, bodyReq === null || bodyReq === void 0 ? void 0 : bodyReq.checkDuplicationValidation, context, tx);
122
122
  // massage data
123
- massagedData = await massageOrderItems(releaseGood, bodyReq.orderInventories, context);
123
+ massagedData = await massageOrderItems(releaseGood, bodyReq.orderInventories, context); //double check this function
124
124
  // validation
125
125
  await Promise.all(massagedData.combinedItems.map(async (item) => {
126
126
  let itemList = await tx.query(`
@@ -157,6 +157,7 @@ api_1.restfulApiRouter.post(`/${apiVersion}/warehouse/add-release-order`, middle
157
157
  }
158
158
  console.log();
159
159
  }));
160
+ // use product id
160
161
  // assignment
161
162
  // console.time('assign')
162
163
  let assignedOrderProducts = await assignToInventory(massagedData.orderProducts, customerBizplace, context, tx, worksheetPickingAssignment);
@@ -503,7 +504,7 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
503
504
  //combine any repeated skus
504
505
  inputOrderProducts = inputOrderProducts.reduce((acc, itm, idx) => {
505
506
  let { sku, refCode } = itm.product;
506
- let { packingType, packingSize, batchId, releaseQty, sellingPrice, paidAmount } = itm;
507
+ let { packingType, packingSize, batchId, releaseQty, sellingPrice, paidAmount, uom } = itm;
507
508
  if (!sku && !refCode) {
508
509
  throw new error_util_1.ApiError('E01', 'sku or refCode not found');
509
510
  }
@@ -515,7 +516,8 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
515
516
  let existingIndex = acc.findIndex(itm => (itm === null || itm === void 0 ? void 0 : itm.sku) == (sku === null || sku === void 0 ? void 0 : sku.trim()) &&
516
517
  (itm === null || itm === void 0 ? void 0 : itm.refCode) == (refCode === null || refCode === void 0 ? void 0 : refCode.trim()) &&
517
518
  (itm === null || itm === void 0 ? void 0 : itm.packingType) == (packingType === null || packingType === void 0 ? void 0 : packingType.trim()) &&
518
- (itm === null || itm === void 0 ? void 0 : itm.packingSize) == packingSize);
519
+ (itm === null || itm === void 0 ? void 0 : itm.packingSize) == packingSize &&
520
+ (itm === null || itm === void 0 ? void 0 : itm.uom) == uom);
519
521
  if (existingIndex >= 0 && releaseQty > 0) {
520
522
  acc[existingIndex].releaseQty = acc[existingIndex].releaseQty + releaseQty;
521
523
  }
@@ -527,7 +529,8 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
527
529
  packingSize: packingSize,
528
530
  releaseQty: releaseQty,
529
531
  sellingPrice: sellingPrice,
530
- paidAmount: paidAmount
532
+ paidAmount: paidAmount,
533
+ uom: uom
531
534
  });
532
535
  }
533
536
  return acc;
@@ -535,6 +538,7 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
535
538
  //find customer sku in system
536
539
  await Promise.all(inputOrderProducts.map(async (inputOrderItem) => {
537
540
  const sku = inputOrderItem.sku;
541
+ const uom = inputOrderItem === null || inputOrderItem === void 0 ? void 0 : inputOrderItem.uom;
538
542
  const refCode = inputOrderItem.refCode;
539
543
  const packingType = inputOrderItem.packingType;
540
544
  const packingSize = inputOrderItem.packingSize;
@@ -588,25 +592,25 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
588
592
  }
589
593
  const foundProductBundle = await qb.getOne();
590
594
  if (foundProductBundle) {
591
- let orderProduct;
592
- // to be further enhanced
593
- // let orderProduct = {
594
- // productBundle: foundProductBundle,
595
- // refCode,
596
- // packingType: foundProductBundle.packingType,
597
- // packingSize: packingSize || 1,
598
- // uom: inputOrderItem?.uom,
599
- // releaseQty: inputOrderItem.releaseQty,
600
- // releaseUomValue: inputOrderItem.releaseQty,
601
- // packQty: 0,
602
- // actualPackQty: 0,
603
- // palletQty: 0,
604
- // actualPalletQty: 0,
605
- // orderInventories: [],
606
- // type: 'RELEASE_OF_GOODS',
607
- // status: ORDER_PRODUCT_STATUS.ASSIGNED,
608
- // batchId: '-'
609
- // }
595
+ //let orderProduct: OrderProduct
596
+ //to be further enhanced
597
+ let orderProduct = {
598
+ productBundle: foundProductBundle,
599
+ refCode,
600
+ packingType: foundProductBundle.packingType,
601
+ packingSize: packingSize || 1,
602
+ uom: inputOrderItem === null || inputOrderItem === void 0 ? void 0 : inputOrderItem.uom,
603
+ releaseQty: inputOrderItem.releaseQty,
604
+ releaseUomValue: inputOrderItem.releaseQty,
605
+ packQty: 0,
606
+ actualPackQty: 0,
607
+ palletQty: 0,
608
+ actualPalletQty: 0,
609
+ orderInventories: [],
610
+ type: 'RELEASE_OF_GOODS',
611
+ status: sales_base_1.ORDER_PRODUCT_STATUS.ASSIGNED,
612
+ batchId: '-'
613
+ };
610
614
  const bundleProductSettings = foundProductBundle.productBundleSettings;
611
615
  bundleProductSettings.map(bundleProductSetting => {
612
616
  const productDetailBundle = bundleProductSetting.productDetail;
@@ -628,11 +632,19 @@ async function massageOrderItems(releaseGood, inputOrderProducts, context) {
628
632
  type: 'RELEASE_OF_GOODS',
629
633
  status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET
630
634
  };
631
- orderProduct = Object.assign(new sales_base_1.OrderProduct(), newOrderInventory);
632
- orderProduct = Object.assign(Object.assign({}, orderProduct), { refCode, packingType: foundProductBundle.packingType, packingSize: packingSize || 1, orderInventories: [], status: sales_base_1.ORDER_PRODUCT_STATUS.ASSIGNED, batchId: '-' });
635
+ // orderProduct = Object.assign(new OrderProduct(), newOrderInventory)
636
+ // orderProduct = {
637
+ // ...orderProduct,
638
+ // refCode,
639
+ // packingType: foundProductBundle.packingType,
640
+ // packingSize: packingSize || 1,
641
+ // orderInventories: [],
642
+ // status: ORDER_PRODUCT_STATUS.ASSIGNED,
643
+ // batchId: '-'
644
+ // }
633
645
  orderProduct.orderInventories.push(newOrderInventory);
634
- orderProducts.push(orderProduct);
635
646
  });
647
+ orderProducts.push(orderProduct);
636
648
  }
637
649
  else {
638
650
  if (sku && refCode) {
@@ -696,191 +708,195 @@ async function assignToInventory(orderProducts, customerBizplace, context, tx, w
696
708
  for (let opIdx = 0; opIdx < orderProducts.length; opIdx++) {
697
709
  let orderProduct = orderProducts[opIdx];
698
710
  let assignedOrderInventories = [];
699
- const orderInventory = orderProduct.orderInventories[0];
711
+ const orderInventory = orderProduct.orderInventories;
712
+ let productBundle = orderProduct === null || orderProduct === void 0 ? void 0 : orderProduct.productBundle;
700
713
  let sortings = [];
701
- if ((worksheetPickingAssignment === null || worksheetPickingAssignment === void 0 ? void 0 : worksheetPickingAssignment.value) !== 'true') {
702
- switch (orderInventory.product.pickingStrategy) {
703
- case 'LIFO':
704
- sortings.push({ name: 'iv.created_at', desc: true });
705
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
706
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
707
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
714
+ for (let oiIdx = 0; oiIdx < orderInventory.length; oiIdx++) {
715
+ if ((worksheetPickingAssignment === null || worksheetPickingAssignment === void 0 ? void 0 : worksheetPickingAssignment.value) !== 'true') {
716
+ switch (orderInventory[oiIdx].product.pickingStrategy) {
717
+ case 'LIFO':
718
+ sortings.push({ name: 'iv.created_at', desc: true });
719
+ if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
720
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
721
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
722
+ }
708
723
  }
709
- }
710
- else {
711
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
712
- }
713
- break;
714
- case 'FEFO':
715
- sortings.push({ name: 'iv.expiration_date', desc: false }, { name: 'iv.created_at', desc: false });
716
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
717
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
718
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
724
+ else {
725
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
719
726
  }
720
- }
721
- else {
722
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
723
- }
724
- break;
725
- case 'FMFO':
726
- sortings.push({ name: 'iv.manufacture_date', desc: false }, { name: 'iv.created_at', desc: false });
727
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
728
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
729
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
727
+ break;
728
+ case 'FEFO':
729
+ sortings.push({ name: 'iv.expiration_date', desc: false }, { name: 'iv.created_at', desc: false });
730
+ if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
731
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
732
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
733
+ }
730
734
  }
731
- }
732
- else {
733
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
734
- }
735
- break;
736
- case 'LOCATION':
737
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
738
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
739
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
735
+ else {
736
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
740
737
  }
741
- }
742
- else {
743
- sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
744
- }
745
- break;
746
- //Every other case includes 'FIFO' will be applicable for this case
747
- default:
748
- sortings.push({ name: 'iv.created_at', desc: false });
749
- if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
750
- for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
751
- sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
738
+ break;
739
+ case 'FMFO':
740
+ sortings.push({ name: 'iv.manufacture_date', desc: false }, { name: 'iv.created_at', desc: false });
741
+ if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
742
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
743
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
744
+ }
745
+ }
746
+ else {
747
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
748
+ }
749
+ break;
750
+ case 'LOCATION':
751
+ if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
752
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
753
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
754
+ }
755
+ }
756
+ else {
757
+ sortings.push({ name: 'loc.name', desc: false }, { name: 'iv.created_at', desc: false });
752
758
  }
753
- }
754
- else {
755
- sortings.push({ name: 'loc.name', desc: false });
756
- sortings.push({ name: 'iv.pallet_id', desc: false });
757
- }
758
- break;
759
- }
760
- let queryFilters = [];
761
- let queryStrings = queryFilters.reduce((acc, itm, idx, arr) => {
762
- acc.values.push(itm.filters);
763
- switch (itm === null || itm === void 0 ? void 0 : itm.operator) {
764
- case 'notin':
765
- case 'in':
766
- acc.query.push(`${itm.query} ${itm.operator == 'notin' ? 'NOT IN' : 'IN'} (${itm.filtes
767
- .map((itm, idx) => {
768
- return `$${acc.values.length + 1}`;
769
- })
770
- .join(',')})`);
771
759
  break;
760
+ //Every other case includes 'FIFO' will be applicable for this case
772
761
  default:
773
- acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
762
+ sortings.push({ name: 'iv.created_at', desc: false });
763
+ if (pickingProductSetting === null || pickingProductSetting === void 0 ? void 0 : pickingProductSetting.value) {
764
+ for (const [key, value] of Object.entries(JSON.parse(pickingProductSetting.value))) {
765
+ sortings.push({ name: `loc.${key}`, desc: value == 'DESC' ? true : false });
766
+ }
767
+ }
768
+ else {
769
+ sortings.push({ name: 'loc.name', desc: false });
770
+ sortings.push({ name: 'iv.pallet_id', desc: false });
771
+ }
774
772
  break;
775
773
  }
776
- acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
777
- }, {
778
- query: [],
779
- values: []
780
- });
781
- let sortQuery = sortings
782
- .map(itm => {
783
- return `${itm.name} ${itm.desc ? 'DESC' : 'ASC'}`;
784
- })
785
- .join(`,`);
786
- let updatedInventories = await tx.getRepository(warehouse_base_1.Inventory).query(`
787
- update inventories tgt set locked_qty = coalesce(locked_qty,0) + src.reserve_qty,
788
- locked_uom_value = coalesce(locked_uom_value,0) + src.reserve_uom_value,
789
- updated_at = NOW(),
790
- updater_id = $1
791
- from (
792
- select "id", "pallet_id","carton_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year",
793
- "reserve_qty", (("uom_value"/"qty") * "reserve_qty") as "reserve_uom_value" from (
794
- 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",
795
- "release_qty", "release_uom_value", lock_amount,
796
- case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end as "reserve_qty"
797
- from (
798
- select *,
799
- (
800
- case when (qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0)) < 0 then 0
801
- else qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0) end
802
- ) as available_qty,
803
- sum(qty - locked_qty - release_qty - unassigned_qty) over (order by sort_seq asc rows between unbounded preceding and current row) as lock_amount
774
+ let queryFilters = [];
775
+ let queryStrings = queryFilters.reduce((acc, itm, idx, arr) => {
776
+ acc.values.push(itm.filters);
777
+ switch (itm === null || itm === void 0 ? void 0 : itm.operator) {
778
+ case 'notin':
779
+ case 'in':
780
+ acc.query.push(`${itm.query} ${itm.operator == 'notin' ? 'NOT IN' : 'IN'} (${itm.filtes
781
+ .map((itm, idx) => {
782
+ return `$${acc.values.length + 1}`;
783
+ })
784
+ .join(',')})`);
785
+ break;
786
+ default:
787
+ acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
788
+ break;
789
+ }
790
+ acc.query.push(`${itm.query} ${(itm === null || itm === void 0 ? void 0 : itm.operator) ? itm.operator : '='} $${acc.values.length + 1}`);
791
+ }, {
792
+ query: [],
793
+ values: []
794
+ });
795
+ let sortQuery = sortings
796
+ .map(itm => {
797
+ return `${itm.name} ${itm.desc ? 'DESC' : 'ASC'}`;
798
+ })
799
+ .join(`,`);
800
+ let updatedInventories = await tx.getRepository(warehouse_base_1.Inventory).query(`
801
+ update inventories tgt set locked_qty = coalesce(locked_qty,0) + src.reserve_qty,
802
+ locked_uom_value = coalesce(locked_uom_value,0) + src.reserve_uom_value,
803
+ updated_at = NOW(),
804
+ updater_id = $1
805
+ from (
806
+ select "id", "pallet_id","carton_id", "batch_id", "batch_id_ref", "unit", "uom", "packing_type", "packing_size", "manufacture_year",
807
+ "reserve_qty", (("uom_value"/"qty") * "reserve_qty") as "reserve_uom_value" from (
808
+ 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",
809
+ "release_qty", "release_uom_value", lock_amount,
810
+ case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end as "reserve_qty"
804
811
  from (
805
- SELECT 0 as sort_seq, null as id, null as pallet_id, null as batch_id, null as batch_id_ref,
806
- null as unit, '${orderInventory.uom}' as uom, '${orderInventory.packingType}' as packing_type, '${orderInventory.packingSize}' as packing_size,
807
- 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,
808
- '${orderInventory.releaseQty}' as release_qty, '${orderInventory.releaseUomValue}' as release_uom_value
809
- UNION
812
+ select *,
810
813
  (
811
- SELECT ROW_NUMBER() OVER(PARTITION BY iv.domain_id ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}) as sort_seq,
812
- iv.id, iv.pallet_id, iv.batch_id, iv.batch_id_ref,
813
- iv.unit, iv.uom, iv.packing_type, iv.packing_size,
814
- iv.manufacture_year, iv.carton_id, iv.uom_value,
815
- 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,
816
- iv.created_at, 0 as release_qty, 0 as release_uom_value
817
- FROM "inventories" "iv"
818
- LEFT JOIN "product_detail_stocks" "pds" ON "pds"."product_detail_id" = "iv"."product_detail_id"
819
- INNER JOIN "locations" "loc" ON "loc"."id"="iv"."location_id"
820
- INNER JOIN "products" "p" ON "p"."id"="iv"."product_id"
821
- INNER JOIN "warehouse_inventory_assignment_rankings" "wiar" ON "wiar"."location_type"="loc"."type"
822
- WHERE case when coalesce("iv"."locked_qty",0) < 0 then 0 else ("iv"."qty" - coalesce("iv"."locked_qty",0)) end > 0 AND
823
- "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)
824
- 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
825
- ${queryStrings.query.length > 0 ? `AND ${queryStrings.join(' AND ')}` : ''}
826
- ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}
827
- )
828
- ) dt1
829
- ) dt2 where case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end > 0
830
- ) dt3 where sort_seq > 0
831
- ) src where src.id = tgt.id
832
- returning
833
- tgt."id", tgt."qty", tgt."pallet_id", tgt."carton_id", tgt."batch_id", tgt."batch_id_ref", tgt."unit",
834
- tgt."uom", tgt."packing_type", tgt."packing_size", tgt."manufacture_year",
835
- tgt."locked_qty", tgt."uom_value", tgt."locked_uom_value", src."reserve_qty", src."reserve_uom_value";`, [
836
- user.id,
837
- domain.id,
838
- customerBizplace.id,
839
- orderInventory.packingType,
840
- orderInventory.packingSize,
841
- orderInventory.product.id,
842
- warehouse_base_1.INVENTORY_STATUS.STORED,
843
- warehouse_base_1.LOCATION_TYPE.QUARANTINE,
844
- warehouse_base_1.LOCATION_TYPE.RESERVE,
845
- warehouse_base_1.LOCATION_TYPE.STORAGE,
846
- ...queryStrings.values
847
- ]);
848
- console.log({
849
- params: {
850
- user: user.id || '',
851
- domain: domain.id || '',
852
- bizplace: customerBizplace.id || '',
853
- packingType: orderInventory.packingType || '',
854
- packingSize: orderInventory.packingSize || '',
855
- productId: orderInventory.product.id || ''
856
- },
857
- result: updatedInventories[0] || '',
858
- location: 'add-release-order unstable assignInventory',
859
- time: new Date()
860
- });
861
- let totalAssigned = updatedInventories[0].reduce((acc, inv) => {
862
- return acc + inv.reserve_qty;
863
- }, 0);
864
- if (orderProduct.releaseQty != totalAssigned) {
865
- throw new error_util_1.ApiError('E01', 'INSUFFICIENT_STOCK');
814
+ case when (qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0)) < 0 then 0
815
+ else qty - greatest(locked_qty, 0) - greatest(unassigned_qty, 0) end
816
+ ) as available_qty,
817
+ sum(qty - locked_qty - release_qty - unassigned_qty) over (order by sort_seq asc rows between unbounded preceding and current row) as lock_amount
818
+ from (
819
+ SELECT 0 as sort_seq, null as id, null as pallet_id, null as batch_id, null as batch_id_ref,
820
+ null as unit, '${orderInventory[oiIdx].uom}' as uom, '${orderInventory[oiIdx].packingType}' as packing_type, '${orderInventory[oiIdx].packingSize}' as packing_size,
821
+ 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,
822
+ '${orderInventory[oiIdx].releaseQty}' as release_qty, '${orderInventory[oiIdx].releaseUomValue}' as release_uom_value
823
+ UNION
824
+ (
825
+ SELECT ROW_NUMBER() OVER(PARTITION BY iv.domain_id ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}) as sort_seq,
826
+ iv.id, iv.pallet_id, iv.batch_id, iv.batch_id_ref,
827
+ iv.unit, iv.uom, iv.packing_type, iv.packing_size,
828
+ iv.manufacture_year, iv.carton_id, iv.uom_value,
829
+ 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,
830
+ iv.created_at, 0 as release_qty, 0 as release_uom_value
831
+ FROM "inventories" "iv"
832
+ LEFT JOIN "product_detail_stocks" "pds" ON "pds"."product_detail_id" = "iv"."product_detail_id"
833
+ INNER JOIN "locations" "loc" ON "loc"."id"="iv"."location_id"
834
+ INNER JOIN "products" "p" ON "p"."id"="iv"."product_id"
835
+ INNER JOIN "warehouse_inventory_assignment_rankings" "wiar" ON "wiar"."location_type"="loc"."type"
836
+ WHERE case when coalesce("iv"."locked_qty",0) < 0 then 0 else ("iv"."qty" - coalesce("iv"."locked_qty",0)) end > 0 AND
837
+ "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)
838
+ 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
839
+ ${queryStrings.query.length > 0 ? `AND ${queryStrings.join(' AND ')}` : ''}
840
+ ORDER BY wiar.rank ${sortQuery ? ', ' + sortQuery : ''}
841
+ )
842
+ ) dt1
843
+ ) dt2 where case when "lock_amount" < 0 then "available_qty" else "available_qty" - "lock_amount" end > 0
844
+ ) dt3 where sort_seq > 0
845
+ ) src where src.id = tgt.id
846
+ returning
847
+ tgt."id", tgt."qty", tgt."pallet_id", tgt."carton_id", tgt."batch_id", tgt."batch_id_ref", tgt."unit",
848
+ tgt."uom", tgt."packing_type", tgt."packing_size", tgt."manufacture_year",
849
+ tgt."locked_qty", tgt."uom_value", tgt."locked_uom_value", src."reserve_qty", src."reserve_uom_value";`, [
850
+ user.id,
851
+ domain.id,
852
+ customerBizplace.id,
853
+ orderInventory[oiIdx].packingType,
854
+ orderInventory[oiIdx].packingSize,
855
+ orderInventory[oiIdx].product.id,
856
+ warehouse_base_1.INVENTORY_STATUS.STORED,
857
+ warehouse_base_1.LOCATION_TYPE.QUARANTINE,
858
+ warehouse_base_1.LOCATION_TYPE.RESERVE,
859
+ warehouse_base_1.LOCATION_TYPE.STORAGE,
860
+ ...queryStrings.values
861
+ ]);
862
+ console.log({
863
+ params: {
864
+ user: user.id || '',
865
+ domain: domain.id || '',
866
+ bizplace: customerBizplace.id || '',
867
+ packingType: orderInventory[oiIdx].packingType || '',
868
+ packingSize: orderInventory[oiIdx].packingSize || '',
869
+ productId: orderInventory[oiIdx].product.id || ''
870
+ },
871
+ result: updatedInventories[0] || '',
872
+ location: 'add-release-order unstable assignInventory',
873
+ time: new Date()
874
+ });
875
+ let totalAssigned = updatedInventories[0].reduce((acc, inv) => {
876
+ return acc + inv.reserve_qty;
877
+ }, 0);
878
+ let opReleaseQty = productBundle ? orderInventory[oiIdx].releaseQty : orderProduct.releaseQty;
879
+ if (opReleaseQty != totalAssigned) {
880
+ throw new error_util_1.ApiError('E01', 'INSUFFICIENT_STOCK');
881
+ }
882
+ updatedInventories[0].forEach(inv => {
883
+ let oi = Object.assign(Object.assign({}, orderInventory[oiIdx]), { inventory: { id: inv.id }, uom: inv.uom, packingType: inv.packing_type, batchId: inv.batch_id, releaseQty: inv.reserve_qty, releaseUomValue: inv.reserve_uom_value, pickedQty: 0, packedQty: 0, type: sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS, status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET, domain: { id: domain.id }, bizplace: { id: customerBizplace.id } });
884
+ assignedOrderInventories.push(oi);
885
+ });
886
+ orderProducts[opIdx].orderInventories = assignedOrderInventories;
887
+ }
888
+ else {
889
+ await tx
890
+ .getRepository(warehouse_base_1.ProductDetailStock)
891
+ .createQueryBuilder()
892
+ .update(warehouse_base_1.ProductDetailStock)
893
+ .set({
894
+ unassignedQty: () => `"unassigned_qty" + ${orderInventory[oiIdx].releaseQty}`,
895
+ unassignedUomValue: () => `"unassigned_uom_value" + ${orderInventory[oiIdx].releaseUomValue}`
896
+ })
897
+ .where({ productDetail: orderInventory[oiIdx].productDetail.id })
898
+ .execute();
866
899
  }
867
- updatedInventories[0].forEach(inv => {
868
- let oi = Object.assign(Object.assign({}, orderInventory), { inventory: { id: inv.id }, uom: inv.uom, packingType: inv.packing_type, batchId: inv.batch_id, releaseQty: inv.reserve_qty, releaseUomValue: inv.reserve_uom_value, pickedQty: 0, packedQty: 0, type: sales_base_1.ORDER_TYPES.RELEASE_OF_GOODS, status: sales_base_1.ORDER_INVENTORY_STATUS.PENDING_WORKSHEET, domain: { id: domain.id }, bizplace: { id: customerBizplace.id } });
869
- assignedOrderInventories.push(oi);
870
- });
871
- orderProducts[opIdx].orderInventories = assignedOrderInventories;
872
- }
873
- else {
874
- await tx
875
- .getRepository(warehouse_base_1.ProductDetailStock)
876
- .createQueryBuilder()
877
- .update(warehouse_base_1.ProductDetailStock)
878
- .set({
879
- unassignedQty: () => `"unassigned_qty" + ${orderInventory.releaseQty}`,
880
- unassignedUomValue: () => `"unassigned_uom_value" + ${orderInventory.releaseUomValue}`
881
- })
882
- .where({ productDetail: orderInventory.productDetail.id })
883
- .execute();
884
900
  }
885
901
  }
886
902
  return orderProducts;