feat: enhance operations dashboard and reporting controls
This commit is contained in:
@@ -33,6 +33,7 @@ function createPrismaMock() {
|
||||
findMany: jest.fn().mockResolvedValue([]),
|
||||
findUnique: jest.fn().mockResolvedValue(null),
|
||||
create: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'field-1', ...data })),
|
||||
update: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'field-1', ...data })),
|
||||
delete: jest.fn().mockResolvedValue({ id: 'field-1' }),
|
||||
},
|
||||
channelReportField: {
|
||||
@@ -46,6 +47,7 @@ function createPrismaMock() {
|
||||
count: jest.fn().mockResolvedValue(0),
|
||||
create: jest.fn().mockImplementation(({ data }) => Promise.resolve({ id: 'common-1', ...data })),
|
||||
delete: jest.fn().mockResolvedValue({ id: 'common-1' }),
|
||||
update: jest.fn(),
|
||||
},
|
||||
smsApplication: {
|
||||
findUnique: jest.fn().mockResolvedValue({ id: 'app-1', tenantId: 'tenant-1' }),
|
||||
@@ -76,6 +78,42 @@ describe('DictionariesService', () => {
|
||||
await expect(service.updateCommonReportField('common-1', body)).rejects.toThrow('已停用');
|
||||
await expect(service.updateCommonReportField('common-1', { ...body, required: 'false' as never })).rejects.toThrow('无效');
|
||||
});
|
||||
|
||||
it('reorders every common field in one report type transaction and writes an audit trail', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const tx = {
|
||||
commonReportField: {
|
||||
update: jest.fn().mockResolvedValue({}),
|
||||
findMany: jest.fn().mockResolvedValue([{ id: 'common-2' }, { id: 'common-1' }]),
|
||||
},
|
||||
operationLog: { create: jest.fn().mockResolvedValue({}) },
|
||||
};
|
||||
prisma.$transaction.mockImplementation((callback) => callback(tx));
|
||||
const service = new DictionariesService(prisma as never);
|
||||
|
||||
await expect(
|
||||
service.reorderCommonReportFields({ reportType: 'signature', ids: ['common-2', 'common-1'] }, 'admin-1'),
|
||||
).resolves.toEqual([{ id: 'common-2' }, { id: 'common-1' }]);
|
||||
expect(tx.commonReportField.update).toHaveBeenNthCalledWith(1, {
|
||||
where: { id: 'common-2' },
|
||||
data: { sortOrder: 10 },
|
||||
});
|
||||
expect(tx.commonReportField.update).toHaveBeenNthCalledWith(2, {
|
||||
where: { id: 'common-1' },
|
||||
data: { sortOrder: 20 },
|
||||
});
|
||||
expect(tx.operationLog.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({ action: 'common_report_field.reorder', userId: 'admin-1' }),
|
||||
});
|
||||
expect(prisma.$transaction).toHaveBeenCalledWith(expect.any(Function), { isolationLevel: 'Serializable' });
|
||||
tx.commonReportField.findMany.mockResolvedValue([{ id: 'common-1' }]);
|
||||
await expect(
|
||||
service.reorderCommonReportFields({ reportType: 'signature', ids: ['common-1'] }),
|
||||
).resolves.toEqual([{ id: 'common-1' }]);
|
||||
await expect(
|
||||
service.reorderCommonReportFields({ reportType: 'signature', ids: ['common-1', 'common-2'] }),
|
||||
).rejects.toThrow('排序范围已变化');
|
||||
});
|
||||
it('builds the enterprise province and city library from distinct real phone segment regions', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
prisma.phoneSegment.findMany.mockResolvedValue([
|
||||
@@ -130,6 +168,32 @@ describe('DictionariesService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('edits an unreferenced field atomically and protects mapping keys once referenced', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const existing = { id: 'field-1', code: 'license', name: '主体证明', fieldType: 'file', description: null };
|
||||
prisma.drainageField.findUnique.mockResolvedValue(existing as never);
|
||||
const tx = {
|
||||
drainageField: { update: jest.fn().mockResolvedValue({ ...existing, name: '企业主体证明', description: '最新版' }) },
|
||||
operationLog: { create: jest.fn().mockResolvedValue({}) },
|
||||
};
|
||||
prisma.$transaction.mockImplementation((callback) => callback(tx));
|
||||
const service = new DictionariesService(prisma as never);
|
||||
|
||||
await expect(service.updateDrainageField('field-1', {
|
||||
code: 'license', name: '企业主体证明', fieldType: 'file', description: ' 最新版 ',
|
||||
}, 'admin-1')).resolves.toEqual(expect.objectContaining({ name: '企业主体证明' }));
|
||||
expect(tx.drainageField.update).toHaveBeenCalledWith({
|
||||
where: { id: 'field-1' },
|
||||
data: { code: 'license', name: '企业主体证明', fieldType: 'file', description: '最新版' },
|
||||
});
|
||||
expect(tx.operationLog.create).toHaveBeenCalledWith({ data: expect.objectContaining({ action: 'drainage_field.update', userId: 'admin-1' }) });
|
||||
|
||||
prisma.channelReportField.count.mockResolvedValue(1);
|
||||
await expect(service.updateDrainageField('field-1', {
|
||||
code: 'newCode', name: '企业主体证明', fieldType: 'file', description: '',
|
||||
})).rejects.toThrow('不能修改字段代码或类型');
|
||||
});
|
||||
|
||||
it('ignores deleted-channel references and removes those stale mappings when deleting the field', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
const tx = {
|
||||
|
||||
Reference in New Issue
Block a user