feat: harden CMPP delivery and platform workflows

This commit is contained in:
hectorzhao
2026-07-20 18:07:29 +08:00
parent 80fb5a8f53
commit f02c33cbb7
61 changed files with 1834 additions and 281 deletions
@@ -2,6 +2,33 @@ import ExcelJS from 'exceljs';
import { ReportMaterialsService } from './report-materials.service';
describe('ReportMaterialsService', () => {
it('builds an official XLSX import template with documented signature columns', async () => {
const operationLog = { create: jest.fn().mockResolvedValue({ id: 'log-template' }) };
const service = new ReportMaterialsService({ operationLog } as never, {} as never, {} as never);
const exported = await service.buildOfficialTemplate('signature', 'operator-1');
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.load(exported.content as never);
expect(exported.fileName).toContain('签名报备资料官方模板');
expect(workbook.worksheets[0].getRow(1).values).toEqual(expect.arrayContaining(['短信签名', '用途说明']));
expect(operationLog.create).toHaveBeenCalledWith({ data: expect.objectContaining({ userId: 'operator-1' }) });
});
it('rejects formula cells before storing or importing a workbook', async () => {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('签名资料');
sheet.addRow(['短信签名']);
sheet.getCell('A2').value = { formula: 'HYPERLINK("https://invalid.example","click")', result: 'click' };
const buffer = Buffer.from(await workbook.xlsx.writeBuffer());
const files = { upload: jest.fn() };
const service = new ReportMaterialsService({ reportMaterialImportProfile: { findUnique: jest.fn() } } as never, files as never, {} as never);
await expect(service.analyzeImport(
{ originalname: 'unsafe.xlsx', mimetype: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', size: buffer.length, buffer },
{ tenantId: 'tenant-1', reportType: 'signature', headerRowCount: 1, dataStartRow: 2 },
)).rejects.toThrow('公式或可执行单元格');
expect(files.upload).not.toHaveBeenCalled();
});
it('detects WPS-compatible embedded images and source columns during XLSX analysis', async () => {
const workbook = new ExcelJS.Workbook();
const sheet = workbook.addWorksheet('签名资料');
@@ -13,6 +40,7 @@ describe('ReportMaterialsService', () => {
const prisma = {
reportMaterialImportProfile: { findUnique: jest.fn().mockResolvedValue({ sheetName: '签名资料', columns: [{ sourceHeader: '短信签名', sourceHeaderPath: '短信签名', sourceColumnIndex: 9, targetFieldCode: 'signature_name', targetKind: 'signatureName', fieldType: 'string', required: true, sortOrder: 10 }] }) },
reportMaterialImportBatch: { create: jest.fn().mockImplementation(({ data }: { data: Record<string, unknown> }) => Promise.resolve({ id: 'import-1', ...data })) },
operationLog: { create: jest.fn().mockResolvedValue({ id: 'log-1' }) },
};
const files = { upload: jest.fn().mockResolvedValue({ id: 'source-1', fileName: '签名资料.xlsx', contentType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }) };
const service = new ReportMaterialsService(prisma as never, files as never, {} as never);