feat: refine template deletion and channel group filters

This commit is contained in:
hectorzhao
2026-08-09 20:54:52 +08:00
parent 482d332f49
commit 78b839f468
11 changed files with 210 additions and 49 deletions
+13 -3
View File
@@ -14,7 +14,7 @@ import { PhoneFrequencyService } from '../risk-review/phone-frequency.service';
import type { CreateBatchTaskDto, CreateHttpBatchTaskDto, GatewayInboundAuthDto, GatewayInboundSubmitDto, GatewayInboundSingleSubmitResult, ImportPreviewDto, ConfirmImportDto, SendJob, QueuePriority, RoutedChannel } from './send-chain.contracts';
import { SEND_QUEUE, GATEWAY_SUBMIT_QUEUE, GATEWAY_SUBMIT_STREAM, DEFAULT_SCHEDULED_DISPATCH_STALE_MS, DEFAULT_INBOUND_LONG_MESSAGE_PROCESSING_STALE_SECONDS, GATEWAY_SUBMIT_REQUEUE_IDEMPOTENCY_TTL_SECONDS, BULLMQ_PRIORITY, statusFromRisk, parseSchedule, parseImportRows, splitImportLine, cellByHeader, normalizeCarrier, normalizeQueuePriority, getPositiveConfigInteger, getNonNegativeConfigInteger, isCarrierCompatible, matchTemplateContent, isNationalChannel, validateInboundApplicationSrcId, composeUpstreamSrcId, positiveInteger, parseOptionalSequenceId, shanghaiDateKey, bullmqConnection, matchesApplicationSecret, octetString, selectChannelCandidate } from './send-chain.helpers';
import { detectDrainageContent } from './drainage-content-detection';
import type { SendSubmissionCallbacks, SendSubmissionService } from './send-submission.service';
import type { SendResourceValidationOptions, SendSubmissionCallbacks, SendSubmissionService } from './send-submission.service';
/**
* R9 batchEntry implementation. Cross-method calls return through the stable SendChainService seam.
@@ -469,7 +469,12 @@ async classifyRejectedPhones(tenantId: string, applicationId: string | undefined
return rejected;
}
async validateSendResources(tenantId: string, applicationId?: string, templateId?: string) {
async validateSendResources(
tenantId: string,
applicationId?: string,
templateId?: string,
options: SendResourceValidationOptions = {},
) {
const tenant = await this.prisma.tenant.findUnique({ where: { id: tenantId } });
if (!tenant || tenant.status !== 'active') {
throw new BadRequestException('企业客户不存在或已停用');
@@ -494,7 +499,12 @@ async validateSendResources(tenantId: string, applicationId?: string, templateId
where: { id: templateId },
include: { signature: true },
});
if (!template || template.tenantId !== tenantId || template.applicationId !== applicationId || template.auditStatus !== 'approved') {
const templateBelongsToApplication = template
&& template.tenantId === tenantId
&& template.applicationId === applicationId;
// 定时任务在创建时已通过模板审核并持久化内容快照;后续删除模板只能阻止新任务,
// 不应追溯性地使已接受任务失败。但仍校验租户、应用归属和签名当前安全状态。
if (!templateBelongsToApplication || (!options.usePersistedTemplateSnapshot && template.auditStatus !== 'approved')) {
throw new BadRequestException('短信模板不存在、未通过审核或不属于当前应用');
}
if (!template.signature || template.signature.auditStatus !== 'approved') {