Files
yara724api/src/sms-orchestration/sms-orchestration.service.ts
SepehrYahyaee 4b9d946bfd YARA-1154
2026-07-27 09:31:07 +03:30

209 lines
6.3 KiB
TypeScript

import { Injectable, Logger, OnModuleInit } from "@nestjs/common";
import { BlameRequestType } from "src/Types&Enums/blame-request-management/blameRequestType.enum";
import { SmsTextDbService } from "./entities/db-service/sms-text.db.service";
import { SmsGatewayService } from "./provider/sms-gateway.service";
import { describeSmsError } from "./provider/sms-provider.exception";
type TemplateArgs = {
template: string;
receptor: string;
token: string;
token2?: string;
token3?: string;
token10?: string;
};
@Injectable()
export class SmsOrchestrationService implements OnModuleInit {
private readonly logger = new Logger(SmsOrchestrationService.name);
constructor(
private readonly smsGatewayService: SmsGatewayService,
private readonly smsTextDbService: SmsTextDbService,
) {}
async onModuleInit(): Promise<void> {
await this.smsTextDbService.upsert(
"parties_disagree_notify",
"متاسفانه طرف مقابل با نظر کارشناس مخالفت کرد. فرآیند آنلاین این پرونده بسته شده است و جهت پیگیری حضوری اقدام نمایید.",
);
await this.smsTextDbService.upsert(
"one_party_signed_wait_signature",
"طرف مقابل توافق را امضا کرده است. لطفا جهت نهایی کردن پرونده، امضای خود را ثبت نمایید.",
);
await this.smsTextDbService.upsert(
"one_party_accepted_wait_24h",
"طرف مقابل نظر کارشناس را قبول و امضا کرده است. در طی 24 ساعت آینده فرصت دارید تا پرونده را تکمیل کرده یا پرونده بسته خواهد شد.",
);
}
buildInviteLink(
frontendRoute: string,
requestId: string,
versionPrefix: string,
): string {
return `${process.env.URL}/${versionPrefix}/${frontendRoute}?token=${requestId}`;
}
buildBlamePartyLink(
requestId: string,
partyRole: "FIRST" | "SECOND",
versionPrefix: string,
): string {
const route = partyRole === "SECOND" ? "user2" : "user";
return `${process.env.URL}/${versionPrefix}/${route}?token=${requestId}`;
}
buildClaimLink(claimRequestId: string, versionPrefix: string): string {
return `${process.env.URL}/${versionPrefix}/caseClaim?token=${claimRequestId}`;
}
async sendInviteLink(
phoneNumber: string,
publicId: string,
link: string,
): Promise<boolean> {
return this.sendTemplate({
template: "yara724-invite-link",
receptor: phoneNumber,
token: publicId,
token2: link,
});
}
async sendAuthOtp(
mobile: string,
otp: string,
template?: string,
): Promise<boolean> {
return this.sendTemplate({
template: template || process.env.AUTH_SMS_TEMPLATE || "",
receptor: mobile,
token: otp,
});
}
async sendFieldExpertLink(params: {
receptor: string;
type: BlameRequestType;
expertLastName: string;
link: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-field-expert-link",
receptor: params.receptor,
token: params.type === BlameRequestType.CAR_BODY ? "بدنه" : "ثالث",
token2: params.expertLastName || "کارشناس",
token3: params.link,
});
}
async sendTextByKey(
receptor: string,
key: string,
fallbackText: string,
): Promise<boolean> {
const row = await this.smsTextDbService.findOne({ key, active: true });
const message = row?.text?.trim() || fallbackText;
try {
await this.smsGatewayService.sendMessage({ receptor, message });
this.logger.log(`[SMS] text sent key=${key} receptor=${receptor}`);
return true;
} catch (err) {
this.logger.error(
`[SMS] text send failed key=${key} receptor=${receptor}: ${describeSmsError(err)}`,
);
return false;
}
}
async sendThirdPartyAgreementSignNotice(params: {
receptor: string;
publicId: string;
link: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-blame-agreement",
receptor: params.receptor,
token: params.publicId,
token2: params.link,
});
}
/** THIRD_PARTY only: notify the damaged (non-guilty) party that blame is completed and they can open the claim flow. */
async sendThirdPartyDamagedPartyClaimLinkNotice(params: {
receptor: string;
publicId: string;
link: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-claim-link",
receptor: params.receptor,
token: params.publicId,
token2: params.link,
});
}
async sendThirdPartyExpertStartedReviewNotice(params: {
receptor: string;
fileKind: "blame" | "claim";
publicId: string;
expertLastName: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-expert-lock",
receptor: params.receptor,
token: params.fileKind === "blame" ? "تصادف" : "خسارت",
token2: params.publicId,
token3: params.expertLastName || "کارشناس",
});
}
async sendResendDocumentsNotice(params: {
receptor: string;
fileKind: "blame" | "claim";
publicId: string;
link: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-resend-documents",
receptor: params.receptor,
token: params.fileKind === "blame" ? "تصادف" : "خسارت",
token2: params.publicId,
token3: params.link,
});
}
async sendSignatureReviewNotice(params: {
receptor: string;
fileKind: "blame" | "claim";
publicId: string;
expertLastName: string;
link: string;
}): Promise<boolean> {
return this.sendTemplate({
template: "yara-signature",
receptor: params.receptor,
token: params.fileKind === "blame" ? "تصادف" : "خسارت",
token2: params.publicId,
token3: params.expertLastName || "کارشناس",
token10: params.link,
});
}
private async sendTemplate(args: TemplateArgs): Promise<boolean> {
try {
await this.smsGatewayService.verifyLookUp(args);
this.logger.log(
`[SMS] template sent template=${args.template} receptor=${args.receptor}`,
);
return true;
} catch (err) {
this.logger.error(
`[SMS] template send failed template=${args.template} receptor=${args.receptor}: ${describeSmsError(err)}`,
);
return false;
}
}
}