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:
parent
2a725af83e
commit
875f86c263
|
|
@ -637,47 +637,64 @@ export class ActivityEventConsumerController {
|
|||
/**
|
||||
* 监听合同签署事件 (planting-service)
|
||||
* 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')
|
||||
async handleContractSigned(
|
||||
@Payload()
|
||||
message: {
|
||||
orderNo: string;
|
||||
userId: string;
|
||||
accountSequence: string;
|
||||
treeCount: number;
|
||||
totalAmount: number;
|
||||
provinceCode: string;
|
||||
cityCode: string;
|
||||
signedAt: string;
|
||||
eventName: string;
|
||||
data: {
|
||||
orderNo: string;
|
||||
userId: string;
|
||||
accountSequence: string;
|
||||
treeCount: number;
|
||||
totalAmount: number;
|
||||
provinceCode: string;
|
||||
cityCode: 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 {
|
||||
const created = await this.activityRepo.createIfNotExists({
|
||||
activityType: 'contract_signed' as ActivityType,
|
||||
title: '合同签署',
|
||||
description: `用户签署了 ${message.treeCount} 棵榴莲树认种合同`,
|
||||
description: `用户签署了 ${eventData.treeCount} 棵榴莲树认种合同`,
|
||||
icon: '📝',
|
||||
relatedUserId: BigInt(message.userId),
|
||||
relatedUserId: BigInt(eventData.userId),
|
||||
relatedEntityType: 'contract',
|
||||
relatedEntityId: message.orderNo,
|
||||
relatedEntityId: eventData.orderNo,
|
||||
metadata: {
|
||||
orderNo: message.orderNo,
|
||||
accountSequence: message.accountSequence,
|
||||
treeCount: message.treeCount,
|
||||
totalAmount: message.totalAmount,
|
||||
provinceCode: message.provinceCode,
|
||||
cityCode: message.cityCode,
|
||||
signedAt: message.signedAt,
|
||||
orderNo: eventData.orderNo,
|
||||
accountSequence: eventData.accountSequence,
|
||||
treeCount: eventData.treeCount,
|
||||
totalAmount: eventData.totalAmount,
|
||||
provinceCode: eventData.provinceCode,
|
||||
cityCode: eventData.cityCode,
|
||||
signedAt: eventData.signedAt,
|
||||
},
|
||||
});
|
||||
|
||||
if (created) {
|
||||
this.logger.log(`Activity recorded for contract signing: ${message.orderNo}`);
|
||||
this.logger.log(`Activity recorded for contract signing: ${eventData.orderNo}`);
|
||||
} else {
|
||||
this.logger.log(`Skipped duplicate contract signing event: ${message.orderNo}`);
|
||||
this.logger.log(`Skipped duplicate contract signing event: ${eventData.orderNo}`);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger.error(`Error recording contract signing activity:`, error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue