Sfoglia il codice sorgente

Merge branch 'dev' of http://110.41.163.243:9980/kd-aiot/kd-aiot-frontend-eom into dev

xieyong 1 settimana fa
parent
commit
4e19313c57

+ 3 - 0
AGENTS.md

@@ -1,4 +1,7 @@
 # 前端数据契约
 
+- 销售发货的订单来源产品在编辑初始化、重新选择时,必须在清空 `id` 前保留 `orderProductId || id`;换仓和换批次只改变实际库存身份,不能覆盖订单明细身份。不同订单行即使物品和批次相同,也分别使用各自剩余额度;同一订单行拆为多条发货明细时累计校验,雪花ID保持字符串。
+
 - 库存台账返回的 `provenance` 是展示字符串;向 EOM 发货接口提交产地时,使用 `purchaseOrigins` 产地编码数组转换为字符串数组。替代料与普通发货物品均需遵守此契约,不能把库存记录中的 `"[]"` 原样提交给 `JSONArray` 字段。
 - 客户抽屉内打开客户历史版本详情时,详情 `ele-modal` 必须设置 `append-to-body`,避免弹窗遮罩受抽屉层叠上下文影响而覆盖弹窗内容。
+- 客户与供应商共用 `saleManage/contact/components/addContactDialog.vue` 的新建并提交入口;保存主档后必须等待新建证照的 `saveOrEdit` 请求全部成功,再开启 `contact_approve` 提交弹窗。证照保存失败须提示并停止提交,避免服务端按已持久化证照校验时误判。

+ 6 - 3
src/views/saleManage/contact/components/addContactDialog.vue

@@ -1793,13 +1793,16 @@ import tabMixins from '@/mixins/tableColumnsMixin';
               });
           } else {
             contactSave(data)
-              .then((id) => {
+              .then(async (id) => {
                 this.loading = false;
                 this.$message.success('新增成功');
-                this.tableCertificateDataList.forEach((item) => {
+                await Promise.all(this.tableCertificateDataList.map((item) => {
                   item['holderId'] = id;
                   item['holder'] = this.form.name;
-                  saveOrEdit(item);
+                  return saveOrEdit(item);
+                })).catch((error) => {
+                  this.$message.error('证书资质保存失败,请重试');
+                  throw error;
                 });
 
                 if (type == 'sub') {

+ 4 - 1
src/views/saleManage/saleOrder/invoice/components/addInvoiceDialog.vue

@@ -596,6 +596,10 @@
             .toString()
         };
 
+        // 编辑初始化也要保留订单明细身份,供重选物品后按原订单行校验额度。
+        data.productList.forEach((item) => {
+          item.orderProductId = item.orderProductId || item.id;
+        });
         this.loading = false;
         this.saleOrderNeedProduce = data.needProduce ?? '';
         this.saleOrderValue = JSON.parse(JSON.stringify(data));
@@ -630,7 +634,6 @@
           if (productList && productList.length > 0) {
             productList.forEach((v) => {
               v.orderTotalCount = v.totalCount;
-              v.orderProductId = v.orderProductId || v.id;
               v.extField = {};
             });
           }

+ 82 - 18
src/views/saleManage/saleOrder/invoice/components/inventoryTable.vue

@@ -109,8 +109,9 @@
               <el-option
                 v-for="item in scope.row.batchNoList || []"
                 :key="item.id"
-                :label="item.batchNo"
+                :label="item.id == 999 ? `${item.batchNo}(无匹配可发库存)` : item.batchNo"
                 :value="item.id"
+                :disabled="item.id == 999"
               >
               </el-option>
             </el-select>
@@ -630,6 +631,7 @@
         form: {
           datasource: []
         },
+        batchLookupPending: 0,
         rules: {},
         columnsVersion: 1
       };
@@ -1202,19 +1204,30 @@
           this.setWarehouseOutStock(index, {});
           return;
         }
-        const stockInfo = await getWarehouseOutStockInfo({
+        const query = {
           warehouseId: row.warehouseId,
           code: row.productCode,
           batchNo: row.batchNo,
           systemBatchNo: row.systemBatchNo,
           colorKey: row.colorKey,
           modelType: row.modelType
-        });
-        this.setWarehouseOutStock(index, stockInfo);
+        };
+        const stockInfo = await getWarehouseOutStockInfo(query);
+        if (this.form.datasource[index] === row &&
+            row.warehouseId == query.warehouseId &&
+            row.batchNo == query.batchNo &&
+            row.systemBatchNo == query.systemBatchNo &&
+            row.colorKey == query.colorKey &&
+            row.modelType == query.modelType) {
+          this.setWarehouseOutStock(index, stockInfo);
+        }
       },
 
       async warehouseChange(index, row, isReset = false) {
         console.log('warehouseChange', index, row.warehouseId, isReset);
+        const warehouseId = row.warehouseId;
+        const colorKey = row.colorKey;
+        const modelType = row.modelType;
         const data = row.warehouseList.find(
           (item) => item.warehouseId == row.warehouseId
         );
@@ -1232,23 +1245,27 @@
           data?.warehouseCode || 0
         );
 
+        if (isReset) {
+          this.$set(row, 'batchStockId', '');
+          this.$set(row, 'batchNo', '');
+          this.$set(row, 'systemBatchNo', '');
+        }
+        const batchStockId = row.batchStockId;
         const tempBatchNoList = await getBatchList({
           warehouseId: data?.warehouseId || '',
           categoryCode: row.productCode,
           colorKey: row.colorKey,
           modelType: row.modelType,
         });
+        if (this.form.datasource[index] !== row || row.warehouseId != warehouseId ||
+            row.colorKey != colorKey || row.modelType != modelType ||
+            row.batchStockId != batchStockId) return;
         this.$set(
           this.form.datasource[index],
           'batchNoList',
           this.dedupeBatchNoList(tempBatchNoList?.list)
         );
 
-        if (isReset) {
-          this.$set(this.form.datasource[index], 'batchStockId', '');
-          this.$set(this.form.datasource[index], 'batchNo', '');
-          this.$set(this.form.datasource[index], 'systemBatchNo', '');
-        }
         await this.refreshWarehouseOutStock(index, this.form.datasource[index]);
       },
 
@@ -1460,6 +1477,8 @@
         console.log(obj, 'obj');
         obj.forEach((item) => {
           item.orderTotalCount = item.totalCount;
+          // 清空选入行ID前保留订单来源,避免换成同一批次后误合并额度。
+          item.orderProductId = item.orderProductId || item.id;
           item.id = '';
         });
         this.putTableValue(copyObj(obj));
@@ -1755,17 +1774,44 @@
               );
               // console.log(this.form.datasource[index]);
             } else {
-              this.setBatchAndWarehouse(item, index);
+              this.batchLookupPending++;
+              this.setBatchAndWarehouse(item, index).then(
+                () => { this.batchLookupPending--; },
+                () => {
+                  this.batchLookupPending--;
+                  if (this.form.datasource[index] === item) {
+                    this.$set(item, 'batchStockId', 999);
+                    this.$set(item, 'batchNoList', [{ id: 999, batchNo: item.batchNo }]);
+                    this.$message.error('批次库存查询失败,请重新打开后重试');
+                  }
+                }
+              );
             }
           }
         });
       },
       async setBatchAndWarehouse(item, index) {
         console.log('333~~~~', index);
+        let warehouseId = item.warehouseId;
+        const batchNo = item.batchNo;
+        const systemBatchNo = item.systemBatchNo;
+        const batchStockId = item.batchStockId;
+        const colorKey = item.colorKey;
+        const modelType = item.modelType;
+        const productId = item.productId;
+        const isCurrent = () => this.form.datasource[index] === item &&
+          item.warehouseId == warehouseId && item.batchNo == batchNo &&
+          item.systemBatchNo == systemBatchNo && item.batchStockId == batchStockId &&
+          item.colorKey == colorKey && item.modelType == modelType &&
+          item.productId == productId;
         // 通过产品编码查仓库
-        const tempWarehouse = await getIdWarehouseList({
+        const tempWarehouse = (await getIdWarehouseList({
           categoryId: item.productId
-        });
+        })) || [];
+        if (!isCurrent()) return;
+        if (warehouseId && !tempWarehouse.some((warehouse) => warehouse.warehouseId == warehouseId)) {
+          tempWarehouse.push({ warehouseId, warehouseName: item.warehouseName || warehouseId });
+        }
         // 有仓库列表
         if (tempWarehouse?.length) {
           console.log('666~~~~', index, tempWarehouse);
@@ -1781,7 +1827,10 @@
                 'warehouseId',
                 this.form.datasource[index]?.warehouseList[0].warehouseId
               );
+              const selectedWarehouseId = item.warehouseId;
               await this.warehouseChange(index, this.form.datasource[index]);
+              if (item.warehouseId != selectedWarehouseId) return;
+              warehouseId = selectedWarehouseId;
             }
           }
 
@@ -1792,18 +1841,22 @@
             modelType: item.modelType,
             size: -1
           });
+          if (!isCurrent()) return;
 
           let tempBatchNoList = this.dedupeBatchNoList(templist1?.list);
           console.log('888~~~~', index, item.batchNo);
 
           // 优先按批次明细ID匹配,无ID时按系统批次和业务批次兼容匹配
-          const batchNoObj = tempBatchNoList.find(
+          const matchingBatches = tempBatchNoList.filter(
             (i) =>
-              (item.batchStockId && i.id == item.batchStockId) ||
-              (!item.batchStockId &&
-                i.batchNo == item.batchNo &&
-                (!item.systemBatchNo || i.systemBatchNo == item.systemBatchNo))
+              i.categoryId == item.productId &&
+              i.warehouseId == item.warehouseId &&
+              (i.colorKey || '') == (item.colorKey || '') &&
+              i.batchNo == item.batchNo &&
+              (!item.systemBatchNo || i.systemBatchNo == item.systemBatchNo) &&
+              (!item.batchStockId || i.id == item.batchStockId)
           );
+          const batchNoObj = matchingBatches.length == 1 ? matchingBatches[0] : null;
 
           if (batchNoObj) {
             this.$set(
@@ -1825,6 +1878,7 @@
             // 批次列表添加不存在的批次号对象
             tempBatchNoList.push({
               batchNo: item.batchNo,
+              systemBatchNo: item.systemBatchNo,
               id: 999,
               measureQuantity: 0
             });
@@ -1834,7 +1888,6 @@
             this.$set(this.form.datasource[index], 'warehouseNum', '');
             this.$set(this.form.datasource[index], 'stockCountBase', '');
             this.$set(this.form.datasource[index], 'availableCountBase', '');
-            this.$set(this.form.datasource[index], 'warehouseId', '');
           }
 
           // // 批次号
@@ -1848,6 +1901,7 @@
             const tempBatchNoList = [
               {
                 batchNo: item.batchNo,
+                systemBatchNo: item.systemBatchNo,
                 id: 999,
                 measureQuantity: 0
               }
@@ -1919,8 +1973,18 @@
         this.$refs.selectStockLedgerDialogRef.open();
       },
       validateForm(callback) {
+        if (this.batchLookupPending) {
+          this.$message.warning('批次库存查询中,请稍后重试');
+          callback(false);
+          return;
+        }
         //开始表单校验
         this.$refs.form.validate((valid, obj) => {
+          if (this.form.datasource.some((item) => item.batchStockId == 999)) {
+            this.$message.warning('订单批次无匹配的可发库存,请核对仓库、批次和颜色');
+            callback(false);
+            return;
+          }
           // 同一订单产品可能拆成多条发货明细,删除明细后只按当前有效行汇总校验。
           const groups = this.form.datasource.reduce((result, item) => {
             const key = item.orderProductId