feat(authorization): add assessment rules for province/city area roles
- Province area (PROVINCE_COMPANY): 50,000 trees initial target - City area (CITY_COMPANY): 10,000 trees initial target - Apply consistent assessment logic: pre-target rewards go to system account, post-target rewards go to company - Auto-activate benefit when target is reached 🤖 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
905725fc2d
commit
4bf4efb1f4
|
|
@ -1259,7 +1259,11 @@ export class AuthorizationApplicationService {
|
|||
* 规则:
|
||||
* 1. 查找该省份是否有正式省公司(PROVINCE_COMPANY)
|
||||
* 2. 如果有且 benefitActive=true,权益进该省公司自己的账户
|
||||
* 3. 如果没有或 benefitActive=false,权益进系统省账户
|
||||
* 3. 如果有但 benefitActive=false(考核中):
|
||||
* - 计算还需要多少棵才能达到初始考核(5万棵)
|
||||
* - 考核前的部分进系统省账户
|
||||
* - 考核后的部分给该省公司
|
||||
* 4. 如果没有正式省公司,全部进系统省账户
|
||||
*/
|
||||
async getProvinceAreaRewardDistribution(
|
||||
provinceCode: string,
|
||||
|
|
@ -1282,7 +1286,21 @@ export class AuthorizationApplicationService {
|
|||
// 查找该省份的正式省公司
|
||||
const provinceCompany = await this.authorizationRepository.findProvinceCompanyByRegion(provinceCode)
|
||||
|
||||
if (provinceCompany && provinceCompany.benefitActive) {
|
||||
if (!provinceCompany) {
|
||||
// 无正式省公司,全部进系统省账户
|
||||
return {
|
||||
distributions: [
|
||||
{
|
||||
accountSequence: systemProvinceAccountId,
|
||||
treeCount,
|
||||
reason: '无正式省公司授权,进系统省账户',
|
||||
isSystemAccount: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
if (provinceCompany.benefitActive) {
|
||||
// 正式省公司权益已激活,进该省公司账户
|
||||
return {
|
||||
distributions: [
|
||||
|
|
@ -1296,21 +1314,79 @@ export class AuthorizationApplicationService {
|
|||
}
|
||||
}
|
||||
|
||||
// 无正式省公司或权益未激活,进系统省账户
|
||||
const reason = provinceCompany
|
||||
? `省区域权益未激活(考核中),进系统省账户`
|
||||
: '无正式省公司授权,进系统省账户'
|
||||
// 权益未激活,计算考核分配 - 使用下级团队认种数(不含自己)
|
||||
const stats = await this.statsRepository.findByAccountSequence(provinceCompany.userId.accountSequence)
|
||||
const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0
|
||||
// 修复竞态条件:减去本次认种数量来还原"认种前"的下级团队数
|
||||
const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
|
||||
const initialTarget = provinceCompany.getInitialTarget() // 5万棵
|
||||
|
||||
return {
|
||||
distributions: [
|
||||
{
|
||||
this.logger.debug(
|
||||
`[getProvinceAreaRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}, initialTarget=${initialTarget}`,
|
||||
)
|
||||
|
||||
const distributions: Array<{
|
||||
accountSequence: number
|
||||
treeCount: number
|
||||
reason: string
|
||||
isSystemAccount: boolean
|
||||
}> = []
|
||||
|
||||
if (currentTeamCount >= initialTarget) {
|
||||
// 已达标但权益未激活,全部给该省公司
|
||||
distributions.push({
|
||||
accountSequence: Number(provinceCompany.userId.accountSequence),
|
||||
treeCount,
|
||||
reason: '已达初始考核目标',
|
||||
isSystemAccount: false,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(provinceCompany)
|
||||
} else {
|
||||
const remaining = initialTarget - currentTeamCount
|
||||
const afterPlantingCount = currentTeamCount + treeCount
|
||||
|
||||
if (afterPlantingCount < initialTarget) {
|
||||
// 本次认种后仍未达标,全部进系统省账户
|
||||
distributions.push({
|
||||
accountSequence: systemProvinceAccountId,
|
||||
treeCount,
|
||||
reason,
|
||||
reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget}),进系统省账户`,
|
||||
isSystemAccount: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (afterPlantingCount === initialTarget) {
|
||||
// 本次认种恰好达标,全部进系统省账户,但需要激活权益
|
||||
distributions.push({
|
||||
accountSequence: systemProvinceAccountId,
|
||||
treeCount,
|
||||
reason: `初始考核达标(${currentTeamCount}+${treeCount}=${initialTarget}),进系统省账户`,
|
||||
isSystemAccount: true,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(provinceCompany)
|
||||
} else {
|
||||
// 本次认种跨越考核达标点
|
||||
// 考核前的部分进系统省账户
|
||||
distributions.push({
|
||||
accountSequence: systemProvinceAccountId,
|
||||
treeCount: remaining,
|
||||
reason: `初始考核(${currentTeamCount}+${remaining}=${initialTarget}),进系统省账户`,
|
||||
isSystemAccount: true,
|
||||
})
|
||||
// 考核后的部分给该省公司
|
||||
distributions.push({
|
||||
accountSequence: Number(provinceCompany.userId.accountSequence),
|
||||
treeCount: treeCount - remaining,
|
||||
reason: '考核达标后权益生效',
|
||||
isSystemAccount: false,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(provinceCompany)
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug(`[getProvinceAreaRewardDistribution] Result: ${JSON.stringify(distributions)}`)
|
||||
return { distributions }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1485,7 +1561,11 @@ export class AuthorizationApplicationService {
|
|||
* 规则:
|
||||
* 1. 查找该城市是否有正式市公司(CITY_COMPANY)
|
||||
* 2. 如果有且 benefitActive=true,权益进该市公司自己的账户
|
||||
* 3. 如果没有或 benefitActive=false,权益进系统市账户
|
||||
* 3. 如果有但 benefitActive=false(考核中):
|
||||
* - 计算还需要多少棵才能达到初始考核(1万棵)
|
||||
* - 考核前的部分进系统市账户
|
||||
* - 考核后的部分给该市公司
|
||||
* 4. 如果没有正式市公司,全部进系统市账户
|
||||
*/
|
||||
async getCityAreaRewardDistribution(
|
||||
cityCode: string,
|
||||
|
|
@ -1508,7 +1588,21 @@ export class AuthorizationApplicationService {
|
|||
// 查找该城市的正式市公司
|
||||
const cityCompany = await this.authorizationRepository.findCityCompanyByRegion(cityCode)
|
||||
|
||||
if (cityCompany && cityCompany.benefitActive) {
|
||||
if (!cityCompany) {
|
||||
// 无正式市公司,全部进系统市账户
|
||||
return {
|
||||
distributions: [
|
||||
{
|
||||
accountSequence: systemCityAccountId,
|
||||
treeCount,
|
||||
reason: '无正式市公司授权,进系统市账户',
|
||||
isSystemAccount: true,
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
if (cityCompany.benefitActive) {
|
||||
// 正式市公司权益已激活,进该市公司账户
|
||||
return {
|
||||
distributions: [
|
||||
|
|
@ -1522,20 +1616,78 @@ export class AuthorizationApplicationService {
|
|||
}
|
||||
}
|
||||
|
||||
// 无正式市公司或权益未激活,进系统市账户
|
||||
const reason = cityCompany
|
||||
? `市区域权益未激活(考核中),进系统市账户`
|
||||
: '无正式市公司授权,进系统市账户'
|
||||
// 权益未激活,计算考核分配 - 使用下级团队认种数(不含自己)
|
||||
const stats = await this.statsRepository.findByAccountSequence(cityCompany.userId.accountSequence)
|
||||
const rawSubordinateCount = stats?.subordinateTeamPlantingCount ?? 0
|
||||
// 修复竞态条件:减去本次认种数量来还原"认种前"的下级团队数
|
||||
const currentTeamCount = Math.max(0, rawSubordinateCount - treeCount)
|
||||
const initialTarget = cityCompany.getInitialTarget() // 1万棵
|
||||
|
||||
return {
|
||||
distributions: [
|
||||
{
|
||||
this.logger.debug(
|
||||
`[getCityAreaRewardDistribution] rawSubordinateCount=${rawSubordinateCount}, treeCount=${treeCount}, currentTeamCount(before)=${currentTeamCount}, initialTarget=${initialTarget}`,
|
||||
)
|
||||
|
||||
const distributions: Array<{
|
||||
accountSequence: number
|
||||
treeCount: number
|
||||
reason: string
|
||||
isSystemAccount: boolean
|
||||
}> = []
|
||||
|
||||
if (currentTeamCount >= initialTarget) {
|
||||
// 已达标但权益未激活,全部给该市公司
|
||||
distributions.push({
|
||||
accountSequence: Number(cityCompany.userId.accountSequence),
|
||||
treeCount,
|
||||
reason: '已达初始考核目标',
|
||||
isSystemAccount: false,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(cityCompany)
|
||||
} else {
|
||||
const remaining = initialTarget - currentTeamCount
|
||||
const afterPlantingCount = currentTeamCount + treeCount
|
||||
|
||||
if (afterPlantingCount < initialTarget) {
|
||||
// 本次认种后仍未达标,全部进系统市账户
|
||||
distributions.push({
|
||||
accountSequence: systemCityAccountId,
|
||||
treeCount,
|
||||
reason,
|
||||
reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget}),进系统市账户`,
|
||||
isSystemAccount: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
} else if (afterPlantingCount === initialTarget) {
|
||||
// 本次认种恰好达标,全部进系统市账户,但需要激活权益
|
||||
distributions.push({
|
||||
accountSequence: systemCityAccountId,
|
||||
treeCount,
|
||||
reason: `初始考核达标(${currentTeamCount}+${treeCount}=${initialTarget}),进系统市账户`,
|
||||
isSystemAccount: true,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(cityCompany)
|
||||
} else {
|
||||
// 本次认种跨越考核达标点
|
||||
// 考核前的部分进系统市账户
|
||||
distributions.push({
|
||||
accountSequence: systemCityAccountId,
|
||||
treeCount: remaining,
|
||||
reason: `初始考核(${currentTeamCount}+${remaining}=${initialTarget}),进系统市账户`,
|
||||
isSystemAccount: true,
|
||||
})
|
||||
// 考核后的部分给该市公司
|
||||
distributions.push({
|
||||
accountSequence: Number(cityCompany.userId.accountSequence),
|
||||
treeCount: treeCount - remaining,
|
||||
reason: '考核达标后权益生效',
|
||||
isSystemAccount: false,
|
||||
})
|
||||
// 自动激活权益
|
||||
await this.tryActivateBenefit(cityCompany)
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.debug(`[getCityAreaRewardDistribution] Result: ${JSON.stringify(distributions)}`)
|
||||
return { distributions }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export class AssessmentConfig {
|
|||
}
|
||||
|
||||
static forProvince(): AssessmentConfig {
|
||||
return new AssessmentConfig(0, MonthlyTargetType.NONE)
|
||||
return new AssessmentConfig(50000, MonthlyTargetType.LADDER) // 省区域:5万棵
|
||||
}
|
||||
|
||||
static forAuthCity(): AssessmentConfig {
|
||||
|
|
@ -23,6 +23,6 @@ export class AssessmentConfig {
|
|||
}
|
||||
|
||||
static forCity(): AssessmentConfig {
|
||||
return new AssessmentConfig(0, MonthlyTargetType.NONE)
|
||||
return new AssessmentConfig(10000, MonthlyTargetType.LADDER) // 市区域:1万棵
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue