refactor: handle kyc journey for customers

This commit is contained in:
Abdalhamid Alhamad
2025-02-20 16:18:06 +03:00
parent 270753cfd7
commit dae9cb6323
74 changed files with 1116 additions and 477 deletions

View File

@ -3,4 +3,5 @@ export enum NotificationScope {
TASK_COMPLETED = 'TASK_COMPLETED',
GIFT_RECEIVED = 'GIFT_RECEIVED',
OTP = 'OTP',
USER_INVITED = 'USER_INVITED',
}

View File

@ -1,5 +1,5 @@
import { MailerModule } from '@nestjs-modules/mailer';
import { Module } from '@nestjs/common';
import { forwardRef, Module } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TwilioModule } from 'nestjs-twilio';
@ -21,7 +21,7 @@ import { FirebaseService, NotificationsService, TwilioService } from './services
useFactory: buildMailerOptions,
inject: [ConfigService],
}),
UserModule,
forwardRef(() => UserModule),
],
providers: [NotificationsService, FirebaseService, NotificationsRepository, TwilioService],
exports: [NotificationsService],

View File

@ -25,36 +25,6 @@ export class NotificationsService {
private readonly mailerService: MailerService,
) {}
async sendPushNotification(userId: string, title: string, body: string) {
this.logger.log(`Sending push notification to user ${userId}`);
// Get the device tokens for the user
const tokens = await this.deviceService.getTokens(userId);
if (!tokens.length) {
this.logger.log(`No device tokens found for user ${userId} but notification created in the database`);
return;
}
// Send the notification
return this.firebaseService.sendNotification(tokens, title, body);
}
async sendSMS(to: string, body: string) {
this.logger.log(`Sending SMS to ${to}`);
await this.twilioService.sendSMS(to, body);
}
async sendEmail({ to, subject, data, template }: SendEmailRequestDto) {
this.logger.log(`Sending email to ${to}`);
await this.mailerService.sendMail({
to,
subject,
template,
context: { ...data },
});
this.logger.log(`Email sent to ${to}`);
}
async getNotifications(userId: string, pageOptionsDto: PageOptionsRequestDto) {
this.logger.log(`Getting notifications for user ${userId}`);
const [[notifications, count], unreadCount] = await Promise.all([
@ -77,6 +47,18 @@ export class NotificationsService {
return this.notificationRepository.markAsRead(userId);
}
async sendEmailAsync(data: SendEmailRequestDto) {
this.logger.log(`emitting ${EventType.NOTIFICATION_CREATED} event`);
const notification = await this.createNotification({
recipient: data.to,
title: data.subject,
message: '',
scope: NotificationScope.USER_INVITED,
channel: NotificationChannel.EMAIL,
});
return this.eventEmitter.emit(EventType.NOTIFICATION_CREATED, notification, data.data);
}
async sendOtpNotification(sendOtpRequest: ISendOtp, otp: string) {
this.logger.log(`Sending OTP to ${sendOtpRequest.recipient}`);
const notification = await this.createNotification({
@ -92,10 +74,42 @@ export class NotificationsService {
return this.eventEmitter.emit(EventType.NOTIFICATION_CREATED, notification);
}
private async sendPushNotification(userId: string, title: string, body: string) {
this.logger.log(`Sending push notification to user ${userId}`);
// Get the device tokens for the user
const tokens = await this.deviceService.getTokens(userId);
if (!tokens.length) {
this.logger.log(`No device tokens found for user ${userId} but notification created in the database`);
return;
}
// Send the notification
return this.firebaseService.sendNotification(tokens, title, body);
}
private async sendSMS(to: string, body: string) {
this.logger.log(`Sending SMS to ${to}`);
await this.twilioService.sendSMS(to, body);
}
private async sendEmail({ to, subject, data, template }: SendEmailRequestDto) {
this.logger.log(`Sending email to ${to}`);
await this.mailerService.sendMail({
to,
subject,
template,
context: { ...data },
});
this.logger.log(`Email sent to ${to}`);
}
private getTemplateFromNotification(notification: Notification) {
switch (notification.scope) {
case NotificationScope.OTP:
return 'otp';
case NotificationScope.USER_INVITED:
return 'user-invite';
default:
return 'otp';
}
@ -115,8 +129,8 @@ export class NotificationsService {
return this.sendEmail({
to: notification.recipient!,
subject: notification.title,
data,
template: this.getTemplateFromNotification(notification),
data,
});
}
}

View File

@ -0,0 +1,71 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>You're Invited!</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.container {
width: 100%;
max-width: 600px;
margin: 20px auto;
background-color: #ffffff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
text-align: center;
}
.header {
font-size: 24px;
font-weight: bold;
color: #333;
}
.content {
font-size: 16px;
color: #555;
margin: 20px 0;
}
.btn {
display: inline-block;
background-color: #007bff;
color: #ffffff;
text-decoration: none;
padding: 12px 20px;
border-radius: 6px;
font-size: 16px;
font-weight: bold;
}
.footer {
font-size: 14px;
color: #888;
margin-top: 20px;
}
.link {
color: #007bff;
text-decoration: none;
}
</style>
</head>
<body>
<div class="container">
<div class="header">You're Invited to Join Us!</div>
<p class="content">
You've been invited to join our platform. Click the button below to accept the invitation and set up your account.
</p>
<a href="{{inviteLink}}" class="btn">Accept Invitation</a>
<p class="content">
If the button above doesn't work, you can copy and paste this link into your browser:<br>
<a href="{{inviteLink}}" class="link">{{inviteLink}}</a>
</p>
<div class="footer">
If you didnt request this invitation, please ignore this email.
</div>
</div>
</body>
</html>