feat: 切换 schema dump 基线并增强返点结算与管理校验
This commit is contained in:
@@ -43,10 +43,17 @@ final class AgentGameSettlementRecorder
|
||||
|
||||
$gameType = trim((string) ($item->play_code ?? '')) ?: '*';
|
||||
$snapshot = $this->snapshotBuilder->buildForPlayer($player, $gameType);
|
||||
$baseRebateRate = $this->baseRebateRateForTicketItem($item);
|
||||
$basicRebateRate = $this->normalizeRate($baseRebateRate + (float) $snapshot['rebate_rate']);
|
||||
$shareSnapshot = [
|
||||
...$snapshot,
|
||||
'base_rebate_rate' => $baseRebateRate,
|
||||
'basic_rebate_rate' => $basicRebateRate,
|
||||
];
|
||||
|
||||
$gameWinLoss = $this->platformWinLoss($item, $netWin, $terminalStatus);
|
||||
$validBet = (int) $item->total_bet_amount;
|
||||
$basicRebate = (int) round($validBet * $snapshot['rebate_rate']);
|
||||
$basicRebate = (int) round($validBet * $basicRebateRate);
|
||||
$extraRebate = (int) round($validBet * $snapshot['extra_rebate_rate']);
|
||||
|
||||
$extraByCode = [];
|
||||
@@ -66,15 +73,11 @@ final class AgentGameSettlementRecorder
|
||||
|
||||
$settledAt = now();
|
||||
|
||||
DB::transaction(function () use ($item, $player, $snapshot, $gameWinLoss, $basicRebate, $result, $settledAt, $validBet, $extraRebate, $gameType): void {
|
||||
DB::transaction(function () use ($item, $player, $snapshot, $shareSnapshot, $basicRebateRate, $gameWinLoss, $basicRebate, $result, $settledAt, $validBet, $extraRebate, $gameType): void {
|
||||
$item->forceFill([
|
||||
'agent_node_id' => $snapshot['agent_node_id'],
|
||||
'share_snapshot' => [
|
||||
'total_shares' => $snapshot['total_shares'],
|
||||
'actual_shares' => $snapshot['actual_shares'],
|
||||
'chain_codes' => $snapshot['chain_codes'],
|
||||
],
|
||||
'agent_rebate_rate_snapshot' => $snapshot['rebate_rate'],
|
||||
'share_snapshot' => $shareSnapshot,
|
||||
'agent_rebate_rate_snapshot' => $basicRebateRate,
|
||||
'agent_settled_at' => $settledAt,
|
||||
])->save();
|
||||
|
||||
@@ -83,7 +86,7 @@ final class AgentGameSettlementRecorder
|
||||
'player_id' => $player->id,
|
||||
'agent_node_id' => $snapshot['agent_node_id'],
|
||||
'agent_path' => json_encode($snapshot['agent_path']),
|
||||
'share_snapshot' => json_encode($snapshot),
|
||||
'share_snapshot' => json_encode($shareSnapshot),
|
||||
'game_win_loss' => (int) round($gameWinLoss),
|
||||
'basic_rebate' => $basicRebate,
|
||||
'shared_net_win_loss' => (int) round($result->sharedNetWinLoss),
|
||||
@@ -99,7 +102,7 @@ final class AgentGameSettlementRecorder
|
||||
'ticket_item_id' => $item->id,
|
||||
'game_type' => $gameType,
|
||||
'valid_bet_amount' => $validBet,
|
||||
'rebate_rate' => $snapshot['rebate_rate'],
|
||||
'rebate_rate' => $basicRebateRate,
|
||||
'rebate_amount' => $basicRebate,
|
||||
'rebate_type' => 'basic',
|
||||
'owner_agent_id' => $snapshot['agent_node_id'],
|
||||
@@ -138,6 +141,38 @@ final class AgentGameSettlementRecorder
|
||||
});
|
||||
}
|
||||
|
||||
private function baseRebateRateForTicketItem(TicketItem $item): float
|
||||
{
|
||||
$ruleSnapshot = is_array($item->rule_snapshot_json) ? $item->rule_snapshot_json : [];
|
||||
$baseFromRule = isset($ruleSnapshot['base_rebate_rate'])
|
||||
? (float) $ruleSnapshot['base_rebate_rate']
|
||||
: null;
|
||||
|
||||
if ($baseFromRule !== null && $baseFromRule > 0) {
|
||||
return $this->normalizeRate($baseFromRule);
|
||||
}
|
||||
|
||||
$oddsSnapshot = is_array($item->odds_snapshot_json) ? $item->odds_snapshot_json : [];
|
||||
foreach ($oddsSnapshot as $row) {
|
||||
if (! is_array($row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! array_key_exists('rebate_rate', $row)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->normalizeRate((float) $row['rebate_rate']);
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
private function normalizeRate(float $rate): float
|
||||
{
|
||||
return max(0.0, min(1.0, $rate));
|
||||
}
|
||||
|
||||
private function platformWinLoss(TicketItem $item, int $netWin, string $terminalStatus): float
|
||||
{
|
||||
if ($terminalStatus === 'settled_lose') {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Services\AgentSettlement;
|
||||
|
||||
use App\Models\Player;
|
||||
use App\Services\Player\PlayerCreditService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
@@ -10,6 +12,7 @@ final class AgentSettlementBadDebtService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly AgentSettlementPeriodCompletionService $periodCompletion,
|
||||
private readonly PlayerCreditService $playerCreditService,
|
||||
) {}
|
||||
|
||||
public function writeOff(int $originalBillId, ?string $reason, int $adminUserId): int
|
||||
@@ -99,6 +102,13 @@ final class AgentSettlementBadDebtService
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
if ((string) $original->owner_type === 'player' && (int) $original->owner_id > 0 && (int) $original->net_amount > 0) {
|
||||
$player = Player::query()->find((int) $original->owner_id);
|
||||
if ($player !== null) {
|
||||
$this->playerCreditService->releaseFromSettlement($player, $unpaid, $originalBillId);
|
||||
}
|
||||
}
|
||||
|
||||
$this->periodCompletion->syncIfReady($periodId);
|
||||
|
||||
return $archiveBillId;
|
||||
|
||||
@@ -56,6 +56,20 @@ final class AgentSettlementBillGuard
|
||||
public function markConfirmed(int $billId): void
|
||||
{
|
||||
$this->assertPeriodMutable($billId);
|
||||
$bill = DB::table('settlement_bills')->where('id', $billId)->first();
|
||||
if ($bill === null) {
|
||||
throw new \InvalidArgumentException('bill_not_found');
|
||||
}
|
||||
|
||||
if ((string) $bill->status === 'confirmed') {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((string) $bill->status !== 'pending_confirm') {
|
||||
throw ValidationException::withMessages([
|
||||
'bill' => ['not_confirmable'],
|
||||
]);
|
||||
}
|
||||
|
||||
DB::table('settlement_bills')->where('id', $billId)->update([
|
||||
'status' => 'confirmed',
|
||||
|
||||
@@ -18,7 +18,9 @@ final class SettlementCenterLedgerService
|
||||
'bet_hold',
|
||||
'bet_hold_release',
|
||||
'game_settlement_loss',
|
||||
'game_settlement_win',
|
||||
'settlement_confirm',
|
||||
'settlement_payout',
|
||||
];
|
||||
|
||||
private const ADJUSTMENT_BIZ_TYPES = [
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Services\AgentSettlement;
|
||||
use App\Models\Player;
|
||||
use App\Services\Player\PlayerCreditService;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
final class SettlementPaymentService
|
||||
{
|
||||
@@ -25,66 +26,72 @@ final class SettlementPaymentService
|
||||
*/
|
||||
public function recordPayment(int $billId, int $amount, int $adminUserId, array $meta = []): void
|
||||
{
|
||||
$bill = DB::table('settlement_bills')->where('id', $billId)->first();
|
||||
if ($bill === null) {
|
||||
throw new \InvalidArgumentException('bill_not_found');
|
||||
}
|
||||
DB::transaction(function () use ($billId, $amount, $adminUserId, $meta): void {
|
||||
$bill = DB::table('settlement_bills')->where('id', $billId)->lockForUpdate()->first();
|
||||
if ($bill === null) {
|
||||
throw new \InvalidArgumentException('bill_not_found');
|
||||
}
|
||||
|
||||
$this->billGuard->assertPeriodMutable($billId);
|
||||
$this->billGuard->assertPayable($billId);
|
||||
$this->billGuard->assertPeriodMutable($billId);
|
||||
if (! in_array((string) $bill->status, ['confirmed', 'partial_paid', 'overdue'], true)) {
|
||||
throw ValidationException::withMessages([
|
||||
'bill' => ['not_payable'],
|
||||
]);
|
||||
}
|
||||
|
||||
$amount = min($amount, abs((int) $bill->unpaid_amount));
|
||||
if ($amount <= 0) {
|
||||
return;
|
||||
}
|
||||
$payAmount = min($amount, abs((int) $bill->unpaid_amount));
|
||||
if ($payAmount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
[$payerType, $payerId, $payeeType, $payeeId] = $this->resolvePayerPayee($bill);
|
||||
[$payerType, $payerId, $payeeType, $payeeId] = $this->resolvePayerPayee($bill);
|
||||
|
||||
DB::table('payment_records')->insert([
|
||||
'settlement_bill_id' => $billId,
|
||||
'payer_type' => $payerType,
|
||||
'payer_id' => $payerId,
|
||||
'payee_type' => $payeeType,
|
||||
'payee_id' => $payeeId,
|
||||
'amount' => $amount,
|
||||
'method' => $meta['method'] ?? null,
|
||||
'proof' => $meta['proof'] ?? null,
|
||||
'remark' => $meta['remark'] ?? null,
|
||||
'status' => 'confirmed',
|
||||
'created_by' => $adminUserId,
|
||||
'confirmed_by' => $adminUserId,
|
||||
'confirmed_at' => now(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
DB::table('payment_records')->insert([
|
||||
'settlement_bill_id' => $billId,
|
||||
'payer_type' => $payerType,
|
||||
'payer_id' => $payerId,
|
||||
'payee_type' => $payeeType,
|
||||
'payee_id' => $payeeId,
|
||||
'amount' => $payAmount,
|
||||
'method' => $meta['method'] ?? null,
|
||||
'proof' => $meta['proof'] ?? null,
|
||||
'remark' => $meta['remark'] ?? null,
|
||||
'status' => 'confirmed',
|
||||
'created_by' => $adminUserId,
|
||||
'confirmed_by' => $adminUserId,
|
||||
'confirmed_at' => now(),
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
$newPaid = (int) $bill->paid_amount + $amount;
|
||||
$newUnpaid = max(0, (int) $bill->unpaid_amount - $amount);
|
||||
$status = $newUnpaid === 0 ? 'settled' : 'partial_paid';
|
||||
$newPaid = (int) $bill->paid_amount + $payAmount;
|
||||
$newUnpaid = max(0, (int) $bill->unpaid_amount - $payAmount);
|
||||
$status = $newUnpaid === 0 ? 'settled' : 'partial_paid';
|
||||
|
||||
DB::table('settlement_bills')->where('id', $billId)->update([
|
||||
'paid_amount' => $newPaid,
|
||||
'unpaid_amount' => $newUnpaid,
|
||||
'status' => $status,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
DB::table('settlement_bills')->where('id', $billId)->update([
|
||||
'paid_amount' => $newPaid,
|
||||
'unpaid_amount' => $newUnpaid,
|
||||
'status' => $status,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
if ($bill->owner_type === 'player' && (int) $bill->owner_id > 0) {
|
||||
$player = Player::query()->find((int) $bill->owner_id);
|
||||
if ($player !== null) {
|
||||
if ((int) $bill->net_amount > 0) {
|
||||
$this->playerCreditService->releaseFromSettlement($player, $amount, $billId);
|
||||
} elseif ((int) $bill->net_amount < 0) {
|
||||
$this->playerCreditService->applySettlementPayout($player, $amount, $billId);
|
||||
}
|
||||
if ($bill->owner_type === 'player' && (int) $bill->owner_id > 0) {
|
||||
$player = Player::query()->find((int) $bill->owner_id);
|
||||
if ($player !== null) {
|
||||
if ((int) $bill->net_amount > 0) {
|
||||
$this->playerCreditService->releaseFromSettlement($player, $payAmount, $billId);
|
||||
} elseif ((int) $bill->net_amount < 0) {
|
||||
$this->playerCreditService->applySettlementPayout($player, $payAmount, $billId);
|
||||
}
|
||||
|
||||
if ($status === 'settled') {
|
||||
$this->periodCloseRebate->markRebatesSettledForBill($billId);
|
||||
if ($status === 'settled') {
|
||||
$this->periodCloseRebate->markRebatesSettledForBill($billId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->periodCompletion->syncIfReady((int) $bill->settlement_period_id);
|
||||
$this->periodCompletion->syncIfReady((int) $bill->settlement_period_id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,7 +8,7 @@ use App\Models\JackpotPool;
|
||||
use App\Models\JackpotContribution;
|
||||
|
||||
/**
|
||||
* 产品文档 §5.11.1:每笔有效注单按比例蓄水(在下注成功路径调用,非结算)。
|
||||
* 产品文档 §5.11.1:每笔满足门槛的有效注单按下注额比例蓄水(在下注成功路径调用,非结算)。
|
||||
*/
|
||||
final class JackpotContributionService
|
||||
{
|
||||
@@ -25,12 +25,14 @@ final class JackpotContributionService
|
||||
return;
|
||||
}
|
||||
|
||||
if ((int) $item->actual_deduct_amount < (int) $pool->min_bet_amount) {
|
||||
$betAmount = (int) $item->total_bet_amount;
|
||||
|
||||
if ($betAmount < (int) $pool->min_bet_amount) {
|
||||
return;
|
||||
}
|
||||
|
||||
$rate = (float) $pool->contribution_rate;
|
||||
$contrib = (int) floor((int) $item->actual_deduct_amount * $rate);
|
||||
$contrib = (int) floor($betAmount * $rate);
|
||||
if ($contrib <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ use Illuminate\Support\Facades\Cache;
|
||||
*/
|
||||
final class LotterySettings
|
||||
{
|
||||
private const CURRENCY_DISPLAY_DECIMALS = 2;
|
||||
private const CURRENCY_DECIMAL_SEPARATOR = '.';
|
||||
private const CURRENCY_THOUSANDS_SEPARATOR = ',';
|
||||
|
||||
public static function defaultCurrency(): string
|
||||
{
|
||||
$fallback = (string) config('lottery.default_currency', 'NPR');
|
||||
@@ -70,25 +74,17 @@ final class LotterySettings
|
||||
|
||||
public static function currencyDisplayDecimals(): int
|
||||
{
|
||||
$fallback = (int) config('lottery.ui.format.currency.decimals', 2);
|
||||
|
||||
return max(0, min(12, (int) self::get('currency.display_decimals', $fallback)));
|
||||
return self::CURRENCY_DISPLAY_DECIMALS;
|
||||
}
|
||||
|
||||
public static function currencyDecimalSeparator(): string
|
||||
{
|
||||
return (string) self::get(
|
||||
'currency.decimal_separator',
|
||||
(string) config('lottery.ui.format.currency.decimal_separator', '.')
|
||||
);
|
||||
return self::CURRENCY_DECIMAL_SEPARATOR;
|
||||
}
|
||||
|
||||
public static function currencyThousandsSeparator(): string
|
||||
{
|
||||
return (string) self::get(
|
||||
'currency.thousands_separator',
|
||||
(string) config('lottery.ui.format.currency.thousands_separator', ',')
|
||||
);
|
||||
return self::CURRENCY_THOUSANDS_SEPARATOR;
|
||||
}
|
||||
|
||||
public static function cacheTtlSeconds(): int
|
||||
|
||||
58
app/Services/Ticket/InstantRebateResolver.php
Normal file
58
app/Services/Ticket/InstantRebateResolver.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Ticket;
|
||||
|
||||
use App\Models\AgentProfile;
|
||||
use App\Models\Player;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
final class InstantRebateResolver
|
||||
{
|
||||
/**
|
||||
* @return array{
|
||||
* base_rebate_rate: float,
|
||||
* player_addon_rebate_rate: float,
|
||||
* final_rebate_rate: float,
|
||||
* inherited_from_agent: bool
|
||||
* }
|
||||
*/
|
||||
public function resolveForPlayer(Player $player, string $playCode, float $baseRebateRate): array
|
||||
{
|
||||
$row = DB::table('player_rebate_profiles')
|
||||
->where('player_id', $player->id)
|
||||
->where('game_type', $playCode)
|
||||
->first();
|
||||
|
||||
if ($row === null) {
|
||||
$row = DB::table('player_rebate_profiles')
|
||||
->where('player_id', $player->id)
|
||||
->where('game_type', '*')
|
||||
->first();
|
||||
}
|
||||
|
||||
$addonRate = 0.0;
|
||||
$inheritedFromAgent = false;
|
||||
|
||||
if ($row !== null && ! (bool) $row->inherit_from_agent) {
|
||||
$addonRate = (float) $row->rebate_rate + (float) $row->extra_rebate_rate;
|
||||
} else {
|
||||
$inheritedFromAgent = true;
|
||||
$profile = $player->agent_node_id
|
||||
? AgentProfile::query()->where('agent_node_id', $player->agent_node_id)->first()
|
||||
: null;
|
||||
$addonRate = (float) ($profile?->default_player_rebate ?? 0);
|
||||
}
|
||||
|
||||
return [
|
||||
'base_rebate_rate' => $this->normalizeRate($baseRebateRate),
|
||||
'player_addon_rebate_rate' => $this->normalizeRate($addonRate),
|
||||
'final_rebate_rate' => $this->normalizeRate($baseRebateRate + $addonRate),
|
||||
'inherited_from_agent' => $inheritedFromAgent,
|
||||
];
|
||||
}
|
||||
|
||||
private function normalizeRate(float $rate): float
|
||||
{
|
||||
return max(0.0, min(1.0, $rate));
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ final class TicketPlacementService
|
||||
public function __construct(
|
||||
private readonly PlayCatalogResolver $catalogResolver,
|
||||
private readonly PlayRuleEngine $ruleEngine,
|
||||
private readonly InstantRebateResolver $instantRebateResolver,
|
||||
private readonly RiskPoolService $riskPoolService,
|
||||
private readonly TicketWalletService $ticketWalletService,
|
||||
private readonly JackpotContributionService $jackpotContribution,
|
||||
@@ -532,12 +533,29 @@ final class TicketPlacementService
|
||||
*/
|
||||
private function applyCreditLineInstantRebatePolicy(Player $player, array $evaluated): array
|
||||
{
|
||||
if (! PlayerFundingMode::usesCredit($player)) {
|
||||
$resolved = $this->instantRebateResolver->resolveForPlayer(
|
||||
$player,
|
||||
(string) $evaluated['play_code'],
|
||||
(float) $evaluated['rebate_rate_snapshot'],
|
||||
);
|
||||
|
||||
$evaluated['rule_snapshot_json']['base_rebate_rate'] = number_format($resolved['base_rebate_rate'], 4, '.', '');
|
||||
$evaluated['rule_snapshot_json']['player_addon_rebate_rate'] = number_format($resolved['player_addon_rebate_rate'], 4, '.', '');
|
||||
$evaluated['rule_snapshot_json']['rebate_inherited_from_agent'] = $resolved['inherited_from_agent'];
|
||||
|
||||
if (PlayerFundingMode::usesCredit($player)) {
|
||||
$evaluated['rebate_rate_snapshot'] = '0.0000';
|
||||
$evaluated['actual_deduct_amount'] = (int) $evaluated['total_bet_amount'];
|
||||
|
||||
return $evaluated;
|
||||
}
|
||||
|
||||
$evaluated['rebate_rate_snapshot'] = '0.0000';
|
||||
$evaluated['actual_deduct_amount'] = (int) $evaluated['total_bet_amount'];
|
||||
$finalRate = $resolved['final_rebate_rate'];
|
||||
$evaluated['rebate_rate_snapshot'] = number_format($finalRate, 4, '.', '');
|
||||
$evaluated['actual_deduct_amount'] = max(
|
||||
0,
|
||||
(int) floor((int) $evaluated['total_bet_amount'] * (1 - $finalRate)),
|
||||
);
|
||||
|
||||
return $evaluated;
|
||||
}
|
||||
|
||||
@@ -3,15 +3,18 @@
|
||||
namespace App\Services\Ticket;
|
||||
|
||||
use App\Models\Draw;
|
||||
use App\Models\Player;
|
||||
use App\Lottery\ErrorCode;
|
||||
use App\Exceptions\TicketOperationException;
|
||||
use App\Services\Draw\DrawHallSnapshotBuilder;
|
||||
use App\Support\PlayerFundingMode;
|
||||
|
||||
final class TicketPreviewService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PlayCatalogResolver $catalogResolver,
|
||||
private readonly PlayRuleEngine $ruleEngine,
|
||||
private readonly InstantRebateResolver $instantRebateResolver,
|
||||
private readonly RiskPoolService $riskPoolService,
|
||||
private readonly DrawHallSnapshotBuilder $drawHallSnapshot,
|
||||
) {}
|
||||
@@ -20,7 +23,7 @@ final class TicketPreviewService
|
||||
* @param array<string, mixed> $payload
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function preview(array $payload): array
|
||||
public function preview(Player $player, array $payload): array
|
||||
{
|
||||
$drawNo = trim((string) ($payload['draw_id'] ?? ''));
|
||||
$draw = $drawNo === ''
|
||||
@@ -62,6 +65,7 @@ final class TicketPreviewService
|
||||
$resolved['play_config'],
|
||||
$resolved['odds_items'],
|
||||
);
|
||||
$evaluated = $this->applyPlayerInstantRebate($player, $evaluated);
|
||||
|
||||
$locks = array_map(fn (array $combo): array => [
|
||||
'number_4d' => $combo['number_4d'],
|
||||
@@ -131,4 +135,37 @@ final class TicketPreviewService
|
||||
'warnings' => $warningRows,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $evaluated
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function applyPlayerInstantRebate(Player $player, array $evaluated): array
|
||||
{
|
||||
$resolved = $this->instantRebateResolver->resolveForPlayer(
|
||||
$player,
|
||||
(string) $evaluated['play_code'],
|
||||
(float) $evaluated['rebate_rate_snapshot'],
|
||||
);
|
||||
|
||||
$evaluated['rule_snapshot_json']['base_rebate_rate'] = number_format($resolved['base_rebate_rate'], 4, '.', '');
|
||||
$evaluated['rule_snapshot_json']['player_addon_rebate_rate'] = number_format($resolved['player_addon_rebate_rate'], 4, '.', '');
|
||||
$evaluated['rule_snapshot_json']['rebate_inherited_from_agent'] = $resolved['inherited_from_agent'];
|
||||
|
||||
if (PlayerFundingMode::usesCredit($player)) {
|
||||
$evaluated['rebate_rate_snapshot'] = '0.0000';
|
||||
$evaluated['actual_deduct_amount'] = (int) $evaluated['total_bet_amount'];
|
||||
|
||||
return $evaluated;
|
||||
}
|
||||
|
||||
$finalRate = $resolved['final_rebate_rate'];
|
||||
$evaluated['rebate_rate_snapshot'] = number_format($finalRate, 4, '.', '');
|
||||
$evaluated['actual_deduct_amount'] = max(
|
||||
0,
|
||||
(int) floor((int) $evaluated['total_bet_amount'] * (1 - $finalRate)),
|
||||
);
|
||||
|
||||
return $evaluated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ final class PlayerLedgerLogsService
|
||||
'bet_hold_release',
|
||||
'game_settlement_loss',
|
||||
'game_settlement_win',
|
||||
'settlement_confirm',
|
||||
'settlement_payout',
|
||||
])->limit(5000)->get()->all();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user