From b4b7d633d17e09c59353bf193f76d2d8838cda89 Mon Sep 17 00:00:00 2001 From: Methapon Metanipat Date: Wed, 30 Oct 2024 13:48:18 +0700 Subject: [PATCH 1/7] feat: add query notification --- src/controllers/00-notification-controller.ts | 30 ++++++++++++++++--- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index 1718e04..4fdfce8 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -14,6 +14,9 @@ import { } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import HttpStatus from "../interfaces/http-status"; +import prisma from "../db"; +import { Prisma } from "@prisma/client"; +import { queryOrNot } from "../utils/relation"; type NotificationCreate = {}; type NotificationUpdate = {}; @@ -29,12 +32,31 @@ export class NotificationController extends Controller { @Query() pageSize: number = 30, @Query() query = "", ) { - const total = 0; - - // TODO: implement + const where: Prisma.NotificationWhereInput = { + AND: [ + { + OR: queryOrNot<(typeof where)[]>(query, [ + { title: { contains: query } }, + { detail: { contains: query } }, + ]), + }, + { + OR: [ + { receiverId: req.user.sub }, + req.user.roles.length > 0 + ? { groupReceiver: { some: { name: { in: req.user.roles } } } } + : {}, + ], + }, + ], + }; + const [result, total] = await prisma.$transaction([ + prisma.notification.findMany({ where }), + prisma.notification.count({ where }), + ]); return { - result: [], + result, page, pageSize, total, From 549410e9e371cc2b463d51fc33e81229f267023f Mon Sep 17 00:00:00 2001 From: Methapon Metanipat Date: Wed, 30 Oct 2024 14:08:39 +0700 Subject: [PATCH 2/7] feat: add delete notification --- src/controllers/00-notification-controller.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index 4fdfce8..a006858 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -17,6 +17,7 @@ import HttpStatus from "../interfaces/http-status"; import prisma from "../db"; import { Prisma } from "@prisma/client"; import { queryOrNot } from "../utils/relation"; +import { notFoundError } from "../utils/error"; type NotificationCreate = {}; type NotificationUpdate = {}; @@ -95,8 +96,8 @@ export class NotificationController extends Controller { @Delete("{notificationId}") @Security("keycloak") async deleteNotification(@Request() req: RequestWithUser, @Path() notificationId: string) { - // TODO: implement - - return {}; + const record = await prisma.notification.deleteMany({ where: { id: notificationId } }); + if (record.count === 0) throw notFoundError("Notification"); + return record; } } From ae252acbb8acdee55e2e9f0973d1049b77e0f564 Mon Sep 17 00:00:00 2001 From: Methapon Metanipat Date: Wed, 30 Oct 2024 14:33:34 +0700 Subject: [PATCH 3/7] feat: add get notification single notification --- src/controllers/00-notification-controller.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index a006858..c0c463c 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -67,9 +67,11 @@ export class NotificationController extends Controller { @Get("{notificationId}") @Security("keycloak") async getNotification(@Request() req: RequestWithUser, @Path() notificationId: string) { - // TODO: implement + const record = await prisma.notification.findFirst({ where: { id: notificationId } }); - return {}; + if (!record) throw notFoundError("Notification"); + + return record; } @Post() From 34af1f9dcd8febef6a9d7654a7f8e8ffb5a3b603 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 5 Mar 2025 10:49:08 +0700 Subject: [PATCH 4/7] feat: read by user --- src/controllers/00-notification-controller.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index c0c463c..0e27847 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -67,7 +67,14 @@ export class NotificationController extends Controller { @Get("{notificationId}") @Security("keycloak") async getNotification(@Request() req: RequestWithUser, @Path() notificationId: string) { - const record = await prisma.notification.findFirst({ where: { id: notificationId } }); + const record = await prisma.notification.update({ + where: { id: notificationId }, + data: { + readByUser: { + connect: { id: req.user.sub }, + }, + }, + }); if (!record) throw notFoundError("Notification"); From 53c0c0fce9cdc6f67f1632fa5b27f5dc03e4656f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:04:21 +0700 Subject: [PATCH 5/7] refactor: response result --- src/controllers/00-notification-controller.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index 0e27847..ee20e50 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -18,6 +18,7 @@ import prisma from "../db"; import { Prisma } from "@prisma/client"; import { queryOrNot } from "../utils/relation"; import { notFoundError } from "../utils/error"; +import dayjs from "dayjs"; type NotificationCreate = {}; type NotificationUpdate = {}; @@ -50,14 +51,24 @@ export class NotificationController extends Controller { ], }, ], + NOT: { + readByUser: { some: { id: req.user.sub } }, + createdAt: dayjs().subtract(7, "days").toDate(), + }, }; const [result, total] = await prisma.$transaction([ - prisma.notification.findMany({ where }), + prisma.notification.findMany({ where, include: { readByUser: true } }), prisma.notification.count({ where }), ]); return { - result, + result: result.map((v) => ({ + id: v.id, + title: v.title, + detail: v.detail, + createdAt: v.createdAt, + read: v.readByUser.some((v) => v.id === req.user.sub), + })), page, pageSize, total, From f0db968b20b453ea9a1335b6d263a9dae8d706bf Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:16:18 +0700 Subject: [PATCH 6/7] feat: add permission query to noti --- prisma/schema.prisma | 4 ++++ src/controllers/00-notification-controller.ts | 16 ++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 5cfd276..671b21d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -21,6 +21,9 @@ model Notification { groupReceiver NotificationGroup[] + registeredBranchId String? + registeredBranch Branch? @relation(fields: [registeredBranchId], references: [id]) + receiver User? @relation(name: "NotificationReceiver", fields: [receiverId], references: [id], onDelete: Cascade) receiverId String? @@ -313,6 +316,7 @@ model Branch { quotation Quotation[] workflowTemplate WorkflowTemplate[] taskOrder TaskOrder[] + notification Notification[] } model BranchBank { diff --git a/src/controllers/00-notification-controller.ts b/src/controllers/00-notification-controller.ts index ee20e50..00baff7 100644 --- a/src/controllers/00-notification-controller.ts +++ b/src/controllers/00-notification-controller.ts @@ -19,10 +19,14 @@ import { Prisma } from "@prisma/client"; import { queryOrNot } from "../utils/relation"; import { notFoundError } from "../utils/error"; import dayjs from "dayjs"; +import HttpError from "../interfaces/http-error"; +import { createPermCondition } from "../services/permission"; type NotificationCreate = {}; type NotificationUpdate = {}; +const permissionCondCompany = createPermCondition((_) => true); + @Route("/api/v1/notification") @Tags("Notification") export class NotificationController extends Controller { @@ -46,7 +50,10 @@ export class NotificationController extends Controller { OR: [ { receiverId: req.user.sub }, req.user.roles.length > 0 - ? { groupReceiver: { some: { name: { in: req.user.roles } } } } + ? { + groupReceiver: { some: { name: { in: req.user.roles } } }, + registeredBranch: { OR: permissionCondCompany(req.user) }, + } : {}, ], }, @@ -97,8 +104,9 @@ export class NotificationController extends Controller { async createNotification(@Request() req: RequestWithUser, @Body() body: NotificationCreate) { // TODO: implement - this.setStatus(HttpStatus.CREATED); - return {}; + // this.setStatus(HttpStatus.CREATED); + + throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "Not implemented.", "notImplemented"); } @Put("{notificationId}") @@ -110,7 +118,7 @@ export class NotificationController extends Controller { ) { // TODO: implement - return {}; + throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "Not implemented.", "notImplemented"); } @Delete("{notificationId}") From c21ef1448b05b3b82317ba12506d60521ac97c0d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 5 Mar 2025 11:16:54 +0700 Subject: [PATCH 7/7] chore: migration --- .../20250305041645_add_noti_perm_related_field/migration.sql | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 prisma/migrations/20250305041645_add_noti_perm_related_field/migration.sql diff --git a/prisma/migrations/20250305041645_add_noti_perm_related_field/migration.sql b/prisma/migrations/20250305041645_add_noti_perm_related_field/migration.sql new file mode 100644 index 0000000..95388f6 --- /dev/null +++ b/prisma/migrations/20250305041645_add_noti_perm_related_field/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Notification" ADD COLUMN "registeredBranchId" TEXT; + +-- AddForeignKey +ALTER TABLE "Notification" ADD CONSTRAINT "Notification_registeredBranchId_fkey" FOREIGN KEY ("registeredBranchId") REFERENCES "Branch"("id") ON DELETE SET NULL ON UPDATE CASCADE;