update : add checkpermission and added api merge for aspects and subAspects
This commit is contained in:
parent
70702950d4
commit
94cf958318
|
|
@ -32,6 +32,21 @@ const permissionsData = [
|
|||
{
|
||||
code: "roles.delete",
|
||||
},
|
||||
{
|
||||
code: "managementAspect.readAll",
|
||||
},
|
||||
{
|
||||
code: "managementAspect.create",
|
||||
},
|
||||
{
|
||||
code: "managementAspect.update",
|
||||
},
|
||||
{
|
||||
code: "managementAspect.delete",
|
||||
},
|
||||
{
|
||||
code: "managementAspect.restore",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type SpecificPermissionCode = (typeof permissionsData)[number]["code"];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { configDotenv } from "dotenv";
|
|||
import { Hono } from "hono";
|
||||
import authRoutes from "./routes/auth/route";
|
||||
import usersRoute from "./routes/users/route";
|
||||
import aspectsRoute from "./routes/managementAspect/route";
|
||||
import managementAspectsRoute from "./routes/managementAspect/route";
|
||||
import { verifyAccessToken } from "./utils/authUtils";
|
||||
import permissionRoutes from "./routes/permissions/route";
|
||||
import { cors } from "hono/cors";
|
||||
|
|
@ -79,7 +79,7 @@ const routes = app
|
|||
.route("/dashboard", dashboardRoutes)
|
||||
.route("/roles", rolesRoute)
|
||||
.route("/dev", devRoutes)
|
||||
.route("/management-aspect", aspectsRoute)
|
||||
.route("/management-aspect", managementAspectsRoute)
|
||||
.onError((err, c) => {
|
||||
if (err instanceof DashboardError) {
|
||||
return c.json(
|
||||
|
|
|
|||
|
|
@ -1,418 +1,495 @@
|
|||
import { and, eq, ilike, isNull, or, sql } from "drizzle-orm";
|
||||
import { Hono } from "hono";
|
||||
import { and, eq, ilike, isNull, or, sql } from "drizzle-orm";
|
||||
import { Hono } from "hono";
|
||||
|
||||
import { z } from "zod";
|
||||
import { HTTPException } from "hono/http-exception";
|
||||
import db from "../../drizzle";
|
||||
import { aspects } from "../../drizzle/schema/aspects";
|
||||
import { subAspects } from "../../drizzle/schema/subAspects";
|
||||
import HonoEnv from "../../types/HonoEnv";
|
||||
import requestValidator from "../../utils/requestValidator";
|
||||
import authInfo from "../../middlewares/authInfo";
|
||||
import checkPermission from "../../middlewares/checkPermission";
|
||||
import { z } from "zod";
|
||||
import { HTTPException } from "hono/http-exception";
|
||||
import db from "../../drizzle";
|
||||
import { aspects } from "../../drizzle/schema/aspects";
|
||||
import { subAspects } from "../../drizzle/schema/subAspects";
|
||||
import HonoEnv from "../../types/HonoEnv";
|
||||
import requestValidator from "../../utils/requestValidator";
|
||||
import authInfo from "../../middlewares/authInfo";
|
||||
import checkPermission from "../../middlewares/checkPermission";
|
||||
|
||||
// Schema for creating and updating aspects
|
||||
export const aspectFormSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
subAspects: z
|
||||
.string()
|
||||
.refine(
|
||||
(data) => {
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
return Array.isArray(parsed);
|
||||
} catch {
|
||||
return false;
|
||||
// Schema for creating and updating aspects
|
||||
export const aspectFormSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
subAspects: z
|
||||
.string()
|
||||
.refine(
|
||||
(data) => {
|
||||
try {
|
||||
const parsed = JSON.parse(data);
|
||||
return Array.isArray(parsed);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
{
|
||||
message: "Sub Aspects must be an array",
|
||||
}
|
||||
},
|
||||
{
|
||||
message: "Sub Aspects must be an array",
|
||||
)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const aspectUpdateSchema = aspectFormSchema.extend({
|
||||
subAspects: z.string().optional().or(z.literal("")),
|
||||
});
|
||||
|
||||
// Schema for creating and updating subAspects
|
||||
export const subAspectFormSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
aspectId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const subAspectUpdateSchema = subAspectFormSchema.extend({});
|
||||
|
||||
const managementAspectRoute = new Hono<HonoEnv>()
|
||||
.use(authInfo)
|
||||
/**
|
||||
* Get All Aspects (With Metadata)
|
||||
*
|
||||
* Query params:
|
||||
* - includeTrashed: boolean (default: false)
|
||||
* - withMetadata: boolean
|
||||
*/
|
||||
// Get all aspects
|
||||
.get(
|
||||
"/",
|
||||
checkPermission("managementAspect.readAll"),
|
||||
requestValidator(
|
||||
"query",
|
||||
z.object({
|
||||
includeTrashed: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((v) => v?.toLowerCase() === "true"),
|
||||
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 { includeTrashed, page, limit, q } = c.req.valid("query");
|
||||
|
||||
const totalCountQuery = includeTrashed
|
||||
? sql<number>`(SELECT count(*) FROM ${aspects})`
|
||||
: sql<number>`(SELECT count(*) FROM ${aspects} WHERE ${aspects.deletedAt} IS NULL)`;
|
||||
|
||||
const result = await db
|
||||
.select({
|
||||
id: aspects.id,
|
||||
name: aspects.name,
|
||||
createdAt: aspects.createdAt,
|
||||
updatedAt: aspects.updatedAt,
|
||||
...(includeTrashed ? { deletedAt: aspects.deletedAt } : {}),
|
||||
fullCount: totalCountQuery,
|
||||
})
|
||||
.from(aspects)
|
||||
.where(
|
||||
and(
|
||||
includeTrashed ? undefined : isNull(aspects.deletedAt),
|
||||
q ? or(ilike(aspects.name, q), eq(aspects.id, q)) : undefined
|
||||
)
|
||||
)
|
||||
.offset(page * limit)
|
||||
.limit(limit);
|
||||
|
||||
return c.json({
|
||||
data: result.map((d) => ({ ...d, fullCount: undefined })),
|
||||
_metadata: {
|
||||
currentPage: page,
|
||||
totalPages: Math.ceil((Number(result[0]?.fullCount) ?? 0) / limit),
|
||||
totalItems: Number(result[0]?.fullCount) ?? 0,
|
||||
perPage: limit,
|
||||
},
|
||||
});
|
||||
}
|
||||
)
|
||||
.optional(),
|
||||
});
|
||||
|
||||
export const aspectUpdateSchema = aspectFormSchema.extend({
|
||||
subAspects: z.string().optional().or(z.literal("")),
|
||||
});
|
||||
|
||||
// Schema for creating and updating subAspects
|
||||
export const subAspectFormSchema = z.object({
|
||||
name: z.string().min(1).max(50),
|
||||
aspectId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const subAspectUpdateSchema = subAspectFormSchema.extend({});
|
||||
|
||||
const managementAspectRoute = new Hono<HonoEnv>()
|
||||
.use(authInfo)
|
||||
/**
|
||||
* Get All Aspects (With Metadata)
|
||||
*
|
||||
* Query params:
|
||||
* - includeTrashed: boolean (default: false)
|
||||
* - withMetadata: boolean
|
||||
*/
|
||||
// Get all aspects
|
||||
.get(
|
||||
"/",
|
||||
requestValidator(
|
||||
"query",
|
||||
z.object({
|
||||
includeTrashed: z
|
||||
.string()
|
||||
.optional()
|
||||
.transform((v) => v?.toLowerCase() === "true"),
|
||||
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 { includeTrashed, page, limit, q } = c.req.valid("query");
|
||||
|
||||
const totalCountQuery = includeTrashed
|
||||
? sql<number>`(SELECT count(*) FROM ${aspects})`
|
||||
: sql<number>`(SELECT count(*) FROM ${aspects} WHERE ${aspects.deletedAt} IS NULL)`;
|
||||
|
||||
const result = await db
|
||||
.select({
|
||||
id: aspects.id,
|
||||
name: aspects.name,
|
||||
createdAt: aspects.createdAt,
|
||||
updatedAt: aspects.updatedAt,
|
||||
...(includeTrashed ? { deletedAt: aspects.deletedAt } : {}),
|
||||
fullCount: totalCountQuery,
|
||||
|
||||
// Get aspect by id
|
||||
.get(
|
||||
"/:id",
|
||||
checkPermission("managementAspect.readAll"),
|
||||
requestValidator(
|
||||
"query",
|
||||
z.object({
|
||||
includeTrashed: z.string().default("false"),
|
||||
})
|
||||
.from(aspects)
|
||||
.where(
|
||||
and(
|
||||
includeTrashed ? undefined : isNull(aspects.deletedAt),
|
||||
q ? or(ilike(aspects.name, q), eq(aspects.id, q)) : undefined
|
||||
)
|
||||
)
|
||||
.offset(page * limit)
|
||||
.limit(limit);
|
||||
),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
|
||||
return c.json({
|
||||
data: result.map((d) => ({ ...d, fullCount: undefined })),
|
||||
_metadata: {
|
||||
currentPage: page,
|
||||
totalPages: Math.ceil((Number(result[0]?.fullCount) ?? 0) / limit),
|
||||
totalItems: Number(result[0]?.fullCount) ?? 0,
|
||||
perPage: limit,
|
||||
},
|
||||
});
|
||||
}
|
||||
)
|
||||
// Get aspect by id
|
||||
.get(
|
||||
"/:id",
|
||||
requestValidator(
|
||||
"query",
|
||||
z.object({
|
||||
includeTrashed: z.string().default("false"),
|
||||
})
|
||||
),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
if (!aspectId) throw new HTTPException(400, { message: "Missing id" });
|
||||
|
||||
if (!aspectId) throw new HTTPException(400, { message: "Missing id" });
|
||||
const includeTrashed =
|
||||
c.req.query("includeTrashed")?.toLowerCase() === "true";
|
||||
|
||||
const includeTrashed =
|
||||
c.req.query("includeTrashed")?.toLowerCase() === "true";
|
||||
const queryResult = await db
|
||||
.select({
|
||||
id: aspects.id,
|
||||
name: aspects.name,
|
||||
createdAt: aspects.createdAt,
|
||||
updatedAt: aspects.updatedAt,
|
||||
...(includeTrashed ? { deletedAt: aspects.deletedAt } : {}),
|
||||
subAspect: {
|
||||
name: subAspects.name,
|
||||
id: subAspects.id,
|
||||
},
|
||||
})
|
||||
.from(aspects)
|
||||
.leftJoin(subAspects, eq(aspects.id, subAspects.aspectId))
|
||||
.where(
|
||||
and(
|
||||
eq(aspects.id, aspectId),
|
||||
!includeTrashed ? isNull(aspects.deletedAt) : undefined
|
||||
)
|
||||
);
|
||||
|
||||
const queryResult = await db
|
||||
.select({
|
||||
id: aspects.id,
|
||||
name: aspects.name,
|
||||
createdAt: aspects.createdAt,
|
||||
updatedAt: aspects.updatedAt,
|
||||
...(includeTrashed ? { deletedAt: aspects.deletedAt } : {}),
|
||||
subAspect: {
|
||||
name: subAspects.name,
|
||||
id: subAspects.id,
|
||||
if (!queryResult.length)
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect does not exist",
|
||||
});
|
||||
|
||||
const subAspectsList = queryResult.reduce((prev, curr) => {
|
||||
if (!curr.subAspect) return prev;
|
||||
prev.set(curr.subAspect.id, curr.subAspect.name);
|
||||
return prev;
|
||||
}, new Map<string, string>()); // Map<id, name>
|
||||
|
||||
const aspectData = {
|
||||
...queryResult[0],
|
||||
subAspect: undefined,
|
||||
subAspects: Array.from(subAspectsList, ([id, name]) => ({ id, name })),
|
||||
};
|
||||
|
||||
return c.json(aspectData);
|
||||
}
|
||||
)
|
||||
|
||||
// Create aspect
|
||||
.post(
|
||||
"/",
|
||||
checkPermission("managementAspect.create"),
|
||||
requestValidator("json", aspectFormSchema),
|
||||
async (c) => {
|
||||
const aspectData = c.req.valid("json");
|
||||
|
||||
// Validasi untuk mengecek apakah nama aspek sudah ada
|
||||
const existingAspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(ilike(aspects.name, aspectData.name));
|
||||
|
||||
if (existingAspect.length > 0) {
|
||||
throw new HTTPException(400, { message: "Aspect name already existss" });
|
||||
}
|
||||
|
||||
const aspect = await db
|
||||
.insert(aspects)
|
||||
.values({
|
||||
name: aspectData.name,
|
||||
})
|
||||
.returning();
|
||||
|
||||
if (aspectData.subAspects) {
|
||||
const subAspectsArray = JSON.parse(aspectData.subAspects) as string[];
|
||||
|
||||
if (subAspectsArray.length) {
|
||||
await db.insert(subAspects).values(
|
||||
subAspectsArray.map((subAspect) => ({
|
||||
aspectId: aspect[0].id,
|
||||
name: subAspect,
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return c.json(
|
||||
{
|
||||
message: "Aspect created successfully",
|
||||
},
|
||||
})
|
||||
.from(aspects)
|
||||
.leftJoin(subAspects, eq(aspects.id, subAspects.aspectId))
|
||||
.where(
|
||||
and(
|
||||
eq(aspects.id, aspectId),
|
||||
!includeTrashed ? isNull(aspects.deletedAt) : undefined
|
||||
)
|
||||
201
|
||||
);
|
||||
|
||||
if (!queryResult.length)
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect does not exist",
|
||||
});
|
||||
|
||||
const subAspectsList = queryResult.reduce((prev, curr) => {
|
||||
if (!curr.subAspect) return prev;
|
||||
prev.set(curr.subAspect.id, curr.subAspect.name);
|
||||
return prev;
|
||||
}, new Map<string, string>()); // Map<id, name>
|
||||
|
||||
const aspectData = {
|
||||
...queryResult[0],
|
||||
subAspect: undefined,
|
||||
subAspects: Array.from(subAspectsList, ([id, name]) => ({ id, name })),
|
||||
};
|
||||
|
||||
return c.json(aspectData);
|
||||
}
|
||||
)
|
||||
// Create aspect
|
||||
.post(
|
||||
"/",
|
||||
requestValidator("json", aspectFormSchema),
|
||||
async (c) => {
|
||||
const aspectData = c.req.valid("json");
|
||||
|
||||
const aspect = await db
|
||||
.insert(aspects)
|
||||
.values({
|
||||
name: aspectData.name,
|
||||
})
|
||||
.returning();
|
||||
|
||||
if (aspectData.subAspects) {
|
||||
const subAspectsArray = JSON.parse(aspectData.subAspects) as string[];
|
||||
|
||||
if (subAspectsArray.length) {
|
||||
await db.insert(subAspects).values(
|
||||
subAspectsArray.map((subAspect) => ({
|
||||
aspectId: aspect[0].id,
|
||||
name: subAspect,
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return c.json(
|
||||
{
|
||||
message: "Aspect created successfully",
|
||||
},
|
||||
201
|
||||
);
|
||||
}
|
||||
)
|
||||
// Update aspect
|
||||
.patch(
|
||||
"/:id",
|
||||
requestValidator("json", aspectUpdateSchema),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
const aspectData = c.req.valid("json");
|
||||
// Update aspect
|
||||
.patch(
|
||||
"/:id",
|
||||
checkPermission("managementAspect.update"),
|
||||
requestValidator("json", aspectUpdateSchema),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
const aspectData = c.req.valid("json");
|
||||
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
|
||||
if (!aspect[0]) return c.notFound();
|
||||
|
||||
await db
|
||||
.update(aspects)
|
||||
.set({
|
||||
...aspectData,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(aspects.id, aspectId));
|
||||
|
||||
if (aspectData.subAspects) {
|
||||
const subAspectsArray = JSON.parse(aspectData.subAspects) as string[];
|
||||
|
||||
await db.delete(subAspects).where(eq(subAspects.aspectId, aspectId));
|
||||
|
||||
if (subAspectsArray.length) {
|
||||
await db.insert(subAspects).values(
|
||||
subAspectsArray.map((subAspect) => ({
|
||||
aspectId: aspectId,
|
||||
name: subAspect,
|
||||
}))
|
||||
// Validasi untuk mengecek apakah nama aspek baru sudah ada
|
||||
const existingAspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(
|
||||
and(
|
||||
ilike(aspects.name, aspectData.name),
|
||||
isNull(aspects.deletedAt),
|
||||
sql`${aspects.id} <> ${aspectId}`
|
||||
)
|
||||
);
|
||||
|
||||
if (existingAspect.length > 0) {
|
||||
throw new HTTPException(400, { message: "Aspect name already exists" });
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({
|
||||
message: "Aspect updated successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
// Delete aspect
|
||||
.delete(
|
||||
"/:id",
|
||||
requestValidator(
|
||||
"form",
|
||||
z.object({
|
||||
skipTrash: z.string().default("false"),
|
||||
})
|
||||
),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
|
||||
const skipTrash = c.req.valid("form").skipTrash.toLowerCase() === "true";
|
||||
if (!aspect[0]) return c.notFound();
|
||||
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), skipTrash ? undefined : isNull(aspects.deletedAt)));
|
||||
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
});
|
||||
|
||||
if (skipTrash) {
|
||||
await db.delete(aspects).where(eq(aspects.id, aspectId));
|
||||
} else {
|
||||
await db
|
||||
.update(aspects)
|
||||
.set({
|
||||
deletedAt: new Date(),
|
||||
...aspectData,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
}
|
||||
return c.json({
|
||||
message: "Aspect deleted successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
// Undo delete
|
||||
.patch(
|
||||
"/restore/:id",
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
.where(eq(aspects.id, aspectId));
|
||||
|
||||
const aspect = (await db.select().from(aspects).where(eq(aspects.id, aspectId)))[0];
|
||||
if (aspectData.subAspects) {
|
||||
const subAspectsArray = JSON.parse(aspectData.subAspects) as string[];
|
||||
|
||||
if (!aspect) return c.notFound();
|
||||
await db.delete(subAspects).where(eq(subAspects.aspectId, aspectId));
|
||||
|
||||
if (!aspect.deletedAt) {
|
||||
throw new HTTPException(400, {
|
||||
message: "The aspect is not deleted",
|
||||
if (subAspectsArray.length) {
|
||||
await db.insert(subAspects).values(
|
||||
subAspectsArray.map((subAspect) => ({
|
||||
aspectId: aspectId,
|
||||
name: subAspect,
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return c.json({
|
||||
message: "Aspect updated successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
await db.update(aspects).set({ deletedAt: null }).where(eq(aspects.id, aspectId));
|
||||
|
||||
return c.json({
|
||||
message: "Aspect restored successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
// Create sub aspect
|
||||
.post(
|
||||
"/subAspect",
|
||||
requestValidator("json", subAspectFormSchema),
|
||||
async (c) => {
|
||||
const subAspectData = c.req.valid("json");
|
||||
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, subAspectData.aspectId), isNull(aspects.deletedAt)));
|
||||
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
});
|
||||
|
||||
await db.insert(subAspects).values(subAspectData);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
message: "Sub aspect created successfully",
|
||||
},
|
||||
201
|
||||
);
|
||||
}
|
||||
)
|
||||
// Update sub aspect
|
||||
.patch(
|
||||
"/subAspect/:id",
|
||||
requestValidator("json", subAspectUpdateSchema),
|
||||
async (c) => {
|
||||
const subAspectId = c.req.param("id");
|
||||
const subAspectData = c.req.valid("json");
|
||||
|
||||
const subAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
|
||||
if (!subAspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The sub aspect is not found",
|
||||
});
|
||||
|
||||
await db
|
||||
.update(subAspects)
|
||||
.set({
|
||||
...subAspectData,
|
||||
updatedAt: new Date(),
|
||||
// Delete aspect
|
||||
.delete(
|
||||
"/:id",
|
||||
checkPermission("managementAspect.delete"),
|
||||
requestValidator(
|
||||
"form",
|
||||
z.object({
|
||||
skipTrash: z.string().default("false"),
|
||||
})
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
|
||||
return c.json({
|
||||
message: "Sub aspect updated successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
// Delete sub aspect
|
||||
.delete(
|
||||
"/subAspect/:id",
|
||||
async (c) => {
|
||||
const subAspectId = c.req.param("id");
|
||||
const skipTrash = c.req.valid("form").skipTrash.toLowerCase() === "true";
|
||||
|
||||
const subAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), skipTrash ? undefined : isNull(aspects.deletedAt)));
|
||||
|
||||
if (!subAspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The sub aspect is not found",
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
});
|
||||
|
||||
if (skipTrash) {
|
||||
await db.delete(aspects).where(eq(aspects.id, aspectId));
|
||||
} else {
|
||||
await db
|
||||
.update(aspects)
|
||||
.set({
|
||||
deletedAt: new Date(),
|
||||
})
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
}
|
||||
return c.json({
|
||||
message: "Aspect deleted successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
await db.delete(subAspects).where(eq(subAspects.id, subAspectId));
|
||||
// Undo delete
|
||||
.patch(
|
||||
"/restore/:id",
|
||||
checkPermission("managementAspect.restore"),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("id");
|
||||
|
||||
return c.json({
|
||||
message: "Sub aspect deleted successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
// Get sub aspects by aspect ID
|
||||
.get(
|
||||
"/subAspects/:aspectId",
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("aspectId");
|
||||
const aspect = (await db.select().from(aspects).where(eq(aspects.id, aspectId)))[0];
|
||||
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
if (!aspect) return c.notFound();
|
||||
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
if (!aspect.deletedAt) {
|
||||
throw new HTTPException(400, {
|
||||
message: "The aspect is not deleted",
|
||||
});
|
||||
}
|
||||
|
||||
await db.update(aspects).set({ deletedAt: null }).where(eq(aspects.id, aspectId));
|
||||
|
||||
return c.json({
|
||||
message: "Aspect restored successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
const subAspectsData = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.aspectId, aspectId));
|
||||
// Get sub aspects by aspect ID
|
||||
.get(
|
||||
"/subAspects/:aspectId",
|
||||
checkPermission("managementAspect.readAll"),
|
||||
async (c) => {
|
||||
const aspectId = c.req.param("aspectId");
|
||||
|
||||
return c.json({
|
||||
subAspects: subAspectsData,
|
||||
});
|
||||
}
|
||||
);
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, aspectId), isNull(aspects.deletedAt)));
|
||||
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
});
|
||||
|
||||
const subAspectsData = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.aspectId, aspectId));
|
||||
|
||||
return c.json({
|
||||
subAspects: subAspectsData,
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
// Create sub aspect
|
||||
.post(
|
||||
"/subAspect",
|
||||
checkPermission("managementAspect.create"),
|
||||
requestValidator("json", subAspectFormSchema),
|
||||
async (c) => {
|
||||
const subAspectData = c.req.valid("json");
|
||||
|
||||
// Validasi untuk mengecek apakah nama sub aspek sudah ada
|
||||
const existingSubAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(
|
||||
and(
|
||||
ilike(subAspects.name, subAspectData.name),
|
||||
eq(subAspects.aspectId, subAspectData.aspectId)
|
||||
)
|
||||
);
|
||||
|
||||
if (existingSubAspect.length > 0) {
|
||||
throw new HTTPException(400, { message: "Nama Sub Aspek sudah tersedia!" });
|
||||
}
|
||||
|
||||
const aspect = await db
|
||||
.select()
|
||||
.from(aspects)
|
||||
.where(and(eq(aspects.id, subAspectData.aspectId), isNull(aspects.deletedAt)));
|
||||
|
||||
if (!aspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The aspect is not found",
|
||||
});
|
||||
|
||||
await db.insert(subAspects).values(subAspectData);
|
||||
|
||||
return c.json(
|
||||
{
|
||||
message: "Sub aspect created successfully",
|
||||
},
|
||||
201
|
||||
);
|
||||
}
|
||||
)
|
||||
|
||||
// Update sub aspect
|
||||
.patch(
|
||||
"/subAspect/:id",
|
||||
checkPermission("managementAspect.update"),
|
||||
requestValidator("json", subAspectUpdateSchema),
|
||||
async (c) => {
|
||||
const subAspectId = c.req.param("id");
|
||||
const subAspectData = c.req.valid("json");
|
||||
|
||||
// Validasi untuk mengecek apakah nama sub aspek baru sudah ada
|
||||
const existingSubAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(
|
||||
and(
|
||||
ilike(subAspects.name, subAspectData.name),
|
||||
eq(subAspects.aspectId, subAspectData.aspectId),
|
||||
sql`${subAspects.id} <> ${subAspectId}`
|
||||
)
|
||||
);
|
||||
|
||||
if (existingSubAspect.length > 0) {
|
||||
throw new HTTPException(400, { message: "Name Sub Aspect already exists" });
|
||||
}
|
||||
|
||||
const subAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
|
||||
if (!subAspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The sub aspect is not found",
|
||||
});
|
||||
|
||||
await db
|
||||
.update(subAspects)
|
||||
.set({
|
||||
...subAspectData,
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
|
||||
return c.json({
|
||||
message: "Sub aspect updated successfully",
|
||||
});
|
||||
}
|
||||
)
|
||||
|
||||
// Delete sub aspect
|
||||
.delete(
|
||||
"/subAspect/:id",
|
||||
checkPermission("managementAspect.delete"),
|
||||
async (c) => {
|
||||
const subAspectId = c.req.param("id");
|
||||
|
||||
const subAspect = await db
|
||||
.select()
|
||||
.from(subAspects)
|
||||
.where(eq(subAspects.id, subAspectId));
|
||||
|
||||
if (!subAspect[0])
|
||||
throw new HTTPException(404, {
|
||||
message: "The sub aspect is not found",
|
||||
});
|
||||
|
||||
await db.delete(subAspects).where(eq(subAspects.id, subAspectId));
|
||||
|
||||
return c.json({
|
||||
message: "Sub aspect deleted successfully",
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
export default managementAspectRoute;
|
||||
|
||||
export default managementAspectRoute;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user