release: prepare RealeseV2.3
This commit is contained in:
@@ -71,7 +71,7 @@ async dashboard(query: { tenantId?: string }) {
|
||||
_count: { _all: true },
|
||||
_sum: { currentConnections: true, desiredConnections: true },
|
||||
}),
|
||||
this.countPendingAudits(query.tenantId),
|
||||
this.pendingAudits(query.tenantId),
|
||||
this.prisma.tenantAccount.findMany({
|
||||
where: query.tenantId ? { tenantId: query.tenantId } : undefined,
|
||||
include: { tenant: true },
|
||||
@@ -358,7 +358,7 @@ async clientDashboard(query: { tenantId?: string }) {
|
||||
},
|
||||
};
|
||||
}
|
||||
private countPendingAudits(tenantId?: string) {
|
||||
pendingAudits(tenantId?: string) {
|
||||
return Promise.all([
|
||||
this.prisma.smsTemplate.count({ where: { tenantId, auditStatus: 'pending' } }),
|
||||
this.prisma.smsSignature.count({ where: { tenantId, auditStatus: 'pending' } }),
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Prisma } from '@prisma/client';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import { moneyToNumber } from '../../common/money';
|
||||
import { PrismaService } from '../../prisma/prisma.service';
|
||||
import type { MessageQuery, TraceQuery, OperationLogQuery, GatewaySubmitDeadLetterQuery, DownstreamDeliveryQuery, DownstreamDeliveryDashboardQuery, DownstreamRecoveryStatusQuery, MessageSegmentAuditQuery, SignatureQualityQuery } from '../operations.contracts';
|
||||
import type { MessageQuery, TraceQuery, OperationLogQuery, GatewaySubmitDeadLetterQuery, ReceiptAnomalyQuery, DownstreamDeliveryQuery, DownstreamDeliveryDashboardQuery, DownstreamRecoveryStatusQuery, MessageSegmentAuditQuery, SignatureQualityQuery } from '../operations.contracts';
|
||||
import { recognizedCarrierValues, carrierWhere, startOfShanghaiDay, endOfShanghaiDay, qualityBusinessDay, shanghaiDateKey, normalizeGroupBy, returnedTransactionWhere, createdAtRange, downstreamAlertPendingMinutes, downstreamAlertRecentFailedHours, downstreamAlertWindows, downstreamAlertWhere, stalledPendingWhere, downstreamDeliveryScopedWhere, parseDateBoundary, downstreamRecoveryStatusWhere, escapeCsvCell, formatCsvDate, formatExportTimestamp, clientApplicationView, clientReceiptView, clientMessageView, clientBatchTaskView, clientUplinkView, clientAccountView, clientRechargeView, summarizeMessageGroups, groupDownstreamByType, groupDownstreamByApplication, positiveInteger, operationLogLevelWhere, normalizeOperationLog, sanitizeGatewaySubmitException, redactGatewayCommandValue } from '../operations.helpers';
|
||||
|
||||
// R2 downstream query domain. Method bodies are preserved byte-for-byte from the facade baseline.
|
||||
@@ -73,6 +73,67 @@ async listGatewaySubmitDeadLetters(query: GatewaySubmitDeadLetterQuery) {
|
||||
},
|
||||
};
|
||||
}
|
||||
async listReceiptAnomalies(query: ReceiptAnomalyQuery) {
|
||||
const page = Math.max(1, Number(query.page ?? 1));
|
||||
const pageSize = Math.min(100, Math.max(1, Number(query.pageSize ?? 10)));
|
||||
const baseWhere: Prisma.SmsReceiptAnomalyWhereInput = {
|
||||
tenantId: query.tenantId,
|
||||
applicationId: query.applicationId,
|
||||
channelId: query.channelId,
|
||||
anomalyType: query.anomalyType && query.anomalyType !== 'all' ? query.anomalyType : undefined,
|
||||
OR: query.keyword ? [
|
||||
{ anomalyKey: { contains: query.keyword } },
|
||||
{ rawStatus: { contains: query.keyword } },
|
||||
{ errorCode: { contains: query.keyword } },
|
||||
{ messageRecord: { messageId: { contains: query.keyword } } },
|
||||
{ submitRecord: { submitId: { contains: query.keyword } } },
|
||||
] : undefined,
|
||||
};
|
||||
const where: Prisma.SmsReceiptAnomalyWhereInput = {
|
||||
...baseWhere,
|
||||
status: query.status && query.status !== 'all' ? query.status : undefined,
|
||||
};
|
||||
const [items, total, statusGroups, oldestPending] = await Promise.all([
|
||||
this.prisma.smsReceiptAnomaly.findMany({
|
||||
where,
|
||||
include: {
|
||||
tenant: { select: { id: true, name: true } },
|
||||
application: { select: { id: true, name: true } },
|
||||
channel: { select: { id: true, code: true, name: true, status: true } },
|
||||
messageRecord: { select: { messageId: true, phoneNumber: true, status: true } },
|
||||
submitRecord: { select: { submitId: true, submitStatus: true } },
|
||||
receiptRecord: { select: { gatewayMessageId: true, receiptStatus: true, rawStatus: true, deliveredAt: true } },
|
||||
},
|
||||
orderBy: [{ lastOccurredAt: 'desc' }, { id: 'desc' }],
|
||||
skip: (page - 1) * pageSize,
|
||||
take: pageSize,
|
||||
}),
|
||||
this.prisma.smsReceiptAnomaly.count({ where }),
|
||||
this.prisma.smsReceiptAnomaly.groupBy({
|
||||
by: ['status'],
|
||||
where: baseWhere,
|
||||
_count: { _all: true },
|
||||
}),
|
||||
this.prisma.smsReceiptAnomaly.findFirst({
|
||||
where: { ...baseWhere, status: 'pending' },
|
||||
orderBy: { firstOccurredAt: 'asc' },
|
||||
select: { firstOccurredAt: true },
|
||||
}),
|
||||
]);
|
||||
const statusCounts = new Map(statusGroups.map((item) => [item.status, item._count._all]));
|
||||
return {
|
||||
items,
|
||||
total,
|
||||
page,
|
||||
pageSize,
|
||||
summary: {
|
||||
pending: statusCounts.get('pending') ?? 0,
|
||||
resolved: statusCounts.get('resolved') ?? 0,
|
||||
ignored: statusCounts.get('ignored') ?? 0,
|
||||
oldestPendingAt: oldestPending?.firstOccurredAt ?? null,
|
||||
},
|
||||
};
|
||||
}
|
||||
async listDownstreamDeliveries(query: DownstreamDeliveryQuery) {
|
||||
const page = Math.max(1, Number(query.page ?? 1));
|
||||
const pageSize = Math.min(100, Math.max(1, Number(query.pageSize ?? 10)));
|
||||
|
||||
Reference in New Issue
Block a user