fix: close receipt delivery workflows

This commit is contained in:
hectorzhao
2026-07-24 14:40:57 +08:00
parent 2ee39056eb
commit 91f04f5288
22 changed files with 829 additions and 48 deletions
@@ -455,6 +455,37 @@ describe('SmsConfigService', () => {
}));
});
it('derives both downstream delivery modes when CMPP is enabled alongside HTTP', async () => {
const prisma = createPrismaMock();
prisma.smsApplication.findUnique.mockResolvedValue({
id: 'app-1',
tenantId: 'tenant-1',
cmppAccount: '100001',
interfaceEnabled: false,
httpConfig: { enabled: true },
});
const tx = {
smsApplication: {
update: jest.fn().mockResolvedValue({ id: 'app-1', interfaceEnabled: true }),
},
smsApplicationHttpConfig: {
update: jest.fn().mockResolvedValue({}),
},
};
prisma.$transaction.mockImplementationOnce((callback: (client: typeof tx) => unknown) => callback(tx));
const service = new SmsConfigService(prisma as never);
await service.updateApplication('app-1', { interfaceEnabled: true });
expect(tx.smsApplicationHttpConfig.update).toHaveBeenCalledWith({
where: { applicationId: 'app-1' },
data: {
receiptDeliveryMode: 'both',
uplinkDeliveryMode: 'both',
},
});
});
it('replaces application carrier channel-group routes with carrier validation', async () => {
const prisma = createPrismaMock();
const tx = {
+17 -2
View File
@@ -4,6 +4,7 @@ import { randomInt, randomUUID } from 'node:crypto';
import { isIpAllowed } from '../common/ip-allowlist';
import { assertMoneyUnits } from '../common/money';
import { PrismaService } from '../prisma/prisma.service';
import { automaticDeliveryMode } from '../open-api/delivery-mode';
export interface CreateSmsApplicationDto {
tenantId: string;
@@ -401,7 +402,10 @@ export class SmsConfigService {
}
async updateApplication(applicationId: string, data: UpdateSmsApplicationDto) {
const application = await this.prisma.smsApplication.findUnique({ where: { id: applicationId } });
const application = await this.prisma.smsApplication.findUnique({
where: { id: applicationId },
include: { httpConfig: true },
});
if (!application) {
throw new NotFoundException('Application not found');
}
@@ -435,7 +439,7 @@ export class SmsConfigService {
if (data.ipAllowlist) {
await tx.smsApplicationIpAllowlist.deleteMany({ where: { applicationId } });
}
return tx.smsApplication.update({
const updated = await tx.smsApplication.update({
where: { id: applicationId },
data: {
name: data.name,
@@ -466,6 +470,17 @@ export class SmsConfigService {
},
include: { tenant: true, ipAllowlist: true },
});
if (data.interfaceEnabled !== undefined && application.httpConfig) {
const deliveryMode = automaticDeliveryMode(data.interfaceEnabled, application.httpConfig.enabled);
await tx.smsApplicationHttpConfig.update({
where: { applicationId },
data: {
receiptDeliveryMode: deliveryMode,
uplinkDeliveryMode: deliveryMode,
},
});
}
return updated;
});
}