Skip to content

Commit 57f5ebc

Browse files
authored
Merge pull request #66 from UMC-AlbaLog/feat/ALBA_65
[FEATURE] 알람 기능 API 추가
2 parents fa1f3d2 + 42d8c7e commit 57f5ebc

6 files changed

Lines changed: 262 additions & 2 deletions

File tree

prisma/schema.prisma

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,6 @@ enum user_work_log_status {
272272

273273
enum notification_type {
274274
payment
275-
work_time @map("work time")
276-
work_approve @map("work approve")
275+
work_time
276+
work_approve
277277
}

src/DTO/error_dto.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ export class UserRegionError extends CustomError {
2626
super('USER_REGION_ERROR', 400, message, data);
2727
}
2828
}
29+
30+
export class NotificationNotFoundError extends CustomError {
31+
constructor(message: string = 'No Notification', data: any = null) {
32+
super('NO_NOTIFICATION', 404, message, data);
33+
}
34+
}

src/DTO/notification_dto.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { binToUuid } from '../util/uuid';
2+
import { notification_type as NotificationType } from '@prisma/client';
3+
4+
export interface DefaultNotificationInterface {
5+
userId: string;
6+
message: string;
7+
type: NotificationType;
8+
}
9+
10+
export class ResponseFromNotification implements DefaultNotificationInterface {
11+
userId: string;
12+
message: string;
13+
type: NotificationType;
14+
notificationId: string;
15+
status: boolean;
16+
createdAt: Date;
17+
updatedAt: Date;
18+
19+
constructor(data: {
20+
user_id: Uint8Array<ArrayBufferLike>;
21+
message: string;
22+
type: NotificationType;
23+
notification_id: Uint8Array<ArrayBufferLike>;
24+
status: boolean;
25+
created_at: Date;
26+
updated_at: Date;
27+
}) {
28+
this.userId = binToUuid(data.user_id);
29+
this.message = data.message;
30+
this.type = data.type as NotificationType;
31+
this.notificationId = binToUuid(data.notification_id);
32+
this.status = data.status;
33+
this.createdAt = data.created_at;
34+
this.updatedAt = data.updated_at;
35+
}
36+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { Body, Controller, Delete, Post, Query, Request, Route, Security, Tags } from 'tsoa';
2+
import { Request as ExpressRequest } from 'express';
3+
import { DefaultNotificationInterface, ResponseFromNotification } from '../DTO/notification_dto';
4+
import { NotificationService } from '../service/notification_service';
5+
import { TsoaSuccessResponse } from '../config/response_interface';
6+
7+
@Route('api/notification')
8+
@Tags('Notification')
9+
export class NotificationController extends Controller {
10+
/**
11+
* 알람 생성 api
12+
* 알람 type - work_time, work_approve, payment
13+
* @param body 알람 정보 입력
14+
* @summary 알람 생성 API
15+
*/
16+
@Post('/new')
17+
public async sendNotification(@Body() body: DefaultNotificationInterface) {
18+
const { userId, message, type } = body;
19+
20+
const notification = await NotificationService.sendNotificationService({
21+
userId,
22+
message,
23+
type,
24+
});
25+
26+
return new TsoaSuccessResponse<ResponseFromNotification>(notification);
27+
}
28+
29+
/**
30+
* 유저 알림 목록 조회
31+
* @param req
32+
* @summary 유저 알림 목록 조회 API
33+
*/
34+
@Post('/get')
35+
@Security('jwt')
36+
public async getUserNotification(@Request() req: ExpressRequest) {
37+
const userId = (req.user as unknown as { id: string }).id;
38+
39+
const result = await NotificationService.getNotificationService(userId);
40+
41+
return new TsoaSuccessResponse<ResponseFromNotification[]>(result);
42+
}
43+
44+
/**
45+
* 알림 삭제 API
46+
* query - 알림 UUID
47+
* @param req
48+
* @param notification_id 삭제할 ID
49+
* @summary 알림 삭제 API (하나)
50+
51+
*/
52+
@Delete('/delete')
53+
@Security('jwt')
54+
public async deleteNotification(
55+
@Request() req: ExpressRequest,
56+
@Query() notification_id: string,
57+
): Promise<TsoaSuccessResponse<string>> {
58+
const userId = (req.user as unknown as { id: string }).id;
59+
60+
const result = await NotificationService.deleteNotificationService(userId, notification_id);
61+
62+
return new TsoaSuccessResponse<string>(result as string);
63+
}
64+
65+
/**
66+
* 모든 알림 삭제 API
67+
* @summary 모든 알림 삭제 API
68+
* @param req
69+
*/
70+
@Delete('/deleteAll')
71+
@Security('jwt')
72+
public async deleteAllNotification(
73+
@Request() req: ExpressRequest,
74+
): Promise<TsoaSuccessResponse<number>> {
75+
const userId = (req.user as unknown as { id: string }).id;
76+
77+
const result: number = await NotificationService.deleteAllNotificationService(userId);
78+
79+
return new TsoaSuccessResponse<number>(result);
80+
}
81+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import prisma from '../config/prisma';
2+
import { DefaultNotificationInterface } from '../DTO/notification_dto';
3+
import { uuidToBin } from '../util/uuid';
4+
5+
export class NotificationRepository {
6+
static async sendNotification(data: DefaultNotificationInterface) {
7+
const { userId, message, type } = data;
8+
9+
const notification = await prisma.notification.create({
10+
data: {
11+
user_id: uuidToBin(userId),
12+
message,
13+
type,
14+
status: true,
15+
},
16+
});
17+
18+
return notification;
19+
}
20+
21+
static async getNotification(userId: Uint8Array<ArrayBuffer>) {
22+
const notification = await prisma.notification.findMany({
23+
where: {
24+
user_id: userId,
25+
status: true,
26+
},
27+
});
28+
29+
return notification;
30+
}
31+
32+
static async verifyUserNotification(
33+
userId: Uint8Array<ArrayBuffer>,
34+
notificationId: Uint8Array<ArrayBuffer>,
35+
) {
36+
const isExist = await prisma.notification.count({
37+
where: {
38+
user_id: userId,
39+
notification_id: notificationId,
40+
status: true,
41+
},
42+
});
43+
44+
if (isExist) {
45+
return true;
46+
}
47+
48+
return false;
49+
}
50+
51+
static async deleteNotification(
52+
userId: Uint8Array<ArrayBuffer>,
53+
notificationId: Uint8Array<ArrayBuffer>,
54+
) {
55+
const result = await prisma.notification.update({
56+
data: {
57+
status: false,
58+
},
59+
where: {
60+
notification_id: notificationId,
61+
user_id: userId,
62+
},
63+
});
64+
65+
return result;
66+
}
67+
68+
static async deleteAllNotification(userId: Uint8Array<ArrayBuffer>) {
69+
const result = await prisma.notification.updateMany({
70+
data: {
71+
status: false,
72+
},
73+
where: {
74+
user_id: userId,
75+
status: true,
76+
},
77+
});
78+
79+
return result.count;
80+
}
81+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { NotificationNotFoundError } from '../DTO/error_dto';
2+
import { DefaultNotificationInterface, ResponseFromNotification } from '../DTO/notification_dto';
3+
import { NotificationRepository } from '../repository/notification_repository';
4+
import { binToUuid, uuidToBin } from '../util/uuid';
5+
6+
export class NotificationService {
7+
static async sendNotificationService(data: DefaultNotificationInterface) {
8+
const result = await NotificationRepository.sendNotification(data);
9+
10+
return new ResponseFromNotification(result);
11+
}
12+
13+
static async getNotificationService(userId: string) {
14+
const parsedId = uuidToBin(userId);
15+
16+
const notification = await NotificationRepository.getNotification(parsedId);
17+
18+
if (notification.length === 0) {
19+
throw new NotificationNotFoundError('알림이 존재하지 않습니다.', { userId });
20+
}
21+
22+
const result = notification.map((item) => new ResponseFromNotification(item));
23+
24+
return result;
25+
}
26+
27+
static async deleteNotificationService(userId: string, notificationId: string) {
28+
const parsedId = uuidToBin(userId);
29+
const parsedNotificationId = uuidToBin(notificationId);
30+
31+
const isExist = await NotificationRepository.verifyUserNotification(
32+
parsedId,
33+
parsedNotificationId,
34+
);
35+
36+
if (!isExist) {
37+
throw new NotificationNotFoundError('알림이 존재하지 않습니다.', { userId });
38+
}
39+
40+
const result = await NotificationRepository.deleteNotification(parsedId, parsedNotificationId);
41+
42+
return binToUuid(result.notification_id);
43+
}
44+
45+
static async deleteAllNotificationService(userId: string) {
46+
const parsedId = uuidToBin(userId);
47+
48+
const result = await NotificationRepository.deleteAllNotification(parsedId);
49+
50+
if (result === 0) {
51+
throw new NotificationNotFoundError('알림이 존재하지 않습니다.', { userId });
52+
}
53+
54+
return result;
55+
}
56+
}

0 commit comments

Comments
 (0)