shish 6 часов назад
Родитель
Сommit
b3514dfdba
1 измененных файлов с 53 добавлено и 29 удалено
  1. 53 29
      biz-ghs/forward/services/ForwardService.php

+ 53 - 29
biz-ghs/forward/services/ForwardService.php

@@ -27,6 +27,13 @@ use common\components\util;
  * 冲销凭证服务(方案A)
  * 职责:同事务创建双侧凭证/明细,处理资金三分支、库存回退、原单汇总缓存、售后转凭证取消;
  * 不插入负销售单/负采购单。ssh 冲销单功能
+ *
+ * —— 原单明细数量设计(xhGhsOrderItem,冲销必须遵守)——
+ * 花材有大小单位(如扎/支),但每一行明细「只会使用其中一个单位」,不会同时有两个单位数量。
+ * - xhUnitType:0=当前为大单位,1=当前为小单位(dict unitType)
+ * - xhNum:当前单位下的数量(唯一规范数量字段)
+ * - num / bigNum / smallNum:历史/非规范字段,冲销校验与累计不要使用
+ * 冲销明细 num、原单 forwardNum 均按 xhNum 同口径累计;回库存时再按 xhUnitType+ratio 换算。
  */
 class ForwardService extends BaseService
 {
@@ -436,7 +443,7 @@ class ForwardService extends BaseService
     }
 
     /**
-     * 从售后明细生成冲销明细
+     * 从售后明细生成冲销明细(数量只用 xhNum + xhUnitType)
      */
     protected static function buildItemsFromRefund($refund)
     {
@@ -447,21 +454,17 @@ class ForwardService extends BaseService
             return [];
         }
         $items = [];
-        $unitSmall = dict::getDict('unitType', 'small');
         foreach ($list as $row) {
-            $unitType = intval($row->xhUnitType ?? 0);
             $xhNum = bcadd((string)($row->xhNum ?? '0'), '0', 2);
-            $itemNum = bcadd((string)($row->itemNum ?? '0'), '0', 2);
-            $bigNum = $unitType === $unitSmall ? '0' : $xhNum;
-            $smallNum = $unitType === $unitSmall ? $xhNum : '0';
             $items[] = [
                 'productId' => intval($row->productId ?? 0),
                 'orderItemId' => intval($row->orderItemId ?? 0),
                 'itemId' => intval($row->itemId ?? 0),
                 'name' => (string)($row->name ?? ''),
-                'num' => $itemNum,
-                'bigNum' => $bigNum,
-                'smallNum' => $smallNum,
+                'num' => $xhNum,
+                'xhNum' => $xhNum,
+                'xhUnitType' => intval($row->xhUnitType ?? 0),
+                'ratio' => bcadd((string)($row->ratio ?? '1'), '0', 2),
                 'unitPrice' => bcadd((string)($row->xhUnitPrice ?? '0'), '0', 2),
                 'price' => bcadd((string)($row->xhUnitPrice ?? '0'), '0', 2),
                 'amount' => bcadd((string)($row->xhPrice ?? '0'), '0', 2),
@@ -471,7 +474,8 @@ class ForwardService extends BaseService
     }
 
     /**
-     * 规范化明细:补全名称/数量/金额,并校验原单明细上限
+     * 规范化明细:数量只认当前单位 xhNum,不用 num/bigNum/smallNum。
+     * 入参优先 raw.xhNum / raw.num(前端当前单位数量);有原单时单位类型以原单 xhUnitType 为准。
      */
     protected static function normalizeItems($items, $order)
     {
@@ -485,6 +489,7 @@ class ForwardService extends BaseService
                 $orderItemMap[intval($oi->id)] = $oi;
             }
         }
+        $unitSmall = dict::getDict('unitType', 'small');
         $result = [];
         foreach ($items as $raw) {
             $productId = intval($raw['productId'] ?? 0);
@@ -501,31 +506,44 @@ class ForwardService extends BaseService
                 $product = ProductClass::getById($productId, true);
                 $name = $product->name ?? '';
             }
-            $bigNum = bcadd((string)($raw['bigNum'] ?? '0'), '0', 2);
-            $smallNum = bcadd((string)($raw['smallNum'] ?? '0'), '0', 2);
+
+            // 当前单位类型:有原单跟原单;自由冲销用入参
+            $xhUnitType = !empty($orderItem)
+                ? intval($orderItem->xhUnitType ?? 0)
+                : intval($raw['xhUnitType'] ?? 0);
             $ratio = bcadd((string)($orderItem->ratio ?? ($raw['ratio'] ?? '1')), '0', 2);
             if (bccomp($ratio, '0', 2) <= 0) {
                 $ratio = '1';
             }
-            // 有大小单位时按售后口径换算 itemNum;否则用入参 num
-            if (bccomp($bigNum, '0', 2) > 0 || bccomp($smallNum, '0', 2) > 0) {
-                $num = ProductClass::mergeItemNum($bigNum, $smallNum, $ratio);
-            } else {
-                $num = bcadd((string)($raw['num'] ?? '0'), '0', 2);
-            }
-            if (bccomp($num, '0', 2) <= 0) {
+
+            // 规范数量:只取当前单位数量(xhNum),忽略 bigNum/smallNum/num 等非规范字段
+            $xhNum = bcadd((string)($raw['xhNum'] ?? ($raw['num'] ?? '0')), '0', 2);
+            if (bccomp($xhNum, '0', 2) <= 0) {
                 util::fail('冲销数量必须大于0');
             }
+
+            // 回库存:大单位直接加 xhNum;小单位按 ratio 换算成库存小数
+            if ($xhUnitType === $unitSmall) {
+                $stockNum = ProductClass::mergeItemNum(0, $xhNum, $ratio);
+                $bigNum = '0';
+                $smallNum = $xhNum;
+            } else {
+                $stockNum = ProductClass::mergeItemNum($xhNum, 0, $ratio);
+                $bigNum = $xhNum;
+                $smallNum = '0';
+            }
+
             $unitPrice = bcadd((string)($raw['unitPrice'] ?? ($raw['price'] ?? '0')), '0', 2);
             $price = bcadd((string)($raw['price'] ?? $unitPrice), '0', 2);
             $amount = bcadd((string)($raw['amount'] ?? '0'), '0', 2);
             if (bccomp($amount, '0', 2) <= 0) {
-                $baseNum = bccomp($bigNum, '0', 2) > 0 ? $bigNum : $num;
-                $amount = bcmul($baseNum, $price, 2);
+                $amount = bcmul($xhNum, $price, 2);
             }
             if (!empty($orderItem)) {
-                $remain = bcsub((string)($orderItem->itemNum ?? '0'), (string)($orderItem->forwardNum ?? '0'), 2);
-                if (bccomp($num, $remain, 2) === 1) {
+                // 可冲销量 = 原单 xhNum − 已冲销 forwardNum(forwardNum 也按 xhNum 累计)
+                $originNum = bcadd((string)($orderItem->xhNum ?? '0'), '0', 2);
+                $remain = bcsub($originNum, (string)($orderItem->forwardNum ?? '0'), 2);
+                if (bccomp($xhNum, $remain, 2) === 1) {
                     util::fail(($name ?: '花材') . '冲销数量超过可冲销量');
                 }
             }
@@ -534,7 +552,10 @@ class ForwardService extends BaseService
                 'orderItemId' => $orderItemId,
                 'itemId' => intval($raw['itemId'] ?? ($orderItem->itemId ?? 0)),
                 'name' => $name,
-                'num' => $num,
+                'num' => $xhNum,
+                'xhNum' => $xhNum,
+                'xhUnitType' => $xhUnitType,
+                'stockNum' => $stockNum,
                 'bigNum' => $bigNum,
                 'smallNum' => $smallNum,
                 'unitPrice' => $unitPrice,
@@ -561,7 +582,8 @@ class ForwardService extends BaseService
         }
         $customName = $custom->name ?? '';
         foreach ($items as $it) {
-            $itemNum = $it['num'];
+            // 回库存必须用换算后的库存数量,不能直接用 xhNum 展示数量
+            $itemNum = $it['stockNum'] ?? $it['num'];
             if (bccomp($itemNum, '0', 2) <= 0) {
                 continue;
             }
@@ -585,7 +607,7 @@ class ForwardService extends BaseService
     }
 
     /**
-     * 累加原销售明细 forwardNum
+     * 累加原销售明细 forwardNum(与 xhNum 同单位:当前下单单位数量)
      */
     protected static function increaseOrderItemForwardNum($items)
     {
@@ -598,13 +620,14 @@ class ForwardService extends BaseService
             if (empty($oi)) {
                 continue;
             }
-            $oi->forwardNum = bcadd((string)($oi->forwardNum ?? '0'), $it['num'], 2);
+            $addNum = $it['xhNum'] ?? $it['num'];
+            $oi->forwardNum = bcadd((string)($oi->forwardNum ?? '0'), (string)$addNum, 2);
             $oi->save(false, ['forwardNum']);
         }
     }
 
     /**
-     * 累加采购明细 forwardNum(按平台 itemId 对齐)
+     * 累加采购明细 forwardNum(按平台 itemId 对齐;数量同 xhNum 口径
      */
     protected static function increaseCgItemForwardNum($items, $cgItemMap)
     {
@@ -618,7 +641,8 @@ class ForwardService extends BaseService
             if (empty($ci)) {
                 continue;
             }
-            $ci->forwardNum = bcadd((string)($ci->forwardNum ?? '0'), $it['num'], 2);
+            $addNum = $it['xhNum'] ?? $it['num'];
+            $ci->forwardNum = bcadd((string)($ci->forwardNum ?? '0'), (string)$addNum, 2);
             $ci->save(false, ['forwardNum']);
         }
     }