fix(contribution): backfill 强制重算 unlock status,修复预种用户层级卡在5级的问题

问题根因:直推用户先买预种导致 directReferralAdoptedCount 已累加到正确值(如5),
但 markAsAdopted() 随后被调用时硬编码 level=5/bonus=1,覆盖了正确的解锁状态。
之后 backfill 因 count 未变(5>5=false)永远不触发重算,level 永久卡死。

修复:updateAccountUnlockStatus 改用 setDirectReferralAdoptedCount() 替代
incrementDirectReferralAdoptedCount 循环,无论 count 是否变化都强制调用
updateUnlockStatus() 重算 unlockedLevelDepth 和 unlockedBonusTiers。

同时为 getDirectReferralAdoptedCount 补充注释,说明常规认种和预种均按人头计。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-03 23:16:47 -08:00
parent 728728bee3
commit 8fcfec9b65
2 changed files with 16 additions and 9 deletions

View File

@ -591,13 +591,17 @@ export class BonusClaimService {
expectedLevelDepth: number,
expectedBonusTiers: number,
): Promise<void> {
// 增量更新直推认种数
const previousCount = account.directReferralAdoptedCount;
if (newDirectReferralAdoptedCount > previousCount) {
for (let i = previousCount; i < newDirectReferralAdoptedCount; i++) {
account.incrementDirectReferralAdoptedCount();
}
}
// 使用 setDirectReferralAdoptedCount 无条件重算解锁状态。
//
// 不能用「if (newCount > previousCount) increment」的方式原因
// 当直推已全部认种DB count 已正确)但 markAsAdopted() 在此之后才
// 被调用时markAsAdopted 会硬编码 level=5/bonus=1导致 level 错误,
// 但 count 不变,条件判断永远为 falsebackfill 无法修复。
//
// setDirectReferralAdoptedCount 内部调用 updateUnlockStatus()
// 无论 count 是否变化都会根据 hasAdopted + count 重新计算正确的
// unlockedLevelDepth 和 unlockedBonusTiers。
account.setDirectReferralAdoptedCount(newDirectReferralAdoptedCount);
await this.contributionAccountRepository.save(account);

View File

@ -291,11 +291,14 @@ export class SyncedDataRepository implements ISyncedDataRepository {
const accountSequences = directReferrals.map((r) => r.accountSequence);
// 只统计有 MINING_ENABLED 状态认种记录的直推用户数
// 解锁阈值按「人头」计:常规认种和预种均以「该直推用户是否有任意一条
// MINING_ENABLED 记录」为准,每人算 1不论认种了几棵树或几份预种。
// 预种 handler 会在用户首次付款时向 synced_adoptions 插入一条
// treeCount=0、status=MINING_ENABLED 的 marker确保预种用户也能被计入。
const adoptedCount = await this.client.syncedAdoption.findMany({
where: {
accountSequence: { in: accountSequences },
status: 'MINING_ENABLED', // 只统计最终成功的认种订单
status: 'MINING_ENABLED',
},
distinct: ['accountSequence'],
});