Sfoglia il codice sorgente

Merge branch 'redesign‌-260706' into dev

shish 1 giorno fa
parent
commit
7aaa1acb53

+ 24 - 20
app-ghs/controllers/ConsoleController.php

@@ -116,6 +116,23 @@ class ConsoleController extends BaseController
         ]);
     }
 
+    /**
+     * 汇总各渠道收入金额(与 kdIncome「合计」一致,不含采购/采购隔天)
+     * @param array $return StatKdClass::eachChannelIncome 返回值
+     * @return float
+     */
+    private static function sumChannelIncomeAmount($return)
+    {
+        $incomeList = $return['incomeList'] ?? [];
+        $totalIncome = '0.00';
+        if (!empty($incomeList)) {
+            foreach ($incomeList as $item) {
+                $totalIncome = bcadd($totalIncome, $item['amount'] ?? 0, 2);
+            }
+        }
+        return floatval($totalIncome);
+    }
+
     /**
      * 昨日各渠道收入合计(与 stat-kd/profile、kdIncome 页「合计」口径一致)
      */
@@ -131,15 +148,7 @@ class ConsoleController extends BaseController
         ]));
         $contain = intval(Yii::$app->request->get('contain', 0));
         $return = StatKdClass::eachChannelIncome($this->mainId, $this->shop, $contain);
-        $incomeList = $return['incomeList'] ?? [];
-        $totalIncome = '0.00';
-        if (!empty($incomeList)) {
-            foreach ($incomeList as $item) {
-                $amount = $item['amount'] ?? 0;
-                $totalIncome = bcadd($totalIncome, $amount, 2);
-            }
-        }
-        util::success(['income' => floatval($totalIncome)]);
+        util::success(['income' => self::sumChannelIncomeAmount($return)]);
     }
 
     //今日概况 ssh 20220723
@@ -176,18 +185,13 @@ class ConsoleController extends BaseController
         //$notice[] = ['title' => '有急事请连续打二次电话 15280215347', 'action' => '', 'page' => ''];
 
         $mainId = $this->mainId;
+        // 概况仍用 profile(订单数/支出等);收入数字与 kdIncome 对齐,见 index_show_income
         $respond = StatSaleClass::profile($mainId);
-        $incomeList = $respond['income'] ?? [];
-        $todaySale = 0;
-        if (!empty($incomeList)) {
-            //这里有二个地方同时要修改,请搜索关键词:index_show_income
-            foreach ($incomeList as $item) {
-                if (isset($item['id']) && $item['id'] == 'allot') {
-                    continue;
-                }
-                $todaySale = bcadd($todaySale, $item['amount'], 2);
-            }
-        }
+        // 工作台「收入」= 各渠道销售收入(含销售隔天扣减),不含采购/采购隔天;与 /stat-kd/profile、昨日收入同口径
+        // 关键词:index_show_income(ShopController 门店列表 todaySale 同步跳过 cgNextDay)
+        $todaySale = self::sumChannelIncomeAmount(
+            StatKdClass::eachChannelIncome($mainId, $this->shop, 0)
+        );
         $expendList = $respond['expend'] ?? [];
         $todayOut = 0;
         if (!empty($expendList)) {

+ 53 - 4
app-ghs/controllers/PurchaseOrderController.php

@@ -2,6 +2,7 @@
 
 namespace ghs\controllers;
 
+use bizGhs\cg\classes\CgPurchaseNextDayClass;
 use biz\ghs\classes\GhsClass;
 use biz\sj\classes\SjClass;
 use bizGhs\book\classes\BookItemClass;
@@ -939,7 +940,10 @@ class PurchaseOrderController extends BaseController
         util::complete('修改成功');
     }
 
-    //应付款统计 ssh 20240528
+    /**
+     * 应付统计:按入库日汇总。
+     * originAmount=未扣隔天;nextDayAmount=隔天售后;amount=已扣隔天(净额)。
+     */
     public function actionDueList()
     {
         $get = Yii::$app->request->get();
@@ -965,22 +969,62 @@ class PurchaseOrderController extends BaseController
         $cgWhere['entryTime'] = ['between', [$currentStartTime, $currentEndTime]];
         $cgList = PurchaseOrderClass::getAllByCondition($cgWhere, null, '*');
         $list = [];
+        $totalOriginAmount = 0;
         $totalAmount = 0;
+        $nextDayDeduct = '0.00';
         if (!empty($cgList)) {
             foreach ($cgList as $cgInfo) {
                 $actPrice = $cgInfo['actPrice'] ?? 0;
                 $ghsId = $cgInfo['ghsId'] ?? 0;
                 if (isset($list[$ghsId])) {
+                    $list[$ghsId]['originAmount'] = bcadd($list[$ghsId]['originAmount'], $actPrice, 2);
                     $list[$ghsId]['amount'] = bcadd($list[$ghsId]['amount'], $actPrice, 2);
                     $list[$ghsId]['num'] = bcadd($list[$ghsId]['num'], 1);
                 } else {
                     $name = $ghsList[$ghsId] && $ghsList[$ghsId]['name'] ? $ghsList[$ghsId]['name'] : '未命名';
-                    $list[$ghsId] = ['id' => $ghsId, 'name' => $name, 'amount' => $actPrice, 'num' => 1];
+                    $list[$ghsId] = [
+                        'id' => $ghsId,
+                        'name' => $name,
+                        'originAmount' => $actPrice,
+                        'amount' => $actPrice,
+                        'num' => 1,
+                        'nextDayAmount' => '0.00',
+                    ];
                 }
+                $totalOriginAmount = bcadd($totalOriginAmount, $actPrice, 2);
                 $totalAmount = bcadd($totalAmount, $actPrice, 2);
             }
-            $list = array_values($list);
         }
+
+        // 隔天售后:只扣 amount,originAmount 保持未扣口径
+        $nextMap = CgPurchaseNextDayClass::sumAmountGroupByGhs($mainId, $currentStartTime, $currentEndTime);
+        foreach ($nextMap as $ghsId => $amt) {
+            if (bccomp((string)$amt, '0', 2) <= 0) {
+                continue;
+            }
+            if (!isset($list[$ghsId])) {
+                $list[$ghsId] = [
+                    'id' => $ghsId,
+                    'name' => $ghsList[$ghsId]['name'] ?? '未命名',
+                    'originAmount' => '0.00',
+                    'amount' => '0.00',
+                    'num' => 0,
+                    'nextDayAmount' => '0.00',
+                ];
+            }
+            if (!isset($list[$ghsId]['originAmount'])) {
+                $list[$ghsId]['originAmount'] = (string)($list[$ghsId]['amount'] ?? '0');
+            }
+            if (!isset($list[$ghsId]['nextDayAmount'])) {
+                $list[$ghsId]['nextDayAmount'] = '0.00';
+            }
+            $list[$ghsId]['amount'] = bcsub((string)$list[$ghsId]['amount'], (string)$amt, 2);
+            $list[$ghsId]['nextDayAmount'] = bcadd((string)$list[$ghsId]['nextDayAmount'], (string)$amt, 2);
+            $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
+            $nextDayDeduct = bcadd($nextDayDeduct, (string)$amt, 2);
+        }
+        $list = array_values($list);
+
         if ($export == 1) {
             if (empty($list)) {
                 util::fail('没有数据需要导出');
@@ -990,7 +1034,12 @@ class PurchaseOrderController extends BaseController
             PurchaseOrderClass::exportDueList($list, $mainId);
             util::stop();
         }
-        util::success(['list' => $list, 'totalAmount' => $totalAmount]);
+        util::success([
+            'list' => $list,
+            'totalOriginAmount' => $totalOriginAmount,
+            'totalAmount' => $totalAmount,
+            'nextDayDeduct' => floatval($nextDayDeduct),
+        ]);
     }
 
     //修改入库时间 ssh 20240511

+ 3 - 2
app-ghs/controllers/ShopController.php

@@ -575,9 +575,10 @@ class ShopController extends BaseController
                 }
                 $todaySale = 0;
                 if (!empty($incomeList)) {
+                    // 与工作台收入口径对齐:不算调拨出库、不算采购隔天退款(关键词 index_show_income)
                     foreach ($incomeList as $item) {
-                        //调拨出库暂时不算到收入里去
-                        if (isset($item['id']) && $item['id'] == 'allot') {
+                        $id = $item['id'] ?? '';
+                        if ($id === 'allot' || $id === 'cgNextDay') {
                             continue;
                         }
                         $todaySale = bcadd($todaySale, $item['amount'], 2);

+ 6 - 0
app-ghs/controllers/StatCgGhsController.php

@@ -172,6 +172,12 @@ class StatCgGhsController extends BaseController
             $totalActPrice = bcsub((string)$totalActPrice, (string)$amt, 2);
             $totalTkPrice = bcadd((string)$totalTkPrice, (string)$amt, 2);
         }
+        // 隔天仅退款并入「仅退款」合计(与小程序供货业绩扣减口径一致)
+        $totalOnlyTkPrice = bcadd(
+            (string)$totalOnlyTkPrice,
+            CgPurchaseNextDayClass::sumMoneyOnlyAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
+            2
+        );
 
         // 有入库单时补齐本主账号下全部供货商行(与旧逻辑一致)
         if (!empty($orderList)) {

+ 14 - 94
app-ghs/controllers/StatItemController.php

@@ -9,9 +9,6 @@ use bizGhs\order\classes\NextDayRefundClass;
 use bizGhs\product\classes\ProductClass;
 use bizGhs\shop\classes\ShopAdminClass;
 use bizGhs\stat\classes\StatSaleClass;
-use bizHd\order\classes\OrderClass as HdOrderClass;
-use bizHd\order\classes\OrderItemClass as HdOrderItemClass;
-use bizHd\refund\classes\HdNextDayRefundClass;
 use common\components\arrayUtil;
 use common\components\dateUtil;
 use common\components\noticeUtil;
@@ -74,7 +71,7 @@ class StatItemController extends BaseController
         $staffId = $get['staffId'] ?? 0;
 
         $list = OrderClass::getAllByCondition($where, null, '*');
-        $productInfo = ProductClass::getAllByCondition(['mainId' => $this->mainId], null, 'id,name,py,cgStaffId,cost,avCost', 'id');
+        $productInfo = ProductClass::getAllByCondition(['mainId' => $this->mainId], null, 'id,name,py,cgStaffId', 'id');
         $stat = [];
         $totalAmount = 0;
         $totalNum = 0;
@@ -149,95 +146,11 @@ class StatItemController extends BaseController
             }
         }
 
-        // 零售开单花材:与批发共用库存花材 id(xhOrderItem.itemId = Product.id)
-        $hdWhere = [
-            'mainId' => $this->mainId,
-            'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]],
-            'payTime' => ['between', [$currentStartTime, $currentEndTime]],
-        ];
-        $hdList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
-        if (!empty($hdList)) {
-            foreach ($hdList as $hdOrder) {
-                if (intval($hdOrder['forward'] ?? 0) === 1) {
-                    continue;
-                }
-                $mainPay = bcsub(
-                    (string)($hdOrder['mainPay'] ?? '0'),
-                    (string)($hdOrder['tkPrice'] ?? '0'),
-                    2
-                );
-                $cash = bcadd((string)($hdOrder['cash'] ?? '0'), '0', 2);
-                if (bccomp(bcadd($mainPay, $cash, 2), '0', 2) <= 0) {
-                    continue;
-                }
-                $orderSn = $hdOrder['orderSn'] ?? '';
-                $itemList = HdOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
-                if (empty($itemList)) {
-                    continue;
-                }
-                foreach ($itemList as $item) {
-                    $productId = intval($item->itemId ?? 0);
-                    if ($productId <= 0) {
-                        continue;
-                    }
-                    $name = $productInfo[$productId]['name'] ?? '';
-                    $py = $productInfo[$productId]['py'] ?? '';
-                    if (!empty($staffId)) {
-                        $currentCgStaffId = $productInfo[$productId]['cgStaffId'] ?? 0;
-                        if ($staffId != $currentCgStaffId) {
-                            continue;
-                        }
-                    }
-                    $num = HdNextDayRefundClass::payDayRemainNum(
-                        $item->num ?? 0,
-                        $item->refundNum ?? 0,
-                        $item->nextRefundNum ?? 0
-                    );
-                    if (bccomp((string)$num, '0', 2) <= 0) {
-                        continue;
-                    }
-                    $unitPrice = $item->unitPrice ?? 0;
-                    $unitCost = $item->cost ?? null;
-                    if ($unitCost === null || $unitCost === '') {
-                        $unitCost = $productInfo[$productId]['avCost']
-                            ?? ($productInfo[$productId]['cost'] ?? 0);
-                    }
-                    $unitGross = bcsub((string)$unitPrice, (string)$unitCost, 2);
-                    $currentAmount = bcmul((string)$unitPrice, (string)$num, 2);
-                    $currentGross = bcmul($unitGross, (string)$num, 2);
-
-                    $totalNum = bcadd($totalNum, $num, 2);
-                    $totalAmount = bcadd($totalAmount, $currentAmount, 2);
-                    $totalMl = bcadd($totalMl, $currentGross, 2);
-
-                    $stat[$productId]['productId'] = $productId;
-                    $stat[$productId]['name'] = $name;
-                    $stat[$productId]['py'] = $py;
-                    if (isset($stat[$productId]['num'])) {
-                        $stat[$productId]['num'] = bcadd($stat[$productId]['num'], $num, 2);
-                    } else {
-                        $stat[$productId]['num'] = $num;
-                    }
-                    if (isset($stat[$productId]['amount'])) {
-                        $stat[$productId]['amount'] = bcadd($stat[$productId]['amount'], $currentAmount, 2);
-                    } else {
-                        $stat[$productId]['amount'] = $currentAmount;
-                    }
-                    if (isset($stat[$productId]['gross'])) {
-                        $stat[$productId]['gross'] = bcadd($stat[$productId]['gross'], $currentGross, 2);
-                    } else {
-                        $stat[$productId]['gross'] = $currentGross;
-                    }
-                }
-            }
-        }
-
-        // 通过日:退货扣数量+金额;仅退款只扣金额;无当日销量的花材也建负行(批发+零售)
+        // 通过日:退货扣数量+金额;仅退款只扣金额;无当日销量的花材也建负行
+        $nextDayDeduct = '0.00';
         $deductMaps = [
             NextDayRefundClass::sumItemByProduct($this->mainId, $currentStartTime, $currentEndTime),
             NextDayRefundClass::sumMoneyOnlyAmountByProduct($this->mainId, $currentStartTime, $currentEndTime),
-            HdNextDayRefundClass::sumItemByProduct($this->mainId, $currentStartTime, $currentEndTime),
-            HdNextDayRefundClass::sumMoneyOnlyAmountByProduct($this->mainId, $currentStartTime, $currentEndTime),
         ];
         foreach ($deductMaps as $deductMap) {
             foreach ($deductMap as $pid => $row) {
@@ -265,14 +178,15 @@ class StatItemController extends BaseController
                 $totalNum = bcsub((string)$totalNum, $subNum, 2);
                 $totalAmount = bcsub((string)$totalAmount, $subAmt, 2);
                 $totalMl = bcsub((string)$totalMl, $subAmt, 2);
+                $nextDayDeduct = bcadd($nextDayDeduct, $subAmt, 2);
             }
         }
 
-        //增加毛利率
+        //增加毛利率(金额为负时不计算毛利率,避免除零/误导)
         foreach ($stat as $key => $val) {
             $profit = $val['gross'] ?? 0;
             $price = $val['amount'] ?? 0;
-            if ($price > 0) {
+            if (bccomp((string)$price, '0', 2) > 0) {
                 $mll = bcdiv($profit, $price, 3);
                 $mll = bcmul($mll, 100);
                 $mll = round($mll, 1);
@@ -291,7 +205,7 @@ class StatItemController extends BaseController
         if ($sort == 'mll') {
             $rank = 'mll';
         }
-        $stat = arrayUtil::arraySort($stat, $rank);
+        $stat = array_values(arrayUtil::arraySort($stat, $rank));
 
         $export = $get['export'] ?? 0;
         if ($export == 1) {
@@ -299,7 +213,13 @@ class StatItemController extends BaseController
             StatSaleClass::exportItemSale($stat, $mainId);
         }
 
-        util::success(['list' => $stat, 'totalAmount' => floatval($totalAmount), 'totalNum' => floatval($totalNum), 'totalMl' => $totalMl,]);
+        util::success([
+            'list' => $stat,
+            'totalAmount' => floatval($totalAmount),
+            'totalNum' => floatval($totalNum),
+            'totalMl' => floatval($totalMl),
+            'nextDayDeduct' => floatval($nextDayDeduct),
+        ]);
 
     }
 

+ 19 - 20
biz-ghs/order/classes/OrderClass.php

@@ -2895,36 +2895,35 @@ XL;
 
         $objPHPExcel->getActiveSheet()->setCellValue('A1', 'ID');
         $objPHPExcel->getActiveSheet()->setCellValue('B1', '名称');
-        $objPHPExcel->getActiveSheet()->setCellValue('C1', '金额');
-        $objPHPExcel->getActiveSheet()->setCellValue('D1', '订单数');
+        $objPHPExcel->getActiveSheet()->setCellValue('C1', '未扣隔天金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('D1', '隔天售后金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('E1', '已扣隔天金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('F1', '订单数');
 
         //设置宽度
         $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(25);
-        $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
-        $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(20);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('E')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('F')->setWidth(15);
         //加粗
-        $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
-        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
-        $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
-        $objPHPExcel->getActiveSheet()->getStyle('D1')->getFont()->setSize(9)->setBold(true);
-
-        $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-        $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-        $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-        $objPHPExcel->getActiveSheet()->getStyle('D1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
+        foreach (['A1', 'B1', 'C1', 'D1', 'E1', 'F1'] as $cell) {
+            $objPHPExcel->getActiveSheet()->getStyle($cell)->getFont()->setSize(9)->setBold(true);
+            $objPHPExcel->getActiveSheet()->getStyle($cell)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
+        }
 
         $baseRow = 2;
         foreach ($list as $key => $custom) {
             $i = $baseRow + $key;
             $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['id']);
             $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['name']);
-            $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['amount']);
-            $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['num']);
-            //居左
-            $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-            $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-            $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
-            $objPHPExcel->getActiveSheet()->getStyle('D' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
+            $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['originAmount'] ?? $custom['amount']);
+            $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['nextDayAmount'] ?? 0);
+            $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['amount']);
+            $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['num']);
+            foreach (['A', 'B', 'C', 'D', 'E', 'F'] as $col) {
+                $objPHPExcel->getActiveSheet()->getStyle($col . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
+            }
         }
         $fileName = '应收统计-' . date("m-d");
         $objPHPExcel->getActiveSheet()->setTitle($fileName);

+ 19 - 14
biz-ghs/order/classes/PurchaseOrderClass.php

@@ -1919,30 +1919,35 @@ class PurchaseOrderClass extends BaseClass
 
         $objPHPExcel->getActiveSheet()->setCellValue('A1', 'ID');
         $objPHPExcel->getActiveSheet()->setCellValue('B1', '名称');
-        $objPHPExcel->getActiveSheet()->setCellValue('C1', '金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('C1', '未扣隔天金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('D1', '隔天售后金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('E1', '已扣隔天金额');
+        $objPHPExcel->getActiveSheet()->setCellValue('F1', '订单数');
 
         //设置宽度
         $objPHPExcel->getActiveSheet()->getColumnDimension('B')->setWidth(25);
-        $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(20);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('C')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('D')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('E')->setWidth(18);
+        $objPHPExcel->getActiveSheet()->getColumnDimension('F')->setWidth(15);
         //加粗
-        $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setSize(9)->setBold(true);
-        $objPHPExcel->getActiveSheet()->getStyle('B1')->getFont()->setSize(9)->setBold(true);
-        $objPHPExcel->getActiveSheet()->getStyle('C1')->getFont()->setSize(9)->setBold(true);
-
-        $objPHPExcel->getActiveSheet()->getStyle('A1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
-        $objPHPExcel->getActiveSheet()->getStyle('B1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
-        $objPHPExcel->getActiveSheet()->getStyle('C1')->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
+        foreach (['A1', 'B1', 'C1', 'D1', 'E1', 'F1'] as $cell) {
+            $objPHPExcel->getActiveSheet()->getStyle($cell)->getFont()->setSize(9)->setBold(true);
+            $objPHPExcel->getActiveSheet()->getStyle($cell)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
+        }
 
         $baseRow = 2;
         foreach ($list as $key => $custom) {
             $i = $baseRow + $key;
             $objPHPExcel->getActiveSheet()->setCellValue('A' . $i, $custom['id']);
             $objPHPExcel->getActiveSheet()->setCellValue('B' . $i, $custom['name']);
-            $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['amount']);
-            //居左
-            $objPHPExcel->getActiveSheet()->getStyle('A' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
-            $objPHPExcel->getActiveSheet()->getStyle('B' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
-            $objPHPExcel->getActiveSheet()->getStyle('C' . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
+            $objPHPExcel->getActiveSheet()->setCellValue('C' . $i, $custom['originAmount'] ?? $custom['amount']);
+            $objPHPExcel->getActiveSheet()->setCellValue('D' . $i, $custom['nextDayAmount'] ?? 0);
+            $objPHPExcel->getActiveSheet()->setCellValue('E' . $i, $custom['amount']);
+            $objPHPExcel->getActiveSheet()->setCellValue('F' . $i, $custom['num'] ?? 0);
+            foreach (['A', 'B', 'C', 'D', 'E', 'F'] as $col) {
+                $objPHPExcel->getActiveSheet()->getStyle($col . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_LEFT);
+            }
         }
         $fileName = '应付统计-' . date("m-d");
         $objPHPExcel->getActiveSheet()->setTitle($fileName);

+ 97 - 320
biz-ghs/stat/classes/StatSaleClass.php

@@ -20,11 +20,9 @@ use bizGhs\product\classes\ProductClass;
 use bizGhs\staff\classes\SalaryClass;
 use bizHd\goods\classes\PlantCgClass;
 use bizHd\order\classes\OrderClass as HdOrderClass;
-use bizHd\order\classes\OrderItemClass as HdOrderItemClass;
 use bizGhs\order\classes\OrderClass;
 use bizHd\purchase\classes\PurchaseClass;
 use bizHd\refund\classes\HdRefundClass;
-use bizHd\refund\classes\HdNextDayRefundClass;
 use common\components\arrayUtil;
 use common\components\dateUtil;
 use common\components\dict;
@@ -122,10 +120,7 @@ class StatSaleClass extends BaseClass
         return ['list' => $ghsOrderList];
     }
 
-    /**
-     * 客户业绩:按客户汇总笔数/扎数/金额/成本/利润,供 ghsApp customSale、/stat-kh-cg/profile 使用。
-     * totalCount 为总扎数(含隔天售后扣减),与各行 count 口径一致。
-     */
+    //客户下单榜 ssh 20230502
     public static function statCustomCg($mainId)
     {
         $get = Yii::$app->request->get();
@@ -154,7 +149,6 @@ class StatSaleClass extends BaseClass
         $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
         $totalAmount = 0;
         $totalNum = 0;
-        $totalCount = 0;
         $totalProfit = 0;
         $totalCost = 0;
         if (!empty($ghsOrderList)) {
@@ -181,7 +175,6 @@ class StatSaleClass extends BaseClass
                 $customName = $customList[$customId]['name'] ?? '';
                 $py = $customList[$customId]['py'] ?? '';
                 $totalNum++;
-                $totalCount = bcadd($totalCount, $count, 2);
                 $totalAmount = bcadd($totalAmount, $actPrice, 2);
                 $totalProfit = bcadd($totalProfit, $profit, 2);
                 $totalCost = bcadd($totalCost, $cost, 2);
@@ -198,7 +191,6 @@ class StatSaleClass extends BaseClass
                         'customId' => $customId,
                         'customName' => $customName,
                         'py' => $py,
-                        'source' => 'ghs',
                         'num' => 1,
                         'count' => $count,
                         'amount' => $actPrice,
@@ -211,99 +203,12 @@ class StatSaleClass extends BaseClass
                 }
             }
         }
-
-        // 零售开单:与批发共用客户业绩;key 用 hd_{id},名称加「零售-」前缀
-        $productCostMap = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,cost,avCost', 'id');
-        $hdWhere = [
-            'mainId' => $mainId,
-            'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]],
-            'payTime' => ['between', [$currentStartTime, $currentEndTime]],
-        ];
-        $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
-        if (!empty($hdOrderList)) {
-            foreach ($hdOrderList as $hdOrder) {
-                $forward = intval($hdOrder['forward'] ?? 0);
-                if ($forward === 1) {
-                    // 售后付款属支出,不进客户业绩
-                    continue;
-                }
-                $status = intval($hdOrder['status'] ?? 0);
-                if ($status === HdOrderClass::ORDER_STATUS_UN_PAY || $status === HdOrderClass::ORDER_STATUS_CANCEL) {
-                    continue;
-                }
-                $mainPay = bcadd((string)($hdOrder['mainPay'] ?? '0'), '0', 2);
-                $tkPrice = bcadd((string)($hdOrder['tkPrice'] ?? '0'), '0', 2);
-                $cash = bcadd((string)($hdOrder['cash'] ?? '0'), '0', 2);
-                // 当天退款已从 mainPay 口径扣 tkPrice;现金另计(对齐渠道收入)
-                $actPrice = bcadd(bcsub($mainPay, $tkPrice, 2), $cash, 2);
-                if (bccomp($actPrice, '0', 2) <= 0) {
-                    continue;
-                }
-                $customId = intval($hdOrder['customId'] ?? 0);
-                $rowKey = HdNextDayRefundClass::customStatKey($customId);
-                $rawName = trim((string)($hdOrder['customName'] ?? ''));
-                $orderSn = $hdOrder['orderSn'] ?? '';
-
-                // 扎数、成本:按支付日净销量(隔天部分 nextRefundNum 留到通过日扣)
-                $count = '0.00';
-                $cost = '0.00';
-                $orderItemList = HdOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
-                if (!empty($orderItemList)) {
-                    foreach ($orderItemList as $orderItem) {
-                        $remainNum = HdNextDayRefundClass::payDayRemainNum(
-                            $orderItem->num ?? 0,
-                            $orderItem->refundNum ?? 0,
-                            $orderItem->nextRefundNum ?? 0
-                        );
-                        $count = bcadd($count, $remainNum, 2);
-                        $productId = intval($orderItem->itemId ?? 0);
-                        $unitCost = $orderItem->cost ?? null;
-                        if ($unitCost === null || $unitCost === '') {
-                            $unitCost = $productCostMap[$productId]['avCost']
-                                ?? ($productCostMap[$productId]['cost'] ?? 0);
-                        }
-                        $cost = bcadd($cost, bcmul($remainNum, (string)$unitCost, 2), 2);
-                    }
-                }
-                $profit = bcsub($actPrice, $cost, 2);
-                $totalNum++;
-                $totalCount = bcadd($totalCount, $count, 2);
-                $totalAmount = bcadd($totalAmount, $actPrice, 2);
-                $totalProfit = bcadd($totalProfit, $profit, 2);
-                $totalCost = bcadd($totalCost, $cost, 2);
-
-                if (isset($arr[$rowKey])) {
-                    $arr[$rowKey]['num']++;
-                    $arr[$rowKey]['amount'] = bcadd($arr[$rowKey]['amount'], $actPrice, 2);
-                    $arr[$rowKey]['count'] = bcadd($arr[$rowKey]['count'], $count, 2);
-                    $arr[$rowKey]['orderPrice'] = bcadd($arr[$rowKey]['orderPrice'], $mainPay, 2);
-                    $arr[$rowKey]['tkPrice'] = bcadd($arr[$rowKey]['tkPrice'], $tkPrice, 2);
-                    $arr[$rowKey]['cost'] = bcadd($arr[$rowKey]['cost'], $cost, 2);
-                    $arr[$rowKey]['profit'] = bcadd($arr[$rowKey]['profit'], $profit, 2);
-                } else {
-                    $arr[$rowKey] = [
-                        'customId' => $customId,
-                        'customName' => HdNextDayRefundClass::displayCustomName($rawName, $customId),
-                        'py' => '',
-                        'source' => 'hd',
-                        'num' => 1,
-                        'count' => $count,
-                        'amount' => $actPrice,
-                        'levelName' => '',
-                        'orderPrice' => $mainPay,
-                        'tkPrice' => $tkPrice,
-                        'cost' => $cost,
-                        'profit' => $profit,
-                    ];
-                }
-            }
-        }
-
         // 隔天售后:按通过日扣金额/扎数;无当日开单也建负行(笔数不减)
-        // ghs 批发客户用原 customId;hd 零售用 hd_{id} 隔离,避免与 xhGhsCustom 撞号
         $fwdMap = NextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
         $qtyMap = NextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
         $cidKeys = array_unique(array_merge(array_keys($fwdMap), array_keys($qtyMap)));
+        // 与按客户扣减同一套数据汇总,避免 passTime 空值导致合计为 0
+        $nextDayDeduct = '0.00';
         foreach ($cidKeys as $cid) {
             $amt = $fwdMap[$cid] ?? '0';
             $qty = $qtyMap[$cid] ?? '0';
@@ -315,7 +220,6 @@ class StatSaleClass extends BaseClass
                     'customId' => $cid,
                     'customName' => $customList[$cid]['name'] ?? '',
                     'py' => $customList[$cid]['py'] ?? '',
-                    'source' => 'ghs',
                     'num' => 0,
                     'count' => '0.00',
                     'amount' => '0.00',
@@ -331,62 +235,20 @@ class StatSaleClass extends BaseClass
             $arr[$cid]['count'] = bcsub((string)($arr[$cid]['count'] ?? 0), (string)$qty, 2);
             $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
             $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
-            $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
-        }
-
-        // hd 零售隔天:独立 key +「零售-」客户名
-        $hdAmtMap = HdNextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
-        $hdQtyMap = HdNextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
-        $hdCids = array_unique(array_merge(array_keys($hdAmtMap), array_keys($hdQtyMap)));
-        foreach ($hdCids as $cid) {
-            $amtInfo = $hdAmtMap[$cid] ?? null;
-            $qtyInfo = $hdQtyMap[$cid] ?? null;
-            $amt = is_array($amtInfo) ? ($amtInfo['amount'] ?? '0') : '0';
-            $qty = is_array($qtyInfo) ? ($qtyInfo['num'] ?? '0') : '0';
-            if (bccomp((string)$amt, '0', 2) == 0 && bccomp((string)$qty, '0', 2) == 0) {
-                continue;
-            }
-            $rowKey = HdNextDayRefundClass::customStatKey($cid);
-            $rawName = '';
-            $py = '';
-            if (is_array($amtInfo)) {
-                $rawName = $amtInfo['customName'] ?? '';
-                $py = $amtInfo['py'] ?? '';
-            }
-            if ($rawName === '' && is_array($qtyInfo)) {
-                $rawName = $qtyInfo['customName'] ?? '';
-                if ($py === '') {
-                    $py = $qtyInfo['py'] ?? '';
-                }
-            }
-            if (!isset($arr[$rowKey])) {
-                $arr[$rowKey] = [
-                    'customId' => $cid,
-                    'customName' => HdNextDayRefundClass::displayCustomName($rawName, $cid),
-                    'py' => $py,
-                    'source' => 'hd',
-                    'num' => 0,
-                    'count' => '0.00',
-                    'amount' => '0.00',
-                    'levelName' => '',
-                    'orderPrice' => 0,
-                    'tkPrice' => 0,
-                    'cost' => 0,
-                    'profit' => '0.00',
-                ];
-            }
-            $arr[$rowKey]['amount'] = bcsub((string)$arr[$rowKey]['amount'], (string)$amt, 2);
-            $arr[$rowKey]['profit'] = bcsub((string)$arr[$rowKey]['profit'], (string)$amt, 2);
-            $arr[$rowKey]['count'] = bcsub((string)($arr[$rowKey]['count'] ?? 0), (string)$qty, 2);
-            $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
-            $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
-            $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
+            $nextDayDeduct = bcadd($nextDayDeduct, (string)$amt, 2);
         }
         if (!empty($arr)) {
-            $arr = arrayUtil::arraySort($arr, 'profit');
+            $arr = array_values(arrayUtil::arraySort($arr, 'profit'));
         }
         $totalAmount = floatval($totalAmount);
-        return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCount' => floatval($totalCount), 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
+        return [
+            'list' => $arr,
+            'totalAmount' => $totalAmount,
+            'totalNum' => $totalNum,
+            'totalCost' => $totalCost,
+            'totalProfit' => $totalProfit,
+            'nextDayDeduct' => floatval($nextDayDeduct),
+        ];
     }
 
     /**
@@ -564,12 +426,6 @@ class StatSaleClass extends BaseClass
                 $lsGiveBalance = bcadd($lsGiveBalance, $remainGiveBalance, 2);
             }
         }
-        // 隔天售后扣减零售收入(当天退款已在 tkPrice 扣过;隔天记 nextDayTkPrice,按通过日扣)
-        $lsIncome = bcsub(
-            (string)$lsIncome,
-            HdNextDayRefundClass::sumAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
-            2
-        );
 
         $condition = ['mainId' => $mainId, 'addTime' => ['between', [$currentStartTime, $currentEndTime]],];
 
@@ -607,7 +463,7 @@ class StatSaleClass extends BaseClass
             ['name' => '零售', 'id' => 'ls', 'amount' => floatval($lsIncome)],
             ['name' => '调拨出库', 'id' => 'allot', 'amount' => floatval($stockOut)],
             // 采购隔天售后冲回(含退货并退款、仅退款);后续若细分再拆行
-            ['name' => '采购隔天退', 'id' => 'cgNextDay', 'amount' => floatval($cgNextDayRefund)],
+            ['name' => '采购隔天退', 'id' => 'cgNextDay', 'amount' => floatval($cgNextDayRefund)],
         ];
         $expend = [
             ['name' => '批发运费', 'id' => 'pfSendCost', 'amount' => floatval($pfSendCost)],
@@ -642,6 +498,9 @@ class StatSaleClass extends BaseClass
     }
 
     //按花材统计收入 ssh 20231111
+    /**
+     * 花材收支明细:销售侧已按隔天通过日扣收入;采购侧入库日净量 + 通过日扣成本。
+     */
     public static function incomeOutItem($mainId)
     {
         $get = Yii::$app->request->get();
@@ -710,7 +569,12 @@ class StatSaleClass extends BaseClass
                         $itemNum = $cgData->itemNum ?? 0;
                         $productId = $cgData->productId ?? 0;
                         $refundNum = $cgData->refundNum ?? 0;
-                        $remainNum = bcsub($itemNum, $refundNum);
+                        // 入库日净量:隔天退货记 nextRefundNum,通过日再扣成本
+                        $remainNum = CgPurchaseNextDayClass::payDayRemainNum(
+                            $itemNum,
+                            $refundNum,
+                            $cgData->nextRefundNum ?? 0
+                        );
                         $bigPrice = $cgData->bigPrice ?? 0;
                         $amount = bcmul($remainNum, $bigPrice, 2);
                         $itemName = $productList[$productId]['name'] ?? '已删除';
@@ -731,6 +595,11 @@ class StatSaleClass extends BaseClass
                         if (!empty($cgRefundOrderList)) {
                             foreach ($cgRefundOrderList as $cgRefundOrder) {
                                 if ($cgRefundOrder->refundType == 2) {
+                                    // 隔天仅退款记在通过日,避免与下方汇总重复
+                                    if (intval($cgRefundOrder->sameDay ?? CgPurchaseNextDayClass::SAME_DAY_YES)
+                                        === CgPurchaseNextDayClass::SAME_DAY_NO) {
+                                        continue;
+                                    }
                                     $onlyRefundCg = bcadd($cgRefundOrder->refundPrice, $onlyRefundCg, 2);
                                 }
                             }
@@ -740,6 +609,19 @@ class StatSaleClass extends BaseClass
             }
         }
 
+        // 采购隔天售后:入库日已用 nextRefundNum;通过日再扣花材成本/数量;仅退款进「采购仅退款」
+        $onlyRefundCg = bcadd(
+            (string)$onlyRefundCg,
+            self::applyNextDayAdjustToProductExpendRows(
+                $arr,
+                $productList,
+                $mainId,
+                $currentStartTime,
+                $currentEndTime
+            ),
+            2
+        );
+
         //批发开单
         $pfIncome = 0;
         $tbSaleIncome = [];
@@ -870,12 +752,7 @@ class StatSaleClass extends BaseClass
                     $refundNum = $orderItem->refundNum ?? 0;
                     $num = $orderItem->num ?? 0;
                     $productId = $orderItem->itemId ?? 0;
-                    // 支付日净销量:隔天部分记 nextRefundNum,通过日再扣
-                    $remainNum = HdNextDayRefundClass::payDayRemainNum(
-                        $num,
-                        $refundNum,
-                        $orderItem->nextRefundNum ?? 0
-                    );
+                    $remainNum = bcsub($num, $refundNum);
                     $amount = bcmul($remainNum, $unitPrice, 2);
                     $itemName = $productList[$productId]['name'] ?? '已删除';
                     $arr[$productId]['name'] = $itemName;
@@ -891,14 +768,10 @@ class StatSaleClass extends BaseClass
                     }
                 }
                 if ($tkPrice > 0) {
-                    $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn, 'status' => HdRefundClass::STATUS_COMPLETE], null, '*', null, true);
+                    $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
                     if (!empty($refundList)) {
                         foreach ($refundList as $refund) {
                             if ($refund->refundType == 2) {
-                                // 隔天仅退款记在通过日,避免与 applyNextDayAdjust 重复
-                                if (intval($refund->sameDay ?? HdRefundClass::SAME_DAY_YES) === HdRefundClass::SAME_DAY_NO) {
-                                    continue;
-                                }
                                 $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
                             }
                         }
@@ -1274,21 +1147,11 @@ class StatSaleClass extends BaseClass
             NextDayRefundClass::sumItemByProduct($mainId, $currentStartTime, $currentEndTime),
             -1
         );
-        // hd 零售隔天退货:同样按花材归属分类扣减
-        $applyClassDelta(
-            HdNextDayRefundClass::sumItemByProduct($mainId, $currentStartTime, $currentEndTime),
-            -1
-        );
         $onlyRefund = bcadd(
             (string)$onlyRefund,
             NextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
             2
         );
-        $onlyRefund = bcadd(
-            (string)$onlyRefund,
-            HdNextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $currentStartTime, $currentEndTime),
-            2
-        );
 
         //零售开单
         $lsIncome = 0;
@@ -1314,11 +1177,7 @@ class StatSaleClass extends BaseClass
                     $num = $orderItem->num ?? 0;
                     $productId = $orderItem->itemId ?? 0;
                     $name = $orderItem->name ?? '';
-                    $remainNum = HdNextDayRefundClass::payDayRemainNum(
-                        $num,
-                        $refundNum,
-                        $orderItem->nextRefundNum ?? 0
-                    );
+                    $remainNum = bcsub($num, $refundNum);
                     $amount = bcmul($remainNum, $unitPrice, 2);
                     $className = $classList[$classId]['name'] ?? '已删除';
                     $arr[$classId]['className'] = $className;
@@ -1343,14 +1202,10 @@ class StatSaleClass extends BaseClass
                     }
                 }
                 if ($tkPrice > 0) {
-                    $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn, 'status' => HdRefundClass::STATUS_COMPLETE], null, '*', null, true);
+                    $refundList = HdRefundClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
                     if (!empty($refundList)) {
                         foreach ($refundList as $refund) {
                             if ($refund->refundType == 2) {
-                                // 隔天仅退款记在通过日
-                                if (intval($refund->sameDay ?? HdRefundClass::SAME_DAY_YES) === HdRefundClass::SAME_DAY_NO) {
-                                    continue;
-                                }
                                 $onlyRefund = bcadd($onlyRefund, $refund->refundPrice, 2);
                             }
                         }
@@ -1756,10 +1611,6 @@ class StatSaleClass extends BaseClass
         return $arr;
     }
 
-    /**
-     * 片区业绩:按片区汇总笔数/扎数/金额/成本/利润,供 ghsApp distSale、/stat-kh-cg/dist 使用。
-     * totalCount 为总扎数(含隔天售后扣减),与各行 count 口径一致。
-     */
     public static function customDistStat($mainId)
     {
         $get = Yii::$app->request->get();
@@ -1790,7 +1641,6 @@ class StatSaleClass extends BaseClass
         $ghsOrderList = OrderClass::getAllByCondition($where, null, '*');
         $totalAmount = 0;
         $totalNum = 0;
-        $totalCount = 0;
         $totalProfit = 0;
         $totalCost = 0;
         if (!empty($ghsOrderList)) {
@@ -1819,7 +1669,6 @@ class StatSaleClass extends BaseClass
                 $distName = isset($distMap[$distId]) ? $distMap[$distId]['name'] : '未划片区';
 
                 $totalNum++;
-                $totalCount = bcadd($totalCount, $count, 2);
                 $totalAmount = bcadd($totalAmount, $actPrice, 2);
                 $totalProfit = bcadd($totalProfit, $profit, 2);
                 $totalCost = bcadd($totalCost, $cost, 2);
@@ -1847,84 +1696,7 @@ class StatSaleClass extends BaseClass
                 }
             }
         }
-
-        // 零售客户无批发片区:全部归入虚拟片区「零售片区」
-        $hdDistKey = 'hd_retail';
-        $productCostMap = ProductClass::getAllByCondition(['mainId' => $mainId], null, 'id,cost,avCost', 'id');
-        $hdWhere = [
-            'mainId' => $mainId,
-            'status' => ['in', [HdOrderClass::ORDER_STATUS_UN_SEND, HdOrderClass::ORDER_STATUS_SENDING, HdOrderClass::ORDER_STATUS_COMPLETE]],
-            'payTime' => ['between', [$currentStartTime, $currentEndTime]],
-        ];
-        $hdOrderList = HdOrderClass::getAllByCondition($hdWhere, null, '*');
-        if (!empty($hdOrderList)) {
-            foreach ($hdOrderList as $hdOrder) {
-                if (intval($hdOrder['forward'] ?? 0) === 1) {
-                    continue;
-                }
-                $status = intval($hdOrder['status'] ?? 0);
-                if ($status === HdOrderClass::ORDER_STATUS_UN_PAY || $status === HdOrderClass::ORDER_STATUS_CANCEL) {
-                    continue;
-                }
-                $mainPay = bcadd((string)($hdOrder['mainPay'] ?? '0'), '0', 2);
-                $tkPrice = bcadd((string)($hdOrder['tkPrice'] ?? '0'), '0', 2);
-                $cash = bcadd((string)($hdOrder['cash'] ?? '0'), '0', 2);
-                $actPrice = bcadd(bcsub($mainPay, $tkPrice, 2), $cash, 2);
-                if (bccomp($actPrice, '0', 2) <= 0) {
-                    continue;
-                }
-                $orderSn = $hdOrder['orderSn'] ?? '';
-                $count = '0.00';
-                $cost = '0.00';
-                $orderItemList = HdOrderItemClass::getAllByCondition(['orderSn' => $orderSn], null, '*', null, true);
-                if (!empty($orderItemList)) {
-                    foreach ($orderItemList as $orderItem) {
-                        $remainNum = HdNextDayRefundClass::payDayRemainNum(
-                            $orderItem->num ?? 0,
-                            $orderItem->refundNum ?? 0,
-                            $orderItem->nextRefundNum ?? 0
-                        );
-                        $count = bcadd($count, $remainNum, 2);
-                        $productId = intval($orderItem->itemId ?? 0);
-                        $unitCost = $orderItem->cost ?? null;
-                        if ($unitCost === null || $unitCost === '') {
-                            $unitCost = $productCostMap[$productId]['avCost']
-                                ?? ($productCostMap[$productId]['cost'] ?? 0);
-                        }
-                        $cost = bcadd($cost, bcmul($remainNum, (string)$unitCost, 2), 2);
-                    }
-                }
-                $profit = bcsub($actPrice, $cost, 2);
-                $totalNum++;
-                $totalCount = bcadd($totalCount, $count, 2);
-                $totalAmount = bcadd($totalAmount, $actPrice, 2);
-                $totalProfit = bcadd($totalProfit, $profit, 2);
-                $totalCost = bcadd($totalCost, $cost, 2);
-                if (!isset($arr[$hdDistKey])) {
-                    $arr[$hdDistKey] = [
-                        'distId' => 0,
-                        'distName' => '零售片区',
-                        'num' => 0,
-                        'count' => '0.00',
-                        'amount' => '0.00',
-                        'levelName' => '',
-                        'orderPrice' => 0,
-                        'tkPrice' => 0,
-                        'cost' => 0,
-                        'profit' => '0.00',
-                    ];
-                }
-                $arr[$hdDistKey]['num']++;
-                $arr[$hdDistKey]['amount'] = bcadd($arr[$hdDistKey]['amount'], $actPrice, 2);
-                $arr[$hdDistKey]['orderPrice'] = bcadd($arr[$hdDistKey]['orderPrice'], $mainPay, 2);
-                $arr[$hdDistKey]['count'] = bcadd($arr[$hdDistKey]['count'], $count, 2);
-                $arr[$hdDistKey]['tkPrice'] = bcadd($arr[$hdDistKey]['tkPrice'], $tkPrice, 2);
-                $arr[$hdDistKey]['cost'] = bcadd($arr[$hdDistKey]['cost'], $cost, 2);
-                $arr[$hdDistKey]['profit'] = bcadd($arr[$hdDistKey]['profit'], $profit, 2);
-            }
-        }
-
-        // 隔天售后按客户归到片区扣金额/扎数(批发走客户片区;零售统一扣「零售片区」)
+        // 隔天售后按客户归到片区扣金额/扎数;无当日开单的片区也建负行
         $fwdMap = NextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
         $qtyMap = NextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
         $cidKeys = array_unique(array_merge(array_keys($fwdMap), array_keys($qtyMap)));
@@ -1954,46 +1726,60 @@ class StatSaleClass extends BaseClass
             $arr[$distId]['count'] = bcsub((string)($arr[$distId]['count'] ?? 0), (string)$qty, 2);
             $totalAmount = bcsub((string)$totalAmount, (string)$amt, 2);
             $totalProfit = bcsub((string)$totalProfit, (string)$amt, 2);
-            $totalCount = bcsub((string)$totalCount, (string)$qty, 2);
-        }
-
-        $hdAmtMap = HdNextDayRefundClass::sumAmountGroupByCustom($mainId, $currentStartTime, $currentEndTime);
-        $hdQtyMap = HdNextDayRefundClass::sumItemQtyByCustom($mainId, $currentStartTime, $currentEndTime);
-        $hdAmtTotal = '0.00';
-        $hdQtyTotal = '0.00';
-        foreach ($hdAmtMap as $row) {
-            $hdAmtTotal = bcadd($hdAmtTotal, (string)($row['amount'] ?? '0'), 2);
-        }
-        foreach ($hdQtyMap as $row) {
-            $hdQtyTotal = bcadd($hdQtyTotal, (string)($row['num'] ?? '0'), 2);
-        }
-        if (bccomp($hdAmtTotal, '0', 2) > 0 || bccomp($hdQtyTotal, '0', 2) > 0) {
-            if (!isset($arr[$hdDistKey])) {
-                $arr[$hdDistKey] = [
-                    'distId' => 0,
-                    'distName' => '零售片区',
-                    'num' => 0,
-                    'count' => '0.00',
-                    'amount' => '0.00',
-                    'levelName' => '',
-                    'orderPrice' => 0,
-                    'tkPrice' => 0,
-                    'cost' => 0,
-                    'profit' => '0.00',
-                ];
-            }
-            $arr[$hdDistKey]['amount'] = bcsub((string)$arr[$hdDistKey]['amount'], $hdAmtTotal, 2);
-            $arr[$hdDistKey]['profit'] = bcsub((string)$arr[$hdDistKey]['profit'], $hdAmtTotal, 2);
-            $arr[$hdDistKey]['count'] = bcsub((string)($arr[$hdDistKey]['count'] ?? 0), $hdQtyTotal, 2);
-            $totalAmount = bcsub((string)$totalAmount, $hdAmtTotal, 2);
-            $totalProfit = bcsub((string)$totalProfit, $hdAmtTotal, 2);
-            $totalCount = bcsub((string)$totalCount, $hdQtyTotal, 2);
         }
         if (!empty($arr)) {
             $arr = arrayUtil::arraySort($arr, 'profit');
         }
         $totalAmount = floatval($totalAmount);
-        return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCount' => floatval($totalCount), 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
+        return ['list' => $arr, 'totalAmount' => $totalAmount, 'totalNum' => $totalNum, 'totalCost' => $totalCost, 'totalProfit' => $totalProfit];
+    }
+
+    /**
+     * 花材收支明细-采购侧:入库日已用 nextRefundNum;通过日扣退货数量/金额,返回隔天仅退款合计。
+     *
+     * @param array $arr 产品收支行(引用修改 expend/outNum)
+     * @param array $productList 花材字典
+     * @param int $mainId
+     * @param string $startTime
+     * @param string $endTime
+     * @return string 通过日隔天「采购仅退款」合计
+     */
+    private static function applyNextDayAdjustToProductExpendRows(
+        &$arr,
+        $productList,
+        $mainId,
+        $startTime,
+        $endTime
+    ) {
+        $applyDelta = function ($pidMap, $sign) use (&$arr, $productList) {
+            foreach ($pidMap as $pid => $row) {
+                $deltaNum = bcmul((string)($row['num'] ?? '0'), (string)$sign, 2);
+                $deltaAmt = bcmul((string)($row['amount'] ?? '0'), (string)$sign, 2);
+                if (bccomp($deltaAmt, '0', 2) == 0 && bccomp($deltaNum, '0', 2) == 0) {
+                    continue;
+                }
+                // 通过日无该花材入库也建负成本行
+                if (!isset($arr[$pid])) {
+                    $arr[$pid] = [
+                        'name' => $productList[$pid]['name'] ?? '已删除',
+                        'id' => $pid,
+                        'expend' => '0.00',
+                        'outNum' => '0.00',
+                        'inNum' => 0,
+                        'income' => 0,
+                    ];
+                }
+                $arr[$pid]['expend'] = bcadd((string)($arr[$pid]['expend'] ?? 0), $deltaAmt, 2);
+                $arr[$pid]['outNum'] = bcadd((string)($arr[$pid]['outNum'] ?? 0), $deltaNum, 2);
+            }
+        };
+
+        $applyDelta(
+            CgPurchaseNextDayClass::sumItemByProduct($mainId, $startTime, $endTime),
+            -1
+        );
+
+        return CgPurchaseNextDayClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime);
     }
 
     /**
@@ -2042,22 +1828,13 @@ class StatSaleClass extends BaseClass
             }
         };
 
-        // 通过日:扣退货数量+金额(ghs 批发 + hd 零售共用花材库存)
+        // 通过日:扣退货数量+金额
         $applyDelta(
             NextDayRefundClass::sumItemByProduct($mainId, $startTime, $endTime),
             -1
         );
-        $applyDelta(
-            HdNextDayRefundClass::sumItemByProduct($mainId, $startTime, $endTime),
-            -1
-        );
 
-        $onlyRefund = NextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime);
-        return bcadd(
-            (string)$onlyRefund,
-            HdNextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime),
-            2
-        );
+        return NextDayRefundClass::sumMoneyOnlyAmountByMainAndTime($mainId, $startTime, $endTime);
     }
 
     /**