fix(admin-service): 引荐关系树实时统计本人认种和直推数量
问题: - 引荐节点的"本人认种"和"引荐"显示为0 - user_query_view.personal_adoption_count 和 referral_query_view.direct_referral_count 没有被CDC更新 解决方案: - getAncestors: 实时统计每个祖先的认种订单数和直推数 - getDirectReferrals: 实时统计每个下级的认种订单数和直推数 - getReferralTree API: 实时获取当前用户的统计数据 - 新增 getDirectReferralCount 方法 实时统计方式: - 本人认种 = planting_order_query_view 中状态为 MINING_ENABLED 的订单数 - 直推数量 = referral_query_view 中 referrer_id 等于该用户的记录数 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3ed72499a0
commit
d303cf076b
|
|
@ -131,16 +131,21 @@ export class UserDetailController {
|
||||||
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
|
throw new NotFoundException(`用户 ${accountSequence} 不存在`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const referralInfo = await this.userDetailRepository.getReferralInfo(accountSequence);
|
// 获取引荐信息和实时统计
|
||||||
|
const [referralInfo, personalAdoptionCount, directReferralCount] = await Promise.all([
|
||||||
|
this.userDetailRepository.getReferralInfo(accountSequence),
|
||||||
|
this.userDetailRepository.getPersonalAdoptionCount(accountSequence),
|
||||||
|
this.userDetailRepository.getDirectReferralCount(accountSequence),
|
||||||
|
]);
|
||||||
|
|
||||||
const currentUser: ReferralNodeDto = {
|
const currentUser: ReferralNodeDto = {
|
||||||
accountSequence: user.accountSequence,
|
accountSequence: user.accountSequence,
|
||||||
userId: user.userId.toString(),
|
userId: user.userId.toString(),
|
||||||
nickname: user.nickname,
|
nickname: user.nickname,
|
||||||
avatar: user.avatarUrl,
|
avatar: user.avatarUrl,
|
||||||
personalAdoptions: user.personalAdoptionCount,
|
personalAdoptions: personalAdoptionCount,
|
||||||
depth: referralInfo?.depth || 0,
|
depth: referralInfo?.depth || 0,
|
||||||
directReferralCount: referralInfo?.directReferralCount || 0,
|
directReferralCount: directReferralCount,
|
||||||
isCurrentUser: true,
|
isCurrentUser: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,11 @@ export interface IUserDetailQueryRepository {
|
||||||
*/
|
*/
|
||||||
getPersonalAdoptionCount(accountSequence: string): Promise<number>;
|
getPersonalAdoptionCount(accountSequence: string): Promise<number>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取用户直推数量
|
||||||
|
*/
|
||||||
|
getDirectReferralCount(accountSequence: string): Promise<number>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取用户团队统计(团队地址数、团队认种量)
|
* 获取用户团队统计(团队地址数、团队认种量)
|
||||||
* 团队包括所有直推和间推用户
|
* 团队包括所有直推和间推用户
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
const ancestorIds = referral.ancestorPath.slice(0, depth);
|
const ancestorIds = referral.ancestorPath.slice(0, depth);
|
||||||
if (ancestorIds.length === 0) return [];
|
if (ancestorIds.length === 0) return [];
|
||||||
|
|
||||||
// 获取祖先用户信息
|
// 获取祖先用户信息和引荐关系
|
||||||
const [users, referrals] = await Promise.all([
|
const [users, referrals] = await Promise.all([
|
||||||
this.prisma.userQueryView.findMany({
|
this.prisma.userQueryView.findMany({
|
||||||
where: { userId: { in: ancestorIds } },
|
where: { userId: { in: ancestorIds } },
|
||||||
|
|
@ -69,19 +69,41 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
accountSequence: true,
|
accountSequence: true,
|
||||||
nickname: true,
|
nickname: true,
|
||||||
avatarUrl: true,
|
avatarUrl: true,
|
||||||
personalAdoptionCount: true,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
this.prisma.referralQueryView.findMany({
|
this.prisma.referralQueryView.findMany({
|
||||||
where: { userId: { in: ancestorIds } },
|
where: { userId: { in: ancestorIds } },
|
||||||
select: {
|
select: {
|
||||||
userId: true,
|
userId: true,
|
||||||
|
accountSequence: true,
|
||||||
depth: true,
|
depth: true,
|
||||||
directReferralCount: true,
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// 实时统计:获取每个祖先的认种数量和直推数量
|
||||||
|
const accountSequences = users.map(u => u.accountSequence);
|
||||||
|
const [adoptionCounts, directReferralCounts] = await Promise.all([
|
||||||
|
// 统计每个用户的认种订单数量(状态为 MINING_ENABLED)
|
||||||
|
this.prisma.plantingOrderQueryView.groupBy({
|
||||||
|
by: ['accountSequence'],
|
||||||
|
where: {
|
||||||
|
accountSequence: { in: accountSequences },
|
||||||
|
status: 'MINING_ENABLED',
|
||||||
|
},
|
||||||
|
_count: { id: true },
|
||||||
|
}),
|
||||||
|
// 统计每个用户的直推数量
|
||||||
|
this.prisma.referralQueryView.groupBy({
|
||||||
|
by: ['referrerId'],
|
||||||
|
where: { referrerId: { in: ancestorIds } },
|
||||||
|
_count: { userId: true },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const adoptionCountMap = new Map(adoptionCounts.map(a => [a.accountSequence, a._count.id]));
|
||||||
|
const directCountMap = new Map(directReferralCounts.map(d => [d.referrerId.toString(), d._count.userId]));
|
||||||
|
|
||||||
// 合并数据
|
// 合并数据
|
||||||
const referralMap = new Map(referrals.map((r) => [r.userId.toString(), r]));
|
const referralMap = new Map(referrals.map((r) => [r.userId.toString(), r]));
|
||||||
const userMap = new Map(users.map((u) => [u.userId.toString(), u]));
|
const userMap = new Map(users.map((u) => [u.userId.toString(), u]));
|
||||||
|
|
@ -94,9 +116,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
accountSequence: user?.accountSequence || '',
|
accountSequence: user?.accountSequence || '',
|
||||||
nickname: user?.nickname || null,
|
nickname: user?.nickname || null,
|
||||||
avatarUrl: user?.avatarUrl || null,
|
avatarUrl: user?.avatarUrl || null,
|
||||||
personalAdoptionCount: user?.personalAdoptionCount || 0,
|
personalAdoptionCount: adoptionCountMap.get(user?.accountSequence || '') || 0,
|
||||||
depth: ref?.depth || index,
|
depth: ref?.depth || index,
|
||||||
directReferralCount: ref?.directReferralCount || 0,
|
directReferralCount: directCountMap.get(id.toString()) || 0,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -115,24 +137,45 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
userId: true,
|
userId: true,
|
||||||
accountSequence: true,
|
accountSequence: true,
|
||||||
depth: true,
|
depth: true,
|
||||||
directReferralCount: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (directReferrals.length === 0) return [];
|
if (directReferrals.length === 0) return [];
|
||||||
|
|
||||||
// 获取用户信息
|
// 获取用户信息
|
||||||
|
const userIds = directReferrals.map((r) => r.userId);
|
||||||
const users = await this.prisma.userQueryView.findMany({
|
const users = await this.prisma.userQueryView.findMany({
|
||||||
where: { userId: { in: directReferrals.map((r) => r.userId) } },
|
where: { userId: { in: userIds } },
|
||||||
select: {
|
select: {
|
||||||
userId: true,
|
userId: true,
|
||||||
accountSequence: true,
|
accountSequence: true,
|
||||||
nickname: true,
|
nickname: true,
|
||||||
avatarUrl: true,
|
avatarUrl: true,
|
||||||
personalAdoptionCount: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 实时统计:获取每个用户的认种数量和直推数量
|
||||||
|
const userAccountSequences = directReferrals.map(r => r.accountSequence);
|
||||||
|
const [adoptionCounts, directReferralCounts] = await Promise.all([
|
||||||
|
// 统计每个用户的认种订单数量(状态为 MINING_ENABLED)
|
||||||
|
this.prisma.plantingOrderQueryView.groupBy({
|
||||||
|
by: ['accountSequence'],
|
||||||
|
where: {
|
||||||
|
accountSequence: { in: userAccountSequences },
|
||||||
|
status: 'MINING_ENABLED',
|
||||||
|
},
|
||||||
|
_count: { id: true },
|
||||||
|
}),
|
||||||
|
// 统计每个用户的直推数量
|
||||||
|
this.prisma.referralQueryView.groupBy({
|
||||||
|
by: ['referrerId'],
|
||||||
|
where: { referrerId: { in: userIds } },
|
||||||
|
_count: { userId: true },
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const adoptionCountMap = new Map(adoptionCounts.map(a => [a.accountSequence, a._count.id]));
|
||||||
|
const directCountMap = new Map(directReferralCounts.map(d => [d.referrerId.toString(), d._count.userId]));
|
||||||
const userMap = new Map(users.map((u) => [u.userId.toString(), u]));
|
const userMap = new Map(users.map((u) => [u.userId.toString(), u]));
|
||||||
|
|
||||||
return directReferrals.map((ref) => {
|
return directReferrals.map((ref) => {
|
||||||
|
|
@ -142,9 +185,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
accountSequence: ref.accountSequence,
|
accountSequence: ref.accountSequence,
|
||||||
nickname: user?.nickname || null,
|
nickname: user?.nickname || null,
|
||||||
avatarUrl: user?.avatarUrl || null,
|
avatarUrl: user?.avatarUrl || null,
|
||||||
personalAdoptionCount: user?.personalAdoptionCount || 0,
|
personalAdoptionCount: adoptionCountMap.get(ref.accountSequence) || 0,
|
||||||
depth: ref.depth,
|
depth: ref.depth,
|
||||||
directReferralCount: ref.directReferralCount,
|
directReferralCount: directCountMap.get(ref.userId.toString()) || 0,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -428,21 +471,32 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
async getPersonalAdoptionCount(accountSequence: string): Promise<number> {
|
async getPersonalAdoptionCount(accountSequence: string): Promise<number> {
|
||||||
|
// 统计用户的认种订单数量(状态为 MINING_ENABLED)
|
||||||
|
const count = await this.prisma.plantingOrderQueryView.count({
|
||||||
|
where: {
|
||||||
|
accountSequence,
|
||||||
|
status: 'MINING_ENABLED',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getDirectReferralCount(accountSequence: string): Promise<number> {
|
||||||
// 先获取用户的 userId
|
// 先获取用户的 userId
|
||||||
const user = await this.prisma.userQueryView.findUnique({
|
const referral = await this.prisma.referralQueryView.findUnique({
|
||||||
where: { accountSequence },
|
where: { accountSequence },
|
||||||
select: { userId: true },
|
select: { userId: true },
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!user) return 0;
|
if (!referral) return 0;
|
||||||
|
|
||||||
// 从 PlantingPositionQueryView 获取有效认种树数
|
// 统计以该用户为 referrerId 的用户数量
|
||||||
const position = await this.prisma.plantingPositionQueryView.findUnique({
|
const count = await this.prisma.referralQueryView.count({
|
||||||
where: { userId: user.userId },
|
where: { referrerId: referral.userId },
|
||||||
select: { effectiveTreeCount: true },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return position?.effectiveTreeCount || 0;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTeamStats(accountSequence: string): Promise<{ teamAddressCount: number; teamAdoptionCount: number }> {
|
async getTeamStats(accountSequence: string): Promise<{ teamAddressCount: number; teamAdoptionCount: number }> {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue