Commit Graph

32 Commits

Author SHA1 Message Date
hailin 4478351f89 fix(authorization): 修复 grantProvinceCompany 业务验证逻辑
- 添加省区域/市区域互斥检查:同一用户不能同时拥有两种身份
- 添加省区域全局唯一性检查:整个系统只允许一个省区域角色被授权
- 添加 findAnyProvinceCompany 仓储方法用于全局唯一性校验
- 移除错误的 validateAuthorizationRequest 调用(该方法只适用于团队角色)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:15:09 -08:00
hailin 298ce52fc7 fix(authorization): 修复 grantCityCompany 业务验证逻辑
- 添加市区域/省区域互斥检查:同一用户不能同时拥有两种身份
- 添加用户市区域唯一性检查:一个用户只能有一个市区域角色
- 添加城市全局唯一性检查:同一城市只允许一个市区域角色
- 移除错误的 validateAuthorizationRequest 调用(该方法只适用于团队角色)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:11:13 -08:00
hailin 10ce981111 fix(authorization-service): 社区授权唯一性约束
- 一个用户只能拥有一个社区角色
- 社区名称全局唯一,不允许重复
- 添加 findCommunityByName repository 方法

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 00:04:24 -08:00
hailin 95e1cdffba feat(authorization-service): 正式省公司(PROVINCE_COMPANY)阶梯考核及月度考核
- 添加 PROVINCE_COMPANY_LADDER 阶梯目标配置 (150→300→600→1200→2400→4800→9600→19200→11750)
- 修改 getProvinceAreaRewardDistribution 使用阶梯目标判断激活条件
- 添加 processExpiredProvinceCompanyBenefits 月度考核方法
- 添加每月最后一天23:59定时任务执行省公司月度考核
- 添加月度数据存档方法 archiveAndResetProvinceCompanyMonthlyTreeCounts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 23:43:41 -08:00
hailin 1896dd6b4c feat(authorization-service): 正式市公司(CITY_COMPANY)阶梯考核及月度考核
- 添加 CITY_COMPANY_LADDER 阶梯目标配置 (30→60→120→240→480→960→1920→3840→2350)
- 修改 getCityAreaRewardDistribution 使用阶梯目标激活权益
- 添加 processExpiredCityCompanyBenefits 月度考核处理方法
- 添加月末23:59考核定时任务 (判断是否当月最后一天)
- 添加正式市公司月度数据存档定时任务

业务规则:
- 第一个月达标30棵树即可激活权益
- 每月最后一天23:59执行考核
- 达标续期并递增月份索引
- 不达标停用权益

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 23:34:55 -08:00
hailin 4d58d4be6c feat(authorization-service): 省团队授权级联激活/停用及月度考核
- 添加 cascadeActivateParentAuthProvinces: 当省团队授权激活时级联激活上级省团队
- 添加 cascadeDeactivateAuthProvinceBenefits: 月度考核失败时级联停用上级省团队
- 添加 processExpiredAuthProvinceBenefits: 月度考核处理(500棵树/月)
- 修改 tryActivateBenefit 支持 AUTH_PROVINCE_COMPANY 级联激活
- 定时任务: 每天凌晨5点检查省团队权益过期
- 定时任务: 每月1号存档并重置省团队月度新增树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:32:39 -08:00
hailin 049a13c97e feat(authorization-service): 市团队授权级联激活/停用及月度考核
- 添加 cascadeActivateParentAuthCities: 当市团队授权激活时级联激活上级市团队
- 添加 cascadeDeactivateAuthCityBenefits: 月度考核失败时级联停用上级市团队
- 添加 processExpiredAuthCityBenefits: 月度考核处理(100棵树/月)
- 添加 findExpiredActiveByRoleType 仓储方法
- 修改 tryActivateBenefit 支持 AUTH_CITY_COMPANY 级联激活
- 定时任务: 每天凌晨4点检查市团队权益过期
- 定时任务: 每月1号存档并重置市团队月度新增树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 22:04:59 -08:00
hailin 4a2a1e3855 feat(authorization-service): 为 getProvinceTeamRewardDistribution 添加 addMonthlyTrees 调用
参考 getCommunityRewardDistribution 的实现,在以下三个场景添加月度新增树数累计:
1. benefitActive=true 时:全部 treeCount 给该省团队,累加 treeCount
2. currentTeamCount >= initialTarget 时(兜底处理):累加 treeCount
3. 跨越考核达标点时:只累加归自己的部分 afterTargetCount

这确保了省团队权益与社区权益的月度考核追踪逻辑一致。
- 考核目标:500棵(省团队)
- 奖励:20 USDT
- 无上级时分配到系统省团队账户

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:55:28 -08:00
hailin 8f91a5b985 feat(authorization-service): 为 getCityTeamRewardDistribution 添加 addMonthlyTrees 调用
参考 getCommunityRewardDistribution 的实现,在以下三个场景添加月度新增树数累计:
1. benefitActive=true 时:全部 treeCount 给该市团队,累加 treeCount
2. currentTeamCount >= initialTarget 时(兜底处理):累加 treeCount
3. 跨越考核达标点时:只累加归自己的部分 afterTargetCount

这确保了市团队权益与社区权益的月度考核追踪逻辑一致。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:36:37 -08:00
hailin d12bf6df2f fix(authorization-service): 修复权益分配边界逻辑 + 添加 addMonthlyTrees 调用
边界逻辑修复:
- 社区/省/市团队和区域权益分配:第N棵(达标棵)也给上级,第N+1棵起才给自己
- 例如社区:第1-10棵全部给上级的上级/总部,第11棵起才归该社区

addMonthlyTrees 调用:
- 权益已激活时:累加全部树数
- 初始考核达标后:累加归自己的那部分(第11棵起)
- 已达标但未激活时:累加全部树数

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 21:24:16 -08:00
hailin 6bd6c6b5be feat(authorization-service): 实现月度考核数据存档机制(方案B)
- 新增 lastMonthTreesAdded 字段,用于存档上月业绩数据
- 新增 archiveAndResetMonthlyTreeCounts 定时任务:每月1日0:00将当月数据存档后重置
- 新增 getTreesForAssessment() 方法:根据 benefitValidUntil 判断使用当月或上月数据
- 修复月度考核时序问题:数据重置(0:00)在考核(3:00)之前执行

业务规则:
- 严格自然月统计,11月的业绩不计入12月
- 激活当月免考核,考核激活当月的下一个月
- 权益有效期在上月末 → 使用 lastMonthTreesAdded
- 权益有效期在当月末 → 使用 monthlyTreesAdded

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 20:39:16 -08:00
hailin 2af44e5854 feat(authorization-service): 实现社区权益月度考核及级联激活/停用功能
- 新增 benefitValidUntil、lastAssessmentMonth、monthlyTreesAdded 字段追踪月度考核
- 实现级联激活:当社区权益激活时,自动激活所有上级社区的权益
- 实现级联停用:当月度考核不达标时,级联停用该社区及所有上级社区
- 新增定时任务:每天凌晨3点检查过期社区权益,每月1号凌晨重置月度树数
- 权益有效期为当前月+下月末

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 07:23:46 -08:00
hailin 8f81c46d75 feat: 省市团队账户及待领取奖励逐笔追踪
1. authorization-service:
   - 省团队权益分配改用系统省团队账户 (7+provinceCode)
   - 市团队权益分配改用系统市团队账户 (6+cityCode)
   - 无推荐链时不再进总部,而是进对应团队账户

2. wallet-service:
   - 新增 pending_rewards 表支持逐笔追踪待领取奖励
   - ensureRegionAccounts 同时创建区域账户和团队账户
   - 新增 getPendingRewards API 查询待领取列表
   - 新增 settleUserPendingRewards 用户认种后结算
   - 新增 processExpiredRewards 定时处理过期奖励
   - PlantingCreatedHandler 监听认种事件触发结算
   - ExpiredRewardsScheduler 每小时处理过期奖励

账户格式:
- 省区域: 9+provinceCode (如 9440000)
- 市区域: 8+cityCode (如 8440100)
- 省团队: 7+provinceCode (如 7440000)
- 市团队: 6+cityCode (如 6440100)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 03:32:47 -08:00
hailin 4be9c1fb82 refactor!: 重构账户序列号格式 (BREAKING CHANGE)
将 accountSequence 从数字类型改为字符串类型,新格式为:
- 普通用户: D + YYMMDD + 5位序号 (例: D2512120001)
- 系统账户: S + 10位序号 (例: S0000000001)

主要变更:
- identity-service: AccountSequence 值对象改为字符串类型
- identity-service: 序列号生成器改为按日期重置计数
- 所有服务: Prisma schema 字段类型从 BigInt/Int 改为 String
- 所有服务: DTO、Command、Event 中的类型定义更新
- Flutter 前端: 相关数据模型类型更新

涉及服务:
- identity-service (核心变更)
- referral-service
- authorization-service
- wallet-service
- reward-service
- blockchain-service
- backup-service
- planting-service
- mpc-service
- admin-service
- mobile-app (Flutter)

注意: 此为破坏性变更,需要清空数据库并重新运行 migration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 09:11:18 -08:00
hailin 16f891b743 fix(authorization): include target-reaching tree in user's reward
修复达标时收益分配错误:达标的那一棵应该归被授权用户所有。

之前逻辑:目标10棵,当前0棵,本次种10棵
- remaining = 10 - 0 = 10
- 上级得到10棵,用户得到0棵 

修复后:
- remaining = max(0, 10 - 0 - 1) = 9(不包括达标那一棵)
- 上级得到9棵,用户得到1棵 

影响:社区、省团队、市团队、省区域、市区域

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 03:53:59 -08:00
hailin a54e9743ef fix(authorization): correctly distribute rewards when assessment target is exactly reached
修复当认种恰好达标时的收益分配错误:
- 之前:恰好达标时全部收益给上级/总部,被授权用户无法获得任何收益
- 现在:达标时的那一棵收益归被授权用户所有

影响的分配方法:
- getCommunityRewardDistribution (社区)
- getProvinceTeamRewardDistribution (省团队)
- getCityTeamRewardDistribution (市团队)
- getProvinceAreaRewardDistribution (省区域)
- getCityAreaRewardDistribution (市区域)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 03:19:09 -08:00
hailin f60d4eac87 feat(authorization): remove region matching requirement for team rewards
省团队(AUTH_PROVINCE_COMPANY)和市团队(AUTH_CITY_COMPANY)收益分配不再要求
认种者选择的省市与被授权用户的省市一致,只要在推荐链上有授权即可获得收益。

省区域(PROVINCE_COMPANY)和市区域(CITY_COMPANY)收益仍保持省市匹配要求。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 03:04:55 -08:00
hailin 4bf4efb1f4 feat(authorization): add assessment rules for province/city area roles
- Province area (PROVINCE_COMPANY): 50,000 trees initial target
- City area (CITY_COMPANY): 10,000 trees initial target
- Apply consistent assessment logic: pre-target rewards go to system account, post-target rewards go to company
- Auto-activate benefit when target is reached

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 21:57:00 -08:00
hailin 905725fc2d feat(authorization): add admin APIs for auth-province and auth-city company
- Add POST /admin/authorizations/auth-province-company for 省团队授权
- Add POST /admin/authorizations/auth-city-company for 市团队授权
- Add team uniqueness validation for all province/city authorization types
- Add domain events: AuthProvinceCompanyGrantedEvent, AuthCityCompanyGrantedEvent
- Add factory methods: createAuthProvinceCompanyByAdmin, createAuthCityCompanyByAdmin

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 21:46:44 -08:00
hailin 582828b8be fix(authorization): activate benefit when assessment target is exactly reached
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 <noreply@anthropic.com>
2025-12-11 20:29:15 -08:00
hailin 9819130f98 fix(authorization): use subordinate team count for assessment and auto-activate benefit
1. Assessment calculation now uses subordinate team count (excluding self planting)
   - Added selfPlantingCount to referral-service API response
   - Added subordinateTeamPlantingCount getter to TeamStatistics interface
   - Updated all assessment checks to use subordinateTeamPlantingCount

2. Auto-activate benefit when assessment target is reached
   - Added tryActivateBenefit helper method
   - Community, province team, and city team reward distribution methods
     now automatically activate benefit when target is reached

3. Fixed event consumer to support AUTHORIZED status (admin grants)
   - Previously only checked PENDING status for activation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 19:33:39 -08:00
hailin f94e7283d5 fix(authorization): fix race condition in reward distribution calculation
When calculating reward distribution for community/province/city benefits,
the totalTeamPlantingCount was being read after referral-service had already
updated it with the current planting. This caused incorrect distribution
where benefits were given to the community holder before they completed
their assessment target.

Fix: Subtract treeCount from rawTeamCount to restore the "before planting"
team count, ensuring correct assessment calculation.

Affected methods:
- getCommunityRewardDistribution
- getProvinceTeamRewardDistribution
- getCityTeamRewardDistribution

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 19:01:11 -08:00
hailin 9378bf7570 feat(authorization): add skipAssessment option to admin grant APIs
Admin grant APIs now default to requiring assessment (benefitActive=false).
Added optional skipAssessment parameter to bypass assessment when needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 17:48:49 -08:00
hailin 16d95999de feat(backend): implement assessment rules for reward distribution
Add proper assessment/考核 logic for all 5 benefit types:
- Community (80 USDT): 10-tree initial assessment, splits rewards between
  current community and parent/headquarters based on progress
- Province Team (20 USDT): 500-tree initial assessment for AUTH_PROVINCE_COMPANY
- Province Area (15 USDT + 1%): 50000-tree target for PROVINCE_COMPANY,
  routes to system account until target reached
- City Team (40 USDT): 100-tree initial assessment for AUTH_CITY_COMPANY
- City Area (35 USDT + 2%): 10000-tree target for CITY_COMPANY,
  routes to system account until target reached

Changes:
- authorization-service: Add 4 new distribution API endpoints and application
  service methods for province/city team/area reward distribution
- authorization-service: Add repository methods for querying authorizations
  including benefitActive=false records
- reward-service: Update client to call new distribution APIs
- reward-service: Modify calculation methods to return multiple reward entries
  based on assessment distribution plan

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-11 07:54:55 -08:00
hailin 6f46a8633f feat(reward): add internal APIs for reward distribution
- Add /referral/chain/{userId} API in referral-service for getting referral chain with hasPlanted status
- Add internal authorization APIs in authorization-service:
  - GET /authorization/nearest-community: find nearest community in referral chain
  - GET /authorization/nearest-province: find nearest province company in referral chain
  - GET /authorization/nearest-city: find nearest city company in referral chain
- Add repository methods for finding active authorizations by accountSequence
- Update reward-service client to use accountSequence parameter

These APIs enable reward-service to correctly distribute:
- 分享权益 (share benefit): to referrer with hasPlanted=true
- 社区权益 (community benefit): to nearest community leader
- 省团队权益 (province team benefit): to nearest province company
- 市团队权益 (city team benefit): to nearest city company

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 21:49:13 -08:00
hailin 9cf8b5305b feat(authorization): add community hierarchy API
- Add internal referral-chain API in referral-service for getting ancestor path and team members
- Extend ReferralServiceClient to call referral-chain API
- Add findActiveCommunityByAccountSequences repository method
- Add getCommunityHierarchy application service method
- Add GET /authorizations/my/community-hierarchy endpoint
- Update frontend with CommunityHierarchy model and getMyCommunityHierarchy method

API returns:
- myCommunity: user's own community authorization (if any)
- parentCommunity: nearest parent community (defaults to 总部社区 if none)
- childCommunities: nearest child communities in user's team

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 18:18:49 -08:00
hailin f8cfb5e597 feat(authorization): add admin API for community authorization
Add new endpoint POST /api/v1/admin/authorizations/community
that allows administrators to directly authorize users as community
managers without requiring the user to self-apply first.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 17:03:34 -08:00
hailin 034fb53674 refactor: use accountSequence as unified user identifier across all services
- planting-service: extract accountSequence from JWT, pass to referral-service
- referral-service: query by accountSequence instead of userId
- reward-service: add accountSequence field to schema and all layers
- wallet-service: prioritize accountSequence lookup over userId
- authorization-service: change userId from String to BigInt, add accountSequence

This change ensures consistent cross-service user identification using
accountSequence (8-digit unique business ID) instead of internal database IDs.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 13:55:03 -08:00
hailin 22c32031af feat(authorization): add community assessment progress to profile page
Backend:
- Add initialTargetTreeCount, currentTreeCount, monthlyTargetTreeCount
  fields to AuthorizationDTO and AuthorizationResponse
- Query TeamStatistics to populate current tree count in getUserAuthorizations

Frontend:
- Update AuthorizationResponse to parse new progress fields
- Replace hardcoded community assessment values with real API data
- Show authorization status: red (unauthorized), orange (pending), green (active)
- Display progress bar and target requirements based on benefit status

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 06:44:13 -08:00
hailin 781721a659 feat(withdrawal): implement withdrawal order and fund allocation system
- Add SystemAccount domain in authorization-service for managing regional/company accounts
- Implement fund allocation service in planting-service with multi-tier distribution
- Add WithdrawalOrder aggregate in wallet-service with full lifecycle management
- Create internal wallet controller for cross-service fund allocation
- Add Kafka event publishing for withdrawal requests
- Implement unit-of-work pattern for transactional consistency
- Update Prisma schemas with withdrawal order and system account tables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 02:35:27 -08:00
hailin 747e4ae8ef refactor(mpc-system): migrate to party-driven architecture with PartyID-based routing
- Remove Address field from PartyEndpoint (parties connect to router themselves)
- Update K8s Discovery to only manage PartyID and Role labels
- Add Party registration and SessionEvent protobuf definitions
- Implement PartyRegistry and SessionEventBroadcaster domain logic
- Add RegisterParty and SubscribeSessionEvents gRPC handlers
- Prepare infrastructure for party-driven MPC coordination

This is the first phase of migrating from coordinator-driven to party-driven
architecture following international MPC system design patterns.
2025-12-05 08:11:28 -08:00
Developer ea03df9059 feat(authorization-service): Implement complete authorization service with DDD architecture
## Features
- Province/City Company authorization (省代/市代授权)
- Community authorization (社区授权)
- Monthly assessment with ladder targets (月度阶梯考核)
- Team validation for referral chain conflicts (推荐链授权冲突检测)
- First place ranking rewards (区域第一名奖励)

## Architecture
- Domain Layer: Aggregates, Entities, Value Objects, Domain Events, Services
- Application Layer: Commands, Services, Schedulers
- Infrastructure Layer: Prisma ORM, Redis Cache, Kafka Events
- API Layer: Controllers, DTOs, Guards

## Testing
- Unit tests: 33 tests (aggregates, entities, value objects)
- Integration tests: 30 tests (domain services)
- E2E tests: 6 tests (API endpoints)
- Docker test environment with PostgreSQL, Redis, Kafka

## Documentation
- ARCHITECTURE.md: System design and DDD patterns
- API.md: REST API endpoints reference
- DEVELOPMENT.md: Development guide
- TESTING.md: Testing strategies and examples
- DEPLOYMENT.md: Docker/Kubernetes deployment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-01 06:30:07 -08:00