feat: 增强代理和玩家管理功能
- 在多个控制器中更新权限检查逻辑,确保管理员能够更灵活地管理代理和玩家。 - 在 AdminPlayerStoreController 中引入对玩家创建能力的验证,确保只有具备相应权限的管理员能够创建玩家。 - 更新请求验证逻辑,新增 credit_limit、rebate_rate 和 extra_rebate_rate 字段,以支持更细粒度的玩家管理。 - 在 AgentNodeProfileController 中添加对父代理能力授予的验证,确保子代理的权限在父代理范围内。 - 引入 AgentProfileFieldRules 以简化代理资料更新请求的规则定义,提升代码复用性。
This commit is contained in:
@@ -13,6 +13,7 @@ use App\Services\LotterySettings;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\QueryException;
|
||||
use App\Exceptions\WalletOperationException;
|
||||
use App\Support\PlayerFundingMode;
|
||||
|
||||
/**
|
||||
* 主站 ↔ 彩票钱包:转入 / 转出(幂等键 + 流水 + 订单)。
|
||||
@@ -68,6 +69,7 @@ final class LotteryTransferService
|
||||
*/
|
||||
public function transferIn(Player $player, string $currencyCode, int $amountMinor, string $idempotentKey): array
|
||||
{
|
||||
$this->assertWalletFundingMode($player);
|
||||
$this->assertPositiveAmount($amountMinor);
|
||||
$currencyCode = $this->normalizeCurrency($currencyCode);
|
||||
$this->assertCurrencyEnabled($currencyCode);
|
||||
@@ -190,6 +192,7 @@ final class LotteryTransferService
|
||||
*/
|
||||
public function transferOut(Player $player, string $currencyCode, int $amountMinor, string $idempotentKey): array
|
||||
{
|
||||
$this->assertWalletFundingMode($player);
|
||||
$this->assertPositiveAmount($amountMinor);
|
||||
$currencyCode = $this->normalizeCurrency($currencyCode);
|
||||
$this->assertCurrencyEnabled($currencyCode);
|
||||
@@ -732,6 +735,17 @@ final class LotteryTransferService
|
||||
}
|
||||
}
|
||||
|
||||
private function assertWalletFundingMode(Player $player): void
|
||||
{
|
||||
if (PlayerFundingMode::usesCredit($player)) {
|
||||
throw new WalletOperationException(
|
||||
'credit_player_no_wallet_transfer',
|
||||
ErrorCode::WalletCreditPlayerNoTransfer->value,
|
||||
422,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function assertPositiveAmount(int $amountMinor): void
|
||||
{
|
||||
if ($amountMinor < 1) {
|
||||
|
||||
578
app/Services/Wallet/PlayerLedgerLogsService.php
Normal file
578
app/Services/Wallet/PlayerLedgerLogsService.php
Normal file
@@ -0,0 +1,578 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Wallet;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use App\Models\AdminUser;
|
||||
use App\Models\Player;
|
||||
use App\Models\WalletTxn;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Support\AdminDataScope;
|
||||
use App\Support\CurrencyFormatter;
|
||||
use App\Support\PlayerFundingMode;
|
||||
use App\Services\Player\PlayerCreditService;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* 玩家流水:钱包玩家读 {@see wallet_txns},信用盘玩家读 {@see credit_ledger}。
|
||||
*/
|
||||
final class PlayerLedgerLogsService
|
||||
{
|
||||
/** PRD 对外类型 → wallet_txns.biz_type */
|
||||
private const WALLET_TYPE_TO_BIZ = [
|
||||
'transfer_in' => ['transfer_in'],
|
||||
'transfer_out' => ['transfer_out'],
|
||||
'refund' => ['transfer_out_refund'],
|
||||
'reversal' => ['reversal', 'bet_reverse'],
|
||||
'bet' => ['bet_deduct', 'bet'],
|
||||
'prize' => ['settle_payout', 'prize', 'jackpot_manual_payout'],
|
||||
];
|
||||
|
||||
/** PRD 对外类型 → credit_ledger.reason */
|
||||
private const CREDIT_TYPE_TO_REASON = [
|
||||
'bet' => ['bet_hold', 'game_settlement_loss'],
|
||||
'reversal' => ['bet_hold_release'],
|
||||
'refund' => ['settlement_confirm'],
|
||||
'prize' => [],
|
||||
'transfer_in' => [],
|
||||
'transfer_out' => [],
|
||||
];
|
||||
|
||||
public function __construct(
|
||||
private readonly PlayerCreditService $playerCreditService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @return array{
|
||||
* items: list<array<string, mixed>>,
|
||||
* total: int,
|
||||
* page: int,
|
||||
* per_page: int,
|
||||
* ledger_source: string,
|
||||
* funding_mode: string,
|
||||
* auth_source: string|null,
|
||||
* }
|
||||
*/
|
||||
public function listForPlayerApi(
|
||||
Player $player,
|
||||
int $page,
|
||||
int $perPage,
|
||||
string $currencyCode,
|
||||
string $typeFilterRaw,
|
||||
): array {
|
||||
$meta = [
|
||||
'ledger_source' => PlayerFundingMode::usesCredit($player) ? 'credit_ledger' : 'wallet_txn',
|
||||
'funding_mode' => (string) ($player->funding_mode ?? ''),
|
||||
'auth_source' => $player->auth_source,
|
||||
];
|
||||
|
||||
if (PlayerFundingMode::usesCredit($player)) {
|
||||
$result = $this->paginateCreditLedger($player, $page, $perPage, $typeFilterRaw);
|
||||
|
||||
return array_merge($result, $meta);
|
||||
}
|
||||
|
||||
$result = $this->paginateWalletTxns($player, $page, $perPage, $currencyCode, $typeFilterRaw);
|
||||
|
||||
return array_merge($result, $meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台玩家详情「钱包流水」:信用盘玩家返回 credit_ledger,字段形状对齐 wallet_txns 列表。
|
||||
*
|
||||
* @return array{items: list<array<string, mixed>>, total: int, page: int, per_page: int}
|
||||
*/
|
||||
public function listForAdminPlayer(
|
||||
Player $player,
|
||||
int $page,
|
||||
int $perPage,
|
||||
?string $bizType = null,
|
||||
): array {
|
||||
if (! PlayerFundingMode::usesCredit($player)) {
|
||||
return ['items' => [], 'total' => 0, 'page' => $page, 'per_page' => $perPage];
|
||||
}
|
||||
|
||||
$reasonFilter = $bizType !== null && $bizType !== ''
|
||||
? [trim($bizType)]
|
||||
: null;
|
||||
|
||||
$paginator = $this->creditLedgerQuery($player->id, $reasonFilter)
|
||||
->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
$currency = (string) $player->default_currency;
|
||||
$runningMinor = $this->playerCreditService->availableCreditMinor($player, $currency);
|
||||
$items = $paginator->getCollection()
|
||||
->map(function (object $row) use (&$runningMinor, $player, $currency): array {
|
||||
$amount = (int) $row->amount;
|
||||
$formatted = $this->formatAdminCreditRow($row, $player, $currency, $runningMinor);
|
||||
$runningMinor -= $amount;
|
||||
|
||||
return $formatted;
|
||||
})
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'total' => $paginator->total(),
|
||||
'page' => $paginator->currentPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 结算中心:站点下全部信用盘玩家的 {@see credit_ledger} 流水。
|
||||
*
|
||||
* @return array{
|
||||
* items: list<array<string, mixed>>,
|
||||
* total: int,
|
||||
* page: int,
|
||||
* per_page: int,
|
||||
* ledger_source: string,
|
||||
* }
|
||||
*/
|
||||
public function listForAdminCreditIndex(
|
||||
AdminUser $admin,
|
||||
string $siteCode,
|
||||
int $page,
|
||||
int $perPage,
|
||||
?int $settlementPeriodId = null,
|
||||
?int $playerId = null,
|
||||
?string $reason = null,
|
||||
?string $createdFrom = null,
|
||||
?string $createdTo = null,
|
||||
): array {
|
||||
$query = DB::table('credit_ledger as cl')
|
||||
->join('players as p', function ($join): void {
|
||||
$join->on('p.id', '=', 'cl.owner_id')
|
||||
->where('cl.owner_type', '=', 'player');
|
||||
})
|
||||
->where('p.site_code', $siteCode)
|
||||
->where('p.funding_mode', PlayerFundingMode::CREDIT)
|
||||
->select([
|
||||
'cl.id',
|
||||
'cl.amount',
|
||||
'cl.reason',
|
||||
'cl.ref_type',
|
||||
'cl.ref_id',
|
||||
'cl.created_at',
|
||||
'cl.updated_at',
|
||||
'p.id as player_id',
|
||||
'p.site_code',
|
||||
'p.site_player_id',
|
||||
'p.username',
|
||||
'p.nickname',
|
||||
'p.funding_mode',
|
||||
'p.auth_source',
|
||||
'p.default_currency',
|
||||
])
|
||||
->orderByDesc('cl.id');
|
||||
|
||||
AdminDataScope::applyToPlayersAlias($query, $admin, 'p');
|
||||
|
||||
if ($playerId !== null && $playerId > 0) {
|
||||
$query->where('p.id', $playerId);
|
||||
}
|
||||
|
||||
if ($reason !== null && $reason !== '') {
|
||||
$query->where('cl.reason', $reason);
|
||||
}
|
||||
|
||||
$range = $this->resolveCreatedRange($settlementPeriodId, $createdFrom, $createdTo);
|
||||
if ($range !== null) {
|
||||
$query->whereBetween('cl.created_at', $range);
|
||||
}
|
||||
|
||||
/** @var LengthAwarePaginator $paginator */
|
||||
$paginator = $query->paginate($perPage, ['*'], 'page', $page);
|
||||
$items = $paginator->getCollection()
|
||||
->map(fn (object $row): array => $this->formatAdminCreditIndexRow($row))
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'total' => $paginator->total(),
|
||||
'page' => $paginator->currentPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
'ledger_source' => 'credit_ledger',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{0: Carbon, 1: Carbon}|null
|
||||
*/
|
||||
private function resolveCreatedRange(
|
||||
?int $settlementPeriodId,
|
||||
?string $createdFrom,
|
||||
?string $createdTo,
|
||||
): ?array {
|
||||
if ($settlementPeriodId !== null && $settlementPeriodId > 0) {
|
||||
$period = DB::table('settlement_periods')->where('id', $settlementPeriodId)->first();
|
||||
if ($period === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
Carbon::parse($period->period_start)->startOfDay(),
|
||||
Carbon::parse($period->period_end)->endOfDay(),
|
||||
];
|
||||
}
|
||||
|
||||
$from = $createdFrom !== null && $createdFrom !== ''
|
||||
? Carbon::parse($createdFrom)->startOfDay()
|
||||
: null;
|
||||
$to = $createdTo !== null && $createdTo !== ''
|
||||
? Carbon::parse($createdTo)->endOfDay()
|
||||
: null;
|
||||
|
||||
if ($from === null && $to === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [
|
||||
$from ?? Carbon::parse('1970-01-01')->startOfDay(),
|
||||
$to ?? Carbon::now()->endOfDay(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatAdminCreditIndexRow(object $row): array
|
||||
{
|
||||
$amount = (int) $row->amount;
|
||||
$amountAbs = abs($amount);
|
||||
$currency = (string) ($row->default_currency ?? '');
|
||||
|
||||
return [
|
||||
'id' => (int) $row->id,
|
||||
'txn_no' => 'CL-'.$row->id,
|
||||
'player_id' => (int) $row->player_id,
|
||||
'site_code' => (string) $row->site_code,
|
||||
'site_player_id' => $row->site_player_id,
|
||||
'username' => $row->username,
|
||||
'nickname' => $row->nickname,
|
||||
'biz_type' => (string) $row->reason,
|
||||
'type' => $this->creditReasonToPublicType((string) $row->reason),
|
||||
'biz_no' => $this->creditRefLabel($row),
|
||||
'direction' => $amount >= 0 ? 1 : 2,
|
||||
'amount' => $amountAbs,
|
||||
'amount_formatted' => CurrencyFormatter::fromMinor($amountAbs),
|
||||
'signed_amount' => $amount,
|
||||
'currency_code' => $currency,
|
||||
'status' => 'posted',
|
||||
'created_at' => $this->isoTimestamp($row->created_at ?? null),
|
||||
'updated_at' => $this->isoTimestamp($row->updated_at ?? null),
|
||||
'ledger_source' => 'credit_ledger',
|
||||
'funding_mode' => (string) ($row->funding_mode ?? PlayerFundingMode::CREDIT),
|
||||
'auth_source' => $row->auth_source,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{items: list<array<string, mixed>>, total: int, page: int, per_page: int}
|
||||
*/
|
||||
private function paginateWalletTxns(
|
||||
Player $player,
|
||||
int $page,
|
||||
int $perPage,
|
||||
string $currencyCode,
|
||||
string $typeFilterRaw,
|
||||
): array {
|
||||
$bizFilter = $this->resolveWalletBizFilter($typeFilterRaw);
|
||||
|
||||
if (is_array($bizFilter) && $bizFilter === []) {
|
||||
return ['items' => [], 'total' => 0, 'page' => $page, 'per_page' => $perPage];
|
||||
}
|
||||
|
||||
$query = WalletTxn::query()
|
||||
->where('player_id', $player->id)
|
||||
->with('wallet')
|
||||
->orderByDesc('id');
|
||||
|
||||
if ($currencyCode !== '') {
|
||||
$query->whereHas('wallet', fn ($q) => $q->where('currency_code', $currencyCode));
|
||||
}
|
||||
|
||||
if ($bizFilter !== null) {
|
||||
$query->whereIn('biz_type', $bizFilter);
|
||||
}
|
||||
|
||||
$paginator = $query->paginate($perPage, ['*'], 'page', $page);
|
||||
$items = $paginator->getCollection()
|
||||
->map(fn (WalletTxn $txn) => $this->formatWalletTxnRow($txn))
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'total' => $paginator->total(),
|
||||
'page' => $paginator->currentPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{items: list<array<string, mixed>>, total: int, page: int, per_page: int}
|
||||
*/
|
||||
private function paginateCreditLedger(
|
||||
Player $player,
|
||||
int $page,
|
||||
int $perPage,
|
||||
string $typeFilterRaw,
|
||||
): array {
|
||||
$reasonFilter = $this->resolveCreditReasonFilter($typeFilterRaw);
|
||||
|
||||
if (is_array($reasonFilter) && $reasonFilter === []) {
|
||||
return ['items' => [], 'total' => 0, 'page' => $page, 'per_page' => $perPage];
|
||||
}
|
||||
|
||||
$paginator = $this->creditLedgerQuery((int) $player->id, $reasonFilter)
|
||||
->paginate($perPage, ['*'], 'page', $page);
|
||||
|
||||
$currency = (string) $player->default_currency;
|
||||
$runningMinor = $this->playerCreditService->availableCreditMinor($player, $currency);
|
||||
$items = $paginator->getCollection()
|
||||
->map(function (object $row) use (&$runningMinor, $player, $currency): array {
|
||||
$amount = (int) $row->amount;
|
||||
$formatted = $this->formatPlayerCreditRow($row, $player, $currency, $runningMinor);
|
||||
$runningMinor -= $amount;
|
||||
|
||||
return $formatted;
|
||||
})
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'items' => $items,
|
||||
'total' => $paginator->total(),
|
||||
'page' => $paginator->currentPage(),
|
||||
'per_page' => $paginator->perPage(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string>|null $reasonFilter
|
||||
*/
|
||||
private function creditLedgerQuery(int $playerId, ?array $reasonFilter)
|
||||
{
|
||||
$query = DB::table('credit_ledger')
|
||||
->where('owner_type', 'player')
|
||||
->where('owner_id', $playerId)
|
||||
->orderByDesc('id');
|
||||
|
||||
if ($reasonFilter !== null) {
|
||||
$query->whereIn('reason', $reasonFilter);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>|null
|
||||
*/
|
||||
private function resolveWalletBizFilter(string $raw): ?array
|
||||
{
|
||||
return $this->resolveTypeFilterMap($raw, self::WALLET_TYPE_TO_BIZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return list<string>|null
|
||||
*/
|
||||
private function resolveCreditReasonFilter(string $raw): ?array
|
||||
{
|
||||
return $this->resolveTypeFilterMap($raw, self::CREDIT_TYPE_TO_REASON);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, list<string>> $map
|
||||
* @return list<string>|null
|
||||
*/
|
||||
private function resolveTypeFilterMap(string $raw, array $map): ?array
|
||||
{
|
||||
$raw = trim($raw);
|
||||
if ($raw === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
$parts = array_filter(array_map('trim', explode(',', $raw)));
|
||||
if ($parts === []) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resolved = [];
|
||||
foreach ($parts as $part) {
|
||||
$key = Str::lower($part);
|
||||
if (! isset($map[$key])) {
|
||||
continue;
|
||||
}
|
||||
foreach ($map[$key] as $value) {
|
||||
$resolved[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($resolved));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatWalletTxnRow(WalletTxn $txn): array
|
||||
{
|
||||
$currency = $txn->wallet?->currency_code ?? '';
|
||||
$amount = (int) $txn->amount;
|
||||
$balanceAfter = (int) $txn->balance_after;
|
||||
|
||||
return [
|
||||
'log_id' => $txn->txn_no,
|
||||
'type' => $this->walletBizToPublicType((string) $txn->biz_type),
|
||||
'biz_type' => $txn->biz_type,
|
||||
'amount' => $this->signedWalletAmount($txn),
|
||||
'amount_formatted' => CurrencyFormatter::fromMinor($amount),
|
||||
'amount_abs' => $amount,
|
||||
'amount_abs_formatted' => CurrencyFormatter::fromMinor($amount),
|
||||
'direction' => (int) $txn->direction === 1 ? 'in' : 'out',
|
||||
'currency_code' => $currency,
|
||||
'balance_after' => $balanceAfter,
|
||||
'balance_after_formatted' => CurrencyFormatter::fromMinor($balanceAfter),
|
||||
'ref_id' => $txn->biz_no,
|
||||
'idempotent_key' => $txn->idempotent_key,
|
||||
'external_ref_no' => $txn->external_ref_no,
|
||||
'status' => $txn->status,
|
||||
'remark' => $txn->remark,
|
||||
'created_at' => $txn->created_at?->toIso8601String(),
|
||||
'ledger_source' => 'wallet_txn',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatPlayerCreditRow(
|
||||
object $row,
|
||||
Player $player,
|
||||
string $currency,
|
||||
int $balanceAfterMinor,
|
||||
): array {
|
||||
$amount = (int) $row->amount;
|
||||
$amountAbs = abs($amount);
|
||||
$publicType = $this->creditReasonToPublicType((string) $row->reason);
|
||||
|
||||
return [
|
||||
'log_id' => 'CL-'.$row->id,
|
||||
'type' => $publicType,
|
||||
'biz_type' => (string) $row->reason,
|
||||
'amount' => $amount,
|
||||
'amount_formatted' => CurrencyFormatter::fromMinor($amountAbs),
|
||||
'amount_abs' => $amountAbs,
|
||||
'amount_abs_formatted' => CurrencyFormatter::fromMinor($amountAbs),
|
||||
'direction' => $amount >= 0 ? 'in' : 'out',
|
||||
'currency_code' => $currency,
|
||||
'balance_after' => $balanceAfterMinor,
|
||||
'balance_after_formatted' => CurrencyFormatter::fromMinor($balanceAfterMinor),
|
||||
'ref_id' => $this->creditRefLabel($row),
|
||||
'idempotent_key' => null,
|
||||
'external_ref_no' => null,
|
||||
'status' => 'posted',
|
||||
'remark' => null,
|
||||
'created_at' => $this->isoTimestamp($row->created_at ?? null),
|
||||
'ledger_source' => 'credit_ledger',
|
||||
'funding_mode' => (string) ($player->funding_mode ?? PlayerFundingMode::CREDIT),
|
||||
'auth_source' => $player->auth_source,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function formatAdminCreditRow(
|
||||
object $row,
|
||||
Player $player,
|
||||
string $currency,
|
||||
int $balanceAfterMinor,
|
||||
): array {
|
||||
$amount = (int) $row->amount;
|
||||
$amountAbs = abs($amount);
|
||||
$balanceBefore = $amount >= 0
|
||||
? max(0, $balanceAfterMinor - $amount)
|
||||
: $balanceAfterMinor + $amountAbs;
|
||||
|
||||
return [
|
||||
'id' => (int) $row->id,
|
||||
'txn_no' => 'CL-'.$row->id,
|
||||
'player_id' => (int) $player->id,
|
||||
'site_code' => $player->site_code,
|
||||
'site_player_id' => $player->site_player_id,
|
||||
'username' => $player->username,
|
||||
'nickname' => $player->nickname,
|
||||
'wallet_id' => null,
|
||||
'biz_type' => (string) $row->reason,
|
||||
'biz_no' => $this->creditRefLabel($row),
|
||||
'direction' => $amount >= 0 ? 1 : 2,
|
||||
'amount' => $amountAbs,
|
||||
'amount_formatted' => CurrencyFormatter::fromMinor($amountAbs),
|
||||
'balance_before' => $balanceBefore,
|
||||
'balance_before_formatted' => CurrencyFormatter::fromMinor($balanceBefore),
|
||||
'balance_after' => $balanceAfterMinor,
|
||||
'balance_after_formatted' => CurrencyFormatter::fromMinor($balanceAfterMinor),
|
||||
'status' => 'posted',
|
||||
'external_ref_no' => null,
|
||||
'idempotent_key' => null,
|
||||
'remark' => null,
|
||||
'created_at' => $this->isoTimestamp($row->created_at ?? null),
|
||||
'updated_at' => $this->isoTimestamp($row->updated_at ?? null),
|
||||
'ledger_source' => 'credit_ledger',
|
||||
'funding_mode' => (string) ($player->funding_mode ?? PlayerFundingMode::CREDIT),
|
||||
'auth_source' => $player->auth_source,
|
||||
];
|
||||
}
|
||||
|
||||
private function creditReasonToPublicType(string $reason): string
|
||||
{
|
||||
return match ($reason) {
|
||||
'bet_hold', 'game_settlement_loss' => 'bet',
|
||||
'bet_hold_release' => 'reversal',
|
||||
'settlement_confirm' => 'refund',
|
||||
default => $reason,
|
||||
};
|
||||
}
|
||||
|
||||
private function walletBizToPublicType(string $biz): string
|
||||
{
|
||||
return match ($biz) {
|
||||
'transfer_out_refund' => 'refund',
|
||||
'bet_deduct', 'bet' => 'bet',
|
||||
'bet_reverse' => 'reversal',
|
||||
'settle_payout', 'prize', 'jackpot_manual_payout' => 'prize',
|
||||
'reversal' => 'reversal',
|
||||
default => $biz,
|
||||
};
|
||||
}
|
||||
|
||||
private function signedWalletAmount(WalletTxn $txn): int
|
||||
{
|
||||
$a = (int) $txn->amount;
|
||||
|
||||
return (int) $txn->direction === 1 ? $a : -$a;
|
||||
}
|
||||
|
||||
private function creditRefLabel(object $row): ?string
|
||||
{
|
||||
if ($row->ref_type === null || $row->ref_id === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (string) $row->ref_type.'#'.$row->ref_id;
|
||||
}
|
||||
|
||||
private function isoTimestamp(mixed $value): ?string
|
||||
{
|
||||
if ($value === null || $value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Carbon::parse($value)->toIso8601String();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user