<?php
declare(strict_types=1);
namespace app\services\stat;
use app\model\agent\Channel;
use app\model\agent\ChannelBalanceLog;
use app\model\agent\ChannelSettlement;
use app\model\basic\Payment;
use app\model\merchant\Merchant;
use app\model\merchant\MerchantAccount;
use app\model\merchant\MerchantWithdraw;
use app\model\order\Order;
use app\model\order\OrderProfit;
use app\model\order\Transactions;
use app\model\order\TransactionsLogs;
use app\model\system\SystemLoginLog;
use app\model\system\SystemUser;
use app\model\user\UserWallets;
use app\model\user\UserWithdrawalApplications;
use app\model\stat\StatDataBoard;
use support\exception\BusinessException;
use think\facade\Db;
class DataBoardService
{
const CHANNEL_TYPE_PLATFORM = 0;
const CHANNEL_TYPE_OFFICIAL = 1;
const CHANNEL_TYPE_CHANNEL = 2;
public static function getDataBoard(array $params): array
{
$suffix = '_'.date('Y');
$cumulative_registered_users = (string)SystemUser::count('id');
$cumulative_paid_users = (string)TransactionsLogs::suffix($suffix)->whereIn('type',[1,3,5])->count('DISTINCT user_id');
$payment_rate_raw = $cumulative_registered_users > 0 ?
bcdiv(bcmul($cumulative_paid_users, '10000', 0), $cumulative_registered_users, 0) : 0;
$payment_rate = bcdiv((string)$payment_rate_raw, '100', 2);
$cumulative_paid_orders = (string)Order::suffix($suffix)->whereIn('hire_pay_status',[1,4])->whereIn('order_type',[1,2])->count('id');
$cumulative_completed_orders = (string)Order::suffix($suffix)->where('order_status',1)->whereIn('order_type',[1,2])->count('id');
$completion_rate_raw = $cumulative_paid_orders > 0 ?
bcdiv(bcmul($cumulative_completed_orders, '10000', 0), $cumulative_paid_orders, 0) : 0;
$completion_rate = bcdiv((string)$completion_rate_raw, '100', 2);
$cumulative_duration_hours_raw = (string)Order::suffix($suffix)->where('order_status',1)->whereIn('order_type',[1,2])->sum('hire_real_times');
$cumulative_duration_hours = bcdiv($cumulative_duration_hours_raw, '1', 1);
$cumulative_gmv = (string)Order::suffix($suffix)->where('order_status',1)->whereIn('order_type',[1,2])->sum('hire_order_prices');
$avg_order_amount = $cumulative_completed_orders > 0 ?
bcdiv($cumulative_gmv, $cumulative_completed_orders, 2) : '0.00';
$cumulative_user_total_revenue = (string)TransactionsLogs::suffix($suffix)->sum('amount');
$cumulative_merchant_total_revenue = (string)MerchantAccount::sum('account');
$cumulative_channel_total_revenue = (string)ChannelBalanceLog::sum('amount');
$cumulative_user_withdraw_service_fee_total_revenue = (string)UserWithdrawalApplications::where('status',2)->sum('fee_amount');
$cumulative_merchant_withdraw_service_fee_total_revenue = (string)MerchantWithdraw::where('status',3)->sum('service_money');
$cumulative_channel_withdraw_service_fee_total_revenue = (string)ChannelSettlement::where('status',1)->sum('service_fee');
$cumulative_account_cost = (string)Order::suffix($suffix)->where('order_status',1)->whereIn('order_type',[1,2])->sum('hire_base_prices');
$cumulative_merchant_revenue = (string)OrderProfit::where('settlement_status',1)->sum('merchant_commission');
$result = OrderProfit::where('settlement_status', 1)
->field('SUM(channel_commission + primary_agent_commission + secondary_agent_commission) as total')
->find();
$cumulative_channel_revenue = (string)($result['total'] ?? '0.00');
$cumulative_user_third_revenue = (string)Transactions::suffix($suffix)->where('payment_status',1)->where('refund_status',0)->sum('paid_amount');
$cumulative_user_third_cost = (string)Transactions::suffix($suffix)->where('payment_status',1)->whereIn('refund_status',[1,2])->sum('refund_amount');
$cumulative_user_third_total_revenue = bcsub($cumulative_user_third_revenue, $cumulative_user_third_cost, 2);
$cumulative_merchant_third_total_revenue = (string)Payment::where('pay_status',1)->whereIn('pay_type',['wechat','alipay'])->sum('money');
$cumulative_platform_revenue = bcadd($cumulative_user_withdraw_service_fee_total_revenue, $cumulative_merchant_withdraw_service_fee_total_revenue, 2);
$cumulative_platform_revenue = bcadd($cumulative_platform_revenue, $cumulative_channel_withdraw_service_fee_total_revenue, 2);
$cumulative_platform_revenue = bcadd($cumulative_platform_revenue, $cumulative_user_third_total_revenue, 2);
$cumulative_platform_revenue = bcadd($cumulative_platform_revenue, $cumulative_merchant_third_total_revenue, 2);
$cumulative_platform_revenue = bcsub($cumulative_platform_revenue, $cumulative_user_total_revenue, 2);
$cumulative_platform_revenue = bcsub($cumulative_platform_revenue, $cumulative_merchant_total_revenue, 2);
$cumulative_platform_revenue = bcsub($cumulative_platform_revenue, $cumulative_channel_total_revenue, 2);
$cumulative_platform_revenue = bcsub($cumulative_platform_revenue, $cumulative_account_cost, 2);
return [
'cumulative_registered_users' => $cumulative_registered_users,
'cumulative_paid_users' => $cumulative_paid_users,
'payment_rate' => $payment_rate,
'cumulative_paid_orders' => $cumulative_paid_orders,
'cumulative_completed_orders' => $cumulative_completed_orders,
'completion_rate' => $completion_rate,
'cumulative_duration_hours' => $cumulative_duration_hours,
'avg_order_amount' => number_format((float)$avg_order_amount, 2),
'cumulative_gmv' => number_format((float)$cumulative_gmv, 2),
'cumulative_platform_revenue' => number_format((float)$cumulative_platform_revenue, 2),
'cumulative_channel_revenue' => number_format((float)$cumulative_channel_revenue, 2),
'cumulative_merchant_revenue' => number_format((float)$cumulative_merchant_revenue, 2),
];
}
public static function getTimeData(array $params): array
{
if (empty($params['time_type']) || !in_array($params['time_type'], ['realtime', 'lastSevenDays'])) {
throw new BusinessException('time_type只能为realtime,lastSevenDays');
}
if ($params['time_type'] === 'realtime') {
$yesterday = date('Y-m-d', strtotime('-1 day'));
return [
'today' => [
'platform' => self::getTodayData(self::CHANNEL_TYPE_PLATFORM),
'official' => self::getTodayData(self::CHANNEL_TYPE_OFFICIAL),
'channel' => self::getTodayData(self::CHANNEL_TYPE_CHANNEL),
],
'yesterday' => [
'platform' => self::getHistoryData($yesterday, self::CHANNEL_TYPE_PLATFORM),
'official' => self::getHistoryData($yesterday, self::CHANNEL_TYPE_OFFICIAL),
'channel' => self::getHistoryData($yesterday, self::CHANNEL_TYPE_CHANNEL),
]
];
} else {
$result = [];
for ($i = 6; $i >= 0; $i--) {
$date = date('Y-m-d', strtotime("-{$i} day"));
$result[$date] = $i === 0 ?
self::getTodayData(self::CHANNEL_TYPE_PLATFORM) :
self::getHistoryData($date, self::CHANNEL_TYPE_PLATFORM);
}
return $result;
}
}
private static function getTodayData(int $channelType): array
{
switch ($channelType) {
case self::CHANNEL_TYPE_PLATFORM:
return self::getPlatformTodayData();
case self::CHANNEL_TYPE_OFFICIAL:
return self::getOfficialTodayData();
case self::CHANNEL_TYPE_CHANNEL:
return self::getChannelTodayData();
default:
throw new BusinessException('无效的渠道类型');
}
}
private static function getHistoryData(string $date, int $channelType): array
{
$statsData = StatDataBoard::where('stat_date', $date)
->where('channel_type', $channelType)
->find();
if ($statsData) {
$data = $statsData->toArray();
$data = self::formatRateFields($data);
return self::formatMoneyFields($data);
}
return self::calculateHistoryData($date, $channelType);
}
private static function getPlatformTodayData(): array
{
$suffix = '_'.date('Y');
$today_start_date = date('Y-m-d 00:00:00');
$today_start_time = strtotime($today_start_date);
$today_end_date = date('Y-m-d 23:59:59');
$today_end_time = strtotime($today_end_date);
$today_date_start_to_end = [$today_start_date, $today_end_date];
$today_time_start_to_end = [$today_start_time, $today_end_time];
$new_users = (int)SystemUser::whereBetween('create_time', $today_time_start_to_end)->count('id');
$active_users = (int)SystemLoginLog::whereBetween('login_time', $today_time_start_to_end)
->where('status', 1)
->count('DISTINCT user_id');
$paying_users = (int)TransactionsLogs::suffix($suffix)
->whereIn('type',[1,3,4,5])
->whereBetween('create_time', $today_date_start_to_end)
->count('DISTINCT user_id');
$completed_order_users = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->count('DISTINCT user_id');
$payment_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$paying_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$paid_orders = (int)Order::suffix($suffix)
->whereIn('hire_pay_status',[1,4])
->whereBetween('create_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->count('id');
$completed_orders = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->count('id');
$completion_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$completed_order_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$total_completed_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->sum('hire_original_prices');
$coupon_deduction_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->sum('hire_coupon_prices');
$total_completed_revenue = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->sum(Db::raw('hire_order_prices'));
$paying_arpu = $completed_order_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$completed_order_users,0) : 0;
$active_arpu = $active_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$active_users,0) : 0;
$total_completed_duration = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->whereIn('order_type',[1,2])
->sum('hire_real_times');
$avg_order_duration = $completed_orders > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_orders,0) : 0;
$avg_user_duration = $completed_order_users > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_order_users,0) : 0;
$avg_orders_per_user = $completed_order_users > 0 ? (int)bcdiv((string)$completed_orders,(string)$completed_order_users,0) : 0;
$revenueData = self::calculateTodayRevenue($today_date_start_to_end, $today_time_start_to_end);
return [
'new_users' => $new_users,
'active_users' => $active_users,
'paying_users' => $paying_users,
'completed_order_users' => $completed_order_users,
'payment_rate' => $payment_rate,
'completion_rate' => $completion_rate,
'paid_orders' => $paid_orders,
'completed_orders' => $completed_orders,
'total_completed_amount' => number_format((float)$total_completed_amount, 2),
'coupon_deduction_amount' => number_format((float)$coupon_deduction_amount, 2),
'total_completed_revenue' => number_format((float)$total_completed_revenue, 2),
'paying_arpu' => $paying_arpu,
'active_arpu' => $active_arpu,
'total_completed_duration' => $total_completed_duration,
'avg_order_duration' => $avg_order_duration,
'avg_user_duration' => $avg_user_duration,
'avg_orders_per_user' => $avg_orders_per_user,
'merchant_revenue' => number_format((float)$revenueData['merchant_revenue'], 2),
'channel_revenue' => number_format((float)$revenueData['channel_revenue'], 2),
'platform_revenue' => number_format((float)$revenueData['platform_revenue'], 2),
];
}
private static function getOfficialTodayData(): array
{
$suffix = '_'.date('Y');
$today_start_date = date('Y-m-d 00:00:00');
$today_start_time = strtotime($today_start_date);
$today_end_date = date('Y-m-d 23:59:59');
$today_end_time = strtotime($today_end_date);
$today_date_start_to_end = [$today_start_date, $today_end_date];
$today_time_start_to_end = [$today_start_time, $today_end_time];
$new_users = (int)SystemUser::whereBetween('create_time', $today_time_start_to_end)
->where('channel_id',0)->count('id');
$active_users = (int)SystemLoginLog::alias('sll')
->whereBetween('sll.login_time', $today_time_start_to_end)
->where('sll.status', 1)
->whereIn('sll.user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', 0);
})
->count('DISTINCT sll.user_id');
$paying_users = (int)TransactionsLogs::suffix($suffix)
->alias('tl')
->whereIn('tl.type',[1,3,4,5])
->whereBetween('tl.create_time', $today_date_start_to_end)
->whereIn('tl.user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', 0);
})
->count('DISTINCT tl.user_id');
$completed_order_users = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->count('DISTINCT user_id');
$payment_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$paying_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$paid_orders = (int)Order::suffix($suffix)->whereIn('hire_pay_status',[1,4])
->whereBetween('create_time', $today_date_start_to_end)->where('channel_id',0)->count('id');
$completed_orders = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->count('id');
$completion_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$completed_order_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$total_completed_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->sum('hire_original_prices');
$coupon_deduction_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->sum('hire_coupon_prices');
$total_completed_revenue = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->sum(Db::raw('hire_order_prices'));
$paying_arpu = $completed_order_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$completed_order_users,0) : 0;
$active_arpu = $active_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$active_users,0) : 0;
$total_completed_duration = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id',0)
->whereIn('order_type',[1,2])
->sum('hire_real_times');
$avg_order_duration = $completed_orders > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_orders,0) : 0;
$avg_user_duration = $completed_order_users > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_order_users,0) : 0;
$avg_orders_per_user = $completed_order_users > 0 ? (int)bcdiv((string)$completed_orders,(string)$completed_order_users,0) : 0;
$revenueData = self::calculateTodayRevenue($today_date_start_to_end, $today_time_start_to_end);
return [
'new_users' => $new_users,
'active_users' => $active_users,
'paying_users' => $paying_users,
'completed_order_users' => $completed_order_users,
'payment_rate' => $payment_rate,
'completion_rate' => $completion_rate,
'paid_orders' => $paid_orders,
'completed_orders' => $completed_orders,
'total_completed_amount' => number_format((float)$total_completed_amount, 2),
'coupon_deduction_amount' => number_format((float)$coupon_deduction_amount, 2),
'total_completed_revenue' => number_format((float)$total_completed_revenue, 2),
'paying_arpu' => $paying_arpu,
'active_arpu' => $active_arpu,
'total_completed_duration' => $total_completed_duration,
'avg_order_duration' => $avg_order_duration,
'avg_user_duration' => $avg_user_duration,
'avg_orders_per_user' => $avg_orders_per_user,
'merchant_revenue' => number_format((float)$revenueData['merchant_revenue'], 2),
'channel_revenue' => number_format((float)$revenueData['channel_revenue'], 2),
'platform_revenue' => number_format((float)$revenueData['platform_revenue'], 2),
];
}
private static function getChannelTodayData(): array
{
$suffix = '_'.date('Y');
$today_start_date = date('Y-m-d 00:00:00');
$today_start_time = strtotime($today_start_date);
$today_end_date = date('Y-m-d 23:59:59');
$today_end_time = strtotime($today_end_date);
$today_date_start_to_end = [$today_start_date, $today_end_date];
$today_time_start_to_end = [$today_start_time, $today_end_time];
$new_users = (int)SystemUser::whereBetween('create_time', $today_time_start_to_end)
->where('channel_id','>',0)->count('id');
$active_users = (int)SystemLoginLog::alias('sll')
->whereBetween('sll.login_time', $today_time_start_to_end)
->where('sll.status', 1)
->whereIn('sll.user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', '>', 0);
})
->count('DISTINCT sll.user_id');
$paying_users = (int)TransactionsLogs::suffix($suffix)
->alias('tl')
->whereIn('tl.type',[1,3,4,5])
->whereBetween('tl.create_time', $today_date_start_to_end)
->whereIn('tl.user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', '>', 0);
})
->count('DISTINCT tl.user_id');
$completed_order_users = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->count('DISTINCT user_id');
$payment_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$paying_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$paid_orders = (int)Order::suffix($suffix)->whereIn('hire_pay_status',[1,4])
->whereBetween('create_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->count('id');
$completed_orders = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->count('id');
$completion_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$completed_order_users,(string)$active_users,4),'10000',0),'100',2) : '0.00';
$total_completed_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->sum('hire_original_prices');
$coupon_deduction_amount = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->sum('hire_coupon_prices');
$total_completed_revenue = (string)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->sum(Db::raw('hire_order_prices'));
$paying_arpu = $completed_order_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$completed_order_users,0) : 0;
$active_arpu = $active_users > 0 ? (int)bcdiv($total_completed_revenue,(string)$active_users,0) : 0;
$total_completed_duration = (int)Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $today_date_start_to_end)
->where('channel_id','>',0)
->whereIn('order_type',[1,2])
->sum('hire_real_times');
$avg_order_duration = $completed_orders > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_orders,0) : 0;
$avg_user_duration = $completed_order_users > 0 ? (int)bcdiv((string)$total_completed_duration,(string)$completed_order_users,0) : 0;
$avg_orders_per_user = $completed_order_users > 0 ? (int)bcdiv((string)$completed_orders,(string)$completed_order_users,0) : 0;
$revenueData = self::calculateTodayRevenue($today_date_start_to_end, $today_time_start_to_end);
return [
'new_users' => $new_users,
'active_users' => $active_users,
'paying_users' => $paying_users,
'completed_order_users' => $completed_order_users,
'payment_rate' => $payment_rate,
'completion_rate' => $completion_rate,
'paid_orders' => $paid_orders,
'completed_orders' => $completed_orders,
'total_completed_amount' => number_format((float)$total_completed_amount, 2),
'coupon_deduction_amount' => number_format((float)$coupon_deduction_amount, 2),
'total_completed_revenue' => number_format((float)$total_completed_revenue, 2),
'paying_arpu' => $paying_arpu,
'active_arpu' => $active_arpu,
'total_completed_duration' => $total_completed_duration,
'avg_order_duration' => $avg_order_duration,
'avg_user_duration' => $avg_user_duration,
'avg_orders_per_user' => $avg_orders_per_user,
'merchant_revenue' => number_format((float)$revenueData['merchant_revenue'], 2),
'channel_revenue' => number_format((float)$revenueData['channel_revenue'], 2),
'platform_revenue' => number_format((float)$revenueData['platform_revenue'], 2),
];
}
private static function calculateHistoryData(string $date, int $channelType): array
{
$suffix = '_'.date('Y', strtotime($date));
$start_date = $date . ' 00:00:00';
$end_date = $date . ' 23:59:59';
$start_time = strtotime($start_date);
$end_time = strtotime($end_date);
$date_range = [$start_date, $end_date];
$time_range = [$start_time, $end_time];
$userQuery = SystemUser::whereBetween('create_time', $time_range);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$userQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$userQuery->where('channel_id', '>', 0);
break;
}
$new_users = (int)$userQuery->count('id');
$activeQuery = SystemLoginLog::whereBetween('login_time', $time_range)->where('status', 1);
switch ($channelType) {
case self::CHANNEL_TYPE_PLATFORM:
$active_users = (int)$activeQuery
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_OFFICIAL:
$active_users = (int)$activeQuery
->whereIn('user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', 0);
})
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_CHANNEL:
$active_users = (int)$activeQuery
->whereIn('user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', '>', 0);
})
->count('DISTINCT user_id');
break;
default:
$active_users = 0;
}
$payingQuery = TransactionsLogs::suffix($suffix)
->whereIn('type', [1, 3, 4, 5])
->whereBetween('create_time', $date_range);
switch ($channelType) {
case self::CHANNEL_TYPE_PLATFORM:
$paying_users = (int)$payingQuery
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_OFFICIAL:
$paying_users = (int)$payingQuery
->whereIn('user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', 0);
})
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_CHANNEL:
$paying_users = (int)$payingQuery
->whereIn('user_id', function($query) {
$query->field('id')->table('rk_system_user')->where('channel_id', '>', 0);
})
->count('DISTINCT user_id');
break;
default:
$paying_users = 0;
}
$orderQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereIn('order_type',[1,2])
->whereBetween('hire_actual_complete_time', $date_range);
switch ($channelType) {
case self::CHANNEL_TYPE_PLATFORM:
$completed_order_users = (int)$orderQuery
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_OFFICIAL:
$completed_order_users = (int)$orderQuery
->where('channel_id', 0)
->count('DISTINCT user_id');
break;
case self::CHANNEL_TYPE_CHANNEL:
$completed_order_users = (int)$orderQuery
->where('channel_id', '>', 0)
->count('DISTINCT user_id');
break;
default:
$completed_order_users = 0;
}
$payment_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$paying_users, (string)$active_users, 4), '10000', 0), '100', 2) : '0.00';
$paidOrderQuery = Order::suffix($suffix)
->whereIn('hire_pay_status', [1, 4])
->whereBetween('create_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$paidOrderQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$paidOrderQuery->where('channel_id', '>', 0);
break;
}
$paid_orders = (int)$paidOrderQuery->count('id');
$completedOrderQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$completedOrderQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$completedOrderQuery->where('channel_id', '>', 0);
break;
}
$completed_orders = (int)$completedOrderQuery->count('id');
$completion_rate = $active_users > 0 ? bcdiv((string)bcmul(bcdiv((string)$completed_order_users, (string)$active_users, 4), '10000', 0), '100', 2) : '0.00';
$amountQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$amountQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$amountQuery->where('channel_id', '>', 0);
break;
}
$total_completed_amount = (string)$amountQuery->sum('hire_original_prices');
$couponQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$couponQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$couponQuery->where('channel_id', '>', 0);
break;
}
$coupon_deduction_amount = (string)$couponQuery->sum('hire_coupon_prices');
$revenueQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$revenueQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$revenueQuery->where('channel_id', '>', 0);
break;
}
$total_completed_revenue = (string)$revenueQuery->sum(Db::raw('hire_order_prices'));
$paying_arpu = $completed_order_users > 0 ? (int)bcdiv($total_completed_revenue, (string)$completed_order_users, 0) : 0;
$active_arpu = $active_users > 0 ? (int)bcdiv($total_completed_revenue, (string)$active_users, 0) : 0;
$durationQuery = Order::suffix($suffix)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->whereBetween('hire_actual_complete_time', $date_range)
->whereIn('order_type',[1,2]);
switch ($channelType) {
case self::CHANNEL_TYPE_OFFICIAL:
$durationQuery->where('channel_id', 0);
break;
case self::CHANNEL_TYPE_CHANNEL:
$durationQuery->where('channel_id', '>', 0);
break;
}
$total_completed_duration = (int)$durationQuery->sum('hire_real_times');
$avg_order_duration = $completed_orders > 0 ? (int)bcdiv((string)$total_completed_duration, (string)$completed_orders, 0) : 0;
$avg_user_duration = $completed_order_users > 0 ? (int)bcdiv((string)$total_completed_duration, (string)$completed_order_users, 0) : 0;
$avg_orders_per_user = $completed_order_users > 0 ? (int)bcdiv((string)$completed_orders, (string)$completed_order_users, 0) : 0;
$revenueData = self::calculateHistoryRevenue($date_range);
return [
'new_users' => $new_users,
'active_users' => $active_users,
'paying_users' => $paying_users,
'completed_order_users' => $completed_order_users,
'payment_rate' => $payment_rate,
'completion_rate' => $completion_rate,
'paid_orders' => $paid_orders,
'completed_orders' => $completed_orders,
'total_completed_amount' => number_format((float)$total_completed_amount, 2),
'coupon_deduction_amount' => number_format((float)$coupon_deduction_amount, 2),
'total_completed_revenue' => number_format((float)$total_completed_revenue, 2),
'paying_arpu' => $paying_arpu,
'active_arpu' => $active_arpu,
'total_completed_duration' => $total_completed_duration,
'avg_order_duration' => $avg_order_duration,
'avg_user_duration' => $avg_user_duration,
'avg_orders_per_user' => $avg_orders_per_user,
'merchant_revenue' => number_format((float)$revenueData['merchant_revenue'], 2),
'channel_revenue' => number_format((float)$revenueData['channel_revenue'], 2),
'platform_revenue' => number_format((float)$revenueData['platform_revenue'], 2),
];
}
private static function formatMoneyFields(array $data): array
{
$moneyFields = [
'total_completed_amount',
'coupon_deduction_amount',
'total_completed_revenue',
'merchant_revenue',
'channel_revenue',
'platform_revenue',
];
foreach ($moneyFields as $field) {
if (isset($data[$field])) {
$data[$field] = number_format((float)$data[$field], 2);
}
}
$durationFields = [
'total_completed_duration',
'avg_order_duration',
'avg_user_duration'
];
foreach ($durationFields as $field) {
if (isset($data[$field])) {
$data[$field] = bcdiv((string)$data[$field], '10', 1);
}
}
return $data;
}
private static function formatRateFields(array $data): array
{
$rateFields = ['payment_rate', 'completion_rate'];
foreach ($rateFields as $field) {
if (isset($data[$field])) {
$data[$field] = bcdiv((string)$data[$field], '100', 2);
}
}
return $data;
}
private static function calculateTodayRevenue(array $dateRange, array $timeRange): array
{
$suffix = '_' . date('Y');
$user_total_revenue = (string)TransactionsLogs::suffix($suffix)
->whereBetween('create_time', $dateRange)
->sum('amount');
$merchant_total_revenue = (string)MerchantAccount::whereBetween('create_time', $dateRange)
->sum('account');
$channel_total_revenue = (string)ChannelBalanceLog::whereBetween('create_time', $dateRange)
->sum('amount');
$user_withdraw_service_fee = (string)UserWithdrawalApplications::whereBetween('completion_time', $dateRange)
->where('status', 2)
->sum('fee_amount');
$merchant_withdraw_service_fee = (string)MerchantWithdraw::whereBetween('transfer_time', $dateRange)
->where('status', 3)
->sum('service_money');
$channel_withdraw_service_fee = (string)ChannelSettlement::whereBetween('process_time', $dateRange)
->where('status', 1)
->sum('service_fee');
$account_cost = (string)Order::suffix($suffix)
->whereBetween('hire_actual_complete_time', $dateRange)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->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', $dateRange)
->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', $dateRange)
->whereIN('third_type',['uhaozu','zuhaowan'])
->whereIn('order_type',[1,2])
->sum('hire_third_actual_order_prices');
$account_cost = bcsub($account_cost,bcsub($thirdAccountCost,$thirdActualAccountCost,2),2);
$merchant_revenue = (string)OrderProfit::whereBetween('settlement_time', $dateRange)
->where('settlement_status', 1)
->sum('merchant_commission');
$result = OrderProfit::whereBetween('settlement_time', $dateRange)
->where('settlement_status', 1)
->field('SUM(channel_commission + primary_agent_commission + secondary_agent_commission) as total')
->find();
$channel_revenue = (string)($result['total'] ?? '0.00');
$user_third_revenue = (string)Transactions::suffix($suffix)
->whereBetween('create_time', $dateRange)
->where('payment_status', 1)
->where('refund_status', 0)
->sum('paid_amount');
$user_third_cost = (string)Transactions::suffix($suffix)
->whereBetween('create_time', $dateRange)
->where('payment_status', 1)
->whereIn('refund_status', [1, 2])
->sum('refund_amount');
$user_third_total_revenue = bcsub($user_third_revenue, $user_third_cost, 2);
$merchant_third_total_revenue = (string)Payment::whereBetween('create_time', $dateRange)
->where('pay_status', 1)
->whereIn('pay_type', ['wechat', 'alipay'])
->sum('money');
$platform_revenue = bcadd($user_withdraw_service_fee, $merchant_withdraw_service_fee, 2);
$platform_revenue = bcadd($platform_revenue, $channel_withdraw_service_fee, 2);
$platform_revenue = bcadd($platform_revenue, $user_third_total_revenue, 2);
$platform_revenue = bcadd($platform_revenue, $merchant_third_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $user_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $merchant_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $channel_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $account_cost, 2);
return [
'merchant_revenue' => $merchant_revenue,
'channel_revenue' => $channel_revenue,
'platform_revenue' => $platform_revenue,
'user_withdraw_service_fee' => $user_withdraw_service_fee,
'merchant_withdraw_service_fee' => $merchant_withdraw_service_fee,
'channel_withdraw_service_fee' => $channel_withdraw_service_fee,
'user_third_total_revenue' => $user_third_total_revenue,
'merchant_third_total_revenue' => $merchant_third_total_revenue,
'account_cost' => $account_cost,
];
}
private static function calculateHistoryRevenue(array $dateRange): array
{
$suffix = '_' . date('Y', strtotime($dateRange[0]));
$user_total_revenue = (string)TransactionsLogs::suffix($suffix)
->whereBetween('create_time', $dateRange)
->sum('amount');
$merchant_total_revenue = (string)MerchantAccount::whereBetween('create_time', $dateRange)
->sum('account');
$channel_total_revenue = (string)ChannelBalanceLog::whereBetween('create_time', $dateRange)
->sum('amount');
$user_withdraw_service_fee = (string)UserWithdrawalApplications::whereBetween('completion_time', $dateRange)
->where('status', 2)
->sum('fee_amount');
$merchant_withdraw_service_fee = (string)MerchantWithdraw::whereBetween('transfer_time', $dateRange)
->where('status', 3)
->sum('service_money');
$channel_withdraw_service_fee = (string)ChannelSettlement::whereBetween('process_time', $dateRange)
->where('status', 1)
->sum('service_fee');
$account_cost = (string)Order::suffix($suffix)
->whereBetween('hire_actual_complete_time', $dateRange)
->whereIn('order_status',[0,1])
->whereIn('hire_pay_status',[1,4])
->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', $dateRange)
->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', $dateRange)
->whereIN('third_type',['uhaozu','zuhaowan'])
->whereIn('order_type',[1,2])
->sum('hire_third_actual_order_prices');
$account_cost = bcsub($account_cost,bcsub($thirdAccountCost,$thirdActualAccountCost,2),2);
$merchant_revenue = (string)OrderProfit::whereBetween('settlement_time', $dateRange)
->where('settlement_status', 1)
->sum('merchant_commission');
$result = OrderProfit::whereBetween('settlement_time', $dateRange)
->where('settlement_status', 1)
->field('SUM(channel_commission + primary_agent_commission + secondary_agent_commission) as total')
->find();
$channel_revenue = (string)($result['total'] ?? '0.00');
$user_third_revenue = (string)Transactions::suffix($suffix)
->whereBetween('create_time', $dateRange)
->where('payment_status', 1)
->where('refund_status', 0)
->sum('paid_amount');
$user_third_cost = (string)Transactions::suffix($suffix)
->whereBetween('create_time', $dateRange)
->where('payment_status', 1)
->whereIn('refund_status', [1, 2])
->sum('refund_amount');
$user_third_total_revenue = bcsub($user_third_revenue, $user_third_cost, 2);
$merchant_third_total_revenue = (string)Payment::whereBetween('create_time', $dateRange)
->where('pay_status', 1)
->whereIn('pay_type', ['wechat', 'alipay'])
->sum('money');
$platform_revenue = bcadd($user_withdraw_service_fee, $merchant_withdraw_service_fee, 2);
$platform_revenue = bcadd($platform_revenue, $channel_withdraw_service_fee, 2);
$platform_revenue = bcadd($platform_revenue, $user_third_total_revenue, 2);
$platform_revenue = bcadd($platform_revenue, $merchant_third_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $user_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $merchant_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $channel_total_revenue, 2);
$platform_revenue = bcsub($platform_revenue, $account_cost, 2);
return [
'merchant_revenue' => $merchant_revenue,
'channel_revenue' => $channel_revenue,
'platform_revenue' => $platform_revenue,
'user_withdraw_service_fee' => $user_withdraw_service_fee,
'merchant_withdraw_service_fee' => $merchant_withdraw_service_fee,
'channel_withdraw_service_fee' => $channel_withdraw_service_fee,
'user_third_total_revenue' => $user_third_total_revenue,
'merchant_third_total_revenue' => $merchant_third_total_revenue,
'account_cost' => $account_cost,
];
}
}