fix: align reporting filters and carrier quality

This commit is contained in:
hectorzhao
2026-07-28 20:55:50 +08:00
parent d8e5319647
commit 95c052e9ea
10 changed files with 172 additions and 52 deletions
+33 -1
View File
@@ -570,6 +570,24 @@ describe('OperationsService', () => {
averageArrivalMs: 1800,
},
]);
prisma.$queryRaw.mockResolvedValueOnce([
{
signatureId: 'signature-1',
carrier: 'mobile',
businessMessageCount: 3,
finalSuccessCount: 2,
finalSuccessRate: 66.7,
averageArrivalMs: 1100,
},
{
signatureId: 'signature-1',
carrier: 'telecom',
businessMessageCount: 2,
finalSuccessCount: 1,
finalSuccessRate: 50,
averageArrivalMs: 1800,
},
]);
const service = new OperationsService(prisma as never);
await expect(service.signatureQuality({
@@ -584,6 +602,20 @@ describe('OperationsService', () => {
signatureName: '【测试签名】',
total: 5,
channelSubmitTotal: 6,
carrierOverview: [
expect.objectContaining({
carrier: 'mobile',
businessMessageCount: 3,
finalSuccessCount: 2,
finalSuccessRate: 66.7,
}),
expect.objectContaining({
carrier: 'telecom',
businessMessageCount: 2,
finalSuccessCount: 1,
finalSuccessRate: 50,
}),
],
breakdowns: [
expect.objectContaining({ channelId: 'channel-1', carrier: 'mobile', total: 4 }),
expect.objectContaining({ channelId: 'channel-2', carrier: 'telecom', total: 2 }),
@@ -593,7 +625,7 @@ describe('OperationsService', () => {
page: 2,
pageSize: 5,
});
expect(prisma.$queryRaw).toHaveBeenCalledTimes(2);
expect(prisma.$queryRaw).toHaveBeenCalledTimes(3);
});
it('does not query channel details when the selected date has no registered signatures', async () => {
+44
View File
@@ -890,11 +890,55 @@ export class OperationsService {
GROUP BY signature_id, channel_id, carrier
ORDER BY signature_id, COUNT(*) DESC, channel_id, carrier
`);
const carrierOverview = signatureIds.length === 0
? []
: await this.prisma.$queryRaw<Array<{
signatureId: string;
carrier: string;
businessMessageCount: number;
finalSuccessCount: number;
finalSuccessRate: number;
averageArrivalMs: number | null;
}>>(Prisma.sql`
SELECT
message."signatureId" AS "signatureId",
COALESCE(NULLIF(message.carrier, ''), 'unknown') AS carrier,
COUNT(*)::integer AS "businessMessageCount",
COUNT(*) FILTER (
WHERE message.status = 'delivered'
OR message."receiptStatus" = 'delivered'
)::integer AS "finalSuccessCount",
CASE
WHEN COUNT(*) = 0 THEN 0
ELSE ROUND(
COUNT(*) FILTER (
WHERE message.status = 'delivered'
OR message."receiptStatus" = 'delivered'
) * 100.0 / COUNT(*),
1
)::double precision
END AS "finalSuccessRate",
ROUND(AVG(
CASE
WHEN (message.status = 'delivered' OR message."receiptStatus" = 'delivered')
AND message."submittedAt" IS NOT NULL
AND message."deliveredAt" >= message."submittedAt"
THEN EXTRACT(EPOCH FROM (message."deliveredAt" - message."submittedAt")) * 1000
END
))::integer AS "averageArrivalMs"
FROM "SmsMessageRecord" message
WHERE message."signatureId" IN (${Prisma.join(signatureIds)})
AND message."queuedAt" >= ${day.startAt}
AND message."queuedAt" < ${day.endAt}
GROUP BY message."signatureId", COALESCE(NULLIF(message.carrier, ''), 'unknown')
ORDER BY message."signatureId", COUNT(*) DESC, carrier
`);
const items = summaries.map(({ rowCount: _rowCount, ...summary }) => {
const signatureBreakdowns = breakdowns.filter((item) => item.signatureId === summary.signatureId);
return {
...summary,
channelSubmitTotal: signatureBreakdowns.reduce((sum, item) => sum + item.total, 0),
carrierOverview: carrierOverview.filter((item) => item.signatureId === summary.signatureId),
breakdowns: signatureBreakdowns,
};
});