Files
lotteryLaravel/app/Services/Agent/CreditAllocationValidator.php
kang 5b6d4cb74d 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.
2026-06-14 21:13:27 +08:00

103 lines
3.2 KiB
PHP

<?php
namespace App\Services\Agent;
use App\Models\AgentNode;
use App\Models\AgentProfile;
use App\Support\AgentOverdueGuard;
use Illuminate\Validation\ValidationException;
final class CreditAllocationValidator
{
public function __construct(
private readonly AgentCreditAllocatedSyncService $allocatedSync,
) {}
public function assertChildCreditLimitWithinParent(
AgentNode $parent,
int $previousChildLimit,
int $newChildLimit,
bool $isNewChild,
): void {
if ($newChildLimit < 0) {
throw ValidationException::withMessages([
'credit_limit' => ['invalid'],
]);
}
$this->allocatedSync->syncForAgent($parent);
$profile = AgentProfile::query()->where('agent_node_id', $parent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['parent_profile_required'],
]);
}
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
$floor = $isNewChild ? 0 : max(0, $previousChildLimit);
$maxAllowed = $floor + $available;
if ($newChildLimit > $maxAllowed) {
throw ValidationException::withMessages([
'credit_limit' => ['exceeds_available'],
]);
}
}
public function assertAllocationWithinParent(AgentNode $parent, int $additionalCredit): void
{
$this->allocatedSync->syncForAgent($parent);
$profile = AgentProfile::query()->where('agent_node_id', $parent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['parent_profile_required'],
]);
}
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
if ($additionalCredit > $available) {
throw ValidationException::withMessages([
'credit_limit' => ['exceeds_available'],
]);
}
}
public function assertPlayerCreditWithinAgent(AgentNode $agent, int $playerCreditLimit): void
{
if ($playerCreditLimit < 0) {
throw ValidationException::withMessages([
'credit_limit' => ['invalid'],
]);
}
$this->assertPlayerCreditDeltaWithinAgent($agent, $playerCreditLimit);
}
public function assertPlayerCreditDeltaWithinAgent(AgentNode $agent, int $additionalCredit): void
{
if ($additionalCredit <= 0) {
return;
}
AgentOverdueGuard::assertAgentMayGrantCredit((int) $agent->id);
$this->allocatedSync->syncForAgent($agent);
$profile = AgentProfile::query()->where('agent_node_id', $agent->id)->first();
if ($profile === null) {
throw ValidationException::withMessages([
'credit_limit' => ['agent_profile_required'],
]);
}
$available = max(0, (int) $profile->credit_limit - (int) $profile->allocated_credit);
if ($additionalCredit > $available) {
throw ValidationException::withMessages([
'credit_limit' => ['exceeds_available'],
]);
}
}
}