feat: inherit channel report requirements

This commit is contained in:
hectorzhao
2026-07-12 16:14:54 +08:00
parent 053bcca990
commit 87ae4a2063
14 changed files with 612 additions and 65 deletions
+22
View File
@@ -94,6 +94,9 @@ function createPrismaMock() {
findMany: jest.fn(),
create: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'field-1', ...data })),
},
drainageField: {
findUnique: jest.fn().mockResolvedValue({ id: 'library-1', code: 'license', name: '营业执照', fieldType: 'file', required: true, status: 'active', description: '执照文件' }),
},
signatureReportMaterial: {
findMany: jest.fn().mockResolvedValue([{ signatureId: 'sig-1', fieldCode: 'license', fieldValue: '营业执照', fileObjectId: 'file-1' }]),
createMany: jest.fn(),
@@ -152,6 +155,25 @@ function createPrismaMock() {
}
describe('ChannelsService', () => {
it('creates channel report requirements only from the report field library', async () => {
const prisma = createPrismaMock();
const service = new ChannelsService(prisma as never);
await service.createReportField({ channelId: 'channel-1', drainageFieldId: 'library-1', reportType: 'signature', code: 'ignored', name: 'ignored', fieldType: 'string' });
expect(prisma.channelReportField.create).toHaveBeenCalledWith({
data: expect.objectContaining({
channelId: 'channel-1',
drainageFieldId: 'library-1',
reportType: 'signature',
code: 'license',
name: '营业执照',
fieldType: 'file',
required: true,
}),
});
});
beforeEach(() => {
mockQueueAdd.mockClear();
mockQueueClose.mockClear();
+26 -9
View File
@@ -75,9 +75,11 @@ export interface CreateRouteRuleDto {
export interface CreateReportFieldDto {
channelId: string;
code: string;
name: string;
fieldType: string;
drainageFieldId: string;
reportType: 'signature' | 'drainage' | 'both';
code?: string;
name?: string;
fieldType?: string;
required?: boolean;
description?: string;
sortOrder?: number;
@@ -363,6 +365,8 @@ export class ChannelsService implements OnModuleInit, OnModuleDestroy {
config: source.config as Prisma.InputJsonValue | undefined,
reportFields: {
create: source.reportFields.map((field) => ({
drainageFieldId: field.drainageFieldId,
reportType: field.reportType,
code: field.code,
name: field.name,
fieldType: field.fieldType,
@@ -894,19 +898,27 @@ export class ChannelsService implements OnModuleInit, OnModuleDestroy {
listReportFields(channelId?: string) {
return this.prisma.channelReportField.findMany({
where: channelId ? { channelId } : undefined,
include: { drainageField: true },
orderBy: [{ sortOrder: 'asc' }, { createdAt: 'desc' }],
});
}
createReportField(data: CreateReportFieldDto) {
async createReportField(data: CreateReportFieldDto) {
const field = await this.prisma.drainageField.findUnique({ where: { id: data.drainageFieldId } });
if (!field || field.status !== 'active') {
throw new BadRequestException('报备字段库字段不存在或已停用');
}
const reportType = normalizeReportType(data.reportType);
return this.prisma.channelReportField.create({
data: {
channelId: data.channelId,
code: data.code,
name: data.name,
fieldType: data.fieldType,
required: data.required ?? false,
description: data.description,
drainageFieldId: field.id,
reportType,
code: field.code,
name: field.name,
fieldType: field.fieldType,
required: data.required ?? field.required,
description: data.description ?? field.description,
sortOrder: data.sortOrder ?? 100,
status: data.status ?? 'active',
},
@@ -1627,6 +1639,11 @@ function validateGroupItems(
}
}
function normalizeReportType(value?: string) {
if (value === 'signature' || value === 'drainage' || value === 'both') return value;
throw new BadRequestException('reportType must be signature, drainage or both');
}
function normalizeLinkEvent(action: string) {
if (action.includes('connect_requested')) {
return '连接请求';