Skip to content

Commit dba7ab7

Browse files
committed
fix: correct the enum postiion and add validation
1 parent fd3aca6 commit dba7ab7

5 files changed

Lines changed: 102 additions & 28 deletions

File tree

src/config/notification.config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,15 @@ export const AppNotificationConfig = {
1111
(process.env.NOTIFY_CHANNEL as NotificationChannel) ||
1212
NotificationChannel.AWS,
1313
};
14+
15+
export enum NotificationType {
16+
ADMISSION_ID = 'admission-id',
17+
EMAIL_VERIFICATION = 'email-verification',
18+
FORM_PAYMENT = 'form-payment',
19+
ADMISSION_REFERENCE = 'admission-reference',
20+
REGISTRATION_DATE = 'registration-date',
21+
REGISTRATION_COMPLETED = 'registration-completed',
22+
PAYMENT_REMINDER = 'payment-reminder',
23+
ATTENDANCE_ABSENCE = 'attendance-absence',
24+
COURSE_WITHDRAWAL_OTP = 'course-withdrawal-otp',
25+
}

src/notification/application/use-cases/send-notification.use-case.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { NotificationFactory } from '../../infrastructure/factories/notification
55
import { NotificationChannel } from '../../../config/notification.config';
66
import { NotificationRepository } from '../../infrastructure/repositories/notification.repository';
77
import { NotificationValidator } from '../validators/notification.validator';
8-
import { NotificationType } from '../../presentation/dtos/send-notification.dto';
8+
import { NotificationType } from '../../../config/notification.config';
99

1010
@Injectable()
1111
export class SendNotificationUseCase {

src/notification/application/validators/notification.validator.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import * as Joi from 'joi';
22
import { NotificationChannel } from '../../../config/notification.config';
3-
import {
4-
SendNotificationDto,
5-
NotificationType,
6-
} from '../../presentation/dtos/send-notification.dto';
3+
import { SendNotificationDto } from '../../presentation/dtos/send-notification.dto';
4+
import { NotificationType } from '../../../config/notification.config';
75

86
export class NotificationValidator {
97
static createNotificationSchema = Joi.object<SendNotificationDto>({
Lines changed: 86 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,97 @@
1-
import { Schema, Prop, SchemaFactory } from '@nestjs/mongoose';
1+
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
22
import { Document } from 'mongoose';
3+
import * as Joi from 'joi';
4+
import { NotificationChannel } from '../../../../config/notification.config';
5+
import { NotificationType } from '../../../../config/notification.config';
6+
7+
export type NotificationDocument = Notification & Document;
38

49
@Schema({ timestamps: true })
5-
export class NotificationDocument extends Document {
6-
@Prop({ required: true, minlength: 1, maxlength: 100 })
10+
export class Notification {
11+
@Prop({ required: true })
712
recipient: string;
813

9-
@Prop({ required: true, minlength: 1, maxlength: 100 })
14+
@Prop({ required: true })
1015
subject: string;
1116

12-
@Prop({ required: true, minlength: 1, maxlength: 1000 })
17+
@Prop({ required: true })
1318
body: string;
1419

15-
@Prop({ required: true })
16-
mediaType: string;
20+
@Prop({ required: true, enum: NotificationChannel })
21+
mediaType: NotificationChannel;
1722

18-
@Prop()
19-
sentAt?: Date;
23+
@Prop({ required: true, enum: NotificationType })
24+
notificationType: NotificationType;
25+
26+
@Prop({ default: Date.now })
27+
sentAt: Date;
2028
}
21-
export const NotificationSchema =
22-
SchemaFactory.createForClass(NotificationDocument);
29+
30+
export const NotificationSchema = SchemaFactory.createForClass(Notification);
31+
32+
const NotificationJoiSchema = Joi.object({
33+
recipient: Joi.string().required().messages({
34+
'string.empty': 'Recipient is required',
35+
}),
36+
subject: Joi.string().min(3).max(100).required().messages({
37+
'string.min': 'Subject must be at least 3 characters',
38+
'string.max': 'Subject must not exceed 100 characters',
39+
'string.empty': 'Subject is required',
40+
}),
41+
body: Joi.string().min(10).max(1000).required().messages({
42+
'string.min': 'Body must be at least 10 characters',
43+
'string.max': 'Body must not exceed 1000 characters',
44+
'string.empty': 'Body is required',
45+
}),
46+
mediaType: Joi.string()
47+
.valid(...Object.values(NotificationChannel))
48+
.required()
49+
.messages({
50+
'any.only': 'Invalid mediaType, must be one of: EMAIL, SMS',
51+
'string.empty': 'mediaType is required',
52+
}),
53+
notificationType: Joi.string()
54+
.valid(...Object.values(NotificationType))
55+
.required()
56+
.messages({
57+
'any.only': 'Invalid notificationType',
58+
'string.empty': 'notificationType is required',
59+
}),
60+
sentAt: Joi.date().default(Date.now),
61+
}).custom(
62+
(value: { recipient: string; mediaType: NotificationChannel }, helpers) => {
63+
if (
64+
value.mediaType === NotificationChannel.EMAIL &&
65+
!Joi.string().email().validate(value.recipient).value
66+
) {
67+
return helpers.message({
68+
custom: 'Recipient must be a valid email for EMAIL channel',
69+
});
70+
}
71+
if (
72+
value.mediaType === NotificationChannel.SMS &&
73+
!Joi.string()
74+
.pattern(/^\+?[1-9]\d{1,14}$/)
75+
.validate(value.recipient).value
76+
) {
77+
return helpers.message({
78+
custom: 'Recipient must be a valid phone number for SMS channel',
79+
});
80+
}
81+
return value;
82+
},
83+
);
84+
85+
NotificationSchema.pre('save', function (next) {
86+
const { error } = NotificationJoiSchema.validate(this.toObject(), {
87+
abortEarly: false,
88+
});
89+
if (error) {
90+
return next(
91+
new Error(
92+
'Validation failed: ' + error.details.map((d) => d.message).join(', '),
93+
),
94+
);
95+
}
96+
next();
97+
});

src/notification/presentation/dtos/send-notification.dto.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,7 @@
11
import { ApiProperty } from '@nestjs/swagger';
22
import * as Joi from 'joi';
33
import { NotificationChannel } from '../../../config/notification.config';
4-
5-
export enum NotificationType {
6-
ADMISSION_ID = 'admission-id',
7-
EMAIL_VERIFICATION = 'email-verification',
8-
FORM_PAYMENT = 'form-payment',
9-
ADMISSION_REFERENCE = 'admission-reference',
10-
REGISTRATION_DATE = 'registration-date',
11-
REGISTRATION_COMPLETED = 'registration-completed',
12-
PAYMENT_REMINDER = 'payment-reminder',
13-
ATTENDANCE_ABSENCE = 'attendance-absence',
14-
COURSE_WITHDRAWAL_OTP = 'course-withdrawal-otp',
15-
}
4+
import { NotificationType } from '../../../config/notification.config';
165

176
export class SendNotificationDto {
187
@ApiProperty({

0 commit comments

Comments
 (0)