Explorar o código

fix:5563【销售订单/发货单】两个入库,创建订单的时候多个物品选择库存式订单可用数量都是够的,提交会提示不足,删除后审批通过去发货又提示不足,实际库存有的

mlchen hai 3 semanas
pai
achega
c5851337a8

+ 139 - 29
src/BIZComponents/inventoryTable.vue

@@ -1011,6 +1011,7 @@
   import ProductionVersion from '@/components/ProductionVersion2/index.vue';
   import {
     getInventoryTotalAPI,
+    getWarehouseOutStockBatchAPI,
     buildInventoryTotalQueryKey,
     matchInventoryTotal
   } from '@/api/wms';
@@ -1949,13 +1950,31 @@
       },
       async getSupplierObj(productList, queryName) {
         try {
-          let categoryIds = productList
-            .filter((item) => item.productId)
-            .map((item) => item.productId);
+          const categoryIds = [
+            ...new Set(
+              productList
+                .map((item) => item[queryName])
+                .filter((categoryId) => categoryId)
+            )
+          ];
           if (categoryIds.length > 0) {
-            return await contactQueryByCategoryIdsAPI({
+            const supplierObj = await contactQueryByCategoryIdsAPI({
               categoryIds
             });
+            Object.keys(supplierObj || {}).forEach((categoryId) => {
+              const supplierIds = new Set();
+              supplierObj[categoryId] = (supplierObj[categoryId] || []).filter(
+                (supplier) => {
+                  const supplierId = String(supplier.id);
+                  if (supplierIds.has(supplierId)) {
+                    return false;
+                  }
+                  supplierIds.add(supplierId);
+                  return true;
+                }
+              );
+            });
+            return supplierObj;
           } else {
             return Promise.resolve({});
           }
@@ -2035,6 +2054,93 @@
           this.getStockCount(item) - Number(item.lockQuantity || 0);
         return Number(availableCount.toFixed(4));
       },
+      getInventoryIdentity(item) {
+        return [
+          item.productCode,
+          item.warehouseId,
+          item.batchNo,
+          item.systemBatchNo,
+          item.colorKey,
+          item.modelType
+        ]
+          .map((value) => (value == null ? '' : String(value).trim()))
+          .join('|');
+      },
+      buildExactInventoryRequest(item) {
+        return {
+          code: item.productCode,
+          warehouseId: item.warehouseId,
+          batchNo: item.batchNo,
+          systemBatchNo: item.systemBatchNo,
+          colorKey: item.colorKey,
+          modelType: item.modelType
+        };
+      },
+      async refreshStockOrderInventory(validateQuantity = false) {
+        if (this.needProduce != 0) {
+          return true;
+        }
+        const inventoryGroups = new Map();
+        this.form.datasource.forEach((item, index) => {
+          if (!item.productCode || !item.warehouseId) {
+            return;
+          }
+          const identity = this.getInventoryIdentity(item);
+          const group = inventoryGroups.get(identity) || {
+            request: this.buildExactInventoryRequest(item),
+            rows: [],
+            requiredQuantity: 0,
+            productCode: item.productCode,
+            productName: item.productName
+          };
+          group.rows.push(index);
+          group.requiredQuantity += Number(item.totalCount || item.saleCount || 0);
+          inventoryGroups.set(identity, group);
+        });
+        const groups = Array.from(inventoryGroups.values());
+        if (groups.length === 0) {
+          return true;
+        }
+        const inventoryList = await getWarehouseOutStockBatchAPI(
+          groups.map((group) => group.request)
+        );
+        const insufficient = [];
+        groups.forEach((group, groupIndex) => {
+          const inventory = inventoryList[groupIndex] || {};
+          const stockCountBase = Number(inventory.stockCountBase || 0);
+          const availableCountBase = Number(inventory.availableCountBase || 0);
+          group.rows.forEach((rowIndex) => {
+            if (this.showStockCount) {
+              this.$set(
+                this.form.datasource[rowIndex],
+                'stockCountBase',
+                stockCountBase
+              );
+            }
+            this.$set(
+              this.form.datasource[rowIndex],
+              'availableCountBase',
+              availableCountBase
+            );
+          });
+          if (
+            validateQuantity &&
+            group.requiredQuantity > availableCountBase
+          ) {
+            insufficient.push(
+              `${group.productCode}-${group.productName || ''}需求${group.requiredQuantity},可用${availableCountBase}`
+            );
+          }
+        });
+        if (insufficient.length > 0) {
+          this.$message.error(`库存不足:${insufficient.join(';')}`);
+          return false;
+        }
+        return true;
+      },
+      async validateInventoryAvailability() {
+        return this.refreshStockOrderInventory(true);
+      },
       // 返回列表数据
       getTableValue() {
         let comitDatasource = copyObj(this.form.datasource);
@@ -2367,34 +2473,38 @@
           });
           this.form.datasource = productList;
 
-          let codeList = this.form.datasource
-            .filter((item) => item.productCode)
-            .map((item) => buildInventoryTotalQueryKey(item));
-          //获取仓库库存
-          let inventoryTotalList = await getInventoryTotalAPI(codeList);
-          this.form.datasource
-            .filter((item) => item.productCode)
-            .forEach((item, index) => {
-              let find =
-                inventoryTotalList.find((key) =>
-                  matchInventoryTotal(item, key)
-                ) || {};
-              this.form.datasource;
-              if (this.showStockCount) {
+          if (this.needProduce == 0) {
+            await this.refreshStockOrderInventory();
+          } else {
+            let codeList = this.form.datasource
+              .filter((item) => item.productCode)
+              .map((item) => buildInventoryTotalQueryKey(item));
+            // 非库存式业务保留原有物品/批次汇总库存口径。
+            let inventoryTotalList = await getInventoryTotalAPI(codeList);
+            this.form.datasource
+              .filter((item) => item.productCode)
+              .forEach((item, index) => {
+                let find =
+                  inventoryTotalList.find((key) =>
+                    matchInventoryTotal(item, key)
+                  ) || {};
+                this.form.datasource;
+                if (this.showStockCount) {
+                  this.$set(
+                    this.form.datasource[index],
+                    'stockCountBase',
+                    this.getStockCount(find)
+                  );
+                }
                 this.$set(
                   this.form.datasource[index],
-                  'stockCountBase',
-                  this.getStockCount(find)
+                  'availableCountBase',
+                  this.showStockCount
+                    ? this.getAvailableStockCount(find)
+                    : find.availableCountBase
                 );
-              }
-              this.$set(
-                this.form.datasource[index],
-                'availableCountBase',
-                this.showStockCount
-                  ? this.getAvailableStockCount(find)
-                  : find.availableCountBase
-              );
-            });
+              });
+          }
           if (this.isChangeCount) {
             this.changeCount();
           } else {

+ 3 - 3
src/BIZComponents/setProduct.js

@@ -7,7 +7,7 @@ export function formatPrice(price, decimals = 4) {
 
 //改变数量
 export function changeCount(row, countObj, noDiscountSingle, weightType) {
-  
+
   let data = JSON.parse(JSON.stringify(row));
   // console.log('changeCount~~', data);
   let total = data[countObj.countKey] || 0;
@@ -122,7 +122,7 @@ function setSingleWeight(row, countObj, endIndex) {
   }
 }
 export function getAllPrice(arr) {
-  console.log('arr~~~', arr);
+  // console.log('arr~~~', arr);
   let sum = 0;
   arr.forEach((item) => {
     if (item.totalPrice) {
@@ -135,7 +135,7 @@ export function getAllPrice(arr) {
 export function getAllQuantity(arr, countObj) {
   let sum = 0;
   arr.forEach((item) => {
-    console.log('item', item, countObj.countKey);
+    // console.log('item', item, countObj.countKey);
     if (item[countObj.countKey]) {
       sum += Number(item[countObj.countKey]);
     }

+ 17 - 0
src/api/wms/index.js

@@ -14,6 +14,23 @@ export async function getInventoryTotalAPI(data) {
   return Promise.reject(new Error(res.data.message));
 }
 
+/**
+ * 按仓库、批次、系统批次、颜色和型号批量查询精确库存。
+ */
+export async function getWarehouseOutStockBatchAPI(data) {
+  if (!data || data.length === 0) {
+    return [];
+  }
+  const res = await request.post(
+    'wms/stocktwo/getWarehouseOutStockBatch',
+    data
+  );
+  if (res.data.code == 0) {
+    return res.data.data;
+  }
+  return Promise.reject(new Error(res.data.message));
+}
+
 /**
  * 生成库存统计查询键;传入字符串时保持旧格式原样透传。
  */

+ 7 - 0
src/views/saleManage/saleOrder/components/addDialog.vue

@@ -1706,6 +1706,13 @@
       async save(type) {
         try {
           await this.getValidate();
+          if (
+            type === 'sub' &&
+            this.form.needProduce == 0 &&
+            !(await this.$refs.inventoryTable.validateInventoryAvailability())
+          ) {
+            return;
+          }
           // 表单验证通过,执行保存操作
           this.loading = true;
           let isTemporary = [];