From ecae5d047c96511152796e3fc205e65c72738a9b Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 13 五月 2026 11:29:37 +0800
Subject: [PATCH] 销售/采购退货流程问题修复

---
 src/views/salesManagement/returnOrder/components/formDia.vue |  203 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 194 insertions(+), 9 deletions(-)

diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 742b79d..fe0a75c 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -122,7 +122,7 @@
                 placeholder="璇疯緭鍏�" 
               />
             </template>
-            <template #action="{ row, index }">
+            <template #action="{ index }">
               <el-button type="danger" link @click="deleteRow(index)">鍒犻櫎</el-button>
             </template>
           </PIMTable>
@@ -242,8 +242,164 @@
   tableData.value.splice(index, 1);
 };
 
+const sameKey = (a, b) => a != null && b != null && String(a) === String(b);
+
+/** 鎺ュ彛鍙兘鎷嗘垚 shippingProductVoList / productDtoData 涓や唤锛屽彧鍙栧叾涓�浼氱己鎵规銆佹暟閲忕瓑瀛楁 */
+const mergeShippingProductLists = (data) => {
+  const lists = [data?.shippingProductVoList, data?.productDtoData].filter(Array.isArray);
+  if (!lists.length) return [];
+  const map = new Map();
+  for (const list of lists) {
+    for (const p of list) {
+      if (p == null) continue;
+      const key = p.id != null ? String(p.id) : null;
+      if (!key) continue;
+      const prev = map.get(key);
+      map.set(key, prev ? { ...prev, ...p } : { ...p });
+    }
+  }
+  return Array.from(map.values());
+};
+
+const pickShippingLine = (normalized) => {
+  const pid = normalized?.returnSaleLedgerProductId ?? normalized?.id;
+  const sid = normalized?.stockOutRecordId ?? normalized?.shippingProductId;
+  const direct = availableProducts.value.find(
+    (p) =>
+      sameKey(p?.id, pid) ||
+      sameKey(p?.stockOutRecordId, pid) ||
+      sameKey(p?.id, sid) ||
+      sameKey(p?.stockOutRecordId, sid)
+  );
+  if (direct) return direct;
+  const pmid = normalized?.productModelId;
+  if (pmid == null || pmid === "") return undefined;
+  const candidates = availableProducts.value.filter((p) => sameKey(p?.productModelId, pmid));
+  if (!candidates.length) return undefined;
+  if (candidates.length === 1) return candidates[0];
+  const spec = String(normalized?.specificationModel ?? normalized?.model ?? "");
+  if (spec) {
+    const hit = candidates.find((p) => {
+      const ps = String(p?.specificationModel ?? p?.model ?? "");
+      return ps && ps === spec;
+    });
+    if (hit) return hit;
+  }
+  return candidates[0];
+};
+
+const isEmptyText = (v) => v === "" || v == null || v === undefined;
+
+const firstFiniteNumber = (...vals) => {
+  for (const v of vals) {
+    if (v === "" || v == null || v === undefined) continue;
+    const n = Number(v);
+    if (Number.isFinite(n)) return n;
+  }
+  return undefined;
+};
+
+const firstNonEmptyText = (...vals) => {
+  const hit = vals.find((v) => !isEmptyText(v));
+  return hit === undefined ? "" : hit;
+};
+
+/** 璇︽儏鎺ュ彛瀛楁甯镐笉鍏紱{...product,...normalized} 浼氳 normalized 閲岀殑绌轰覆鐩栨帀鍑哄簱琛屼笂鐨勫睍绀哄瓧娈� */
+const mergeShippingLineWithDetail = (product, normalized) => {
+  const row = { ...product, ...normalized };
+  row.outboundBatches = firstNonEmptyText(
+    row.outboundBatches,
+    product?.outboundBatches,
+    product?.shippingNo,
+    product?.outboundNo,
+    normalized?.outboundBatches,
+    normalized?.outboundNo,
+    normalized?.shippingNo
+  );
+  row.batchNo = firstNonEmptyText(
+    row.batchNo,
+    product?.batchNo,
+    product?.batchNumber,
+    product?.lotNo,
+    product?.batchCode,
+    product?.shippingBatchNo,
+    normalized?.batchNo,
+    normalized?.batchNumber,
+    normalized?.lotNo,
+    normalized?.shippingBatchNo
+  );
+  const stock = firstFiniteNumber(
+    row.stockOutNum,
+    product?.stockOutNum,
+    product?.totalQuantity,
+    product?.shippingQuantity,
+    product?.deliveryQuantity,
+    product?.quantity,
+    product?.outQuantity,
+    normalized?.stockOutNum,
+    normalized?.totalQuantity,
+    normalized?.shippingQuantity,
+    normalized?.deliveryQuantity
+  );
+  if (stock !== undefined) row.stockOutNum = stock;
+  const un = firstFiniteNumber(
+    row.unQuantity,
+    product?.unQuantity,
+    product?.remainingQuantity,
+    product?.noReturnQuantity,
+    product?.canReturnQuantity,
+    product?.availableReturnNum,
+    normalized?.unQuantity,
+    normalized?.remainingQuantity,
+    normalized?.noReturnQuantity,
+    normalized?.canReturnQuantity
+  );
+  if (un !== undefined) row.unQuantity = un;
+  else {
+    const s = Number(row.stockOutNum);
+    const ret = Number(row.totalReturnNum ?? 0);
+    if (Number.isFinite(s) && s >= 0 && Number.isFinite(ret) && ret >= 0) {
+      row.unQuantity = Math.max(0, s - ret);
+    }
+  }
+  const returned = firstFiniteNumber(
+    row.totalReturnNum,
+    product?.totalReturnNum,
+    product?.totalReturnedNum,
+    normalized?.totalReturnNum,
+    normalized?.totalReturnedNum
+  );
+  if (returned !== undefined) row.totalReturnNum = returned;
+  else if (isEmptyText(row.totalReturnNum)) row.totalReturnNum = 0;
+  if (isEmptyText(row.unit)) {
+    row.unit = firstNonEmptyText(product?.unit, normalized?.unit);
+  }
+  if (isEmptyText(row.productCategory)) {
+    row.productCategory = firstNonEmptyText(
+      normalized?.productCategory,
+      normalized?.productName,
+      product?.productCategory,
+      product?.productName
+    );
+  }
+  if (isEmptyText(row.specificationModel)) {
+    row.specificationModel = firstNonEmptyText(
+      normalized?.specificationModel,
+      normalized?.model,
+      product?.specificationModel,
+      product?.model
+    );
+  }
+  return row;
+};
+
 const normalizeDetailRow = (raw) => {
-  const productId = raw?.returnSaleLedgerProductId ?? raw?.saleLedgerProductId ?? raw?.id;
+  const ledgerId =
+    raw?.returnSaleLedgerProductId ??
+    raw?.saleLedgerProductId ??
+    raw?.stockOutRecordId ??
+    raw?.shippingProductId;
+  const productId = ledgerId ?? raw?.id;
   const returnSaleProductId = raw?.returnSaleProductId ?? raw?.id;
   const num = Number(raw?.num ?? raw?.returnQuantity ?? 0);
   return {
@@ -252,6 +408,29 @@
     returnSaleProductId,
     returnSaleLedgerProductId: productId,
     productModelId: raw?.productModelId,
+    stockOutRecordId: raw?.stockOutRecordId,
+    shippingProductId: raw?.shippingProductId,
+    productCategory: raw?.productCategory ?? raw?.productName ?? raw?.productTypeName ?? "",
+    specificationModel: raw?.specificationModel ?? raw?.model ?? raw?.specModel ?? "",
+    outboundBatches: raw?.outboundBatches ?? raw?.outboundNo ?? raw?.shippingNo,
+    batchNo:
+      raw?.batchNo ??
+      raw?.batchNumber ??
+      raw?.lotNo ??
+      raw?.batchCode ??
+      raw?.shippingBatchNo,
+    stockOutNum:
+      raw?.stockOutNum ??
+      raw?.totalQuantity ??
+      raw?.shippingQuantity ??
+      raw?.deliveryQuantity ??
+      raw?.quantity,
+    totalReturnNum: raw?.totalReturnNum ?? raw?.totalReturnedNum,
+    unQuantity:
+      raw?.unQuantity ??
+      raw?.remainingQuantity ??
+      raw?.noReturnQuantity ??
+      raw?.canReturnQuantity,
     num,
     returnQuantity: Number.isFinite(num) ? num : 0,
     price: Number(raw?.taxInclusiveUnitPrice ?? raw?.price ?? 0),
@@ -263,7 +442,6 @@
 
 const setFormForEdit = async (row) => {
   const res = await returnManagementGetById({ returnManagementId: row?.id });
-  console.log("res", res);
   const detail = res?.data ?? res ?? {};
 
   Object.assign(form.value, detail);
@@ -285,11 +463,18 @@
   tableData.value = Array.isArray(list)
     ? list.map((raw) => {
         const normalized = normalizeDetailRow(raw);
-        const product = availableProducts.value.find((p) => p.id === normalized.id);
-        return product ? { ...product, ...normalized } : normalized;
+        const product = pickShippingLine(normalized);
+        return product ? mergeShippingLineWithDetail(product, normalized) : normalized;
       })
     : [];
-  
+
+  const headerShipNo = detail?.shippingNo ?? form.value?.shippingNo;
+  if (headerShipNo && Array.isArray(tableData.value) && tableData.value.length) {
+    tableData.value = tableData.value.map((r) =>
+      isEmptyText(r.outboundBatches) ? { ...r, outboundBatches: headerShipNo } : r
+    );
+  }
+
   calculateTotalRefund();
 };
 
@@ -423,8 +608,7 @@
     // If backend returns project info, set it
     if (res.data.projectId) form.value.projectId = res.data.projectId;
     
-    availableProducts.value =
-      res.data.shippingProductVoList || [];
+    availableProducts.value = mergeShippingProductLists(res.data);
     if (clearTable) tableData.value = [];
   }
 };
@@ -515,8 +699,9 @@
         amount: "0.00",
         isQuality: 2,
         remark: "",
+        productCategory: product.productCategory ?? product.productName ?? "",
         productName: product.productName,
-        specificationModel: product.specificationModel,
+        specificationModel: product.specificationModel ?? product.model ?? "",
         unit: product.unit,
         stockOutNum: product.stockOutNum,
         totalReturnNum: product.totalReturnNum,

--
Gitblit v1.9.3