瀏覽代碼

余额管理问题

shish 1 月之前
父節點
當前提交
0d2fad7118

+ 36 - 0
app-ghs/controllers/CustomRechargeController.php

@@ -25,4 +25,40 @@ class CustomRechargeController extends BaseController
         util::success($list);
     }
 
+    /**
+     * 充值退款:财务权限;线上原路退,线下扣减余额并记变动明细。
+     */
+    public function actionRefund()
+    {
+        $staff = $this->shopAdmin;
+        if (!isset($staff->finance) || intval($staff->finance) === 0) {
+            util::fail('请有财务权限的人操作');
+        }
+
+        $post = Yii::$app->request->post();
+        $id = intval($post['id'] ?? 0);
+        if ($id <= 0) {
+            util::fail('参数错误');
+        }
+
+        $cacheKey = 'ghs_custom_recharge_refund_' . $id;
+        $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if (!empty($has)) {
+            util::fail('请5秒之后再提交');
+        }
+        Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
+
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            CustomRechargeClass::refundPaidRecharge($id, $this->shop, $staff);
+            $transaction->commit();
+            util::complete('退款成功');
+        } catch (\Exception $e) {
+            $transaction->rollBack();
+            Yii::info('充值退款失败:' . $e->getMessage());
+            util::fail($e->getMessage() ?: '退款失败');
+        }
+    }
+
 }

+ 63 - 0
app-hd/controllers/GhsRechargeController.php

@@ -2,6 +2,8 @@
 
 namespace hd\controllers;
 
+use biz\shop\classes\ShopClass;
+use bizGhs\custom\classes\CustomRechargeClass;
 use bizHd\ghs\classes\GhsClass;
 use bizHd\ghs\classes\GhsRechargeClass;
 use common\components\util;
@@ -23,4 +25,65 @@ class GhsRechargeController extends BaseController
         util::success($list);
     }
 
+    /**
+     * 花店端:对已付款充值退款(财务权限),经 customRechargeId 走统一退款逻辑。
+     */
+    public function actionRefund()
+    {
+        $staff = $this->shopAdmin;
+        if (!isset($staff->finance) || intval($staff->finance) === 0) {
+            util::fail('请有财务权限的人操作');
+        }
+
+        $post = Yii::$app->request->post();
+        $id = intval($post['id'] ?? 0);
+        if ($id <= 0) {
+            util::fail('参数错误');
+        }
+
+        $ghsRecharge = GhsRechargeClass::getById($id, true);
+        if (empty($ghsRecharge)) {
+            util::fail('没有找到充值记录');
+        }
+        $ghsId = intval($ghsRecharge->ghsId ?? 0);
+        $ghs = GhsClass::getById($ghsId, true);
+        if (empty($ghs)) {
+            util::fail('没有找到供货商');
+        }
+        GhsClass::valid($ghs, $this->shopId);
+
+        $customRechargeId = intval($ghsRecharge->customRechargeId ?? 0);
+        if ($customRechargeId <= 0) {
+            util::fail('充值记录不完整,无法退款');
+        }
+        $customRecharge = CustomRechargeClass::getById($customRechargeId, true);
+        if (empty($customRecharge)) {
+            util::fail('没有找到对应充值单');
+        }
+        $ghsShopId = intval($customRecharge->shopId ?? ($ghs->shopId ?? 0));
+        $ghsShop = ShopClass::getById($ghsShopId, true);
+        if (empty($ghsShop)) {
+            util::fail('没有找到供货商门店');
+        }
+
+        $cacheKey = 'hd_ghs_recharge_refund_' . $id;
+        $has = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+        if (!empty($has)) {
+            util::fail('请5秒之后再提交');
+        }
+        Yii::$app->redis->executeCommand('SETEX', [$cacheKey, 5, 'has']);
+
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
+        try {
+            CustomRechargeClass::refundPaidRecharge($customRechargeId, $ghsShop, $staff);
+            $transaction->commit();
+            util::complete('退款成功');
+        } catch (\Exception $e) {
+            $transaction->rollBack();
+            Yii::info('花店充值退款失败:' . $e->getMessage());
+            util::fail($e->getMessage() ?: '退款失败');
+        }
+    }
+
 }

+ 7 - 0
app-hd/controllers/ShopAdminController.php

@@ -21,6 +21,13 @@ class ShopAdminController extends BaseController
 
     public $guestAccess = ['generate-admin'];
 
+    /** 当前登录员工信息(含财务权限 finance) */
+    public function actionGetStaffInfo()
+    {
+        $staff = $this->shopAdmin;
+        util::success(['staff' => $staff]);
+    }
+
     public function actionSetManager()
     {
         $get = Yii::$app->request->get();

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

@@ -716,6 +716,31 @@ class CustomClass extends BaseClass
         GhsBalanceChangeClass::add($gbData, true);
     }
 
+    /**
+     * 充值退款:扣减成对客户/供货商净余额(调用方须已 lockAccountPair)。
+     *
+     * @return string 扣减后的净余额
+     */
+    public static function deductPairBalanceForRefund($custom, $ghs, $amount)
+    {
+        AccountMoneyClass::ensureCustomMoneyReady($custom, true);
+        if (!empty($ghs)) {
+            AccountMoneyClass::ensureGhsMoneyReady($ghs, true);
+            self::assertPairBalanceEqual($custom, $ghs);
+        }
+        $amount = bcadd((string)$amount, '0', 2);
+        if (bccomp($amount, '0', 2) <= 0) {
+            util::fail('退款金额有误');
+        }
+        $beforeBalance = bcadd((string)($custom->balance ?? '0'), '0', 2);
+        if (bccomp($beforeBalance, $amount, 2) < 0) {
+            util::fail('客户余额不足,本笔充值可能已用于销账或消费');
+        }
+        $newBalance = bcsub($beforeBalance, $amount, 2);
+        self::savePairBalanceAfterDeduct($custom, $ghs, $newBalance);
+        return $newBalance;
+    }
+
     /**
      * 后台手动减少客户净余额(只减正余额部分,不增加待结)。
      * 调用方须已通过 lockAccountPair 锁定 custom/ghs。

+ 253 - 0
biz-ghs/custom/classes/CustomRechargeClass.php

@@ -7,12 +7,17 @@ use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\services\GhsRechargeSettleService;
 use bizGhs\ghs\classes\GhsRechargeClass;
 use bizGhs\shop\classes\MainClass;
+use bizGhs\shop\classes\ShopClass as GhsShopClass;
+use bizGhs\shop\classes\ShopMoneyClass;
 use bizHd\ghs\classes\GhsClass;
 use common\components\dict;
+use common\components\lakala\Lakala;
 use common\components\noticeUtil;
+use common\components\orderSn;
 use common\components\util;
 use bizHd\base\classes\BaseClass;
 use bizGhs\ghs\classes\GhsBalanceChangeClass;
+use Yii;
 
 class CustomRechargeClass extends BaseClass
 {
@@ -176,4 +181,252 @@ class CustomRechargeClass extends BaseClass
 
     }
 
+    /**
+     * 供货商后台:对已付款充值单退款(线上原路退 / 线下扣减余额)。
+     *
+     * @param int $rechargeId xhCustomRecharge.id
+     * @param object $shop 当前供货商门店
+     * @param object $staff 操作员工(记余额变动 staffId/staffName)
+     */
+    public static function refundPaidRecharge($rechargeId, $shop, $staff)
+    {
+        $rechargeId = intval($rechargeId);
+        if ($rechargeId <= 0) {
+            util::fail('参数错误');
+        }
+        $customRecharge = self::getLockById($rechargeId);
+        if (empty($customRecharge)) {
+            util::fail('没有找到充值记录');
+        }
+        $shopMainId = intval($shop->mainId ?? 0);
+        if (intval($customRecharge->mainId ?? 0) !== $shopMainId) {
+            util::fail('没有权限操作该充值记录');
+        }
+        if (intval($customRecharge->payStatus ?? 0) !== 1) {
+            util::fail('仅已付款的充值可退款');
+        }
+        if (self::isRechargeRefunded($customRecharge)) {
+            util::fail('该充值已退款');
+        }
+
+        $amount = bcadd((string)($customRecharge->amount ?? '0'), '0', 2);
+        if (bccomp($amount, '0', 2) <= 0) {
+            util::fail('充值金额有误');
+        }
+
+        $customId = intval($customRecharge->customId ?? 0);
+        $pair = GhsRechargeSettleService::lockAccountPair(['id' => $customId]);
+        $custom = $pair['custom'];
+        $ghs = $pair['ghs'];
+        if (empty($custom)) {
+            util::fail('没有找到客户');
+        }
+
+        $onlinePayYes = intval(dict::getDict('onlinePay', 'yes'));
+        $isOnline = intval($customRecharge->onlinePay ?? 0) === $onlinePayYes;
+        $payWay = intval($customRecharge->payWay ?? -1);
+        $wxPay = intval(dict::getDict('payWay', 'wxPay'));
+        $aliPay = intval(dict::getDict('payWay', 'alipay'));
+        $cashPay = intval(dict::getDict('payWay', 'cash'));
+
+        // 线上退款:先调支付渠道原路退回(拉卡拉商户取充值单所属门店)
+        if ($isOnline) {
+            if ($payWay !== $wxPay && $payWay !== $aliPay) {
+                util::fail('暂不支持该支付方式原路退款');
+            }
+            $returnCode = trim((string)($customRecharge->returnCode ?? ''));
+            if ($returnCode === '') {
+                util::fail('缺少支付流水号,无法原路退款');
+            }
+            $payShopId = intval($customRecharge->shopId ?? 0);
+            $payShop = $payShopId > 0 ? ShopClass::getById($payShopId, true) : $shop;
+            if (empty($payShop)) {
+                util::fail('没有找到收款门店');
+            }
+            self::refundOnlineByLakala($customRecharge, $payShop, $amount, $returnCode);
+        }
+
+        $staffId = intval($staff->id ?? 0);
+        $staffName = (string)($staff->name ?? '');
+        $newBalance = CustomClass::deductPairBalanceForRefund($custom, $ghs, $amount);
+
+        $capitalType = dict::getDict('capitalType', 'customRechargeRefund', 'id');
+        $fromType = dict::getDict('fromType', 'shop');
+        $orderSn = (string)($customRecharge->orderSn ?? '');
+        $customName = (string)($custom->name ?? '');
+        $ghsName = (string)($ghs->name ?? ($customRecharge->ghsName ?? ''));
+        $event = '充值退款(操作人:' . $staffName . ')单号:' . $orderSn;
+        $shopId = intval($shop->id ?? 0);
+        $mainId = intval($shop->mainId ?? 0);
+        $sjId = intval($shop->sjId ?? 0);
+        $onlinePayVal = $isOnline ? $onlinePayYes : intval(dict::getDict('onlinePay', 'not'));
+
+        CustomBalanceChangeClass::add([
+            'customId' => $customId,
+            'customName' => $customName,
+            'relateId' => $rechargeId,
+            'onlinePay' => $onlinePayVal,
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => $capitalType,
+            'amount' => $amount,
+            'balance' => $newBalance,
+            'staffId' => $staffId,
+            'staffName' => $staffName,
+            'io' => 0,
+            'side' => 0,
+            'payWay' => $payWay,
+            'fromType' => $fromType,
+            'event' => $event,
+            'mainId' => $mainId,
+            'shopId' => $shopId,
+            'sjId' => $sjId,
+            'remark' => '',
+        ], true);
+
+        $customShopId = intval($custom->shopId ?? 0);
+        $customShop = GhsShopClass::getById($customShopId, true);
+        $ghsRechargeId = intval($customRecharge->ghsRechargeId ?? 0);
+        GhsBalanceChangeClass::add([
+            'ghsId' => intval($ghs->id ?? 0),
+            'ghsName' => $ghsName,
+            'relateId' => $ghsRechargeId,
+            'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+            'capitalType' => $capitalType,
+            'amount' => $amount,
+            'balance' => $newBalance,
+            'staffId' => $staffId,
+            'staffName' => $staffName,
+            'io' => 0,
+            'side' => 0,
+            'onlinePay' => $onlinePayVal,
+            'payWay' => $payWay,
+            'fromType' => $fromType,
+            'event' => $event,
+            'sjId' => $customShop->sjId ?? 0,
+            'mainId' => $customShop->mainId ?? 0,
+            'shopId' => $customShopId,
+            'remark' => '',
+        ], true);
+
+        // 线上充值曾增加门店 xhMain 余额,退款时对称扣减
+        if ($isOnline) {
+            $ghsShopId = intval($customRecharge->shopId ?? 0);
+            $ghsShop = ShopClass::getById($ghsShopId, true);
+            if (empty($ghsShop)) {
+                util::fail('没有找到供货商门店');
+            }
+            $ghsMain = MainClass::getLockById($ghsShop->mainId ?? 0);
+            if (empty($ghsMain)) {
+                util::fail('没有找到资产信息');
+            }
+            $originCapitalType = dict::getDict('capitalType', 'customRechargeToGhs', 'id');
+            $rechargeType = intval($customRecharge->rechargeType ?? 0);
+            if ($rechargeType === 1) {
+                $originCapitalType = dict::getDict('capitalType', 'ghsHelpCustomRechargeReturn', 'id');
+            }
+            ShopClass::customRechargeRefundReduceBalance($ghsMain, $ghsShop, $customRecharge, $originCapitalType, $staffName);
+        }
+
+        // 线下现金充值:扣减 xhMain.money
+        if (!$isOnline && $payWay === $cashPay) {
+            $m = MainClass::getById($mainId, true, 'id, money');
+            if (!empty($m)) {
+                $moneyBefore = $m->money ?? 0;
+                $m->money = bcsub((string)$moneyBefore, $amount, 2);
+                $m->save(false, ['money']);
+                ShopMoneyClass::addData([
+                    'amount' => $amount,
+                    'balance' => $m->money,
+                    'io' => 0,
+                    'mainId' => $mainId,
+                    'capitalType' => $capitalType,
+                    'ptStyle' => dict::getDict('ptStyle', 'ghs'),
+                    'event' => '客户(' . $customName . ')充值退款' . $amount . '元',
+                    'remark' => '操作人:' . $staffName,
+                ]);
+            }
+        }
+
+        self::markRechargeRefunded($customRecharge);
+        if ($ghsRechargeId > 0) {
+            $ghsRecharge = GhsRechargeClass::getLockById($ghsRechargeId);
+            if (!empty($ghsRecharge)) {
+                self::markRechargeRefunded($ghsRecharge);
+                $ghsRecharge->balance = $newBalance;
+                $ghsRecharge->save(false);
+            }
+        }
+        $customRecharge->balance = $newBalance;
+        $customRecharge->save(false);
+
+        return $customRecharge;
+    }
+
+    /** 充值记录是否已退款(兼容未加 refundStatus 列的环境) */
+    protected static function isRechargeRefunded($recharge)
+    {
+        if (empty($recharge)) {
+            return true;
+        }
+        if (self::modelHasAttr($recharge, 'refundStatus')) {
+            return intval($recharge->refundStatus ?? 0) === 1;
+        }
+        return false;
+    }
+
+    /** 标记充值单已退款 */
+    protected static function markRechargeRefunded($recharge)
+    {
+        if (empty($recharge) || !self::modelHasAttr($recharge, 'refundStatus')) {
+            return;
+        }
+        $recharge->refundStatus = 1;
+        $recharge->save(false, ['refundStatus']);
+    }
+
+    protected static function modelHasAttr($model, $attr)
+    {
+        return is_object($model) && method_exists($model, 'hasAttribute') && $model->hasAttribute($attr);
+    }
+
+    /**
+     * 拉卡拉原路退款(微信/支付宝线上充值)。
+     */
+    protected static function refundOnlineByLakala($customRecharge, $shop, $amount, $returnCode)
+    {
+        $termNo = $shop->lklScanTermNo ?? '';
+        $payWay = intval($customRecharge->payWay ?? 0);
+        if ($payWay === intval(dict::getDict('payWay', 'alipay'))) {
+            $termNo = $shop->lklB2BTermNo ?? '';
+        }
+        if (empty($shop->lklSjNo) || empty($termNo)) {
+            util::fail('门店未配置拉卡拉商户信息');
+        }
+        $merchantPrivateKeyPath = Yii::getAlias('@vendor/lakala') . '/production/api_private_key.pem';
+        $lklCertificatePath = Yii::getAlias('@vendor/lakala') . '/production/lkl-apigw-v1.cer';
+        $params = [
+            'appid' => 'OP00002119',
+            'serial_no' => '018b08cfddbd',
+            'merchant_no' => $shop->lklSjNo,
+            'term_no' => $termNo,
+            'merchantPrivateKeyPath' => $merchantPrivateKeyPath,
+            'lklCertificatePath' => $lklCertificatePath,
+        ];
+        $laResource = new Lakala($params);
+        $refundSn = orderSn::getGhsCustomRechargeSn();
+        $refundFee = bcmul($amount, 100);
+        $aliParams = [
+            'refundSn' => $refundSn,
+            'orderSn' => $customRecharge->orderSn ?? '',
+            'refundAmount' => $refundFee,
+            'refundReason' => '充值退款',
+            'thirdNo' => $returnCode,
+        ];
+        $response = $laResource->refund($aliParams);
+        if (!isset($response['code']) || $response['code'] != 'BBS00000') {
+            $errMsg = $response['msg'] ?? '退款失败';
+            util::fail('原路退款失败:' . $errMsg);
+        }
+    }
+
 }

+ 66 - 0
biz/pt/classes/PtAssetClass.php

@@ -119,6 +119,72 @@ class PtAssetClass extends BaseClass
         PtYeChangeClass::addChange($change, true);
     }
 
+    /**
+     * 客户线上充值退款:扣减平台资产(与 customRechargeAddBalance 对称)。
+     */
+    public static function customRechargeRefundReduceBalance($shop, $order, $capitalType, $tx, $staffName = '')
+    {
+        $amount = bcadd((string)($order->amount ?? '0'), '0', 2);
+        if (bccomp($amount, '0', 2) <= 0) {
+            return;
+        }
+        $ptStyle = $shop->ptStyle ?? 0;
+        if ($ptStyle == dict::getDict('ptStyle', 'hd')) {
+            $asset = self::getHdBalance();
+        } elseif ($ptStyle == dict::getDict('ptStyle', 'ghs')) {
+            $asset = self::getGhsBalance();
+        } else {
+            util::fail('没有找到平台');
+        }
+        $currentAmount = bcsub((string)($asset->amount ?? '0'), $amount, 2);
+        if (bccomp($currentAmount, '0', 2) < 0) {
+            util::fail('平台余额不足,无法退款');
+        }
+        $asset->amount = $currentAmount;
+        $asset->save();
+
+        if ($ptStyle == dict::getDict('ptStyle', 'hd')) {
+            $txAsset = self::getHdTxBalance();
+        } elseif ($ptStyle == dict::getDict('ptStyle', 'ghs')) {
+            $txAsset = self::getGhsTxBalance();
+        } else {
+            util::fail('没有找到平台');
+        }
+        $currentTxBalance = $txAsset->amount ?? 0;
+        if ($tx == dict::getDict('yeTx', 'can')) {
+            $currentTxBalance = bcsub((string)$currentTxBalance, $amount, 2);
+            if (bccomp($currentTxBalance, '0', 2) < 0) {
+                $currentTxBalance = '0.00';
+            }
+            $txAsset->amount = $currentTxBalance;
+            $txAsset->save();
+        }
+        $sjName = $shop->merchantName ?? '';
+        if (!isset($shop->default) || $shop->default != 1 || ($shop->shopName ?? '') != '首店') {
+            $sjName .= ' ' . ($shop->shopName ?? '');
+        }
+        $operator = $staffName !== '' ? "(操作人:{$staffName})" : '';
+        $event = "客户向商家-{$sjName}充值退款{$operator},单号:" . ($order->orderSn ?? '');
+        $change = [
+            'relateId' => $order->id ?? 0,
+            'capitalType' => $capitalType,
+            'amount' => $amount,
+            'balance' => $currentAmount,
+            'txBalance' => $currentTxBalance,
+            'io' => 0,
+            'payWay' => $order->payWay ?? 0,
+            'event' => $event,
+            'sjId' => $order->sjId ?? ($shop->sjId ?? 0),
+            'shopId' => $shop->shopId ?? ($shop->id ?? 0),
+            'mainId' => $shop->mainId ?? 0,
+            'tx' => $tx,
+            'ptStyle' => $ptStyle,
+            'shopName' => $shop->shopName ?? '',
+            'sjName' => $shop->merchantName ?? '',
+        ];
+        PtYeChangeClass::addChange($change, true);
+    }
+
     //客户结帐增加加余额 ssh 20210729
     public static function customClearAddBalance($shop, $order, $capitalType, $tx)
     {

+ 49 - 0
biz/shop/classes/ShopClass.php

@@ -361,6 +361,55 @@ class ShopClass extends BaseClass
         PtAssetClass::customRechargeAddBalance($shop, $order, $capitalType, $tx);
     }
 
+    /**
+     * 客户线上充值退款:扣减门店 xhMain 余额并记门店余额变动(与 customRechargeAddBalance 对称)。
+     */
+    public static function customRechargeRefundReduceBalance($main, $shop, $order, $capitalType, $staffName = '')
+    {
+        $amount = bcadd((string)($order->amount ?? '0'), '0', 2);
+        if (bccomp($amount, '0', 2) <= 0) {
+            util::fail('退款金额有误');
+        }
+        $mainId = $shop->mainId ?? 0;
+        $currentBalance = bcsub((string)($main->balance ?? '0'), $amount, 2);
+        if (bccomp($currentBalance, '0', 2) < 0) {
+            util::fail('门店余额不足,无法退款');
+        }
+        $main->balance = $currentBalance;
+        $currentTx = bcsub((string)($main->txBalance ?? '0'), $amount, 2);
+        if (bccomp($currentTx, '0', 2) < 0) {
+            $currentTx = '0.00';
+        }
+        $main->txBalance = $currentTx;
+        $main->save();
+
+        $custom = '客户';
+        if (!empty($order->customName)) {
+            $custom = $order->customName;
+        }
+        $orderSn = $order->orderSn ?? '';
+        $operator = $staffName !== '' ? "(操作人:{$staffName})" : '';
+        $event = $custom . "充值退款{$operator},单号:{$orderSn}";
+        $tx = dict::getDict('yeTx', 'can');
+        $change = [
+            'relateId' => $order->id ?? 0,
+            'capitalType' => $capitalType,
+            'amount' => $amount,
+            'balance' => $currentBalance,
+            'txBalance' => $currentTx,
+            'io' => 0,
+            'payWay' => $order->payWay ?? 0,
+            'event' => $event,
+            'sjId' => $shop->sjId ?? 0,
+            'shopId' => $shop->id ?? 0,
+            'mainId' => $mainId,
+            'tx' => $tx,
+            'ptStyle' => $shop->ptStyle ?? 0,
+        ];
+        ShopYeChangeClass::addChange($change, true);
+        PtAssetClass::customRechargeRefundReduceBalance($shop, $order, $capitalType, $tx, $staffName);
+    }
+
     public static function skRechargeAddBalance($main, $shop, $order)
     {
         $mainId = $main->id;

+ 2 - 0
common/components/dict.php

@@ -423,6 +423,8 @@ class dict
             'scanPayRefund' => ['id' => 80, 'name' => 'scanPayRefund'],
             // AccountMoneyClass 首次合并挂账入 balance 时写入余额变动的事项类型
             'balanceMerge' => ['id' => 81, 'name' => 'balanceMerge'],
+            // 客户充值退款(供货商后台操作)
+            'customRechargeRefund' => ['id' => 82, 'name' => 'customRechargeRefund'],
         ],
         "capitalTypeList" => [//流水类型的对应链接,后台收支明细查看时跳转的链接
             0 => ['link' => '/capital/order-detail', 'name' => '网店', 'orderLink' => '/order/detail', 'id' => 0,],

+ 19 - 0
scripts/sql/add_custom_recharge_refund_status.sql

@@ -0,0 +1,19 @@
+-- =============================================================================
+-- 充值记录退款状态 — xhCustomRecharge / xhGhsRecharge
+-- =============================================================================
+-- 【用途】供货商后台对已完成充值原路/线下退款后,列表展示「已退款」
+-- 【业务类】CustomRechargeClass::refundPaidRecharge
+-- 执行前确认列不存在;已存在则跳过对应 ALTER。
+-- =============================================================================
+
+SET SESSION lock_wait_timeout = 10;
+
+ALTER TABLE `xhCustomRecharge`
+    ADD COLUMN `refundStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '0正常 1已退款',
+    ALGORITHM = INPLACE,
+    LOCK = NONE;
+
+ALTER TABLE `xhGhsRecharge`
+    ADD COLUMN `refundStatus` tinyint(1) NOT NULL DEFAULT 0 COMMENT '0正常 1已退款',
+    ALGORITHM = INPLACE,
+    LOCK = NONE;