import Decimal from 'decimal.js'; import { ContributionAmount } from '../value-objects/contribution-amount.vo'; /** * 贡献值来源类型 */ export enum ContributionSourceType { PERSONAL = 'PERSONAL', // 来自自己认种 TEAM_LEVEL = 'TEAM_LEVEL', // 来自团队层级 (1-15级) TEAM_BONUS = 'TEAM_BONUS', // 来自团队加成奖励 (3档) // ========== 转让相关(纯新增)========== // 卖方转出(负数金额) TRANSFER_OUT_PERSONAL = 'TRANSFER_OUT_PERSONAL', // 卖方个人算力转出 TRANSFER_OUT_TEAM_LEVEL = 'TRANSFER_OUT_TEAM_LEVEL', // 卖方上线团队层级算力转出 TRANSFER_OUT_BONUS = 'TRANSFER_OUT_BONUS', // 卖方个人加成算力转出 // 买方转入(正数金额) TRANSFER_IN_PERSONAL = 'TRANSFER_IN_PERSONAL', // 买方个人算力转入 TRANSFER_IN_TEAM_LEVEL = 'TRANSFER_IN_TEAM_LEVEL', // 买方上线团队层级算力转入 TRANSFER_IN_BONUS = 'TRANSFER_IN_BONUS', // 买方个人加成算力转入 } /** * 算力账户聚合根 * 管理用户的贡献值/算力 * * 设计说明: * - 个人算力:自己认种,立即生效 * - 层级算力:下级1-15层认种的分成,每层0.5%,共7.5% * - 加成算力:团队加成,3档各2.5%,共7.5% * * 解锁规则: * - 自己认种:解锁层级1-5 + 加成第1档 * - 直推≥2人认种:解锁加成第2档 * - 直推≥3人认种:解锁层级6-10 * - 直推≥4人认种:解锁加成第3档 * - 直推≥5人认种:解锁层级11-15 */ export class ContributionAccountAggregate { private _id: bigint | null; private _accountSequence: string; // ========== 个人算力(立即生效)========== private _personalContribution: ContributionAmount; // ========== 15级层级待解锁算力 ========== private _level1Pending: ContributionAmount; private _level2Pending: ContributionAmount; private _level3Pending: ContributionAmount; private _level4Pending: ContributionAmount; private _level5Pending: ContributionAmount; private _level6Pending: ContributionAmount; private _level7Pending: ContributionAmount; private _level8Pending: ContributionAmount; private _level9Pending: ContributionAmount; private _level10Pending: ContributionAmount; private _level11Pending: ContributionAmount; private _level12Pending: ContributionAmount; private _level13Pending: ContributionAmount; private _level14Pending: ContributionAmount; private _level15Pending: ContributionAmount; // ========== 3档加成待解锁算力 ========== private _bonusTier1Pending: ContributionAmount; private _bonusTier2Pending: ContributionAmount; private _bonusTier3Pending: ContributionAmount; // ========== 汇总字段 ========== private _totalLevelPending: ContributionAmount; private _totalBonusPending: ContributionAmount; private _totalPending: ContributionAmount; private _totalUnlocked: ContributionAmount; private _effectiveContribution: ContributionAmount; // ========== 解锁条件状态 ========== private _hasAdopted: boolean; private _directReferralAdoptedCount: number; private _unlockedLevelDepth: number; // 0, 5, 10, 15 private _unlockedBonusTiers: number; // 0, 1, 2, 3 private _version: number; private _createdAt: Date; private _updatedAt: Date; constructor(props: { id?: bigint | null; accountSequence: string; personalContribution?: ContributionAmount; level1Pending?: ContributionAmount; level2Pending?: ContributionAmount; level3Pending?: ContributionAmount; level4Pending?: ContributionAmount; level5Pending?: ContributionAmount; level6Pending?: ContributionAmount; level7Pending?: ContributionAmount; level8Pending?: ContributionAmount; level9Pending?: ContributionAmount; level10Pending?: ContributionAmount; level11Pending?: ContributionAmount; level12Pending?: ContributionAmount; level13Pending?: ContributionAmount; level14Pending?: ContributionAmount; level15Pending?: ContributionAmount; bonusTier1Pending?: ContributionAmount; bonusTier2Pending?: ContributionAmount; bonusTier3Pending?: ContributionAmount; totalLevelPending?: ContributionAmount; totalBonusPending?: ContributionAmount; totalPending?: ContributionAmount; totalUnlocked?: ContributionAmount; effectiveContribution?: ContributionAmount; hasAdopted?: boolean; directReferralAdoptedCount?: number; unlockedLevelDepth?: number; unlockedBonusTiers?: number; version?: number; createdAt?: Date; updatedAt?: Date; }) { this._id = props.id ?? null; this._accountSequence = props.accountSequence; this._personalContribution = props.personalContribution ?? ContributionAmount.zero(); // 15级待解锁 this._level1Pending = props.level1Pending ?? ContributionAmount.zero(); this._level2Pending = props.level2Pending ?? ContributionAmount.zero(); this._level3Pending = props.level3Pending ?? ContributionAmount.zero(); this._level4Pending = props.level4Pending ?? ContributionAmount.zero(); this._level5Pending = props.level5Pending ?? ContributionAmount.zero(); this._level6Pending = props.level6Pending ?? ContributionAmount.zero(); this._level7Pending = props.level7Pending ?? ContributionAmount.zero(); this._level8Pending = props.level8Pending ?? ContributionAmount.zero(); this._level9Pending = props.level9Pending ?? ContributionAmount.zero(); this._level10Pending = props.level10Pending ?? ContributionAmount.zero(); this._level11Pending = props.level11Pending ?? ContributionAmount.zero(); this._level12Pending = props.level12Pending ?? ContributionAmount.zero(); this._level13Pending = props.level13Pending ?? ContributionAmount.zero(); this._level14Pending = props.level14Pending ?? ContributionAmount.zero(); this._level15Pending = props.level15Pending ?? ContributionAmount.zero(); // 3档加成待解锁 this._bonusTier1Pending = props.bonusTier1Pending ?? ContributionAmount.zero(); this._bonusTier2Pending = props.bonusTier2Pending ?? ContributionAmount.zero(); this._bonusTier3Pending = props.bonusTier3Pending ?? ContributionAmount.zero(); // 汇总字段 this._totalLevelPending = props.totalLevelPending ?? ContributionAmount.zero(); this._totalBonusPending = props.totalBonusPending ?? ContributionAmount.zero(); this._totalPending = props.totalPending ?? ContributionAmount.zero(); this._totalUnlocked = props.totalUnlocked ?? ContributionAmount.zero(); this._effectiveContribution = props.effectiveContribution ?? ContributionAmount.zero(); this._hasAdopted = props.hasAdopted ?? false; this._directReferralAdoptedCount = props.directReferralAdoptedCount ?? 0; this._unlockedLevelDepth = props.unlockedLevelDepth ?? 0; this._unlockedBonusTiers = props.unlockedBonusTiers ?? 0; this._version = props.version ?? 1; this._createdAt = props.createdAt ?? new Date(); this._updatedAt = props.updatedAt ?? new Date(); } // Getters get id(): bigint | null { return this._id; } get accountSequence(): string { return this._accountSequence; } get personalContribution(): ContributionAmount { return this._personalContribution; } // 15级待解锁 get level1Pending(): ContributionAmount { return this._level1Pending; } get level2Pending(): ContributionAmount { return this._level2Pending; } get level3Pending(): ContributionAmount { return this._level3Pending; } get level4Pending(): ContributionAmount { return this._level4Pending; } get level5Pending(): ContributionAmount { return this._level5Pending; } get level6Pending(): ContributionAmount { return this._level6Pending; } get level7Pending(): ContributionAmount { return this._level7Pending; } get level8Pending(): ContributionAmount { return this._level8Pending; } get level9Pending(): ContributionAmount { return this._level9Pending; } get level10Pending(): ContributionAmount { return this._level10Pending; } get level11Pending(): ContributionAmount { return this._level11Pending; } get level12Pending(): ContributionAmount { return this._level12Pending; } get level13Pending(): ContributionAmount { return this._level13Pending; } get level14Pending(): ContributionAmount { return this._level14Pending; } get level15Pending(): ContributionAmount { return this._level15Pending; } // 3档加成待解锁 get bonusTier1Pending(): ContributionAmount { return this._bonusTier1Pending; } get bonusTier2Pending(): ContributionAmount { return this._bonusTier2Pending; } get bonusTier3Pending(): ContributionAmount { return this._bonusTier3Pending; } // 汇总 get totalLevelPending(): ContributionAmount { return this._totalLevelPending; } get totalBonusPending(): ContributionAmount { return this._totalBonusPending; } get totalPending(): ContributionAmount { return this._totalPending; } get totalUnlocked(): ContributionAmount { return this._totalUnlocked; } get effectiveContribution(): ContributionAmount { return this._effectiveContribution; } get hasAdopted(): boolean { return this._hasAdopted; } get directReferralAdoptedCount(): number { return this._directReferralAdoptedCount; } get unlockedLevelDepth(): number { return this._unlockedLevelDepth; } get unlockedBonusTiers(): number { return this._unlockedBonusTiers; } get version(): number { return this._version; } get createdAt(): Date { return this._createdAt; } get updatedAt(): Date { return this._updatedAt; } /** * 添加个人贡献值(立即生效) */ addPersonalContribution(amount: ContributionAmount): void { this._personalContribution = this._personalContribution.add(amount); this._effectiveContribution = this._effectiveContribution.add(amount); this._updatedAt = new Date(); } /** * 添加层级待解锁贡献值 * @param levelDepth 层级深度 1-15 * @param amount 贡献值金额 */ addLevelPendingContribution(levelDepth: number, amount: ContributionAmount): void { if (levelDepth < 1 || levelDepth > 15) { throw new Error(`Invalid level depth: ${levelDepth}, must be 1-15`); } const levelPendingMap: Record = { 1: this._level1Pending, 2: this._level2Pending, 3: this._level3Pending, 4: this._level4Pending, 5: this._level5Pending, 6: this._level6Pending, 7: this._level7Pending, 8: this._level8Pending, 9: this._level9Pending, 10: this._level10Pending, 11: this._level11Pending, 12: this._level12Pending, 13: this._level13Pending, 14: this._level14Pending, 15: this._level15Pending, }; // 更新对应层级的待解锁金额 switch (levelDepth) { case 1: this._level1Pending = this._level1Pending.add(amount); break; case 2: this._level2Pending = this._level2Pending.add(amount); break; case 3: this._level3Pending = this._level3Pending.add(amount); break; case 4: this._level4Pending = this._level4Pending.add(amount); break; case 5: this._level5Pending = this._level5Pending.add(amount); break; case 6: this._level6Pending = this._level6Pending.add(amount); break; case 7: this._level7Pending = this._level7Pending.add(amount); break; case 8: this._level8Pending = this._level8Pending.add(amount); break; case 9: this._level9Pending = this._level9Pending.add(amount); break; case 10: this._level10Pending = this._level10Pending.add(amount); break; case 11: this._level11Pending = this._level11Pending.add(amount); break; case 12: this._level12Pending = this._level12Pending.add(amount); break; case 13: this._level13Pending = this._level13Pending.add(amount); break; case 14: this._level14Pending = this._level14Pending.add(amount); break; case 15: this._level15Pending = this._level15Pending.add(amount); break; } this._totalLevelPending = this._totalLevelPending.add(amount); this._totalPending = this._totalPending.add(amount); this._updatedAt = new Date(); } /** * 添加加成待解锁贡献值 * @param tier 加成档位 1-3 * @param amount 贡献值金额 */ addBonusTierPendingContribution(tier: number, amount: ContributionAmount): void { if (tier < 1 || tier > 3) { throw new Error(`Invalid bonus tier: ${tier}, must be 1-3`); } switch (tier) { case 1: this._bonusTier1Pending = this._bonusTier1Pending.add(amount); break; case 2: this._bonusTier2Pending = this._bonusTier2Pending.add(amount); break; case 3: this._bonusTier3Pending = this._bonusTier3Pending.add(amount); break; } this._totalBonusPending = this._totalBonusPending.add(amount); this._totalPending = this._totalPending.add(amount); this._updatedAt = new Date(); } /** * 标记用户已认种 * 解锁层级1-5和加成第1档 */ markAsAdopted(): void { if (this._hasAdopted) return; // 已经认种过 this._hasAdopted = true; this._unlockedLevelDepth = 5; // 解锁1-5级 this._unlockedBonusTiers = 1; // 解锁第1档 this._updatedAt = new Date(); } /** * 增加直推认种用户数 */ incrementDirectReferralAdoptedCount(): void { this._directReferralAdoptedCount++; this.updateUnlockStatus(); } /** * 设置直推认种用户数 */ setDirectReferralAdoptedCount(count: number): void { this._directReferralAdoptedCount = count; this.updateUnlockStatus(); } /** * 更新解锁状态 * 根据直推认种用户数 */ private updateUnlockStatus(): void { // 层级解锁规则(只有在已认种的情况下才会解锁) if (this._hasAdopted) { if (this._directReferralAdoptedCount >= 5) { this._unlockedLevelDepth = 15; // 解锁11-15级 } else if (this._directReferralAdoptedCount >= 3) { this._unlockedLevelDepth = 10; // 解锁6-10级 } else { this._unlockedLevelDepth = 5; // 保持1-5级 } } // 加成解锁规则 let bonusTiers = 0; if (this._hasAdopted) bonusTiers = 1; // 自己认种解锁第1档 if (this._directReferralAdoptedCount >= 2) bonusTiers = 2; // 直推≥2解锁第2档 if (this._directReferralAdoptedCount >= 4) bonusTiers = 3; // 直推≥4解锁第3档 this._unlockedBonusTiers = bonusTiers; this._updatedAt = new Date(); } /** * 解锁待解锁的贡献值 * 根据当前解锁深度,将对应的 pending 转移到 unlocked * @returns 本次解锁的金额 */ unlockPendingContributions(): ContributionAmount { let unlockAmount = ContributionAmount.zero(); // 解锁层级算力 if (this._unlockedLevelDepth >= 5) { unlockAmount = unlockAmount.add(this._level1Pending); unlockAmount = unlockAmount.add(this._level2Pending); unlockAmount = unlockAmount.add(this._level3Pending); unlockAmount = unlockAmount.add(this._level4Pending); unlockAmount = unlockAmount.add(this._level5Pending); this._level1Pending = ContributionAmount.zero(); this._level2Pending = ContributionAmount.zero(); this._level3Pending = ContributionAmount.zero(); this._level4Pending = ContributionAmount.zero(); this._level5Pending = ContributionAmount.zero(); } if (this._unlockedLevelDepth >= 10) { unlockAmount = unlockAmount.add(this._level6Pending); unlockAmount = unlockAmount.add(this._level7Pending); unlockAmount = unlockAmount.add(this._level8Pending); unlockAmount = unlockAmount.add(this._level9Pending); unlockAmount = unlockAmount.add(this._level10Pending); this._level6Pending = ContributionAmount.zero(); this._level7Pending = ContributionAmount.zero(); this._level8Pending = ContributionAmount.zero(); this._level9Pending = ContributionAmount.zero(); this._level10Pending = ContributionAmount.zero(); } if (this._unlockedLevelDepth >= 15) { unlockAmount = unlockAmount.add(this._level11Pending); unlockAmount = unlockAmount.add(this._level12Pending); unlockAmount = unlockAmount.add(this._level13Pending); unlockAmount = unlockAmount.add(this._level14Pending); unlockAmount = unlockAmount.add(this._level15Pending); this._level11Pending = ContributionAmount.zero(); this._level12Pending = ContributionAmount.zero(); this._level13Pending = ContributionAmount.zero(); this._level14Pending = ContributionAmount.zero(); this._level15Pending = ContributionAmount.zero(); } // 解锁加成算力 if (this._unlockedBonusTiers >= 1) { unlockAmount = unlockAmount.add(this._bonusTier1Pending); this._bonusTier1Pending = ContributionAmount.zero(); } if (this._unlockedBonusTiers >= 2) { unlockAmount = unlockAmount.add(this._bonusTier2Pending); this._bonusTier2Pending = ContributionAmount.zero(); } if (this._unlockedBonusTiers >= 3) { unlockAmount = unlockAmount.add(this._bonusTier3Pending); this._bonusTier3Pending = ContributionAmount.zero(); } // 更新汇总 this._totalUnlocked = this._totalUnlocked.add(unlockAmount); this._totalPending = this._totalPending.subtract(unlockAmount); this._effectiveContribution = this._effectiveContribution.add(unlockAmount); this.recalculatePendingTotals(); this._updatedAt = new Date(); return unlockAmount; } /** * 重新计算待解锁汇总 */ private recalculatePendingTotals(): void { this._totalLevelPending = this._level1Pending .add(this._level2Pending) .add(this._level3Pending) .add(this._level4Pending) .add(this._level5Pending) .add(this._level6Pending) .add(this._level7Pending) .add(this._level8Pending) .add(this._level9Pending) .add(this._level10Pending) .add(this._level11Pending) .add(this._level12Pending) .add(this._level13Pending) .add(this._level14Pending) .add(this._level15Pending); this._totalBonusPending = this._bonusTier1Pending .add(this._bonusTier2Pending) .add(this._bonusTier3Pending); this._totalPending = this._totalLevelPending.add(this._totalBonusPending); } /** * 增加版本号(乐观锁) */ incrementVersion(): void { this._version++; this._updatedAt = new Date(); } /** * 创建新账户 */ static create(accountSequence: string): ContributionAccountAggregate { return new ContributionAccountAggregate({ accountSequence }); } /** * 从持久化数据恢复 */ static fromPersistence(data: { id: bigint; accountSequence: string; personalContribution: Decimal; level1Pending: Decimal; level2Pending: Decimal; level3Pending: Decimal; level4Pending: Decimal; level5Pending: Decimal; level6Pending: Decimal; level7Pending: Decimal; level8Pending: Decimal; level9Pending: Decimal; level10Pending: Decimal; level11Pending: Decimal; level12Pending: Decimal; level13Pending: Decimal; level14Pending: Decimal; level15Pending: Decimal; bonusTier1Pending: Decimal; bonusTier2Pending: Decimal; bonusTier3Pending: Decimal; totalLevelPending: Decimal; totalBonusPending: Decimal; totalPending: Decimal; totalUnlocked: Decimal; effectiveContribution: Decimal; hasAdopted: boolean; directReferralAdoptedCount: number; unlockedLevelDepth: number; unlockedBonusTiers: number; version: number; createdAt: Date; updatedAt: Date; }): ContributionAccountAggregate { return new ContributionAccountAggregate({ id: data.id, accountSequence: data.accountSequence, personalContribution: new ContributionAmount(data.personalContribution), level1Pending: new ContributionAmount(data.level1Pending), level2Pending: new ContributionAmount(data.level2Pending), level3Pending: new ContributionAmount(data.level3Pending), level4Pending: new ContributionAmount(data.level4Pending), level5Pending: new ContributionAmount(data.level5Pending), level6Pending: new ContributionAmount(data.level6Pending), level7Pending: new ContributionAmount(data.level7Pending), level8Pending: new ContributionAmount(data.level8Pending), level9Pending: new ContributionAmount(data.level9Pending), level10Pending: new ContributionAmount(data.level10Pending), level11Pending: new ContributionAmount(data.level11Pending), level12Pending: new ContributionAmount(data.level12Pending), level13Pending: new ContributionAmount(data.level13Pending), level14Pending: new ContributionAmount(data.level14Pending), level15Pending: new ContributionAmount(data.level15Pending), bonusTier1Pending: new ContributionAmount(data.bonusTier1Pending), bonusTier2Pending: new ContributionAmount(data.bonusTier2Pending), bonusTier3Pending: new ContributionAmount(data.bonusTier3Pending), totalLevelPending: new ContributionAmount(data.totalLevelPending), totalBonusPending: new ContributionAmount(data.totalBonusPending), totalPending: new ContributionAmount(data.totalPending), totalUnlocked: new ContributionAmount(data.totalUnlocked), effectiveContribution: new ContributionAmount(data.effectiveContribution), hasAdopted: data.hasAdopted, directReferralAdoptedCount: data.directReferralAdoptedCount, unlockedLevelDepth: data.unlockedLevelDepth, unlockedBonusTiers: data.unlockedBonusTiers, version: data.version, createdAt: data.createdAt, updatedAt: data.updatedAt, }); } /** * 转换为持久化数据 */ toPersistence(): { accountSequence: string; personalContribution: Decimal; level1Pending: Decimal; level2Pending: Decimal; level3Pending: Decimal; level4Pending: Decimal; level5Pending: Decimal; level6Pending: Decimal; level7Pending: Decimal; level8Pending: Decimal; level9Pending: Decimal; level10Pending: Decimal; level11Pending: Decimal; level12Pending: Decimal; level13Pending: Decimal; level14Pending: Decimal; level15Pending: Decimal; bonusTier1Pending: Decimal; bonusTier2Pending: Decimal; bonusTier3Pending: Decimal; totalLevelPending: Decimal; totalBonusPending: Decimal; totalPending: Decimal; totalUnlocked: Decimal; effectiveContribution: Decimal; hasAdopted: boolean; directReferralAdoptedCount: number; unlockedLevelDepth: number; unlockedBonusTiers: number; version: number; } { return { accountSequence: this._accountSequence, personalContribution: this._personalContribution.value, level1Pending: this._level1Pending.value, level2Pending: this._level2Pending.value, level3Pending: this._level3Pending.value, level4Pending: this._level4Pending.value, level5Pending: this._level5Pending.value, level6Pending: this._level6Pending.value, level7Pending: this._level7Pending.value, level8Pending: this._level8Pending.value, level9Pending: this._level9Pending.value, level10Pending: this._level10Pending.value, level11Pending: this._level11Pending.value, level12Pending: this._level12Pending.value, level13Pending: this._level13Pending.value, level14Pending: this._level14Pending.value, level15Pending: this._level15Pending.value, bonusTier1Pending: this._bonusTier1Pending.value, bonusTier2Pending: this._bonusTier2Pending.value, bonusTier3Pending: this._bonusTier3Pending.value, totalLevelPending: this._totalLevelPending.value, totalBonusPending: this._totalBonusPending.value, totalPending: this._totalPending.value, totalUnlocked: this._totalUnlocked.value, effectiveContribution: this._effectiveContribution.value, hasAdopted: this._hasAdopted, directReferralAdoptedCount: this._directReferralAdoptedCount, unlockedLevelDepth: this._unlockedLevelDepth, unlockedBonusTiers: this._unlockedBonusTiers, version: this._version, }; } }