diff --git a/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts b/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts index a7121846..52551790 100644 --- a/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts +++ b/backend/services/contribution-service/src/application/services/contribution-calculation.service.ts @@ -61,12 +61,15 @@ export class ContributionCalculationService { ancestorChain = await this.buildAncestorChain(userReferral.referrerAccountSequence); } - // 获取上线的算力账户(用于判断解锁状态) + // 获取认种人的算力账户(用于判断 TEAM_BONUS 解锁状态) + const adopterAccount = await this.contributionAccountRepository.findByAccountSequence(adoption.accountSequence); + + // 获取上线的算力账户(用于判断 TEAM_LEVEL 解锁状态) const ancestorAccountSequences = ancestorChain.map((a) => a.accountSequence); const ancestorAccounts = await this.contributionAccountRepository.findByAccountSequences(ancestorAccountSequences); // 执行算力计算 - const result = this.domainCalculator.calculateAdoptionContribution(adoption, ancestorChain, ancestorAccounts); + const result = this.domainCalculator.calculateAdoptionContribution(adoption, adopterAccount, ancestorChain, ancestorAccounts); // 在事务中保存所有结果 await this.unitOfWork.executeInTransaction(async () => { diff --git a/backend/services/contribution-service/src/domain/services/contribution-calculator.service.ts b/backend/services/contribution-service/src/domain/services/contribution-calculator.service.ts index 4efa9384..01065d81 100644 --- a/backend/services/contribution-service/src/domain/services/contribution-calculator.service.ts +++ b/backend/services/contribution-service/src/domain/services/contribution-calculator.service.ts @@ -15,7 +15,7 @@ export interface ContributionDistributionResult { // 团队层级贡献值记录(给上线们的) teamLevelRecords: ContributionRecordAggregate[]; - // 团队额外奖励贡献值记录(给直接上线的) + // 团队额外奖励贡献值记录(给认种人自己的) teamBonusRecords: ContributionRecordAggregate[]; // 未分配的贡献值(归总部) @@ -47,12 +47,14 @@ export class ContributionCalculatorService { * 计算认种产生的贡献值分配 * * @param adoption 认种记录 + * @param adopterAccount 认种人的算力账户(用于判断 TEAM_BONUS 解锁状态) * @param ancestorChain 上线链条(从直接上线开始,最多15级) - * @param ancestorAccounts 上线的算力账户(用于判断解锁状态) + * @param ancestorAccounts 上线的算力账户(用于判断 TEAM_LEVEL 解锁状态) * @returns 分配结果 */ calculateAdoptionContribution( adoption: SyncedAdoption, + adopterAccount: ContributionAccountAggregate | null, ancestorChain: SyncedReferral[], ancestorAccounts: Map, ): ContributionDistributionResult { @@ -104,6 +106,7 @@ export class ContributionCalculatorService { // 3. 团队贡献值 (15%) this.distributeTeamContribution( adoption, + adopterAccount, baseContribution, treeCount, ancestorChain, @@ -121,6 +124,7 @@ export class ContributionCalculatorService { */ private distributeTeamContribution( adoption: SyncedAdoption, + adopterAccount: ContributionAccountAggregate | null, baseContribution: ContributionAmount, treeCount: number, ancestorChain: SyncedReferral[], @@ -176,49 +180,41 @@ export class ContributionCalculatorService { } } - // 3.2 额外奖励部分 (7.5% = 2.5% × 3档) - 只给直接上线 - if (ancestorChain.length > 0) { - const directReferrer = ancestorChain[0]; - const directReferrerAccount = ancestorAccounts.get(directReferrer.accountSequence); - const unlockedBonusTiers = directReferrerAccount?.unlockedBonusTiers ?? 0; + // 3.2 额外奖励部分 (7.5% = 2.5% × 3档) - 给认种人自己 + // T1: 自己认种即解锁(无条件,当前正在认种所以一定解锁) + // T2: 直推≥2人认种解锁 + // T3: 直推≥4人认种解锁 + const directReferralAdoptedCount = adopterAccount?.directReferralAdoptedCount ?? 0; - for (let tier = 1; tier <= 3; tier++) { - if (unlockedBonusTiers >= tier) { - // 上线已解锁该档位 - result.teamBonusRecords.push( - ContributionRecordAggregate.createTeamBonus({ - accountSequence: directReferrer.accountSequence, - sourceAdoptionId: adoption.originalAdoptionId, - sourceAccountSequence: adoption.accountSequence, - treeCount, - baseContribution, - bonusTier: tier, - effectiveDate, - expireDate, - }), - ); - } else { - // 上线未解锁该档位,归总部 - const bonusAmount = baseContribution.multiply(treeCount).multiply(DistributionRate.BONUS_PER.value); - result.unallocatedContributions.push({ - type: `BONUS_TIER_${tier}`, - wouldBeAccountSequence: directReferrer.accountSequence, - levelDepth: null, - amount: bonusAmount, - reason: `上线${directReferrer.accountSequence}未解锁第${tier}档奖励(已解锁${unlockedBonusTiers}档)`, - }); - } - } - } else { - // 没有上线,三个2.5%全部归总部 - for (let tier = 1; tier <= 3; tier++) { + // T1 始终解锁(因为当前正在认种) + // T2 需要直推≥2人认种 + // T3 需要直推≥4人认种 + const effectiveUnlockedBonusTiers = this.calculateUnlockedBonusTiers(true, directReferralAdoptedCount); + + for (let tier = 1; tier <= 3; tier++) { + if (effectiveUnlockedBonusTiers >= tier) { + // 认种人已解锁该档位,给认种人自己 + result.teamBonusRecords.push( + ContributionRecordAggregate.createTeamBonus({ + accountSequence: adoption.accountSequence, + sourceAdoptionId: adoption.originalAdoptionId, + sourceAccountSequence: adoption.accountSequence, + treeCount, + baseContribution, + bonusTier: tier, + effectiveDate, + expireDate, + }), + ); + } else { + // 认种人未解锁该档位,归总部(冻结/待领取) const bonusAmount = baseContribution.multiply(treeCount).multiply(DistributionRate.BONUS_PER.value); result.unallocatedContributions.push({ type: `BONUS_TIER_${tier}`, - wouldBeAccountSequence: null, + wouldBeAccountSequence: adoption.accountSequence, levelDepth: null, amount: bonusAmount, - reason: `认种人无上线`, + reason: `认种人${adoption.accountSequence}未解锁第${tier}档奖励(需直推${tier === 2 ? '2人' : '4人'}认种)`, }); } } diff --git a/backend/services/contribution-service/src/infrastructure/persistence/repositories/synced-data.repository.ts b/backend/services/contribution-service/src/infrastructure/persistence/repositories/synced-data.repository.ts index a098cf65..e7ac6e48 100644 --- a/backend/services/contribution-service/src/infrastructure/persistence/repositories/synced-data.repository.ts +++ b/backend/services/contribution-service/src/infrastructure/persistence/repositories/synced-data.repository.ts @@ -247,18 +247,22 @@ export class SyncedDataRepository implements ISyncedDataRepository { let currentSequence = accountSequence; for (let i = 0; i < maxLevel; i++) { + // 获取当前账户的 referral 记录(包含该账户作为上线的信息) const referral = await this.findSyncedReferralByAccountSequence(currentSequence); - if (!referral || !referral.referrerAccountSequence) { + if (!referral) { break; } - const referrer = await this.findSyncedReferralByAccountSequence(referral.referrerAccountSequence); - if (!referrer) { + // 把当前账户加入上线链条 + ancestors.push(referral); + + // 如果没有更上级的推荐人,终止 + if (!referral.referrerAccountSequence) { break; } - ancestors.push(referrer); - currentSequence = referrer.accountSequence; + // 继续向上追溯 + currentSequence = referral.referrerAccountSequence; } return ancestors;