feat(reward): 补全10种认种奖励分配规则
新增4种系统费用类权益: - COST_FEE: 成本费 400 USDT → 成本账户(userId=2) - OPERATION_FEE: 运营费 300 USDT → 运营账户(userId=3) - HEADQUARTERS_BASE_FEE: 总部社区基础费 9 USDT → 总部社区(userId=1) - RWAD_POOL_INJECTION: RWAD底池注入 800 USDT → 底池账户(userId=4) 原有6种用户权益类保持不变: - SHARE_RIGHT: 分享权益 500 USDT - PROVINCE_AREA_RIGHT: 省区域权益 15 USDT + 1%算力 - PROVINCE_TEAM_RIGHT: 省团队权益 20 USDT - CITY_AREA_RIGHT: 市区域权益 35 USDT + 2%算力 - CITY_TEAM_RIGHT: 市团队权益 40 USDT - COMMUNITY_RIGHT: 社区权益 80 USDT 总计: 400 + 300 + 9 + 800 + 500 + 15 + 20 + 35 + 40 + 80 = 2199 USDT 同时更新seed脚本创建4个系统账户 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
667ca1527a
commit
51be55d315
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<RewardLedgerEntry[]> {
|
||||
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)
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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, { usdt: number; hashpowerPercent: number }> = {
|
||||
// 系统费用类
|
||||
[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<RightType, { usdt: number; hashpowerPercent:
|
|||
[RightType.CITY_TEAM_RIGHT]: { usdt: 40, hashpowerPercent: 0 },
|
||||
[RightType.COMMUNITY_RIGHT]: { usdt: 80, hashpowerPercent: 0 },
|
||||
};
|
||||
|
||||
// 总金额验证: 400 + 300 + 9 + 800 + 500 + 15 + 20 + 35 + 40 + 80 = 2199 USDT
|
||||
|
|
|
|||
Loading…
Reference in New Issue