编辑代码

<?php

declare(strict_types=1);

namespace app\crontab\stat;

use app\model\basic\Payment;
use app\model\basic\VipSubscriptionRecords;
use app\model\merchant\MerchantCertOrder;
use app\model\order\Order;
use app\model\order\OrderProfit;
use app\model\order\Transactions;
use app\model\user\UserWithdrawalApplications;
use app\model\merchant\MerchantWithdraw;
use app\model\agent\ChannelSettlement;
use app\model\stat\StatRevenueData;
use support\Response;
use madong\utils\Json;
use think\facade\Db;

/**
 * 平台营收统计定时任务
 * 每天凌晨执行,统计昨日的营收数据
 */
class CronRevenueData
{
    private array $logMessages = [];

    /**
     * 定时任务入口
     * @param string|null $date 可选的指定日期,格式:Y-m-d
     * @param bool $force 是否强制重新统计(覆盖已有数据)
     * @return Response
     */
    public function run(?string $date = null, bool $force = false): Response
    {
        try {
            // 重置日志收集器
            $this->logMessages = [];

            // 默认统计昨日,也可通过参数指定
            $statDate = $date ?: date('Y-m-d', strtotime('-1 day'));
            $currentTime = date('Y-m-d H:i:s');

            $this->addLog("========== 平台营收统计开始 ==========");
            $this->addLog("统计日期:{$statDate}");
            $this->addLog("执行时间:{$currentTime}");
            if ($force) {
                $this->addLog("模式:强制重新统计");
            }

            // 检查是否已统计过
            if (!$force) {
                $existCount = StatRevenueData::where('stat_date', $statDate)->count();
                if ($existCount > 0) {
                    $this->addLog("日期 {$statDate} 已统计过,跳过统计");
                    $this->printLogs();
                    return Json::success("数据已存在,跳过统计");
                }
            }

            // 构建时间范围
            $dateStart = $statDate . ' 00:00:00';
            $dateEnd = $statDate . ' 23:59:59';
            $this->addLog("时间范围:{$dateStart} 至 {$dateEnd}");

            // 开始事务
            Db::startTrans();

            try {
                // 如果是强制模式,先删除已有数据
                if ($force) {
                    $deleteCount = StatRevenueData::where('stat_date', $statDate)->delete();
                    if ($deleteCount > 0) {
                        $this->addLog("删除已有数据:{$deleteCount} 条");
                    }
                }

                $year = date('Y', strtotime($statDate));
                $suffix = '_' . $year;

                // 计算营收数据
                $revenueData = $this->calculateRevenueData($statDate, $dateStart, $dateEnd, $suffix);

                // 保存统计数据
                $this->saveRevenueData($statDate, $revenueData);

                // 提交事务
                Db::commit();

                $this->addLog("========== 统计汇总 ==========");
                $this->addLog("完单总金额:{$revenueData['completed_order_amount']}");
                $this->addLog("完单总流水:{$revenueData['completed_revenue']}");
                $this->addLog("平台日流水:{$revenueData['platform_daily_revenue']}");
                $this->addLog("平台营收:{$revenueData['platform_net_revenue']}");
                $this->addLog("平台营收率:" . bcdiv((string)$revenueData['platform_revenue_rate'], '100', 2) . '%');
                $this->addLog("========== 平台营收统计完成 ==========");

                $this->printLogs();
                return Json::success("平台营收统计完成");

            } catch (\Exception $e) {
                Db::rollback();
                throw $e;
            }

        } catch (\Exception $e) {
            $this->addLog("平台营收统计失败:{$e->getMessage()} 在第 {$e->getLine()} 行");
            $this->printLogs();
            return Json::fail("平台营收统计失败:" . $e->getMessage());
        }
    }

    /**
     * 计算营收数据
     */
    private function calculateRevenueData(string $statDate, string $dateStart, string $dateEnd, string $suffix): array
    {
        // 完单总金额:订单状态为已完成的订单金额之和(按实际完单时间筛选)
        $completedOrderAmount = (string)Order::suffix($suffix)
            ->whereIn('order_status',[0,1])
            ->whereIn('hire_pay_status',[1,4])
            ->whereBetween('hire_actual_complete_time', [$dateStart, $dateEnd])
            ->whereIn('order_type',[1,2])
            ->sum('hire_original_prices');

        // 抵扣红包金额:订单状态为已完成的订单中红包实际抵扣金额(按实际完单时间筛选)
        $deductedBonusAmount = (string)Order::suffix($suffix)
            ->whereIn('order_status',[0,1])
            ->whereIn('hire_pay_status',[1,4])
            ->whereBetween('hire_actual_complete_time', [$dateStart, $dateEnd])
            ->whereIn('order_type',[1,2])
            ->sum('hire_coupon_prices');

        // 完单总流水:完单总金额-抵扣红包金额
        $completedRevenue = bcsub($completedOrderAmount, $deductedBonusAmount, 2);

        // 代理总营收:从OrderProfit表按日期筛选已结算的代理佣金
        $agentRevenueResult = OrderProfit::whereBetween('settlement_time', [$dateStart, $dateEnd])
            ->field('SUM(channel_commission + primary_agent_commission + secondary_agent_commission) as total')
            ->find();
        $agentRevenue = (string)($agentRevenueResult['total'] ?? '0.00');

        // 自营商家营收:从OrderProfit表按日期筛选已结算的商户佣金
        $merchantRevenue = (string)OrderProfit::whereBetween('settlement_time', [$dateStart, $dateEnd])
            ->where('settlement_status', 1)
            ->sum('merchant_commission');

        // 账号采购成本:从号源采购账号的成本价格(按实际完单时间筛选)
        $accountPurchaseCost = (string)Order::suffix($suffix)
            ->whereIn('order_status',[0,1])
            ->whereIn('hire_pay_status',[1,4])
            ->whereBetween('hire_actual_complete_time', [$dateStart, $dateEnd])
            ->whereIn('order_type',[1,2])
            ->sum('hire_base_prices');

        $thirdAccountCost = (string)Order::suffix($suffix)
            ->whereIn('order_status',[0,1])
            ->whereIn('hire_pay_status',[1,4])
            ->whereBetween('hire_actual_complete_time', [$dateStart, $dateEnd])
            ->whereIN('third_type',['uhaozu','zuhaowan'])
            ->whereIn('order_type',[1,2])
            ->sum('hire_base_prices');
        $thirdActualAccountCost =  (string)Order::suffix($suffix)
            ->whereIn('order_status',[0,1])
            ->whereIn('hire_pay_status',[1,4])
            ->whereBetween('hire_actual_complete_time', [$dateStart, $dateEnd])
            ->whereIN('third_type',['uhaozu','zuhaowan'])
            ->whereIn('order_type',[1,2])
            ->sum('hire_third_actual_order_prices');

        $accountPurchaseCost =  bcsub($accountPurchaseCost,bcsub($thirdAccountCost,$thirdActualAccountCost,2),2);

        // VIP认证流水:开通VIP的认证的实际支付总金额
        $vipCertificationRevenue = (string)VipSubscriptionRecords::whereBetween('create_time', [$dateStart, $dateEnd])
            ->where('payment_status', 1)
            ->sum('actual_paid');

        // 商户认证流水:自营商家认证的实际支付的总金额
        $merchantCertificationRevenue = (string)MerchantCertOrder::whereBetween('pay_time', [$dateStart, $dateEnd])
            ->where('pay_status', 1)
            ->sum('money');

        // 提现手续费:按你的逻辑,需要三个表的手续费相加
        // 用户提现手续费
        $userWithdrawFee = (string)UserWithdrawalApplications::whereBetween('completion_time', [$dateStart, $dateEnd])
            ->where('status', 2)
            ->sum('fee_amount');

        // 商户提现手续费
        $merchantWithdrawFee = (string)MerchantWithdraw::whereBetween('transfer_time', [$dateStart, $dateEnd])
            ->where('status', 3)
            ->sum('service_money');

        // 渠道提现手续费
        $channelWithdrawFee = (string)ChannelSettlement::whereBetween('process_time', [$dateStart, $dateEnd])
            ->where('status', 1)
            ->sum('service_fee');

        // 总提现手续费
        $withdrawalFee = bcadd(bcadd($userWithdrawFee, $merchantWithdrawFee, 2), $channelWithdrawFee, 2);

        // 平台日流水:完单总流水+ VIP认证流水+商户认证流水
        $platformDailyRevenue = bcadd(
            bcadd($completedRevenue, $vipCertificationRevenue, 2),
            $merchantCertificationRevenue,
            2
        );

        // 平台营收:根据你提供的累积平台收入计算逻辑
        // 用户第三方支付收入
        $userThirdRevenue = (string)Transactions::suffix($suffix)
            ->where('payment_status', 1)
            ->where('refund_status', 0)
            ->whereBetween('create_time', [$dateStart, $dateEnd])
            ->sum('paid_amount');

        $userThirdCost = (string)Transactions::suffix($suffix)
            ->where('payment_status', 1)
            ->whereIn('refund_status', [1, 2])
            ->whereBetween('create_time', [$dateStart, $dateEnd])
            ->sum('refund_amount');

        $userThirdTotalRevenue = bcsub($userThirdRevenue, $userThirdCost, 2);

        // 商户第三方支付收入
        $merchantThirdTotalRevenue = (string)Payment::where('pay_status', 1)
            ->whereIn('pay_type', ['wechat', 'alipay'])
            ->whereBetween('create_time', [$dateStart, $dateEnd])
            ->sum('money');

        // 按照你的平台收入计算公式:
        // 用户提现手续费+商户提现手续费+渠道手续费+用户第三方支付收入+商户第三方支付收入-账号成本-代理营收-商户营收
        $platformNetRevenue = bcadd($withdrawalFee, $userThirdTotalRevenue, 2);
        $platformNetRevenue = bcadd($platformNetRevenue, $merchantThirdTotalRevenue, 2);
        $platformNetRevenue = bcsub($platformNetRevenue, $accountPurchaseCost, 2);
        $platformNetRevenue = bcsub($platformNetRevenue, $agentRevenue, 2);
        $platformNetRevenue = bcsub($platformNetRevenue, $merchantRevenue, 2);

        // 平台营收率:平台营收/平台日流水 (存储时乘以10000)
        $platformRevenueRate = '0.0000';
        if (bccomp($platformDailyRevenue, '0', 2) > 0) {
            $platformRevenueRate = bcdiv($platformNetRevenue, $platformDailyRevenue, 4);
        }

        return [
            'completed_order_amount' => $completedOrderAmount,
            'deducted_bonus_amount' => $deductedBonusAmount,
            'completed_revenue' => $completedRevenue,
            'agent_revenue' => $agentRevenue,
            'merchant_revenue' => $merchantRevenue,
            'account_purchase_cost' => $accountPurchaseCost,
            'vip_certification_revenue' => $vipCertificationRevenue,
            'merchant_certification_revenue' => $merchantCertificationRevenue,
            'withdrawal_fee' => $withdrawalFee,
            'platform_daily_revenue' => $platformDailyRevenue,
            'platform_net_revenue' => $platformNetRevenue,
            'platform_revenue_rate' => (int)bcmul($platformRevenueRate, '10000', 0)
        ];
    }

    /**
     * 保存营收数据
     */
    private function saveRevenueData(string $statDate, array $data): void
    {
        StatRevenueData::create([
            'stat_date' => $statDate,
            'completed_order_amount' => $data['completed_order_amount'],
            'deducted_bonus_amount' => $data['deducted_bonus_amount'],
            'completed_revenue' => $data['completed_revenue'],
            'agent_revenue' => $data['agent_revenue'],
            'merchant_revenue' => $data['merchant_revenue'],
            'account_purchase_cost' => $data['account_purchase_cost'],
            'vip_certification_revenue' => $data['vip_certification_revenue'],
            'merchant_certification_revenue' => $data['merchant_certification_revenue'],
            'withdrawal_fee' => $data['withdrawal_fee'],
            'platform_daily_revenue' => $data['platform_daily_revenue'],
            'platform_net_revenue' => $data['platform_net_revenue'],
            'platform_revenue_rate' => $data['platform_revenue_rate']
        ]);
    }

    /**
     * 添加日志信息
     */
    private function addLog(string $message): void
    {
        $this->logMessages[] = $message;
    }

    /**
     * 打印所有日志
     */
    private function printLogs(): void
    {
        $fullLog = implode("\n", $this->logMessages);
        sea_log($fullLog);
    }
}