fix: align daily operations statistics

This commit is contained in:
hectorzhao
2026-07-24 22:08:06 +08:00
parent c78ed1cc32
commit 53736c96e8
9 changed files with 433 additions and 77 deletions
+66 -3
View File
@@ -222,11 +222,38 @@ describe('OperationsService', () => {
lte: new Date('2026-07-02T23:59:59.999+08:00'),
},
},
include: { tenant: true, application: true, channel: true, submitRecords: true, receiptRecords: true },
include: {
tenant: true,
application: true,
channel: true,
submitRecords: true,
receiptRecords: true,
downstreamDeliveries: {
where: { deliveryType: 'receipt' },
select: { id: true, deliveryType: true, status: true, deliveredAt: true, lastError: true },
},
},
orderBy: { queuedAt: 'desc' },
});
});
it('separates upstream submit failures from post-acceptance delivery failures', async () => {
const prisma = createPrismaMock();
const service = new OperationsService(prisma as never);
await service.listMessages({ status: 'submit_failed' });
expect(prisma.smsMessageRecord.findMany).toHaveBeenLastCalledWith(expect.objectContaining({
where: expect.objectContaining({
OR: [{ status: 'submit_failed' }, { submitStatus: { in: ['rejected', 'timeout'] } }],
}),
}));
await service.listMessages({ status: 'failed' });
expect(prisma.smsMessageRecord.findMany).toHaveBeenLastCalledWith(expect.objectContaining({
where: expect.objectContaining({ status: 'failed', submitStatus: 'accepted' }),
}));
});
it('returns uplink messages with tenant and channel display data', async () => {
const prisma = createPrismaMock();
const service = new OperationsService(prisma as never);
@@ -399,6 +426,9 @@ describe('OperationsService', () => {
channelId: 'channel-1',
channelName: '通道一',
total: 5,
acceptedCount: 4,
submitFailureCount: 1,
submitFailureRate: 20,
successCount: 3,
unknownCount: 1,
failureCount: 1,
@@ -420,15 +450,48 @@ describe('OperationsService', () => {
failureCount: 1,
successRate: 60,
averageArrivalMs: 1200,
}])
.mockResolvedValueOnce([{
total: 5,
successCount: 3,
unknownCount: 1,
failureCount: 1,
successRate: 60,
}])
.mockResolvedValueOnce([{
applicationId: 'app-1',
applicationName: '通知应用',
tenantId: 'tenant-1',
tenantName: '租户A',
total: 5,
successCount: 3,
unknownCount: 1,
failureCount: 1,
successRate: 60,
}]);
const service = new OperationsService(prisma as never);
await expect(service.sendQuality('2026-07-24')).resolves.toEqual({
date: '2026-07-24',
channels: [expect.objectContaining({ channelId: 'channel-1', total: 5, successRate: 60 })],
summary: {
total: 5,
successCount: 3,
unknownCount: 1,
failureCount: 1,
successRate: 60,
},
channels: [expect.objectContaining({
channelId: 'channel-1',
total: 5,
acceptedCount: 4,
submitFailureCount: 1,
submitFailureRate: 20,
successRate: 60,
})],
signatures: [expect.objectContaining({ signatureId: 'signature-1', signatureName: '【测试签名】', hasDrainage: false })],
applications: [expect.objectContaining({ applicationId: 'app-1', applicationName: '通知应用', tenantName: '租户A', total: 5 })],
});
expect(prisma.$queryRaw).toHaveBeenCalledTimes(2);
expect(prisma.$queryRaw).toHaveBeenCalledTimes(4);
});
it('rejects invalid send quality dates', async () => {