<?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 = [];
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);
$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');
$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);
$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);
$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);
$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);
}
}