feat: 增强代理和玩家管理功能
- 在多个控制器中更新权限检查逻辑,确保管理员能够更灵活地管理代理和玩家。 - 在 AdminPlayerStoreController 中引入对玩家创建能力的验证,确保只有具备相应权限的管理员能够创建玩家。 - 更新请求验证逻辑,新增 credit_limit、rebate_rate 和 extra_rebate_rate 字段,以支持更细粒度的玩家管理。 - 在 AgentNodeProfileController 中添加对父代理能力授予的验证,确保子代理的权限在父代理范围内。 - 引入 AgentProfileFieldRules 以简化代理资料更新请求的规则定义,提升代码复用性。
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\AgentSettlement\SettlementCenterLedgerService;
|
||||
use App\Services\AgentSettlement\SettlementLedgerListFilters;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use App\Support\PaginationTrait;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 结算中心:信用盘玩家实时流水({@see credit_ledger}),与关账后 {@see settlement_bills} 不同。
|
||||
*/
|
||||
final class AdminCreditLedgerIndexController extends Controller
|
||||
{
|
||||
use PaginationTrait;
|
||||
|
||||
public function __construct(
|
||||
private readonly SettlementCenterLedgerService $ledgerService,
|
||||
) {}
|
||||
|
||||
public function __invoke(Request $request): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$adminSiteId = (int) $request->query('admin_site_id', 0);
|
||||
abort_if($adminSiteId <= 0, 422, 'admin_site_id required');
|
||||
abort_if(! AdminAgentSettlementScope::siteAccessible($admin, $adminSiteId), 403);
|
||||
|
||||
$siteCode = (string) DB::table('admin_sites')->where('id', $adminSiteId)->value('code');
|
||||
abort_if($siteCode === '', 422, 'admin_site not found');
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
if ($periodId > 0) {
|
||||
abort_if(! AdminAgentSettlementScope::periodAccessible($admin, $periodId), 403);
|
||||
}
|
||||
|
||||
$filters = SettlementLedgerListFilters::fromQuery(array_merge(
|
||||
$request->query(),
|
||||
$periodId > 0 ? ['settlement_period_id' => $periodId] : [],
|
||||
));
|
||||
|
||||
$perPage = $this->perPage($request, 'per_page', 20, 100);
|
||||
$page = $this->page($request);
|
||||
|
||||
$result = $this->ledgerService->listUnified(
|
||||
$admin,
|
||||
$siteCode,
|
||||
$page,
|
||||
$perPage,
|
||||
$filters,
|
||||
);
|
||||
|
||||
return ApiResponse::success($result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementAdjustmentIndexController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
$adminSiteId = (int) $request->query('admin_site_id', 0);
|
||||
$adjustmentType = trim((string) $request->query('adjustment_type', ''));
|
||||
|
||||
$query = DB::table('settlement_adjustments as sa')
|
||||
->leftJoin('settlement_periods as sp', 'sp.id', '=', 'sa.settlement_period_id')
|
||||
->leftJoin('settlement_bills as sb', 'sb.id', '=', 'sa.original_bill_id')
|
||||
->select([
|
||||
'sa.*',
|
||||
'sp.period_start',
|
||||
'sp.period_end',
|
||||
'sp.admin_site_id',
|
||||
'sb.bill_type as original_bill_type',
|
||||
'sb.owner_type as original_owner_type',
|
||||
'sb.owner_id as original_owner_id',
|
||||
])
|
||||
->orderByDesc('sa.id');
|
||||
|
||||
if ($periodId > 0) {
|
||||
$query->where('sa.settlement_period_id', $periodId);
|
||||
}
|
||||
|
||||
if ($adminSiteId > 0) {
|
||||
$query->where('sp.admin_site_id', $adminSiteId);
|
||||
}
|
||||
|
||||
if ($adjustmentType !== '') {
|
||||
$query->where('sa.adjustment_type', $adjustmentType);
|
||||
}
|
||||
|
||||
$siteIds = $admin->accessibleAdminSiteIds();
|
||||
if ($siteIds !== null) {
|
||||
if ($siteIds === []) {
|
||||
$query->whereRaw('0 = 1');
|
||||
} else {
|
||||
$query->whereIn('sp.admin_site_id', $siteIds);
|
||||
}
|
||||
}
|
||||
|
||||
return ApiResponse::success([
|
||||
'items' => $query->limit(200)->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Middleware\RecordAdminApiAudit;
|
||||
use App\Http\Requests\Admin\AdminSettlementBillAdjustmentRequest;
|
||||
use App\Services\AgentSettlement\AgentSettlementBillAdjustmentService;
|
||||
use App\Services\AuditLogger;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementBillAdjustmentController extends Controller
|
||||
{
|
||||
public function __invoke(
|
||||
AdminSettlementBillAdjustmentRequest $request,
|
||||
int $settlement_bill,
|
||||
AgentSettlementBillAdjustmentService $adjustments,
|
||||
): JsonResponse {
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
abort_if(! AdminAgentSettlementScope::billAccessible($admin, $settlement_bill), 404);
|
||||
|
||||
$before = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
abort_if($before === null, 404);
|
||||
|
||||
$newBillId = $adjustments->createAdjustment(
|
||||
$settlement_bill,
|
||||
(int) $request->validated('amount'),
|
||||
(string) ($request->validated('adjustment_type') ?? 'adjustment'),
|
||||
$request->validated('reason'),
|
||||
(int) $admin->id,
|
||||
);
|
||||
|
||||
$after = DB::table('settlement_bills')->where('id', $newBillId)->first();
|
||||
|
||||
AuditLogger::recordForAdmin(
|
||||
$admin,
|
||||
$request,
|
||||
moduleCode: 'settlement',
|
||||
actionCode: 'settlement_bill.adjustment',
|
||||
targetType: 'settlement_bill',
|
||||
targetId: (string) $newBillId,
|
||||
beforeJson: (array) $before,
|
||||
afterJson: (array) $after,
|
||||
);
|
||||
$request->attributes->set(RecordAdminApiAudit::ATTRIBUTE_AUDIT_RECORDED, true);
|
||||
|
||||
return ApiResponse::success([
|
||||
'original_bill_id' => $settlement_bill,
|
||||
'adjustment_bill_id' => $newBillId,
|
||||
'bill' => $after,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Middleware\RecordAdminApiAudit;
|
||||
use App\Http\Requests\Admin\AdminSettlementBillBadDebtRequest;
|
||||
use App\Services\AgentSettlement\AgentSettlementBadDebtService;
|
||||
use App\Services\AuditLogger;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementBillBadDebtWriteOffController extends Controller
|
||||
{
|
||||
public function __invoke(
|
||||
AdminSettlementBillBadDebtRequest $request,
|
||||
int $settlement_bill,
|
||||
AgentSettlementBadDebtService $badDebt,
|
||||
): JsonResponse {
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
abort_if(! AdminAgentSettlementScope::billAccessible($admin, $settlement_bill), 404);
|
||||
|
||||
$before = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
abort_if($before === null, 404);
|
||||
|
||||
$archiveBillId = $badDebt->writeOff(
|
||||
$settlement_bill,
|
||||
$request->validated('reason'),
|
||||
(int) $admin->id,
|
||||
);
|
||||
|
||||
$after = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
|
||||
AuditLogger::recordForAdmin(
|
||||
$admin,
|
||||
$request,
|
||||
moduleCode: 'settlement',
|
||||
actionCode: 'settlement_bill.bad_debt',
|
||||
targetType: 'settlement_bill',
|
||||
targetId: (string) $settlement_bill,
|
||||
beforeJson: (array) $before,
|
||||
afterJson: (array) $after,
|
||||
);
|
||||
$request->attributes->set(RecordAdminApiAudit::ATTRIBUTE_AUDIT_RECORDED, true);
|
||||
|
||||
return ApiResponse::success([
|
||||
'original_bill_id' => $settlement_bill,
|
||||
'bad_debt_bill_id' => $archiveBillId,
|
||||
'bill' => $after,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,8 @@ namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Middleware\RecordAdminApiAudit;
|
||||
use App\Models\Player;
|
||||
use App\Services\AgentSettlement\SettlementPaymentService;
|
||||
use App\Services\AuditLogger;
|
||||
use App\Services\Player\PlayerCreditService;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -18,7 +17,7 @@ final class AgentSettlementBillConfirmController extends Controller
|
||||
public function __invoke(
|
||||
Request $request,
|
||||
int $settlement_bill,
|
||||
PlayerCreditService $creditService,
|
||||
SettlementPaymentService $payments,
|
||||
): JsonResponse {
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
@@ -28,21 +27,7 @@ final class AgentSettlementBillConfirmController extends Controller
|
||||
$bill = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
abort_if($bill === null, 404);
|
||||
|
||||
$unpaid = (int) $bill->unpaid_amount;
|
||||
DB::table('settlement_bills')->where('id', $settlement_bill)->update([
|
||||
'paid_amount' => (int) $bill->paid_amount + $unpaid,
|
||||
'unpaid_amount' => 0,
|
||||
'status' => 'confirmed',
|
||||
'confirmed_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
if ($bill->owner_type === 'player' && (int) $bill->owner_id > 0) {
|
||||
$player = Player::query()->find((int) $bill->owner_id);
|
||||
if ($player !== null) {
|
||||
$creditService->releaseFromSettlement($player, $unpaid, $settlement_bill);
|
||||
}
|
||||
}
|
||||
$payments->confirmBill($settlement_bill);
|
||||
|
||||
AuditLogger::recordForAdmin(
|
||||
$admin,
|
||||
@@ -51,8 +36,8 @@ final class AgentSettlementBillConfirmController extends Controller
|
||||
actionCode: 'settlement_bill.confirm',
|
||||
targetType: 'settlement_bill',
|
||||
targetId: (string) $settlement_bill,
|
||||
beforeJson: ['status' => (string) $bill->status, 'unpaid_amount' => $unpaid],
|
||||
afterJson: ['status' => 'confirmed', 'paid_amount' => (int) $bill->paid_amount + $unpaid],
|
||||
beforeJson: ['status' => (string) $bill->status],
|
||||
afterJson: ['status' => 'confirmed'],
|
||||
);
|
||||
$request->attributes->set(RecordAdminApiAudit::ATTRIBUTE_AUDIT_RECORDED, true);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementBillIndexController extends Controller
|
||||
@@ -17,15 +18,142 @@ final class AgentSettlementBillIndexController extends Controller
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
$query = DB::table('settlement_bills')->orderByDesc('id');
|
||||
$adminSiteId = (int) $request->query('admin_site_id', 0);
|
||||
|
||||
$query = DB::table('settlement_bills as sb')
|
||||
->leftJoin('settlement_periods as sp', 'sp.id', '=', 'sb.settlement_period_id')
|
||||
->select([
|
||||
'sb.*',
|
||||
'sp.period_start',
|
||||
'sp.period_end',
|
||||
'sp.admin_site_id',
|
||||
])
|
||||
->orderByDesc('sb.id');
|
||||
|
||||
if ($periodId > 0) {
|
||||
$query->where('settlement_period_id', $periodId);
|
||||
$query->where('sb.settlement_period_id', $periodId);
|
||||
}
|
||||
|
||||
AdminAgentSettlementScope::applyToBillsQuery($query, $admin);
|
||||
if ($adminSiteId > 0) {
|
||||
$query->where('sp.admin_site_id', $adminSiteId);
|
||||
}
|
||||
|
||||
$billType = (string) $request->query('bill_type', '');
|
||||
if ($billType !== '') {
|
||||
$query->where('sb.bill_type', $billType);
|
||||
}
|
||||
|
||||
$scope = (string) $request->query('scope', '');
|
||||
match ($scope) {
|
||||
'pending_confirm' => $query->where('sb.status', 'pending_confirm'),
|
||||
'awaiting_payment' => $query
|
||||
->whereIn('sb.status', ['confirmed', 'partial_paid', 'overdue'])
|
||||
->where('sb.unpaid_amount', '>', 0),
|
||||
'settled' => $query->where('sb.status', 'settled'),
|
||||
'adjustment' => $query->whereIn('sb.bill_type', ['adjustment', 'reversal']),
|
||||
default => null,
|
||||
};
|
||||
|
||||
AdminAgentSettlementScope::applyToBillsQuery($query, $admin, 'sb');
|
||||
|
||||
/** @var Collection<int, object> $items */
|
||||
$items = $query->limit(200)->get();
|
||||
|
||||
return ApiResponse::success([
|
||||
'items' => $query->limit(100)->get(),
|
||||
'items' => $this->enrichBillRows($items),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, object> $items
|
||||
* @return list<array<string, mixed>>
|
||||
*/
|
||||
private function enrichBillRows(Collection $items): array
|
||||
{
|
||||
if ($items->isEmpty()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$playerIds = [];
|
||||
$agentIds = [];
|
||||
foreach ($items as $row) {
|
||||
if ((string) $row->owner_type === 'player') {
|
||||
$playerIds[] = (int) $row->owner_id;
|
||||
} elseif ((string) $row->owner_type === 'agent') {
|
||||
$agentIds[] = (int) $row->owner_id;
|
||||
}
|
||||
if ((string) $row->counterparty_type === 'agent' && (int) $row->counterparty_id > 0) {
|
||||
$agentIds[] = (int) $row->counterparty_id;
|
||||
}
|
||||
}
|
||||
|
||||
$players = $playerIds !== []
|
||||
? DB::table('players')
|
||||
->whereIn('id', array_unique($playerIds))
|
||||
->select(['id', 'username', 'site_player_id', 'funding_mode', 'auth_source'])
|
||||
->get()
|
||||
->keyBy('id')
|
||||
: collect();
|
||||
$agents = $agentIds !== []
|
||||
? DB::table('agent_nodes')->whereIn('id', array_unique($agentIds))->get()->keyBy('id')
|
||||
: collect();
|
||||
|
||||
$out = [];
|
||||
foreach ($items as $row) {
|
||||
$item = (array) $row;
|
||||
$item['owner_label'] = $this->resolvePartyLabel(
|
||||
(string) $row->owner_type,
|
||||
(int) $row->owner_id,
|
||||
$players,
|
||||
$agents,
|
||||
);
|
||||
$item['counterparty_label'] = $this->resolvePartyLabel(
|
||||
(string) $row->counterparty_type,
|
||||
(int) $row->counterparty_id,
|
||||
$players,
|
||||
$agents,
|
||||
);
|
||||
if ((string) $row->owner_type === 'player') {
|
||||
$player = $players->get((int) $row->owner_id);
|
||||
$item['owner_funding_mode'] = $player !== null ? (string) ($player->funding_mode ?? '') : null;
|
||||
$item['owner_auth_source'] = $player !== null ? $player->auth_source : null;
|
||||
}
|
||||
$out[] = $item;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection<int, object> $players
|
||||
* @param Collection<int, object> $agents
|
||||
*/
|
||||
private function resolvePartyLabel(
|
||||
string $type,
|
||||
int $id,
|
||||
Collection $players,
|
||||
Collection $agents,
|
||||
): string {
|
||||
if ($type === 'platform' || $id <= 0) {
|
||||
return 'platform';
|
||||
}
|
||||
|
||||
if ($type === 'player') {
|
||||
$player = $players->get($id);
|
||||
|
||||
return $player !== null
|
||||
? (string) ($player->username ?: $player->site_player_id)
|
||||
: "player#{$id}";
|
||||
}
|
||||
|
||||
if ($type === 'agent') {
|
||||
$agent = $agents->get($id);
|
||||
|
||||
return $agent !== null
|
||||
? (string) ($agent->name ?: $agent->code)
|
||||
: "agent#{$id}";
|
||||
}
|
||||
|
||||
return "{$type}#{$id}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Middleware\RecordAdminApiAudit;
|
||||
use App\Http\Requests\Admin\AdminSettlementBillPaymentRequest;
|
||||
use App\Services\AgentSettlement\SettlementPaymentService;
|
||||
use App\Services\AuditLogger;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementBillPaymentController extends Controller
|
||||
{
|
||||
public function __invoke(
|
||||
AdminSettlementBillPaymentRequest $request,
|
||||
int $settlement_bill,
|
||||
SettlementPaymentService $payments,
|
||||
): JsonResponse {
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
abort_if(! AdminAgentSettlementScope::billAccessible($admin, $settlement_bill), 404);
|
||||
|
||||
$before = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
abort_if($before === null, 404);
|
||||
|
||||
$validated = $request->validated();
|
||||
$payments->recordPayment(
|
||||
$settlement_bill,
|
||||
(int) $validated['amount'],
|
||||
(int) $admin->id,
|
||||
[
|
||||
'method' => $validated['method'] ?? null,
|
||||
'proof' => $validated['proof'] ?? null,
|
||||
'remark' => $validated['remark'] ?? null,
|
||||
],
|
||||
);
|
||||
|
||||
$after = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
|
||||
AuditLogger::recordForAdmin(
|
||||
$admin,
|
||||
$request,
|
||||
moduleCode: 'settlement',
|
||||
actionCode: 'settlement_bill.payment',
|
||||
targetType: 'settlement_bill',
|
||||
targetId: (string) $settlement_bill,
|
||||
beforeJson: (array) $before,
|
||||
afterJson: (array) $after,
|
||||
);
|
||||
$request->attributes->set(RecordAdminApiAudit::ATTRIBUTE_AUDIT_RECORDED, true);
|
||||
|
||||
return ApiResponse::success(['bill' => $after]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementBillShowController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request, int $settlement_bill): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
abort_if(! AdminAgentSettlementScope::billAccessible($admin, $settlement_bill), 404);
|
||||
|
||||
$bill = DB::table('settlement_bills')->where('id', $settlement_bill)->first();
|
||||
abort_if($bill === null, 404);
|
||||
|
||||
$payments = DB::table('payment_records')
|
||||
->where('settlement_bill_id', $settlement_bill)
|
||||
->orderBy('id')
|
||||
->get();
|
||||
|
||||
$rebateAllocations = DB::table('rebate_allocations')
|
||||
->where('settlement_bill_id', $settlement_bill)
|
||||
->orderBy('id')
|
||||
->get();
|
||||
|
||||
$adjustments = DB::table('settlement_adjustments')
|
||||
->where('original_bill_id', $settlement_bill)
|
||||
->orderByDesc('id')
|
||||
->get();
|
||||
|
||||
$meta = $bill->meta_json ?? null;
|
||||
$tierSettlements = null;
|
||||
if (is_string($meta) && $meta !== '') {
|
||||
$decoded = json_decode($meta, true);
|
||||
$tierSettlements = is_array($decoded) ? ($decoded['edge'] ?? $decoded['tier_settlements'] ?? null) : null;
|
||||
}
|
||||
|
||||
return ApiResponse::success([
|
||||
'bill' => $bill,
|
||||
'payments' => $payments,
|
||||
'rebate_allocations' => $rebateAllocations,
|
||||
'adjustments' => $adjustments,
|
||||
'tier_edge' => $tierSettlements,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementPaymentIndexController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
$adminSiteId = (int) $request->query('admin_site_id', 0);
|
||||
|
||||
$query = DB::table('payment_records as pr')
|
||||
->join('settlement_bills as sb', 'sb.id', '=', 'pr.settlement_bill_id')
|
||||
->join('settlement_periods as sp', 'sp.id', '=', 'sb.settlement_period_id')
|
||||
->select([
|
||||
'pr.*',
|
||||
'sb.bill_type',
|
||||
'sb.owner_type',
|
||||
'sb.owner_id',
|
||||
'sb.counterparty_type',
|
||||
'sb.counterparty_id',
|
||||
'sp.period_start',
|
||||
'sp.period_end',
|
||||
'sp.admin_site_id',
|
||||
])
|
||||
->orderByDesc('pr.id');
|
||||
|
||||
if ($periodId > 0) {
|
||||
$query->where('sb.settlement_period_id', $periodId);
|
||||
}
|
||||
|
||||
if ($adminSiteId > 0) {
|
||||
$query->where('sp.admin_site_id', $adminSiteId);
|
||||
}
|
||||
|
||||
$siteIds = $admin->accessibleAdminSiteIds();
|
||||
if ($siteIds !== null) {
|
||||
if ($siteIds === []) {
|
||||
$query->whereRaw('0 = 1');
|
||||
} else {
|
||||
$query->whereIn('sp.admin_site_id', $siteIds);
|
||||
}
|
||||
}
|
||||
|
||||
return ApiResponse::success([
|
||||
'items' => $query->limit(200)->get(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\AgentSettlement\AgentSettlementPeriodSummaryService;
|
||||
use App\Support\AdminAgentSettlementScope;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class AgentSettlementPeriodIndexController extends Controller
|
||||
{
|
||||
public function __invoke(
|
||||
Request $request,
|
||||
AgentSettlementPeriodSummaryService $summaryService,
|
||||
): JsonResponse {
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$query = DB::table('settlement_periods')->orderByDesc('id');
|
||||
AdminAgentSettlementScope::applyToPeriodsQuery($query, $admin);
|
||||
|
||||
$siteId = (int) $request->query('admin_site_id', 0);
|
||||
if ($siteId > 0) {
|
||||
$query->where('admin_site_id', $siteId);
|
||||
}
|
||||
|
||||
$periods = $query->limit(100)->get();
|
||||
|
||||
return ApiResponse::success([
|
||||
'items' => $summaryService->attachToPeriodRows($periods),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\AgentSettlement\AgentSettlementReportQueryService;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/** @deprecated 请用 AgentSettlementReportShowController?type=summary */
|
||||
final class AgentSettlementReportIndexController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request, AgentSettlementReportQueryService $reports): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
|
||||
return ApiResponse::success($reports->summary($admin, $periodId));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\V1\Admin\AgentSettlement;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Services\AgentSettlement\AgentSettlementReportQueryService;
|
||||
use App\Support\ApiResponse;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
final class AgentSettlementReportShowController extends Controller
|
||||
{
|
||||
private const TYPES = [
|
||||
'summary',
|
||||
'player_win_loss',
|
||||
'agent_share',
|
||||
'rebate',
|
||||
'credit',
|
||||
'unpaid_bills',
|
||||
'overdue',
|
||||
'platform_pnl',
|
||||
'draw_period',
|
||||
];
|
||||
|
||||
public function __invoke(Request $request, AgentSettlementReportQueryService $reports): JsonResponse
|
||||
{
|
||||
$admin = $request->lotteryAdmin();
|
||||
abort_if($admin === null, 401);
|
||||
|
||||
$type = (string) $request->query('type', 'summary');
|
||||
abort_unless(in_array($type, self::TYPES, true), 404);
|
||||
|
||||
$periodId = (int) $request->query('settlement_period_id', 0);
|
||||
$period = $this->resolvePeriod($periodId, $request);
|
||||
|
||||
$data = match ($type) {
|
||||
'summary' => $reports->summary($admin, $periodId),
|
||||
'player_win_loss' => [
|
||||
'items' => $reports->playerWinLoss($admin, $periodId, $period['start'], $period['end']),
|
||||
],
|
||||
'agent_share' => [
|
||||
'items' => $reports->agentShare($admin, $period['start'], $period['end']),
|
||||
],
|
||||
'rebate' => $reports->rebate($admin, $periodId, $period['start'], $period['end']),
|
||||
'credit' => $reports->credit($admin),
|
||||
'unpaid_bills' => [
|
||||
'items' => $reports->unpaidBills($admin, $periodId),
|
||||
],
|
||||
'overdue' => [
|
||||
'items' => $reports->overdue($admin),
|
||||
],
|
||||
'platform_pnl' => $periodId > 0
|
||||
? $reports->platformPnl($admin, $periodId)
|
||||
: ['error' => 'settlement_period_id_required'],
|
||||
'draw_period' => [
|
||||
'items' => $reports->drawPeriod($admin, $period['start'], $period['end']),
|
||||
],
|
||||
default => [],
|
||||
};
|
||||
|
||||
return ApiResponse::success([
|
||||
'type' => $type,
|
||||
'settlement_period_id' => $periodId > 0 ? $periodId : null,
|
||||
'period_start' => $period['start'],
|
||||
'period_end' => $period['end'],
|
||||
'data' => $data,
|
||||
'footnote' => $type === 'summary'
|
||||
? null
|
||||
: 'agent_credit_line_settlement',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{start: string, end: string}
|
||||
*/
|
||||
private function resolvePeriod(int $periodId, Request $request): array
|
||||
{
|
||||
if ($periodId > 0) {
|
||||
$row = DB::table('settlement_periods')->where('id', $periodId)->first();
|
||||
abort_if($row === null, 404);
|
||||
|
||||
return [
|
||||
'start' => (string) $row->period_start,
|
||||
'end' => (string) $row->period_end,
|
||||
];
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'period_start' => ['required_with:period_end', 'date'],
|
||||
'period_end' => ['required_with:period_start', 'date', 'after_or_equal:period_start'],
|
||||
]);
|
||||
|
||||
$start = $request->query('period_start');
|
||||
$end = $request->query('period_end');
|
||||
if ($start && $end) {
|
||||
return ['start' => (string) $start, 'end' => (string) $end];
|
||||
}
|
||||
|
||||
$now = now();
|
||||
|
||||
return [
|
||||
'start' => $now->copy()->subDays(7)->toDateTimeString(),
|
||||
'end' => $now->toDateTimeString(),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user