feat(sms): add WALLET_CHARGED sms trigger for online topup, manual admin credit, refund, and cashback
This commit is contained in:
parent
7093978e27
commit
e15c25dae1
@ -984,6 +984,32 @@ export class AdminService {
|
||||
});
|
||||
});
|
||||
|
||||
// Send SMS notification for wallet refund
|
||||
if (this.smsService && order.user?.mobile) {
|
||||
try {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: order.userId },
|
||||
});
|
||||
const customerFullName = (
|
||||
order.user.firstName
|
||||
? `${order.user.firstName} ${order.user.lastName || ''}`
|
||||
: 'کاربر گرامی'
|
||||
).trim();
|
||||
const refundData = {
|
||||
customerName: customerFullName,
|
||||
customerPhone: order.user.mobile,
|
||||
amount: Number(refundAmount || 0).toLocaleString('fa-IR'),
|
||||
balance: Number(user?.walletBalance || 0).toLocaleString('fa-IR'),
|
||||
reason: reason || `استرداد وجه سفارش #${order.trackingNumber || order.id.slice(0, 8)}`,
|
||||
date: new Date().toLocaleDateString('fa-IR'),
|
||||
};
|
||||
|
||||
this.smsService.triggerEvent('WALLET_CHARGED', refundData).catch(() => {});
|
||||
} catch (err) {
|
||||
// Silently catch SMS errors
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: `مبلغ ${refundAmount.toLocaleString('fa-IR')} تومان با موفقیت به کیف پول کاربر بازگردانده شد.`,
|
||||
@ -1243,7 +1269,7 @@ export class AdminService {
|
||||
});
|
||||
|
||||
const isIncrement = type === 'deposit' || type === 'refund';
|
||||
await this.prisma.user.update({
|
||||
const updatedUser = await this.prisma.user.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
walletBalance: isIncrement
|
||||
@ -1252,6 +1278,31 @@ export class AdminService {
|
||||
},
|
||||
});
|
||||
|
||||
// Send SMS notification if wallet is topped up or refunded
|
||||
if (isIncrement && this.smsService && updatedUser.mobile) {
|
||||
try {
|
||||
const customerFullName = (
|
||||
updatedUser.firstName
|
||||
? `${updatedUser.firstName} ${updatedUser.lastName || ''}`
|
||||
: 'کاربر گرامی'
|
||||
).trim();
|
||||
const topupData = {
|
||||
customerName: customerFullName,
|
||||
customerPhone: updatedUser.mobile,
|
||||
amount: Number(amount || 0).toLocaleString('fa-IR'),
|
||||
balance: Number(updatedUser.walletBalance || 0).toLocaleString('fa-IR'),
|
||||
reason: description || (type === 'refund' ? 'استرداد وجه به کیف پول' : 'شارژ کیف پول توسط مدیریت'),
|
||||
date: new Date().toLocaleDateString('fa-IR'),
|
||||
};
|
||||
|
||||
this.smsService
|
||||
.triggerEvent('WALLET_CHARGED', topupData)
|
||||
.catch(() => {});
|
||||
} catch (err) {
|
||||
// Silently catch SMS errors
|
||||
}
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
||||
@ -104,6 +104,19 @@ export const SMS_EVENT_DEFINITIONS: SmsEventDefinition[] = [
|
||||
{ key: 'date', label: 'تاریخ ارسال', sample: '۱۴۰۳/۰۶/۱۵' },
|
||||
],
|
||||
},
|
||||
{
|
||||
event: 'WALLET_CHARGED',
|
||||
label: 'شارژ و افزایش موجودی کیف پول',
|
||||
description: 'هنگام افزایش موجودی کیف پول کاربر (درگاه آنلاین، پنل مدیریت، کشبک یا استرداد)',
|
||||
variables: [
|
||||
{ key: 'customerName', label: 'نام مشتری', sample: 'علی محمدی' },
|
||||
{ key: 'amount', label: 'مبلغ شارژ (تومان)', sample: '۵۰,۰۰۰' },
|
||||
{ key: 'balance', label: 'موجودی جدید کیف پول (تومان)', sample: '۱۵۰,۰۰۰' },
|
||||
{ key: 'reason', label: 'علت / نوع شارژ', sample: 'شارژ آنلاین / پاداش خرید (Cashback)' },
|
||||
{ key: 'customerPhone', label: 'شماره همراه مشتری', sample: '09123456789' },
|
||||
{ key: 'date', label: 'تاریخ شارژ', sample: '۱۴۰۳/۰۶/۱۵' },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export const DEFAULT_SMS_RULES: SmsRule[] = [
|
||||
@ -147,4 +160,14 @@ export const DEFAULT_SMS_RULES: SmsRule[] = [
|
||||
variables: ['applicantName'],
|
||||
description: 'پیامک ثبت درخواست متقاضیان عمدهفروشی',
|
||||
},
|
||||
{
|
||||
id: 'default-wallet-charged-customer',
|
||||
title: 'اطلاعرسانی شارژ کیف پول به کاربر',
|
||||
event: 'WALLET_CHARGED',
|
||||
enabled: true,
|
||||
recipientType: 'customer',
|
||||
patternId: 0,
|
||||
variables: ['customerName', 'amount', 'balance'],
|
||||
description: 'ارسال پیامک افزایش موجودی کیف پول (آنلاین، مدیریت یا کشبک)',
|
||||
},
|
||||
];
|
||||
|
||||
@ -608,6 +608,38 @@ export class PaymentService {
|
||||
});
|
||||
}
|
||||
|
||||
// Send SMS notification if wallet top-up
|
||||
if (transaction.type === 'WALLET_TOPUP' && transaction.userId) {
|
||||
try {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: transaction.userId },
|
||||
});
|
||||
if (user?.mobile) {
|
||||
const customerFullName = (
|
||||
user.firstName
|
||||
? `${user.firstName} ${user.lastName || ''}`
|
||||
: 'کاربر گرامی'
|
||||
).trim();
|
||||
const topupData = {
|
||||
customerName: customerFullName,
|
||||
customerPhone: user.mobile,
|
||||
amount: Number(transaction.amount || 0).toLocaleString('fa-IR'),
|
||||
balance: Number(user.walletBalance || 0).toLocaleString('fa-IR'),
|
||||
reason: 'شارژ آنلاین از طریق درگاه بانکی',
|
||||
date: new Date().toLocaleDateString('fa-IR'),
|
||||
};
|
||||
|
||||
this.smsService
|
||||
.triggerEvent('WALLET_CHARGED', topupData)
|
||||
.catch((err) => {
|
||||
this.logger.warn(`Could not trigger SMS event WALLET_CHARGED: ${err}`);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.warn(`Error dispatching WALLET_CHARGED SMS: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
status: 'VERIFIED',
|
||||
@ -1075,6 +1107,37 @@ export class PaymentService {
|
||||
}
|
||||
});
|
||||
|
||||
if (transaction.type === 'WALLET_TOPUP' && transaction.userId) {
|
||||
try {
|
||||
const user = await this.prisma.user.findUnique({
|
||||
where: { id: transaction.userId },
|
||||
});
|
||||
if (user?.mobile) {
|
||||
const customerFullName = (
|
||||
user.firstName
|
||||
? `${user.firstName} ${user.lastName || ''}`
|
||||
: 'کاربر گرامی'
|
||||
).trim();
|
||||
const topupData = {
|
||||
customerName: customerFullName,
|
||||
customerPhone: user.mobile,
|
||||
amount: Number(transaction.amount || 0).toLocaleString('fa-IR'),
|
||||
balance: Number(user.walletBalance || 0).toLocaleString('fa-IR'),
|
||||
reason: adminNote || 'افزایش موجودی (کارت به کارت / فیش بانکی)',
|
||||
date: new Date().toLocaleDateString('fa-IR'),
|
||||
};
|
||||
|
||||
this.smsService
|
||||
.triggerEvent('WALLET_CHARGED', topupData)
|
||||
.catch((err) => {
|
||||
this.logger.warn(`Could not trigger SMS event WALLET_CHARGED: ${err}`);
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.warn(`Error dispatching WALLET_CHARGED SMS: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: 'تراکنش با موفقیت به صورت دستی تایید و اعمال شد',
|
||||
|
||||
@ -2,9 +2,11 @@ import {
|
||||
Injectable,
|
||||
BadRequestException,
|
||||
NotFoundException,
|
||||
Optional,
|
||||
} from '@nestjs/common';
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { PrismaService } from '../prisma/prisma.service';
|
||||
import { SmsService } from '../common/services/sms.service';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { normalizeMobile } from '../common/utils/phone.utils';
|
||||
import { UpdateProfileDto } from './dto/update-profile.dto';
|
||||
@ -22,7 +24,10 @@ export interface UserAddressInput {
|
||||
|
||||
@Injectable()
|
||||
export class UsersService {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
@Optional() private smsService?: SmsService,
|
||||
) {}
|
||||
|
||||
async findById(id: string) {
|
||||
if (id === '12345678-1234-1234-1234-123456789012') {
|
||||
@ -277,7 +282,7 @@ export class UsersService {
|
||||
throw new Error('مبلغ شارژ باید بزرگتر از صفر باشد');
|
||||
}
|
||||
|
||||
const [transaction] = await this.prisma.$transaction([
|
||||
const [transaction, updatedUser] = await this.prisma.$transaction([
|
||||
this.prisma.walletTransaction.create({
|
||||
data: {
|
||||
userId,
|
||||
@ -293,6 +298,28 @@ export class UsersService {
|
||||
}),
|
||||
]);
|
||||
|
||||
if (this.smsService && updatedUser.mobile) {
|
||||
try {
|
||||
const customerFullName = (
|
||||
updatedUser.firstName
|
||||
? `${updatedUser.firstName} ${updatedUser.lastName || ''}`
|
||||
: 'کاربر گرامی'
|
||||
).trim();
|
||||
const topupData = {
|
||||
customerName: customerFullName,
|
||||
customerPhone: updatedUser.mobile,
|
||||
amount: Number(amount || 0).toLocaleString('fa-IR'),
|
||||
balance: Number(updatedUser.walletBalance || 0).toLocaleString('fa-IR'),
|
||||
reason: 'افزایش موجودی کیف پول',
|
||||
date: new Date().toLocaleDateString('fa-IR'),
|
||||
};
|
||||
|
||||
this.smsService.triggerEvent('WALLET_CHARGED', topupData).catch(() => {});
|
||||
} catch (err) {
|
||||
// Silently catch SMS error
|
||||
}
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
||||
@ -2153,6 +2153,7 @@ export default function SmsSettingsPage() {
|
||||
<option value="ORDER_PAID">پرداخت موفق سفارش (Order Paid)</option>
|
||||
<option value="ORDER_CREATED">ثبت سفارش کارت به کارت / در انتظار</option>
|
||||
<option value="ORDER_SHIPPED">ارسال مرسوله و صدور بارکد پستی</option>
|
||||
<option value="WALLET_CHARGED">شارژ و افزایش موجودی کیف پول</option>
|
||||
<option value="B2B_SUBMITTED">ثبت درخواست همکاری B2B</option>
|
||||
<option value="CONTACT_SUBMITTED">ثبت پیام در فرم تماس با ما</option>
|
||||
</>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user