feat: scope blacklists and paginate phone segments
This commit is contained in:
@@ -81,6 +81,7 @@ describe('RiskReviewService', () => {
|
||||
it('routes duplicate and blacklist ratio hits to manual review', async () => {
|
||||
const prisma = createPrismaMock();
|
||||
prisma.globalBlacklist.findMany.mockResolvedValue([{ phoneNumber: '13800000001' }]);
|
||||
prisma.enterpriseBlacklist.findMany.mockResolvedValue([{ phoneNumber: '13800000002' }]);
|
||||
prisma.riskRule.findMany.mockResolvedValue([
|
||||
{
|
||||
id: 'rule-dup',
|
||||
@@ -105,6 +106,7 @@ describe('RiskReviewService', () => {
|
||||
const service = new RiskReviewService(prisma as never);
|
||||
const result = await service.evaluateTask({
|
||||
tenantId: 'tenant-1',
|
||||
applicationId: 'app-1',
|
||||
content: 'hello',
|
||||
phones: ['13800000001', '13800000001', '13800000002'],
|
||||
});
|
||||
@@ -113,11 +115,15 @@ describe('RiskReviewService', () => {
|
||||
expect(prisma.smsSendTask.create).toHaveBeenCalledWith({
|
||||
data: expect.objectContaining({
|
||||
duplicateRatio: 0.3333,
|
||||
blacklistHitRatio: 0.3333,
|
||||
blacklistHitRatio: 0.6667,
|
||||
status: 'pending_review',
|
||||
riskDecision: 'manual_review',
|
||||
}),
|
||||
});
|
||||
expect(prisma.enterpriseBlacklist.findMany).toHaveBeenCalledWith({
|
||||
where: { tenantId: 'tenant-1', applicationId: 'app-1', phoneNumber: { in: ['13800000001', '13800000002'] }, status: 'active' },
|
||||
select: { phoneNumber: true },
|
||||
});
|
||||
expect(prisma.riskHitRecord.createMany).toHaveBeenCalledWith({
|
||||
data: expect.arrayContaining([
|
||||
expect.objectContaining({ ruleCode: 'DUPLICATE_PHONE_RATIO' }),
|
||||
|
||||
@@ -181,7 +181,7 @@ export class RiskReviewService {
|
||||
const duplicateRatio = ratio(phoneTotal - uniquePhoneTotal, phoneTotal);
|
||||
const illegalCount = phones.filter((phone) => !isMainlandMobile(phone)).length;
|
||||
const illegalRatio = ratio(illegalCount, phoneTotal);
|
||||
const blacklistHitCount = await this.countBlacklistHits(data.tenantId, uniquePhones);
|
||||
const blacklistHitCount = await this.countBlacklistHits(data.tenantId, data.applicationId, uniquePhones);
|
||||
const blacklistHitRatio = ratio(blacklistHitCount, phoneTotal);
|
||||
const [application, template, rules, recentTaskCount, sensitiveWords] = await Promise.all([
|
||||
data.applicationId ? this.prisma.smsApplication.findUnique({ where: { id: data.applicationId } }) : null,
|
||||
@@ -324,7 +324,7 @@ export class RiskReviewService {
|
||||
return [...byCode.values()].sort((a, b) => a.priority - b.priority);
|
||||
}
|
||||
|
||||
private async countBlacklistHits(tenantId: string, phones: string[]) {
|
||||
private async countBlacklistHits(tenantId: string, applicationId: string | undefined, phones: string[]) {
|
||||
if (phones.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
@@ -333,10 +333,10 @@ export class RiskReviewService {
|
||||
where: { phoneNumber: { in: phones }, status: 'active' },
|
||||
select: { phoneNumber: true },
|
||||
}),
|
||||
this.prisma.enterpriseBlacklist.findMany({
|
||||
where: { tenantId, phoneNumber: { in: phones }, status: 'active' },
|
||||
applicationId ? this.prisma.enterpriseBlacklist.findMany({
|
||||
where: { tenantId, applicationId, phoneNumber: { in: phones }, status: 'active' },
|
||||
select: { phoneNumber: true },
|
||||
}),
|
||||
}) : Promise.resolve([]),
|
||||
]);
|
||||
return new Set([...globalHits, ...enterpriseHits].map((hit) => hit.phoneNumber)).size;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user