fix(lint): clean up type definitions and missing imports
Some checks failed
Deploy Canina / deploy (push) Failing after 30m46s
Some checks failed
Deploy Canina / deploy (push) Failing after 30m46s
This commit is contained in:
parent
9c8286c63f
commit
2de442dbae
@ -1,4 +1,4 @@
|
|||||||
import { Injectable, HttpException } from '@nestjs/common';
|
import { Injectable, HttpException, NotFoundException } from '@nestjs/common';
|
||||||
import { PrismaService } from '../prisma/prisma.service';
|
import { PrismaService } from '../prisma/prisma.service';
|
||||||
import { RedisService } from '../redis/redis.service';
|
import { RedisService } from '../redis/redis.service';
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,10 @@ export class AuthService {
|
|||||||
// Dispatch OTP via MeliPayamak Pattern SMS
|
// Dispatch OTP via MeliPayamak Pattern SMS
|
||||||
await this.smsService.sendOtp(phoneNumber, code);
|
await this.smsService.sendOtp(phoneNumber, code);
|
||||||
|
|
||||||
return { success: true, message: 'کد تایید با موفقیت به شماره شما پیامک شد.' };
|
return {
|
||||||
|
success: true,
|
||||||
|
message: 'کد تایید با موفقیت به شماره شما پیامک شد.',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifyOtp(verifyOtpDto: VerifyOtpDto) {
|
async verifyOtp(verifyOtpDto: VerifyOtpDto) {
|
||||||
|
|||||||
@ -19,9 +19,10 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
|
|||||||
const request = ctx.getRequest<Request>();
|
const request = ctx.getRequest<Request>();
|
||||||
|
|
||||||
let status = HttpStatus.INTERNAL_SERVER_ERROR;
|
let status = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
let message = 'خطای داخلی سرور رخ داده است. لطفاً بعداً تلاش کنید یا با پشتیبانی تماس بگیرید.';
|
let message =
|
||||||
|
'خطای داخلی سرور رخ داده است. لطفاً بعداً تلاش کنید یا با پشتیبانی تماس بگیرید.';
|
||||||
let code = 'INTERNAL_SERVER_ERROR';
|
let code = 'INTERNAL_SERVER_ERROR';
|
||||||
let details: ErrorDetailField[] | Record<string, any> = {};
|
let details: ErrorDetailField[] | Record<string, unknown> = {};
|
||||||
|
|
||||||
if (exception instanceof HttpException) {
|
if (exception instanceof HttpException) {
|
||||||
status = exception.getStatus();
|
status = exception.getStatus();
|
||||||
@ -30,14 +31,17 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
|
|||||||
if (typeof exceptionResponse === 'string') {
|
if (typeof exceptionResponse === 'string') {
|
||||||
message = this.translateGenericMessage(exceptionResponse, status);
|
message = this.translateGenericMessage(exceptionResponse, status);
|
||||||
code = this.deriveErrorCode(status, exceptionResponse);
|
code = this.deriveErrorCode(status, exceptionResponse);
|
||||||
} else if (typeof exceptionResponse === 'object' && exceptionResponse !== null) {
|
} else if (
|
||||||
const resObj = exceptionResponse as Record<string, any>;
|
typeof exceptionResponse === 'object' &&
|
||||||
|
exceptionResponse !== null
|
||||||
|
) {
|
||||||
|
const resObj = exceptionResponse as Record<string, unknown>;
|
||||||
|
|
||||||
// Handle class-validator validation array messages
|
// Handle class-validator validation array messages
|
||||||
if (Array.isArray(resObj.message)) {
|
if (Array.isArray(resObj.message)) {
|
||||||
message = 'اطلاعات وارد شده نامعتبر است. لطفاً فرم را بررسی کنید.';
|
message = 'اطلاعات وارد شده نامعتبر است. لطفاً فرم را بررسی کنید.';
|
||||||
code = 'INVALID_INPUT_DATA';
|
code = 'INVALID_INPUT_DATA';
|
||||||
details = resObj.message.map((msg: string) => {
|
details = (resObj.message as string[]).map((msg: string) => {
|
||||||
const parts = msg.split(' ');
|
const parts = msg.split(' ');
|
||||||
return {
|
return {
|
||||||
field: parts[0] || 'general',
|
field: parts[0] || 'general',
|
||||||
@ -45,13 +49,19 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
message = this.translateGenericMessage(resObj.message || exception.message, status);
|
const rawMsg = typeof resObj.message === 'string' ? resObj.message : exception.message;
|
||||||
code = resObj.code || this.deriveErrorCode(status, resObj.error);
|
message = this.translateGenericMessage(rawMsg, status);
|
||||||
details = resObj.details || {};
|
const rawCode = typeof resObj.code === 'string' ? resObj.code : undefined;
|
||||||
|
const rawError = typeof resObj.error === 'string' ? resObj.error : undefined;
|
||||||
|
code = rawCode || this.deriveErrorCode(status, rawError);
|
||||||
|
details = (resObj.details as Record<string, unknown>) || {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (exception instanceof Error) {
|
} else if (exception instanceof Error) {
|
||||||
this.logger.error(`Unhandled Exception: ${exception.message}`, exception.stack);
|
this.logger.error(
|
||||||
|
`Unhandled Exception: ${exception.message}`,
|
||||||
|
exception.stack,
|
||||||
|
);
|
||||||
message = 'خطای غیرمنتظره در پردازش درخواست رخ داد.';
|
message = 'خطای غیرمنتظره در پردازش درخواست رخ داد.';
|
||||||
code = 'UNHANDLED_EXCEPTION';
|
code = 'UNHANDLED_EXCEPTION';
|
||||||
}
|
}
|
||||||
@ -66,14 +76,16 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
|
|||||||
path: request.url,
|
path: request.url,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.logger.warn(`[${request.method}] ${request.url} - Status ${status} - ${message}`);
|
this.logger.warn(
|
||||||
|
`[${request.method}] ${request.url} - Status ${status} - ${message}`,
|
||||||
|
);
|
||||||
|
|
||||||
response.status(status).json(errorPayload);
|
response.status(status).json(errorPayload);
|
||||||
}
|
}
|
||||||
|
|
||||||
private translateGenericMessage(msg: string, status: number): string {
|
private translateGenericMessage(msg: string, status: number): string {
|
||||||
if (!msg) return 'خطای نامشخص رخ داده است.';
|
if (!msg) return 'خطای نامشخص رخ داده است.';
|
||||||
|
|
||||||
const lower = msg.toLowerCase();
|
const lower = msg.toLowerCase();
|
||||||
if (lower.includes('unauthorized') || status === 401) {
|
if (lower.includes('unauthorized') || status === 401) {
|
||||||
return 'شما دسترسی لازم برای این عملیات را ندارید. لطفاً ابتدا وارد حساب کاربری خود شوید.';
|
return 'شما دسترسی لازم برای این عملیات را ندارید. لطفاً ابتدا وارد حساب کاربری خود شوید.';
|
||||||
@ -100,14 +112,22 @@ export class CustomHttpExceptionFilter implements ExceptionFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 400: return 'BAD_REQUEST';
|
case 400:
|
||||||
case 401: return 'UNAUTHORIZED';
|
return 'BAD_REQUEST';
|
||||||
case 403: return 'FORBIDDEN';
|
case 401:
|
||||||
case 404: return 'NOT_FOUND';
|
return 'UNAUTHORIZED';
|
||||||
case 409: return 'CONFLICT';
|
case 403:
|
||||||
case 422: return 'UNPROCESSABLE_ENTITY';
|
return 'FORBIDDEN';
|
||||||
case 429: return 'TOO_MANY_REQUESTS';
|
case 404:
|
||||||
default: return 'INTERNAL_SERVER_ERROR';
|
return 'NOT_FOUND';
|
||||||
|
case 409:
|
||||||
|
return 'CONFLICT';
|
||||||
|
case 422:
|
||||||
|
return 'UNPROCESSABLE_ENTITY';
|
||||||
|
case 429:
|
||||||
|
return 'TOO_MANY_REQUESTS';
|
||||||
|
default:
|
||||||
|
return 'INTERNAL_SERVER_ERROR';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export class PrismaExceptionFilter implements ExceptionFilter {
|
|||||||
let status = HttpStatus.BAD_REQUEST;
|
let status = HttpStatus.BAD_REQUEST;
|
||||||
let message = 'خطایی در پردازش اطلاعات دیتابیس رخ داده است.';
|
let message = 'خطایی در پردازش اطلاعات دیتابیس رخ داده است.';
|
||||||
let code = `PRISMA_${exception.code}`;
|
let code = `PRISMA_${exception.code}`;
|
||||||
let details: Record<string, any> = {};
|
let details: Record<string, unknown> = {};
|
||||||
|
|
||||||
switch (exception.code) {
|
switch (exception.code) {
|
||||||
case 'P2002': {
|
case 'P2002': {
|
||||||
@ -34,14 +34,16 @@ export class PrismaExceptionFilter implements ExceptionFilter {
|
|||||||
}
|
}
|
||||||
case 'P2025': {
|
case 'P2025': {
|
||||||
status = HttpStatus.NOT_FOUND;
|
status = HttpStatus.NOT_FOUND;
|
||||||
message = 'اطلاعات یا رکورد مورد نظر در سیستم یافت نشد یا قبلاً حذف شده است.';
|
message =
|
||||||
|
'اطلاعات یا رکورد مورد نظر در سیستم یافت نشد یا قبلاً حذف شده است.';
|
||||||
code = 'RECORD_NOT_FOUND';
|
code = 'RECORD_NOT_FOUND';
|
||||||
details = { meta: exception.meta };
|
details = { meta: exception.meta };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'P2003': {
|
case 'P2003': {
|
||||||
status = HttpStatus.BAD_REQUEST;
|
status = HttpStatus.BAD_REQUEST;
|
||||||
message = 'امکان انجام عملیات به دلیل وجود وابستگی بین اطلاعات وجود ندارد.';
|
message =
|
||||||
|
'امکان انجام عملیات به دلیل وجود وابستگی بین اطلاعات وجود ندارد.';
|
||||||
code = 'FOREIGN_KEY_CONSTRAINT_FAILED';
|
code = 'FOREIGN_KEY_CONSTRAINT_FAILED';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -52,7 +54,9 @@ export class PrismaExceptionFilter implements ExceptionFilter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.error(`[Prisma ${exception.code}] ${request.method} ${request.url} - ${message}`);
|
this.logger.error(
|
||||||
|
`[Prisma ${exception.code}] ${request.method} ${request.url} - ${message}`,
|
||||||
|
);
|
||||||
|
|
||||||
response.status(status).json({
|
response.status(status).json({
|
||||||
success: false,
|
success: false,
|
||||||
|
|||||||
@ -4,12 +4,18 @@ export class ErrorDetailField {
|
|||||||
@ApiProperty({ description: 'نام فیلد دارای خطا', example: 'phone' })
|
@ApiProperty({ description: 'نام فیلد دارای خطا', example: 'phone' })
|
||||||
field: string;
|
field: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'توضیح توصیفی خطا به فارسی', example: 'شماره تلفن همراه وارد شده نامعتبر است.' })
|
@ApiProperty({
|
||||||
|
description: 'توضیح توصیفی خطا به فارسی',
|
||||||
|
example: 'شماره تلفن همراه وارد شده نامعتبر است.',
|
||||||
|
})
|
||||||
message: string;
|
message: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ApiErrorResponse {
|
export class ApiErrorResponse {
|
||||||
@ApiProperty({ description: 'وضعیت موفقیت درخواست (همیشه false در زمان خطا)', example: false })
|
@ApiProperty({
|
||||||
|
description: 'وضعیت موفقیت درخواست (همیشه false در زمان خطا)',
|
||||||
|
example: false,
|
||||||
|
})
|
||||||
success: boolean;
|
success: boolean;
|
||||||
|
|
||||||
@ApiProperty({ description: 'کد وضعیت HTTP درخواست', example: 400 })
|
@ApiProperty({ description: 'کد وضعیت HTTP درخواست', example: 400 })
|
||||||
@ -17,11 +23,15 @@ export class ApiErrorResponse {
|
|||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: 'پیام جامع و توصیفی خطا به زبان فارسی',
|
description: 'پیام جامع و توصیفی خطا به زبان فارسی',
|
||||||
example: 'اطلاعات وارد شده نامعتبر است. لطفاً موارد مشخص شده را بررسی نمایید.',
|
example:
|
||||||
|
'اطلاعات وارد شده نامعتبر است. لطفاً موارد مشخص شده را بررسی نمایید.',
|
||||||
})
|
})
|
||||||
message: string;
|
message: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'کد سیستمیک و ثابت خطا جهت پردازش فرانتاند', example: 'INVALID_INPUT_DATA' })
|
@ApiProperty({
|
||||||
|
description: 'کد سیستمیک و ثابت خطا جهت پردازش فرانتاند',
|
||||||
|
example: 'INVALID_INPUT_DATA',
|
||||||
|
})
|
||||||
code: string;
|
code: string;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
@ -31,9 +41,15 @@ export class ApiErrorResponse {
|
|||||||
})
|
})
|
||||||
details?: ErrorDetailField[] | Record<string, any>;
|
details?: ErrorDetailField[] | Record<string, any>;
|
||||||
|
|
||||||
@ApiProperty({ description: 'زمان وقوع خطا به فرمت ISO', example: '2026-07-29T16:30:00.000Z' })
|
@ApiProperty({
|
||||||
|
description: 'زمان وقوع خطا به فرمت ISO',
|
||||||
|
example: '2026-07-29T16:30:00.000Z',
|
||||||
|
})
|
||||||
timestamp: string;
|
timestamp: string;
|
||||||
|
|
||||||
@ApiProperty({ description: 'مسیر و انکوینتی که خطا در آن رخ داده است', example: '/api/auth/register' })
|
@ApiProperty({
|
||||||
|
description: 'مسیر و انکوینتی که خطا در آن رخ داده است',
|
||||||
|
example: '/api/auth/register',
|
||||||
|
})
|
||||||
path: string;
|
path: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -68,7 +68,9 @@ export class SmsService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
req.on('error', (err) => {
|
req.on('error', (err) => {
|
||||||
this.logger.error(`[SMS Exception] MeliPayamak HTTP Error: ${err.message}`);
|
this.logger.error(
|
||||||
|
`[SMS Exception] MeliPayamak HTTP Error: ${err.message}`,
|
||||||
|
);
|
||||||
resolve(false);
|
resolve(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -92,7 +94,11 @@ export class SmsService {
|
|||||||
/**
|
/**
|
||||||
* Send Order Confirmation SMS
|
* Send Order Confirmation SMS
|
||||||
*/
|
*/
|
||||||
async sendOrderConfirmation(phone: string, orderNumber: string, amount: string): Promise<boolean> {
|
async sendOrderConfirmation(
|
||||||
|
phone: string,
|
||||||
|
orderNumber: string,
|
||||||
|
amount: string,
|
||||||
|
): Promise<boolean> {
|
||||||
const bodyId = parseInt(process.env.MELIPAYAMAK_ORDER_BODY_ID || '0', 10);
|
const bodyId = parseInt(process.env.MELIPAYAMAK_ORDER_BODY_ID || '0', 10);
|
||||||
return this.sendPatternSms({
|
return this.sendPatternSms({
|
||||||
to: phone,
|
to: phone,
|
||||||
@ -104,8 +110,15 @@ export class SmsService {
|
|||||||
/**
|
/**
|
||||||
* Send Shipping Status SMS with Tracking Code
|
* Send Shipping Status SMS with Tracking Code
|
||||||
*/
|
*/
|
||||||
async sendShippingNotification(phone: string, orderNumber: string, trackingCode: string): Promise<boolean> {
|
async sendShippingNotification(
|
||||||
const bodyId = parseInt(process.env.MELIPAYAMAK_SHIPPING_BODY_ID || '0', 10);
|
phone: string,
|
||||||
|
orderNumber: string,
|
||||||
|
trackingCode: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const bodyId = parseInt(
|
||||||
|
process.env.MELIPAYAMAK_SHIPPING_BODY_ID || '0',
|
||||||
|
10,
|
||||||
|
);
|
||||||
return this.sendPatternSms({
|
return this.sendPatternSms({
|
||||||
to: phone,
|
to: phone,
|
||||||
bodyId,
|
bodyId,
|
||||||
@ -116,8 +129,15 @@ export class SmsService {
|
|||||||
/**
|
/**
|
||||||
* Send Pet Care Vaccination / Deworming Reminder SMS
|
* Send Pet Care Vaccination / Deworming Reminder SMS
|
||||||
*/
|
*/
|
||||||
async sendPetCareReminder(phone: string, petName: string, reminderType: string): Promise<boolean> {
|
async sendPetCareReminder(
|
||||||
const bodyId = parseInt(process.env.MELIPAYAMAK_PET_CARE_BODY_ID || '0', 10);
|
phone: string,
|
||||||
|
petName: string,
|
||||||
|
reminderType: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
const bodyId = parseInt(
|
||||||
|
process.env.MELIPAYAMAK_PET_CARE_BODY_ID || '0',
|
||||||
|
10,
|
||||||
|
);
|
||||||
return this.sendPatternSms({
|
return this.sendPatternSms({
|
||||||
to: phone,
|
to: phone,
|
||||||
bodyId,
|
bodyId,
|
||||||
|
|||||||
@ -36,15 +36,21 @@ async function bootstrap() {
|
|||||||
forbidNonWhitelisted: true,
|
forbidNonWhitelisted: true,
|
||||||
exceptionFactory: (errors) => {
|
exceptionFactory: (errors) => {
|
||||||
const formattedDetails = errors.map((err) => {
|
const formattedDetails = errors.map((err) => {
|
||||||
const constraints = err.constraints ? Object.values(err.constraints) : [];
|
const constraints = err.constraints
|
||||||
|
? Object.values(err.constraints)
|
||||||
|
: [];
|
||||||
return {
|
return {
|
||||||
field: err.property,
|
field: err.property,
|
||||||
message: constraints.length > 0 ? constraints[0] : 'مقدار وارد شده نامعتبر است.',
|
message:
|
||||||
|
constraints.length > 0
|
||||||
|
? constraints[0]
|
||||||
|
: 'مقدار وارد شده نامعتبر است.',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
return new BadRequestException({
|
return new BadRequestException({
|
||||||
message: 'اطلاعات ورودی فرم معتبر نمیباشد. لطفاً موارد مشخص شده را اصلاح نمایید.',
|
message:
|
||||||
|
'اطلاعات ورودی فرم معتبر نمیباشد. لطفاً موارد مشخص شده را اصلاح نمایید.',
|
||||||
error: 'INVALID_INPUT_DATA',
|
error: 'INVALID_INPUT_DATA',
|
||||||
details: formattedDetails,
|
details: formattedDetails,
|
||||||
});
|
});
|
||||||
@ -52,7 +58,10 @@ async function bootstrap() {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
app.useGlobalFilters(new CustomHttpExceptionFilter(), new PrismaExceptionFilter());
|
app.useGlobalFilters(
|
||||||
|
new CustomHttpExceptionFilter(),
|
||||||
|
new PrismaExceptionFilter(),
|
||||||
|
);
|
||||||
|
|
||||||
const config = new DocumentBuilder()
|
const config = new DocumentBuilder()
|
||||||
.setTitle('Canina Iran API')
|
.setTitle('Canina Iran API')
|
||||||
|
|||||||
@ -92,7 +92,12 @@ export class OrdersService {
|
|||||||
|
|
||||||
// Verify stock and build items
|
// Verify stock and build items
|
||||||
let cartTotal = 0;
|
let cartTotal = 0;
|
||||||
const orderItems: Array<{ productId: string; quantity: number; unitPrice: number; totalPrice: number }> = [];
|
const orderItems: Array<{
|
||||||
|
productId: string;
|
||||||
|
quantity: number;
|
||||||
|
unitPrice: number;
|
||||||
|
totalPrice: number;
|
||||||
|
}> = [];
|
||||||
|
|
||||||
for (const item of createOrderDto.items) {
|
for (const item of createOrderDto.items) {
|
||||||
const product = await this.prisma.product.findUnique({
|
const product = await this.prisma.product.findUnique({
|
||||||
@ -182,15 +187,20 @@ export class OrdersService {
|
|||||||
|
|
||||||
// Send Order Confirmation SMS
|
// Send Order Confirmation SMS
|
||||||
if (userId) {
|
if (userId) {
|
||||||
this.prisma.user.findUnique({ where: { id: userId } }).then((user) => {
|
this.prisma.user
|
||||||
if (user && user.mobile) {
|
.findUnique({ where: { id: userId } })
|
||||||
this.smsService.sendOrderConfirmation(
|
.then((user) => {
|
||||||
user.mobile,
|
if (user && user.mobile) {
|
||||||
trackingNumber,
|
this.smsService
|
||||||
finalAmount.toLocaleString('fa-IR'),
|
.sendOrderConfirmation(
|
||||||
).catch(() => {});
|
user.mobile,
|
||||||
}
|
trackingNumber,
|
||||||
}).catch(() => {});
|
finalAmount.toLocaleString('fa-IR'),
|
||||||
|
)
|
||||||
|
.catch(() => {});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return createdOrder;
|
return createdOrder;
|
||||||
@ -219,11 +229,9 @@ export class OrdersService {
|
|||||||
const mobile = updatedOrder.user?.mobile;
|
const mobile = updatedOrder.user?.mobile;
|
||||||
const trackingNum = updatedOrder.trackingNumber || trackingCode || '';
|
const trackingNum = updatedOrder.trackingNumber || trackingCode || '';
|
||||||
if (status === 'shipped' && mobile && trackingCode) {
|
if (status === 'shipped' && mobile && trackingCode) {
|
||||||
this.smsService.sendShippingNotification(
|
this.smsService
|
||||||
mobile,
|
.sendShippingNotification(mobile, trackingNum, trackingCode)
|
||||||
trackingNum,
|
.catch(() => {});
|
||||||
trackingCode,
|
|
||||||
).catch(() => {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return updatedOrder;
|
return updatedOrder;
|
||||||
|
|||||||
@ -26,11 +26,16 @@ export class WholesaleService {
|
|||||||
// Alert admin via SMS if admin mobile is configured
|
// Alert admin via SMS if admin mobile is configured
|
||||||
const adminMobile = process.env.ADMIN_MOBILE_ALERT;
|
const adminMobile = process.env.ADMIN_MOBILE_ALERT;
|
||||||
if (adminMobile) {
|
if (adminMobile) {
|
||||||
this.smsService.sendPatternSms({
|
this.smsService
|
||||||
to: adminMobile,
|
.sendPatternSms({
|
||||||
bodyId: parseInt(process.env.MELIPAYAMAK_ADMIN_ALERT_BODY_ID || '0', 10),
|
to: adminMobile,
|
||||||
args: [dto.businessName || 'نامشخص', user.mobile || ''],
|
bodyId: parseInt(
|
||||||
}).catch(() => {});
|
process.env.MELIPAYAMAK_ADMIN_ALERT_BODY_ID || '0',
|
||||||
|
10,
|
||||||
|
),
|
||||||
|
args: [dto.businessName || 'نامشخص', user.mobile || ''],
|
||||||
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user