feat: improve operations diagnostics and channel management

This commit is contained in:
hectorzhao
2026-08-09 14:27:19 +08:00
parent 44352aeb2f
commit 4724b9db6a
65 changed files with 1211 additions and 293 deletions
@@ -68,6 +68,29 @@ describe('DeletionGovernanceService', () => {
]));
});
it('does not classify approved or abandoned report history as unfinished', async () => {
const { service, prisma } = setup();
prisma.smsSignature.findFirst.mockResolvedValue({
id: 'signature-1', name: '示例签名', auditStatus: 'approved', updatedAt: now,
tenant: { name: '示例企业' }, application: { name: '验证码应用' },
templates: [], drainageItems: [], reportTasks: [],
});
const result = await service.preflight('signature', 'signature-1', 'tenant-1');
expect(prisma.smsSignature.findFirst).toHaveBeenCalledWith(expect.objectContaining({
include: expect.objectContaining({
reportTasks: expect.objectContaining({
where: { status: { notIn: expect.arrayContaining(['approved', 'abandoned']) } },
}),
}),
}));
expect(result.dependencies).toEqual(expect.arrayContaining([
expect.objectContaining({ kind: 'report_tasks', count: 0 }),
]));
expect(result.allowedActions).toEqual(['delete']);
});
it('requires version, idempotency key and a meaningful reason', async () => {
const { service } = setup();
await expect(service.delete('template', 'template-1', {})).rejects.toBeInstanceOf(BadRequestException);
@@ -13,6 +13,10 @@ export type DeleteTargetDto = {
type Dependency = { kind: string; label: string; count: number; items: string[] };
// Report tasks use more terminal values than generic send tasks. Keep this explicit so
// completed approval and deliberately abandoned history do not block signature deletion.
const TERMINAL_REPORT_TASK_STATUSES = ['approved', 'completed', 'failed', 'cancelled', 'rejected', 'abandoned', 'partial', 'partial_success'];
export type DeletionPreflight = {
type: DeletionTargetType;
id: string;
@@ -114,7 +118,7 @@ export class DeletionGovernanceService {
tenant: { select: { name: true } }, application: { select: { name: true } },
templates: { where: { auditStatus: { not: 'deleted' } }, select: { id: true, name: true } },
drainageItems: { where: { auditStatus: { not: 'deleted' } }, select: { id: true, siteName: true } },
reportTasks: { where: { status: { notIn: ['completed', 'failed', 'cancelled', 'rejected'] } }, select: { id: true, status: true } },
reportTasks: { where: { status: { notIn: TERMINAL_REPORT_TASK_STATUSES } }, select: { id: true, status: true } },
},
});
if (!item) throw new NotFoundException('签名不存在或无权访问');