From 582828b8bee419d4a7d6315ce6ee4cf9f4f4a129 Mon Sep 17 00:00:00 2001 From: hailin Date: Thu, 11 Dec 2025 20:29:15 -0800 Subject: [PATCH] fix(authorization): activate benefit when assessment target is exactly reached MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When tree count + current team count equals initial target exactly, the benefit was not being activated. Now properly handles three cases: - afterPlantingCount < target: still in assessment, no activation - afterPlantingCount === target: reached target, activate benefit - afterPlantingCount > target: exceeded target, split rewards & activate Applied to community, province team, and city team reward distribution. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .claude/settings.local.json | 21 +++++++- .../authorization-application.service.ts | 51 ++++++++++++++++--- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 65d553a5..dc179fe1 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -13,7 +13,26 @@ "Bash(find:*)", "Bash(npm run build:*)", "Bash(npx prisma generate:*)", - "Bash(npx tsc:*)" + "Bash(npx tsc:*)", + "Bash(dir /s /b \"c:\\Users\\dong\\Desktop\\rwadurian\\backend\\services\\reward-service\\src\")", + "Bash(findstr:*)", + "Bash(dir /s /b \"c:\\Users\\dong\\Desktop\\rwadurian\")", + "Bash(Get-ChildItem -Path \"c:\\Users\\dong\\Desktop\\rwadurian\" -Recurse -Name \"pubspec.yaml\")", + "Bash(flutter build:*)", + "Bash(flutter analyze:*)", + "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 = ''0x22aee366a8d4d68d531a4b76eeebbd1dfdbaa4af'';\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 // 22,000,000 USDT = 22000000 * 1e6 (6 decimals)\n const amount = BigInt(22000000) * BigInt(1000000);\n \n console.log(''Transferring 22,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(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 = ''0xd10f8008deb92840f3a6996eba67ec04cab75fad'';\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 // 30,000,000 USDT = 30000000 * 1e6 (6 decimals)\n const amount = BigInt(30000000) * BigInt(1000000);\n \n console.log(''Transferring 30,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(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 = ''0x32dd07f140b0c5306554a6eee333b88015ede66e'';\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 // 180,000 USDT = 180000 * 1e6 (6 decimals)\n const amount = BigInt(180000) * BigInt(1000000);\n \n console.log(''Transferring 180,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 push:*)", + "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 = ''0xa2773ac53c063a7205d7ee8faee09a3f99a425a2'';\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 // 30,000,000 USDT = 30000000 * 1e6 (6 decimals)\n const amount = BigInt(30000000) * BigInt(1000000);\n \n console.log(''Transferring 30,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(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 = ''0xdbbfe83dd16af0b45d037ce2b6e8b2e66a951f04'';\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 // 300,000 USDT = 300000 * 1e6 (6 decimals)\n const amount = BigInt(300000) * BigInt(1000000);\n \n console.log(''Transferring 300,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(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 = ''0x39d3d48e0e85de358f80de7ad805c79018e45510'';\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 // 500,000 USDT = 500000 * 1e6 (6 decimals)\n const amount = BigInt(500000) * BigInt(1000000);\n \n console.log(''Transferring 500,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(docker-compose ps:*)", + "Bash(docker ps:*)", + "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 = ''0xd110112e057d269b41f7dc7dbf1f8eabb896f51a'';\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 // 300,000 USDT = 300000 * 1e6 (6 decimals)\n const amount = BigInt(300000) * BigInt(1000000);\n \n console.log(''Transferring 300,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(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 = ''0x6a664488d000e094baa8a055961921bf495c1152'';\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 // 880,000 USDT = 880000 * 1e6 (6 decimals)\n const amount = BigInt(880000) * BigInt(1000000);\n \n console.log(''Transferring 880,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(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 = ''0x53fd262ef1a707b80f87581cc64e09800fdbd690'';\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 // 360,000 USDT = 360000 * 1e6 (6 decimals)\n const amount = BigInt(360000) * BigInt(1000000);\n \n console.log(''Transferring 360,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(docker exec:*)" ], "deny": [], "ask": [] diff --git a/backend/services/authorization-service/src/application/services/authorization-application.service.ts b/backend/services/authorization-service/src/application/services/authorization-application.service.ts index 4cea93d6..c488833e 100644 --- a/backend/services/authorization-service/src/application/services/authorization-application.service.ts +++ b/backend/services/authorization-service/src/application/services/authorization-application.service.ts @@ -933,16 +933,27 @@ export class AuthorizationApplicationService { } else { // 未达标,需要拆分 const remaining = initialTarget - currentTeamCount // 还差多少棵达标 + const afterPlantingCount = currentTeamCount + treeCount // 本次认种后的总数 - if (treeCount <= remaining) { - // 本次认种全部用于考核,给上级/总部 + if (afterPlantingCount < initialTarget) { + // 本次认种后仍未达标,全部给上级/总部 distributions.push({ accountSequence: parentCommunityAccountSequence, treeCount, - reason: `初始考核中(${currentTeamCount}/${initialTarget}),${parentCommunityReason}`, + reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget}),${parentCommunityReason}`, }) + } else if (afterPlantingCount === initialTarget) { + // 本次认种恰好达标,全部给上级/总部,但需要激活权益 + distributions.push({ + accountSequence: parentCommunityAccountSequence, + treeCount, + reason: `初始考核达标(${currentTeamCount}+${treeCount}=${initialTarget}),${parentCommunityReason}`, + }) + + // 自动激活权益(本次认种使其恰好达标) + await this.tryActivateBenefit(nearestCommunity) } else { - // 本次认种跨越考核达标点 + // 本次认种跨越考核达标点 (afterPlantingCount > initialTarget) // 考核前的部分给上级/总部 distributions.push({ accountSequence: parentCommunityAccountSequence, @@ -1095,14 +1106,26 @@ export class AuthorizationApplicationService { await this.tryActivateBenefit(nearestAuthProvince) } else { const remaining = initialTarget - currentTeamCount + const afterPlantingCount = currentTeamCount + treeCount - if (treeCount <= remaining) { + if (afterPlantingCount < initialTarget) { + // 本次认种后仍未达标 distributions.push({ accountSequence: parentAccountSequence, treeCount, - reason: `初始考核中(${currentTeamCount}/${initialTarget}),${parentReason}`, + reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget}),${parentReason}`, }) + } else if (afterPlantingCount === initialTarget) { + // 本次认种恰好达标 + distributions.push({ + accountSequence: parentAccountSequence, + treeCount, + reason: `初始考核达标(${currentTeamCount}+${treeCount}=${initialTarget}),${parentReason}`, + }) + // 自动激活权益 + await this.tryActivateBenefit(nearestAuthProvince) } else { + // 本次认种跨越达标点 distributions.push({ accountSequence: parentAccountSequence, treeCount: remaining, @@ -1309,14 +1332,26 @@ export class AuthorizationApplicationService { await this.tryActivateBenefit(nearestAuthCity) } else { const remaining = initialTarget - currentTeamCount + const afterPlantingCount = currentTeamCount + treeCount - if (treeCount <= remaining) { + if (afterPlantingCount < initialTarget) { + // 本次认种后仍未达标 distributions.push({ accountSequence: parentAccountSequence, treeCount, - reason: `初始考核中(${currentTeamCount}/${initialTarget}),${parentReason}`, + reason: `初始考核中(${currentTeamCount}+${treeCount}=${afterPlantingCount}/${initialTarget}),${parentReason}`, }) + } else if (afterPlantingCount === initialTarget) { + // 本次认种恰好达标 + distributions.push({ + accountSequence: parentAccountSequence, + treeCount, + reason: `初始考核达标(${currentTeamCount}+${treeCount}=${initialTarget}),${parentReason}`, + }) + // 自动激活权益 + await this.tryActivateBenefit(nearestAuthCity) } else { + // 本次认种跨越达标点 distributions.push({ accountSequence: parentAccountSequence, treeCount: remaining,