Files
grow-api/src/sms-settings/sms-dispatch.service.ts
T
2026-07-11 22:08:41 +03:30

138 lines
3.7 KiB
TypeScript

import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { renderSmsTemplate } from '../sms-templates/utils/render-sms-template.util';
import { SmsTemplatesService } from '../sms-templates/sms-templates.service';
import { SmsService } from '../sms/sms.service';
import {
getSampleVariables,
SMS_SCENARIOS,
SMS_SCENARIO_MAP,
} from './constants/sms-scenarios.constants';
import { PreviewSmsScenarioDto } from './dto/update-sms-scenario-setting.dto';
import { SmsScenarioSetting } from './entities/sms-scenario-setting.entity';
import { SmsScenarioKey } from './enums/sms-scenario-key.enum';
@Injectable()
export class SmsDispatchService {
constructor(
@InjectRepository(SmsScenarioSetting)
private readonly settingsRepository: Repository<SmsScenarioSetting>,
private readonly smsTemplatesService: SmsTemplatesService,
private readonly smsService: SmsService,
) {}
getScenarioDefinitions() {
return SMS_SCENARIOS;
}
async findAllSettings(): Promise<SmsScenarioSetting[]> {
return this.settingsRepository.find({
relations: { template: true },
order: { key: 'ASC' },
});
}
async findSettingByKey(key: SmsScenarioKey): Promise<SmsScenarioSetting> {
const setting = await this.settingsRepository.findOne({
where: { key },
relations: { template: true },
});
if (!setting) {
throw new NotFoundException(`SMS scenario setting "${key}" not found`);
}
return setting;
}
async resolveMessage(
key: SmsScenarioKey,
variables: Record<string, string>,
): Promise<string | null> {
const setting = await this.findSettingByKey(key);
if (!setting.isActive) {
return null;
}
const body = await this.resolveBody(setting);
if (!body) {
return null;
}
return renderSmsTemplate(body, variables);
}
async resolveMessageFromTemplateId(
templateId: string,
variables: Record<string, string>,
): Promise<string | null> {
const template = await this.smsTemplatesService.findOne(templateId);
if (!template.isActive) {
return null;
}
return renderSmsTemplate(template.body, variables);
}
async previewMessage(dto: PreviewSmsScenarioDto): Promise<string> {
const body = await this.resolvePreviewBody(dto);
const variables = getSampleVariables(dto.key);
return renderSmsTemplate(body, variables);
}
async sendScenarioSms(
key: SmsScenarioKey,
mobile: string,
variables: Record<string, string>,
): Promise<boolean> {
const message = await this.resolveMessage(key, variables);
if (!message) {
return false;
}
return this.smsService.sendSms(mobile, message);
}
private async resolveBody(
setting: SmsScenarioSetting,
): Promise<string | null> {
if (setting.templateId) {
const template = await this.smsTemplatesService.findOne(
setting.templateId,
);
if (!template.isActive) {
return null;
}
return template.body;
}
if (setting.body) {
return setting.body;
}
return SMS_SCENARIO_MAP.get(setting.key)?.defaultBody ?? null;
}
private async resolvePreviewBody(
dto: PreviewSmsScenarioDto,
): Promise<string> {
if (dto.templateId) {
const template = await this.smsTemplatesService.findOne(dto.templateId);
return template.body;
}
if (dto.body) {
return dto.body;
}
const setting = await this.findSettingByKey(dto.key);
const resolved = await this.resolveBody(setting);
if (!resolved) {
throw new NotFoundException('No SMS body configured for this scenario');
}
return resolved;
}
}