From 068b8047ddbfbacf32b233b7b8cfb4e52fd04a6f Mon Sep 17 00:00:00 2001 From: hectorzhao Date: Thu, 3 Sep 2026 09:37:24 +0800 Subject: [PATCH] fix: keep absent brief SMS content empty --- api/src/report-materials/channel-export.service.ts | 6 ++++-- .../report-materials.service.spec.ts | 12 +++++++----- ...batch-import-records-remediation-plan-20260902.md | 2 +- docs/system-functional-test-cases.md | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/api/src/report-materials/channel-export.service.ts b/api/src/report-materials/channel-export.service.ts index 4518658..8f9074d 100644 --- a/api/src/report-materials/channel-export.service.ts +++ b/api/src/report-materials/channel-export.service.ts @@ -95,8 +95,10 @@ export class ReportChannelExportService { const values = fields.map( (field) => resolveExportValue(item.snapshot, field.code, field.name) ?? field.defaultValue ?? '', ); - const smsContentIndex = fields.findIndex((field) => field.name.trim() === '短信内容'); - const smsContentValue = smsContentIndex >= 0 ? values[smsContentIndex] : ''; + const smsContentField = fields.find((field) => field.name.trim() === '短信内容'); + const smsContentValue = smsContentField + ? resolveExportValue(item.snapshot, smsContentField.code, smsContentField.name) ?? '' + : ''; const smsContent = isFileRef(smsContentValue) ? '' : String(smsContentValue ?? ''); const missing = fields.filter((field, index) => field.required && !hasValue(values[index])); const missingReason = diff --git a/api/src/report-materials/report-materials.service.spec.ts b/api/src/report-materials/report-materials.service.spec.ts index 63b9ce9..17437f1 100644 --- a/api/src/report-materials/report-materials.service.spec.ts +++ b/api/src/report-materials/report-materials.service.spec.ts @@ -149,7 +149,7 @@ describe('ReportMaterialsService', () => { ]); }); - it('expands one selected signature to every routed channel and embeds images in each XLSX', async () => { + it('expands one selected signature to every routed channel, embeds images and snapshots the first material SMS content', async () => { const uploadedWorkbooks: Buffer[] = []; let batchItemSequence = 0; let exportSequence = 0; @@ -189,6 +189,8 @@ describe('ReportMaterialsService', () => { drainageInfo: { signatureReportValues: { license: { fileObjectId: 'image-1', fileName: 'license.png', contentType: 'image/png' }, + sms_content_primary: '第一条短信内容', + sms_content_secondary: '第二条短信内容', }, }, tenant: { name: '测试企业' }, @@ -223,7 +225,7 @@ describe('ReportMaterialsService', () => { ), }, channelReportField: { - findMany: jest.fn().mockResolvedValue([ + findMany: jest.fn().mockImplementation(({ where }: { where: { channelId: string } }) => Promise.resolve([ { code: 'sign', name: '短信签名', @@ -247,7 +249,7 @@ describe('ReportMaterialsService', () => { defaultValue: null, }, { - code: 'sms_content_primary', + code: where.channelId === 'channel-b' ? 'sms_content_missing' : 'sms_content_primary', name: '短信内容', exportName: '短信内容一', required: false, @@ -268,7 +270,7 @@ describe('ReportMaterialsService', () => { transform: null, defaultValue: '第二条短信内容', }, - ]), + ])), }, channelSignatureReportTask: { findMany: jest.fn().mockResolvedValue([]), @@ -331,7 +333,7 @@ describe('ReportMaterialsService', () => { snapshot: expect.objectContaining({ briefSmsContentByChannel: { 'channel-a': '第一条短信内容', - 'channel-b': '第一条短信内容', + 'channel-b': '', }, }), }, diff --git a/docs/reporting-batch-import-records-remediation-plan-20260902.md b/docs/reporting-batch-import-records-remediation-plan-20260902.md index 2b30b43..e0c6921 100644 --- a/docs/reporting-batch-import-records-remediation-plan-20260902.md +++ b/docs/reporting-batch-import-records-remediation-plan-20260902.md @@ -107,7 +107,7 @@ 2. 通道简报 - 每个通道一份,日期取批次生成时间,批次号取 `batchNo`。 - 签名资料行格式为“短信签名:【签名】,短信内容:内容”;引流资料行格式为“引流信息:URL或号码,短信内容:内容”。 - - “短信内容”只从该通道按 `sortOrder ASC, createdAt ASC` 排列的字段库中取第一个名称为“短信内容”的字段;没有则留空,后续同名字段不参与简报。 + - “短信内容”只从该通道按 `sortOrder ASC, createdAt ASC` 排列的字段库中取第一个名称为“短信内容”的字段,并读取资料中的实际字段值;没有字段或资料未提供该字段值时留空,不使用通道缺省值,后续同名字段不参与简报。 - 简报取值写入现有批次 JSON 快照,不新增数据库字段或 migration;字段库或签名资料后续变化不得改写历史批次简报。 - 页面支持查看全文和一键复制,复制失败时保留可手工选择的原文。 3. 通道文件 diff --git a/docs/system-functional-test-cases.md b/docs/system-functional-test-cases.md index ad5e002..d04a4ac 100644 --- a/docs/system-functional-test-cases.md +++ b/docs/system-functional-test-cases.md @@ -5022,7 +5022,7 @@ npm run verify:phase8 | TC-REPORT-WORKBENCH-012 | 查看企业签名表头和签名列表 | 签名列不显示升序、降序或其他排序按钮;列表不显示逐行待生成明细字段;默认按创建时间倒序 | | TC-REPORT-WORKBENCH-013 | 通道报备明细当前页有10条数据,点击“全选当前页” | 当前页10条全部选中,按钮变为“取消全选”,批量数为10;翻页或查询后选择清空,不选中其他页面数据 | | TC-REPORT-WORKBENCH-014 | 生成同时包含签名和引流资料、覆盖多个通道的批次 | 每个通道生成一份简报;日期取批次生成日期,批次号一致;签名行和引流行分别按已确认格式展示,且可一键复制完整原文 | -| TC-REPORT-WORKBENCH-015 | 通道配置0个、1个或多个名称为“短信内容”的字段 | 0个时简报短信内容为空;1个时取该字段;多个时严格按`sortOrder ASC, createdAt ASC`取第一个字段值,后续同名字段不参与 | +| TC-REPORT-WORKBENCH-015 | 通道配置0个、1个或多个名称为“短信内容”的字段 | 0个时简报短信内容为空;1个时取资料中该字段的实际值;多个时严格按`sortOrder ASC, createdAt ASC`取第一个字段在资料中的实际值,后续同名字段不参与;资料未提供首字段时保持为空,不得使用通道缺省值冒充资料内容 | | TC-REPORT-WORKBENCH-016 | 批次生成后修改字段库或签名/引流资料 | 历史批次简报仍使用生成时固化的批次快照,不随当前资料改变;不新增数据库migration,不触发短信发送或队列 | ## TC-HIGH-FREQUENCY-QUERY-20260902 高频查询与按需详情