Commit Graph

1248 Commits

Author SHA1 Message Date
hailin 51114f265d fix(planting-service): 修复合同PDF签署日期显示为UTC时间的问题
合同生成时使用 new Date().toISOString().split('T')[0] 获取日期,
该方法返回UTC时间,导致北京时间凌晨签署的合同显示为前一天日期。

修复方案:新增 getBeijingDateString() 函数,将UTC时间转换为北京时间(UTC+8)

影响范围:仅影响PDF合同上显示的签署日期,不影响数据库时间戳或业务逻辑

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 11:42:16 -08:00
hailin 641612a5d0 fix(wallet-service): 修复提现订单查询使用 userId 的问题
将提现订单查询从 userId 改为使用 accountSequence:
- getWithdrawals: 使用 findByAccountSequence 替代 findByUserId
- getFiatWithdrawals: 使用 findByAccountSequence 替代 findByUserId
- 新增 withdrawal-order.repository 的 findByAccountSequence 方法

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 11:24:31 -08:00
hailin 217be89c43 fix(wallet-service): 修复流水查询使用 userId 导致记录丢失的问题
将所有流水查询从 userId 改为使用 accountSequence:
- getMyLedger: 使用 findByAccountSequence 替代 findByUserId
- getLedgerStatistics: 查询改为按 accountSequence
- getLedgerTrend: 查询改为按 accountSequence
- findByAccountSequence: 添加 HIDDEN_ENTRY_TYPES 过滤

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 11:16:04 -08:00
hailin 53df97839d fix(reporting-service): 修复 roleType 可能为 undefined 的类型错误
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 10:21:36 -08:00
hailin ee6a092a1a fix(authorization-service): 修复授权查询使用错误字段导致省市互斥验证失效
问题:数据库 user_id 列存储的是 accountSequence,但查询时使用 userId.value,
导致查询不到已有授权记录,省市互斥验证被绕过。

修复方法:所有基于 UserId 的查询改为使用 accountSequence 字段:
- findByUserIdAndRoleType
- findByUserIdRoleTypeAndRegion
- findByUserId
- findPendingByUserId
- findAllByUserIdIncludeDeleted

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 10:15:40 -08:00
hailin 347e5ce3de fix(reporting-service): 修复授权事件区域名称显示 undefined
不同授权事件使用不同的字段名:
- province 事件:provinceCode/provinceName
- city 事件:cityCode/cityName
- community 事件:communityName
- 通用:regionCode/regionName

现在正确处理所有变体,避免显示 "undefined undefined 完成授权"

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:51:11 -08:00
hailin 1676e82cc6 fix(admin-service): 认种汇总和分类账只显示已支付订单
过滤掉 CREATED、PROVINCE_CITY_CONFIRMED、CANCELLED 状态的订单,
只统计已支付及之后的订单(PAID, FUND_ALLOCATED, POOL_SCHEDULED, POOL_INJECTED, MINING_ENABLED)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:37:28 -08:00
hailin 2553d05902 chore(api-gateway): 提升速率限制100倍
- minute: 100 → 10000
- hour: 5000 → 500000

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 09:19:50 -08:00
hailin bc38ec6ec0 feat(wallet-service): 三层保护机制确保内部转账接收方钱包存在
新增三层保护机制:
1. 用户注册时:监听 identity.UserAccountCreated 事件自动创建钱包
2. 发起转账时:检测内部转账后调用 ensureWalletExists() 预创建钱包
3. 链上确认时:原有 upsert 逻辑兜底(保持不变)

新增文件:
- identity-event-consumer.service.ts: 消费 identity 用户注册事件
- user-account-created.handler.ts: 处理用户注册事件创建钱包

新增 API:
- POST /wallets/ensure-wallet: 确保单个钱包存在
- POST /wallets/ensure-wallets: 批量确保钱包存在

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 07:33:47 -08:00
hailin 68841abbf4 fix(reporting-service): 修复错误的 Kafka topic 订阅
- 充值事件:blockchain.deposit.credited → wallet.acks (过滤 wallet.deposit.credited)
- 权益事件:authorization.benefit.applied → 整合到 authorization-events (过滤 benefit.activated)

原来订阅的 topic 不存在,导致事件无法消费。现已修复为正确的 topic。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 06:01:08 -08:00
hailin 38fff077dd feat(reporting-service): 新增多种活动事件类型
扩展仪表板"最近活动"功能,新增以下活动类型:

活动类型新增:
- kyc_submitted: KYC认证提交
- kyc_approved: KYC认证通过
- kyc_rejected: KYC认证拒绝
- contract_signed: 合同签署
- deposit: 充值到账
- withdrawal: 提现成功
- benefit_applied: 权益申请

监听的 Kafka Topics:
- identity.KYCSubmitted
- identity.KYCApproved
- identity.KYCRejected
- contract.signed
- blockchain.deposit.credited
- wallet.withdrawals (仅处理 completed 事件)
- authorization.benefit.applied

所有新增事件处理器均使用幂等创建,防止重复记录。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:51:26 -08:00
hailin 65bd6a857f fix(reporting-service): 添加活动记录幂等性处理
问题:Kafka 消息重试或重复消费时,同一事件会被记录多次活动,
导致"最近活动"显示重复条目,统计数据也会被重复累加。

修复:
1. 仓储层新增 exists() 和 createIfNotExists() 方法
2. 所有事件消费者改用幂等创建,仅首次创建时累加统计
3. 添加数据库唯一约束 uk_sa_entity_activity 作为最后防线
4. 迁移脚本会自动清理历史重复数据

影响的事件:
- identity.UserAccountCreated
- identity.UserAccountAutoCreated
- authorization-events
- planting.order.paid
- reporting.report.generated

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:46:43 -08:00
hailin a86116fef4 fix(admin-service): 修复祖先节点数据获取依赖 user_query_view 的问题
问题:当祖先用户存在于 referral_query_view 但不存在于
user_query_view 时(CDC 同步延迟),祖先节点的
accountSequence 和统计数据无法正确获取。

修复:
- 改用 referralAccountSequences(从 referrals 获取)
  替代 userAccountSequences(从 users 获取)
- 确保即使用户基本信息未同步,仍能获取正确的认种统计

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:30:00 -08:00
hailin ca337bcdb7 fix(admin-service): 优先从 referralQueryView 获取祖先 accountSequence
修复祖先节点可能缺少 accountSequence 的问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:23:46 -08:00
hailin e2b2c17d38 feat(admin-web): 用户详情页引荐关系树优化
- 引荐关系节点显示团队认种量:本人认种 / 团队认种
- 无上级引荐人时显示"总部"节点
- 角色标签优化:社区权益→部门权益,区域→部门名称/城市名称
- 后端 ReferralNode 添加 teamAdoptionCount 字段

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 05:12:28 -08:00
hailin f55ac7e9cb feat(admin-web): 用户详情页显示权益考核记录
- 后端 admin-service 添加 getBenefitAssessments 查询方法
- 更新 AuthorizationDetailResponseDto 包含 benefitAssessments
- 前端用户详情页授权信息 Tab 新增权益考核记录表格
- 显示字段:考核月份、角色、区域、完成/需求、权益操作、
  权益状态变化、有效期至、结果
- 添加权益操作类型样式:已激活(绿)、已续期(蓝)、已停用(红)、无变化(灰)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 04:42:51 -08:00
hailin 178c484f04 feat(admin-service): 添加 BenefitAssessmentRecord CDC 同步
- 新增 BenefitAssessmentQueryView schema 和 migration
- 扩展 AuthorizationCdcConsumerService 处理 benefit_assessment_records 表
- 更新 Debezium authorization-connector 添加新表同步

CDC 同步字段:
- authorization_id, user_id, account_sequence
- role_type, region_code, region_name
- assessment_month, month_index
- monthly_target, cumulative_target
- trees_completed, trees_required
- benefit_action_taken, previous/new_benefit_status
- new_valid_until, result, remarks, assessed_at

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 04:22:37 -08:00
hailin 8f5b4df3d1 feat(authorization-service): 新增权益考核记录表 BenefitAssessmentRecord
新增独立的权益有效性考核记录表,与火柴人排名(MonthlyAssessment)分离:

Schema & Migration:
- 新增 BenefitAssessmentRecord 表存储权益考核历史
- 新增 BenefitActionType 枚举(ACTIVATED/RENEWED/DEACTIVATED/NO_CHANGE)
- 记录考核月份、目标、完成数、权益状态变化等信息

领域层:
- 新增 BenefitAssessmentRecord 聚合根
- 新增 IBenefitAssessmentRecordRepository 接口

应用层:
- 修改 processExpiredCommunityBenefits 保存考核记录
- 修改 processExpiredCityCompanyBenefits 保存考核记录
- 修改 processExpiredProvinceCompanyBenefits 保存考核记录
- 修改 processExpiredAuthCityBenefits 保存考核记录(新增,原无记录)
- 修改 processExpiredAuthProvinceBenefits 保存考核记录(新增,原无记录)

此改动 100% 不影响原有业务逻辑:
- 原有 MonthlyAssessment 表继续用于火柴人排名
- 仅在权益考核执行完成后追加保存记录到新表

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 04:15:07 -08:00
hailin d1e04152dc feat(admin-service): 实现团队本省/本市认种量实时统计
- getBatchUserStats 新增 provinceAdoptionCount 和 cityAdoptionCount
- 根据用户认种订单中的省市信息,统计团队成员同省/同市的认种量
- 百分比改为相对于该用户团队总认种量计算

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 23:07:33 -08:00
hailin 23994a23be feat(admin-service): 用户列表页使用实时统计数据
- 添加 getBatchUserStats 批量查询方法
- user.controller 注入 userDetailRepository
- listUsers 接口使用实时统计替代预计算字段

实时查询的字段:
- personalAdoptionCount: 个人认种量
- teamAddressCount: 团队地址数
- teamAdoptionCount: 团队认种量

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:56:07 -08:00
hailin 6a05150017 fix(admin-service): 用户详情页引荐人数改用实时查询
之前 directReferralCount 使用 CDC 同步的预计算字段(值为 0),
现在改为调用 getDirectReferralCount 实时查询

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:51:16 -08:00
hailin da5bb98cb7 fix(admin-service): 修复团队统计查询使用错误的 userId
user_query_view 和 referral_query_view 的 userId 不一致:
- user_query_view.user_id = 10 (identity-service CDC)
- referral_query_view.user_id = 25122700001 (referral-service CDC)

修复:
- getTeamStats 改为从 referralQueryView 获取 userId
- 直接用 accountSequence 查询团队认种量,避免再次关联

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:47:23 -08:00
hailin bab30dbeba refactor(admin-service): 团队认种量改用 PlantingOrderQueryView
统一使用 PlantingOrderQueryView 计算团队认种量,
与个人认种量保持一致的数据源,避免 CDC 同步不一致问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:42:30 -08:00
hailin 97bcaa2dfc fix(admin-service): 修复 referrerId 可能为 null 的 TypeScript 错误
- getAncestors 和 getDirectReferrals 中的 directReferralCounts
  groupBy 结果 referrerId 字段可能为 null
- 添加 filter 过滤 null 值,使用非空断言通过类型检查

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:34:17 -08:00
hailin d303cf076b fix(admin-service): 引荐关系树实时统计本人认种和直推数量
问题:
- 引荐节点的"本人认种"和"引荐"显示为0
- user_query_view.personal_adoption_count 和
  referral_query_view.direct_referral_count 没有被CDC更新

解决方案:
- getAncestors: 实时统计每个祖先的认种订单数和直推数
- getDirectReferrals: 实时统计每个下级的认种订单数和直推数
- getReferralTree API: 实时获取当前用户的统计数据
- 新增 getDirectReferralCount 方法

实时统计方式:
- 本人认种 = planting_order_query_view 中状态为 MINING_ENABLED 的订单数
- 直推数量 = referral_query_view 中 referrer_id 等于该用户的记录数

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 22:30:38 -08:00
hailin 2781ffccc1 fix(postgres): 增加 max_wal_senders 到 10 支持更多 CDC connector
- max_replication_slots: 4 -> 10
- max_wal_senders: 4 -> 10
- 修复 authorization-connector FAILED 的问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 21:53:25 -08:00
hailin 475acf71cc fix(admin-service): 修复钱包金额显示被除以10^8的问题
- decimalToString 改用 toString() 替代 toFixed(8)
- Prisma Decimal 的 toFixed 会导致精度错误
- 删除调试日志代码

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 21:46:29 -08:00
hailin 7176bbd5c2 feat(admin-service): 用户详情页统计数据改用真实数据
- 移除前端"活跃引荐"统计卡片
- 添加 getPersonalAdoptionCount 方法从 PlantingPositionQueryView 获取个人认种量
- 添加 getTeamStats 方法计算团队地址数和团队认种量
- 修改 getFullDetail 使用新方法获取真实统计数据
- 团队地址数通过 ancestorPath 查询所有下级用户
- 团队认种量汇总所有团队成员的 effectiveTreeCount

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 21:23:18 -08:00
hailin eccc637a02 fix(admin-service): 修复金额显示单位错误
移除错误的 1e8 乘除转换:
- 数据库存储的是实际金额 (Decimal(20,8)),不需要缩放
- decimalToBigint → decimalToString: 直接格式化为字符串
- 移除 controller 中不再需要的 formatDecimal 方法
- 更新接口类型: bigint → string (金额相关字段)

影响的接口:
- PlantingSummary.totalAmount
- PlantingLedgerItem.totalAmount
- WalletSummary 所有余额字段
- WalletLedgerItem.amount/balanceAfter
- SystemAccountLedger.amount/balanceAfter

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 21:15:28 -08:00
hailin 1c5fd9eaad fix(admin-service): 修复 BigInt 序列化错误
日志输出时不再使用 JSON.stringify 序列化包含 BigInt 的对象,
改为直接输出关键字段值,避免 "Do not know how to serialize a BigInt" 错误

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 21:03:41 -08:00
hailin 5f6ecf9670 fix(admin): 用户详情页 USDT 改为绿积分 + 添加调试日志
前端修改:
- 钱包汇总: USDT 可用/冻结 → 绿积分 可用/冻结
- 认种汇总: 总金额 (USDT) → 总金额 (绿积分)
- 资产类型标签: USDT → 绿积分

后端修改:
- UserDetailController: 添加认种/钱包查询日志
- UserDetailQueryRepositoryImpl: 添加数据库查询日志
- 日志包含 accountSequence、查询结果、数据条数等信息

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 20:53:30 -08:00
hailin f15bdeaef8 fix(admin-service): 用户详情查询改用 accountSequence
- 钱包/认种查询从 userId 改为 accountSequence 作为关联键
- 修复用户详情页钱包数据显示为0的问题
- accountSequence 是全局唯一业务标识,关联更可靠

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 20:43:36 -08:00
hailin b49776fadb fix(admin-service): 注册 CDC 消费者到 AppModule
CDC 数据无法同步的原因是消费者服务未在 AppModule 中注册。
添加以下 CDC 消费者:
- CdcConsumerService (identity 用户数据)
- ReferralCdcConsumerService (推荐关系)
- WalletCdcConsumerService (钱包账户和流水)
- PlantingCdcConsumerService (认种订单和持仓)
- AuthorizationCdcConsumerService (授权角色和考核)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 20:20:54 -08:00
hailin 3d31e8beb9 feat(admin): 实现用户详情页面
前端 (admin-web):
- 新增用户详情页面 /users/[id]
- 实现推荐关系树可视化,支持点击节点切换视角
- 添加认种分类账Tab,显示汇总和订单明细
- 添加钱包分类账Tab,显示余额汇总和流水明细
- 添加授权信息Tab,显示角色、月度考核和系统账户流水
- 用户列表"查看详情"改为 Link 导航到详情页

后端 (admin-service):
- 新增 UserDetailController 提供详情页API
- 新增 UserDetailQueryRepository 查询CDC同步的数据
- API: GET /admin/users/:seq/full-detail
- API: GET /admin/users/:seq/referral-tree
- API: GET /admin/users/:seq/planting-ledger
- API: GET /admin/users/:seq/wallet-ledger
- API: GET /admin/users/:seq/authorization-detail

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 20:10:01 -08:00
hailin 83f84b9d7c feat(admin-service): 添加 CDC 分类账流水同步
新增 wallet/planting/authorization 服务的 CDC 数据同步:

状态表同步:
- WalletAccountQueryView: 钱包账户余额状态
- WithdrawalOrderQueryView: 提现订单状态
- FiatWithdrawalOrderQueryView: 法币提现订单
- PlantingOrderQueryView: 认种订单状态
- PlantingPositionQueryView: 持仓状态
- ContractSigningTaskQueryView: 合同签约任务
- AuthorizationRoleQueryView: 授权角色
- MonthlyAssessmentQueryView: 月度考核
- SystemAccountQueryView: 系统账户余额

分类账流水同步:
- WalletLedgerEntryView: 钱包流水分类账
- FundAllocationView: 认种资金分配记录
- SystemAccountLedgerView: 系统账户流水

其他:
- Debezium Connect 端口改为 8084 避免冲突
- 更新连接器配置添加流水表

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 19:29:27 -08:00
hailin c4cec836d9 feat(admin-service): 添加 referral-service CDC 数据同步
- 新增 ReferralQueryView schema 和 migration
- 新增 ReferralCdcConsumerService 消费推荐关系变更
- 配置 referral-postgres-connector 用于 Debezium CDC
- 更新 deploy.sh 自动注册 referral connector
- 更新 init-databases.sh 配置 rwa_referral 逻辑复制权限

CDC 同步的字段:
- user_id, account_sequence, referrer_id
- my_referral_code, used_referral_code
- ancestor_path, depth
- direct_referral_count, active_direct_count

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 18:57:58 -08:00
hailin 6b55b69d0d fix(leaderboard-service): 修复健康检查 API 路径
将 Dockerfile 和 docker-compose.yml 中的健康检查路径从
/api/health 修改为 /api/v1/health,与实际 API 路由保持一致

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 18:48:34 -08:00
hailin 7d3483b565 fix(referral-service): 修复 Kafka 消费异常被吞掉的问题
- kafka.service.ts: 抛出异常让 KafkaJS 触发重试
- user-registered.handler.ts: 传播异常到 KafkaService

修复前处理失败的消息不会重试,导致推荐关系可能丢失

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 18:47:05 -08:00
hailin b5ebf8a615 feat(admin-service): 实现 Debezium CDC 数据同步
- 新增 CdcConsumerService 消费 PostgreSQL WAL 变更事件
- 配置 Debezium Connect 服务和 PostgreSQL 逻辑复制
- 更新 deploy.sh 支持 Debezium 启动和连接器管理
- 新增 identity-postgres-connector 配置同步 user_accounts 表
- 保留原有 Outbox 机制用于业务领域事件

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 18:35:53 -08:00
hailin 84aa8181a9 fix(reporting-service): 兼容 referral-service 的认种事件格式
- planting.order.paid 事件现在由 referral-service 发送
- 消息格式为 { eventName, data: {...} },与原 planting-service 格式不同
- 添加兼容逻辑,同时支持两种格式
- 修复今日认种统计为0的问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 06:58:33 -08:00
hailin c7c793f128 fix(reporting-service): 账户余额改为 累计收入 - 累计转出
- 所有固定账户:账户余额 = 累计收入 - 累计转出
- 总部储蓄(HQ_COMMUNITY):累计收入 = ledger收入 + 过期收益
- 统一计算公式,确保数据一致性

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 06:41:28 -08:00
hailin 842bc42579 fix(reporting-service): 总部储蓄账户余额也需累加过期收益
- 账户余额改为 usdtBalance + expiredRewardsTotal
- 与累计收入的计算方式保持一致
- 过期的分享权益会进入 S0000000001,余额和收入都应包含

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 06:40:20 -08:00
hailin a719294dda fix(blockchain-service): 添加系统账户转出事件主题订阅
- 消费者添加订阅 wallet.system-withdrawals 主题
- 解决系统账户转出订单一直处于 FROZEN 状态的问题
- 事件现在可以被 blockchain-service 消费并处理链上转账

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 06:17:57 -08:00
hailin c22ce4ecc4 fix(reporting-service): 将过期收益累加到总部储蓄账户统计
- 修改 assembleFixedAccounts 方法接受过期收益总额参数
- 将过期分享收益累加到 HQ_COMMUNITY (S0000000001) 的累计收入中
- 添加日志记录累加过程

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:53:51 -08:00
hailin db833fdf45 fix(wallet-service): 修复系统划转请求 DTO 验证错误
- 为 SystemWithdrawalRequestDTO 添加 class-validator 装饰器
- 添加 @ApiProperty 装饰器用于 Swagger 文档
- 使用 @Type(() => Number) 自动转换 amount 类型
- 简化验证逻辑,移除冗余的手动验证

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:52:36 -08:00
hailin 4f2f808484 feat(wallet-service): 实现 Outbox Pattern 保证系统划转事件发布的可靠性
实现内容:
- 添加 OutboxEvent 模型到 schema.prisma
- 创建 OutboxRepository 服务处理事件持久化
- 创建 OutboxPublisherService 后台轮询发布事件到 Kafka
- 修改 SystemWithdrawalApplicationService 将事件写入事务内
- 添加数据库迁移文件创建 outbox_events 表

技术细节:
- 业务数据和事件数据在同一个数据库事务中写入
- 后台任务每秒轮询 outbox_events 表,发布 PENDING 状态事件
- 事件发布后标记为 SENT,等待消费方确认后标记为 CONFIRMED
- 超时未确认的事件自动重试(指数退避策略)
- 保证事件不丢失,即使 Kafka 暂时不可用

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 05:15:07 -08:00
hailin d16ad81d62 fix(wallet-service): 完善系统账户转出分类账memo信息
- memo 格式更新为包含完整信息:
  - 接收方账户ID
  - 接收方姓名
  - 接收方钱包地址(缩略显示)
  - 操作员姓名/ID
  - 备注(如有)
- payloadJson 新增 toAddress 字段存储完整地址

示例: "转账至 D25010100001 (张三) | 地址: 0x1234...5678 | 操作员: 管理员A | 备注: 奖励发放"

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:52:00 -08:00
hailin 6350b36e1a feat(reporting, admin-web): 添加省/市区域账户累计转出统计
- 后端 reporting-service: RegionAccountInfo 和汇总接口添加 totalTransferred 字段
- 后端 wallet-service client: 更新 AllSystemAccountsResponse 类型定义
- 前端 admin-web: SystemAccountsTab 组件显示累计转出列
- 前端类型: RegionAccountsSummary 添加 totalTransferred 字段

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:45:56 -08:00
hailin 27e64819b7 feat(wallet-service): 省/市区域账户增加累计转出字段
- provinceAccounts 和 cityAccounts 返回结构增加 totalTransferred 字段
- 完善分类账统计,与固定系统账户保持一致

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:39:47 -08:00
hailin 78fa354117 fix(wallet-service): 修复系统账户余额统计不一致问题
- 账户余额改为 usdtAvailable + settleableUsdt,与累计收入统计保持一致
- 解决社区权益进入 settleableUsdt 导致的余额与累计收入不匹配问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 04:15:42 -08:00
hailin 5c7cb616a7 feat(wallet-service): 添加运营1和积分股池到系统划转账户列表
- 添加 S0000000002 (运营1) 和 S0000000004 (积分股池) 到允许转出白名单
- 更新系统账户名称映射与前端保持一致
- 为 S0000000006 手续费归集账户添加兼容逻辑,当余额为0时从提现订单表统计历史手续费
- 优化过期奖励处理,按分配类型分别记录流水便于明细查看

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 03:44:46 -08:00
hailin fa7b45ec2f fix(wallet-service, admin-web): 修复系统账户划转金额类型问题
- wallet-service: 支持 amount 为字符串或数字类型,添加类型转换
- admin-web: 改进错误处理,正确提取 Axios 错误消息

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-07 03:01:52 -08:00
hailin eb40b658f6 revert(wallet-service): 回滚 fixedAccountTypes 映射修改
撤销错误的账户类型映射修改,恢复原始映射:
- S0000000001 → HQ_COMMUNITY
- S0000000002 → COST_ACCOUNT
- S0000000003 → OPERATION_ACCOUNT

修改后端映射会影响 reward-service、authorization-service 等多个服务。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 23:22:22 -08:00
hailin d28723f141 fix(wallet-service): 修正固定账户类型映射顺序
修复 getAllSystemAccounts 中 fixedAccountTypes 映射错误:
- S0000000001 应为 COST_ACCOUNT (运营1),而非 HQ_COMMUNITY
- S0000000002 应为 OPERATION_ACCOUNT (运营2),而非 COST_ACCOUNT
- S0000000003 应为 HQ_COMMUNITY (总部储蓄),而非 OPERATION_ACCOUNT

此修复确保固定账户的余额、收入和分类账明细正确对应。
同时移除前端调试日志。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 23:20:41 -08:00
hailin 7744abf57d fix(reporting-service): 修复 DashboardController 的依赖注入问题
在 ApiModule 中导入 RedisModule,使 HotWalletBalanceCacheService
可以被 DashboardController 注入使用。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 23:12:24 -08:00
hailin 8dba325499 feat(dashboard): 添加热钱包余额实时显示(公共账户/因子)
- blockchain-service: 扩展调度器同时缓存 dUSDT 和 KAVA 原生代币余额到 Redis
  - Redis Key: hot_wallet:dusdt_balance:KAVA, hot_wallet:native_balance:KAVA
  - 每5秒更新,TTL 30秒

- reporting-service: 添加热钱包余额读取服务和 API
  - 新增 HotWalletBalanceCacheService 从 Redis 读取缓存
  - 新增 GET /v1/dashboard/hot-wallet-balance 接口

- admin-web: 仪表板添加热钱包余额显示
  - 公共账户显示 dUSDT 余额
  - 因子显示 KAVA 原生代币余额
  - 每15秒自动刷新

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 23:04:21 -08:00
hailin 95cb3510aa fix(reward-service): 修复 getExpiredRewardsEntries 的 userId 类型转换
将 bigint 类型的 userId 转换为 number 类型以匹配返回类型定义

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 22:38:50 -08:00
hailin e9c0196d68 feat(admin-web): 添加过期收益明细查询功能
- reward-service: 添加 getExpiredRewardsEntries API 查询过期收益明细
- reporting-service: 添加过期收益明细转发接口和类型定义
- admin-web: 过期收益统计区域新增"查看明细"按钮
  - 支持分页浏览过期收益记录
  - 支持按权益类型筛选
  - 显示过期时间、用户ID、账户、权益类型、金额、订单号

回滚方式:删除各服务中标注 [2026-01-07] 的代码块

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 22:36:31 -08:00
hailin 8c29603f5a fix(reporting-service): use field-level @unique for statsDate in schema
Root cause: @@unique([field], name: "xxx") requires { xxx: { field } } syntax
in findUnique/upsert, but code used { field } directly.

Fix: Change to @unique(map: "uk_realtime_stats_date") on the field itself.
This keeps the same database index name while allowing { statsDate } syntax.

No migration needed - only Prisma client type generation changes.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:38:13 -08:00
hailin 4e201d3a66 fix(reporting-service): use findFirst + update instead of upsert for realtimeStats
Replace upsert with findFirst + create/update pattern to avoid Prisma
unique constraint syntax issues. The @@unique constraint with a custom
name doesn't allow direct field-based queries in findUnique/upsert.

This approach maintains the same behavior without schema changes.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:36:26 -08:00
hailin ce1d342269 fix(reporting-service): use named unique constraint for realtimeStats queries
Prisma requires using the named unique constraint (uk_realtime_stats_date)
in where clauses for findUnique and upsert operations. This fixes the
PrismaClientValidationError that was occurring when processing planting
order events.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:25:24 -08:00
hailin d400290652 fix(reporting-service): 修复统计 incrementPlanting 对 undefined 参数的处理
当 planting.order.paid 事件中 treeCount 为 undefined 时:
- GlobalStatsRepository: 使用 ?? 0 提供默认值
- RealtimeStatsRepository: 使用 ?? 0 提供默认值
- 避免 Prisma upsert 因 undefined increment 值而报错

问题原因:planting-service 发送的事件数据中 treeCount 可能为 undefined

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:18:26 -08:00
hailin 272b4ffdbf feat(wallet-service): 添加手续费归集统计的历史数据兼容
当 FEE_COLLECTION 流水为空时,自动从提现订单表查询历史手续费:
- getFeeCollectionSummary: 从 withdrawal_orders 和 fiat_withdrawal_orders 聚合统计
- getFeeCollectionEntries: 从两个订单表查询明细列表,支持分页和类型筛选
- 按月统计使用 UNION ALL 合并两种提现订单数据
- 明细记录添加备注说明区分来源(区块链/法币)

回滚方式:删除 fallback 代码块和两个私有方法

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:11:37 -08:00
hailin 4dcdfb8a3c fix(wallet/reporting): 修复手续费归集统计 API 的数据库表名和响应解包问题
- wallet-service: 修复 getFeeCollectionSummary 中原生 SQL 使用错误表名
  - 将 ledger_entries 改为 wallet_ledger_entries(Prisma 映射表名)
- reporting-service: 修复 getFeeCollectionSummary/Entries 响应解包
  - wallet-service 返回 { success, data, timestamp } 格式需要解包 data

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 21:04:02 -08:00
hailin 4e5d9685a1 feat(admin-web): 添加面对面结算明细列表功能
- wallet-service: 新增 getOfflineSettlementEntries 方法和 API
- reporting-service: 新增客户端方法和 API 转发
- admin-web: 添加明细列表组件和样式,支持展开/收起

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 20:40:12 -08:00
hailin 9953f0eee5 fix(reporting-service): 修复面对面结算数据解包问题
wallet-service 返回 { success, data, timestamp } 包装格式,
getOfflineSettlementSummary 需要用 response.data.data 解包才能获取真正的数据。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 20:23:54 -08:00
hailin 4df9895863 feat(admin-web): 完善系统账户报表收益统计显示
- 分享引荐收益汇总:显示所有状态(PENDING/SETTLEABLE/SETTLED/EXPIRED)的完整数据
- 面对面结算:改为从 wallet_ledger_entries 表查询 SPECIAL_DEDUCTION 类型
- 新增按状态分组统计表格和详细分类卡片

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 20:11:09 -08:00
hailin 2c8263754f fix(wallet-service): fix system-withdrawal API route prefix to match Kong gateway
Changed controller route from 'system-withdrawal' to 'wallets/system-withdrawal'
to align with Kong's /api/v1/wallets/* routing

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:53:54 -08:00
hailin 305514b246 feat(admin-web): 仪表板改用 planting-service 源数据
统计卡片和趋势图不再使用 reporting-service,直接使用 planting-service 的源数据:

- 统计卡片:总认种量、总订单数、今日认种、本月认种
- 趋势图:支持 7天/30天/90天 切换
- 新增 usePlantingTrendForDashboard hook

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:47:44 -08:00
hailin fe8e9a9bb6 fix(planting-service): 修复趋势数据查询表名错误
表名应为 planting_orders(复数),不是 planting_order

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:26:36 -08:00
hailin 64bd82b77b feat(wallet/blockchain/identity): implement system account withdrawal feature
- Add SystemWithdrawalApplicationService to handle system account transfers
- Add SystemWithdrawalController with endpoints for request, query, and account listing
- Add SystemWithdrawalStatusHandler to process blockchain confirmation/failure events
- Add SystemWithdrawalRequestedHandler in blockchain-service to execute ERC20 transfers
- Add getUserByAccountSequence endpoint in identity-service for user lookup
- Support dynamic memo generation based on actual source account name
- Dual-sided ledger entries for system account transfers

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:22:15 -08:00
hailin fa1931b3b6 feat(planting-service, admin-web): 实现认种趋势图表功能
后端变更 (planting-service):
- 添加 getTrendData API 接口支持按时间维度(日/周/月/季度/年)查询趋势数据
- 添加 TrendPeriod 类型和 TrendDataPoint 接口
- 实现 repository 层的趋势数据聚合查询

前端变更 (admin-web):
- 添加趋势数据 API 端点和类型定义
- 使用 recharts 实现折线图展示认种棵数和订单数趋势
- 支持日/周/月/季度/年度时间维度切换
- 添加加载状态、错误状态和空数据状态处理

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:21:11 -08:00
hailin 4f3660f05e feat(statistics): 恢复榴莲树认种数量趋势图表
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:01:37 -08:00
hailin 24bcc45d5a refactor(statistics): 删除认种统计页面不相关的mock功能
删除以下mock数据和功能:
- 榴莲树认种数量趋势图表
- 龙虎榜与排名统计
- 区域认种数据统计
- 省/市公司运营统计
- 收益明细与来源

保留核心认种统计:
- 榴莲树认种总量(含积分)
- 今日认种数量(含积分)
- 本月认种数量(含积分)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 10:00:50 -08:00
hailin 36a83397a8 revert: 撤销对 authorization/identity/reporting 服务的修改
这些服务不需要同步手续费账户的定义,wallet-service 独立处理。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:48:42 -08:00
hailin 2be9a2d9c2 feat(statistics): 认种统计改为真实数据并显示积分
后端变更(planting-service):
- 添加 getMonthStats() 方法获取本月认种统计
- 更新 GlobalStatsResult 接口添加 monthStats 字段
- 添加 MonthStatsDto 响应类型

前端变更(admin-web):
- 更新 PlantingGlobalStats 类型定义
- statistics 页面调用真实 API 获取认种统计
- 显示认种总量、今日、本月的棵数和积分

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:36:46 -08:00
hailin 898521d236 fix: 同步手续费归集账户到所有相关服务
- identity-service: seed.ts 添加 S0000000005 和 S0000000006
- authorization-service: 枚举添加 SHARE_RIGHT_POOL 和 FEE_COLLECTION
- authorization-service: 初始化固定账户列表添加新账户
- reporting-service: 修复账户类型映射 (PLATFORM_FEE -> FEE_COLLECTION)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:30:45 -08:00
hailin 84fb6b8500 fix(reward-service): 修复字段名错误 sourceOrderId → sourceOrderNo
数据库中的字段名是 sourceOrderNo,修复 getRewardEntriesByType 和
getFeeEntriesDetailed 方法中的字段映射错误。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:27:25 -08:00
hailin 4b5270f130 feat(admin-web): 添加系统账户收益类型详细明细列表功能
为系统账户报表中的5个收益类型汇总Tab添加详细明细查看功能:
- 手续费账户汇总:点击"查看详细明细"展开手续费记录列表
- 省团队收益汇总:展开省团队权益记录列表
- 市团队收益汇总:展开市团队权益记录列表
- 分享引荐收益汇总:展开分享权益记录列表
- 社区收益汇总:展开社区权益记录列表

后端变更:
- reward-service: 添加 getRewardEntriesByType、getFeeEntriesDetailed 方法
- reward-service: 添加 /statistics/reward-entries-by-type、/statistics/fee-entries-detailed 接口
- reporting-service: 添加对应的聚合接口

前端变更:
- 添加 RewardEntryDTO、RewardEntriesResponse 类型定义
- 添加 getRewardEntriesByType、getFeeEntriesDetailed API 方法
- FeeAccountSection、RewardTypeSummarySection 组件添加详细明细列表展开功能
- 添加分页支持(每页20条)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:19:15 -08:00
hailin 283553a474 fix(wallet-service): 统一系统账户 seed migration
- 将 S0000000005 和 S0000000006 添加到初始 seed migration
- 简化 S0000000006 migration 格式与其他账户保持一致
- 新环境初始化时所有系统账户一次性创建

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:12:17 -08:00
hailin b9911ab460 feat(wallet-service): 实现手续费归集账户功能
- 新增系统账户 S0000000006 (user_id=-6) 用于归集提现手续费
- 新增 FEE_COLLECTION 流水类型记录手续费归集
- 区块链提现完成时使用 UnitOfWork 事务归集手续费
- 法币提现完成时在事务中归集手续费
- WithdrawalOrderRepository 添加事务支持
- 所有手续费归集操作使用乐观锁保护

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 09:10:41 -08:00
hailin 99b725db0a feat(admin-web): 添加系统账户收益类型汇总统计功能
在数据统计-系统账户中新增5个统计Tab:
- 手续费账户汇总:统计成本费、运营费、总部社区基础费、RWAD底池注入
- 省团队收益汇总:统计省团队权益收益
- 市团队收益汇总:统计市团队权益收益
- 分享引荐收益汇总:统计分享权益收益
- 社区收益汇总:统计社区权益收益

后端变更:
- reward-service: 添加 getRewardsSummaryByType、getAllRewardTypeSummaries 方法
- reporting-service: 聚合收益类型汇总统计接口

前端变更:
- 添加 RewardTypeSummary、FeeAccountSummary 类型定义
- 添加 getRewardTypeSummaries API 方法
- 添加 FeeAccountSection、RewardTypeSummarySection 组件

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 08:54:35 -08:00
hailin bbafe58e86 fix(wallet-service): update init migration memo column to TEXT
Ensure new database installations use TEXT type for memo column from the start.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 08:30:07 -08:00
hailin 069c549bc4 feat(wallet-service): add migration for memo column type change to TEXT
Change wallet_ledger_entries.memo from VARCHAR(500) to TEXT to support longer settlement memos.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 08:27:12 -08:00
hailin bf1c8d2228 feat(wallet-service): 实现 Unit of Work 模式保证 settleToBalance 事务原子性
- 新增 UnitOfWork 接口和实现,使用 Prisma Interactive Transaction
- 修改 IWalletAccountRepository 和 ILedgerEntryRepository 接口支持可选事务参数
- 修改仓库实现,支持在事务中执行数据库操作
- 修改 settleToBalance 方法使用 UnitOfWork,确保钱包更新和流水记录原子性
- 注册 UnitOfWorkService 到 InfrastructureModule

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 07:50:02 -08:00
hailin 7dc25b75d2 revert: 回滚 settleToBalance 的直接 Prisma 实现,准备用 Unit of Work 模式重新实现 2026-01-06 07:07:27 -08:00
hailin 4c6e64a604 fix(wallet-service): settleToBalance 添加乐观锁防止并发冲突 2026-01-06 06:56:50 -08:00
hailin 65cb574f59 fix(wallet-service): 添加钱包状态检查,确保只有 ACTIVE 钱包可结算 2026-01-06 06:50:08 -08:00
hailin 5204d24c88 fix(wallet-service): 修复 settleToBalance 方法缺少事务保护的严重 Bug
问题原因:
settleToBalance 方法先执行 wallet.save() 更新账户余额,再执行
ledgerRepo.save() 写入流水记录。两个操作不在同一个事务中。

当流水写入失败时(如 memo 字段超过 VarChar(500) 限制),账户余额
已经被修改,但流水记录未写入,导致数据不一致。

具体案例:
用户 D25122700023 点击结算时,memo 内容超长(66笔奖励详情),
wallet-service 先把 settleable_usdt 转入 usdt_available,然后
写流水失败。账户余额被改但没有对应流水。

修复内容:
1. settleToBalance: 使用 prisma.$transaction 确保原子性
   - 账户余额更新和流水记录在同一事务中
   - 任一操作失败整个事务回滚
2. schema: memo 字段从 VarChar(500) 改为 Text 类型,无长度限制

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 06:40:09 -08:00
hailin 573e58c89b fix(wallet-service): 统一奖励分配到 settleable_usdt,与 reward-service 保持一致
问题原因:
wallet-service 对不同类型奖励的分配方式不一致:
- SHARE_RIGHT: 正确使用 addSettleableReward() → settleable_usdt
- CITY_TEAM_RIGHT/COMMUNITY_RIGHT: 错误使用 addAvailableBalance() → usdt_available

这导致 reward-service 记录的 SETTLEABLE 奖励总额与 wallet-service 的
settleable_usdt 字段不匹配。用户 D25122700024 的案例中:
- reward-service: 3条奖励共 4464 USDT (SHARE_RIGHT 3600 + CITY_TEAM_RIGHT 288 + COMMUNITY_RIGHT 576)
- wallet-service: settleable_usdt = 3600 (仅 SHARE_RIGHT)
差额 864 USDT 被错误地放入了 usdt_available

修复内容:
1. allocateCommunityRight: 改用 addSettleableReward() 替代 addAvailableBalance()
2. allocateToRegionAccount: 改用 addSettleableReward() 替代 addAvailableBalance()
3. 流水类型统一使用 REWARD_TO_SETTLEABLE 替代 SYSTEM_ALLOCATION
4. 日志和备注更新以反映新的分配方式

设计原则:
- reward-service 是奖励的权威来源
- wallet-service 应跟随 reward-service 的设计
- 所有奖励都应进入 settleable_usdt,用户主动结算后才转入 usdt_available

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 03:49:31 -08:00
hailin ec71121907 fix(reward-service): 修复 WalletServiceClient 未正确解析 wallet-service 响应格式的 Bug
问题原因:
wallet-service 使用全局 TransformInterceptor 拦截器,会将所有响应包装成:
{ success: true, data: { success: boolean, ... }, timestamp: "..." }

原代码直接读取外层的 success 字段(始终为 true),导致即使业务失败
(内层 data.success = false)也被误判为成功。

具体案例:
用户 D25122700024 点击结算时,wallet-service 因余额不足返回:
{ success: true, data: { success: false, error: "Insufficient..." }, ... }
reward-service 误读为成功,导致奖励被标记为 SETTLED 但钱包余额未变更。

修复内容:
1. settleToBalance: 解析 response_data.data 获取真实业务结果
2. confirmPlantingDeduction: 同上
3. allocateFunds: 同上

所有方法现在会:
- 使用 response_data.data || response_data 兼容包装和非包装格式
- 严格检查 data.success !== true 来判断业务是否成功
- 失败时记录详细错误日志

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-06 03:38:00 -08:00
hailin 8b80e45524 fix(authorization): 火柴人排名过滤已撤销授权的考核记录
- findRankingsByMonthAndRegion 和 findRankingsByMonthAndRoleType 增加过滤条件
- 排除 authorization.status = 'REVOKED' 的记录
- 解决同一用户因有多条授权记录(含已撤销)而重复显示的问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 19:55:23 -08:00
hailin 6c78e22000 fix(authorization): 添加火柴人排名调试日志
添加详细日志显示返回的每条记录的区域信息,便于调试过滤问题。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 06:23:57 -08:00
hailin bdc6ba524f fix(authorization): 火柴人排名改为按区域过滤
修改排名逻辑,只显示获得相同省/市公司授权的用户排名。

- 后端 getStickmanRanking 改用 findRankingsByMonthAndRegion
- 简化实时创建评估逻辑,只为当前区域创建
- 更新前端注释说明

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 05:56:30 -08:00
hailin 3b3342de5c feat(wallet-service): 添加内部转账入账修复脚本
新增一次性修复脚本用于补录因接收方钱包未创建导致入账失败的内部转账。

脚本特性:
- DRY_RUN 模式:默认只检查不执行,需手动改为 false 才真正修复
- 完整验证:订单状态、类型、接收方信息、txHash
- 幂等性检查:确认接收方没有 TRANSFER_IN 流水
- 转出方验证:确认转出方有 TRANSFER_OUT 流水(已扣款)
- 乐观锁:使用 version 字段防止并发修改
- 审计追踪:payloadJson.dataFix=true 标记修复操作
- 详细日志:每步操作都有时间戳和日志级别

使用方法:
1. 在 wallet-service 容器内执行 DRY_RUN 检查
2. 确认无误后将 DRY_RUN 改为 false 再次执行

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 05:06:27 -08:00
hailin ac0e73afac feat(wallet/blockchain): 热钱包余额预检查及接收方钱包自动创建
1. blockchain-service: 新增热钱包 dUSDT 余额定时更新调度器
   - 每 5 秒查询热钱包在 KAVA 链上的 dUSDT 余额
   - 更新到 Redis DB 0,key 格式: hot_wallet:dusdt_balance:{chainType}
   - TTL 30 秒,服务故障时缓存自动过期

2. wallet-service: 新增热钱包余额缓存服务
   - 从 Redis DB 0 读取热钱包余额缓存
   - 严格模式:无法获取余额或余额不足时拒绝转账
   - 提示信息:"财务系统审计中,请稍后再试"

3. wallet-service: 转账确认时自动创建接收方钱包
   - 解决接收方钱包不存在导致入账失败的问题
   - 使用 upsert 避免并发创建冲突
   - 在同一事务中完成创建和入账

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 04:31:52 -08:00
hailin 66ace25935 fix(reporting): remove userId dependency in planting.order.paid handler
- Change userId to optional in PlantingOrderPaidEvent interface
- Add accountSequence field for user identification
- Remove relatedUserId from activity creation (was causing BigInt error)
- Store accountSequence in metadata instead

Fixes: TypeError: Cannot convert undefined to a BigInt

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-05 00:05:56 -08:00
hailin c3c15b7880 fix(wallet-service): remove invalid nested $queryRaw in getOfflineSettlementSummary
删除使用嵌套 $queryRaw 进行条件拼接的错误查询,保留简化版本。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:37:57 -08:00
hailin 49cdeb4aef fix(reporting-service): fix planting.order.paid event message format
planting-service 发送的消息是直接数据格式,不包含 payload 包装,
修正 ActivityEventConsumerController 以适配实际消息格式。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:32:32 -08:00
hailin 229dff1a9d feat(system-accounts): add ledger detail API for all system accounts
新增所有系统账户的分类账明细查询功能:
- wallet-service: 添加 getSystemAccountLedger 和 getAllSystemAccountsLedger 方法
- wallet-service: 添加 /statistics/system-account-ledger 和 /statistics/all-system-accounts-ledger API
- reporting-service: 添加 /all-ledger 端点透传分类账数据

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:30:38 -08:00
hailin 56f2fd206d fix(reporting-service): extract data from wrapped API response
wallet-service API 返回 { success, data } 格式,需要解析 response.data.data

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:20:38 -08:00
hailin 6d5c5f7e4c fix(reporting-service): add /api/v1 prefix to wallet and reward service API calls
修复 reporting-service 调用 wallet-service 和 reward-service 时的 404 错误,
所有内部 HTTP 调用路径添加 /api/v1 全局前缀。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:18:10 -08:00
hailin 838d5c1d3b feat(reporting): fix system account report to use wallet-service data
The system account balances were showing 0 because data was being fetched
from authorization-service.system_accounts table instead of the actual
wallet-service.wallet_accounts table where funds are stored.

Changes:
- wallet-service: Add getAllSystemAccounts() method to query all system
  accounts (fixed S*, province 9*, city 8*) with actual balances
- wallet-service: Add /wallets/statistics/all-system-accounts API endpoint
- reporting-service: Update SystemAccountReportApplicationService to fetch
  data from wallet-service instead of authorization-service
- reporting-service: Fix default service URLs to use correct container names
  and ports (rwa-wallet-service:3001, rwa-reward-service:3005)
- docker-compose: Add WALLET_SERVICE_URL and REWARD_SERVICE_URL env vars
  for reporting-service

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 23:10:20 -08:00
hailin 1c4def2867 feat(kong): add system-account-reports route to reporting-service
Add Kong route for the new system account reports API endpoint
at /api/v1/system-account-reports, forwarding to reporting-service.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 22:27:55 -08:00
hailin e95316c5f4 fix(authorization-service): register SystemAccountApplicationService in AppModule
Add missing dependency injection for SystemAccountApplicationService
which is required by InternalAuthorizationController for system account
report statistics API.

- Import SystemAccountRepositoryImpl and SYSTEM_ACCOUNT_REPOSITORY
- Register SystemAccountApplicationService as provider
- Register SYSTEM_ACCOUNT_REPOSITORY with SystemAccountRepositoryImpl

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 22:22:02 -08:00
hailin 6e395ce58c feat(reporting): add system account report aggregation feature
## Changes
- Add system account report aggregation APIs in reporting-service
- Add internal statistics APIs in wallet-service, reward-service, authorization-service
- Add system accounts tab in admin-web statistics page
- Enhanced metadata in reward entries for traceability

## Backend Changes
- wallet-service: Add offline settlement summary and system accounts balances APIs
- reward-service: Add expired rewards summary API
- authorization-service: Add fixed accounts list, region accounts summary APIs
- reporting-service: Add HTTP clients and aggregation service for system account reports

## Frontend Changes
- admin-web: Add SystemAccountsTab component with fixed accounts, region summaries,
  offline settlement stats, and expired rewards display

## Rollback Instructions
Each file includes rollback comments with [2026-01-04] tag marking new additions.
To rollback: delete files marked as new, remove code sections marked with date comments.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 22:06:58 -08:00
hailin 8d97ed2720 fix(wallet-service): convert BigInt to string for JSON serialization in getUnprocessedSettlements
The entry.id field is BigInt type from Prisma which cannot be JSON serialized directly.
Convert to string for API response and back to BigInt when storing to database.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 07:46:46 -08:00
hailin 251fee4f1e feat(wallet-service): add offline settlement deduction feature
Add new functionality for admins to automatically deduct all settled
earnings when creating special deductions with amount=0, marking
each record to prevent duplicate deductions.

- Add OfflineSettlementDeduction model to track deducted records
- Add API endpoints for querying unprocessed settlements and executing batch deduction
- Add mode selection UI in admin-web pending-actions
- Add offline settlement card display in mobile-app special deduction page

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 06:56:39 -08:00
hailin 46b68e8652 feat(planting-service): add global stats API for data verification
Add new endpoint GET /api/v1/planting/stats/global to query planting
statistics directly from the database, providing reliable data source
for verifying reporting-service statistics.

New features:
- GlobalPlantingStats: total tree count, order count, amount
- StatusDistribution: breakdown by order status (PAID to MINING_ENABLED)
- TodayStats: daily statistics with tree count, order count, amount

Implementation:
- Pure additive changes, no modifications to existing code
- Read-only aggregate queries using Prisma aggregate/groupBy
- No database schema changes required

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 06:55:08 -08:00
hailin 8148f7a52a fix(leaderboard-service): add @IsIn validator to UpdateLeaderboardSwitchDto
The 'type' field was missing validation decorator, causing 400 Bad Request
when ValidationPipe with forbidNonWhitelisted was enabled.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 04:11:05 -08:00
hailin aa58b9e745 fix(leaderboard-service): fix AdminGuard role case sensitivity
The AdminAccount table stores roles in lowercase (admin, super_admin),
but AdminGuard was checking for uppercase (ADMIN, SUPER_ADMIN).
This caused 403 Forbidden errors for authenticated admin users.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 04:07:23 -08:00
hailin cb59a964dd fix(leaderboard-service): change global prefix from 'api' to 'api/v1'
Match the global prefix convention used by all other services.
This fixes Kong routing 404 errors for /api/v1/leaderboard/* endpoints.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 04:01:09 -08:00
hailin ea93bafe7e fix(leaderboard): add REFERRAL_SERVICE_URL to docker-compose
The leaderboard-service needs to connect to referral-service for
team statistics data. Without this environment variable, it falls
back to localhost:3004 which fails inside Docker network.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 03:47:00 -08:00
hailin dacefa2b51 feat(leaderboard): add toggle control for mobile-app ranking page
- Add public /leaderboard/status endpoint (no auth required)
- Add LeaderboardService in mobile-app to fetch board status
- Update RankingPage to show "待开启" when board is disabled
- Connect admin-web leaderboard page to real API
- Board toggle now takes effect immediately

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 03:35:57 -08:00
hailin 52afe72f17 fix(authorization): migration should drop both constraint and index
The original migration only used DROP CONSTRAINT which failed silently
because Prisma created an INDEX instead. Added DROP INDEX as well to
handle both cases in future deployments.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 03:14:00 -08:00
hailin 0991d5d484 fix(authorization): allow querying REVOKED records despite deletedAt being set
撤销授权时会同时设置 status=REVOKED 和 deletedAt(软删除),
导致 findByStatus(REVOKED) 因为 deletedAt IS NULL 条件永远返回空。
修改为查询 REVOKED 状态时不过滤 deletedAt。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 02:52:43 -08:00
hailin 5026661fa8 chore(planting): update contract PDF template to release version
Signature field position: x=449.51, y=140.18 (moved further right and up).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 02:45:28 -08:00
hailin bdc3cdd75e chore(planting): update contract PDF template to v1.2
Moved signature button field further right (x=435.60) and down (y=113.51).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 02:13:48 -08:00
hailin bc1d4a62c6 fix(authorization): add Transform decorator to parse includeRevoked query param
查询参数都是字符串类型,需要将 'true' 转换为布尔值 true,
否则后端无法正确处理 includeRevoked 参数,导致已撤销的授权记录不显示。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 02:07:49 -08:00
hailin c8f2d5edff chore(planting): update contract PDF template to v1.1
Updated signature field position to x=427.60 for better alignment.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 01:48:34 -08:00
hailin af0b9d38c0 Revert "fix(authorization): exclude revoked records when checking existing authorization"
This reverts commit ec528a7226.
2026-01-04 01:08:28 -08:00
hailin ec528a7226 fix(authorization): exclude revoked records when checking existing authorization
The findByAccountSequenceAndRoleType query now excludes REVOKED status,
allowing users to be re-authorized after their authorization was revoked.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 00:59:37 -08:00
hailin 30cb245301 refactor: rename "总部社区" to "总部" across backend services
Changed display name from "总部社区" to "总部" in:
- authorization-service
- identity-service seed
- leaderboard-service seed and entity

Note: Existing database records need manual update if already seeded.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 00:34:36 -08:00
hailin 67c7d9149c fix(planting): move signature field right to avoid overlapping text
Moved the signature field from x=415 to x=470 in the PDF template
to prevent the signature image from covering the "乙方(签字/盖章):" text.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 00:28:07 -08:00
hailin 16d895d460 debug: add logging to queryAuthorizations 2026-01-04 00:12:43 -08:00
hailin ef6b2ceb22 fix(authorization): show all authorized users in admin list including those in assessment period
Previously used findAllActive() which only returned users with benefitActive=true,
causing users still in assessment period to be hidden. Now uses findByStatus()
to show all AUTHORIZED users regardless of benefit activation status.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 00:04:24 -08:00
hailin f5afb65df8 fix(planting): center signature image on the signature field
Calculate signature position based on field center instead of left-bottom
corner, so the signature image is properly centered within the field area.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-04 00:00:13 -08:00
hailin ef80a2f23b fix(planting): remove signature button field before flatten to avoid gray background
The signature button field has a gray background that covers the drawn
signature image when the form is flattened. Now we remove the signature
field after drawing the signature image to prevent this.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 23:45:44 -08:00
hailin 083c0fd540 fix(planting): draw signature directly on page instead of using form field
The PDF signature field is only 92x51 points, which causes signatures to
appear too small or invisible. Changed to use drawImage() directly on
the page at the field's position with a larger size (150x80 max).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 23:28:18 -08:00
hailin 50f960ecea fix(authorization): allow admin tokens without accountSequence field
Admin JWT tokens from identity-service don't include the accountSequence
field (only userId, email, role, type). This caused a 400 error with
message "管理员账户序列号不能为空" when admins tried to grant authorizations.

Changes:
- Update AdminUserId value object to make accountSequence optional
- Use 'ADMIN' as default value when accountSequence is not provided
- Update all controller methods to handle optional accountSequence

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 22:57:56 -08:00
hailin 4a3658e770 chore(planting): update contract PDF template to v1
更新认种合同PDF模板为v1版本

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 22:43:15 -08:00
hailin 825b80b319 fix(planting): match PDF form field names to template
修改代码中的表单字段名以匹配PDF模板中的实际字段名:
- totalAmount → RmbAmount
- totalAmountChinese → SpellChineseFormatNumber
- greenPointsAmount → GreenAmount

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 21:33:14 -08:00
hailin 9c17140b33 feat(contract): update contract template with amount fields
更新合同模板和 PDF 生成服务,支持动态计算金额字段。

## 合同模板更新
- 替换为新版联合种植协议模板(3页,带公章)
- 新增表单字段:totalAmount、totalAmountChinese、greenPointsAmount

## PDF 生成服务更新
- 新增单价常量:
  - PRICE_PER_TREE_CNY = 17414.1(人民币含税价)
  - PRICE_PER_TREE_GREEN_POINTS = 15831(绿积分价格)
- 新增 numberToChineseAmount() 函数:数字转中文大写金额
- 更新 ContractPdfData 接口:新增可选字段 totalAmount、greenPointsAmount
- 更新 fillFormFields():根据认种棵数自动计算金额
- 移除坐标定位填充方式,仅使用表单字段方式
- 所有表单字段现为必需,缺少时抛出明确错误

## 金额计算逻辑
- 人民币金额 = 棵数 × 17414.1
- 绿积分金额 = 棵数 × 15831
- 大写金额自动生成(如:壹万柒仟肆佰壹拾肆元壹角)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 20:21:37 -08:00
hailin 17b9c09381 feat(ledger): add detailed ledger entry views with source tracking
实现账本流水详情功能,支持点击查看各类型流水的详细信息。

## reward-service 后端

### 数据库
- 新增 `source_account_sequence` 字段到 `reward_ledger_entries` 表
- 添加索引 `idx_source_account_seq` 提升查询性能
- 字段可空,兼容历史数据

### 领域层
- `RewardSource` 值对象新增 `sourceAccountSequence` 属性
- `RewardCalculationService` 传递 `sourceAccountSequence`

### 应用层
- 新增 `getSettlementHistory` 方法查询结算历史
- 新增 `SettlementRecordRepository` 仓储实现

### API层
- 新增 `GET /settlements/history` 接口
- 新增 `SettlementHistoryQueryDTO` 和 `SettlementHistoryDTO`

## mobile-app 前端

### 服务层
- `RewardService` 新增结算历史相关模型和方法:
  - `SettlementHistoryItem` 结算记录模型
  - `SettlementRewardEntry` 关联奖励条目模型
  - `getSettlementHistory()` 获取结算历史

- `WalletService` 新增:
  - `LedgerEntry.payloadJson` 字段及辅助方法
  - `counterpartyAccountSequence` 获取转账对手方ID
  - `counterpartyUserId` 获取转账对手方用户ID
  - `transferFee` 获取转账手续费

### 账本详情页
- 结算流水详情:显示结算金额、币种、涉及奖励明细(含来源用户)
- 提现流水详情:显示提现订单信息、状态、手续费等
- 转账流水详情:显示转入来源/转出目标用户信息

### 交互优化
- REWARD_SETTLED、WITHDRAWAL、TRANSFER_IN、TRANSFER_OUT 类型可点击
- 使用底部弹窗展示详情,支持滚动查看长列表

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 20:09:17 -08:00
hailin 35a812c058 feat(authorization): add admin authorization management API and real data integration
Backend (authorization-service):
- Add QueryAuthorizationsDto for query parameters (roleType, keyword, includeRevoked, page, limit)
- Add queryAuthorizations method to fetch all authorizations with user info
- Add GET /admin/authorizations endpoint for listing authorizations
- Add POST /admin/authorizations/:id/revoke endpoint for revoking authorization

Frontend (admin-web):
- Add authorization.types.ts with RoleType, Authorization, and request types
- Add authorizationService.ts for API calls (list, revoke, grant operations)
- Add useAuthorizations.ts React Query hooks
- Update authorization page to use real API data instead of mock data
- Add loading/error states, pagination, and revoke reason display
- Add new styles for loading, error, pagination, and date columns

The authorization management page now displays all authorized users
from the database with support for filtering by role type, status,
and keyword search.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 18:50:10 -08:00
hailin dcd6f2ce18 fix: 修复特殊扣减API路径和批量创建用户ID解析问题
1. mobile-app: 修复特殊扣减API路径重复问题
   - 将 /api/v1/wallets/special-deduction/execute 改为 /wallets/special-deduction/execute
   - 因为 ApiClient baseURL 已包含 /api/v1 前缀

2. admin-web: 批量创建待办操作支持中文逗号分隔
   - 正则表达式从 /[\n,]/ 改为 /[\n,,]/
   - 同时支持换行、英文逗号、中文逗号作为分隔符

3. identity-service: 添加用户查找调试日志
   - 在 findUserByIdOrSequence 方法中添加日志
   - 便于排查用户ID查找失败的问题

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 17:54:27 -08:00
hailin dfdd8ed65a feat(pending-actions): add special deduction feature for admin-created user actions
实现特殊扣减功能,允许管理员为用户创建扣减待办操作,由用户在移动端确认执行。

## 后端 (wallet-service)

### 领域层
- 新增 `SPECIAL_DEDUCTION` 到 LedgerEntryType 枚举
  用于记录特殊扣减的账本流水类型

### 应用层
- 新增 `executeSpecialDeduction` 方法
  - 验证用户钱包存在性
  - 检查余额是否充足
  - 乐观锁控制并发
  - 扣减余额并记录账本流水
  - 返回操作结果和新余额

### API层
- 新增内部API: POST /api/v1/wallets/special-deduction/execute
  供移动端调用执行特殊扣减操作

## 前端 (admin-web)

### 类型定义
- 新增 `SPECIAL_DEDUCTION` 到 ACTION_CODES
- 新增 `SpecialDeductionParams` 接口定义扣减参数
  - amount: 扣减金额
  - reason: 扣减原因

### 页面
- 更新待办操作管理页面
  - 当选择 SPECIAL_DEDUCTION 时显示扣减金额和原因输入框
  - 验证扣减金额必须大于0
  - 验证扣减原因不能为空

### 样式
- 新增特殊扣减表单区域样式

## 前端 (mobile-app)

### 服务层
- 新增 `executeSpecialDeduction` 方法到 WalletService
- 新增 `SpecialDeductionResult` 结果类
- 新增 `specialDeduction` 到 PendingActionCode 枚举

### 页面
- 新增 `SpecialDeductionPage` 特殊扣减确认页面
  - 显示扣减金额和管理员备注
  - 显示当前余额和扣减后余额
  - 余额不足时禁用确认按钮
  - 温馨提示说明操作性质

- 更新 `PendingActionsPage`
  - 处理 SPECIAL_DEDUCTION 类型的待办操作
  - 从 actionParams 解析 amount 和 reason
  - 导航到特殊扣减确认页面

## 工作流程

1. 管理员在 admin-web 创建 SPECIAL_DEDUCTION 待办操作
   - 选择目标用户
   - 输入扣减金额
   - 输入扣减原因

2. 用户在 mobile-app 待办操作列表看到该操作

3. 用户点击后进入特殊扣减确认页面
   - 查看扣减详情
   - 确认余额充足
   - 点击确认执行扣减

4. 后端执行扣减并记录账本流水

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 07:04:46 -08:00
hailin a609600cd8 feat(fiat-withdrawal): add complete fiat withdrawal system
实现完整的法币提现功能,支持银行卡、支付宝、微信三种收款方式。
此功能与现有的区块链划转功能完全独立,互不影响。

## 后端 (wallet-service)

### 数据库
- 新增 `fiat_withdrawal_orders` 表存储法币提现订单
- 与现有 `withdrawal_orders` 表(区块链划转)完全分离
- 添加完整索引支持高效查询

### 领域层
- 新增 `FiatWithdrawalStatus` 枚举(与 WithdrawalStatus 独立)
  - 流程: PENDING -> FROZEN -> REVIEWING -> APPROVED -> PAYING -> COMPLETED
  - 或 REJECTED / FAILED / CANCELLED
- 新增 `PaymentMethod` 枚举: BANK_CARD / ALIPAY / WECHAT
- 新增 `FiatWithdrawalOrder` 聚合根
- 新增 `IFiatWithdrawalOrderRepository` 仓储接口
- 新增 `FIAT_WITHDRAWAL` 账本流水类型

### 应用层
- 新增 `FiatWithdrawalApplicationService` 处理业务逻辑
  - 发送短信验证码
  - 申请法币提现(冻结余额)
  - 提交审核
  - 审核通过/驳回
  - 开始打款
  - 完成打款

### API层
- 新增 `FiatWithdrawalController` 提供用户端API
  - POST /wallet/fiat-withdrawal/send-sms - 发送验证码
  - POST /wallet/fiat-withdrawal - 申请提现
  - GET /wallet/fiat-withdrawal - 获取提现记录
- 新增内部API供管理端调用
  - GET /api/v1/wallets/fiat-withdrawals - 查询订单
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/review - 审核
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/start-payment - 开始打款
  - POST /api/v1/wallets/fiat-withdrawals/:orderNo/complete-payment - 完成打款

## 前端 (admin-web)

- 新增法币提现审核管理页面 `/withdrawals`
- 支持按状态分 Tab 查看订单
- 支持审核通过/驳回
- 支持打款操作
- 支持查看订单详情

## 前端 (mobile-app)

- 新增 `WithdrawFiatPage` 法币提现页面
  - 支持选择银行卡/支付宝/微信
  - 输入收款账户信息
- 新增 `WithdrawFiatConfirmPage` 确认页面
  - 短信验证码验证
  - 密码验证
- 在 `WalletService` 中添加法币提现相关方法和模型

## 重要说明

此功能与现有的区块链划转功能 (withdraw_usdt_page.dart) 完全独立:
- 独立的数据库表
- 独立的聚合根
- 独立的状态枚举
- 独立的API端点
- 独立的前端页面

原有的区块链划转功能保持不变,不受任何影响。

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 06:39:11 -08:00
hailin d614d18e97 Revert "feat(withdrawal): implement fiat withdrawal with bank/alipay/wechat"
This reverts commit 288d894746.
2026-01-03 05:44:43 -08:00
hailin 288d894746 feat(withdrawal): implement fiat withdrawal with bank/alipay/wechat
Add complete fiat withdrawal feature that allows users to withdraw
green credits (绿积分) to their bank card, Alipay, or WeChat account
with 1:1 CNY conversion. Key changes:

Backend (wallet-service):
- Update Prisma schema with fiat withdrawal fields (paymentMethod,
  bankName, bankCardNo, cardHolderName, alipay*, wechat*, review fields)
- Rewrite withdrawal status enum for fiat flow: PENDING → FROZEN →
  REVIEWING → APPROVED → PAYING → COMPLETED (or REJECTED/FAILED)
- Add PaymentMethod enum: BANK_CARD, ALIPAY, WECHAT
- Update WithdrawalOrderAggregate with new fiat withdrawal methods
- Add review/payment workflow methods in WalletApplicationService
- Add internal API endpoints for admin withdrawal management
- Remove blockchain withdrawal event handler (no longer needed)

Frontend (admin-web):
- Add withdrawal review management page at /withdrawals
- Add tabs for reviewing/approved/paying order states
- Add withdrawal service and React Query hooks
- Add types for withdrawal orders and payment methods
- Add sidebar menu item for withdrawal review

Frontend (mobile-app):
- Add withdrawFiat() method to WalletService
- Add PaymentMethod enum with BANK_CARD/ALIPAY/WECHAT
- Create new WithdrawFiatPage for fiat withdrawal input
- Create WithdrawFiatConfirmPage with SMS + password verification
- Add routes for /withdraw/fiat and /withdraw/fiat/confirm
- Keep existing withdraw/usdt (划转) pages unchanged

Note: The existing withdraw_usdt_page.dart is for point-to-point
transfer (划转), which is a different feature from fiat withdrawal.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 05:28:05 -08:00
hailin 036696878f feat(settlement): implement settle-to-balance with detailed source tracking
Add complete settlement-to-balance feature that transfers settleable
earnings directly to wallet USDT balance (no currency swap). Key changes:

Backend (wallet-service):
- Add SettleToBalanceCommand for settlement operations
- Add settleToBalance method to WalletAccountAggregate
- Add settleToBalance application service with ledger recording
- Add internal API endpoint POST /api/v1/wallets/settle-to-balance

Backend (reward-service):
- Add settleToBalance client method for wallet-service communication
- Add settleRewardsToBalance application service method
- Add user-facing API endpoint POST /rewards/settle-to-balance
- Build detailed settlement memo with source user tracking per reward

Frontend (mobile-app):
- Add SettleToBalanceResult model class
- Add settleToBalance() method to RewardService
- Update pending_actions_page to handle SETTLE_REWARDS action
- Add completion detection via settleableUsdt balance check

Settlement memo now includes detailed breakdown by right type with
source user accountSequence for each reward entry, e.g.:
  结算 1000.00 绿积分到钱包余额
  涉及 5 笔奖励
    - SHARE_RIGHT: 500.00 绿积分
        来自 D2512120001: 288.00 绿积分
        来自 D2512120002: 212.00 绿积分

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-03 04:29:38 -08:00
hailin cbbef170e8 feat(pending-actions): display accountSequence alongside userId
- Add accountSequence field to PendingActionResponseDto
- Add helper methods to fetch accountSequence from UserAccount
- Update queryActions and getAction to include accountSequence
- Update admin-web table and detail view to show both fields
- accountSequence displayed prominently, userId shown as secondary info

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 21:33:03 -08:00
hailin 789d921fd7 fix(pending-actions): support accountSequence for user lookup
Allow admin to create pending actions using accountSequence (e.g.,
D25122700022) instead of requiring numeric userId.

- Add findUserByIdOrSequence helper method
- Update createAction to use helper
- Update batchCreateActions to use helper
- Update queryActions to support accountSequence filter

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 20:39:54 -08:00
hailin 582e80b750 fix(pending-actions): add @Public() decorator to AdminPendingActionController
Skip JWT auth for admin pending-actions endpoints since admin-web
authenticates through a different mechanism (admin-service tokens).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 19:00:24 -08:00
hailin ff038f31f9 fix(pending-actions): fix API response handling and add Kong route
- Fix pending_action_service.dart to access response.data instead of response
- Add Kong route for /api/v1/admin/pending-actions to identity-service

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:33:58 -08:00
hailin 28e0396a65 feat(pending-actions): add user pending actions system
Add a fully optional pending actions system that allows admins to configure
specific tasks that users must complete after login.

Backend (identity-service):
- Add UserPendingAction model to Prisma schema
- Add migration for user_pending_actions table
- Add PendingActionService with full CRUD operations
- Add user-facing API (GET list, POST complete)
- Add admin API (CRUD, batch create)

Admin Web:
- Add pending actions management page
- Support single/batch create, edit, cancel, delete
- View action details including completion time
- Filter by userId, actionCode, status

Flutter Mobile App:
- Add PendingActionService and PendingActionCheckService
- Add PendingActionsPage for forced task execution
- Integrate into splash_page login flow
- Users must complete all pending tasks in priority order

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 18:22:51 -08:00
hailin 04a8c56ad6 fix(identity): use correct Aliyun API for ID card verification
Change API from Id2MetaStandardVerify to Id2MetaVerify for two-factor
identity verification (name + ID card number). The previous API was
returning error 440 (no permission).

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 08:05:08 -08:00
hailin e2cf3c3d7e fix(admin-service): 修复通知查询时publishedAt为null的问题
问题:当 publishedAt 为 NULL(表示立即发布)时,Prisma 的
`publishedAt: { lte: now }` 条件不匹配,导致通知无法显示

修复:将查询条件改为 OR 逻辑:
- publishedAt 为 null(立即发布)
- publishedAt <= now(定时发布且已到时间)

影响的方法:
- findNotificationsForUser
- countUnreadForUser
- markAllAsRead

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 05:56:43 -08:00
hailin fea0b42223 fix(admin-service): 修复维护拦截器路径检测和错误处理
问题:添加系统维护检测后站内通知功能失效

修复:
1. 使用 request.url 获取完整路径(包含 /api/v1 前缀)
2. 同时支持带前缀和不带前缀的路径检测
3. 添加 try-catch 错误处理,数据库错误时放行请求而非阻断
4. 添加日志记录便于调试

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 05:01:32 -08:00
hailin c392142562 feat(blockchain): 切换到dUSDT(绿积分)合约 - KAVA主网
合约信息:
- 地址: 0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3
- 名称: Durian USDT (dUSDT)
- 精度: 6位
- 网络: KAVA EVM Mainnet (Chain ID: 2222)
- 链接: https://kavascan.com/address/0xA9F3A35dBa8699c8C681D8db03F0c1A8CEB9D7c3

修改:
- blockchain.config.ts: 更新默认合约地址
- chain-config.service.ts: 更新默认合约地址
- docker-compose.yml: NETWORK_MODE改为mainnet,配置KAVA主网
- .env.example: 更新合约地址和注释
- KAVA_NETWORK.md: 标注dUSDT为当前使用合约

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 04:31:11 -08:00