feat(risk): 支持按开注商隔离风险池并新增经营报表
This commit is contained in:
@@ -478,6 +478,39 @@ final class AdminReportQueryService
|
||||
return $query->paginate($perPage, ['*'], 'page', $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开注商经营汇总。多开注商会将一笔订单拆为多个注项,故必须以 ticket_items 为统计口径。
|
||||
*/
|
||||
public function providerProfitPaginated(
|
||||
string $dateFrom,
|
||||
string $dateTo,
|
||||
int $page,
|
||||
int $perPage,
|
||||
AdminUser|AdminScopeContext|null $scope = null,
|
||||
): LengthAwarePaginator {
|
||||
$context = $this->normalizeScope($scope);
|
||||
$providerCodeSql = "COALESCE(NULLIF(ti.provider_code, ''), 'SG')";
|
||||
|
||||
$query = DB::table('ticket_items as ti')
|
||||
->join('ticket_orders as o', 'o.id', '=', 'ti.order_id')
|
||||
->join('draws as d', 'd.id', '=', 'ti.draw_id')
|
||||
->leftJoin('bet_providers as bp', 'bp.code', '=', 'ti.provider_code')
|
||||
->whereDate('d.business_date', '>=', $dateFrom)
|
||||
->whereDate('d.business_date', '<=', $dateTo)
|
||||
->selectRaw($providerCodeSql.' as provider_code')
|
||||
->selectRaw("COALESCE(NULLIF(MAX(ti.provider_name), ''), MAX(bp.name), ".$providerCodeSql.") as provider_name")
|
||||
->selectRaw('COUNT(ti.id) as ticket_item_count')
|
||||
->selectRaw('SUM(ti.actual_deduct_amount) as total_bet_minor')
|
||||
->selectRaw('SUM(ti.win_amount + ti.jackpot_win_amount) as total_payout_minor')
|
||||
->selectRaw('SUM(ti.actual_deduct_amount) - SUM(ti.win_amount + ti.jackpot_win_amount) as approx_house_gross_minor')
|
||||
->groupByRaw($providerCodeSql)
|
||||
->orderByDesc('total_bet_minor');
|
||||
|
||||
AdminDataScope::applyToTicketOrdersViaPlayer($query, $context?->admin, 'o');
|
||||
|
||||
return $query->paginate($perPage, ['*'], 'page', $page);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<int, string|int|float|null>>
|
||||
*/
|
||||
@@ -492,6 +525,7 @@ final class AdminReportQueryService
|
||||
'daily_profit_summary' => $this->dailyProfitExportRows($dateFrom, $dateTo, $scope),
|
||||
'player_win_loss' => $this->playerWinLossExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'play_dimension_report' => $this->playDimensionExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'provider_profit_report' => $this->providerProfitExportRows($dateFrom, $dateTo, $scope),
|
||||
'audit_operation_report' => $this->auditExportRows($filterJson, $dateFrom, $dateTo),
|
||||
'wallet_transfer_report', 'transfer_orders_daily' => $this->transferOrdersExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'wallet_txns_daily' => $this->walletTxnsExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
@@ -531,6 +565,7 @@ final class AdminReportQueryService
|
||||
'wallet_transfer_report', 'wallet_txns_daily', 'transfer_orders_daily' => '玩家转入转出报表',
|
||||
'hot_number_risk_report' => '热门号码风险报表',
|
||||
'play_dimension_report' => '玩法维度报表',
|
||||
'provider_profit_report' => '开注商经营报表',
|
||||
'sold_out_number_report' => '售罄号码报表',
|
||||
'audit_operation_report' => '后台操作审计报表',
|
||||
default => $reportType,
|
||||
@@ -603,6 +638,16 @@ final class AdminReportQueryService
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/** @return list<array<int, string|int|float|null>> */
|
||||
private function providerProfitExportRows(string $dateFrom, string $dateTo, AdminUser|AdminScopeContext|null $scope = null): array
|
||||
{
|
||||
$rows = [['开注商编码', '开注商名称', '注项数', '下注', '派彩', '平台毛利']];
|
||||
foreach ($this->providerProfitPaginated($dateFrom, $dateTo, 1, 10_000, $scope)->items() as $row) {
|
||||
$rows[] = [(string) $row->provider_code, (string) $row->provider_name, (int) $row->ticket_item_count, (int) $row->total_bet_minor, (int) $row->total_payout_minor, (int) $row->approx_house_gross_minor];
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<array<int, string|int|float|null>>
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,7 @@ final class AdminRiskPoolLockLogQueryService
|
||||
{
|
||||
$action = trim((string) $request->query('action_type', ''));
|
||||
$number = trim((string) $request->query('normalized_number', ''));
|
||||
$providerCode = strtoupper(trim((string) $request->query('provider_code', '')));
|
||||
$ticketItemId = (int) $request->integer('ticket_item_id', 0);
|
||||
|
||||
$q = RiskPoolLockLog::query()
|
||||
@@ -36,6 +37,10 @@ final class AdminRiskPoolLockLogQueryService
|
||||
$q->where('normalized_number', $number);
|
||||
}
|
||||
|
||||
if ($providerCode !== '') {
|
||||
$q->where('provider_code', $providerCode);
|
||||
}
|
||||
|
||||
if ($ticketItemId > 0) {
|
||||
$q->where('ticket_item_id', $ticketItemId);
|
||||
}
|
||||
@@ -50,6 +55,7 @@ final class AdminRiskPoolLockLogQueryService
|
||||
{
|
||||
$action = trim((string) $request->query('action_type', ''));
|
||||
$number = trim((string) $request->query('normalized_number', ''));
|
||||
$providerCode = strtoupper(trim((string) $request->query('provider_code', '')));
|
||||
$ticketItemId = (int) $request->integer('ticket_item_id', 0);
|
||||
|
||||
$bindings = ['draw_id' => $draw->id];
|
||||
@@ -65,6 +71,11 @@ final class AdminRiskPoolLockLogQueryService
|
||||
$bindings['normalized_number'] = $number;
|
||||
}
|
||||
|
||||
if ($providerCode !== '') {
|
||||
$filters .= ' AND l.provider_code = :provider_code';
|
||||
$bindings['provider_code'] = $providerCode;
|
||||
}
|
||||
|
||||
if ($ticketItemId > 0) {
|
||||
$filters .= ' AND l.ticket_item_id = :ticket_item_id';
|
||||
$bindings['ticket_item_id'] = $ticketItemId;
|
||||
@@ -86,6 +97,7 @@ final class AdminRiskPoolLockLogQueryService
|
||||
|
||||
$aggregateSql = <<<SQL
|
||||
SELECT
|
||||
COALESCE(NULLIF(ti.provider_code, ''), l.provider_code) AS provider_code,
|
||||
l.ticket_item_id AS ticket_item_id,
|
||||
ti.ticket_no AS ticket_no,
|
||||
ti.play_code AS play_code,
|
||||
@@ -101,7 +113,7 @@ SELECT
|
||||
FROM risk_pool_lock_logs l
|
||||
INNER JOIN ticket_items ti ON ti.id = l.ticket_item_id
|
||||
WHERE {$filters}
|
||||
GROUP BY l.ticket_item_id, ti.ticket_no, ti.play_code, ti.original_number, ti.combination_count, ti.player_id
|
||||
GROUP BY COALESCE(NULLIF(ti.provider_code, ''), l.provider_code), l.ticket_item_id, ti.ticket_no, ti.play_code, ti.original_number, ti.combination_count, ti.player_id
|
||||
SQL;
|
||||
|
||||
$countSql = "SELECT COUNT(*) AS aggregate_count FROM ({$aggregateSql}) AS grouped";
|
||||
|
||||
Reference in New Issue
Block a user