fix: ( notification ) add notification templet and fix issues

This commit is contained in:
Abubeker Yasin
2026-06-19 06:12:46 +03:00
parent f1dfbbcc3f
commit 42c020c97a
6 changed files with 75 additions and 31 deletions

View File

@@ -40,18 +40,5 @@ export class SendEmail {
@IsOptional()
context?: Record<string, any>;
@ApiPropertyOptional()
@IsOptional()
@IsString()
templateName?: string;
@ApiPropertyOptional()
@IsOptional()
@IsEmail()
from?: string;
@ApiPropertyOptional()
@IsOptional()
@IsEmail()
replyTo?: string;
}

View File

@@ -29,11 +29,17 @@ export class EmailClientService implements OnApplicationBootstrap {
}
async sendEmail(dto: SendEmail) {
if (!this.enabled) return {};
if (!this.enabled) {
this.logger.warn(`RABBITMQ disabled — skipped EMAIL to ${dto.to}`);
return {};
}
this.emailServiceClient.emit("send-email", {
...dto,
appKey: "IFHCRS-LICENSE-MANAGEMENT",
});
this.logger.log(
`EMAIL emitted to RabbitMQ [${process.env.EMAIL_QUEUE ?? "email_queue"}] pattern='send-email' to=${dto.to} subject="${dto.subject ?? ""}" body="${dto.text ?? dto.body ?? dto.html ?? ""}"`,
);
return {};
}
}

View File

@@ -169,7 +169,12 @@ export class NotificationsService {
private async getUserPreferredChannels(recipient: string): Promise<NotificationChannelType[]> {
const user = await this.prisma.user.findFirst({
where: {
OR: [{ id: recipient }, { email: recipient }, { phone: recipient }],
OR: [
{ id: recipient },
{ email: recipient },
{ phone: recipient },
{ passenger: { id: recipient } },
],
},
include: { preferences: true },
});
@@ -192,7 +197,12 @@ export class NotificationsService {
): Promise<string | null> {
const user = await this.prisma.user.findFirst({
where: {
OR: [{ id: recipient }, { email: recipient }, { phone: recipient }],
OR: [
{ id: recipient },
{ email: recipient },
{ phone: recipient },
{ passenger: { id: recipient } },
],
},
});
@@ -239,27 +249,46 @@ export class NotificationsService {
@OnEvent('booking.created')
async onBookingCreated(payload: any) {
const booking = payload.booking;
await this.send(
'booking.created',
payload.booking.passengerId,
booking.passengerId,
{
bookingRef: payload.booking.bookingRef,
bookingRef: booking.bookingRef,
amount: this.formatAmount(booking),
currency: booking.displayCurrency ?? 'ETB',
category: 'BOOKING',
deepLink: `edr://bookings/${payload.booking.bookingRef}`,
deepLink: `edr://bookings/${booking.bookingRef}`,
},
// For now, always notify the travelling passenger on every channel.
['IN_APP', 'EMAIL', 'SMS'],
);
}
@OnEvent('payment.succeeded')
async onPaymentSucceeded(payload: any) {
const booking = payload.booking;
await this.send(
'payment.succeeded',
payload.booking.passengerId,
booking.passengerId,
{
bookingRef: payload.booking.bookingRef,
bookingRef: booking.bookingRef,
amount: this.formatAmount(booking),
currency: booking.displayCurrency ?? 'ETB',
category: 'PAYMENT',
deepLink: `edr://tickets/${payload.booking.bookingRef}`,
deepLink: `edr://tickets/${booking.bookingRef}`,
},
['IN_APP', 'EMAIL', 'SMS'],
);
}
/**
* Formats a booking's payable amount from minor units into a major-unit string.
* Money is stored as integer minor units (e.g. 59600 santim) to avoid floating-point
* drift; we divide by 100 only here, at the display edge. e.g. 59600 -> "596.00".
*/
private formatAmount(booking: any): string {
const minor = booking.displayTotalMinor ?? booking.totalMinor ?? 0;
return (minor / 100).toFixed(2);
}
}

View File

@@ -31,20 +31,34 @@ export class SmsClientService implements OnApplicationBootstrap {
}
async sendSms(dto: SingleMessageDto) {
if (!this.enabled) return {};
if (!this.enabled) {
this.logger.warn(`RABBITMQ disabled — skipped SMS to ${dto.to}`);
return {};
}
this.smsClient.emit("send-sms", {
...dto,
appKey: "IFHCRS-LICENSE-MANAGEMENT",
});
this.logger.log(
`SMS emitted to RabbitMQ [${process.env.SMS_QUEUE ?? "sms_queue"}] pattern='send-sms' to=${dto.to} message="${dto.message}"`,
);
return {};
}
async sendBulkMessages(dto: BulkMessagesDto) {
if (!this.enabled) return {};
if (!this.enabled) {
this.logger.warn(`RABBITMQ disabled — skipped BULK SMS (${dto.messages?.length ?? 0} messages)`);
return {};
}
this.smsClient.emit("ozeking-bulk-sms", {
...dto,
appKey: "IFHCRS-LICENSE-MANAGEMENT",
});
this.logger.log(
`BULK SMS emitted to RabbitMQ [${process.env.SMS_QUEUE ?? "sms_queue"}] pattern='ozeking-bulk-sms' count=${dto.messages?.length ?? 0} messages=${JSON.stringify(
(dto.messages ?? []).map((m) => ({ to: m.to, message: m.message })),
)}`,
);
return {};
}
}