fix: complete first version issue remediation

This commit is contained in:
hectorzhao
2026-07-11 10:14:37 +08:00
parent 709ac97764
commit 208a6c23f8
73 changed files with 1549 additions and 245 deletions
@@ -34,9 +34,25 @@ export class AdminOperationsController {
@Query('taskId') taskId?: string,
@Query('messageId') messageId?: string,
@Query('phoneNumber') phoneNumber?: string,
@Query('contentKeyword') contentKeyword?: string,
@Query('channelKeyword') channelKeyword?: string,
@Query('queuedAtFrom') queuedAtFrom?: string,
@Query('queuedAtTo') queuedAtTo?: string,
@Query('status') status?: string,
) {
return this.operations.listMessages({ tenantId, applicationId, channelId, taskId, messageId, phoneNumber, status });
return this.operations.listMessages({
tenantId,
applicationId,
channelId,
taskId,
messageId,
phoneNumber,
contentKeyword,
channelKeyword,
queuedAtFrom,
queuedAtTo,
status,
});
}
@Get('message-segment-audits')
+15 -2
View File
@@ -6,6 +6,9 @@ function createPrismaMock() {
findMany: jest.fn().mockResolvedValue([{ id: 'task-1', taskNo: 'BATCH-1' }]),
count: jest.fn().mockResolvedValue(3),
},
smsSendTask: {
count: jest.fn().mockResolvedValue(2),
},
smsMessageRecord: {
findMany: jest.fn().mockResolvedValue([{ messageId: 'MSG-1' }]),
groupBy: jest.fn().mockResolvedValue([{ status: 'delivered', _count: { _all: 2 }, _sum: { amountCents: 20, billingUnits: 2 } }]),
@@ -163,7 +166,7 @@ function createPrismaMock() {
}
describe('OperationsService', () => {
it('filters send-chain messages by tenant, application, channel, task, phone, and status', async () => {
it('filters send-chain messages by tenant, application, channel, content, date, task, phone, and status', async () => {
const prisma = createPrismaMock();
const service = new OperationsService(prisma as never);
@@ -171,9 +174,13 @@ describe('OperationsService', () => {
tenantId: 'tenant-1',
applicationId: 'app-1',
channelId: 'channel-1',
channelKeyword: '移动通道',
taskId: 'task-1',
messageId: 'MSG-1',
phoneNumber: '13800000001',
contentKeyword: '验证码',
queuedAtFrom: '2026-07-01',
queuedAtTo: '2026-07-02',
status: 'delivered',
});
@@ -186,6 +193,12 @@ describe('OperationsService', () => {
messageId: 'MSG-1',
phoneNumber: '13800000001',
status: 'delivered',
content: { contains: '验证码', mode: 'insensitive' },
channel: { name: { contains: '移动通道', mode: 'insensitive' } },
queuedAt: {
gte: new Date('2026-07-01T00:00:00+08:00'),
lte: new Date('2026-07-02T23:59:59.999+08:00'),
},
},
include: { tenant: true, application: true, channel: true, submitRecords: true, receiptRecords: true },
orderBy: { queuedAt: 'desc' },
@@ -234,7 +247,7 @@ describe('OperationsService', () => {
expect.objectContaining({
taskCount: 3,
uplinkCount: 1,
pendingAuditCount: 6,
pendingAuditCount: 5,
gatewayConnections: [{ status: 'connected', _count: { _all: 1 }, _sum: { currentConnections: 2, desiredConnections: 2 } }],
downstreamDeliverySummary: expect.objectContaining({
pending: 3,
+21 -1
View File
@@ -6,10 +6,14 @@ export interface MessageQuery {
tenantId?: string;
applicationId?: string;
channelId?: string;
channelKeyword?: string;
taskId?: string;
messageId?: string;
phoneNumber?: string;
contentKeyword?: string;
status?: string;
queuedAtFrom?: string;
queuedAtTo?: string;
}
export interface TraceQuery extends MessageQuery {
@@ -731,7 +735,7 @@ export class OperationsService {
this.prisma.smsTemplate.count({ where: { tenantId, auditStatus: 'pending' } }),
this.prisma.smsSignature.count({ where: { tenantId, auditStatus: 'pending' } }),
this.prisma.enterpriseCertification.count({ where: { tenantId, status: 'pending' } }),
this.prisma.smsBatchTask.count({ where: { tenantId, auditStatus: 'pending' } }),
this.prisma.smsSendTask.count({ where: { tenantId, status: 'pending_review' } }),
]).then((counts) => counts.reduce((sum, value) => sum + value, 0));
}
@@ -756,9 +760,25 @@ function messageWhere(query: MessageQuery): Prisma.SmsMessageRecordWhereInput {
messageId: query.messageId,
phoneNumber: query.phoneNumber,
status: query.status,
...(query.contentKeyword ? { content: { contains: query.contentKeyword, mode: 'insensitive' } } : {}),
...(query.channelKeyword ? { channel: { name: { contains: query.channelKeyword, mode: 'insensitive' } } } : {}),
...(query.queuedAtFrom || query.queuedAtTo ? {
queuedAt: {
...(query.queuedAtFrom ? { gte: startOfShanghaiDay(query.queuedAtFrom) } : {}),
...(query.queuedAtTo ? { lte: endOfShanghaiDay(query.queuedAtTo) } : {}),
},
} : {}),
};
}
function startOfShanghaiDay(value: string) {
return new Date(`${value}T00:00:00+08:00`);
}
function endOfShanghaiDay(value: string) {
return new Date(`${value}T23:59:59.999+08:00`);
}
function normalizeGroupBy(groupBy?: string) {
if (groupBy === 'tenant' || groupBy === 'tenantId') {
return 'tenantId';