feat: enhance agent management and validation logic

- Updated AGENTS.md to clarify agent account restrictions and permissions.
- Implemented checks in AgentNodeAdminUserStoreController and AgentNodeRoleStoreController to restrict admin user and role creation to the agent's own node.
- Enhanced validation in AdminPlayerStoreController and AdminPlayerUpdateController to enforce credit limit and rebate rate rules based on player funding mode.
- Refactored various request classes to utilize shared admin account field rules for consistency.
- Improved error handling in services related to credit allocation and rebate limits to ensure proper validation and messaging.
This commit is contained in:
2026-06-14 21:13:27 +08:00
parent 395e1c7400
commit 5b6d4cb74d
56 changed files with 1558 additions and 222 deletions

View File

@@ -0,0 +1,78 @@
<?php
namespace App\Services\Ticket;
use App\Models\Player;
use App\Support\PlayerFundingMode;
/**
* 下注行回水:钱包盘立减实扣;信用盘仅展示账期回水预估,实扣仍按全额占用授信。
*/
final class TicketLineInstantRebateApplicator
{
public function __construct(
private readonly InstantRebateResolver $instantRebateResolver,
) {}
/**
* @param array<string, mixed> $evaluated
* @return array<string, mixed>
*/
public function apply(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'];
$evaluated['rule_snapshot_json']['instant_rebate_applied'] = ! PlayerFundingMode::usesCredit($player);
$finalRate = $resolved['final_rebate_rate'];
$evaluated['rebate_rate_snapshot'] = number_format($finalRate, 4, '.', '');
if (PlayerFundingMode::usesCredit($player)) {
$evaluated['actual_deduct_amount'] = (int) $evaluated['total_bet_amount'];
return $evaluated;
}
$evaluated['actual_deduct_amount'] = max(
0,
(int) floor((int) $evaluated['total_bet_amount'] * (1 - $finalRate)),
);
return $evaluated;
}
/**
* 确认弹窗展示用回水:信用盘为账期回水预估,钱包盘为下注立减额。
*
* @param array<string, mixed> $evaluated
*/
public function displayRebateAmount(Player $player, array $evaluated): int
{
$bet = (int) $evaluated['total_bet_amount'];
if (PlayerFundingMode::usesCredit($player)) {
$rate = (float) ($evaluated['rebate_rate_snapshot'] ?? 0);
return (int) floor($bet * max(0.0, min(1.0, $rate)));
}
return max(0, $bet - (int) $evaluated['actual_deduct_amount']);
}
/** 落库订单/注单上的即时回水合计(信用盘为 0。 */
public function persistedInstantRebateAmount(Player $player, array $evaluated): int
{
if (PlayerFundingMode::usesCredit($player)) {
return 0;
}
return $this->displayRebateAmount($player, $evaluated);
}
}