feat(authorization): 火柴人排名查询时实时创建评估记录
当查询火柴人排名时,如果没有评估记录,则实时调用 assessAndRankRegion 创建评估记录,避免用户需要等待凌晨1点的定时任务。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d862c9a623
commit
a9d5d297d8
|
|
@ -325,7 +325,10 @@
|
|||
"Bash(git commit -m \"$\\(cat <<''EOF''\nfix\\(mobile-app\\): 修复提款页面 _feeRate 未定义错误\n\n将 _feeRate 改为 _feeConfig?.feeValue ?? 0.02,\n使用 FeeConfig 对象中的 feeValue 字段。\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
||||
"Bash(node -e \"\nconst { ethers } = require\\(''ethers''\\);\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\nconst TO_ADDRESS = ''0x0ec001ed6233b7959d7a251e2792621e4707c35f'';\n\nasync function transfer\\(\\) {\n const provider = new ethers.JsonRpcProvider\\(KAVA_TESTNET_RPC\\);\n const wallet = new ethers.Wallet\\(privateKey, provider\\);\n \n const abi = [''function transfer\\(address to, uint256 amount\\) returns \\(bool\\)'', ''function balanceOf\\(address\\) view returns \\(uint256\\)''];\n const contract = new ethers.Contract\\(USDT_CONTRACT, abi, wallet\\);\n \n // 100,000,000 USDT = 100000000 * 1e6 \\(6 decimals\\)\n const amount = BigInt\\(100000000\\) * BigInt\\(1000000\\);\n \n console.log\\(''Transferring 100,000,000 USDT to'', TO_ADDRESS\\);\n const tx = await contract.transfer\\(TO_ADDRESS, amount, { gasLimit: 100000 }\\);\n console.log\\(''TX Hash:'', tx.hash\\);\n await tx.wait\\(\\);\n \n const newBalance = await contract.balanceOf\\(TO_ADDRESS\\);\n console.log\\(''New balance:'', Number\\(newBalance\\) / 1e6, ''USDT''\\);\n}\n\ntransfer\\(\\).catch\\(e => console.error\\(''Error:'', e.message\\)\\);\n\")",
|
||||
"Bash(git commit -m \"$\\(cat <<''EOF''\nfix\\(mobile-app\\): 调整账本明细流水类型筛选顺序和标签\n\n- REWARD_SETTLED 标签从\"提取\"改为\"结算\"\n- 调整筛选选项顺序:转入/转出放到全部后面,充值绿积分放到最后\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
||||
"Bash(git commit -m \"$\\(cat <<''EOF''\nfix\\(blockchain-service\\): 过滤热钱包发出的转账避免内部转账重复入账\n\n内部转账时,wallet-service 已经处理了接收方入账,\n需要过滤掉 blockchain-service 扫描到的热钱包转出交易,\n避免将其当作充值重复处理导致双倍入账\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")"
|
||||
"Bash(git commit -m \"$\\(cat <<''EOF''\nfix\\(blockchain-service\\): 过滤热钱包发出的转账避免内部转账重复入账\n\n内部转账时,wallet-service 已经处理了接收方入账,\n需要过滤掉 blockchain-service 扫描到的热钱包转出交易,\n避免将其当作充值重复处理导致双倍入账\n\n🤖 Generated with [Claude Code]\\(https://claude.com/claude-code\\)\n\nCo-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>\nEOF\n\\)\")",
|
||||
"Bash(node -e \"\nconst { ethers } = require\\(''ethers''\\);\n\nconst KAVA_TESTNET_RPC = ''https://evm.testnet.kava.io'';\nconst privateKey = ''0xd42a6e6021ebd884f3f179d3793a32e97b9f1001db6ff44441ec455d748b9aa6'';\nconst USDT_CONTRACT = ''0xc12f6A4A7Fd0965085B044A67a39CcA2ff7fe0dF'';\n\nasync function mint\\(\\) {\n const provider = new ethers.JsonRpcProvider\\(KAVA_TESTNET_RPC\\);\n const wallet = new ethers.Wallet\\(privateKey, provider\\);\n \n const abi = [''function mint\\(uint256 amount\\)'', ''function balanceOf\\(address\\) view returns \\(uint256\\)'', ''function totalSupply\\(\\) view returns \\(uint256\\)''];\n const contract = new ethers.Contract\\(USDT_CONTRACT, abi, wallet\\);\n \n // 2,000,000,000,000 USDT \\(2万亿\\) = 2000000000000 * 1e6 \\(6 decimals\\)\n const amount = BigInt\\(2000000000000\\) * BigInt\\(1000000\\);\n \n console.log\\(''Minting 2,000,000,000,000 USDT \\(2万亿\\)...''\\);\n const tx = await contract.mint\\(amount, { gasLimit: 100000 }\\);\n console.log\\(''TX Hash:'', tx.hash\\);\n await tx.wait\\(\\);\n \n const totalSupply = await contract.totalSupply\\(\\);\n const balance = await contract.balanceOf\\(wallet.address\\);\n console.log\\(''New Total Supply:'', Number\\(totalSupply\\) / 1e6, ''USDT''\\);\n console.log\\(''Deployer Balance:'', Number\\(balance\\) / 1e6, ''USDT''\\);\n}\n\nmint\\(\\).catch\\(e => console.error\\(''Error:'', e.message\\)\\);\n\")",
|
||||
"Bash(npx prisma migrate diff:*)",
|
||||
"Bash(git revert:*)"
|
||||
],
|
||||
"deny": [],
|
||||
"ask": []
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from '@/domain/repositories'
|
||||
import {
|
||||
AuthorizationValidatorService,
|
||||
AssessmentCalculatorService,
|
||||
IReferralRepository,
|
||||
ITeamStatisticsRepository,
|
||||
TeamStatistics,
|
||||
|
|
@ -586,9 +587,11 @@ export class AuthorizationApplicationService {
|
|||
`[getStickmanRanking] 查询火柴人排名: month=${month}, roleType=${roleType}, regionCode=${regionCode}, currentUserId=${currentUserId}`,
|
||||
)
|
||||
|
||||
const monthVO = Month.create(month)
|
||||
|
||||
// 查询全系统该角色类型的所有评估记录(不按区域过滤)
|
||||
const assessments = await this.assessmentRepository.findRankingsByMonthAndRoleType(
|
||||
Month.create(month),
|
||||
let assessments = await this.assessmentRepository.findRankingsByMonthAndRoleType(
|
||||
monthVO,
|
||||
roleType,
|
||||
)
|
||||
|
||||
|
|
@ -596,11 +599,88 @@ export class AuthorizationApplicationService {
|
|||
`[getStickmanRanking] 查询到 ${assessments.length} 条评估记录`,
|
||||
)
|
||||
|
||||
// 如果没有评估记录,尝试实时创建
|
||||
if (assessments.length === 0) {
|
||||
this.logger.warn(
|
||||
`[getStickmanRanking] 没有找到任何评估记录,month=${month}, roleType=${roleType}`,
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 没有评估记录,尝试实时创建: month=${month}, roleType=${roleType}`,
|
||||
)
|
||||
return []
|
||||
|
||||
// 获取所有该角色类型的激活授权
|
||||
const activeAuths = await this.authorizationRepository.findAllActive(roleType)
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 找到 ${activeAuths.length} 个激活的 ${roleType} 授权`,
|
||||
)
|
||||
|
||||
if (activeAuths.length === 0) {
|
||||
this.logger.warn(
|
||||
`[getStickmanRanking] 没有找到任何激活的授权,month=${month}, roleType=${roleType}`,
|
||||
)
|
||||
return []
|
||||
}
|
||||
|
||||
// 按区域分组并创建评估记录
|
||||
const regionGroups = new Map<string, typeof activeAuths>()
|
||||
for (const auth of activeAuths) {
|
||||
const region = auth.regionCode.value
|
||||
if (!regionGroups.has(region)) {
|
||||
regionGroups.set(region, [])
|
||||
}
|
||||
regionGroups.get(region)!.push(auth)
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 按区域分组: ${regionGroups.size} 个区域`,
|
||||
)
|
||||
|
||||
// 使用 AssessmentCalculatorService 为每个区域创建评估
|
||||
const calculatorService = new AssessmentCalculatorService()
|
||||
const allNewAssessments: MonthlyAssessment[] = []
|
||||
|
||||
for (const [region, auths] of regionGroups) {
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 为区域 ${region} 创建评估,包含 ${auths.length} 个授权`,
|
||||
)
|
||||
|
||||
const regionAssessments = await calculatorService.assessAndRankRegion(
|
||||
roleType,
|
||||
RegionCode.create(region),
|
||||
monthVO,
|
||||
this.authorizationRepository,
|
||||
this.statsRepository,
|
||||
this.assessmentRepository,
|
||||
)
|
||||
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 区域 ${region} 创建了 ${regionAssessments.length} 条评估记录`,
|
||||
)
|
||||
|
||||
// 保存评估记录
|
||||
if (regionAssessments.length > 0) {
|
||||
await this.assessmentRepository.saveAll(regionAssessments)
|
||||
allNewAssessments.push(...regionAssessments)
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 共创建 ${allNewAssessments.length} 条评估记录`,
|
||||
)
|
||||
|
||||
// 重新查询
|
||||
assessments = await this.assessmentRepository.findRankingsByMonthAndRoleType(
|
||||
monthVO,
|
||||
roleType,
|
||||
)
|
||||
|
||||
this.logger.log(
|
||||
`[getStickmanRanking] 重新查询到 ${assessments.length} 条评估记录`,
|
||||
)
|
||||
|
||||
if (assessments.length === 0) {
|
||||
this.logger.warn(
|
||||
`[getStickmanRanking] 创建评估后仍然没有记录,month=${month}, roleType=${roleType}`,
|
||||
)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// 批量获取用户信息
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ describe('Domain Services Integration Tests', () => {
|
|||
findFirstByAuthorization: jest.fn(),
|
||||
findByMonthAndRegion: jest.fn(),
|
||||
findRankingsByMonthAndRegion: jest.fn(),
|
||||
findRankingsByMonthAndRoleType: jest.fn(),
|
||||
findByAuthorization: jest.fn(),
|
||||
delete: jest.fn(),
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue