Просмотр исходного кода

Merge branch 'clear-cg' into dev

shish 2 месяцев назад
Родитель
Сommit
3182233e1d

+ 14 - 6
app-ghs/controllers/OrderController.php

@@ -2477,9 +2477,9 @@ class OrderController extends BaseController
                 util::fail('请选时间');
             }
         }
-        $allowedPageSizes = [50, 100, 200, 300];
+        $allowedPageSizes = [100, 200, 300];
         $pageSize = isset($get['pageSize']) && in_array((int)$get['pageSize'], $allowedPageSizes, true)
-            ? (int)$get['pageSize'] : 50;
+            ? (int)$get['pageSize'] : 100;
         $page = max(1, (int)($get['page'] ?? 1));
         $fields = ['id', 'orderSn', 'actPrice', 'addTime', 'remainDebtPrice', 'debtPrice', 'payTime'];
         Yii::$app->request->setQueryParams(array_merge($get, ['page' => $page, 'pageSize' => $pageSize]));
@@ -3077,7 +3077,6 @@ class OrderController extends BaseController
         set_time_limit(0);
 
         $connection = Yii::$app->db;
-        $transaction = $connection->beginTransaction();
         try {
 
             $get = Yii::$app->request->get();
@@ -3231,9 +3230,19 @@ class OrderController extends BaseController
                 $post['bookSn'] = $bookSn;
 
                 //多处有用到此方法,需要同步修改,搜索关键词create_new_order
-                OrderService::createNewOrder($post, $custom, $hasPay);
+                util::runWithDbConcurrencyRetry(function () use ($connection, $post, $custom, $hasPay) {
+                    $transaction = $connection->beginTransaction();
+                    try {
+                        OrderService::createNewOrder($post, $custom, $hasPay);
+                        $transaction->commit();
+                    } catch (\Exception $exception) {
+                        if ($transaction->isActive) {
+                            $transaction->rollBack();
+                        }
+                        throw $exception;
+                    }
+                });
 
-                $transaction->commit();
                 util::complete('提交成功');
 
             } else {
@@ -3241,7 +3250,6 @@ class OrderController extends BaseController
             }
 
         } catch (\Exception $e) {
-            $transaction->rollBack();
             Yii::info("导入失败了," . $e->getMessage());
             noticeUtil::push('导入失败,失败原因:' . $e->getMessage(), '15280215347');
             $msg = $e->getMessage();

+ 2 - 2
app-hd/controllers/OrderController.php

@@ -184,9 +184,9 @@ class OrderController extends BaseController
             $period = dateUtil::formatTime($searchTime, $startTime, $endTime);
             $where['addTime'] = ['between', [$period['startTime'], $period['endTime']]];
         }
-        $allowedPageSizes = [50, 100, 200, 300];
+        $allowedPageSizes = [100, 200, 300];
         $pageSize = isset($get['pageSize']) && in_array((int)$get['pageSize'], $allowedPageSizes, true)
-            ? (int)$get['pageSize'] : 50;
+            ? (int)$get['pageSize'] : 100;
         $page = max(1, (int)($get['page'] ?? 1));
         $fields = ['id', 'orderSn', 'actPrice', 'addTime', 'remainDebtPrice', 'debtPrice'];
         Yii::$app->request->setQueryParams(array_merge($get, ['page' => $page, 'pageSize' => $pageSize]));

+ 174 - 5
biz-ghs/custom/classes/CustomClass.php

@@ -14,6 +14,7 @@ use bizGhs\shop\classes\ShopMoneyClass;
 use bizGhs\shop\classes\TotalDebtChangeClass;
 use bizGhs\ghs\classes\GhsBalanceClass;
 use bizGhs\ghs\classes\GhsRechargeClass;
+use bizGhs\order\classes\OrderClearClass;
 use bizGhs\shop\classes\ShopClass;
 use bizHd\member\classes\MemberLevelClass;
 use bizHd\saas\classes\ApplyClass;
@@ -648,19 +649,187 @@ class CustomClass extends BaseClass
         }
     }
 
+    /**
+     * 调用方已 lockAccountPair 时,校验 custom/ghs 净余额一致。
+     */
+    protected static function assertPairBalanceEqual($custom, $ghs)
+    {
+        if (empty($ghs)) {
+            return;
+        }
+        $customBal = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        $ghsBal = bcadd((string)($ghs->balance ?? '0'), '0', 2);
+        if (bccomp($customBal, $ghsBal, 2) !== 0) {
+            util::fail('客户与供货商余额不一致,请联系管理员');
+        }
+    }
+
+    /**
+     * 开单扣减净 balance:写 custom(及成对 ghs),调用方须已 FOR UPDATE 锁行。
+     */
+    protected static function savePairBalanceAfterDeduct($custom, $ghs, $newBalance)
+    {
+        $newBalance = bcadd((string)$newBalance, '0', 2);
+        $custom->balance = $newBalance;
+        $custom->isDebt = bccomp($newBalance, '0', 2) < 0 ? CustomClass::IS_DEBT_YES : CustomClass::IS_DEBT_NO;
+        $custom->save(false, ['balance', 'isDebt']);
+        if (empty($ghs)) {
+            return;
+        }
+        AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
+        $ghs->balance = $newBalance;
+        $ghs->debt = bccomp($newBalance, '0', 2) < 0 ? 2 : 1;
+        $ghs->save(false, ['balance', 'debt']);
+        self::assertPairBalanceEqual($custom, $ghs);
+    }
+
+    protected static function addGhsOrderBalanceChange($custom, $ghs, $order, $amount, $newBalance, $bookOrder = false)
+    {
+        if (empty($ghs)) {
+            return;
+        }
+        $orderSn = $order->orderSn ?? '';
+        $event = '购买花材,单号:' . $orderSn;
+        if ($bookOrder) {
+            $event = '预订单多退少补,单号:' . $orderSn;
+        }
+        $customShopId = $custom->shopId ?? 0;
+        $customShop = ShopClass::getById($customShopId, true);
+        $gbData = [
+            'ghsId' => $ghs->id ?? 0,
+            'relateId' => $order->id ?? 0,
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => dict::getDict('capitalType', 'xhGhsOrder', 'id'),
+            'amount' => $amount,
+            'balance' => $newBalance,
+            'io' => 0,
+            'side' => 0,
+            'onlinePay' => 1,
+            'payWay' => $order->payWay ?? 0,
+            'fromType' => dict::getDict('fromType', 'shop'),
+            'event' => $event,
+            'sjId' => $customShop->sjId ?? ($custom->sjId ?? 0),
+            'mainId' => $customShop->mainId ?? 0,
+            'shopId' => $customShopId,
+            'remark' => '',
+        ];
+        GhsBalanceChangeClass::add($gbData, true);
+    }
+
+    /**
+     * 开单余额支付:扣减净 balance 并记购买流水(须传入 payAfter 已 lockAccountPair 的 custom/ghs)。
+     */
+    public static function payToChangeBalance($order, $custom, $ghs = null)
+    {
+        $actPrice = bcadd((string)($order->actPrice ?? '0'), '0', 2);
+        if (bccomp($actPrice, '0', 2) <= 0) {
+            return;
+        }
+        if (empty($custom)) {
+            util::fail('没有找到客户');
+        }
+        AccountMoneyClass::ensureCustomMoneyReady($custom, true);
+        if (!empty($ghs)) {
+            AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
+            self::assertPairBalanceEqual($custom, $ghs);
+        }
+        $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        if (bccomp($beforeBalance, $actPrice, 2) < 0) {
+            util::fail('余额不足');
+        }
+        $newBalance = bcsub($beforeBalance, $actPrice, 2);
+        self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
+
+        $orderSn = $order->orderSn ?? '';
+        $customId = $custom->id ?? 0;
+        $capitalType = dict::getDict('capitalType', 'xhGhsOrder', 'id');
+        $change = [
+            'relateId' => $order->id ?? 0,
+            'customId' => $customId,
+            'customName' => $custom->name ?? '',
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => $capitalType,
+            'amount' => $actPrice,
+            'balance' => $newBalance,
+            'io' => 0,
+            'payWay' => dict::getDict('payWay', 'balancePay'),
+            'event' => '购买花材,单号:' . $orderSn,
+            'sjId' => $order->sjId ?? 0,
+            'shopId' => $order->shopId ?? 0,
+            'mainId' => $order->mainId ?? 0,
+            'staffId' => $order->shopAdminId ?? 0,
+            'staffName' => $order->shopAdminName ?? '',
+            'side' => 0,
+            'fromType' => dict::getDict('fromType', 'shop'),
+            'remark' => '',
+        ];
+        CustomBalanceChangeClass::add($change, true);
+        self::addGhsOrderBalanceChange($custom, $ghs, $order, $actPrice, $newBalance, false);
+    }
+
+    /**
+     * 挂账开单时若账户有正余额且不足本单:用余额先结本单一部分(只改 remainDebtPrice,不另扣 balance)。
+     */
+    protected static function inlineOrderBalancePartialClear($custom, $order, $clearAmount)
+    {
+        $clearAmount = bcadd((string)$clearAmount, '0', 2);
+        if (bccomp($clearAmount, '0', 2) <= 0) {
+            return;
+        }
+        $orderId = intval($order->id ?? 0);
+        if ($orderId <= 0) {
+            return;
+        }
+        $shopId = intval($order->shopId ?? 0);
+        $shop = ShopClass::getById($shopId, true);
+        if (empty($shop)) {
+            util::fail('没有找到门店');
+        }
+        $staffId = intval($order->shopAdminId ?? 0);
+        $staffName = $order->shopAdminName ?? '';
+        $sjId = $shop->sjId ?? 0;
+        $orderSn = $order->orderSn ?? '';
+
+        OrderClearClass::expireAwaitPayClears(intval($custom->id ?? 0));
+        $clear = OrderClearClass::clearWithAmountMap([
+            'customId' => $custom->id ?? 0,
+            'ghsShopAdminId' => $staffId,
+            'ghsShopId' => $shopId,
+            'ghsShopAdminName' => $staffName,
+            'modifyPrice' => $clearAmount,
+            'payWay' => dict::getDict('payWay', 'balancePay'),
+            'complete' => 0,
+            'remark' => '开单余额抵挂账',
+        ], [
+            ['orderId' => $orderId, 'clearAmount' => $clearAmount, 'orderSn' => $orderSn],
+        ], $sjId, $shopId);
+        OrderClearClass::applyNetBalanceClear($clear, dict::getDict('payWay', 'balancePay'), ['skipCashMoney' => true]);
+    }
+
     /**
      * 挂账开单:增加客户待结(改造后 balance 减少,只记余额变动,不再记挂账变动)
      * ssh 20220306
      */
-    public static function cgDebtAmountAdd($custom, $order, $bookOrder = false)
+    public static function cgDebtAmountAdd($custom, $order, $bookOrder = false, $ghs = null)
     {
         // 挂账开单:合并后 balance 减少,不再写 CustomDebtChange
         AccountMoneyClass::ensureCustomMoneyReady($custom, true);
-        $amount = $order->remainDebtPrice ?? 0;
+        if (!empty($ghs)) {
+            AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
+            self::assertPairBalanceEqual($custom, $ghs);
+        }
+        $amount = bcadd((string)($order->remainDebtPrice ?? '0'), '0', 2);
         if (bccomp($amount, '0', 2) <= 0) {
             return;
         }
-        $beforeBalance = $custom->balance ?? '0.00';
+        $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        $positiveBalance = bccomp($beforeBalance, '0', 2) > 0 ? $beforeBalance : '0.00';
+        if (bccomp($positiveBalance, $amount, 2) >= 0) {
+            util::fail('余额充足,请用余额支付');
+        }
+        if (bccomp($positiveBalance, '0', 2) > 0) {
+            self::inlineOrderBalancePartialClear($custom, $order, $positiveBalance);
+        }
         $custom->isDebt = CustomClass::IS_DEBT_YES;
         $debtLimit = $custom->debtLimit ?? 0;
         if (!$bookOrder) {
@@ -692,8 +861,7 @@ class CustomClass extends BaseClass
             }
         }
 
-        $custom->balance = $newBalance;
-        $custom->save(false, ['balance', 'isDebt']);
+        self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
 
         $relateId = $order->id ?? 0;
         $customId = $custom->id ?? 0;
@@ -726,6 +894,7 @@ class CustomClass extends BaseClass
             'remark' => '',
         ];
         CustomBalanceChangeClass::add($change, true);
+        self::addGhsOrderBalanceChange($custom, $ghs, $order, $amount, $newBalance, $bookOrder);
 
         $mainId = $order->mainId ?? 0;
         $main = MainClass::getLockById($mainId);

+ 4 - 2
biz-ghs/order/classes/OrderClass.php

@@ -771,11 +771,13 @@ class OrderClass extends BaseClass
 
                 $payWay = dict::getDict('payWay', 'debtPay');
 
-                $custom = CustomClass::getLockById($customId);
+                $pair = \bizGhs\custom\services\GhsRechargeSettleService::lockAccountPair(['id' => $customId]);
+                $custom = $pair['custom'];
+                $ghs = $pair['ghs'];
                 if (empty($custom)) {
                     util::fail('没有找到客户');
                 }
-                CustomClass::cgDebtAmountAdd($custom, $order, true);
+                CustomClass::cgDebtAmountAdd($custom, $order, true, $ghs);
 
                 //收入增加
                 StatIncomeClass::updateOrInsert($main, $shop, $currentDebt);

+ 47 - 28
biz-ghs/order/services/OrderService.php

@@ -15,6 +15,7 @@ use bizGhs\base\services\BaseService;
 use bizGhs\book\classes\BookItemClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\custom\classes\CustomDebtChangeClass;
+use bizGhs\custom\services\GhsRechargeSettleService;
 use bizGhs\clear\classes\OrderCgClearClass;
 use bizGhs\order\classes\OrderClass;
 use bizGhs\order\classes\OrderExpressClass;
@@ -203,7 +204,10 @@ class OrderService extends BaseService
         //销售单欠款字段与采购单欠款字段转换
         $debt = $data['debt'] ?? 0;
         $purchaseDebt = $debt == 1 ? PurchaseClass::DEBT_YES : PurchaseClass::DEBT_NO;
-        if ($debt == 1) {
+        if ($hasPay == dict::getDict('hasPay', 'balance')) {
+            $payWay = dict::getDict('payWay', 'balancePay');
+            $purchaseDebt = PurchaseClass::DEBT_NO;
+        } elseif ($debt == 1) {
             $payWay = dict::getDict('payWay', 'debtPay');
         }
         //销售单的自取还是配送字段 与 采购单的转换
@@ -285,33 +289,26 @@ class OrderService extends BaseService
         $returnOrder->purchaseId = $purchaseId;
         $returnOrder->save();
 
-        //欠款和已付款的走付款后流程
-        if (in_array($hasPay, [dict::getDict('hasPay', 'payed'), dict::getDict('hasPay', 'debt')])) {
-
-            if ($hasPay == dict::getDict('hasPay', 'debt')) {
-                $shopId = $data['shopId'] ?? 0;
-                $shop = ShopClass::getById($shopId, true);
-                if (empty($shop)) {
-                    util::fail('没有门店信息');
-                }
-                //老商家允许设置overAllowDebt,新商家已经不允许设置,默认就是 1,不能超过已经设置的授信额度
-                if (isset($shop->overAllowDebt) && $shop->overAllowDebt == 0) {
-                    $debtLimit = $custom['debtLimit'] ?? 0;
-                    $debtLimit = floatval($debtLimit);
-                    // 待结额度校验:用净余额欠款额,不再读 debtAmount
-                    $outstanding = \bizGhs\custom\classes\AccountMoneyClass::getOutstandingDebt($custom);
-                    $currentPrice = $returnOrder->actPrice ?? 0;
-                    $newDebt = bcadd($currentPrice, $outstanding, 2);
-                    if (bccomp($newDebt, $debtLimit, 2) > 0) {
-                        util::fail('欠款已超' . $debtLimit . ',请先清账');
-                    }
+        //欠款、已付款、余额支付的走付款后流程
+        if (in_array($hasPay, [dict::getDict('hasPay', 'payed'), dict::getDict('hasPay', 'debt'), dict::getDict('hasPay', 'balance')])) {
+
+            // 挂账/余额:先处理销售单(含余额抵挂账),再同步采购单待结
+            if (in_array($hasPay, [dict::getDict('hasPay', 'debt'), dict::getDict('hasPay', 'balance')])) {
+                self::payAfter($returnOrder, $payWay);
+                $purchase = PurchaseClass::getLockById($purchaseId, true);
+                if (!empty($purchase)) {
+                    $purchase->remainDebtPrice = $returnOrder->remainDebtPrice;
+                    $purchase->debtPrice = $returnOrder->debtPrice;
+                    $purchase->debt = ($returnOrder->debt ?? 0) == OrderClass::DEBT_YES
+                        ? PurchaseClass::DEBT_YES : PurchaseClass::DEBT_NO;
+                    $purchase->save(false, ['remainDebtPrice', 'debtPrice', 'debt']);
                 }
+                PurchaseService::payAfter($purchase, $payWay);
+            } else {
+                PurchaseService::payAfter($purchase, $payWay);
+                self::payAfter($returnOrder, $payWay);
             }
 
-            //下面二个顺序不能换
-            PurchaseService::payAfter($purchase, $payWay);
-            self::payAfter($returnOrder, $payWay);
-
             //不是预订单,并且供货商不是源花汇、小明鲜花、淄博花超、云漫梦金鹏、海翔,则订单直接完成掉。是预订单,则确认发货时直接完成掉。有多个地方要修改,请搜索关键词zjFinish
             if (isset($returnOrder->book) && $returnOrder->book == 0) {
                 $ghsShopId = $ghs['shopId'] ?? 0;
@@ -729,7 +726,14 @@ class OrderService extends BaseService
         $orderId = $order->id;
         $orderSn = $order->orderSn ?? '';
         $customId = $order->customId;
-        $custom = CustomClass::getLockById($customId);
+        $ghs = null;
+        if (in_array($payWay, [dict::getDict('payWay', 'balancePay'), dict::getDict('payWay', 'debtPay')], true)) {
+            $pair = GhsRechargeSettleService::lockAccountPair(['id' => $customId]);
+            $custom = $pair['custom'];
+            $ghs = $pair['ghs'];
+        } else {
+            $custom = CustomClass::getLockById($customId);
+        }
         if (empty($custom)) {
             util::fail('没有找到客户信息');
         }
@@ -743,6 +747,16 @@ class OrderService extends BaseService
         if (empty($shop)) {
             util::fail('没有找到门店5');
         }
+        if ($payWay == dict::getDict('payWay', 'debtPay') && $book != 1) {
+            if (isset($shop->overAllowDebt) && $shop->overAllowDebt == 0) {
+                $debtLimit = $custom->debtLimit ?? 0;
+                $outstanding = \bizGhs\custom\classes\AccountMoneyClass::getOutstandingDebt($custom);
+                $newDebt = bcadd((string)$realPrice, (string)$outstanding, 2);
+                if (bccomp($newDebt, (string)$debtLimit, 2) > 0) {
+                    util::fail('待结款已超' . $debtLimit . ',请先结账');
+                }
+            }
+        }
         $mainId = $shop->mainId ?? 0;
         $main = MainClass::getLockById($mainId);
         if (empty($main)) {
@@ -886,9 +900,14 @@ class OrderService extends BaseService
             StatYjClass::addYj($main, $shop, $shopAdminId, $yjAmount);
         }
 
+        //余额支付
+        if ($payWay == dict::getDict('payWay', 'balancePay') && $isPurchase == false) {
+            CustomClass::payToChangeBalance($order, $custom, $ghs);
+        }
+
         //欠款
         if ($payWay == dict::getDict('payWay', 'debtPay')) {
-            CustomClass::cgDebtAmountAdd($custom, $order);
+            CustomClass::cgDebtAmountAdd($custom, $order, false, $ghs);
         }
         $custom->buyNum += 1;
         $custom->buyAmount = bcadd($custom->buyAmount, $amount, 2);
@@ -995,4 +1014,4 @@ class OrderService extends BaseService
         return $saleRefund;
     }
 
-}
+}

+ 2 - 2
biz-ghs/order/services/PurchaseOrderService.php

@@ -15,9 +15,9 @@ class PurchaseOrderService extends BaseService
     public static function getDebtList($where)
     {
         $get = Yii::$app->request->get();
-        $allowedPageSizes = [50, 100, 200, 300];
+        $allowedPageSizes = [100, 200, 300];
         $pageSize = isset($get['pageSize']) && in_array((int)$get['pageSize'], $allowedPageSizes, true)
-            ? (int)$get['pageSize'] : 50;
+            ? (int)$get['pageSize'] : 100;
         $page = max(1, (int)($get['page'] ?? 1));
         Yii::$app->request->setQueryParams(array_merge($get, ['page' => $page, 'pageSize' => $pageSize]));
         $result = PurchaseOrderClass::getList('*', $where, 'addTime DESC');

+ 5 - 1
biz-hd/ghs/classes/GhsClass.php

@@ -25,7 +25,11 @@ class GhsClass extends BaseClass
     {
         // hd 采购挂账:净 balance 减少
         AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
-        $amount = $order->remainDebtPrice ?? 0;
+        // 开单余额抵挂账后 remainDebtPrice 变小,balance 仍按整单 debtPrice 扣减
+        $amount = bcadd((string)($order->debtPrice ?? '0'), '0', 2);
+        if (bccomp($amount, '0', 2) <= 0) {
+            $amount = bcadd((string)($order->remainDebtPrice ?? '0'), '0', 2);
+        }
         if (bccomp($amount, '0', 2) <= 0) {
             return;
         }

+ 16 - 8
biz-hd/purchase/services/PurchaseService.php

@@ -186,9 +186,9 @@ class PurchaseService extends BaseService
     public static function getDebtList($where)
     {
         $get = Yii::$app->request->get();
-        $allowedPageSizes = [50, 100, 200, 300];
+        $allowedPageSizes = [100, 200, 300];
         $pageSize = isset($get['pageSize']) && in_array((int)$get['pageSize'], $allowedPageSizes, true)
-            ? (int)$get['pageSize'] : 50;
+            ? (int)$get['pageSize'] : 100;
         $page = max(1, (int)($get['page'] ?? 1));
 
         $list = PurchaseClass::getAllList('*', $where, 'addTime DESC');
@@ -503,14 +503,22 @@ class PurchaseService extends BaseService
         $info->payTime = $payTime;
 
         if ($payWay == dict::getDict('payWay', 'debtPay')) {
-            //欠款支付
-            if (isset($info->actPrice) && $info->actPrice == 0) {
-                $info->debt = 0;
+            //欠款支付(批发开单若销售单已 payAfter,沿用其待结,支持开单余额抵挂账)
+            $saleId = intval($info->saleId ?? 0);
+            $saleOrder = $saleId > 0 ? \bizGhs\order\classes\OrderClass::getById($saleId, true) : null;
+            if (!empty($saleOrder) && intval($saleOrder->payStatus ?? 0) === 1) {
+                $info->debt = ($saleOrder->debt ?? 0) == 1 ? 1 : 0;
+                $info->remainDebtPrice = $saleOrder->remainDebtPrice ?? 0;
+                $info->debtPrice = $saleOrder->debtPrice ?? ($info->orderPrice ?? 0);
             } else {
-                $info->debt = 1;
+                if (isset($info->actPrice) && $info->actPrice == 0) {
+                    $info->debt = 0;
+                } else {
+                    $info->debt = 1;
+                }
+                $info->remainDebtPrice = $info->orderPrice ?? 0;
+                $info->debtPrice = $info->orderPrice ?? 0;
             }
-            $info->remainDebtPrice = $info->orderPrice ?? 0;
-            $info->debtPrice = $info->orderPrice ?? 0;
         }
         $info->save();