feat(admin+api): 代理停用默认、结算加固与冒烟配置探针
- 代理层级默认授信比例与停用冻结/禁登全局默认 - 结算预览去重、比分校验、串关当场判负与市场类型校验 - 站内信 Banner/公告自动通知开关;开发环境动态 API 端口 - 扩充 RBAC/结算/认证/返现单元测试与 agent skills
This commit is contained in:
@@ -40,6 +40,15 @@ export class AgentsService {
|
||||
return agentLevel < maxLevel;
|
||||
}
|
||||
|
||||
/** 与 Admin 创建下级代理预填逻辑一致:可用授信 × 比例(%),非 100% 时向下取整到百位 */
|
||||
computeDefaultSubAgentCredit(availableCredit: number, ratioPercent: number): number {
|
||||
if (availableCredit <= 0) return 0;
|
||||
const pct = Math.min(100, Math.max(1, ratioPercent)) / 100;
|
||||
const raw = availableCredit * pct;
|
||||
const rounded = pct >= 1 ? availableCredit : Math.floor(raw / 100) * 100;
|
||||
return Math.min(availableCredit, Math.max(0, rounded));
|
||||
}
|
||||
|
||||
private async buildAgentAncestorChainMap(parentAgentIds: (bigint | null | undefined)[]) {
|
||||
return this.network.buildAgentAncestorChainMap(parentAgentIds);
|
||||
}
|
||||
@@ -923,11 +932,17 @@ export class AgentsService {
|
||||
});
|
||||
}
|
||||
|
||||
// Handle status change (per-action cascade freeze / login block)
|
||||
// Handle status change (per-action cascade freeze / login block; 未传参时用全局默认)
|
||||
if (data.status) {
|
||||
const profilePatch: Prisma.AgentProfileUpdateInput = { status: data.status };
|
||||
let freezeDirectPlayers = false;
|
||||
if (data.status === 'SUSPENDED') {
|
||||
profilePatch.blockDirectPlayerLogin = data.blockDirectPlayerLogin === true;
|
||||
const suspendDefaults = await this.systemConfig.getAgentSuspendSettings();
|
||||
const blockDirectPlayerLogin =
|
||||
data.blockDirectPlayerLogin ?? suspendDefaults.suspendBlockPlayerLogin;
|
||||
freezeDirectPlayers =
|
||||
data.freezeDirectPlayers ?? suspendDefaults.suspendFreezeDirectPlayers;
|
||||
profilePatch.blockDirectPlayerLogin = blockDirectPlayerLogin === true;
|
||||
} else if (data.status === 'ACTIVE') {
|
||||
profilePatch.blockDirectPlayerLogin = false;
|
||||
}
|
||||
@@ -943,7 +958,7 @@ export class AgentsService {
|
||||
}),
|
||||
]);
|
||||
|
||||
if (data.status === 'SUSPENDED' && data.freezeDirectPlayers) {
|
||||
if (data.status === 'SUSPENDED' && freezeDirectPlayers) {
|
||||
await this.prisma.user.updateMany({
|
||||
where: { parentId: agentId, userType: 'PLAYER', deletedAt: null },
|
||||
data: { status: 'SUSPENDED' },
|
||||
@@ -1156,20 +1171,31 @@ export class AgentsService {
|
||||
) {
|
||||
await this.validateAgentLevel(data.level, data.parentAgentId);
|
||||
|
||||
let resolvedCreditLimit = data.creditLimit;
|
||||
let resolvedCashbackRate = data.cashbackRate ?? 0;
|
||||
if (data.parentAgentId) {
|
||||
const parentProfile = await this.prisma.agentProfile.findUnique({
|
||||
where: { userId: data.parentAgentId },
|
||||
select: { cashbackRate: true },
|
||||
select: { cashbackRate: true, creditLimit: true, usedCredit: true },
|
||||
});
|
||||
resolvedCashbackRate =
|
||||
data.cashbackRate ?? (parentProfile ? Number(parentProfile.cashbackRate) : 0);
|
||||
if (resolvedCreditLimit === undefined && parentProfile) {
|
||||
const hierarchy = await this.systemConfig.getAgentHierarchySettings();
|
||||
const available = new Decimal(parentProfile.creditLimit).sub(parentProfile.usedCredit);
|
||||
resolvedCreditLimit = this.computeDefaultSubAgentCredit(
|
||||
available.toNumber(),
|
||||
hierarchy.defaultSubAgentCreditRatio,
|
||||
);
|
||||
}
|
||||
await this.assertChildAgentWithinParent(data.parentAgentId, {
|
||||
creditLimit: data.creditLimit ?? 0,
|
||||
creditLimit: resolvedCreditLimit ?? 0,
|
||||
cashbackRate: resolvedCashbackRate,
|
||||
maxSingleDeposit: data.maxSingleDeposit,
|
||||
maxDailyDeposit: data.maxDailyDeposit,
|
||||
});
|
||||
} else if (resolvedCreditLimit === undefined) {
|
||||
resolvedCreditLimit = 0;
|
||||
}
|
||||
|
||||
const maxSingleDeposit = this.normalizeOptionalLimit(data.maxSingleDeposit);
|
||||
@@ -1208,7 +1234,7 @@ export class AgentsService {
|
||||
userId: user.id,
|
||||
level: data.level,
|
||||
parentAgentId: data.parentAgentId,
|
||||
creditLimit: data.creditLimit ?? 0,
|
||||
creditLimit: resolvedCreditLimit ?? 0,
|
||||
cashbackRate: resolvedCashbackRate,
|
||||
maxSingleDeposit,
|
||||
maxDailyDeposit,
|
||||
|
||||
Reference in New Issue
Block a user