From 20188025d64ab22cb277d5a272491abb8839336d Mon Sep 17 00:00:00 2001 From: ferdiansyah666 Date: Mon, 19 Aug 2024 16:53:38 +0700 Subject: [PATCH 1/5] add: route for assessmentRequestManagement --- apps/backend/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/backend/src/index.ts b/apps/backend/src/index.ts index 9076b79..88a66d5 100644 --- a/apps/backend/src/index.ts +++ b/apps/backend/src/index.ts @@ -16,6 +16,7 @@ import HonoEnv from "./types/HonoEnv"; import devRoutes from "./routes/dev/route"; import appEnv from "./appEnv"; import questionsRoute from "./routes/questions/route"; +import assessmentsRequestManagementRoutes from "./routes/assessmentRequestManagement/route"; configDotenv(); @@ -80,6 +81,7 @@ const routes = app .route("/roles", rolesRoute) .route("/dev", devRoutes) .route("/questions", questionsRoute) + .route("/assessmentRequestManagement",assessmentsRequestManagementRoutes) .onError((err, c) => { if (err instanceof DashboardError) { return c.json( From 0948b9e117f95753741682c63a6d4e279aded315 Mon Sep 17 00:00:00 2001 From: ferdiansyah666 Date: Mon, 19 Aug 2024 16:54:21 +0700 Subject: [PATCH 2/5] add: premission for assessmentRequestManagement --- apps/backend/src/data/permissions.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/backend/src/data/permissions.ts b/apps/backend/src/data/permissions.ts index e4d458c..6314f8c 100644 --- a/apps/backend/src/data/permissions.ts +++ b/apps/backend/src/data/permissions.ts @@ -47,6 +47,16 @@ const permissionsData = [ { code: "questions.restore", }, + { + code :"assessmentRequestManagement.readAll", + }, + { + code: "assessmentRequestManagement.update", + }, + { + code :"assessmentRequestManagement.read", + }, + ] as const; export type SpecificPermissionCode = (typeof permissionsData)[number]["code"]; From eaf8c8a027fffcaf2764b9a618dae14202772d3a Mon Sep 17 00:00:00 2001 From: ferdiansyah666 Date: Mon, 19 Aug 2024 16:55:13 +0700 Subject: [PATCH 3/5] create: develop API assessmentRequestManagement --- .../assessmentRequestManagement/route.ts | 173 ++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 apps/backend/src/routes/assessmentRequestManagement/route.ts diff --git a/apps/backend/src/routes/assessmentRequestManagement/route.ts b/apps/backend/src/routes/assessmentRequestManagement/route.ts new file mode 100644 index 0000000..e05e3bd --- /dev/null +++ b/apps/backend/src/routes/assessmentRequestManagement/route.ts @@ -0,0 +1,173 @@ + import { and, eq, ilike, or, sql } from "drizzle-orm"; + import { Hono } from "hono"; + import checkPermission from "../../middlewares/checkPermission"; + import { z } from "zod"; + import { HTTPException } from "hono/http-exception"; + import db from "../../drizzle"; + import { assessments } from "../../drizzle/schema/assessments"; + import { respondents } from "../../drizzle/schema/respondents"; + import { users } from "../../drizzle/schema/users"; + import HonoEnv from "../../types/HonoEnv"; + import requestValidator from "../../utils/requestValidator"; + import authInfo from "../../middlewares/authInfo"; + + export const assessmentFormSchema = z.object({ + respondentId: z.string().min(1), + status: z.enum(["tertunda", "disetujui", "ditolak", "selesai"]), + reviewedBy: z.string().min(1), + validatedBy: z.string().min(1), + validatedAt: z.string().optional(), + }); + + export const assessmentUpdateSchema = assessmentFormSchema.extend({ + validatedAt: z.string().optional().or(z.literal("")), + }); + + const assessmentsRequestManagementRoutes = new Hono() + .use(authInfo) + /** + * Get All Assessments (With Metadata) + * + * Query params: + * - withMetadata: boolean + */ + .get( + "/", + checkPermission("assessmentRequestManagement.readAll"), + requestValidator( + "query", + z.object({ + withMetadata: z + .string() + .optional() + .transform((v) => v?.toLowerCase() === "true"), + page: z.coerce.number().int().min(0).default(0), + limit: z.coerce.number().int().min(1).max(1000).default(10), + q: z.string().default(""), + }) + ), + async (c) => { + const { page, limit, q } = c.req.valid("query"); + + const totalCountQuery = sql`(SELECT count(*) FROM ${assessments})`; + + const result = await db + .select({ + idPermohonan: assessments.id, + namaResponden: users.name, + namaPerusahaan: respondents.companyName, + status: assessments.status, + tanggal: assessments.createdAt, + fullCount: totalCountQuery, + }) + .from(assessments) + .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) + .leftJoin(users, eq(respondents.userId, users.id)) + .where( + q + ? or( + ilike(users.name, `%${q}%`), + ilike(respondents.companyName, `%${q}%`), + eq(assessments.id, q) + ) + : undefined + ) + .offset(page * limit) + .limit(limit); + + return c.json({ + data: result.map((d) => ({ + idPermohonan: d.idPermohonan, + namaResponden: d.namaResponden, + namaPerusahaan: d.namaPerusahaan, + status: d.status, + tanggal: d.tanggal, + })), + _metadata: { + currentPage: page, + totalPages: Math.ceil( + (Number(result[0]?.fullCount) ?? 0) / limit + ), + totalItems: Number(result[0]?.fullCount) ?? 0, + perPage: limit, + }, + }); + } + ) + + // Get assessment by id + .get( + "/:id", + checkPermission("assessmentRequestManagement.read"), + async (c) => { + const assessmentId = c.req.param("id"); + + const queryResult = await db + .select({ + // id: assessments.id, + tanggal: assessments.createdAt, + nama: users.name, + posisi: respondents.position, + pengalamanKerja: respondents.workExperience, + email: users.email, + namaPerusahaan: respondents.companyName, + alamat: respondents.address, + nomorTelepon: respondents.phoneNumber, + username: users.username, + status: assessments.status, + }) + .from(assessments) + .leftJoin(respondents, eq(assessments.respondentId, respondents.id)) + .leftJoin(users, eq(respondents.userId, users.id)) + .where(eq(assessments.id, assessmentId)); + + if (!queryResult.length) + throw new HTTPException(404, { + message: "The assessment does not exist", + }); + + const assessmentData = queryResult[0]; + + return c.json(assessmentData); + } + ) + + .patch( + "/:id", + checkPermission("assessmentRequestManagement.update"), + requestValidator( + "json", + z.object({ + status: z.enum(["tertunda", "disetujui", "ditolak", "selesai"]), + }) + ), + async (c) => { + const assessmentId = c.req.param("id"); + const { status } = c.req.valid("json"); + + const assessment = await db + .select() + .from(assessments) + .where(and(eq(assessments.id, assessmentId),)); + + if (!assessment[0]) throw new HTTPException(404, { + message: "Assessment tidak ditemukan.", + }); + + await db + .update(assessments) + .set({ + status, + }) + .where(eq(assessments.id, assessmentId)); + + return c.json({ + message: "Status assessment berhasil diperbarui.", + }); + } + ) + + + + + export default assessmentsRequestManagementRoutes; From ddbce9d65e386e377d240a73d9041b6bc6b255b4 Mon Sep 17 00:00:00 2001 From: ferdiansyah666 Date: Fri, 6 Sep 2024 15:06:59 +0700 Subject: [PATCH 4/5] create API for assessmentRequestManagement --- apps/backend/src/data/permissions.ts | 9 +++++++++ apps/backend/src/index.ts | 2 ++ .../src/routes/assessmentRequestManagement/route.ts | 4 ++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/backend/src/data/permissions.ts b/apps/backend/src/data/permissions.ts index d0a7c76..2396260 100644 --- a/apps/backend/src/data/permissions.ts +++ b/apps/backend/src/data/permissions.ts @@ -47,6 +47,15 @@ const permissionsData = [ { code: "questions.restore", }, + { + code :"assessmentRequestManagement.readAll", + }, + { + code: "assessmentRequestManagement.update", + }, + { + code :"assessmentRequestManagement.read", + }, { code: "managementAspect.readAll", }, diff --git a/apps/backend/src/index.ts b/apps/backend/src/index.ts index 925b235..820fe77 100644 --- a/apps/backend/src/index.ts +++ b/apps/backend/src/index.ts @@ -93,11 +93,13 @@ const routes = app .route("/assessmentRequest", assessmentRequestRoute) .route("/forgot-password", forgotPasswordRoutes) .route("/assessments", assessmentsRoute) + .route("/assessmentRequestManagement",assessmentsRequestManagementRoutes) .onError((err, c) => { if (err instanceof DashboardError) { return c.json( { message: err.message, + errorCode: err.errorCode, formErrors: err.formErrors, }, diff --git a/apps/backend/src/routes/assessmentRequestManagement/route.ts b/apps/backend/src/routes/assessmentRequestManagement/route.ts index e05e3bd..c8e7fca 100644 --- a/apps/backend/src/routes/assessmentRequestManagement/route.ts +++ b/apps/backend/src/routes/assessmentRequestManagement/route.ts @@ -13,7 +13,7 @@ export const assessmentFormSchema = z.object({ respondentId: z.string().min(1), - status: z.enum(["tertunda", "disetujui", "ditolak", "selesai"]), + status: z.enum(["menunggu konfirmasi", "disetujui", "ditolak", "selesai"]), reviewedBy: z.string().min(1), validatedBy: z.string().min(1), validatedAt: z.string().optional(), @@ -138,7 +138,7 @@ requestValidator( "json", z.object({ - status: z.enum(["tertunda", "disetujui", "ditolak", "selesai"]), + status: z.enum(["menunggu konfirmasi", "disetujui", "ditolak", "selesai"]), }) ), async (c) => { From 66323174f78f355ac7388df2b77673b45be3966a Mon Sep 17 00:00:00 2001 From: ferdiansyah666 Date: Thu, 12 Sep 2024 10:07:46 +0700 Subject: [PATCH 5/5] update: perubahan status --- apps/backend/src/drizzle/schema/assessments.ts | 8 +++++--- .../src/routes/assessmentRequestManagement/route.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/backend/src/drizzle/schema/assessments.ts b/apps/backend/src/drizzle/schema/assessments.ts index 75b9ccd..8507c1a 100644 --- a/apps/backend/src/drizzle/schema/assessments.ts +++ b/apps/backend/src/drizzle/schema/assessments.ts @@ -4,7 +4,7 @@ import { relations } from "drizzle-orm"; import { respondents } from "./respondents"; import { users } from "./users"; -const statusEnum = pgEnum("status", ["menunggu konfirmasi", "disetujui", "ditolak", "selesai"]); +const statusEnum = pgEnum("status", ["menunggu konfirmasi", "diterima", "ditolak", "selesai"]); export const assessments = pgTable("assessments", { id: varchar("id", { length: 50 }) @@ -16,7 +16,9 @@ export const assessments = pgTable("assessments", { reviewedAt: timestamp("reviewedAt", { mode: "date" }), validatedBy: varchar("validatedBy"), validatedAt: timestamp("validatedAt", { mode: "date" }), - createdAt: timestamp("createdAt", { mode: "date" }).defaultNow(), + createdAt: timestamp("createdAt", { mode: "date" }).defaultNow(), + + }); // Query Tools in PosgreSQL -// CREATE TYPE status AS ENUM ('menunggu konfirmasi', 'disetujui', 'ditolak', 'selesai'); \ No newline at end of file +// CREATE TYPE status AS ENUM ('menunggu konfirmasi', 'diterima', 'ditolak', 'selesai'); \ No newline at end of file diff --git a/apps/backend/src/routes/assessmentRequestManagement/route.ts b/apps/backend/src/routes/assessmentRequestManagement/route.ts index c8e7fca..802c702 100644 --- a/apps/backend/src/routes/assessmentRequestManagement/route.ts +++ b/apps/backend/src/routes/assessmentRequestManagement/route.ts @@ -13,7 +13,7 @@ export const assessmentFormSchema = z.object({ respondentId: z.string().min(1), - status: z.enum(["menunggu konfirmasi", "disetujui", "ditolak", "selesai"]), + status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), reviewedBy: z.string().min(1), validatedBy: z.string().min(1), validatedAt: z.string().optional(), @@ -138,7 +138,7 @@ requestValidator( "json", z.object({ - status: z.enum(["menunggu konfirmasi", "disetujui", "ditolak", "selesai"]), + status: z.enum(["menunggu konfirmasi", "diterima", "ditolak", "selesai"]), }) ), async (c) => {