hailin
666be6ea60
fix(planting-service): 签名后查看合同返回已签名的PDF
...
- 修改 /tasks/:orderNo/pdf 接口,检查任务状态
- 如果已签名且有 signedPdfUrl,从 MinIO 下载已签名的 PDF
- 添加 downloadSignedPdf 方法到 MinioStorageService
- 在 ContractSigningTaskDto 中添加 signedPdfUrl 字段
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 05:48:22 -08:00
hailin
1d6982c73e
feat(planting-service): 合同签署超时时间从24小时改为1年
2025-12-26 03:58:56 -08:00
hailin
9addd99710
fix(planting-service): 修正导入路径
...
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 01:50:37 -08:00
hailin
24a46521f3
fix(planting-service): 修复跨服务调用使用错误标识符导致的500错误
...
问题根源:
- getBalance 调用使用 userId.toString() (纯数字如 "14")
- wallet-service 按 accountSequence 查找钱包失败后尝试创建新钱包
- 但 userId 已存在,触发唯一约束冲突导致500错误
修复内容:
1. planting-application.service.ts:
- createOrder: getBalance(userId.toString()) → getBalance(accountSequence)
- payOrder: getBalance(userId.toString()) → getBalance(walletIdentifier)
2. payment-compensation.service.ts:
- 注入 IPlantingOrderRepository 获取订单的 accountSequence
- handleUnfreeze/handleRetryConfirm 添加 accountSequence 参数
3. wallet-service.client.ts:
- ensureRegionAccounts 接口添加 provinceTeamAccount/cityTeamAccount 字段
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-26 01:48:22 -08:00
hailin
f62a96f3f1
feat(planting): 已付款未KYC用户强制进入实名认证流程
...
后端 (planting-service):
- 添加 /contract-signing/kyc-requirement 接口检查用户是否需要KYC
- 检查已付款订单但无合同签署任务的情况
前端 (mobile-app):
- ContractCheckService 新增 checkAll() 综合检查方法
- HomeShellPage 综合检查待签署合同和KYC需求
- 需要KYC时弹出强制认证弹窗,不可关闭
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 21:14:53 -08:00
hailin
63ac0debf3
feat(planting-service): 添加合同签署后事件恢复定时任务
...
每2~5分钟随机间隔扫描已签署超过2分钟的合同
重新发布 contract.signed 事件,确保扣款确认和奖励分配完成
幂等性已由 wallet-service 保证
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 09:08:47 -08:00
hailin
c907f44851
feat(planting-service): 订单表添加 accountSequence,实现合同恢复任务
...
变更内容:
1. 订单表添加 account_sequence 字段
- 创建订单时保存用户的 accountSequence
- 避免跨服务调用 identity-service 获取用户信息
2. 新增 ContractSigningRecoveryJob 定时任务
- 每 3 分钟扫描已支付但未创建合同的订单
- 使用订单中的 accountSequence 获取 KYC 信息
- 为已通过 KYC 的用户补创建合同签署任务
3. 修改 PlantingOrder 聚合根
- create() 方法增加 accountSequence 参数
- markAsPaid() 不再需要 accountSequence 参数
- 事件中携带 accountSequence
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 08:19:36 -08:00
hailin
8163804f23
fix(contract-signing): 修复合同签署流程的持仓更新时机
...
问题:支付后直接更新持仓和开启挖矿,导致款还在冻结中树就种下去了
修复:
- planting-application.service: 支付时不再更新持仓和开启挖矿
- contract-signing.service: signContract 在事务里同时完成合同+持仓+挖矿
- contract-signing.service: handleExpiredTasks 超时也更新持仓+挖矿(钱扣总部)
- KYCVerifiedEvent 添加 accountSequence 字段
- kyc-verified-event.consumer 直接用事件里的 accountSequence
流程变为:支付冻结 → 签署合同 → [事务: 合同+持仓+挖矿] → 发事件
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 06:50:03 -08:00
hailin
929ae335c5
feat(contract): 增强合同生成功能
...
- 添加 IdentityServiceClient 从 identity-service 获取用户 KYC 信息
- 只允许已完成实名认证的用户创建合同
- 添加 KycVerifiedEventConsumer 监听 KYC 完成事件
- 用户完成 KYC 后自动为其之前已支付的订单补创建合同
- PDF 生成器支持 AcroForm 表单字段填充(更可靠)
- 保留坐标定位方式作为后备方案
- 更新 PDF 模板为带表单字段版本
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 05:35:40 -08:00
hailin
0e93d2a343
feat(contract): 使用合同编号代替订单号
...
合同编号格式: accountSequence-yyyyMMddHHmm
例如: 10001-202512251003
修改内容:
- 数据库: 添加 contract_no 字段
- 后端: 聚合根、Repository、Service、PDF生成器支持 contractNo
- 前端: 显示合同编号代替订单号
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 04:58:39 -08:00
hailin
a7206eef2e
fix(planting-service): 修复 BigInt userId 比较问题
...
- 使用 toString() 比较 BigInt 避免类型不匹配
- 添加调试日志帮助排查问题
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 03:59:27 -08:00
hailin
c509daa353
feat(contract-signing): 使用 pdf-lib 实现专业 PDF 合同展示
...
后端改动:
- 添加 pdf-lib 和 @pdf-lib/fontkit 依赖
- 新建 PdfGeneratorService 使用 PDF 模板直接填充用户数据
- 添加中文字体支持 (NotoSansSC-Regular.ttf)
- 新增 GET /tasks/:orderNo/pdf 接口返回 PDF 文件
- 合同模板存放于 templates/contract-template.pdf
前端改动:
- 添加 flutter_pdfview 依赖
- 重写合同签署页面使用 PDFView 组件展示 PDF
- 下载 PDF 到临时目录后展示
- 滑动到最后一页自动标记已阅读
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 02:27:54 -08:00
hailin
714ce42e4f
feat(contract-signing): 添加电子合同签署功能及单点配置优化
...
- planting-service: 添加合同签署任务管理和超时检测
- 新增 ContractSigningTask 领域模型
- 添加 24 小时合同签署超时定时任务
- 支付后资金保持冻结,由 referral-service 统一确认扣款
- referral-service: 单点配置 CONTRACT_SIGNING_ENABLED
- 新增 ContractSigningHandler 处理合同签署/超时事件
- 新增 WalletServiceClient 调用钱包服务确认扣款
- planting.created 处理后根据配置决定是否等待合同签署
- reward-service: 移除 CONTRACT_SIGNING_ENABLED 配置
- 扣款确认由 referral-service 在发送事件前完成
- 保持奖励分配逻辑不变
配置说明:
- CONTRACT_SIGNING_ENABLED=true (默认): 等待合同签署后分配奖励
- CONTRACT_SIGNING_ENABLED=false: 立即分配奖励(原有流程)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-24 20:12:12 -08:00
hailin
1cc27731d9
fix(planting): 移除个人最大认种数量限制
...
删除 MAX_TREES_PER_USER = 1000 的限制和 checkRiskControl 方法
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 01:10:03 -08:00
hailin
d6055099c7
fix(planting): 支付完成后直接开启挖矿,跳过底池注入流程
...
- enableMining() 允许从 PAID 状态直接开启
- addPlanting() 树直接进入 effectiveTreeCount
- payOrder() 删除底池批次逻辑,直接调用 enableMining()
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 04:25:31 -08:00
hailin
c93f43546e
fix(planting-service): PlantingOrderPaidEvent 添加 accountSequence 字段
...
Bug 3 修复: wallet-service 结算待领取奖励时需要 accountSequence
- PlantingOrderPaidEvent 事件 data 添加 accountSequence 字段
- markAsPaid(accountSequence) 方法接收并传递 accountSequence
- payOrder 调用 markAsPaid 时传入 accountSequence
- 更新相关单元测试
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 06:13:59 -08:00
hailin
98d8bee20d
fix: 统一推荐码生成逻辑 - 由 identity-service 单点生成
...
重要变更:
- identity-service 生成用户推荐码,通过 Kafka 事件传递给 referral-service
- referral-service 不再自己生成推荐码,直接使用事件中的推荐码
- 修复两个服务推荐码不一致的问题
涉及服务:
- identity-service: 事件 payload 添加 referralCode 字段
- referral-service: 接收并存储 identity-service 生成的推荐码
- wallet-service: 添加区域账户动态创建接口
- planting-service: 调用区域账户创建接口
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-13 01:14:56 -08:00
hailin
ebbf2d971a
feat: 跨服务使用 accountSequence 查询推荐链 + 系统账户动态创建
...
1. reward-service 使用 accountSequence 查询推荐链
- event-consumer.controller.ts: 优先使用 accountSequence 作为用户标识
- reward-calculation.service.ts: 使用 accountSequence 查询推荐关系
- referral-service.client.ts: 参数从 userId 改为 accountSequence
2. referral-service 支持 accountSequence 格式的推荐链查询
- referral.controller.ts: /chain/:identifier 同时支持 userId 和 accountSequence
3. wallet-service 系统账户动态创建
- wallet-application.service.ts: allocateToUserWallet 使用 getOrCreate
- 支持省区域(9+code)和市区域(8+code)账户自动创建
- 新增 migration seed: 4个固定系统账户 (S0000000001-S0000000004)
4. planting-service 事件增强
- 事件中添加 accountSequence 字段用于跨服务关联
系统账户格式:
- S0000000001: 总部社区 (基础费9U + 兜底权益)
- S0000000002: 成本费账户 (400U)
- S0000000003: 运营费账户 (300U)
- S0000000004: RWAD底池账户 (800U)
- 9+provinceCode: 省区域系统账户 (动态创建)
- 8+cityCode: 市区域系统账户 (动态创建)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 23:22:01 -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
8148d1d127
fix: 修复权益分配竞态条件和统计数据bug
...
1. 事件流重构:将 planting.order.paid 事件从 planting-service 移至 referral-service 发送
- 确保统计数据更新后再触发奖励计算,避免竞态条件
- planting-service 只发送 planting.planting.created 事件(包含订单信息)
- referral-service 处理完统计更新后转发 planting.order.paid 给 reward-service
2. 修复 addPersonalPlanting 方法:
- 原代码错误地更新 _totalTeamCount(团队人数)而非 _teamPlantingCount(团队认种数)
- 导致 subordinateTeamPlantingCount 计算错误,权益无法正确分配
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 05:35:31 -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
e5e2793337
feat(planting): add payment reliability improvements
...
## wallet-service
- Add freeze/confirm/unfreeze API endpoints for planting deduction
- Add deductFrozen method to wallet-account aggregate
- Add PLANT_FREEZE and PLANT_UNFREEZE ledger entry types
- Add idempotency check in deductForPlanting
- Fix test files to include accountSequence parameter
## planting-service
- Add PaymentCompensation model and migration
- Add payment-compensation.repository.ts
- Add payment-compensation.service.ts (background job for retry)
- Add HTTP retry mechanism with exponential backoff
- Refactor payOrder to use freeze → transaction → confirm flow
- Create compensation record on unfreeze failure
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 06:31:54 -08:00
hailin
014ad9d19f
feat(planting): implement Outbox Pattern with consumer acknowledgment (B方案)
...
Implement reliable event delivery using Outbox Pattern with consumer confirmation:
## planting-service (Producer)
- Add OutboxEvent table with status: PENDING → SENT → CONFIRMED
- Add OutboxRepository with transaction support and timeout handling
- Add OutboxPublisherService with polling, timeout check, and retry
- Add EventAckController to receive consumer confirmations
- Update UnitOfWork to save outbox events atomically with business data
- Update PlantingApplicationService to use outbox pattern
- Update PoolInjectionService to use outbox pattern
## Consumer Services
- Add EventAckPublisher to reward-service, referral-service, authorization-service
- Update event handlers to send acknowledgment after successful processing
## Event Flow
1. Business data + outbox events saved in same transaction
2. OutboxPublisher polls and sends to Kafka, marks as SENT
3. Consumer processes event and sends ack to planting.events.ack
4. EventAckController receives ack and marks as CONFIRMED
5. Timeout check resets SENT→PENDING for retry (max 5 times)
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-09 21:32:16 -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
98f5d948dd
feat(planting-service): Implement complete planting service with DDD architecture
...
- Domain Layer:
- PlantingOrder aggregate with full lifecycle management
- PlantingPosition aggregate for user holdings
- PoolInjectionBatch aggregate for 5-day batch processing
- Value objects: TreeCount, ProvinceCitySelection, FundAllocation, Money
- Domain events for state transitions
- FundAllocationDomainService for 10-target fund distribution (2199 USDT/tree)
- Application Layer:
- PlantingApplicationService for order management
- PoolInjectionService for batch processing
- 5-second province/city confirmation mechanism
- Infrastructure Layer:
- Prisma ORM with PostgreSQL
- Repository implementations
- External service clients (Wallet, Referral)
- Object mappers
- API Layer:
- REST controllers with Swagger documentation
- JWT authentication guard
- Request/Response DTOs with validation
- Testing:
- 45+ unit tests
- 12+ integration tests
- 17+ E2E tests
- Docker test environment
- Documentation:
- Architecture design (DDD + Hexagonal)
- API documentation
- Development guide
- Testing guide
- Deployment guide
🤖 Generated with [Claude Code](https://claude.com/claude-code )
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 18:55:50 -08:00