diff --git a/backend/services/identity-service/prisma/seed.ts b/backend/services/identity-service/prisma/seed.ts index c02bf630..67aa0c94 100644 --- a/backend/services/identity-service/prisma/seed.ts +++ b/backend/services/identity-service/prisma/seed.ts @@ -2,6 +2,48 @@ import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); +// ============================================ +// 系统账户定义 +// ============================================ +const SYSTEM_ACCOUNTS = [ + { + userId: BigInt(1), + accountSequence: BigInt(1), + nickname: '总部社区', + referralCode: 'HQ000001', + provinceCode: '000000', + cityCode: '000000', + status: 'SYSTEM', + }, + { + userId: BigInt(2), + accountSequence: BigInt(2), + nickname: '成本费账户', + referralCode: 'COST0002', + provinceCode: '000000', + cityCode: '000000', + status: 'SYSTEM', + }, + { + userId: BigInt(3), + accountSequence: BigInt(3), + nickname: '运营费账户', + referralCode: 'OPER0003', + provinceCode: '000000', + cityCode: '000000', + status: 'SYSTEM', + }, + { + userId: BigInt(4), + accountSequence: BigInt(4), + nickname: 'RWAD底池账户', + referralCode: 'POOL0004', + provinceCode: '000000', + cityCode: '000000', + status: 'SYSTEM', + }, +]; + async function main() { console.log('Seeding database...'); @@ -14,17 +56,29 @@ async function main() { await prisma.userDevice.deleteMany(); await prisma.userAccount.deleteMany(); - // 初始化账户序列号生成器 + // 初始化账户序列号生成器 (从100000开始,系统账户使用1-99) await prisma.accountSequenceGenerator.deleteMany(); await prisma.accountSequenceGenerator.create({ data: { id: 1, - currentSequence: BigInt(100000), // 从100000开始 + currentSequence: BigInt(100000), // 普通用户从100000开始 }, }); + // 创建系统账户 + console.log('Creating system accounts...'); + for (const account of SYSTEM_ACCOUNTS) { + await prisma.userAccount.upsert({ + where: { userId: account.userId }, + update: account, + create: account, + }); + console.log(` - Created system account: ${account.nickname} (userId=${account.userId})`); + } + console.log('Database seeded successfully!'); console.log('- Initialized account sequence generator starting at 100000'); + console.log(`- Created ${SYSTEM_ACCOUNTS.length} system accounts (userId 1-4)`); } main() diff --git a/backend/services/reward-service/prisma/seed.ts b/backend/services/reward-service/prisma/seed.ts index d4c93acb..e133bd04 100644 --- a/backend/services/reward-service/prisma/seed.ts +++ b/backend/services/reward-service/prisma/seed.ts @@ -3,8 +3,42 @@ import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { + // ============================================ // 初始化权益定义 + // 总计 2199 USDT = 400 + 300 + 9 + 800 + 500 + 15 + 20 + 35 + 40 + 80 + // ============================================ const rightDefinitions = [ + // === 系统费用类 (1509 USDT) === + { + rightType: 'COST_FEE', + usdtPerTree: 400, + hashpowerPercent: 0, + payableTo: 'SYSTEM_ACCOUNT', + ruleDescription: '成本费:每棵树400 USDT,进成本账户(userId=2)', + }, + { + rightType: 'OPERATION_FEE', + usdtPerTree: 300, + hashpowerPercent: 0, + payableTo: 'SYSTEM_ACCOUNT', + ruleDescription: '运营费:每棵树300 USDT,进运营账户(userId=3)', + }, + { + rightType: 'HEADQUARTERS_BASE_FEE', + usdtPerTree: 9, + hashpowerPercent: 0, + payableTo: 'HEADQUARTERS', + ruleDescription: '总部社区基础费:每棵树9 USDT,进总部社区账户(userId=1)', + }, + { + rightType: 'RWAD_POOL_INJECTION', + usdtPerTree: 800, + hashpowerPercent: 0, + payableTo: 'SYSTEM_ACCOUNT', + ruleDescription: 'RWAD底池注入:每棵树800 USDT,注入1号底池(userId=4)', + }, + + // === 用户权益类 (690 USDT + 算力) === { rightType: 'SHARE_RIGHT', usdtPerTree: 500, diff --git a/backend/services/reward-service/src/domain/services/reward-calculation.service.ts b/backend/services/reward-service/src/domain/services/reward-calculation.service.ts index 09b9fdc0..d6c6ca7c 100644 --- a/backend/services/reward-service/src/domain/services/reward-calculation.service.ts +++ b/backend/services/reward-service/src/domain/services/reward-calculation.service.ts @@ -21,9 +21,22 @@ export interface IAuthorizationServiceClient { export const REFERRAL_SERVICE_CLIENT = Symbol('IReferralServiceClient'); export const AUTHORIZATION_SERVICE_CLIENT = Symbol('IAuthorizationServiceClient'); +// ============================================ +// 系统账户ID配置 +// ============================================ + // 总部社区账户ID const HEADQUARTERS_COMMUNITY_USER_ID = BigInt(1); +// 成本费账户ID (需要在系统初始化时创建) +const COST_FEE_ACCOUNT_ID = BigInt(2); + +// 运营费账户ID (需要在系统初始化时创建) +const OPERATION_FEE_ACCOUNT_ID = BigInt(3); + +// RWAD 1号底池账户ID (需要在系统初始化时创建) +const RWAD_POOL_ACCOUNT_ID = BigInt(4); + @Injectable() export class RewardCalculationService { constructor( @@ -35,6 +48,7 @@ export class RewardCalculationService { /** * 计算认种订单产生的所有奖励 + * 总计 2199 USDT = 400 + 300 + 9 + 800 + 500 + 15 + 20 + 35 + 40 + 80 */ async calculateRewards(params: { sourceOrderId: bigint; @@ -45,7 +59,47 @@ export class RewardCalculationService { }): Promise { const rewards: RewardLedgerEntry[] = []; - // 1. 分享权益 (500 USDT) + // ============================================ + // 系统费用类 (709 USDT) + // ============================================ + + // 1. 成本费 (400 USDT) + const costFeeReward = this.calculateCostFee( + params.sourceOrderId, + params.sourceUserId, + params.treeCount, + ); + rewards.push(costFeeReward); + + // 2. 运营费 (300 USDT) + const operationFeeReward = this.calculateOperationFee( + params.sourceOrderId, + params.sourceUserId, + params.treeCount, + ); + rewards.push(operationFeeReward); + + // 3. 总部社区基础费 (9 USDT) + const headquartersBaseFeeReward = this.calculateHeadquartersBaseFee( + params.sourceOrderId, + params.sourceUserId, + params.treeCount, + ); + rewards.push(headquartersBaseFeeReward); + + // 4. RWAD底池注入 (800 USDT) + const rwadPoolReward = this.calculateRwadPoolInjection( + params.sourceOrderId, + params.sourceUserId, + params.treeCount, + ); + rewards.push(rwadPoolReward); + + // ============================================ + // 用户权益类 (690 USDT + 算力) + // ============================================ + + // 5. 分享权益 (500 USDT) const shareRewards = await this.calculateShareRights( params.sourceOrderId, params.sourceUserId, @@ -53,7 +107,7 @@ export class RewardCalculationService { ); rewards.push(...shareRewards); - // 2. 省团队权益 (20 USDT) + // 6. 省团队权益 (20 USDT) const provinceTeamReward = await this.calculateProvinceTeamRight( params.sourceOrderId, params.sourceUserId, @@ -62,7 +116,7 @@ export class RewardCalculationService { ); rewards.push(provinceTeamReward); - // 3. 省区域权益 (15 USDT + 1%算力) + // 7. 省区域权益 (15 USDT + 1%算力) const provinceAreaReward = this.calculateProvinceAreaRight( params.sourceOrderId, params.sourceUserId, @@ -71,7 +125,7 @@ export class RewardCalculationService { ); rewards.push(provinceAreaReward); - // 4. 市团队权益 (40 USDT) + // 8. 市团队权益 (40 USDT) const cityTeamReward = await this.calculateCityTeamRight( params.sourceOrderId, params.sourceUserId, @@ -80,7 +134,7 @@ export class RewardCalculationService { ); rewards.push(cityTeamReward); - // 5. 市区域权益 (35 USDT + 2%算力) + // 9. 市区域权益 (35 USDT + 2%算力) const cityAreaReward = this.calculateCityAreaRight( params.sourceOrderId, params.sourceUserId, @@ -89,7 +143,7 @@ export class RewardCalculationService { ); rewards.push(cityAreaReward); - // 6. 社区权益 (80 USDT) + // 10. 社区权益 (80 USDT) const communityReward = await this.calculateCommunityRight( params.sourceOrderId, params.sourceUserId, @@ -100,6 +154,126 @@ export class RewardCalculationService { return rewards; } + // ============================================ + // 系统费用计算方法 + // ============================================ + + /** + * 计算成本费 (400 USDT) + * 分配至指定成本账户 + */ + private calculateCostFee( + sourceOrderId: bigint, + sourceUserId: bigint, + treeCount: number, + ): RewardLedgerEntry { + const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.COST_FEE]; + const usdtAmount = Money.USDT(usdt * treeCount); + const hashpower = Hashpower.fromTreeCount(treeCount, hashpowerPercent); + + const rewardSource = RewardSource.create( + RightType.COST_FEE, + sourceOrderId, + sourceUserId, + ); + + return RewardLedgerEntry.createSettleable({ + userId: COST_FEE_ACCOUNT_ID, + rewardSource, + usdtAmount, + hashpowerAmount: hashpower, + memo: `成本费:来自用户${sourceUserId}的认种,${treeCount}棵树`, + }); + } + + /** + * 计算运营费 (300 USDT) + * 分配至指定运营账户 + */ + private calculateOperationFee( + sourceOrderId: bigint, + sourceUserId: bigint, + treeCount: number, + ): RewardLedgerEntry { + const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.OPERATION_FEE]; + const usdtAmount = Money.USDT(usdt * treeCount); + const hashpower = Hashpower.fromTreeCount(treeCount, hashpowerPercent); + + const rewardSource = RewardSource.create( + RightType.OPERATION_FEE, + sourceOrderId, + sourceUserId, + ); + + return RewardLedgerEntry.createSettleable({ + userId: OPERATION_FEE_ACCOUNT_ID, + rewardSource, + usdtAmount, + hashpowerAmount: hashpower, + memo: `运营费:来自用户${sourceUserId}的认种,${treeCount}棵树`, + }); + } + + /** + * 计算总部社区基础费 (9 USDT) + * 分配至总部社区账户 + */ + private calculateHeadquartersBaseFee( + sourceOrderId: bigint, + sourceUserId: bigint, + treeCount: number, + ): RewardLedgerEntry { + const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.HEADQUARTERS_BASE_FEE]; + const usdtAmount = Money.USDT(usdt * treeCount); + const hashpower = Hashpower.fromTreeCount(treeCount, hashpowerPercent); + + const rewardSource = RewardSource.create( + RightType.HEADQUARTERS_BASE_FEE, + sourceOrderId, + sourceUserId, + ); + + return RewardLedgerEntry.createSettleable({ + userId: HEADQUARTERS_COMMUNITY_USER_ID, + rewardSource, + usdtAmount, + hashpowerAmount: hashpower, + memo: `总部社区基础费:来自用户${sourceUserId}的认种,${treeCount}棵树`, + }); + } + + /** + * 计算RWAD底池注入 (800 USDT) + * 注入RWAD 1号底池 + */ + private calculateRwadPoolInjection( + sourceOrderId: bigint, + sourceUserId: bigint, + treeCount: number, + ): RewardLedgerEntry { + const { usdt, hashpowerPercent } = RIGHT_AMOUNTS[RightType.RWAD_POOL_INJECTION]; + const usdtAmount = Money.USDT(usdt * treeCount); + const hashpower = Hashpower.fromTreeCount(treeCount, hashpowerPercent); + + const rewardSource = RewardSource.create( + RightType.RWAD_POOL_INJECTION, + sourceOrderId, + sourceUserId, + ); + + return RewardLedgerEntry.createSettleable({ + userId: RWAD_POOL_ACCOUNT_ID, + rewardSource, + usdtAmount, + hashpowerAmount: hashpower, + memo: `RWAD底池注入:来自用户${sourceUserId}的认种,${treeCount}棵树,800U注入1号底池`, + }); + } + + // ============================================ + // 用户权益计算方法 + // ============================================ + /** * 计算分享权益 (500 USDT) */ diff --git a/backend/services/reward-service/src/domain/value-objects/right-type.enum.ts b/backend/services/reward-service/src/domain/value-objects/right-type.enum.ts index 300a9ace..c330ebae 100644 --- a/backend/services/reward-service/src/domain/value-objects/right-type.enum.ts +++ b/backend/services/reward-service/src/domain/value-objects/right-type.enum.ts @@ -1,4 +1,11 @@ export enum RightType { + // === 系统费用类 === + COST_FEE = 'COST_FEE', // 成本费 400U + OPERATION_FEE = 'OPERATION_FEE', // 运营费 300U + HEADQUARTERS_BASE_FEE = 'HEADQUARTERS_BASE_FEE', // 总部社区基础费 9U + RWAD_POOL_INJECTION = 'RWAD_POOL_INJECTION', // RWAD底池注入 800U + + // === 用户权益类 === SHARE_RIGHT = 'SHARE_RIGHT', // 分享权益 500U PROVINCE_AREA_RIGHT = 'PROVINCE_AREA_RIGHT', // 省区域权益 15U + 1%算力 PROVINCE_TEAM_RIGHT = 'PROVINCE_TEAM_RIGHT', // 省团队权益 20U @@ -9,6 +16,13 @@ export enum RightType { // 权益金额配置 export const RIGHT_AMOUNTS: Record = { + // 系统费用类 + [RightType.COST_FEE]: { usdt: 400, hashpowerPercent: 0 }, + [RightType.OPERATION_FEE]: { usdt: 300, hashpowerPercent: 0 }, + [RightType.HEADQUARTERS_BASE_FEE]: { usdt: 9, hashpowerPercent: 0 }, + [RightType.RWAD_POOL_INJECTION]: { usdt: 800, hashpowerPercent: 0 }, + + // 用户权益类 [RightType.SHARE_RIGHT]: { usdt: 500, hashpowerPercent: 0 }, [RightType.PROVINCE_AREA_RIGHT]: { usdt: 15, hashpowerPercent: 1 }, [RightType.PROVINCE_TEAM_RIGHT]: { usdt: 20, hashpowerPercent: 0 }, @@ -16,3 +30,5 @@ export const RIGHT_AMOUNTS: Record