Jelajahi Sumber

冲销单 大改

shish 1 hari lalu
induk
melakukan
a0bb76f561

+ 104 - 0
app-ghs/controllers/OrderController.php

@@ -9,6 +9,7 @@ use bizGhs\custom\classes\CustomDebtChangeClass;
 use bizGhs\express\classes\GhsDeliveryOrderClass;
 use bizGhs\express\services\DadaExpressServices;
 use bizGhs\ghs\classes\GhsClass;
+use bizGhs\order\classes\OrderForwardClass;
 use bizGhs\order\classes\OrderItemClass;
 use bizGhs\order\classes\RefundOrderClass;
 use bizHd\purchase\classes\PurchaseClass;
@@ -1751,6 +1752,109 @@ class OrderController extends BaseController
         }
     }
 
+    /**
+     * 创建冲销单(金额为负的独立订单)ssh 冲销单功能
+     * 独立通道,不复用常规开单主链路(actionCreateOrder->createNewOrder),避免误伤现网正常开单流程。
+     * 支持两种入口:
+     * 1. 从 selectCustom(forward=1) 自由开单:不传 relateOrderId,不关联具体原订单。
+     * 2. 从售后 refund.vue 转入(原订单非当天/欠款已结清):传 relateOrderId,做累计冲销上限校验,
+     *    并强制按原订单实际支付方式覆盖 payWay(不信任前端传值)。
+     */
+    public function actionCreateForwardOrder()
+    {
+        $post = Yii::$app->request->post();
+        $customId = $post['customId'] ?? 0;
+        if (empty($customId)) {
+            util::fail('请选择客户');
+        }
+        $custom = CustomClass::getCustom($customId);
+        if (empty($custom)) {
+            util::fail('请选客户哦');
+        }
+        CustomClass::valid($custom, $this->shopId);
+
+        $shopAdmin = $this->shopAdmin;
+        $shopAdminId = $this->shopAdminId;
+        $shopAdminName = $shopAdmin->name ?? '';
+
+        //防止连点/重复提交
+        util::checkRepeatCommit('forward_' . $this->shopId . '_' . $this->adminId . '_' . $customId, 3);
+
+        $productJson = $post['product'] ?? '';
+        $productList = is_string($productJson) ? json_decode($productJson, true) : $productJson;
+        if (empty($productList)) {
+            util::fail('请选择花材');
+        }
+
+        $post['product'] = $productList;
+        $post['sjId'] = $this->sjId;
+        $post['shopId'] = $this->shopId;
+        $post['mainId'] = $this->mainId;
+        $post['shopAdminId'] = $shopAdminId;
+        $post['shopAdminName'] = $shopAdminName;
+
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            $result = OrderService::createForwardOrder($post, $custom);
+            $transaction->commit();
+        } catch (\Exception $exception) {
+            if ($transaction->isActive) {
+                $transaction->rollBack();
+            }
+            Yii::error('冲销单创建失败原因:' . $exception->getMessage());
+            if (util::isDbConcurrencyException($exception)) {
+                util::fail('系统繁忙中,请稍后再试');
+            }
+            throw $exception;
+        }
+
+        $order = $result['order'];
+        util::success([
+            'id' => $order->id,
+            'orderSn' => $order->orderSn,
+            'actPrice' => $order->actPrice,
+            'customName' => $order->customName,
+            'customBalance' => $result['customBalance'],
+        ]);
+    }
+
+    //按原销售单查询关联的冲销记录(供售后记录页“冲销记录”展示)ssh 冲销单功能
+    public function actionGetForwardListByOrder()
+    {
+        $get = Yii::$app->request->get();
+        $orderSn = $get['orderSn'] ?? '';
+        if (empty($orderSn)) {
+            util::fail('缺少订单号');
+        }
+        $order = OrderClass::getByCondition(['orderSn' => $orderSn], true);
+        if (empty($order)) {
+            util::fail('没有找到订单');
+        }
+        if ($order->mainId != $this->mainId) {
+            util::fail('无权查看');
+        }
+        $list = OrderForwardClass::getByOrderId($order->id);
+        if (empty($list)) {
+            util::success(['list' => []]);
+        }
+        $forwardOrderIds = array_unique(array_filter(array_column($list, 'forwardOrderId')));
+        $forwardOrderInfo = empty($forwardOrderIds) ? [] : OrderClass::getByIds($forwardOrderIds, null, 'id');
+        $data = [];
+        foreach ($list as $row) {
+            $forwardOrder = $forwardOrderInfo[$row['forwardOrderId']] ?? [];
+            $data[] = [
+                'forwardOrderId' => $row['forwardOrderId'],
+                'forwardOrderSn' => $row['forwardOrderSn'],
+                'forwardPrice' => $row['forwardPrice'],
+                'addTime' => $row['addTime'],
+                'shopAdminName' => $forwardOrder['shopAdminName'] ?? '',
+                'forwardStock' => $forwardOrder['forwardStock'] ?? 1,
+            ];
+        }
+        util::success(['list' => $data]);
+    }
+
     //修改订单 ssh 20210810
     public function actionUpdateOrder()
     {

+ 10 - 4
app-ghs/controllers/StatItemController.php

@@ -83,10 +83,13 @@ class StatItemController extends BaseController
             $status = $order['status'] ?? 0;
             $book = $order['book'] ?? 0;
             $actPrice = $order['actPrice'] ?? 0;
+            //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已全部退款"误跳过,
+            //改成只有非冲销单才按原逻辑跳过,让冲销数量能正常从销量里扣除
+            $forward = $order['forward'] ?? 0;
             if ($status == 5 || $status == 1 || ($book == 1 && $status == 2)) {
                 continue;
             }
-            if ($actPrice <= 0) {
+            if ($forward != 1 && $actPrice <= 0) {
                 //如果全部退款的花材也不统计
                 continue;
             }
@@ -111,7 +114,10 @@ class StatItemController extends BaseController
                     $currentAmount = bcmul($unitPrice, $num, 2);
                     $currentGross = bcmul($unitGross, $num, 2);
 
-                    $totalNum = bcadd($totalNum, $num, 2);
+                    //冲销单的数量字段($num)是正数,代表冲销掉的数量,需要反转符号去抵扣总销量;
+                    //但金额($currentAmount/$currentGross)已经用正数量×负单价算出了正确的负值,不能再用这个反转后的数量
+                    $qtyForTotal = ($forward == 1) ? bcmul($num, -1, 2) : $num;
+                    $totalNum = bcadd($totalNum, $qtyForTotal, 2);
                     $totalAmount = bcadd($totalAmount, $currentAmount, 2);
 
                     $totalMl = bcadd($totalMl, $currentGross, 2);
@@ -124,9 +130,9 @@ class StatItemController extends BaseController
                     $stat[$productId]['name'] = $name;
                     $stat[$productId]['py'] = $py;
                     if (isset($stat[$productId]['num'])) {
-                        $stat[$productId]['num'] = bcadd($stat[$productId]['num'], $num, 2);
+                        $stat[$productId]['num'] = bcadd($stat[$productId]['num'], $qtyForTotal, 2);
                     } else {
-                        $stat[$productId]['num'] = $num;
+                        $stat[$productId]['num'] = $qtyForTotal;
                     }
                     if (isset($stat[$productId]['amount'])) {
                         $stat[$productId]['amount'] = bcadd($stat[$productId]['amount'], $currentAmount, 2);

+ 42 - 0
app-hd/controllers/PurchaseController.php

@@ -11,6 +11,7 @@ use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\express\classes\GhsDeliveryOrderClass;
 use bizGhs\order\classes\OrderClass;
+use bizGhs\order\classes\OrderForwardClass;
 use bizGhs\order\classes\ShMethodClass;
 use bizHd\cg\classes\CgMergeSnClass;
 use bizHd\purchase\classes\PurchaseClass;
@@ -1437,6 +1438,47 @@ class PurchaseController extends BaseController
         util::success($info);
     }
 
+    /**
+     * 按采购单查询关联的冲销记录,供 hdApp 售后记录页展示"冲销记录" ssh 冲销单功能
+     * xhCg.saleId 指向对应的批发销售单(xhGhsOrder.id),冲销关联记录统一存在 xhGhsOrderForward 表,
+     * 花店和供货商两端共用同一张表,这里直接跨命名空间复用 bizGhs\order\classes\OrderForwardClass 查询
+     */
+    public function actionGetForwardListByOrder()
+    {
+        $get = Yii::$app->request->get();
+        $id = $get['id'] ?? 0;
+        $cg = PurchaseClass::getById($id, true);
+        if (empty($cg)) {
+            util::fail('没有找到采购单');
+        }
+        if ($cg->mainId != $this->mainId) {
+            util::fail('无权查看');
+        }
+        $saleId = $cg->saleId ?? 0;
+        if (empty($saleId)) {
+            util::success(['list' => []]);
+        }
+        $list = OrderForwardClass::getByOrderId($saleId);
+        if (empty($list)) {
+            util::success(['list' => []]);
+        }
+        $forwardOrderIds = array_unique(array_filter(array_column($list, 'forwardOrderId')));
+        //冲销单在花店侧对应的采购单id(purchaseId),用于点击跳转到 hdApp 的采购单详情
+        $forwardOrderInfo = empty($forwardOrderIds) ? [] : OrderClass::getByIds($forwardOrderIds, null, 'id');
+        $data = [];
+        foreach ($list as $row) {
+            $forwardOrder = $forwardOrderInfo[$row['forwardOrderId']] ?? [];
+            $data[] = [
+                'forwardCgId' => $forwardOrder['purchaseId'] ?? 0,
+                'forwardOrderSn' => $row['forwardOrderSn'],
+                'forwardPrice' => $row['forwardPrice'],
+                'addTime' => $row['addTime'],
+                'forwardStock' => $forwardOrder['forwardStock'] ?? 1,
+            ];
+        }
+        util::success(['list' => $data]);
+    }
+
     //可用的支付方式 ssh 2021.1.25
     public function actionPayWay()
     {

+ 48 - 0
biz-ghs/custom/classes/CustomClass.php

@@ -1250,6 +1250,54 @@ class CustomClass extends BaseClass
         TotalDebtChangeClass::addChange($change);
     }
 
+    /**
+     * 冲销单:选择“返充到余额”时,把冲销金额加回客户 balance,只记余额变动流水。
+     * 与 refundDebtAmountReduce 的区别:这里是独立的冲销单创建流程调用,不依赖 RefundOrder 模型,
+     * 也不联动 main.debt / TotalDebtChangeClass 这类主体级挂账汇总缓存,降低对现有售后/结账体系的影响面。
+     * ssh 冲销单功能
+     * @param $custom object 客户模型(调用方应已 getLockById 加锁)
+     * @param $forwardOrder object 冲销单(xhGhsOrder)模型
+     * @param string|float $returnAmount 本次返充金额(正数)
+     * @return string 返充后的客户最新余额
+     */
+    public static function forwardReturnBalance($custom, $forwardOrder, $returnAmount)
+    {
+        AccountMoneyClass::ensureCustomMoneyReady($custom, true);
+        if (bccomp($returnAmount, '0', 2) <= 0) {
+            return $custom->balance ?? '0.00';
+        }
+        $newBalance = bcadd($custom->balance ?? '0.00', $returnAmount, 2);
+        $custom->balance = $newBalance;
+        $custom->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
+        $custom->save(false, ['balance', 'isDebt']);
+
+        $forwardOrderSn = $forwardOrder->orderSn ?? '';
+        $change = [
+            'relateId' => $forwardOrder->id ?? 0,
+            'customId' => $custom->id ?? 0,
+            'customName' => $custom->name ?? '',
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => dict::getDict('capitalType', 'saleRefund', 'id'),
+            'amount' => $returnAmount,
+            'balance' => $newBalance,
+            'io' => 1,
+            'payWay' => 0,
+            'event' => "冲销单号:{$forwardOrderSn} 退款",
+            'sjId' => $forwardOrder->sjId ?? 0,
+            'shopId' => $forwardOrder->shopId ?? 0,
+            'mainId' => $forwardOrder->mainId ?? 0,
+            'payTime' => $forwardOrder->payTime ?? date('Y-m-d H:i:s'),
+            'staffId' => 0,
+            'staffName' => '',
+            'side' => 0,
+            'fromType' => dict::getDict('fromType', 'shop'),
+            'remark' => '冲销单退款',
+        ];
+        CustomBalanceChangeClass::add($change, true);
+
+        return $newBalance;
+    }
+
     public static function exportCustom($where, $sort, $mainId)
     {
         $list = self::getAllByCondition($where, $sort, '*', null);

+ 46 - 0
biz-ghs/order/classes/OrderForwardClass.php

@@ -0,0 +1,46 @@
+<?php
+
+namespace bizGhs\order\classes;
+
+use bizGhs\base\classes\BaseClass;
+
+/**
+ * 原销售单与冲销单的关联记录(xhGhsOrderForward)
+ * 用于“售后转冲销单”场景:写入一条关联记录,并配合 OrderClass 上的 hasForward/forwardPrice、
+ * OrderItemClass 上的 forwardNum 缓存字段,支持累计冲销上限校验与售后记录页“冲销记录”展示。
+ */
+class OrderForwardClass extends BaseClass
+{
+
+    public static $baseFile = '\bizGhs\order\models\OrderForward';
+
+    /**
+     * 新增一条冲销关联记录
+     * @param $order object 原销售单模型
+     * @param $forwardOrder object 冲销单模型
+     * @param $forwardPrice string|float 本次冲销金额(正数)
+     */
+    public static function addRelate($order, $forwardOrder, $forwardPrice)
+    {
+        $data = [
+            'mainId' => $order->mainId ?? 0,
+            'orderId' => $order->id ?? 0,
+            'orderSn' => $order->orderSn ?? '',
+            'customId' => $order->customId ?? 0,
+            'forwardOrderId' => $forwardOrder->id ?? 0,
+            'forwardOrderSn' => $forwardOrder->orderSn ?? '',
+            'forwardPrice' => $forwardPrice,
+            'addTime' => date('Y-m-d H:i:s'),
+        ];
+        return self::add($data, true);
+    }
+
+    /**
+     * 按原销售单id查询关联的冲销记录列表(供售后记录页“冲销记录”展示用)
+     * 返回普通数组(非AR对象),方便控制器直接按下标取值/array_column处理
+     */
+    public static function getByOrderId($orderId)
+    {
+        return self::getAllByCondition(['orderId' => $orderId], 'addTime DESC,id DESC', '*', null, false);
+    }
+}

+ 20 - 0
biz-ghs/order/models/OrderForward.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace bizGhs\order\models;
+
+use bizGhs\base\models\Base;
+
+/**
+ * 原销售单与冲销单的关联记录模型
+ * 用于“售后转冲销单”场景:记录某张原销售单被哪些冲销单冲销过多少金额,
+ * 配合 xhGhsOrder.hasForward/forwardPrice 缓存字段做累计冲销上限校验。
+ */
+class OrderForward extends Base
+{
+
+    public static function tableName()
+    {
+        return 'xhGhsOrderForward';
+    }
+
+}

+ 304 - 0
biz-ghs/order/services/OrderService.php

@@ -19,17 +19,22 @@ use bizGhs\custom\services\GhsRechargeSettleService;
 use bizGhs\clear\classes\OrderCgClearClass;
 use bizGhs\order\classes\OrderClass;
 use bizGhs\order\classes\OrderExpressClass;
+use bizGhs\order\classes\OrderForwardClass;
 use bizGhs\order\classes\OrderItemClass;
 use bizGhs\order\classes\OrderSendClass;
 use bizGhs\product\classes\ProductClass;
 use bizGhs\shop\classes\MainClass;
 use bizGhs\shop\classes\ShopMoneyChangeClass;
 use bizGhs\stat\classes\StatYjClass;
+use biz\stat\classes\StatOrderCountClass;
+use bizGhs\stock\classes\StockRecordClass;
 use bizHd\cg\services\CgRefundService;
+use bizHd\purchase\classes\PurchaseItemClass;
 use bizHd\purchase\services\PurchaseService;
 use bizHd\stat\classes\StatIncomeClass;
 use bizHd\stat\classes\StatOrderClass;
 use common\components\dict;
+use common\components\orderSn;
 use common\components\util;
 use bizHd\purchase\classes\PurchaseClass;
 use common\components\stringUtil;
@@ -1010,4 +1015,303 @@ class OrderService extends BaseService
         return $saleRefund;
     }
 
+    /**
+     * 创建冲销单(金额为负的独立订单)。
+     * 设计说明:不复用极其庞杂的常规开单主链路(createNewOrder->OrderClass::addOrder),
+     * 避免误伤现网所有商户的正常开单流程;只在数据落地时保持与正常订单相同的表结构,方便统一查询/统计。
+     * @param $post array 前端提交参数:customId,product(JSON数组),remark,needPrint,payWay,forwardStock,returnBalance,relateOrderId(可选)
+     * @param $custom array 客户信息(CustomClass::getCustom 返回)
+     * @return array ['order'=>冲销单模型, 'customBalance'=>返充后的余额(未返充时为null)]
+     */
+    public static function createForwardOrder($post, $custom)
+    {
+        $customId = $custom['id'] ?? 0;
+        $mainId = $post['mainId'] ?? 0;
+        $shopId = $post['shopId'] ?? 0;
+        $sjId = $post['sjId'] ?? 0;
+        $shopAdminId = $post['shopAdminId'] ?? 0;
+        $shopAdminName = $post['shopAdminName'] ?? '';
+        $ghsId = $custom['ghsId'] ?? 0;
+
+        $productList = $post['product'] ?? [];
+        if (empty($productList)) {
+            util::fail('请选择花材');
+        }
+
+        $level = $custom['level'] ?? 1;
+        $live = isset($custom['live']) ? $custom['live'] : 1;
+        $respond = ProductClass::formatProductInfo($productList, $level, $live, ['custom' => $custom]);
+        $items = $respond['product'] ?? [];
+        if (empty($items)) {
+            util::fail('花材信息有误');
+        }
+
+        //本次冲销总金额(正数)
+        $totalAmount = 0;
+        foreach ($items as $it) {
+            $totalAmount = bcadd($totalAmount, $it['price'], 2);
+        }
+        if (bccomp($totalAmount, '0', 2) <= 0) {
+            util::fail('冲销金额必须大于0');
+        }
+
+        $forwardStock = isset($post['forwardStock']) && in_array((int)$post['forwardStock'], [0, 1], true) ? (int)$post['forwardStock'] : 1;
+        $returnBalance = isset($post['returnBalance']) && (int)$post['returnBalance'] == 1 ? 1 : 0;
+        $payWay = isset($post['payWay']) ? (int)$post['payWay'] : dict::getDict('payWay', 'wxPay');
+
+        //关联原单场景:累计冲销上限校验,并且强制按原单支付方式,不信任前端传的 payWay
+        $relateOrderId = $post['relateOrderId'] ?? 0;
+        $relateOrder = null;
+        if (!empty($relateOrderId)) {
+            $relateOrder = OrderClass::getLockById($relateOrderId);
+            if (empty($relateOrder)) {
+                util::fail('没有找到原订单');
+            }
+            if ($relateOrder->mainId != $mainId || $relateOrder->customId != $customId) {
+                util::fail('原订单信息不匹配');
+            }
+            $actPrice = $relateOrder->actPrice ?? 0;
+            $hasForwardPrice = $relateOrder->forwardPrice ?? 0;
+            if (bccomp($hasForwardPrice, $actPrice, 2) >= 0) {
+                util::fail('该订单已冲销完,无法再次冲销');
+            }
+            $remain = bcsub($actPrice, $hasForwardPrice, 2);
+            if (bccomp($totalAmount, $remain, 2) == 1) {
+                util::fail("冲销金额超过原订单可冲销余额(剩余可冲销 ¥{$remain})");
+            }
+            //退款方式锁定为原单实际支付方式
+            $payWay = $relateOrder->payWay ?? $payWay;
+        }
+
+        //落库统一取负:金额字段为负,数量字段保持正数(代表冲销的数量)
+        $negItems = [];
+        $totalCost = 0;
+        foreach ($items as $it) {
+            $it['price'] = bcmul($it['price'], -1, 2);
+            $it['userPrice'] = bcmul($it['userPrice'], -1, 2);
+            $it['unitPrice'] = bcmul($it['unitPrice'], -1, 2);
+            $it['smallUnitPrice'] = bcmul($it['smallUnitPrice'], -1, 2);
+            $it['xhPrice'] = bcmul($it['xhPrice'], -1, 2);
+            $it['xhUnitPrice'] = bcmul($it['xhUnitPrice'], -1, 2);
+            $it['xhPrePrice'] = bcmul($it['xhPrePrice'], -1, 2);
+            $it['xhPreUnitPrice'] = bcmul($it['xhPreUnitPrice'], -1, 2);
+            $it['cost'] = bcmul($it['cost'], -1, 2);
+            $it['forward'] = 1;
+            $totalCost = bcadd($totalCost, $it['cost'], 2);
+            $negItems[] = $it;
+        }
+        $actPrice = bcmul($totalAmount, -1, 2);
+
+        $snData = ['shopId' => $shopId, 'mainId' => $mainId, 'ghsId' => $ghsId, 'customId' => $customId];
+        $orderSn = orderSn::getGhsOrderSn($snData);
+        $now = date('Y-m-d H:i:s');
+        $deadline = date('Y-m-d H:i:s', time() + dict::getDict('order_pay_has_time'));
+
+        $orderData = [
+            'mainId' => $mainId,
+            'sendNum' => '0' . date('j') . StatOrderCountClass::addOrder(ShopClass::getLockById($shopId), MainClass::getLockById($mainId)),
+            'orderSn' => $orderSn,
+            'customId' => $customId,
+            'customName' => $custom['name'] ?? '',
+            'customNamePy' => $custom['py'] ?? '',
+            'customAvatar' => $custom['shortSmallAvatar'] ?? '',
+            'customMobile' => $custom['mobile'] ?? '',
+            'ghsId' => $ghsId,
+            'sjId' => $sjId,
+            'shopId' => $shopId,
+            'shopAdminId' => $shopAdminId,
+            'shopAdminName' => $shopAdminName,
+            'getStaffId' => $shopAdminId,
+            'getStaffName' => $shopAdminName,
+            'itemNum' => $respond['totalItemNum'] ?? 0,
+            'bigNum' => $respond['bigNum'] ?? 0,
+            'smallNum' => $respond['smallNum'] ?? 0,
+            'itemPrice' => $actPrice,
+            'prePrice' => $actPrice,
+            'orderPrice' => $actPrice,
+            'bookPrice' => $actPrice,
+            'realPrice' => $actPrice,
+            'actPrice' => $actPrice,
+            'totalCost' => $totalCost,
+            'remainCost' => $totalCost,
+            'payWay' => $payWay,
+            'fromType' => 1,
+            'debt' => OrderClass::DEBT_NO,
+            'status' => OrderClass::ORDER_STATUS_COMPLETE,
+            'payStatus' => OrderClass::PAY_STATUS_HAS_PAY,
+            'sendType' => OrderClass::SEND_TYPE_SHOP_GET,
+            'sendStatus' => 2,
+            'sendTimeWant' => date('Y-m-d'),
+            'payTime' => $now,
+            'deadline' => $deadline,
+            'autoSetTime' => $deadline,
+            'needPrint' => $post['needPrint'] ?? 2,
+            'remark' => $post['remark'] ?? '',
+            'forward' => 1,
+            'forwardStock' => $forwardStock,
+            'salt' => stringUtil::charsShuffleLowerCase(10),
+        ];
+        $order = OrderClass::add($orderData, true);
+
+        foreach ($negItems as $it) {
+            $it['orderSn'] = $orderSn;
+            $it['mainId'] = $mainId;
+            OrderItemClass::add($it, true);
+        }
+
+        //库存处理:forwardStock==0 货退回来则加库存,==1 不退回则不动库存
+        if ($forwardStock == 0) {
+            $customName = $custom['name'] ?? '';
+            foreach ($negItems as $it) {
+                $productId = $it['productId'] ?? 0;
+                $itemNum = $it['num'] ?? 0;
+                if (empty($productId) || bccomp($itemNum, '0', 2) <= 0) {
+                    continue;
+                }
+                $stockInfo = ProductClass::addStockByItemNum($productId, $itemNum);
+                $recordData = [
+                    'sjId' => $sjId,
+                    'shopId' => $shopId,
+                    'mainId' => $mainId,
+                    'orderSn' => $orderSn,
+                    'itemId' => $it['itemId'] ?? 0,
+                    'productId' => $productId,
+                    'itemNum' => $itemNum,
+                    'oldStock' => $stockInfo['oldStock'] ?? 0,
+                    'newStock' => $stockInfo['newStock'] ?? 0,
+                    'relateName' => $customName,
+                    'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+                    'io' => 1,
+                ];
+                StockRecordClass::ghsRefundAddRecord($recordData);
+            }
+        }
+
+        //配对生成花店侧采购冲销记录 xhCg/xhCgItem,直接构造模型保存,不复用 PurchaseClass::addPurchase 的完整业务规则
+        $ghs = GhsClass::getById($ghsId);
+        $cgSn = orderSn::getPurchaseSn($snData);
+        $cgData = [
+            'mainId' => $ghs['ownMainId'] ?? 0,
+            'saleId' => $order->id ?? 0,
+            'orderSn' => $cgSn,
+            'customId' => $customId,
+            'ghsId' => $ghsId,
+            'ghsName' => $ghs['name'] ?? '',
+            'ghsAvatar' => $ghs['avatar'] ?? '',
+            'ghsMobile' => $ghs['mobile'] ?? '',
+            'ghsFullAddress' => $ghs['fullAddress'] ?? '',
+            'sjId' => $custom['sjId'] ?? 0,
+            'shopId' => $custom['shopId'] ?? 0,
+            'ghsShopId' => $shopId,
+            'ghsShopAdminId' => $shopAdminId,
+            'ghsShopAdminName' => $shopAdminName,
+            'itemPrice' => $actPrice,
+            'prePrice' => $actPrice,
+            'orderPrice' => $actPrice,
+            'bookPrice' => $actPrice,
+            'realPrice' => $actPrice,
+            'actPrice' => $actPrice,
+            'kindNum' => count($negItems),
+            'bigNum' => $respond['bigNum'] ?? 0,
+            'smallNum' => $respond['smallNum'] ?? 0,
+            'payWay' => $payWay,
+            'status' => PurchaseClass::STATUS_COMPLETE,
+            'cgStyle' => dict::getDict('cgStyle', 'ghs'),
+            'debt' => PurchaseClass::DEBT_NO,
+            'getType' => PurchaseClass::GET_TYPE_SELF_GET,
+            'payStatus' => 1,
+            'sendTimeWant' => date('Y-m-d'),
+            'payTime' => $now,
+            'remark' => $post['remark'] ?? '',
+            'forward' => 1,
+            'forwardStock' => $forwardStock,
+            'salt' => stringUtil::charsShuffleLowerCase(10),
+        ];
+        $cg = PurchaseClass::add($cgData, true);
+        $order->purchaseId = $cg->id ?? 0;
+        $order->save(false, ['purchaseId']);
+
+        foreach ($negItems as $it) {
+            $cgItemData = [
+                'name' => $it['name'] ?? '',
+                'cover' => $it['cover'] ?? '',
+                'orderSn' => $cgSn,
+                'productId' => $it['productId'] ?? 0,
+                'itemId' => $it['itemId'] ?? 0,
+                'mainId' => $cgData['mainId'],
+                'ghsId' => $ghsId,
+                'itemNum' => $it['num'] ?? 0,
+                'preItemNum' => $it['num'] ?? 0,
+                'itemInfo' => json_encode(['itemName' => $it['name'] ?? '', 'bigNum' => $it['bigNum'] ?? 0, 'smallNum' => $it['smallNum'] ?? 0]),
+                'ghsProductId' => $it['productId'] ?? 0,
+                'ratio' => $it['ratio'] ?? 0,
+                'ratioType' => $it['ratioType'] ?? 0,
+                'price' => $it['userPrice'] ?? 0,
+                'totalPrice' => $it['price'] ?? 0,
+                'preTotalPrice' => $it['price'] ?? 0,
+                'variety' => $it['variety'] ?? 0,
+                'unitWeight' => $it['unitWeight'] ?? 0,
+                'belongCost' => $it['belongCost'] ?? 0,
+                'remark' => $it['remark'] ?? '',
+                'kind' => $it['kind'] ?? 0,
+                'forward' => 1,
+            ];
+            PurchaseItemClass::add($cgItemData, true);
+        }
+
+        //余额处理:returnBalance==1 加回客户余额;==0 不改 balance,只把 payWay 记在订单上作为返款渠道记录
+        $customBalance = null;
+        if ($returnBalance == 1) {
+            $lockCustom = CustomClass::getLockById($customId);
+            if (empty($lockCustom)) {
+                util::fail('没有找到客户');
+            }
+            $customBalance = CustomClass::forwardReturnBalance($lockCustom, $order, $totalAmount);
+        }
+
+        //关联原单:写关系表 + 同步原单 hasForward/forwardPrice 与订单项 forwardNum
+        if (!empty($relateOrderId) && !empty($relateOrder)) {
+            OrderForwardClass::addRelate($relateOrder, $order, $totalAmount);
+            $relateOrder->hasForward = 1;
+            $relateOrder->forwardPrice = bcadd($relateOrder->forwardPrice ?? 0, $totalAmount, 2);
+            $relateOrder->save(false, ['hasForward', 'forwardPrice']);
+
+            $relateItems = OrderItemClass::getAllByCondition(['orderSn' => $relateOrder->orderSn], null, '*', 'productId', true);
+            foreach ($negItems as $it) {
+                $productId = $it['productId'] ?? 0;
+                $relateItem = $relateItems[$productId] ?? null;
+                if (!empty($relateItem)) {
+                    $relateItem->forward = 1;
+                    $relateItem->forwardNum = bcadd($relateItem->forwardNum ?? 0, $it['num'] ?? 0, 2);
+                    $relateItem->save(false, ['forward', 'forwardNum']);
+                }
+            }
+
+            //同步花店侧原采购单(xhCg)的 hasForward/forwardPrice 与采购单项(xhCgItem)的 forwardNum,
+            //供 hdApp 的 purDetails.vue/refundList.vue 展示冲销记录,与 GHS 侧原单缓存字段保持一致
+            $relateCgId = $relateOrder->purchaseId ?? 0;
+            if (!empty($relateCgId)) {
+                $relateCg = PurchaseClass::getById($relateCgId, true);
+                if (!empty($relateCg)) {
+                    $relateCg->hasForward = 1;
+                    $relateCg->forwardPrice = bcadd($relateCg->forwardPrice ?? 0, $totalAmount, 2);
+                    $relateCg->save(false, ['hasForward', 'forwardPrice']);
+
+                    $relateCgItems = PurchaseItemClass::getAllByCondition(['orderSn' => $relateCg->orderSn], null, '*', 'productId', true);
+                    foreach ($negItems as $it) {
+                        $productId = $it['productId'] ?? 0;
+                        $relateCgItem = $relateCgItems[$productId] ?? null;
+                        if (!empty($relateCgItem)) {
+                            $relateCgItem->forward = 1;
+                            $relateCgItem->forwardNum = bcadd($relateCgItem->forwardNum ?? 0, $it['num'] ?? 0, 2);
+                            $relateCgItem->save(false, ['forward', 'forwardNum']);
+                        }
+                    }
+                }
+            }
+        }
+
+        return ['order' => $order, 'customBalance' => $customBalance];
+    }
+
 }

+ 26 - 22
biz-ghs/stat/classes/StatKdClass.php

@@ -187,83 +187,87 @@ class StatKdClass extends BaseClass
                 if ($book == 1 && $status == 2) {
                     continue;
                 }
+                //ssh 冲销单功能:金额(actPrice为负数)正常混入各渠道抵扣;但冲销单本质是售后调整,
+                //不算一笔正常收款,所有"笔数(num)"统计都要排除冲销单,用 $numDelta 代替固定的 1
+                $forward = $ghsOrder['forward'] ?? 0;
+                $numDelta = ($forward == 1) ? 0 : 1;
 
                 if (isset($staffAmountList[$staffId])) {
-                    $staffAmountList[$staffId]['num'] = bcadd($staffAmountList[$staffId]['num'], 1);
+                    $staffAmountList[$staffId]['num'] = bcadd($staffAmountList[$staffId]['num'], $numDelta);
                     $staffAmountList[$staffId]['amount'] = bcadd($staffAmountList[$staffId]['amount'], $actPrice, 2);
                 } else {
-                    $staffAmountList[$staffId] = ['num' => 1, 'amount' => $actPrice, 'staffName' => $staffName, 'staffId' => $staffId];
+                    $staffAmountList[$staffId] = ['num' => $numDelta, 'amount' => $actPrice, 'staffName' => $staffName, 'staffId' => $staffId];
                 }
 
                 if ($debtPrice > 0) {
                     if ($remainDebtPrice > 0) {
                         $incomeList['debt']['amount'] = bcadd($incomeList['debt']['amount'], $actPrice, 2);
-                        $incomeList['debt']['num'] = bcadd($incomeList['debt']['num'], 1);
+                        $incomeList['debt']['num'] = bcadd($incomeList['debt']['num'], $numDelta);
                         $incomeList['debt']['category']['pf']['amount'] = bcadd($incomeList['debt']['category']['pf']['amount'], $actPrice, 2);
-                        $incomeList['debt']['category']['pf']['num'] = bcadd($incomeList['debt']['category']['pf']['num'], 1);
+                        $incomeList['debt']['category']['pf']['num'] = bcadd($incomeList['debt']['category']['pf']['num'], $numDelta);
                     } else {
                         $incomeList['debtClear']['amount'] = bcadd($incomeList['debtClear']['amount'], $actPrice, 2);
-                        $incomeList['debtClear']['num'] = bcadd($incomeList['debtClear']['num'], 1);
+                        $incomeList['debtClear']['num'] = bcadd($incomeList['debtClear']['num'], $numDelta);
                         $incomeList['debtClear']['category']['pf']['amount'] = bcadd($incomeList['debtClear']['category']['pf']['amount'], $actPrice, 2);
-                        $incomeList['debtClear']['category']['pf']['num'] = bcadd($incomeList['debtClear']['category']['pf']['num'], 1);
+                        $incomeList['debtClear']['category']['pf']['num'] = bcadd($incomeList['debtClear']['category']['pf']['num'], $numDelta);
                     }
                 } else {
                     if ($onlinePay == dict::getDict('onlinePay', 'yes')) {
                         //使用在线支付
                         $incomeList['system']['amount'] = bcadd($incomeList['system']['amount'], $actPrice, 2);
-                        $incomeList['system']['num'] = bcadd($incomeList['system']['num'], 1);
+                        $incomeList['system']['num'] = bcadd($incomeList['system']['num'], $numDelta);
                         $incomeList['system']['category']['pf']['amount'] = bcadd($incomeList['system']['category']['pf']['amount'], $actPrice, 2);
-                        $incomeList['system']['category']['pf']['num'] = bcadd($incomeList['system']['category']['pf']['num'], 1);
+                        $incomeList['system']['category']['pf']['num'] = bcadd($incomeList['system']['category']['pf']['num'], $numDelta);
                     } else {
                         //使用非在线支付
                         switch ($payWay) {
                             case dict::getDict('payWay', 'wxPay'):
                                 //员工微信总共收了多少笔多少钱
                                 $incomeList['kfWx']['amount'] = bcadd($incomeList['kfWx']['amount'], $actPrice, 2);
-                                $incomeList['kfWx']['num'] = bcadd($incomeList['kfWx']['num'], 1);
+                                $incomeList['kfWx']['num'] = bcadd($incomeList['kfWx']['num'], $numDelta);
                                 //批发开单、零售开单、批发结账、零售尾款各收了多少现金
                                 $incomeList['kfWx']['category']['pf']['amount'] = bcadd($incomeList['kfWx']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['kfWx']['category']['pf']['num'] = bcadd($incomeList['kfWx']['category']['pf']['num'], 1);
+                                $incomeList['kfWx']['category']['pf']['num'] = bcadd($incomeList['kfWx']['category']['pf']['num'], $numDelta);
                                 //每个客服总共收了多少笔多少钱
                                 if (isset($incomeList['kfWx']['class'][$getStaffId])) {
                                     $incomeList['kfWx']['class'][$getStaffId]['amount'] = floatval(bcadd($incomeList['kfWx']['class'][$getStaffId]['amount'], $actPrice, 2));
-                                    $incomeList['kfWx']['class'][$getStaffId]['num'] = bcadd($incomeList['kfWx']['class'][$getStaffId]['num'], 1);
+                                    $incomeList['kfWx']['class'][$getStaffId]['num'] = bcadd($incomeList['kfWx']['class'][$getStaffId]['num'], $numDelta);
                                 }
                                 //每个客服收的明细
                                 if (isset($incomeList['kfWx']['class'][$getStaffId]['itemList']['pf'])) {
                                     $incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['amount'] = floatval(bcadd($incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['amount'], $actPrice, 2));
-                                    $incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['num'] = bcadd($incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['num'], 1);
+                                    $incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['num'] = bcadd($incomeList['kfWx']['class'][$getStaffId]['itemList']['pf']['num'], $numDelta);
                                 }
                                 break;
                             case dict::getDict('payWay', 'alipay'):
                                 $incomeList['aliPay']['amount'] = bcadd($incomeList['aliPay']['amount'], $actPrice, 2);
-                                $incomeList['aliPay']['num'] = bcadd($incomeList['aliPay']['num'], 1);
+                                $incomeList['aliPay']['num'] = bcadd($incomeList['aliPay']['num'], $numDelta);
                                 $incomeList['aliPay']['category']['pf']['amount'] = bcadd($incomeList['aliPay']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['aliPay']['category']['pf']['num'] = bcadd($incomeList['aliPay']['category']['pf']['num'], 1);
+                                $incomeList['aliPay']['category']['pf']['num'] = bcadd($incomeList['aliPay']['category']['pf']['num'], $numDelta);
                                 break;
                             case dict::getDict('payWay', 'cash'):
                                 $incomeList['cash']['amount'] = bcadd($incomeList['cash']['amount'], $actPrice, 2);
-                                $incomeList['cash']['num'] = bcadd($incomeList['cash']['num'], 1);
+                                $incomeList['cash']['num'] = bcadd($incomeList['cash']['num'], $numDelta);
                                 $incomeList['cash']['category']['pf']['amount'] = bcadd($incomeList['cash']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['cash']['category']['pf']['num'] = bcadd($incomeList['cash']['category']['pf']['num'], 1);
+                                $incomeList['cash']['category']['pf']['num'] = bcadd($incomeList['cash']['category']['pf']['num'], $numDelta);
                                 break;
                             case dict::getDict('payWay', 'balancePay'):
                                 $incomeList['balancePay']['amount'] = bcadd($incomeList['balancePay']['amount'], $actPrice, 2);
-                                $incomeList['balancePay']['num'] = bcadd($incomeList['balancePay']['num'], 1);
+                                $incomeList['balancePay']['num'] = bcadd($incomeList['balancePay']['num'], $numDelta);
                                 $incomeList['balancePay']['category']['pf']['amount'] = bcadd($incomeList['balancePay']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['balancePay']['category']['pf']['num'] = bcadd($incomeList['balancePay']['category']['pf']['num'], 1);
+                                $incomeList['balancePay']['category']['pf']['num'] = bcadd($incomeList['balancePay']['category']['pf']['num'], $numDelta);
                                 break;
                             case dict::getDict('payWay', 'bankCard'):
                                 $incomeList['bankCard']['amount'] = bcadd($incomeList['bankCard']['amount'], $actPrice, 2);
-                                $incomeList['bankCard']['num'] = bcadd($incomeList['bankCard']['num'], 1);
+                                $incomeList['bankCard']['num'] = bcadd($incomeList['bankCard']['num'], $numDelta);
                                 $incomeList['bankCard']['category']['pf']['amount'] = bcadd($incomeList['bankCard']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['bankCard']['category']['pf']['num'] = bcadd($incomeList['bankCard']['category']['pf']['num'], 1);
+                                $incomeList['bankCard']['category']['pf']['num'] = bcadd($incomeList['bankCard']['category']['pf']['num'], $numDelta);
                                 break;
                             case dict::getDict('payWay', 'unknown'):
                                 $incomeList['other']['amount'] = bcadd($incomeList['other']['amount'], $actPrice, 2);
-                                $incomeList['other']['num'] = bcadd($incomeList['other']['num'], 1);
+                                $incomeList['other']['num'] = bcadd($incomeList['other']['num'], $numDelta);
                                 $incomeList['other']['category']['pf']['amount'] = bcadd($incomeList['other']['category']['pf']['amount'], $actPrice, 2);
-                                $incomeList['other']['category']['pf']['num'] = bcadd($incomeList['other']['category']['pf']['num'], 1);
+                                $incomeList['other']['category']['pf']['num'] = bcadd($incomeList['other']['category']['pf']['num'], $numDelta);
                                 break;
                             default:
                         }

+ 38 - 12
biz-ghs/stat/classes/StatSaleClass.php

@@ -152,7 +152,10 @@ class StatSaleClass extends BaseClass
         if (!empty($ghsOrderList)) {
             foreach ($ghsOrderList as $ghsKey => $ghsOrder) {
                 $actPrice = $ghsOrder['actPrice'] ?? 0;
-                if ($actPrice <= 0) {
+                //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
+                //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入业绩抵扣
+                $forward = $ghsOrder['forward'] ?? 0;
+                if ($forward != 1 && $actPrice <= 0) {
                     continue;
                 }
                 $cost = $ghsOrder['remainCost'] ?? 0;
@@ -172,12 +175,17 @@ class StatSaleClass extends BaseClass
                 }
                 $customName = $customList[$customId]['name'] ?? '';
                 $py = $customList[$customId]['py'] ?? '';
-                $totalNum++;
+                //冲销单本质是售后调整,不算一笔销售单,笔数不计入,但金额要正常混入抵扣
+                if ($forward != 1) {
+                    $totalNum++;
+                }
                 $totalAmount = bcadd($totalAmount, $actPrice, 2);
                 $totalProfit = bcadd($totalProfit, $profit, 2);
                 $totalCost = bcadd($totalCost, $cost, 2);
                 if (isset($arr[$customId])) {
-                    $arr[$customId]['num']++;
+                    if ($forward != 1) {
+                        $arr[$customId]['num']++;
+                    }
                     $arr[$customId]['amount'] = bcadd($arr[$customId]['amount'], $actPrice, 2);
                     $arr[$customId]['count'] = bcadd($arr[$customId]['count'], $count, 2);
                     $arr[$customId]['orderPrice'] = bcadd($arr[$customId]['orderPrice'], $orderPrice, 2);
@@ -189,7 +197,7 @@ class StatSaleClass extends BaseClass
                         'customId' => $customId,
                         'customName' => $customName,
                         'py' => $py,
-                        'num' => 1,
+                        'num' => $forward == 1 ? 0 : 1,
                         'count' => $count,
                         'amount' => $actPrice,
                         'levelName' => '',
@@ -314,7 +322,11 @@ class StatSaleClass extends BaseClass
                 $pfIncome = bcadd($pfIncome, $actPrice, 2);
                 $pfSendCost = bcadd($pfSendCost, $remainSendCost, 2);
                 $pfPack = bcadd($pfPack, $remainPackCost, 2);
-                $totalOrderNum++;
+                //ssh 冲销单功能:金额(actPrice为负数)正常混入抵扣收入,但冲销单本质是售后调整,不算一笔销售单,笔数不计入
+                $forward = $ghsOrder['forward'] ?? 0;
+                if ($forward != 1) {
+                    $totalOrderNum++;
+                }
             }
         }
 
@@ -877,7 +889,10 @@ class StatSaleClass extends BaseClass
                 $shopAdminName = $ghsOrder['shopAdminName'] ?? '';
                 $orderSn = $ghsOrder['orderSn'] ?? '';
                 $actPrice = $ghsOrder['actPrice'] ?? 0;
-                if ($actPrice <= 0) {
+                //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
+                //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入收支分类抵扣
+                $forward = $ghsOrder['forward'] ?? 0;
+                if ($forward != 1 && $actPrice <= 0) {
                     continue;
                 }
                 $tkPrice = $ghsOrder['tkPrice'] ?? 0;
@@ -898,15 +913,18 @@ class StatSaleClass extends BaseClass
                         $className = $classList[$classId]['name'] ?? '已删除';
                         $xhUnitPrice = $orderItem->xhUnitPrice ?? 0;
                         $amount = bcmul($remainNum, $xhUnitPrice, 2);
+                        //ssh 冲销单功能:金额用原始正数量×负单价,方向天然正确;但销量(saleNum)是数量统计,
+                        //冲销单的数量字段是正数(代表冲销掉的数量),需要反转符号去抵扣销量,不能直接累加
+                        $saleNumDelta = ($forward == 1) ? bcmul($remainNum, -1, 2) : $remainNum;
                         $arr[$classId]['className'] = $className;
                         $arr[$classId]['classId'] = $classId;
                         if (isset($arr[$classId]['income'])) {
                             $arr[$classId]['income'] = bcadd($amount, $arr[$classId]['income'], 2);
-                            $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $remainNum);
+                            $arr[$classId]['saleNum'] = bcadd($arr[$classId]['saleNum'], $saleNumDelta);
                         } else {
                             $arr[$classId]['expend'] = 0;
                             $arr[$classId]['income'] = $amount;
-                            $arr[$classId]['saleNum'] = $remainNum;
+                            $arr[$classId]['saleNum'] = $saleNumDelta;
                             $arr[$classId]['cgNum'] = 0;
                         }
 
@@ -1429,7 +1447,10 @@ class StatSaleClass extends BaseClass
         if (!empty($ghsOrderList)) {
             foreach ($ghsOrderList as $ghsOrder) {
                 $actPrice = $ghsOrder['actPrice'] ?? 0;
-                if ($actPrice <= 0) {
+                //ssh 冲销单功能:冲销单 actPrice 为负数,原有 actPrice<=0 会把它当"已退款归零单"误跳过,
+                //改成只有非冲销单才按原逻辑跳过,让冲销金额能正常混入片区业绩抵扣
+                $forward = $ghsOrder['forward'] ?? 0;
+                if ($forward != 1 && $actPrice <= 0) {
                     continue;
                 }
                 $cost = $ghsOrder['remainCost'] ?? 0;
@@ -1451,12 +1472,17 @@ class StatSaleClass extends BaseClass
                 $distId = $customList[$customId]['distId'] ?? 0;
                 $distName = isset($distMap[$distId]) ? $distMap[$distId]['name'] : '未划片区';
 
-                $totalNum++;
+                //冲销单本质是售后调整,不算一笔销售单,笔数不计入,但金额要正常混入抵扣
+                if ($forward != 1) {
+                    $totalNum++;
+                }
                 $totalAmount = bcadd($totalAmount, $actPrice, 2);
                 $totalProfit = bcadd($totalProfit, $profit, 2);
                 $totalCost = bcadd($totalCost, $cost, 2);
                 if (isset($arr[$distId])) {
-                    $arr[$distId]['num']++;
+                    if ($forward != 1) {
+                        $arr[$distId]['num']++;
+                    }
                     $arr[$distId]['amount'] = bcadd($arr[$distId]['amount'], $actPrice, 2);
                     $arr[$distId]['orderPrice'] = bcadd($arr[$distId]['orderPrice'], $orderPrice, 2);
                     $arr[$distId]['count'] = bcadd($arr[$distId]['count'], $count, 2);
@@ -1467,7 +1493,7 @@ class StatSaleClass extends BaseClass
                     $arr[$distId] = [
                         'distId' => $distId,
                         'distName' => $distName,
-                        'num' => 1,
+                        'num' => $forward == 1 ? 0 : 1,
                         'count' => $count,
                         'amount' => $actPrice,
                         'levelName' => '',