feat: aggregate cmpp template mismatch reviews
This commit is contained in:
@@ -33,16 +33,65 @@ function createPrismaMock(overrides: Record<string, unknown> = {}) {
|
||||
findUnique: jest.fn().mockResolvedValue({ id: 'risk-task-1', riskHits: [] }),
|
||||
update: jest.fn(),
|
||||
findMany: jest.fn(),
|
||||
upsert: jest.fn().mockImplementation(({ create }: { create: Record<string, unknown> }) => Promise.resolve({ id: 'review-task-1', ...create })),
|
||||
},
|
||||
smsMessageRecord: {
|
||||
update: jest.fn().mockResolvedValue({ id: 'message-1' }),
|
||||
},
|
||||
riskHitRecord: {
|
||||
createMany: jest.fn(),
|
||||
findMany: jest.fn(),
|
||||
},
|
||||
$transaction: jest.fn(async (callback) => callback({
|
||||
smsSendTask: {
|
||||
upsert: jest.fn().mockImplementation(({ create }: { create: Record<string, unknown> }) => Promise.resolve({ id: 'review-task-1', ...create })),
|
||||
},
|
||||
smsMessageRecord: {
|
||||
update: jest.fn().mockResolvedValue({ id: 'message-1' }),
|
||||
},
|
||||
})),
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
describe('RiskReviewService', () => {
|
||||
it('groups identical CMPP template mismatches into a deterministic short review window', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
prisma.smsSendTask.findUnique.mockResolvedValue({
|
||||
id: 'review-task-1',
|
||||
sourceType: 'cmpp_template_mismatch',
|
||||
phoneTotal: 2,
|
||||
_count: { messageRecords: 2 },
|
||||
riskHits: [],
|
||||
});
|
||||
const service = new RiskReviewService(prisma as never);
|
||||
|
||||
const result = await service.aggregateTemplateMismatch({
|
||||
tenantId: 'tenant-1',
|
||||
applicationId: 'app-1',
|
||||
account: '100001',
|
||||
messageRecordId: 'message-1',
|
||||
signatureId: 'sig-1',
|
||||
content: '【签名】同一审核内容',
|
||||
});
|
||||
|
||||
expect(prisma.$transaction).toHaveBeenCalledTimes(1);
|
||||
expect(result).toEqual(expect.objectContaining({ sourceType: 'cmpp_template_mismatch', phoneTotal: 2 }));
|
||||
});
|
||||
|
||||
it('does not allow an aggregated review task to be decided before its window closes', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
prisma.smsSendTask.findUnique.mockResolvedValue({
|
||||
id: 'review-task-1',
|
||||
sourceType: 'cmpp_template_mismatch',
|
||||
windowEndsAt: new Date(Date.now() + 10_000),
|
||||
});
|
||||
const service = new RiskReviewService(prisma as never);
|
||||
|
||||
await expect(service.approveTask('review-task-1', { reason: '通过' })).rejects.toThrow('聚合窗口尚未关闭');
|
||||
expect(prisma.smsSendTask.update).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects tasks over the application max phone threshold', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
prisma.smsApplication.findUnique.mockResolvedValue({ id: 'app-1', maxPhonesPerTask: 2 });
|
||||
|
||||
Reference in New Issue
Block a user