fix(core): harden settlement and wallet integration
This commit is contained in:
@@ -2,23 +2,26 @@
|
||||
|
||||
namespace App\Services\Admin;
|
||||
|
||||
use App\Models\AdminUser;
|
||||
use App\Models\AuditLog;
|
||||
use App\Support\AdminDataScope;
|
||||
use App\Support\AdminScopeContext;
|
||||
use App\Support\AdminScopeContextResolver;
|
||||
use Carbon\Carbon;
|
||||
use App\Models\Draw;
|
||||
use App\Models\AuditLog;
|
||||
use App\Models\RiskPool;
|
||||
use App\Models\RiskPoolLockLog;
|
||||
use App\Models\SettlementBatch;
|
||||
use App\Models\AdminUser;
|
||||
use App\Models\WalletTxn;
|
||||
use App\Models\TicketItem;
|
||||
use App\Models\TicketOrder;
|
||||
use App\Models\TransferOrder;
|
||||
use App\Models\WalletTxn;
|
||||
use Carbon\Carbon;
|
||||
use App\Services\AuditLogger;
|
||||
use App\Support\LimitedQuery;
|
||||
use App\Models\RiskPoolLockLog;
|
||||
use App\Models\SettlementBatch;
|
||||
use App\Support\AdminDataScope;
|
||||
use App\Support\AdminScopeContext;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Query\Builder;
|
||||
use App\Support\AdminScopeContextResolver;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\LengthAwarePaginator as PaginatorInstance;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 报表中心聚合查询(模块十三)。
|
||||
@@ -498,7 +501,7 @@ final class AdminReportQueryService
|
||||
->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("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')
|
||||
@@ -514,7 +517,7 @@ final class AdminReportQueryService
|
||||
/**
|
||||
* @return list<array<int, string|int|float|null>>
|
||||
*/
|
||||
public function reportRows(string $reportType, ?array $filterJson, AdminUser|AdminScopeContext|null $scope = null): array
|
||||
public function reportRows(string $reportType, ?array $filterJson, AdminUser|AdminScopeContext $scope): array
|
||||
{
|
||||
$range = $this->resolveDateRange($filterJson);
|
||||
$dateFrom = $range['date_from'];
|
||||
@@ -526,7 +529,7 @@ final class AdminReportQueryService
|
||||
'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),
|
||||
'audit_operation_report' => $this->auditExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'wallet_transfer_report', 'transfer_orders_daily' => $this->transferOrdersExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'wallet_txns_daily' => $this->walletTxnsExportRows($filterJson, $dateFrom, $dateTo, $scope),
|
||||
'hot_number_risk_report' => $this->hotNumberRiskExportRows($filterJson),
|
||||
@@ -645,27 +648,38 @@ final class AdminReportQueryService
|
||||
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>>
|
||||
*/
|
||||
private function auditExportRows(?array $filterJson, string $dateFrom, string $dateTo): array
|
||||
{
|
||||
private function auditExportRows(
|
||||
?array $filterJson,
|
||||
string $dateFrom,
|
||||
string $dateTo,
|
||||
AdminUser|AdminScopeContext $scope,
|
||||
): array {
|
||||
$admin = $scope instanceof AdminScopeContext ? $scope->admin : $scope;
|
||||
$operatorId = isset($filterJson['operator_id']) ? (int) $filterJson['operator_id'] : null;
|
||||
$rows = [
|
||||
['ID', '操作者类型', '操作者ID', '模块', '操作', 'IP', '时间'],
|
||||
];
|
||||
|
||||
$q = AuditLog::query()->orderByDesc('id');
|
||||
if (! $admin->isSuperAdmin()) {
|
||||
// audit_logs 没有可靠的站点快照;普通审计账号仅能导出自己的后台操作。
|
||||
$q->where('operator_type', AuditLogger::OPERATOR_ADMIN)
|
||||
->where('operator_id', (int) $admin->getKey());
|
||||
}
|
||||
if ($operatorId !== null && $operatorId > 0) {
|
||||
$q->where('operator_id', $operatorId);
|
||||
}
|
||||
$q->whereDate('created_at', '>=', $dateFrom)
|
||||
->whereDate('created_at', '<=', $dateTo);
|
||||
|
||||
$limited = \App\Support\LimitedQuery::get($q, 5000);
|
||||
$limited = LimitedQuery::get($q, 5000);
|
||||
foreach ($limited['rows'] as $log) {
|
||||
$rows[] = [
|
||||
(int) $log->id,
|
||||
@@ -685,7 +699,7 @@ final class AdminReportQueryService
|
||||
return $rows;
|
||||
}
|
||||
|
||||
/** @return \Illuminate\Database\Query\Builder */
|
||||
/** @return Builder */
|
||||
private function playerWinLossBaseQuery(
|
||||
?int $playerId,
|
||||
string $dateFrom,
|
||||
@@ -725,7 +739,7 @@ final class AdminReportQueryService
|
||||
return $query;
|
||||
}
|
||||
|
||||
/** @return \Illuminate\Database\Query\Builder */
|
||||
/** @return Builder */
|
||||
private function playDimensionBaseQuery(?string $playCode, string $dateFrom, string $dateTo, AdminUser|AdminScopeContext|null $scope = null)
|
||||
{
|
||||
$context = $this->normalizeScope($scope);
|
||||
@@ -755,9 +769,9 @@ final class AdminReportQueryService
|
||||
/**
|
||||
* @return list<array<int, string|int|float|null>>
|
||||
*/
|
||||
private function drawProfitExportRows(?array $filterJson, AdminUser|AdminScopeContext|null $scope = null): array
|
||||
private function drawProfitExportRows(?array $filterJson, AdminUser|AdminScopeContext $scope): array
|
||||
{
|
||||
$context = $this->normalizeScope($scope);
|
||||
$admin = $scope instanceof AdminScopeContext ? $scope->admin : $scope;
|
||||
$draw = $this->resolveDrawForReport($filterJson);
|
||||
if ($draw === null) {
|
||||
return [['提示', '请提供 draw_id 或 draw_no']];
|
||||
@@ -766,10 +780,8 @@ final class AdminReportQueryService
|
||||
$drawId = (int) $draw->id;
|
||||
$orderQuery = TicketOrder::query()->where('draw_id', $drawId);
|
||||
$itemQuery = TicketItem::query()->where('draw_id', $drawId);
|
||||
if ($context !== null) {
|
||||
AdminDataScope::applyEloquentViaPlayer($orderQuery, $context->admin);
|
||||
AdminDataScope::applyEloquentViaPlayer($itemQuery, $context->admin);
|
||||
}
|
||||
AdminDataScope::applyEloquentViaPlayer($orderQuery, $admin);
|
||||
AdminDataScope::applyEloquentViaPlayer($itemQuery, $admin);
|
||||
|
||||
$totalBetMinor = (int) $orderQuery->sum('total_actual_deduct');
|
||||
$orderCount = (int) $orderQuery->count();
|
||||
@@ -805,11 +817,13 @@ final class AdminReportQueryService
|
||||
],
|
||||
];
|
||||
|
||||
$batches = SettlementBatch::query()
|
||||
->where('draw_id', $drawId)
|
||||
->orderByDesc('id')
|
||||
->limit(100)
|
||||
->get();
|
||||
$batches = $admin->isSuperAdmin()
|
||||
? SettlementBatch::query()
|
||||
->where('draw_id', $drawId)
|
||||
->orderByDesc('id')
|
||||
->limit(100)
|
||||
->get()
|
||||
: collect();
|
||||
|
||||
foreach ($batches as $batch) {
|
||||
$rows[] = [
|
||||
|
||||
Reference in New Issue
Block a user