- 在多个控制器中引入 SettlementPartyEnrichment 服务,以优化代理结算和账单的处理逻辑。 - 更新 AgentSettlementBillIndexController 和 AgentSettlementBillShowController,支持根据账单 ID 和关键字进行查询。 - 在 AgentSettlementPeriodCloseController 中添加对站点管理权限的验证,确保只有具备相应权限的管理员能够关闭账期。 - 在 AgentSettlementPeriodIndexController 中更新账期数据的返回格式,提升数据的完整性和可用性。 - 引入对相对占成比例的支持,增强代理资料的管理能力,确保数据一致性。
125 lines
3.8 KiB
PHP
125 lines
3.8 KiB
PHP
<?php
|
||
|
||
namespace App\Support;
|
||
|
||
use Illuminate\Support\Facades\DB;
|
||
|
||
final class AgentOverdueGuard
|
||
{
|
||
public static function agentHasOverdueBills(int $agentNodeId): bool
|
||
{
|
||
if ($agentNodeId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
return DB::table('settlement_bills')
|
||
->where('owner_type', 'agent')
|
||
->where('owner_id', $agentNodeId)
|
||
->where('status', 'overdue')
|
||
->where('unpaid_amount', '>', 0)
|
||
->exists();
|
||
}
|
||
|
||
public static function agentHasSevereOverdueBills(int $agentNodeId, int $days = 7): bool
|
||
{
|
||
if ($agentNodeId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
$cutoff = now()->subDays($days);
|
||
|
||
return DB::table('settlement_bills')
|
||
->where('owner_type', 'agent')
|
||
->where('owner_id', $agentNodeId)
|
||
->where('status', 'overdue')
|
||
->where('unpaid_amount', '>', 0)
|
||
->where('updated_at', '<', $cutoff)
|
||
->exists();
|
||
}
|
||
|
||
public static function agentLineHasSevereOverdueBills(int $agentNodeId, int $days = 7): bool
|
||
{
|
||
if ($agentNodeId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
$agent = DB::table('agent_nodes')->where('id', $agentNodeId)->first();
|
||
if ($agent === null) {
|
||
return false;
|
||
}
|
||
|
||
// 获取该代理的所有祖先节点ID(包括自己)
|
||
$path = (string) $agent->path;
|
||
if ($path === '') {
|
||
// 根节点,只检查自己
|
||
$ancestorIds = [$agentNodeId];
|
||
} else {
|
||
// 解析 path 获取所有祖先ID
|
||
$parts = explode('/', trim($path, '/'));
|
||
$ancestorIds = array_map('intval', $parts);
|
||
$ancestorIds[] = $agentNodeId;
|
||
}
|
||
|
||
$cutoff = now()->subDays($days);
|
||
|
||
return DB::table('settlement_bills')
|
||
->where('owner_type', 'agent')
|
||
->where('status', 'overdue')
|
||
->where('unpaid_amount', '>', 0)
|
||
->where('updated_at', '<', $cutoff)
|
||
->whereIn('owner_id', $ancestorIds)
|
||
->exists();
|
||
}
|
||
|
||
public static function assertAgentMayGrantCredit(int $agentNodeId): void
|
||
{
|
||
if (self::agentHasOverdueBills($agentNodeId)) {
|
||
throw \Illuminate\Validation\ValidationException::withMessages([
|
||
'credit' => ['agent_overdue'],
|
||
]);
|
||
}
|
||
}
|
||
|
||
public static function assertAgentLineMayPlaceBet(int $agentNodeId, ?int $severeOverdueDays = null): void
|
||
{
|
||
$days = $severeOverdueDays ?? config('agent_line_defaults.overdue.severe_days_threshold', 7);
|
||
if (self::agentLineHasSevereOverdueBills($agentNodeId, $days)) {
|
||
throw \Illuminate\Validation\ValidationException::withMessages([
|
||
'credit' => ['agent_line_severe_overdue'],
|
||
]);
|
||
}
|
||
}
|
||
|
||
public static function parentHasOverdueBills(int $agentNodeId): bool
|
||
{
|
||
if ($agentNodeId <= 0) {
|
||
return false;
|
||
}
|
||
|
||
$agent = DB::table('agent_nodes')->where('id', $agentNodeId)->first();
|
||
if ($agent === null || $agent->parent_id === null) {
|
||
return false;
|
||
}
|
||
|
||
return DB::table('settlement_bills')
|
||
->where('owner_type', 'agent')
|
||
->where('owner_id', $agent->parent_id)
|
||
->where('status', 'overdue')
|
||
->where('unpaid_amount', '>', 0)
|
||
->exists();
|
||
}
|
||
|
||
public static function assertMayOperateWhenParentOverdue(int $agentNodeId): void
|
||
{
|
||
if (! config('agent_line_defaults.overdue.cascade_freeze_on_parent_overdue', false)) {
|
||
return;
|
||
}
|
||
|
||
if (self::parentHasOverdueBills($agentNodeId)) {
|
||
throw \Illuminate\Validation\ValidationException::withMessages([
|
||
'parent_id' => ['parent_overdue'],
|
||
]);
|
||
}
|
||
}
|
||
}
|