feat(admin-service): 实现团队本省/本市认种量实时统计
- getBatchUserStats 新增 provinceAdoptionCount 和 cityAdoptionCount - 根据用户认种订单中的省市信息,统计团队成员同省/同市的认种量 - 百分比改为相对于该用户团队总认种量计算 🤖 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
8298f2e371
commit
d1e04152dc
|
|
@ -150,19 +150,28 @@ export class UserController {
|
|||
private mapToListItem(
|
||||
item: UserQueryItem,
|
||||
totalTeamAdoptions: number,
|
||||
realTimeStats?: { personalAdoptionCount: number; teamAddressCount: number; teamAdoptionCount: number },
|
||||
realTimeStats?: {
|
||||
personalAdoptionCount: number;
|
||||
teamAddressCount: number;
|
||||
teamAdoptionCount: number;
|
||||
provinceAdoptionCount: number;
|
||||
cityAdoptionCount: number;
|
||||
},
|
||||
): UserListItemDto {
|
||||
// 使用实时统计数据(如果有),否则使用预计算数据
|
||||
const personalAdoptions = realTimeStats?.personalAdoptionCount ?? item.personalAdoptionCount;
|
||||
const teamAddresses = realTimeStats?.teamAddressCount ?? item.teamAddressCount;
|
||||
const teamAdoptions = realTimeStats?.teamAdoptionCount ?? item.teamAdoptionCount;
|
||||
const provinceAdoptions = realTimeStats?.provinceAdoptionCount ?? item.provinceAdoptionCount;
|
||||
const cityAdoptions = realTimeStats?.cityAdoptionCount ?? item.cityAdoptionCount;
|
||||
|
||||
// 计算省市认种百分比
|
||||
const provincePercentage = totalTeamAdoptions > 0
|
||||
? Math.round((item.provinceAdoptionCount / totalTeamAdoptions) * 100)
|
||||
// 计算省市认种百分比(相对于该用户的团队总认种量)
|
||||
const userTeamAdoptions = teamAdoptions > 0 ? teamAdoptions : 1;
|
||||
const provincePercentage = teamAdoptions > 0
|
||||
? Math.round((provinceAdoptions / userTeamAdoptions) * 100)
|
||||
: 0;
|
||||
const cityPercentage = totalTeamAdoptions > 0
|
||||
? Math.round((item.cityAdoptionCount / totalTeamAdoptions) * 100)
|
||||
const cityPercentage = teamAdoptions > 0
|
||||
? Math.round((cityAdoptions / userTeamAdoptions) * 100)
|
||||
: 0;
|
||||
|
||||
return {
|
||||
|
|
@ -175,11 +184,11 @@ export class UserController {
|
|||
teamAddresses,
|
||||
teamAdoptions,
|
||||
provincialAdoptions: {
|
||||
count: item.provinceAdoptionCount,
|
||||
count: provinceAdoptions,
|
||||
percentage: provincePercentage,
|
||||
},
|
||||
cityAdoptions: {
|
||||
count: item.cityAdoptionCount,
|
||||
count: cityAdoptions,
|
||||
percentage: cityPercentage,
|
||||
},
|
||||
referrerId: item.inviterSequence,
|
||||
|
|
|
|||
|
|
@ -270,5 +270,7 @@ export interface IUserDetailQueryRepository {
|
|||
personalAdoptionCount: number;
|
||||
teamAddressCount: number;
|
||||
teamAdoptionCount: number;
|
||||
provinceAdoptionCount: number;
|
||||
cityAdoptionCount: number;
|
||||
}>>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -549,11 +549,15 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
personalAdoptionCount: number;
|
||||
teamAddressCount: number;
|
||||
teamAdoptionCount: number;
|
||||
provinceAdoptionCount: number;
|
||||
cityAdoptionCount: number;
|
||||
}>> {
|
||||
const result = new Map<string, {
|
||||
personalAdoptionCount: number;
|
||||
teamAddressCount: number;
|
||||
teamAdoptionCount: number;
|
||||
provinceAdoptionCount: number;
|
||||
cityAdoptionCount: number;
|
||||
}>();
|
||||
|
||||
if (accountSequences.length === 0) return result;
|
||||
|
|
@ -571,18 +575,40 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
personalAdoptionCounts.map(p => [p.accountSequence, p._count.id])
|
||||
);
|
||||
|
||||
// 2. 批量获取 userId 用于团队统计
|
||||
// 2. 批量获取用户的省市信息(从认种订单中获取第一个订单的省市)
|
||||
const userProvinceCity = await this.prisma.plantingOrderQueryView.findMany({
|
||||
where: {
|
||||
accountSequence: { in: accountSequences },
|
||||
status: 'MINING_ENABLED',
|
||||
selectedProvince: { not: null },
|
||||
},
|
||||
select: {
|
||||
accountSequence: true,
|
||||
selectedProvince: true,
|
||||
selectedCity: true,
|
||||
},
|
||||
distinct: ['accountSequence'],
|
||||
orderBy: { createdAt: 'asc' },
|
||||
});
|
||||
const userProvinceCityMap = new Map(
|
||||
userProvinceCity.map(u => [u.accountSequence, { province: u.selectedProvince, city: u.selectedCity }])
|
||||
);
|
||||
|
||||
// 3. 批量获取 userId 用于团队统计
|
||||
const referrals = await this.prisma.referralQueryView.findMany({
|
||||
where: { accountSequence: { in: accountSequences } },
|
||||
select: { accountSequence: true, userId: true },
|
||||
});
|
||||
const userIdMap = new Map(referrals.map(r => [r.accountSequence, r.userId]));
|
||||
|
||||
// 3. 对每个用户计算团队统计(这里需要单独查询,因为 PostgreSQL 数组查询不支持批量)
|
||||
// 4. 对每个用户计算团队统计
|
||||
for (const accountSequence of accountSequences) {
|
||||
const userId = userIdMap.get(accountSequence);
|
||||
const userLocation = userProvinceCityMap.get(accountSequence);
|
||||
let teamAddressCount = 0;
|
||||
let teamAdoptionCount = 0;
|
||||
let provinceAdoptionCount = 0;
|
||||
let cityAdoptionCount = 0;
|
||||
|
||||
if (userId) {
|
||||
// 获取团队成员
|
||||
|
|
@ -595,15 +621,41 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
|
||||
teamAddressCount = teamMembers.length;
|
||||
|
||||
// 获取团队认种量
|
||||
// 获取团队认种量及省市统计
|
||||
if (teamMembers.length > 0) {
|
||||
const count = await this.prisma.plantingOrderQueryView.count({
|
||||
const teamAccountSequences = teamMembers.map(m => m.accountSequence);
|
||||
|
||||
// 团队总认种量
|
||||
teamAdoptionCount = await this.prisma.plantingOrderQueryView.count({
|
||||
where: {
|
||||
accountSequence: { in: teamMembers.map(m => m.accountSequence) },
|
||||
accountSequence: { in: teamAccountSequences },
|
||||
status: 'MINING_ENABLED',
|
||||
},
|
||||
});
|
||||
teamAdoptionCount = count;
|
||||
|
||||
// 如果用户有省市信息,统计同省同市的认种量
|
||||
if (userLocation?.province) {
|
||||
// 同省认种量
|
||||
provinceAdoptionCount = await this.prisma.plantingOrderQueryView.count({
|
||||
where: {
|
||||
accountSequence: { in: teamAccountSequences },
|
||||
status: 'MINING_ENABLED',
|
||||
selectedProvince: userLocation.province,
|
||||
},
|
||||
});
|
||||
|
||||
// 同市认种量
|
||||
if (userLocation.city) {
|
||||
cityAdoptionCount = await this.prisma.plantingOrderQueryView.count({
|
||||
where: {
|
||||
accountSequence: { in: teamAccountSequences },
|
||||
status: 'MINING_ENABLED',
|
||||
selectedProvince: userLocation.province,
|
||||
selectedCity: userLocation.city,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -611,6 +663,8 @@ export class UserDetailQueryRepositoryImpl implements IUserDetailQueryRepository
|
|||
personalAdoptionCount: personalAdoptionMap.get(accountSequence) || 0,
|
||||
teamAddressCount,
|
||||
teamAdoptionCount,
|
||||
provinceAdoptionCount,
|
||||
cityAdoptionCount,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue