fix(reporting): 修复 contract.signed 事件 BigInt(undefined) 错误

根因:planting-service 发送的 contract.signed 消息为嵌套结构
  { eventName: 'contract.signed', data: { orderNo, userId, ... } }
但 reporting-service handleContractSigned 按扁平结构解析
  message.userId → undefined → BigInt(undefined) → TypeError
导致 ~200 次/10分钟持续报错。

修复:
- 消息类型改为匹配实际嵌套格式 { eventName, data: { ... } }
- 解构 message.data 后再访问各字段
- 添加 userId 防御性检查,避免再次 BigInt 崩溃
- 与 referral-service ContractSigningHandler 消息结构保持一致

影响范围:仅 reporting-service 活动记录,不影响核心业务流程
(referral-service / reward-service 已正确处理嵌套格式)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-02-15 07:59:16 -08:00
parent 2a725af83e
commit 875f86c263
1 changed files with 38 additions and 21 deletions

View File

@ -637,11 +637,20 @@ export class ActivityEventConsumerController {
/** /**
* (planting-service) * (planting-service)
* Topic: contract.signed * Topic: contract.signed
*
* planting-service EventPublisherService.publishContractSigned :
* { eventName: 'contract.signed', data: { orderNo, userId, accountSequence, ... } }
*
* payload data referral-service ContractSigningHandler
* message.userId undefined BigInt(undefined)
* TypeError (~200/10)
*/ */
@MessagePattern('contract.signed') @MessagePattern('contract.signed')
async handleContractSigned( async handleContractSigned(
@Payload() @Payload()
message: { message: {
eventName: string;
data: {
orderNo: string; orderNo: string;
userId: string; userId: string;
accountSequence: string; accountSequence: string;
@ -649,35 +658,43 @@ export class ActivityEventConsumerController {
totalAmount: number; totalAmount: number;
provinceCode: string; provinceCode: string;
cityCode: string; cityCode: string;
signedAt: string; signedAt?: string;
};
}, },
) { ) {
this.logger.log(`Received contract.signed event: ${message.orderNo}`); const eventData = message.data;
if (!eventData?.userId) {
this.logger.warn(`Received contract.signed with missing data.userId, skipping. Raw: ${JSON.stringify(message)}`);
return;
}
this.logger.log(`Received contract.signed event: ${eventData.orderNo}`);
try { try {
const created = await this.activityRepo.createIfNotExists({ const created = await this.activityRepo.createIfNotExists({
activityType: 'contract_signed' as ActivityType, activityType: 'contract_signed' as ActivityType,
title: '合同签署', title: '合同签署',
description: `用户签署了 ${message.treeCount} 棵榴莲树认种合同`, description: `用户签署了 ${eventData.treeCount} 棵榴莲树认种合同`,
icon: '📝', icon: '📝',
relatedUserId: BigInt(message.userId), relatedUserId: BigInt(eventData.userId),
relatedEntityType: 'contract', relatedEntityType: 'contract',
relatedEntityId: message.orderNo, relatedEntityId: eventData.orderNo,
metadata: { metadata: {
orderNo: message.orderNo, orderNo: eventData.orderNo,
accountSequence: message.accountSequence, accountSequence: eventData.accountSequence,
treeCount: message.treeCount, treeCount: eventData.treeCount,
totalAmount: message.totalAmount, totalAmount: eventData.totalAmount,
provinceCode: message.provinceCode, provinceCode: eventData.provinceCode,
cityCode: message.cityCode, cityCode: eventData.cityCode,
signedAt: message.signedAt, signedAt: eventData.signedAt,
}, },
}); });
if (created) { if (created) {
this.logger.log(`Activity recorded for contract signing: ${message.orderNo}`); this.logger.log(`Activity recorded for contract signing: ${eventData.orderNo}`);
} else { } else {
this.logger.log(`Skipped duplicate contract signing event: ${message.orderNo}`); this.logger.log(`Skipped duplicate contract signing event: ${eventData.orderNo}`);
} }
} catch (error) { } catch (error) {
this.logger.error(`Error recording contract signing activity:`, error); this.logger.error(`Error recording contract signing activity:`, error);