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} 不存在`);
|
||||
}
|
||||
|
||||
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 = {
|
||||
accountSequence: user.accountSequence,
|
||||
userId: user.userId.toString(),
|
||||
nickname: user.nickname,
|
||||
avatar: user.avatarUrl,
|
||||
personalAdoptions: user.personalAdoptionCount,
|
||||
personalAdoptions: personalAdoptionCount,
|
||||
depth: referralInfo?.depth || 0,
|
||||
directReferralCount: referralInfo?.directReferralCount || 0,
|
||||
directReferralCount: directReferralCount,
|
||||
isCurrentUser: true,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -251,6 +251,11 @@ export interface IUserDetailQueryRepository {
|
|||
*/
|
||||
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);
|
||||
if (ancestorIds.length === 0) return [];
|
||||
|
||||
// 获取祖先用户信息
|
||||
// 获取祖先用户信息和引荐关系
|
||||
const [users, referrals] = await Promise.all([
|
||||
this.prisma.userQueryView.findMany({
|
||||
where: { userId: { in: ancestorIds } },
|
||||
|
|
@ -69,19 +69,41 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
accountSequence: true,
|
||||
nickname: true,
|
||||
avatarUrl: true,
|
||||
personalAdoptionCount: true,
|
||||
},
|
||||
}),
|
||||
this.prisma.referralQueryView.findMany({
|
||||
where: { userId: { in: ancestorIds } },
|
||||
select: {
|
||||
userId: true,
|
||||
accountSequence: 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 userMap = new Map(users.map((u) => [u.userId.toString(), u]));
|
||||
|
|
@ -94,9 +116,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
accountSequence: user?.accountSequence || '',
|
||||
nickname: user?.nickname || null,
|
||||
avatarUrl: user?.avatarUrl || null,
|
||||
personalAdoptionCount: user?.personalAdoptionCount || 0,
|
||||
personalAdoptionCount: adoptionCountMap.get(user?.accountSequence || '') || 0,
|
||||
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,
|
||||
accountSequence: true,
|
||||
depth: true,
|
||||
directReferralCount: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (directReferrals.length === 0) return [];
|
||||
|
||||
// 获取用户信息
|
||||
const userIds = directReferrals.map((r) => r.userId);
|
||||
const users = await this.prisma.userQueryView.findMany({
|
||||
where: { userId: { in: directReferrals.map((r) => r.userId) } },
|
||||
where: { userId: { in: userIds } },
|
||||
select: {
|
||||
userId: true,
|
||||
accountSequence: true,
|
||||
nickname: 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]));
|
||||
|
||||
return directReferrals.map((ref) => {
|
||||
|
|
@ -142,9 +185,9 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
accountSequence: ref.accountSequence,
|
||||
nickname: user?.nickname || null,
|
||||
avatarUrl: user?.avatarUrl || null,
|
||||
personalAdoptionCount: user?.personalAdoptionCount || 0,
|
||||
personalAdoptionCount: adoptionCountMap.get(ref.accountSequence) || 0,
|
||||
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> {
|
||||
// 统计用户的认种订单数量(状态为 MINING_ENABLED)
|
||||
const count = await this.prisma.plantingOrderQueryView.count({
|
||||
where: {
|
||||
accountSequence,
|
||||
status: 'MINING_ENABLED',
|
||||
},
|
||||
});
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
async getDirectReferralCount(accountSequence: string): Promise<number> {
|
||||
// 先获取用户的 userId
|
||||
const user = await this.prisma.userQueryView.findUnique({
|
||||
const referral = await this.prisma.referralQueryView.findUnique({
|
||||
where: { accountSequence },
|
||||
select: { userId: true },
|
||||
});
|
||||
|
||||
if (!user) return 0;
|
||||
if (!referral) return 0;
|
||||
|
||||
// 从 PlantingPositionQueryView 获取有效认种树数
|
||||
const position = await this.prisma.plantingPositionQueryView.findUnique({
|
||||
where: { userId: user.userId },
|
||||
select: { effectiveTreeCount: true },
|
||||
// 统计以该用户为 referrerId 的用户数量
|
||||
const count = await this.prisma.referralQueryView.count({
|
||||
where: { referrerId: referral.userId },
|
||||
});
|
||||
|
||||
return position?.effectiveTreeCount || 0;
|
||||
return count;
|
||||
}
|
||||
|
||||
async getTeamStats(accountSequence: string): Promise<{ teamAddressCount: number; teamAdoptionCount: number }> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue