feat(authorization): 提高社区和市团队权益初始激活门槛

社区初始激活门槛: 10棵 → 100棵
市团队初始激活门槛: 100棵 → 500棵

变更说明:
- 仅调整初始激活门槛,月度考核目标不变(社区仍为10棵/月,市团队仍为100棵/月)
- 已激活用户不受影响(祖父条款),仅对新申请的授权生效
- 激活逻辑通过 AssessmentConfig 工厂方法动态获取门槛值,无需修改业务代码
- 数据库已有记录的 initialTargetTreeCount 保持旧值不变

修改文件:
- assessment-config.vo.ts: 核心门槛配置
- authorization-application.service.ts: 同步注释
- authorization-role.aggregate.spec.ts: 同步测试断言
- DEVELOPMENT_GUIDE.md: 同步文档描述

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-25 22:55:22 -08:00
parent eda39b982d
commit eacdfddff8
4 changed files with 25 additions and 25 deletions

View File

@ -53,8 +53,8 @@ Authorization Service 是 RWA 榴莲皇后平台的授权管理微服务,负
- 市公司团队权益40 USDT/棵 - 市公司团队权益40 USDT/棵
初始考核: 初始考核:
- 伞下团队认种总量达到100棵后权益自动生效 - 伞下团队认种总量达到500棵后权益自动生效
- 考核的100棵权益归上级市公司所有无上级则归总部社区账户 - 考核的500棵权益归上级市公司所有无上级则归总部社区账户
``` ```
### 3. 正式省公司授权 ### 3. 正式省公司授权
@ -92,8 +92,8 @@ Authorization Service 是 RWA 榴莲皇后平台的授权管理微服务,负
- 社区权益80 USDT/棵 - 社区权益80 USDT/棵
初始考核: 初始考核:
- 伞下团队认种总量达到10棵后权益自动生效 - 伞下团队认种总量达到100棵后权益自动生效
- 考核的10棵权益归上级社区所有无上级则归总部社区账户 - 考核的100棵权益归上级社区所有(无上级则归总部社区账户)
月度考核: 月度考核:
- 每月需新增10棵 - 每月需新增10棵
@ -1891,7 +1891,7 @@ export class AuthorizationApplicationService {
communityName: command.communityName communityName: command.communityName
}) })
// 3. 检查初始考核10棵 // 3. 检查初始考核100棵)
const teamStats = await this.statsRepository.findByUserId(userId) const teamStats = await this.statsRepository.findByUserId(userId)
const totalTreeCount = teamStats?.totalTeamPlantingCount || 0 const totalTreeCount = teamStats?.totalTeamPlantingCount || 0
@ -2005,7 +2005,7 @@ export class AuthorizationApplicationService {
cityName: command.cityName cityName: command.cityName
}) })
// 3. 检查初始考核(100棵 // 3. 检查初始考核(500棵
const teamStats = await this.statsRepository.findByUserId(userId) const teamStats = await this.statsRepository.findByUserId(userId)
const totalTreeCount = teamStats?.totalTeamPlantingCount || 0 const totalTreeCount = teamStats?.totalTeamPlantingCount || 0

View File

@ -102,7 +102,7 @@ export class AuthorizationApplicationService {
communityName: command.communityName, communityName: command.communityName,
}) })
// 3. 检查初始考核10棵)- 使用下级团队认种数(不含自己) // 3. 检查初始考核100棵)- 使用下级团队认种数(不含自己)
const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence) const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence)
const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0 const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
@ -212,7 +212,7 @@ export class AuthorizationApplicationService {
cityName: command.cityName, cityName: command.cityName,
}) })
// 3. 检查初始考核(100棵- 使用下级团队认种数(不含自己) // 3. 检查初始考核(500棵- 使用下级团队认种数(不含自己)
const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence) const teamStats = await this.statsRepository.findByAccountSequence(userId.accountSequence)
const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0 const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
@ -1175,7 +1175,7 @@ export class AuthorizationApplicationService {
* *
* *
* - * -
* - 10 * - 100
* - * -
* *
* @param accountSequence accountSequence * @param accountSequence accountSequence
@ -1307,7 +1307,7 @@ export class AuthorizationApplicationService {
* *
* *
* - * -
* - 100 * - 500
*/ */
async cascadeDeactivateAuthCityBenefits( async cascadeDeactivateAuthCityBenefits(
accountSequence: string, accountSequence: string,
@ -2064,7 +2064,7 @@ export class AuthorizationApplicationService {
* 1. * 1.
* 2. benefitActive=true * 2. benefitActive=true
* 3. benefitActive=false * 3. benefitActive=false
* - (10) * - (100)
* - * -
* - * -
* 4. * 4.
@ -2179,7 +2179,7 @@ export class AuthorizationApplicationService {
// 注意:如果 referral-service 还没处理完rawSubordinateCount 可能还是旧值, // 注意:如果 referral-service 还没处理完rawSubordinateCount 可能还是旧值,
// 此时 currentTeamCount 可能为负数,需要取 max(0, ...) // 此时 currentTeamCount 可能为负数,需要取 max(0, ...)
const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount) const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
const initialTarget = nearestCommunity.getInitialTarget() // 社区初始考核目标10 const initialTarget = nearestCommunity.getInitialTarget() // 社区初始考核目标100
this.logger.debug( this.logger.debug(
`[getCommunityRewardDistribution] Community ${nearestCommunity.userId.accountSequence} ` + `[getCommunityRewardDistribution] Community ${nearestCommunity.userId.accountSequence} ` +
@ -2229,8 +2229,8 @@ export class AuthorizationApplicationService {
} else { } else {
// 未达标,需要拆分 // 未达标,需要拆分
// toReachTarget: 还差多少棵达到考核目标(包括达标那一棵) // toReachTarget: 还差多少棵达到考核目标(包括达标那一棵)
// 业务规则第1-10棵全部给上级的上级/总部第11棵开始才给该社区 // 业务规则第1-100棵全部给上级的上级/总部第101棵开始才给该社区
// 例如目标10当前2棵 -> toReachTarget = 8第3-10棵给上级第11棵开始给自己 // 例如目标100棵当前20棵 -> toReachTarget = 80第21-100棵给上级第101棵开始给自己
const toReachTarget = Math.max(0, initialTarget - currentTeamCount) const toReachTarget = Math.max(0, initialTarget - currentTeamCount)
const afterPlantingCount = currentTeamCount + treeCount // 本次认种后的总数 const afterPlantingCount = currentTeamCount + treeCount // 本次认种后的总数
@ -2248,7 +2248,7 @@ export class AuthorizationApplicationService {
} }
} else { } else {
// 本次认种跨越考核达标点 (afterPlantingCount > initialTarget) // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
// 达标前的部分包括第10棵)给上级/总部 // 达标前的部分包括第100棵)给上级/总部
if (toReachTarget > 0) { if (toReachTarget > 0) {
distributions.push({ distributions.push({
accountSequence: parentCommunityAccountSequence, accountSequence: parentCommunityAccountSequence,
@ -2256,7 +2256,7 @@ export class AuthorizationApplicationService {
reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})${parentCommunityReason}`, reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})${parentCommunityReason}`,
}) })
} }
// 超过达标点的部分第11棵开始给该社区 // 超过达标点的部分第101棵开始给该社区
const afterTargetCount = treeCount - toReachTarget const afterTargetCount = treeCount - toReachTarget
if (afterTargetCount > 0) { if (afterTargetCount > 0) {
distributions.push({ distributions.push({
@ -2635,7 +2635,7 @@ export class AuthorizationApplicationService {
* 1. AUTH_CITY_COMPANY * 1. AUTH_CITY_COMPANY
* 2. benefitActive=true * 2. benefitActive=true
* 3. benefitActive=false * 3. benefitActive=false
* - (100) * - (500)
* - / * - /
* - * -
* 4. * 4.
@ -2726,7 +2726,7 @@ export class AuthorizationApplicationService {
const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0 const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0
// 修复竞态条件:减去本次认种数量来还原"认种前"的下级团队数 // 修复竞态条件:减去本次认种数量来还原"认种前"的下级团队数
const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount) const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
const initialTarget = nearestAuthCity.getInitialTarget() // 100棵 const initialTarget = nearestAuthCity.getInitialTarget() // 500棵
this.logger.debug( this.logger.debug(
`[getCityTeamRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`, `[getCityTeamRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}`,
@ -2786,7 +2786,7 @@ export class AuthorizationApplicationService {
} }
} else { } else {
// 本次认种跨越考核达标点 (afterPlantingCount > initialTarget) // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget)
// 达标前的部分(包括第100棵给上级/总部 // 达标前的部分(包括第500棵给上级/总部
if (toReachTarget > 0) { if (toReachTarget > 0) {
distributions.push({ distributions.push({
accountSequence: parentAccountSequence, accountSequence: parentAccountSequence,
@ -2794,7 +2794,7 @@ export class AuthorizationApplicationService {
reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})${parentReason}`, reason: `初始考核(${currentTeamCount}+${toReachTarget}=${initialTarget}/${initialTarget})${parentReason}`,
}) })
} }
// 超过达标点的部分(第101棵开始给该市团队 // 超过达标点的部分(第501棵开始给该市团队
const afterTargetCount = treeCount - toReachTarget const afterTargetCount = treeCount - toReachTarget
if (afterTargetCount > 0) { if (afterTargetCount > 0) {
distributions.push({ distributions.push({
@ -3467,7 +3467,7 @@ export class AuthorizationApplicationService {
cityName: command.cityName!, cityName: command.cityName!,
}) })
// 检查初始考核(100棵 // 检查初始考核(500棵
const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence) const teamStats = await this.statsRepository.findByAccountSequence(command.accountSequence)
const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0 const subordinateTreeCount = teamStats?.subordinateTeamPlantingCount || 0
if (subordinateTreeCount >= authorization.getInitialTarget()) { if (subordinateTreeCount >= authorization.getInitialTarget()) {

View File

@ -15,7 +15,7 @@ describe('AuthorizationRole Aggregate', () => {
expect(auth.status).toBe(AuthorizationStatus.PENDING) expect(auth.status).toBe(AuthorizationStatus.PENDING)
expect(auth.displayTitle).toBe('量子社区') expect(auth.displayTitle).toBe('量子社区')
expect(auth.benefitActive).toBe(false) expect(auth.benefitActive).toBe(false)
expect(auth.getInitialTarget()).toBe(10) expect(auth.getInitialTarget()).toBe(100)
expect(auth.domainEvents.length).toBe(1) expect(auth.domainEvents.length).toBe(1)
expect(auth.domainEvents[0].eventType).toBe('authorization.community.requested') expect(auth.domainEvents[0].eventType).toBe('authorization.community.requested')
}) })
@ -51,7 +51,7 @@ describe('AuthorizationRole Aggregate', () => {
expect(auth.status).toBe(AuthorizationStatus.PENDING) expect(auth.status).toBe(AuthorizationStatus.PENDING)
expect(auth.displayTitle).toBe('授权长沙市') expect(auth.displayTitle).toBe('授权长沙市')
expect(auth.benefitActive).toBe(false) expect(auth.benefitActive).toBe(false)
expect(auth.getInitialTarget()).toBe(100) expect(auth.getInitialTarget()).toBe(500)
}) })
}) })

View File

@ -7,7 +7,7 @@ export class AssessmentConfig {
) {} ) {}
static forCommunity(): AssessmentConfig { static forCommunity(): AssessmentConfig {
return new AssessmentConfig(10, MonthlyTargetType.FIXED) return new AssessmentConfig(100, MonthlyTargetType.FIXED)
} }
static forAuthProvince(): AssessmentConfig { static forAuthProvince(): AssessmentConfig {
@ -19,7 +19,7 @@ export class AssessmentConfig {
} }
static forAuthCity(): AssessmentConfig { static forAuthCity(): AssessmentConfig {
return new AssessmentConfig(100, MonthlyTargetType.LADDER) return new AssessmentConfig(500, MonthlyTargetType.LADDER)
} }
static forCity(): AssessmentConfig { static forCity(): AssessmentConfig {