online order notif after success

This commit is contained in:
2025-12-23 10:16:45 +03:30
parent c911ec711a
commit 5bb18afa11
4 changed files with 127 additions and 7 deletions
@@ -8,6 +8,7 @@ import { NotificationService } from 'src/modules/notifications/services/notifica
import { ConfigService } from '@nestjs/config';
import { OrderRepository } from '../repositories/order.repository';
import { OrderStatus } from '../interface/order.interface';
import { PaymentMethodEnum } from 'src/modules/payments/interface/payment';
@Injectable()
export class OrderListeners {
@@ -44,11 +45,17 @@ export class OrderListeners {
this.logger.log(
`Order created event received: ${event.orderId} for restaurant: ${event.restaurantId} and order number: ${event.orderNumber}`,
);
const order = await this.OrderRepository.findOne(event.orderId);
if (order?.paymentMethod.method === PaymentMethodEnum.Online) {
return;
}
// get admnin os restuaraant that have order permissuins
const admins = await this.adminService.findAdminsWithPermission(event.restaurantId, Permission.MANAGE_ORDERS);
const recipients = admins.map(admin => ({
adminId: admin.id,
}));
await this.notificationService.sendNotification({
restaurantId: event.restaurantId,
message: {
@@ -11,3 +11,12 @@ export class paymentSucceedEvent {
}
export class onlinePaymentSucceedEvent {
constructor(
public readonly paymentId: string,
public readonly restaurantId: string,
public readonly orderNumber: string,
public readonly total: number,
) { }
}
@@ -1,23 +1,25 @@
import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { AdminRepository } from 'src/modules/admin/repositories/admin.repository';
import { paymentSucceedEvent } from '../events/payment.events';
import { onlinePaymentSucceedEvent, paymentSucceedEvent } from '../events/payment.events';
import { Permission } from 'src/common/enums/permission.enum';
import { NotifTitleEnum } from 'src/modules/notifications/interfaces/notification.interface';
import { NotificationService } from 'src/modules/notifications/services/notification.service';
import { ConfigService } from '@nestjs/config';
import { PaymentMethodEnum } from '../interface/payment';
import { OrdersService } from 'src/modules/orders/providers/orders.service';
@Injectable()
export class PaymentListeners {
private readonly logger = new Logger(PaymentListeners.name);
private paymentSuccessSmsTemplateId: string;
private orderCreatedSmsTemplateId: string;
constructor(
private readonly adminService: AdminRepository,
private readonly notificationService: NotificationService,
private readonly configService: ConfigService,
// private readonly orderSer
private readonly orderService: OrdersService,
) {
this.paymentSuccessSmsTemplateId = this.configService.get<string>('SMS_PATTERN_PAYMENT_SUCCESS') ?? '123';
this.orderCreatedSmsTemplateId = this.configService.get<string>('SMS_PATTERN_ORDER_CREATED') ?? '123';
}
private getPaymentMethodFarsi(method: string): string {
@@ -47,10 +49,10 @@ export class PaymentListeners {
title: NotifTitleEnum.PAYMENT_SUCCESS,
content: `پرداخت سفارش شماره ${event.orderNumber} با روش ${this.getPaymentMethodFarsi(event.paymentMethod)} و مبلغ ${event.total} تومان با موفقیت انجام شد`,
sms: {
templateId: this.paymentSuccessSmsTemplateId,
templateId: this.orderCreatedSmsTemplateId,
parameters: {
orderNumber: event.orderNumber,
},
},
pushNotif: {
@@ -76,4 +78,94 @@ export class PaymentListeners {
}
}
@OnEvent(onlinePaymentSucceedEvent.name)
async handleOnlinePaymentSucceed(event: onlinePaymentSucceedEvent) {
try {
this.logger.log(
`Online payment succeed event received: ${event.paymentId} for restaurant: ${event.restaurantId} and order number: ${event.orderNumber}`,
);
const admins = await this.adminService.findAdminsWithPermission(event.restaurantId, Permission.MANAGE_ORDERS);
const recipients = admins.map(admin => ({
adminId: admin.id,
}));
await this.notificationService.sendNotification({
restaurantId: event.restaurantId,
message: {
title: NotifTitleEnum.ORDER_CREATED,
content: `سفارش شماره ${event.orderNumber} با مبلغ ${event.total} تومان با موفقیت ایجاد شد`,
sms: {
templateId: this.orderCreatedSmsTemplateId,
parameters: {
orderNumber: event.orderNumber,
total: event.total.toString(),
},
},
pushNotif: {
title: `سفارش جدید`,
content: `سفارش شماره ${event.orderNumber} با مبلغ ${event.total} تومان با موفقیت ایجاد شد`,
icon: `/`,
action: {
type: NotifTitleEnum.ORDER_CREATED,
url: `/`,
},
},
},
recipients,
metadata: {
priority: 1,
},
});
const order = await this.orderService.findOne(event.paymentId, event.restaurantId);
if (!order) {
this.logger.error(
`Order not found: ${event.paymentId} for restaurant: ${event.restaurantId}`,
);
return;
}
if (order.paymentMethod.method === PaymentMethodEnum.Online) {
return;
}
const userRecipients = [
{
userId: order.user.id,
},
];
await this.notificationService.sendNotification({
restaurantId: event.restaurantId,
message: {
title: NotifTitleEnum.PAYMENT_SUCCESS,
content: `پرداخت سفارش شماره ${order.orderNumber} با روش ${this.getPaymentMethodFarsi(order.paymentMethod.method)} و مبلغ ${order.total} تومان با موفقیت انجام شد`,
sms: {
templateId: this.orderCreatedSmsTemplateId,
parameters: {
orderNumber: String(order.orderNumber),
total: order.total.toString(),
},
},
pushNotif: {
title: `پرداخت موفق`,
content: `پرداخت سفارش شماره ${order.orderNumber} با روش ${this.getPaymentMethodFarsi(order.paymentMethod.method)} و مبلغ ${order.total} تومان با موفقیت انجام شد`,
icon: `/`,
action: {
type: NotifTitleEnum.PAYMENT_SUCCESS,
url: `/`,
},
},
},
recipients: userRecipients,
metadata: {
priority: 1,
},
});
} catch (error) {
this.logger.error(
`Failed to send notification for online payment succeed event: ${event.restaurantId}`,
error instanceof Error ? error.stack : String(error),
);
}
}
}
@@ -10,6 +10,8 @@ import { OrderPaymentContext } from '../interface/payment';
import { OrderStatus } from 'src/modules/orders/interface/order.interface';
import { ChartPeriodEnum, PaymentChartDto } from '../dto/payment-chart.dto';
import { PaymentMessage, OrderMessage } from 'src/common/enums/message.enum';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { onlinePaymentSucceedEvent, paymentSucceedEvent } from '../events/payment.events';
@Injectable()
export class PaymentsService {
@@ -18,6 +20,7 @@ export class PaymentsService {
constructor(
private readonly em: EntityManager,
private readonly gatewayManager: GatewayManager,
private readonly eventEmitter: EventEmitter2,
) { }
async payOrder(orderId: string): Promise<{ paymentUrl: string | null }> {
@@ -127,6 +130,10 @@ export class PaymentsService {
em.persist([wallet, payment, order]);
await em.flush();
});
this.eventEmitter.emit(
paymentSucceedEvent.name,
new paymentSucceedEvent(ctx.order.id, ctx.order.restaurant.id, String(ctx.order?.orderNumber) || '', ctx.method, ctx.amount),
);
}
private async handleOnlinePayment(ctx: OrderPaymentContext): Promise<{ paymentUrl: string }> {
@@ -162,7 +169,7 @@ export class PaymentsService {
}
async verifyPayment(transactionId: string, orderId: string): Promise<Payment> {
return this.em.transactional(async em => {
const payment =await this.em.transactional(async em => {
const payment = await em.findOne(
Payment,
{ transactionId, order: { id: orderId } },
@@ -202,6 +209,11 @@ export class PaymentsService {
await em.flush();
return payment;
});
this.eventEmitter.emit(
onlinePaymentSucceedEvent.name ,
new onlinePaymentSucceedEvent(payment.id, payment.order.restaurant.id, String(payment.order?.orderNumber) || '', payment.amount),
);
return payment;
}
findAllByRestaurantId(restId: string, userId: string) {