From 52bf59cc64c7aea42f8d45032b960478e7465882 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 19 Apr 2024 13:02:47 +0700 Subject: [PATCH 001/157] fix: edit should not require telephone no --- src/controllers/branch-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 9aa12a3..5a51f7a 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -57,7 +57,7 @@ type BranchUpdate = { address?: string; zipCode?: string; email?: string; - telephoneNo: string; + telephoneNo?: string; contactName?: string; contact?: string | string[] | null; lineId?: string; From 2e5fba0b07483764c268b585a4bb6ae57825a457 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:28:39 +0700 Subject: [PATCH 002/157] feat: role based permission endpoints --- src/controllers/permission-controller.ts | 166 +++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/src/controllers/permission-controller.ts b/src/controllers/permission-controller.ts index 8d9b17c..37d2af7 100644 --- a/src/controllers/permission-controller.ts +++ b/src/controllers/permission-controller.ts @@ -83,6 +83,82 @@ export class MenuController extends Controller { } } +type RoleMenuPermissionCreate = { + userRole: string; + permission: string; +}; + +type RoleMenuPermissionEdit = { + userRole?: string; + permission?: string; +}; + +@Route("v1/permission/menu/{menuId}/role") +@Tags("Permission") +@Security("keycloak") +export class RoleMenuController extends Controller { + @Get() + async listRoleMenu(@Path() menuId: string) { + const record = await prisma.roleMenuPermission.findMany({ + where: { menuId }, + orderBy: [{ userRole: "asc" }, { createdAt: "asc" }], + }); + return record; + } + + @Post() + async createRoleMenu(@Path() menuId: string, @Body() body: RoleMenuPermissionCreate) { + const menu = await prisma.menu.findFirst({ where: { id: menuId } }); + + if (!menu) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Menu not found.", + "missing_or_invalid_parameter", + ); + } + + const record = await prisma.roleMenuPermission.create({ + data: Object.assign(body, { menuId }), + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{roleMenuId}") + async editRoleMenu( + @Path("roleMenuId") id: string, + @Path() menuId: string, + @Body() body: RoleMenuPermissionEdit, + ) { + const record = await prisma.roleMenuPermission + .update({ + where: { id, menuId }, + data: body, + }) + .catch((e) => { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "data_not_found"); + } + throw new Error(e); + }); + + return record; + } + + @Delete("{roleMenuId}") + async deleteRoleMenu(@Path("roleMenuId") id: string, @Path() menuId: string) { + const record = await prisma.roleMenuPermission.deleteMany({ + where: { id, menuId }, + }); + if (record.count <= 0) { + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "data_not_found"); + } + } +} + type MenuComponentCreate = { componentId: string; componentTag: string; @@ -176,3 +252,93 @@ export class MenuComponentController extends Controller { } } } + +type RoleMenuComponentPermissionCreate = { + userRole: string; + permission: string; +}; + +type RoleMenuComponentPermissionEdit = { + userRole?: string; + permission?: string; +}; + +@Route("v1/permission/menu-component/{menuComponentId}/role") +@Tags("Permission") +@Security("keycloak") +export class RoleMenuComponentController extends Controller { + @Get() + async listRoleMenuComponent(@Path() menuComponentId: string) { + const record = await prisma.roleMenuComponentPermission.findMany({ + where: { menuComponentId }, + orderBy: [{ userRole: "asc" }, { createdAt: "asc" }], + }); + return record; + } + + @Post() + async createRoleMenuComponent( + @Path() menuComponentId: string, + @Body() body: RoleMenuComponentPermissionCreate, + ) { + const menu = await prisma.menuComponent.findFirst({ where: { id: menuComponentId } }); + + if (!menu) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Menu not found.", + "missing_or_invalid_parameter", + ); + } + + const record = await prisma.roleMenuComponentPermission.create({ + data: Object.assign(body, { menuComponentId }), + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{roleMenuComponentId}") + async editRoleMenuComponent( + @Path("roleMenuComponentId") id: string, + @Path() menuComponentId: string, + @Body() body: RoleMenuComponentPermissionEdit, + ) { + const record = await prisma.roleMenuComponentPermission + .update({ + where: { id, menuComponentId }, + data: body, + }) + .catch((e) => { + if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Role menu component cannot be found.", + "data_not_found", + ); + } + throw new Error(e); + }); + + return record; + } + + @Delete("{roleMenuComponentId}") + async deleteRoleMenuComponent( + @Path("roleMenuComponentId") id: string, + @Path() menuComponentId: string, + ) { + const record = await prisma.roleMenuComponentPermission.deleteMany({ + where: { id, menuComponentId }, + }); + if (record.count <= 0) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Role menu component cannot be found.", + "data_not_found", + ); + } + } +} From 503505757db4037d27a24657cf6159f27afaa52e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:18:10 +0700 Subject: [PATCH 003/157] fix: do not remove default role --- src/controllers/user-controller.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index a31b0a8..d65a21c 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -370,7 +370,16 @@ export class UserController extends Controller { if (!resultAddRole) { throw new Error("Failed. Cannot set user's role."); } else { - if (Array.isArray(currentRole)) await removeUserRoles(userId, currentRole); + if (Array.isArray(currentRole)) + await removeUserRoles( + userId, + currentRole.filter( + (a) => + !["uma_authorization", "offline_access", "default-roles"].some((b) => + a.name.includes(b), + ), + ), + ); } userRole = role.name; From e38e4c71d02670d9a16c5e228fac8d989535827c Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:17:50 +0700 Subject: [PATCH 004/157] feat: can create branch when create customer --- src/controllers/customer-branch-controller.ts | 4 +- src/controllers/customer-controller.ts | 123 +++++++++++++++++- 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index c2220cc..0cf41ad 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -29,7 +29,7 @@ function imageLocation(id: string) { return `employee/profile-img-${id}`; } -type CustomerBranchCreate = { +export type CustomerBranchCreate = { customerId: string; status?: Status; @@ -56,7 +56,7 @@ type CustomerBranchCreate = { provinceId?: string | null; }; -type CustomerBranchUpdate = { +export type CustomerBranchUpdate = { customerId?: string; status?: "ACTIVE" | "INACTIVE"; diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 4be81cf..086a8d2 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -18,6 +18,7 @@ import prisma from "../db"; import minio from "../services/minio"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; +import { CustomerBranchCreate, CustomerBranchUpdate } from "./customer-branch-controller"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); @@ -30,6 +31,7 @@ export type CustomerCreate = { customerType: CustomerType; customerName: string; customerNameEN: string; + customerBranch?: Omit[]; }; export type CustomerUpdate = { @@ -37,6 +39,7 @@ export type CustomerUpdate = { customerType?: CustomerType; customerName?: string; customerNameEN?: string; + customerBranch?: (Omit & { id: string })[]; }; function imageLocation(id: string) { @@ -103,10 +106,74 @@ export class CustomerController extends Controller { const code = `${body.customerType}${(+(last?.code.slice(-6) || 0) + 1).toString().padStart(6, "0")}`; + const { customerBranch, ...payload } = body; + + const provinceId = body.customerBranch?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + const districtId = body.customerBranch?.reduce((acc, cur) => { + if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId); + return acc; + }, []); + const subDistrictId = body.customerBranch?.reduce((acc, cur) => { + if (cur.subDistrictId && !acc.includes(cur.subDistrictId)) + return acc.concat(cur.subDistrictId); + return acc; + }, []); + + const [province, district, subDistrict] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: provinceId } } }), + prisma.district.findMany({ where: { id: { in: districtId } } }), + prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }), + ]); + + if (provinceId && province.length !== provinceId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "missing_or_invalid_parameter", + ); + } + if (districtId && district.length !== districtId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some district cannot be found.", + "missing_or_invalid_parameter", + ); + } + if (subDistrictId && subDistrict.length !== subDistrictId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some sub district cannot be found.", + "missing_or_invalid_parameter", + ); + } + const record = await prisma.customer.create({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, data: { - ...body, + ...payload, code, + branch: { + createMany: { + data: + customerBranch?.map((v, i) => ({ + ...v, + branchNo: `${i + 1}`, + createdBy: req.user.name, + updateBy: req.user.name, + })) || [], + }, + }, createdBy: req.user.name, updateBy: req.user.name, }, @@ -138,11 +205,61 @@ export class CustomerController extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); } + const provinceId = body.customerBranch?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + const districtId = body.customerBranch?.reduce((acc, cur) => { + if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId); + return acc; + }, []); + const subDistrictId = body.customerBranch?.reduce((acc, cur) => { + if (cur.subDistrictId && !acc.includes(cur.subDistrictId)) + return acc.concat(cur.subDistrictId); + return acc; + }, []); + + const [province, district, subDistrict] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: provinceId } } }), + prisma.district.findMany({ where: { id: { in: districtId } } }), + prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }), + ]); + + if (provinceId && province.length !== provinceId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "missing_or_invalid_parameter", + ); + } + if (districtId && district.length !== districtId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some district cannot be found.", + "missing_or_invalid_parameter", + ); + } + if (subDistrictId && subDistrict.length !== subDistrictId?.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some sub district cannot be found.", + "missing_or_invalid_parameter", + ); + } + + const { customerBranch, ...payload } = body; + const record = await prisma.customer.update({ where: { id: customerId }, data: { - ...body, - createdBy: req.user.name, + ...payload, + branch: { + updateMany: + customerBranch?.map((v) => ({ + where: { id: v.id }, + data: { ...v, updateBy: req.user.name }, + })) || [], + }, updateBy: req.user.name, }, }); From 6b8aa241eb8c2cdceaeed0c4f347cef16a1ac3a3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 16:20:45 +0700 Subject: [PATCH 005/157] chore: db migration add new table --- .../20240422092016_add_running_no_table/migration.sql | 10 ++++++++++ prisma/schema.prisma | 5 +++++ 2 files changed, 15 insertions(+) create mode 100644 prisma/migrations/20240422092016_add_running_no_table/migration.sql diff --git a/prisma/migrations/20240422092016_add_running_no_table/migration.sql b/prisma/migrations/20240422092016_add_running_no_table/migration.sql new file mode 100644 index 0000000..ad777a0 --- /dev/null +++ b/prisma/migrations/20240422092016_add_running_no_table/migration.sql @@ -0,0 +1,10 @@ +-- CreateTable +CREATE TABLE "RunningNo" ( + "key" TEXT NOT NULL, + "value" INTEGER NOT NULL, + + CONSTRAINT "RunningNo_pkey" PRIMARY KEY ("key") +); + +-- CreateIndex +CREATE UNIQUE INDEX "RunningNo_key_key" ON "RunningNo"("key"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1652ee2..791a18c 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -93,6 +93,11 @@ model RoleMenuComponentPermission { updatedAt DateTime @updatedAt } +model RunningNo { + key String @id @unique + value Int +} + model UserMenuComponentPermission { id String @id @default(uuid()) From 00dff0814f39f98420b74177f412dc1262ef23e2 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:05:08 +0700 Subject: [PATCH 006/157] refactor: branch code gen transaction --- src/controllers/branch-controller.ts | 59 +++++++++++++++++----------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 5a51f7a..d4791a5 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -241,33 +241,46 @@ export class BranchController extends Controller { const year = new Date().getFullYear(); - const last = await prisma.branch.findFirst({ - orderBy: { createdAt: "desc" }, - where: { headOfficeId: headOfficeId ?? null }, - }); + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: !headOfficeId ? `HQ${year.toString().slice(2)}` : `BR${head?.code.slice(2, 5)}`, + }, + create: { + key: !headOfficeId ? `HQ${year.toString().slice(2)}` : `BR${head?.code.slice(2, 5)}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); - const code = !headOfficeId - ? `HQ${year.toString().slice(2)}${+(last?.code.slice(-1) || 0) + 1}` - : `BR${head?.code.slice(2, 5)}${(+(last?.code.slice(-2) || 0) + 1).toString().padStart(2, "0")}`; + const code = !headOfficeId + ? `HQ${year.toString().slice(2)}${last.value}` + : `BR${head?.code.slice(2, 5)}${last.value.toString().padStart(2, "0")}`; - const record = await prisma.branch.create({ - include: { - province: true, - district: true, - subDistrict: true, + return await tx.branch.create({ + include: { + province: true, + district: true, + subDistrict: true, + }, + data: { + ...rest, + code, + isHeadOffice: !headOfficeId, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + headOffice: { connect: headOfficeId ? { id: headOfficeId } : undefined }, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); }, - data: { - ...rest, - code, - isHeadOffice: !headOfficeId, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - headOffice: { connect: headOfficeId ? { id: headOfficeId } : undefined }, - createdBy: req.user.name, - updateBy: req.user.name, + { + isolationLevel: Prisma.TransactionIsolationLevel.Serializable, }, - }); + ); if (headOfficeId) { await prisma.branch.updateMany({ From 0635ef062d872d95e338de7ccc222e154b2a20aa Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:09:37 +0700 Subject: [PATCH 007/157] feat: also delete branch that not sent on update --- src/controllers/customer-controller.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 086a8d2..24d930f 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -254,6 +254,9 @@ export class CustomerController extends Controller { data: { ...payload, branch: { + deleteMany: { + id: { notIn: customerBranch?.map((v) => v.id) || [] }, + }, updateMany: customerBranch?.map((v) => ({ where: { id: v.id }, From b455985ba11d34b8ff88b219dbda60be7b0f2c85 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 22 Apr 2024 17:16:30 +0700 Subject: [PATCH 008/157] feat: update query to also return branch --- src/controllers/customer-controller.ts | 56 +++++++++++++++++++++----- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 24d930f..8fbe421 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -55,6 +55,7 @@ export class CustomerController extends Controller { @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, + @Query() includeBranch: boolean = false, ) { const where = { OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], @@ -62,6 +63,17 @@ export class CustomerController extends Controller { const [result, total] = await prisma.$transaction([ prisma.customer.findMany({ + include: { + branch: includeBranch + ? { + include: { + province: true, + district: true, + subDistrict: true, + }, + } + : undefined, + }, orderBy: { createdAt: "asc" }, where, take: pageSize, @@ -85,7 +97,18 @@ export class CustomerController extends Controller { @Get("{customerId}") async getById(@Path() customerId: string) { - const record = await prisma.customer.findFirst({ where: { id: customerId } }); + const record = await prisma.customer.findFirst({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, + where: { id: customerId }, + }); if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); return Object.assign(record, { @@ -250,19 +273,30 @@ export class CustomerController extends Controller { const { customerBranch, ...payload } = body; const record = await prisma.customer.update({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, where: { id: customerId }, data: { ...payload, - branch: { - deleteMany: { - id: { notIn: customerBranch?.map((v) => v.id) || [] }, - }, - updateMany: - customerBranch?.map((v) => ({ - where: { id: v.id }, - data: { ...v, updateBy: req.user.name }, - })) || [], - }, + branch: + (customerBranch && { + deleteMany: { + id: { notIn: customerBranch.map((v) => v.id) || [] }, + }, + updateMany: + customerBranch.map((v) => ({ + where: { id: v.id }, + data: { ...v, updateBy: req.user.name }, + })) || [], + }) || + undefined, updateBy: req.user.name, }, }); From 8bb3e8a0a0e2d75db227a286c8883348d5d1e276 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:19:16 +0700 Subject: [PATCH 009/157] refactor: update code gen strategy (branch user) --- src/controllers/branch-user-controller.ts | 70 +++++++++++------------ 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index d33b307..c9059a4 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -1,4 +1,4 @@ -import { Prisma, Status, UserType } from "@prisma/client"; +import { Branch, Prisma, Status, User, UserType } from "@prisma/client"; import { Body, Controller, @@ -20,6 +20,37 @@ import { RequestWithUser } from "../interfaces/user"; type BranchUserBody = { user: string[] }; +async function userBranchCodeGen(branch: Branch, user: User[]) { + await prisma.$transaction( + async (tx) => { + for (const usr of user) { + if (usr.code !== null) continue; + + const typ = usr.userType; + + const last = await tx.runningNo.upsert({ + where: { + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0) : ""}`, + }, + create: { + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0) : ""}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + await prisma.user.update({ + where: { id: usr.id }, + data: { + code: `${last.key.slice(7)}${last.value.toString().padStart(4, "0")}`, + }, + }); + } + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); +} + @Route("api/branch/{branchId}/user") @Tags("Branch User") @Security("keycloak") @@ -114,42 +145,7 @@ export class BranchUserController extends Controller { }), ]); - const group: Record = { - USER: [], - AGENCY: [], - DELEGATE: [], - MESSENGER: [], - }; - - for (const u of user) group[u.userType].push(u.id); - - for (const g of Object.values(UserType)) { - if (group[g].length === 0) continue; - - const last = await prisma.branchUser.findFirst({ - orderBy: { createdAt: "desc" }, - include: { user: true }, - where: { - branchId, - user: { - userType: g, - code: { startsWith: `${branch.code.slice(4).padEnd(3, "0")}` }, - }, - }, - }); - - const code = (idx: number) => - `${branch.code.slice(4).padEnd(3, "0")}${g !== "USER" ? g.charAt(0) : ""}${(+(last?.user.code?.slice(-4) || 0) + idx + 1).toString().padStart(4, "0")}`; - - await prisma.$transaction( - group[g].map((v, i) => - prisma.user.updateMany({ - where: { id: v, code: null }, - data: { code: code(i) }, - }), - ), - ); - } + await userBranchCodeGen(branch, user); } @Delete() From a2e38d7069ee1d84484f22d48b0fc4449c5386eb Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:19:27 +0700 Subject: [PATCH 010/157] chore: format --- src/controllers/branch-controller.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index d4791a5..68a4213 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -277,9 +277,7 @@ export class BranchController extends Controller { }, }); }, - { - isolationLevel: Prisma.TransactionIsolationLevel.Serializable, - }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, ); if (headOfficeId) { From 3fcabd723b517b9854fdae0a5faa31709acd44b1 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:28:44 +0700 Subject: [PATCH 011/157] feat: prepare for dynamic user type --- src/controllers/branch-user-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index c9059a4..7046ad6 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -30,10 +30,10 @@ async function userBranchCodeGen(branch: Branch, user: User[]) { const last = await tx.runningNo.upsert({ where: { - key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0) : ""}`, + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0).toLocaleUpperCase() : ""}`, }, create: { - key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0) : ""}`, + key: `BR_USR_${branch.code.slice(4).padEnd(3, "0")}${typ !== "USER" ? typ.charAt(0).toLocaleUpperCase() : ""}`, value: 1, }, update: { value: { increment: 1 } }, From 3b8e156e47d4f388db95688cca44e6aebeba8903 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 11:56:40 +0700 Subject: [PATCH 012/157] refactor: update code gen strategy (customer) --- src/controllers/customer-controller.ts | 71 +++++++++++++++----------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 8fbe421..d251748 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -122,13 +122,6 @@ export class CustomerController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: CustomerCreate) { - const last = await prisma.customer.findFirst({ - orderBy: { createdAt: "desc" }, - where: { customerType: body.customerType }, - }); - - const code = `${body.customerType}${(+(last?.code.slice(-6) || 0) + 1).toString().padStart(6, "0")}`; - const { customerBranch, ...payload } = body; const provinceId = body.customerBranch?.reduce((acc, cur) => { @@ -173,34 +166,50 @@ export class CustomerController extends Controller { ); } - const record = await prisma.customer.create({ - include: { - branch: { + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `CUSTOMER_${body.customerType}`, + }, + create: { + key: `CUSTOMER_${body.customerType}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await prisma.customer.create({ include: { - province: true, - district: true, - subDistrict: true, + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, }, - }, - }, - data: { - ...payload, - code, - branch: { - createMany: { - data: - customerBranch?.map((v, i) => ({ - ...v, - branchNo: `${i + 1}`, - createdBy: req.user.name, - updateBy: req.user.name, - })) || [], + data: { + ...payload, + code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}`, + branch: { + createMany: { + data: + customerBranch?.map((v, i) => ({ + ...v, + branchNo: `${i + 1}`, + createdBy: req.user.name, + updateBy: req.user.name, + })) || [], + }, + }, + createdBy: req.user.name, + updateBy: req.user.name, }, - }, - createdBy: req.user.name, - updateBy: req.user.name, + }); }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); this.setStatus(HttpStatus.CREATED); From 21aeacfaf33336ceec1fa43ae416ed12600b1657 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 13:48:08 +0700 Subject: [PATCH 013/157] feat: sort stats --- src/controllers/branch-controller.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 68a4213..f772de3 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -109,13 +109,26 @@ export class BranchController extends Controller { const record = await prisma.branch.findMany({ select: { id: true, + headOfficeId: true, + isHeadOffice: true, nameEN: true, name: true, - isHeadOffice: true, }, + orderBy: [{ isHeadOffice: "desc" }, { createdAt: "asc" }], }); - return record.map((a) => + const sort = record.reduce<(typeof record)[]>((acc, curr) => { + for (const i of acc) { + if (i[0].id === curr.headOfficeId) { + i.push(curr); + return acc; + } + } + acc.push([curr]); + return acc; + }, []); + + return sort.flat().map((a) => Object.assign(a, { count: list.find((b) => b.branchId === a.id)?._count ?? 0, }), From 7627b51a2502741c3f5e554450c59634acd6bd41 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 23 Apr 2024 18:09:08 +0700 Subject: [PATCH 014/157] feat: add missing field --- .../migration.sql | 28 +++++++++ prisma/schema.prisma | 12 +++- src/controllers/customer-branch-controller.ts | 59 +++++++++++++------ src/controllers/customer-controller.ts | 2 + 4 files changed, 79 insertions(+), 22 deletions(-) create mode 100644 prisma/migrations/20240423104607_add_missing_field/migration.sql diff --git a/prisma/migrations/20240423104607_add_missing_field/migration.sql b/prisma/migrations/20240423104607_add_missing_field/migration.sql new file mode 100644 index 0000000..6c8a704 --- /dev/null +++ b/prisma/migrations/20240423104607_add_missing_field/migration.sql @@ -0,0 +1,28 @@ +/* + Warnings: + + - You are about to drop the column `latitude` on the `CustomerBranch` table. All the data in the column will be lost. + - You are about to drop the column `longitude` on the `CustomerBranch` table. All the data in the column will be lost. + - Added the required column `bussinessType` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `employmentOffice` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `jobDescription` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `jobPosition` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `payDate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `saleEmployee` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `wageDate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "Customer" ADD COLUMN "taxNo" TEXT; + +-- AlterTable +ALTER TABLE "CustomerBranch" DROP COLUMN "latitude", +DROP COLUMN "longitude", +ADD COLUMN "bussinessType" TEXT NOT NULL, +ADD COLUMN "employmentOffice" TEXT NOT NULL, +ADD COLUMN "jobDescription" TEXT NOT NULL, +ADD COLUMN "jobPosition" TEXT NOT NULL, +ADD COLUMN "payDate" TEXT NOT NULL, +ADD COLUMN "saleEmployee" TEXT NOT NULL, +ADD COLUMN "wageDate" TEXT NOT NULL, +ALTER COLUMN "taxNo" DROP NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 791a18c..6d805d0 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -335,6 +335,7 @@ model Customer { customerType CustomerType customerName String customerNameEN String + taxNo String? status Status @default(CREATED) @@ -357,7 +358,7 @@ model CustomerBranch { customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade) customerId String - taxNo String + taxNo String? registerName String registerDate DateTime authorizedCapital String @@ -379,8 +380,13 @@ model CustomerBranch { email String telephoneNo String - latitude String - longitude String + employmentOffice String + bussinessType String + jobPosition String + jobDescription String + saleEmployee String + payDate String + wageDate String status Status @default(CREATED) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 0cf41ad..9cac3da 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -51,6 +51,14 @@ export type CustomerBranchCreate = { registerDate: Date; authorizedCapital: string; + employmentOffice: string; + bussinessType: string; + jobPosition: string; + jobDescription: string; + saleEmployee: string; + payDate: string; + wageDate: string; + subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; @@ -78,6 +86,14 @@ export type CustomerBranchUpdate = { registerDate?: Date; authorizedCapital?: string; + employmentOffice?: string; + bussinessType?: string; + jobPosition?: string; + jobDescription?: string; + saleEmployee?: string; + payDate?: string; + wageDate?: string; + subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; @@ -226,27 +242,32 @@ export class CustomerBranchController extends Controller { const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; - const count = await prisma.customerBranch.count({ - where: { customerId }, - }); + const record = await prisma.$transaction( + async (tx) => { + const count = await tx.customerBranch.count({ + where: { customerId }, + }); - const record = await prisma.customerBranch.create({ - include: { - province: true, - district: true, - subDistrict: true, + return await tx.customerBranch.create({ + include: { + province: true, + district: true, + subDistrict: true, + }, + data: { + ...rest, + branchNo: `${count + 1}`, + customer: { connect: { id: customerId } }, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); }, - data: { - ...rest, - branchNo: `${count + 1}`, - customer: { connect: { id: customerId } }, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); await prisma.customer.updateMany({ where: { id: customerId, status: Status.CREATED }, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index d251748..276e863 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -31,6 +31,7 @@ export type CustomerCreate = { customerType: CustomerType; customerName: string; customerNameEN: string; + taxNo?: string; customerBranch?: Omit[]; }; @@ -39,6 +40,7 @@ export type CustomerUpdate = { customerType?: CustomerType; customerName?: string; customerNameEN?: string; + taxNo?: string; customerBranch?: (Omit & { id: string })[]; }; From 1e8ef2114c8f4843f783a49cf7b75abe34f97efc Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:01:24 +0700 Subject: [PATCH 015/157] chore: add migration --- .../20240424030115_add_missing_field_en/migration.sql | 10 ++++++++++ prisma/schema.prisma | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 prisma/migrations/20240424030115_add_missing_field_en/migration.sql diff --git a/prisma/migrations/20240424030115_add_missing_field_en/migration.sql b/prisma/migrations/20240424030115_add_missing_field_en/migration.sql new file mode 100644 index 0000000..d3726ca --- /dev/null +++ b/prisma/migrations/20240424030115_add_missing_field_en/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - Added the required column `bussinessTypeEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + - Added the required column `jobPositionEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "CustomerBranch" ADD COLUMN "bussinessTypeEN" TEXT NOT NULL, +ADD COLUMN "jobPositionEN" TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6d805d0..9d562fa 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -382,7 +382,9 @@ model CustomerBranch { employmentOffice String bussinessType String + bussinessTypeEN String jobPosition String + jobPositionEN String jobDescription String saleEmployee String payDate String From a5d59c6e8b77a9e6f1d71e660b4c32d74097d289 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:02:37 +0700 Subject: [PATCH 016/157] fix: add missing field --- src/controllers/customer-branch-controller.ts | 12 ++++++------ src/controllers/customer-controller.ts | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 9cac3da..ff24201 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -36,7 +36,7 @@ export type CustomerBranchCreate = { legalPersonNo: string; - taxNo: string; + taxNo: string | null; name: string; nameEN: string; addressEN: string; @@ -44,8 +44,6 @@ export type CustomerBranchCreate = { zipCode: string; email: string; telephoneNo: string; - longitude: string; - latitude: string; registerName: string; registerDate: Date; @@ -53,7 +51,9 @@ export type CustomerBranchCreate = { employmentOffice: string; bussinessType: string; + bussinessTypeEN: string; jobPosition: string; + jobPositionEN: string; jobDescription: string; saleEmployee: string; payDate: string; @@ -71,7 +71,7 @@ export type CustomerBranchUpdate = { legalPersonNo?: string; - taxNo?: string; + taxNo?: string | null; name?: string; nameEN?: string; addressEN?: string; @@ -79,8 +79,6 @@ export type CustomerBranchUpdate = { zipCode?: string; email?: string; telephoneNo?: string; - longitude?: string; - latitude?: string; registerName?: string; registerDate?: Date; @@ -88,7 +86,9 @@ export type CustomerBranchUpdate = { employmentOffice?: string; bussinessType?: string; + bussinessTypeEN?: string; jobPosition?: string; + jobPositionEN?: string; jobDescription?: string; saleEmployee?: string; payDate?: string; diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 276e863..2721e52 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -31,7 +31,7 @@ export type CustomerCreate = { customerType: CustomerType; customerName: string; customerNameEN: string; - taxNo?: string; + taxNo?: string | null; customerBranch?: Omit[]; }; @@ -40,7 +40,7 @@ export type CustomerUpdate = { customerType?: CustomerType; customerName?: string; customerNameEN?: string; - taxNo?: string; + taxNo?: string | null; customerBranch?: (Omit & { id: string })[]; }; From 5053f83470b1c2f01bebee48065d201978485bf3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:26:26 +0700 Subject: [PATCH 017/157] feat: update keycloak function --- src/services/keycloak.ts | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/services/keycloak.ts b/src/services/keycloak.ts index db7b4b5..b83a522 100644 --- a/src/services/keycloak.ts +++ b/src/services/keycloak.ts @@ -2,8 +2,8 @@ import { DecodedJwt, createDecoder } from "fast-jwt"; const KC_URL = process.env.KC_URL; const KC_REALM = process.env.KC_REALM; -const KC_CLIENT_ID = process.env.KC_SERVICE_ACCOUNT_CLIENT_ID; -const KC_SECRET = process.env.KC_SERVICE_ACCOUNT_SECRET; +const KC_ADMIN_USERNAME = process.env.KC_ADMIN_USERNAME; +const KC_ADMIN_PASSWORD = process.env.KC_ADMIN_PASSWORD; let token: string | null = null; let decoded: DecodedJwt | null = null; @@ -14,7 +14,7 @@ const jwtDecode = createDecoder({ complete: true }); * Check if token is expired or will expire in 30 seconds * @returns true if expire or can't get exp, false otherwise */ -export function isTokenExpired(token: string, beforeExpire: number = 30) { +export function isTokenExpired(token: string, beforeExpire: number = 10) { decoded = jwtDecode(token); if (decoded && decoded.payload.exp) { @@ -28,19 +28,20 @@ export function isTokenExpired(token: string, beforeExpire: number = 30) { * Get token from keycloak if needed */ export async function getToken() { - if (!KC_CLIENT_ID || !KC_SECRET) { - throw new Error("KC_CLIENT_ID and KC_SECRET are required to used this feature."); + if (!KC_ADMIN_PASSWORD || !KC_ADMIN_USERNAME) { + throw new Error("KC_ADMIN_USERNAME and KC_ADMIN_PASSWORD are required to used this feature."); } if (token && !isTokenExpired(token)) return token; const body = new URLSearchParams(); - body.append("client_id", KC_CLIENT_ID); - body.append("client_secret", KC_SECRET); - body.append("grant_type", "client_credentials"); + body.append("client_id", "admin-cli"); + body.append("grant_type", "password"); + body.append("username", KC_ADMIN_USERNAME); + body.append("password", KC_ADMIN_PASSWORD); - const res = await fetch(`${KC_URL}/realms/${KC_REALM}/protocol/openid-connect/token`, { + const res = await fetch(`${KC_URL}/realms/master/protocol/openid-connect/token`, { method: "POST", body: body, }).catch((e) => console.error(e)); From a3e72cbb1b76d439317dc2922035a17a302466b6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:42:02 +0700 Subject: [PATCH 018/157] refactor!: add v1 prefix to endpoints --- src/controllers/address-controller.ts | 2 +- src/controllers/branch-contact-controller.ts | 2 +- src/controllers/branch-controller.ts | 2 +- src/controllers/branch-user-controller.ts | 4 ++-- src/controllers/customer-branch-controller.ts | 2 +- src/controllers/customer-controller.ts | 2 +- src/controllers/employee-checkup-controller.ts | 2 +- src/controllers/employee-controller.ts | 2 +- src/controllers/employee-other-info-controller.ts | 2 +- src/controllers/keycloak-controller.ts | 2 +- src/controllers/permission-controller.ts | 8 ++++---- src/controllers/user-controller.ts | 4 ++-- 12 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/controllers/address-controller.ts b/src/controllers/address-controller.ts index c836829..ba123bf 100644 --- a/src/controllers/address-controller.ts +++ b/src/controllers/address-controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Path, Route, Tags } from "tsoa"; import prisma from "../db"; -@Route("api/address") +@Route("api/v1/address") @Tags("Address") export class AddressController extends Controller { @Get("province") diff --git a/src/controllers/branch-contact-controller.ts b/src/controllers/branch-contact-controller.ts index b71aea5..473fd51 100644 --- a/src/controllers/branch-contact-controller.ts +++ b/src/controllers/branch-contact-controller.ts @@ -26,7 +26,7 @@ type BranchContactUpdate = { telephoneNo?: string; }; -@Route("api/branch/{branchId}/contact") +@Route("api/v1/branch/{branchId}/contact") @Tags("Branch Contact") @Security("keycloak") export class BranchContactController extends Controller { diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index f772de3..889c5a1 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -78,7 +78,7 @@ function branchImageLoc(id: string) { return `branch/branch-img-${id}`; } -@Route("api/branch") +@Route("api/v1/branch") @Tags("Branch") @Security("keycloak") export class BranchController extends Controller { diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index 7046ad6..a12c546 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -51,7 +51,7 @@ async function userBranchCodeGen(branch: Branch, user: User[]) { ); } -@Route("api/branch/{branchId}/user") +@Route("api/v1/branch/{branchId}/user") @Tags("Branch User") @Security("keycloak") export class BranchUserController extends Controller { @@ -178,7 +178,7 @@ export class BranchUserController extends Controller { type UserBranchBody = { branch: string[] }; -@Route("api/user/{userId}/branch") +@Route("api/v1/user/{userId}/branch") @Tags("Branch User") @Security("keycloak") export class UserBranchController extends Controller { diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index ff24201..2a2371b 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -99,7 +99,7 @@ export type CustomerBranchUpdate = { provinceId?: string | null; }; -@Route("api/customer-branch") +@Route("api/v1/customer-branch") @Tags("Customer Branch") @Security("keycloak") export class CustomerBranchController extends Controller { diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 2721e52..e71485c 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -48,7 +48,7 @@ function imageLocation(id: string) { return `customer/img-${id}`; } -@Route("api/customer") +@Route("api/v1/customer") @Tags("Customer") @Security("keycloak") export class CustomerController extends Controller { diff --git a/src/controllers/employee-checkup-controller.ts b/src/controllers/employee-checkup-controller.ts index de683d8..eff4b5c 100644 --- a/src/controllers/employee-checkup-controller.ts +++ b/src/controllers/employee-checkup-controller.ts @@ -44,7 +44,7 @@ type EmployeeCheckupEdit = { coverageExpireDate?: Date; }; -@Route("api/employee/{employeeId}/checkup") +@Route("api/v1/employee/{employeeId}/checkup") @Tags("Employee Checkup") @Security("keycloak") export class EmployeeCheckupController extends Controller { diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index aeff13e..fbb6aa0 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -90,7 +90,7 @@ type EmployeeUpdate = { provinceId?: string | null; }; -@Route("api/employee") +@Route("api/v1/employee") @Tags("Employee") @Security("keycloak") export class EmployeeController extends Controller { diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index 4445c17..e134ec5 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -33,7 +33,7 @@ type EmployeeOtherInfoUpdate = { birthPlace: string; }; -@Route("api/employee/{employeeId}/other-info") +@Route("api/v1/employee/{employeeId}/other-info") @Tags("Employee Other Info") @Security("keycloak") export class EmployeeOtherInfo extends Controller { diff --git a/src/controllers/keycloak-controller.ts b/src/controllers/keycloak-controller.ts index 5ebb09f..69ed2de 100644 --- a/src/controllers/keycloak-controller.ts +++ b/src/controllers/keycloak-controller.ts @@ -8,7 +8,7 @@ import { removeUserRoles, } from "../services/keycloak"; -@Route("api/keycloak") +@Route("api/v1/keycloak") @Tags("Single-Sign On") @Security("keycloak") export class KeycloakController extends Controller { diff --git a/src/controllers/permission-controller.ts b/src/controllers/permission-controller.ts index 37d2af7..0ea14e0 100644 --- a/src/controllers/permission-controller.ts +++ b/src/controllers/permission-controller.ts @@ -19,7 +19,7 @@ type MenuEdit = { url: string; }; -@Route("v1/permission/menu") +@Route("api/v1/permission/menu") @Tags("Permission") @Security("keycloak") export class MenuController extends Controller { @@ -93,7 +93,7 @@ type RoleMenuPermissionEdit = { permission?: string; }; -@Route("v1/permission/menu/{menuId}/role") +@Route("api/v1/permission/menu/{menuId}/role") @Tags("Permission") @Security("keycloak") export class RoleMenuController extends Controller { @@ -171,7 +171,7 @@ type MenuComponentEdit = { menuId?: string; }; -@Route("v1/permission/menu-component") +@Route("api/v1/permission/menu-component") @Tags("Permission") @Security("keycloak") export class MenuComponentController extends Controller { @@ -263,7 +263,7 @@ type RoleMenuComponentPermissionEdit = { permission?: string; }; -@Route("v1/permission/menu-component/{menuComponentId}/role") +@Route("api/v1/permission/menu-component/{menuComponentId}/role") @Tags("Permission") @Security("keycloak") export class RoleMenuComponentController extends Controller { diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index d65a21c..05aaf79 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -119,7 +119,7 @@ function imageLocation(id: string) { return `user/profile-img-${id}`; } -@Route("api/user") +@Route("api/v1/user") @Tags("User") @Security("keycloak") export class UserController extends Controller { @@ -507,7 +507,7 @@ function attachmentLocation(uid: string) { return `user-attachment/${uid}`; } -@Route("api/user/{userId}/attachment") +@Route("api/v1/user/{userId}/attachment") @Tags("User") @Security("keycloak") export class UserAttachmentController extends Controller { From a6910de55518a28d9368e3c3c78a8437c2045587 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:47:13 +0700 Subject: [PATCH 019/157] feat: employee code gen --- src/controllers/employee-controller.ts | 114 +++++++++++++++---------- 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index fbb6aa0..bcb12a2 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -163,57 +163,77 @@ export class EmployeeController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: EmployeeCreate) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerBranchId) { - const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customerBranch.findFirst({ where: { id: body.customerBranchId || undefined } }), - ]); - if (body.provinceId && !province) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerBranchId && !customerBranch) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer Branch cannot be found.", - "missing_or_invalid_parameter", - ); - } + const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customerBranch.findFirst({ + where: { id: body.customerBranchId || undefined }, + include: { + customer: true, + }, + }), + ]); + if (body.provinceId && !province) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.districtId && !district) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.subDistrictId && !subDistrict) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "missing_or_invalid_parameter", + ); + if (!customerBranch) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer Branch cannot be found.", + "missing_or_invalid_parameter", + ); const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body; - const record = await prisma.employee.create({ - include: { - province: true, - district: true, - subDistrict: true, + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + }, + create: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await prisma.employee.create({ + include: { + province: true, + district: true, + subDistrict: true, + }, + data: { + ...rest, + code: `${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, + province: { connect: provinceId ? { id: provinceId } : undefined }, + district: { connect: districtId ? { id: districtId } : undefined }, + subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, + customerBranch: { connect: { id: customerBranchId } }, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); }, - data: { - ...rest, - province: { connect: provinceId ? { id: provinceId } : undefined }, - district: { connect: districtId ? { id: districtId } : undefined }, - subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, - customerBranch: { connect: { id: customerBranchId } }, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); await prisma.customerBranch.updateMany({ where: { id: customerBranchId, status: Status.CREATED }, From 25f6d94fae72c88c3070a35df2a55e155b19b147 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:35:10 +0700 Subject: [PATCH 020/157] fix: wrong object delete --- src/controllers/user-controller.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 05aaf79..7ebc22f 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -484,9 +484,7 @@ export class UserController extends Controller { stream.on("error", () => reject(new Error("MinIO error."))); }).then((list) => { list.map(async (v) => { - await minio.removeObject(MINIO_BUCKET, `${attachmentLocation(userId)}/${v}`, { - forceDelete: true, - }); + await minio.removeObject(MINIO_BUCKET, v, { forceDelete: true }); }); }); From 359e0ad31421b5bbe9d8246b24ec1b20f5618b97 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 16:50:44 +0700 Subject: [PATCH 021/157] feat: product group endpoints --- src/controllers/product/group-controller.ts | 108 ++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/controllers/product/group-controller.ts diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts new file mode 100644 index 0000000..d480c22 --- /dev/null +++ b/src/controllers/product/group-controller.ts @@ -0,0 +1,108 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type ProductGroupCreate = { + code: string; + name: string; + detail: string; + remark: string; +}; + +type ProductGroupUpdate = { + code?: string; + name?: string; + detail?: string; + remark?: string; +}; + +@Route("api/product-group") +@Tags("Product Group") +@Security("keycloak") +export class ProductGroup extends Controller { + @Get() + async getProductGroup(@Query() query: string = "") { + const where = { + OR: [{ name: { contains: query } }, { detail: { contains: query } }], + } satisfies Prisma.ProductGroupWhereInput; + const result = prisma.productGroup.findMany({ orderBy: { createdAt: "asc" }, where }); + return result; + } + + @Get("{groupId}") + async getProductGroupById(@Path() groupId: string) { + const record = await prisma.productGroup.findFirst({ + where: { id: groupId }, + }); + + if (!record) + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + + return record; + } + + @Post() + async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { + const record = await prisma.productGroup.create({ + data: { + ...body, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{groupId}") + async editProductGroup( + @Request() req: RequestWithUser, + @Body() body: ProductGroupUpdate, + @Path() groupId: string, + ) { + if (!(await prisma.work.findUnique({ where: { id: groupId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + } + + const record = await prisma.work.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: groupId }, + }); + + return record; + } + + @Delete("{groupId}") + async deleteProductGroup(@Path() groupId: string) { + const record = await prisma.productGroup.findFirst({ where: { id: groupId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product group is in used.", "data_in_used"); + } + + return await prisma.productGroup.delete({ where: { id: groupId } }); + } +} From 818dd044b69dff6f2bc681e646ab39e84b0fd26e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 6 Jun 2024 17:09:47 +0700 Subject: [PATCH 022/157] feat: scope customer branch by customer id --- src/controllers/customer-branch-controller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 2a2371b..27aaae0 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -106,6 +106,7 @@ export class CustomerBranchController extends Controller { @Get() async list( @Query() zipCode?: string, + @Query() customerId?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, @@ -116,7 +117,8 @@ export class CustomerBranchController extends Controller { { name: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, ], - } satisfies Prisma.BranchWhereInput; + AND: { customerId }, + } satisfies Prisma.CustomerBranchWhereInput; const [result, total] = await prisma.$transaction([ prisma.customerBranch.findMany({ From 7cfc49eae045541dcac8598c2646fd95c2cd35b4 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:09:49 +0700 Subject: [PATCH 023/157] feat: count customer by type --- src/controllers/customer-controller.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index e71485c..cb18ca5 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -52,6 +52,25 @@ function imageLocation(id: string) { @Tags("Customer") @Security("keycloak") export class CustomerController extends Controller { + @Get("type-stats") + async stat() { + const list = await prisma.customer.groupBy({ + by: "customerType", + _count: true, + }); + + return list.reduce>( + (a, c) => { + a[c.customerType] = c._count; + return a; + }, + { + CORP: 0, + PERS: 0, + }, + ); + } + @Get() async list( @Query() query: string = "", From fea4bd874fd8a1d1f78aec07fc013ca123d8281f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 10:44:40 +0700 Subject: [PATCH 024/157] feat: customer branch attachment --- src/controllers/customer-branch-controller.ts | 127 +++++++++++++++++- src/controllers/customer-controller.ts | 25 +++- 2 files changed, 148 insertions(+), 4 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 27aaae0..6e90c2e 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -29,6 +29,10 @@ function imageLocation(id: string) { return `employee/profile-img-${id}`; } +function attachmentLocation(customerId: string, branchId: string) { + return `customer/${customerId}/branch/${branchId}`; +} + export type CustomerBranchCreate = { customerId: string; @@ -360,7 +364,9 @@ export class CustomerBranchController extends Controller { @Delete("{branchId}") async delete(@Path() branchId: string) { - const record = await prisma.customerBranch.findFirst({ where: { id: branchId } }); + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); if (!record) { throw new HttpError( @@ -374,6 +380,123 @@ export class CustomerBranchController extends Controller { throw new HttpError(HttpStatus.FORBIDDEN, "Customer branch is in used.", "data_in_used"); } - return await prisma.customerBranch.delete({ where: { id: branchId } }); + return await prisma.customerBranch.delete({ where: { id: branchId } }).then((v) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/`, + ); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + return v; + }); + } +} + +@Route("api/v1/customer-branch/{branchId}/attachment") +@Tags("Customer Branch") +@Security("keycloak") +export class CustomerAttachmentController extends Controller { + @Get() + async listAttachment(@Path() branchId: string) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "data_not_found", + ); + } + + const list = await new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/`, + ); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }); + + return await Promise.all( + list.map(async (v) => ({ + name: v.split("/").at(-1) as string, + url: await minio.presignedGetObject(MINIO_BUCKET, v, 12 * 60 * 60), + })), + ); + } + + @Post() + async addAttachment(@Path() branchId: string, @Body() payload: { file: string[] }) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "data_not_found", + ); + } + + return await Promise.all( + payload.file.map(async (v) => ({ + name: v, + url: await minio.presignedGetObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + ), + uploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + 12 * 60 * 60, + ), + })), + ); + } + + @Delete() + async deleteAttachment(@Path() branchId: string, @Body() payload: { file: string[] }) { + const record = await prisma.customerBranch.findFirst({ + where: { id: branchId }, + }); + + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Customer branch cannot be found.", + "data_not_found", + ); + } + + await Promise.all( + payload.file.map(async (v) => { + await minio.removeObject( + MINIO_BUCKET, + `${attachmentLocation(record.customerId, branchId)}/${v}`, + { + forceDelete: true, + }, + ); + }), + ); } } diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index cb18ca5..931cf4e 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -45,7 +45,11 @@ export type CustomerUpdate = { }; function imageLocation(id: string) { - return `customer/img-${id}`; + return `customer/${id}/profile-image`; +} + +function attachmentLocation(customerId: string, branchId: string) { + return `customer/${customerId}/branch/${branchId}`; } @Route("api/v1/customer") @@ -357,6 +361,23 @@ export class CustomerController extends Controller { throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "data_in_used"); } - return await prisma.customer.delete({ where: { id: customerId } }); + return await prisma.customer.delete({ where: { id: customerId } }).then((v) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${customerId}`); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + return v; + }); } } From e5dcc867470fb28fca7e6c76c2e0083f403bf3a0 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:14:34 +0700 Subject: [PATCH 025/157] feat: update customer branch --- src/controllers/customer-controller.ts | 103 +++++++++++++++++-------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 931cf4e..047a711 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -18,7 +18,7 @@ import prisma from "../db"; import minio from "../services/minio"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -import { CustomerBranchCreate, CustomerBranchUpdate } from "./customer-branch-controller"; +import { CustomerBranchCreate } from "./customer-branch-controller"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); @@ -41,17 +41,13 @@ export type CustomerUpdate = { customerName?: string; customerNameEN?: string; taxNo?: string | null; - customerBranch?: (Omit & { id: string })[]; + customerBranch?: (Omit & { id?: string })[]; }; function imageLocation(id: string) { return `customer/${id}/profile-image`; } -function attachmentLocation(customerId: string, branchId: string) { - return `customer/${customerId}/branch/${branchId}`; -} - @Route("api/v1/customer") @Tags("Customer") @Security("keycloak") @@ -306,35 +302,78 @@ export class CustomerController extends Controller { const { customerBranch, ...payload } = body; - const record = await prisma.customer.update({ - include: { - branch: { - include: { - province: true, - district: true, - subDistrict: true, - }, - }, - }, - where: { id: customerId }, - data: { - ...payload, - branch: - (customerBranch && { - deleteMany: { - id: { notIn: customerBranch.map((v) => v.id) || [] }, - }, - updateMany: - customerBranch.map((v) => ({ - where: { id: v.id }, - data: { ...v, updateBy: req.user.name }, - })) || [], - }) || - undefined, - updateBy: req.user.name, + const relation = await prisma.customerBranch.findMany({ + where: { + customerId, }, }); + const record = await prisma.customer + .update({ + include: { + branch: { + include: { + province: true, + district: true, + subDistrict: true, + }, + }, + }, + where: { id: customerId }, + data: { + ...payload, + branch: + (customerBranch && { + deleteMany: { + id: { + notIn: customerBranch.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: customerBranch.map((v, i) => ({ + where: { id: v.id || "" }, + create: { + ...v, + branchNo: `${i + 1}`, + createdBy: req.user.name, + updateBy: req.user.name, + id: undefined, + }, + update: { + ...v, + branchNo: `${i + 1}`, + updateBy: req.user.name, + }, + })), + }) || + undefined, + updateBy: req.user.name, + }, + }) + .then((v) => { + if (customerBranch) { + relation + .filter((a) => !customerBranch?.find((b) => b.id === a.id)) + .forEach((deleted) => { + new Promise((resolve, reject) => { + const item: string[] = []; + + const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${deleted.id}`); + + stream.on("data", (v) => v && v.name && item.push(v.name)); + stream.on("end", () => resolve(item)); + stream.on("error", () => reject(new Error("MinIO error."))); + }).then((list) => { + list.map(async (v) => { + await minio.removeObject(MINIO_BUCKET, v, { + forceDelete: true, + }); + }); + }); + }); + } + return v; + }); + return Object.assign(record, { imageUrl: await minio.presignedGetObject( MINIO_BUCKET, From 2c134aa68aa8c430498512613a1e32e65535dede Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:34:04 +0700 Subject: [PATCH 026/157] fix: validate error --- src/controllers/customer-controller.ts | 69 ++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 047a711..9dbf98d 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -18,7 +18,6 @@ import prisma from "../db"; import minio from "../services/minio"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -import { CustomerBranchCreate } from "./customer-branch-controller"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); @@ -32,7 +31,38 @@ export type CustomerCreate = { customerName: string; customerNameEN: string; taxNo?: string | null; - customerBranch?: Omit[]; + customerBranch?: { + status?: Status; + + legalPersonNo: string; + + taxNo: string | null; + name: string; + nameEN: string; + addressEN: string; + address: string; + zipCode: string; + email: string; + telephoneNo: string; + + registerName: string; + registerDate: Date; + authorizedCapital: string; + + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: string; + wageDate: string; + + subDistrictId?: string | null; + districtId?: string | null; + provinceId?: string | null; + }[]; }; export type CustomerUpdate = { @@ -41,7 +71,40 @@ export type CustomerUpdate = { customerName?: string; customerNameEN?: string; taxNo?: string | null; - customerBranch?: (Omit & { id?: string })[]; + customerBranch?: { + id?: string; + + status?: Status; + + legalPersonNo: string; + + taxNo: string | null; + name: string; + nameEN: string; + addressEN: string; + address: string; + zipCode: string; + email: string; + telephoneNo: string; + + registerName: string; + registerDate: Date; + authorizedCapital: string; + + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: string; + wageDate: string; + + subDistrictId?: string | null; + districtId?: string | null; + provinceId?: string | null; + }[]; }; function imageLocation(id: string) { From 23f52b137d9352695f56dec1c2de949f9c52467d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:54:02 +0700 Subject: [PATCH 027/157] fix: wrong data type --- .../20240607065019_update_data_type/migration.sql | 15 +++++++++++++++ prisma/schema.prisma | 6 +++--- src/controllers/customer-branch-controller.ts | 10 +++++----- src/controllers/customer-controller.ts | 14 +++++++------- 4 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 prisma/migrations/20240607065019_update_data_type/migration.sql diff --git a/prisma/migrations/20240607065019_update_data_type/migration.sql b/prisma/migrations/20240607065019_update_data_type/migration.sql new file mode 100644 index 0000000..b72dc89 --- /dev/null +++ b/prisma/migrations/20240607065019_update_data_type/migration.sql @@ -0,0 +1,15 @@ +/* + Warnings: + + - Changed the type of `branchNo` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + - Changed the type of `payDate` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + - Changed the type of `wageDate` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- AlterTable +ALTER TABLE "CustomerBranch" DROP COLUMN "branchNo", +ADD COLUMN "branchNo" INTEGER NOT NULL, +DROP COLUMN "payDate", +ADD COLUMN "payDate" TIMESTAMP(3) NOT NULL, +DROP COLUMN "wageDate", +ADD COLUMN "wageDate" TIMESTAMP(3) NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9d562fa..d00c514 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -349,7 +349,7 @@ model Customer { model CustomerBranch { id String @id @default(uuid()) - branchNo String + branchNo Int legalPersonNo String name String @@ -387,8 +387,8 @@ model CustomerBranch { jobPositionEN String jobDescription String saleEmployee String - payDate String - wageDate String + payDate DateTime + wageDate DateTime status Status @default(CREATED) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 6e90c2e..d9feddc 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -60,8 +60,8 @@ export type CustomerBranchCreate = { jobPositionEN: string; jobDescription: string; saleEmployee: string; - payDate: string; - wageDate: string; + payDate: Date; + wageDate: Date; subDistrictId?: string | null; districtId?: string | null; @@ -95,8 +95,8 @@ export type CustomerBranchUpdate = { jobPositionEN?: string; jobDescription?: string; saleEmployee?: string; - payDate?: string; - wageDate?: string; + payDate?: Date; + wageDate?: Date; subDistrictId?: string | null; districtId?: string | null; @@ -262,7 +262,7 @@ export class CustomerBranchController extends Controller { }, data: { ...rest, - branchNo: `${count + 1}`, + branchNo: count + 1, customer: { connect: { id: customerId } }, province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 9dbf98d..d227583 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -56,8 +56,8 @@ export type CustomerCreate = { jobPositionEN: string; jobDescription: string; saleEmployee: string; - payDate: string; - wageDate: string; + payDate: Date; + wageDate: Date; subDistrictId?: string | null; districtId?: string | null; @@ -98,8 +98,8 @@ export type CustomerUpdate = { jobPositionEN: string; jobDescription: string; saleEmployee: string; - payDate: string; - wageDate: string; + payDate: Date; + wageDate: Date; subDistrictId?: string | null; districtId?: string | null; @@ -281,7 +281,7 @@ export class CustomerController extends Controller { data: customerBranch?.map((v, i) => ({ ...v, - branchNo: `${i + 1}`, + branchNo: i + 1, createdBy: req.user.name, updateBy: req.user.name, })) || [], @@ -396,14 +396,14 @@ export class CustomerController extends Controller { where: { id: v.id || "" }, create: { ...v, - branchNo: `${i + 1}`, + branchNo: i + 1, createdBy: req.user.name, updateBy: req.user.name, id: undefined, }, update: { ...v, - branchNo: `${i + 1}`, + branchNo: i + 1, updateBy: req.user.name, }, })), From c3f8673ac852b984b970c49b46747534e720e6d5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:02:31 +0700 Subject: [PATCH 028/157] fix: wrong field --- .../20240607070114_fix_wrong_field/migration.sql | 10 ++++++++++ prisma/schema.prisma | 2 +- src/controllers/customer-branch-controller.ts | 4 ++-- src/controllers/customer-controller.ts | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 prisma/migrations/20240607070114_fix_wrong_field/migration.sql diff --git a/prisma/migrations/20240607070114_fix_wrong_field/migration.sql b/prisma/migrations/20240607070114_fix_wrong_field/migration.sql new file mode 100644 index 0000000..a5494e8 --- /dev/null +++ b/prisma/migrations/20240607070114_fix_wrong_field/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - You are about to drop the column `wageDate` on the `CustomerBranch` table. All the data in the column will be lost. + - Added the required column `wageRate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "CustomerBranch" DROP COLUMN "wageDate", +ADD COLUMN "wageRate" INTEGER NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index d00c514..a8d0dd9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -388,7 +388,7 @@ model CustomerBranch { jobDescription String saleEmployee String payDate DateTime - wageDate DateTime + wageRate Int status Status @default(CREATED) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index d9feddc..032ee8f 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -61,7 +61,7 @@ export type CustomerBranchCreate = { jobDescription: string; saleEmployee: string; payDate: Date; - wageDate: Date; + wageRate: number; subDistrictId?: string | null; districtId?: string | null; @@ -96,7 +96,7 @@ export type CustomerBranchUpdate = { jobDescription?: string; saleEmployee?: string; payDate?: Date; - wageDate?: Date; + wageDate?: number; subDistrictId?: string | null; districtId?: string | null; diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index d227583..9319525 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -57,7 +57,7 @@ export type CustomerCreate = { jobDescription: string; saleEmployee: string; payDate: Date; - wageDate: Date; + wageRate: number; subDistrictId?: string | null; districtId?: string | null; @@ -99,7 +99,7 @@ export type CustomerUpdate = { jobDescription: string; saleEmployee: string; payDate: Date; - wageDate: Date; + wageRate: number; subDistrictId?: string | null; districtId?: string | null; From 23f05503c5bc71b92ac54897398f6605b6aea463 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:34:34 +0700 Subject: [PATCH 029/157] feat: must not delete if status is not CREATED --- src/controllers/customer-controller.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 9319525..03dfa38 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -371,6 +371,17 @@ export class CustomerController extends Controller { }, }); + if ( + customerBranch && + relation.find((a) => !customerBranch.find((b) => a.id === b.id) && a.status !== "CREATED") + ) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "One or more branch cannot be delete and is missing.", + "missing_or_invalid_parameter", + ); + } + const record = await prisma.customer .update({ include: { @@ -391,6 +402,7 @@ export class CustomerController extends Controller { id: { notIn: customerBranch.map((v) => v.id).filter((v): v is string => !!v) || [], }, + status: Status.CREATED, }, upsert: customerBranch.map((v, i) => ({ where: { id: v.id || "" }, @@ -415,7 +427,7 @@ export class CustomerController extends Controller { .then((v) => { if (customerBranch) { relation - .filter((a) => !customerBranch?.find((b) => b.id === a.id)) + .filter((a) => !customerBranch.find((b) => b.id === a.id)) .forEach((deleted) => { new Promise((resolve, reject) => { const item: string[] = []; From 4b7acf9a4341aaa5268c684b50d55ccc649e55af Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:49:11 +0700 Subject: [PATCH 030/157] feat: employee work endpoints --- src/controllers/employee-work-controller.ts | 122 ++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 src/controllers/employee-work-controller.ts diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts new file mode 100644 index 0000000..c3cde09 --- /dev/null +++ b/src/controllers/employee-work-controller.ts @@ -0,0 +1,122 @@ +import { + Body, + Controller, + Delete, + Get, + Path, + Post, + Put, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { RequestWithUser } from "../interfaces/user"; +import prisma from "../db"; +import HttpStatus from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; + +type EmployeeWorkCreate = { + ownerName: string; + positionName: string; + jobType: string; + workplace: string; + workPermitNo: string; + workPermitIssuDate: Date; + workPermitExpireDate: Date; + workEndDate: Date; +}; + +type EmployeeWorkUpdate = { + ownerName?: string; + positionName?: string; + jobType?: string; + workplace?: string; + workPermitNo?: string; + workPermitIssuDate?: Date; + workPermitExpireDate?: Date; + workEndDate?: Date; +}; + +@Route("api/v1/employee/{employeeId}/work") +@Tags("Employee Work") +@Security("keycloak") +export class EmployeeWorkController extends Controller { + @Get() + async list(@Path() employeeId: string) { + return prisma.employeeWork.findMany({ + orderBy: { createdAt: "asc" }, + where: { employeeId }, + }); + } + + @Get("{workId}") + async getById(@Path() employeeId: string, @Path() workId: string) { + const record = await prisma.employeeWork.findFirst({ + where: { id: workId, employeeId }, + }); + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + } + return record; + } + + @Post() + async create( + @Request() req: RequestWithUser, + @Path() employeeId: string, + @Body() body: EmployeeWorkCreate, + ) { + if (!(await prisma.employee.findUnique({ where: { id: employeeId } }))) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Employee cannot be found.", + "missing_or_invalid_parameter", + ); + + const record = await prisma.employeeWork.create({ + data: { + ...body, + employee: { connect: { id: employeeId } }, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{workId}") + async editById( + @Request() req: RequestWithUser, + @Path() employeeId: string, + @Path() workId: string, + @Body() body: EmployeeWorkUpdate, + ) { + if (!(await prisma.employeeWork.findUnique({ where: { id: workId, employeeId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + } + + const record = await prisma.employeeWork.update({ + where: { id: workId, employeeId }, + data: { ...body, createdBy: req.user.name, updateBy: req.user.name }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Delete("{workId}") + async deleteById(@Path() employeeId: string, @Path() workId: string) { + const record = await prisma.employeeWork.findFirst({ where: { id: workId, employeeId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + } + + return await prisma.employeeWork.delete({ where: { id: workId, employeeId } }); + } +} From d0b59a40889212883108fc682839ac7750909a51 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Sun, 9 Jun 2024 11:14:26 +0700 Subject: [PATCH 031/157] feat: product type endpoints --- src/controllers/product/type-controller.ts | 108 +++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 src/controllers/product/type-controller.ts diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts new file mode 100644 index 0000000..14a7e6b --- /dev/null +++ b/src/controllers/product/type-controller.ts @@ -0,0 +1,108 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type ProductTypeCreate = { + code: string; + name: string; + detail: string; + remark: string; +}; + +type ProductTypeUpdate = { + code?: string; + name?: string; + detail?: string; + remark?: string; +}; + +@Route("api/product-type") +@Tags("Product Type") +@Security("keycloak") +export class ProductType extends Controller { + @Get() + async getProductType(@Query() query: string = "") { + const where = { + OR: [{ name: { contains: query } }, { detail: { contains: query } }], + } satisfies Prisma.ProductTypeWhereInput; + const result = prisma.productType.findMany({ orderBy: { createdAt: "asc" }, where }); + return result; + } + + @Get("{typeId}") + async getProductTypeById(@Path() typeId: string) { + const record = await prisma.productType.findFirst({ + where: { id: typeId }, + }); + + if (!record) + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + + return record; + } + + @Post() + async createProductType(@Request() req: RequestWithUser, @Body() body: ProductTypeCreate) { + const record = await prisma.productType.create({ + data: { + ...body, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{typeId}") + async editProductType( + @Request() req: RequestWithUser, + @Body() body: ProductTypeUpdate, + @Path() typeId: string, + ) { + if (!(await prisma.productType.findUnique({ where: { id: typeId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + } + + const record = await prisma.work.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: typeId }, + }); + + return record; + } + + @Delete("{typeId}") + async deleteProductType(@Path() typeId: string) { + const record = await prisma.productType.findFirst({ where: { id: typeId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product type is in used.", "data_in_used"); + } + + return await prisma.productType.delete({ where: { id: typeId } }); + } +} From dcfa543479864c72c61d8cccbc7b945fb8766479 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Sun, 9 Jun 2024 11:18:02 +0700 Subject: [PATCH 032/157] feat: minio util func --- src/services/minio.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/services/minio.ts b/src/services/minio.ts index 5f68d91..36d2d11 100644 --- a/src/services/minio.ts +++ b/src/services/minio.ts @@ -9,3 +9,15 @@ const minio = new Client({ }); export default minio; + +export async function presignedGetObjectIfExist(bucket: string, obj: string, exp?: number) { + if ( + await minio.statObject(bucket, obj).catch((e) => { + if (e.code === "NotFound") return false; + throw new Error("Object storage error."); + }) + ) { + return await minio.presignedGetObject(bucket, obj, exp); + } + return null; +} From 43b97be4f1815a7cbc2ba3c3f614910ca2eea355 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 09:41:24 +0700 Subject: [PATCH 033/157] feat; add query string to include customer on get list --- src/controllers/customer-branch-controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 032ee8f..87df4f6 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -111,6 +111,7 @@ export class CustomerBranchController extends Controller { async list( @Query() zipCode?: string, @Query() customerId?: string, + @Query() includeCustomer?: boolean, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, @@ -128,6 +129,7 @@ export class CustomerBranchController extends Controller { prisma.customerBranch.findMany({ orderBy: { createdAt: "asc" }, include: { + customer: includeCustomer, province: true, district: true, subDistrict: true, From 5492f9533af9d6498a79006bd862b683365d6e91 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:03:40 +0700 Subject: [PATCH 034/157] feat: return null if no image exist --- src/controllers/user-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 7ebc22f..2e0951a 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -15,7 +15,7 @@ import { import { Prisma, Status, UserType } from "@prisma/client"; import prisma from "../db"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; import { RequestWithUser } from "../interfaces/user"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; @@ -185,7 +185,7 @@ export class UserController extends Controller { result.map(async (v) => ({ ...v, branch: includeBranch ? v.branch.map((a) => a.branch) : undefined, - profileImageUrl: await minio.presignedGetObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60, From 1dc0db7987e9aa012be7ef6eb4c235dbd9d64f46 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:12:43 +0700 Subject: [PATCH 035/157] feat: return null if no image exist --- src/controllers/customer-controller.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 03dfa38..86a6a9b 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -15,7 +15,7 @@ import { } from "tsoa"; import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; @@ -170,7 +170,11 @@ export class CustomerController extends Controller { result: await Promise.all( result.map(async (v) => ({ ...v, - imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60), + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), })), ), page, @@ -450,7 +454,7 @@ export class CustomerController extends Controller { }); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From 5f20d8b05219e72e9332aa85b1df79f06536e2a6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 11:14:21 +0700 Subject: [PATCH 036/157] feat: return null if no image exist --- src/controllers/employee-controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index bcb12a2..f1705de 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -17,7 +17,7 @@ import { RequestWithUser } from "../interfaces/user"; import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -import minio from "../services/minio"; +import minio, { presignedGetObjectIfExist } from "../services/minio"; if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); @@ -130,7 +130,7 @@ export class EmployeeController extends Controller { result: await Promise.all( result.map(async (v) => ({ ...v, - profileImageUrl: await minio.presignedGetObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60, @@ -243,7 +243,7 @@ export class EmployeeController extends Controller { this.setStatus(HttpStatus.CREATED); return Object.assign(record, { - profileImageUrl: await minio.presignedPutObject( + profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From a6d8f1c7f6321d45af0c2c4465e51e009a859e41 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:11:29 +0700 Subject: [PATCH 037/157] feat: employee with relation on create / update --- src/controllers/employee-controller.ts | 204 ++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index f1705de..d5fd5ce 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -58,6 +58,38 @@ type EmployeeCreate = { subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; + + employeeWork?: { + ownerName: string; + positionName: string; + jobType: string; + workplace: string; + workPermitNo: string; + workPermitIssuDate: Date; + workPermitExpireDate: Date; + workEndDate: Date; + }[]; + + employeeCheckup?: { + checkupType: string; + checkupResult: string; + + provinceId?: string | null; + + hospitalName: string; + remark: string; + medicalBenefitScheme: string; + insuranceCompany: string; + coverageStartDate: Date; + coverageExpireDate: Date; + }[]; + + employeeOtherInfo: { + citizenId: string; + fatherFullName: string; + motherFullName: string; + birthPlace: string; + }; }; type EmployeeUpdate = { @@ -88,6 +120,40 @@ type EmployeeUpdate = { subDistrictId?: string | null; districtId?: string | null; provinceId?: string | null; + + employeeWork?: { + id?: string; + ownerName: string; + positionName: string; + jobType: string; + workplace: string; + workPermitNo: string; + workPermitIssuDate: Date; + workPermitExpireDate: Date; + workEndDate: Date; + }[]; + + employeeCheckup?: { + id?: string; + checkupType: string; + checkupResult: string; + + provinceId?: string | null; + + hospitalName: string; + remark: string; + medicalBenefitScheme: string; + insuranceCompany: string; + coverageStartDate: Date; + coverageExpireDate: Date; + }[]; + + employeeOtherInfo: { + citizenId: string; + fatherFullName: string; + motherFullName: string; + birthPlace: string; + }; }; @Route("api/v1/employee") @@ -199,7 +265,34 @@ export class EmployeeController extends Controller { "missing_or_invalid_parameter", ); - const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body; + const { + provinceId, + districtId, + subDistrictId, + customerBranchId, + employeeWork, + employeeCheckup, + employeeOtherInfo, + ...rest + } = body; + + const listProvinceId = employeeCheckup?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + + if (listProvinceId) { + const [listProvince] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: listProvinceId } } }), + ]); + if (listProvince.length !== listProvinceId.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "missing_or_invalid_parameter", + ); + } + } const record = await prisma.$transaction( async (tx) => { @@ -219,10 +312,30 @@ export class EmployeeController extends Controller { province: true, district: true, subDistrict: true, + employeeOtherInfo: true, + employeeCheckup: { + include: { + province: true, + }, + }, + employeeWork: true, }, data: { ...rest, code: `${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, + employeeWork: { + createMany: { + data: employeeWork || [], + }, + }, + employeeCheckup: { + createMany: { + data: employeeCheckup || [], + }, + }, + employeeOtherInfo: { + create: employeeOtherInfo, + }, province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, @@ -295,7 +408,34 @@ export class EmployeeController extends Controller { ); } - const { provinceId, districtId, subDistrictId, customerBranchId, ...rest } = body; + const { + provinceId, + districtId, + subDistrictId, + customerBranchId, + employeeWork, + employeeCheckup, + employeeOtherInfo, + ...rest + } = body; + + const listProvinceId = employeeCheckup?.reduce((acc, cur) => { + if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + return acc; + }, []); + + if (listProvinceId) { + const [listProvince] = await prisma.$transaction([ + prisma.province.findMany({ where: { id: { in: listProvinceId } } }), + ]); + if (listProvince.length !== listProvinceId.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some province cannot be found.", + "missing_or_invalid_parameter", + ); + } + } const record = await prisma.employee.update({ where: { id: employeeId }, @@ -303,10 +443,68 @@ export class EmployeeController extends Controller { province: true, district: true, subDistrict: true, + employeeOtherInfo: true, + employeeCheckup: { + include: { + province: true, + }, + }, + employeeWork: true, }, data: { ...rest, customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, + employeeWork: employeeWork + ? { + deleteMany: { + id: { + notIn: employeeWork.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeWork.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + createdBy: req.user.name, + updateBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updateBy: req.user.name, + }, + })), + } + : undefined, + + employeeCheckup: employeeCheckup + ? { + deleteMany: { + id: { + notIn: employeeCheckup.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeCheckup.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + createdBy: req.user.name, + updateBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updateBy: req.user.name, + }, + })), + } + : undefined, + employeeOtherInfo: employeeOtherInfo + ? { + deleteMany: {}, + create: employeeOtherInfo, + } + : undefined, province: { connect: provinceId ? { id: provinceId } : undefined, disconnect: provinceId === null || undefined, @@ -340,7 +538,7 @@ export class EmployeeController extends Controller { if (record.status !== Status.CREATED) { throw new HttpError( HttpStatus.FORBIDDEN, - "Emplyee is in used.", + "Employee is in used.", "missing_or_invalid_parameter", ); } From 6750ba8c34860f63ba80f5939b5c333dec041958 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:12:26 +0700 Subject: [PATCH 038/157] feat: return null if no image exist --- src/controllers/customer-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 86a6a9b..c5a8510 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -302,7 +302,7 @@ export class CustomerController extends Controller { this.setStatus(HttpStatus.CREATED); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From 629805b6f1bc1cc9382a800d5b1f5b78964a4eb4 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:57:24 +0700 Subject: [PATCH 039/157] feat: return null if no image exist --- src/controllers/customer-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index c5a8510..ebcd031 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -200,7 +200,7 @@ export class CustomerController extends Controller { if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From a8d0d7f45c9b07f12417e07b30d9034267b02b00 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:11:45 +0700 Subject: [PATCH 040/157] feat: customer type filter --- src/controllers/customer-controller.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index ebcd031..4da54e8 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -136,13 +136,17 @@ export class CustomerController extends Controller { @Get() async list( + @Query() customerType?: CustomerType, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, @Query() includeBranch: boolean = false, ) { const where = { - OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], + OR: [ + { customerName: { contains: query }, customerType }, + { customerNameEN: { contains: query }, customerType }, + ], } satisfies Prisma.CustomerWhereInput; const [result, total] = await prisma.$transaction([ From e96a05e3ad144d2c295f60a8ebd4d5edfebb431e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:12:10 +0700 Subject: [PATCH 041/157] feat: update schema --- .../20240610061629_add_field/migration.sql | 30 +++++++++++++++++++ .../migration.sql | 10 +++++++ prisma/schema.prisma | 15 +++++++--- src/controllers/employee-controller.ts | 22 +++++++++++--- .../employee-other-info-controller.ts | 22 +++++++++++--- 5 files changed, 87 insertions(+), 12 deletions(-) create mode 100644 prisma/migrations/20240610061629_add_field/migration.sql create mode 100644 prisma/migrations/20240610062435_fix_prev_typo/migration.sql diff --git a/prisma/migrations/20240610061629_add_field/migration.sql b/prisma/migrations/20240610061629_add_field/migration.sql new file mode 100644 index 0000000..bea038e --- /dev/null +++ b/prisma/migrations/20240610061629_add_field/migration.sql @@ -0,0 +1,30 @@ +/* + Warnings: + + - You are about to drop the column `birthPlace` on the `EmployeeOtherInfo` table. All the data in the column will be lost. + - You are about to drop the column `fatherFullName` on the `EmployeeOtherInfo` table. All the data in the column will be lost. + - You are about to drop the column `motherFullName` on the `EmployeeOtherInfo` table. All the data in the column will be lost. + - Added the required column `birthPlaceEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `fatherFirstName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `fatherFirstNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `fatherLastName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `fatherLastNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `motherFirstName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `motherFirstNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `motherLastName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + - Added the required column `motherLastNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlace", +DROP COLUMN "fatherFullName", +DROP COLUMN "motherFullName", +ADD COLUMN "birthPlaceEN" TEXT NOT NULL, +ADD COLUMN "fatherFirstName" TEXT NOT NULL, +ADD COLUMN "fatherFirstNameEN" TEXT NOT NULL, +ADD COLUMN "fatherLastName" TEXT NOT NULL, +ADD COLUMN "fatherLastNameEN" TEXT NOT NULL, +ADD COLUMN "motherFirstName" TEXT NOT NULL, +ADD COLUMN "motherFirstNameEN" TEXT NOT NULL, +ADD COLUMN "motherLastName" TEXT NOT NULL, +ADD COLUMN "motherLastNameEN" TEXT NOT NULL; diff --git a/prisma/migrations/20240610062435_fix_prev_typo/migration.sql b/prisma/migrations/20240610062435_fix_prev_typo/migration.sql new file mode 100644 index 0000000..23b59f5 --- /dev/null +++ b/prisma/migrations/20240610062435_fix_prev_typo/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - You are about to drop the column `birthPlaceEN` on the `EmployeeOtherInfo` table. All the data in the column will be lost. + - Added the required column `birthPlace` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlaceEN", +ADD COLUMN "birthPlace" TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a8d0dd9..f5f8e21 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -501,10 +501,17 @@ model EmployeeOtherInfo { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - citizenId String - fatherFullName String - motherFullName String - birthPlace String + citizenId String + birthPlace String + fatherFirstName String + fatherLastName String + motherFirstName String + motherLastName String + + fatherFirstNameEN String + fatherLastNameEN String + motherFirstNameEN String + motherLastNameEN String createdBy String? createdAt DateTime @default(now()) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index d5fd5ce..c1745f7 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -86,8 +86,15 @@ type EmployeeCreate = { employeeOtherInfo: { citizenId: string; - fatherFullName: string; - motherFullName: string; + fatherFirstName: string; + fatherLastName: string; + motherFirstName: string; + motherLastName: string; + + fatherFirstNameEN: string; + fatherLastNameEN: string; + motherFirstNameEN: string; + motherLastNameEN: string; birthPlace: string; }; }; @@ -150,8 +157,15 @@ type EmployeeUpdate = { employeeOtherInfo: { citizenId: string; - fatherFullName: string; - motherFullName: string; + fatherFirstName: string; + fatherLastName: string; + motherFirstName: string; + motherLastName: string; + + fatherFirstNameEN: string; + fatherLastNameEN: string; + motherFirstNameEN: string; + motherLastNameEN: string; birthPlace: string; }; }; diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index e134ec5..c866678 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -21,15 +21,29 @@ import { RequestWithUser } from "../interfaces/user"; type EmployeeOtherInfoCreate = { citizenId: string; - fatherFullName: string; - motherFullName: string; + fatherFirstName: string; + fatherLastName: string; + motherFirstName: string; + motherLastName: string; + + fatherFirstNameEN: string; + fatherLastNameEN: string; + motherFirstNameEN: string; + motherLastNameEN: string; birthPlace: string; }; type EmployeeOtherInfoUpdate = { citizenId: string; - fatherFullName: string; - motherFullName: string; + fatherFirstName: string; + fatherLastName: string; + motherFirstName: string; + motherLastName: string; + + fatherFirstNameEN: string; + fatherLastNameEN: string; + motherFirstNameEN: string; + motherLastNameEN: string; birthPlace: string; }; From 1aea0d91334029627a0d54a1e61d9cb56f9681df Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 14:47:33 +0700 Subject: [PATCH 042/157] feat: add remark field --- src/controllers/employee-controller.ts | 2 ++ src/controllers/employee-work-controller.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index c1745f7..afef206 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -68,6 +68,7 @@ type EmployeeCreate = { workPermitIssuDate: Date; workPermitExpireDate: Date; workEndDate: Date; + remark?: string; }[]; employeeCheckup?: { @@ -138,6 +139,7 @@ type EmployeeUpdate = { workPermitIssuDate: Date; workPermitExpireDate: Date; workEndDate: Date; + remark?: string; }[]; employeeCheckup?: { diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts index c3cde09..0b48fbb 100644 --- a/src/controllers/employee-work-controller.ts +++ b/src/controllers/employee-work-controller.ts @@ -25,6 +25,7 @@ type EmployeeWorkCreate = { workPermitIssuDate: Date; workPermitExpireDate: Date; workEndDate: Date; + remark?: string; }; type EmployeeWorkUpdate = { @@ -36,6 +37,7 @@ type EmployeeWorkUpdate = { workPermitIssuDate?: Date; workPermitExpireDate?: Date; workEndDate?: Date; + remark?: string; }; @Route("api/v1/employee/{employeeId}/work") From c746b2ffbe3b572409e1015b4938f7e843886626 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 15:24:06 +0700 Subject: [PATCH 043/157] fix: type --- src/controllers/customer-branch-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 87df4f6..3d23525 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -96,7 +96,7 @@ export type CustomerBranchUpdate = { jobDescription?: string; saleEmployee?: string; payDate?: Date; - wageDate?: number; + wageRate?: number; subDistrictId?: string | null; districtId?: string | null; From 9c4e47105d595fcf4a24018bbbc061a1e44ef55c Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:06:33 +0700 Subject: [PATCH 044/157] chore: migration --- .../20240610074721_update_field/migration.sql | 11 +++++++++++ prisma/schema.prisma | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20240610074721_update_field/migration.sql diff --git a/prisma/migrations/20240610074721_update_field/migration.sql b/prisma/migrations/20240610074721_update_field/migration.sql new file mode 100644 index 0000000..d6e7653 --- /dev/null +++ b/prisma/migrations/20240610074721_update_field/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - You are about to drop the column `imageUrl` on the `Product` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "EmployeeWork" ADD COLUMN "remark" TEXT; + +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "imageUrl"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f5f8e21..a65e776 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -488,6 +488,7 @@ model EmployeeWork { workPermitIssuDate DateTime workPermitExpireDate DateTime workEndDate DateTime + remark String? createdBy String? createdAt DateTime @default(now()) @@ -610,7 +611,6 @@ model Product { price Int agentPrice Int serviceCharge Int - imageUrl String status Status @default(CREATED) From aba68af123addea0f2602c360dc1e3727282df82 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:50:17 +0700 Subject: [PATCH 045/157] fix: change structure --- .../migration.sql | 45 +++++++++++++++++++ prisma/schema.prisma | 20 +++++++-- src/controllers/employee-controller.ts | 45 ++++++++++++++----- 3 files changed, 95 insertions(+), 15 deletions(-) create mode 100644 prisma/migrations/20240610094945_change_employee_fields/migration.sql diff --git a/prisma/migrations/20240610094945_change_employee_fields/migration.sql b/prisma/migrations/20240610094945_change_employee_fields/migration.sql new file mode 100644 index 0000000..e20d1e0 --- /dev/null +++ b/prisma/migrations/20240610094945_change_employee_fields/migration.sql @@ -0,0 +1,45 @@ +/* + Warnings: + + - You are about to drop the column `arrivalBarricade` on the `Employee` table. All the data in the column will be lost. + - You are about to drop the column `arrivalCardNo` on the `Employee` table. All the data in the column will be lost. + - You are about to drop the column `email` on the `Employee` table. All the data in the column will be lost. + - You are about to drop the column `telephoneNo` on the `Employee` table. All the data in the column will be lost. + - Added the required column `entryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportExpiryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportIssueDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportIssuingCountry` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportIssuingPlace` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportNumber` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `passportType` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `tm6Number` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaExpiryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaIssueDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaIssuingPlace` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaNumber` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaStayUntilDate` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `visaType` to the `Employee` table without a default value. This is not possible if the table is not empty. + - Added the required column `workerStatus` to the `Employee` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "Employee" DROP COLUMN "arrivalBarricade", +DROP COLUMN "arrivalCardNo", +DROP COLUMN "email", +DROP COLUMN "telephoneNo", +ADD COLUMN "entryDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "passportExpiryDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "passportIssueDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "passportIssuingCountry" TEXT NOT NULL, +ADD COLUMN "passportIssuingPlace" TEXT NOT NULL, +ADD COLUMN "passportNumber" TEXT NOT NULL, +ADD COLUMN "passportType" TEXT NOT NULL, +ADD COLUMN "previousPassportReference" TEXT, +ADD COLUMN "tm6Number" TEXT NOT NULL, +ADD COLUMN "visaExpiryDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "visaIssueDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "visaIssuingPlace" TEXT NOT NULL, +ADD COLUMN "visaNumber" TEXT NOT NULL, +ADD COLUMN "visaStayUntilDate" TIMESTAMP(3) NOT NULL, +ADD COLUMN "visaType" TEXT NOT NULL, +ADD COLUMN "workerStatus" TEXT NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a65e776..a93e1dc 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -428,11 +428,23 @@ model Employee { zipCode String - email String - telephoneNo String + passportType String + passportNumber String + passportIssueDate DateTime + passportExpiryDate DateTime + passportIssuingCountry String + passportIssuingPlace String + previousPassportReference String? - arrivalBarricade String - arrivalCardNo String + visaType String + visaNumber String + visaIssueDate DateTime + visaExpiryDate DateTime + visaIssuingPlace String + visaStayUntilDate DateTime + tm6Number String + entryDate DateTime + workerStatus String customerBranch CustomerBranch? @relation(fields: [customerBranchId], references: [id], onDelete: SetNull) customerBranchId String? diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index afef206..e13c628 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -34,7 +34,6 @@ type EmployeeCreate = { status?: Status; - code: string; nrcNo: string; dateOfBirth: Date; @@ -49,11 +48,24 @@ type EmployeeCreate = { addressEN: string; address: string; zipCode: string; - email: string; - telephoneNo: string; - arrivalBarricade: string; - arrivalCardNo: string; + passportType: string; + passportNumber: string; + passportIssueDate: Date; + passportExpiryDate: Date; + passportIssuingCountry: string; + passportIssuingPlace: string; + previousPassportReference?: string; + + visaType: string; + visaNumber: string; + visaIssueDate: Date; + visaExpiryDate: Date; + visaIssuingPlace: string; + visaStayUntilDate: Date; + tm6Number: string; + entryDate: Date; + workerStatus: string; subDistrictId?: string | null; districtId?: string | null; @@ -104,7 +116,6 @@ type EmployeeUpdate = { customerBranchId?: string; status?: "ACTIVE" | "INACTIVE"; - code?: string; nrcNo?: string; dateOfBirth?: Date; @@ -119,11 +130,24 @@ type EmployeeUpdate = { addressEN?: string; address?: string; zipCode?: string; - email?: string; - telephoneNo?: string; - arrivalBarricade?: string; - arrivalCardNo?: string; + passportType?: string; + passportNumber?: string; + passportIssueDate?: Date; + passportExpiryDate?: Date; + passportIssuingCountry?: string; + passportIssuingPlace?: string; + previousPassportReference?: string; + + visaType?: string; + visaNumber?: string; + visaIssueDate?: Date; + visaExpiryDate?: Date; + visaIssuingPlace?: string; + visaStayUntilDate?: Date; + tm6Number?: string; + entryDate?: Date; + workerStatus?: string; subDistrictId?: string | null; districtId?: string | null; @@ -189,7 +213,6 @@ export class EmployeeController extends Controller { { firstNameEN: { contains: query }, zipCode }, { lastName: { contains: query }, zipCode }, { lastNameEN: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, ], } satisfies Prisma.EmployeeWhereInput; From cd2d0ae9530042fac6713c15d0aed240232f3eab Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:54:58 +0700 Subject: [PATCH 046/157] fix: type error --- src/controllers/customer-branch-controller.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 3d23525..43254c4 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -177,7 +177,6 @@ export class CustomerBranchController extends Controller { { firstNameEN: { contains: query }, zipCode }, { lastName: { contains: query }, zipCode }, { lastNameEN: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, ], } satisfies Prisma.EmployeeWhereInput; From cc22d761b6f8282c79972b9d41881fe1a516bb89 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:47:40 +0700 Subject: [PATCH 047/157] feat: service api endpoint --- src/controllers/service/service-controller.ts | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/controllers/service/service-controller.ts diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts new file mode 100644 index 0000000..b6391f0 --- /dev/null +++ b/src/controllers/service/service-controller.ts @@ -0,0 +1,181 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import minio from "../../services/minio"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +if (!process.env.MINIO_BUCKET) { + throw Error("Require MinIO bucket."); +} + +const MINIO_BUCKET = process.env.MINIO_BUCKET; + +type ServiceCreate = { + code: string; + name: string; + detail: string; +}; + +type ServiceUpdate = { + code: string; + name: string; + detail: string; +}; + +function imageLocation(id: string) { + return `service/img-${id}`; +} + +@Route("api/service") +@Tags("Service") +@Security("keycloak") +export class ServiceController extends Controller { + @Get() + async getService( + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + OR: [{ name: { contains: query } }, { detail: { contains: query } }], + } satisfies Prisma.ServiceWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.service.findMany({ + orderBy: { createdAt: "asc" }, + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.service.count({ where }), + ]); + + return { + result: await Promise.all( + result.map(async (v) => ({ + ...v, + imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60), + })), + ), + page, + pageSize, + total, + }; + } + + @Get("{serviceId}") + async getServiceById(@Path() serviceId: string) { + const record = await prisma.service.findFirst({ + where: { id: serviceId }, + }); + + if (!record) + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + + return Object.assign(record, { + imageUrl: await minio.presignedGetObject(MINIO_BUCKET, `service/img-${record.id}`, 60 * 60), + }); + } + + @Get("{serviceId}/work") + async getWorkOfService( + @Path() serviceId: string, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const [result, total] = await prisma.$transaction([ + prisma.work.findMany({ + where: { serviceId }, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.work.count({ where: { serviceId } }), + ]); + return { result, page, pageSize, total }; + } + + @Post() + async createService(@Request() req: RequestWithUser, @Body() body: ServiceCreate) { + const record = await prisma.service.create({ + data: { + ...body, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + + this.setStatus(HttpStatus.CREATED); + + return Object.assign(record, { + imageUrl: await minio.presignedGetObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Put("{serviceId}") + async editService( + @Request() req: RequestWithUser, + @Body() body: ServiceUpdate, + @Path() serviceId: string, + ) { + if (!(await prisma.service.findUnique({ where: { id: serviceId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + } + + const record = await prisma.service.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: serviceId }, + }); + return Object.assign(record, { + profileImageUrl: await minio.presignedGetObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + profileImageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Delete("{serviceId}") + async deleteService(@Path() serviceId: string) { + const record = await prisma.service.findFirst({ where: { id: serviceId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Service is in used.", "data_in_used"); + } + + return await prisma.service.delete({ where: { id: serviceId } }); + } +} From c7aec4559284a394b06cb006883378e9d4c2a4cf Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 09:27:37 +0700 Subject: [PATCH 048/157] feat: count data --- src/controllers/product/group-controller.ts | 5 +++++ src/controllers/product/type-controller.ts | 5 +++++ src/controllers/service/service-controller.ts | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index d480c22..e5b3ef1 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -37,6 +37,11 @@ type ProductGroupUpdate = { @Tags("Product Group") @Security("keycloak") export class ProductGroup extends Controller { + @Get() + async getProductGroupStats() { + return await prisma.productGroup.count(); + } + @Get() async getProductGroup(@Query() query: string = "") { const where = { diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 14a7e6b..87611d7 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -37,6 +37,11 @@ type ProductTypeUpdate = { @Tags("Product Type") @Security("keycloak") export class ProductType extends Controller { + @Get() + async getProductTypeStats() { + return await prisma.productType.count(); + } + @Get() async getProductType(@Query() query: string = "") { const where = { diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index b6391f0..a2a5ca8 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -46,6 +46,11 @@ function imageLocation(id: string) { @Tags("Service") @Security("keycloak") export class ServiceController extends Controller { + @Get() + async getServiceStats() { + return await prisma.service.count(); + } + @Get() async getService( @Query() query: string = "", From aa7d865352417fe53eb1e7f7b795ef7e61d569dc Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 09:31:10 +0700 Subject: [PATCH 049/157] fix: wrong endpoints --- src/controllers/product/group-controller.ts | 2 +- src/controllers/product/type-controller.ts | 2 +- src/controllers/service/service-controller.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index e5b3ef1..cea4f52 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -37,7 +37,7 @@ type ProductGroupUpdate = { @Tags("Product Group") @Security("keycloak") export class ProductGroup extends Controller { - @Get() + @Get("stats") async getProductGroupStats() { return await prisma.productGroup.count(); } diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 87611d7..e1c5bb8 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -37,7 +37,7 @@ type ProductTypeUpdate = { @Tags("Product Type") @Security("keycloak") export class ProductType extends Controller { - @Get() + @Get("stats") async getProductTypeStats() { return await prisma.productType.count(); } diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index a2a5ca8..d8a9583 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -46,7 +46,7 @@ function imageLocation(id: string) { @Tags("Service") @Security("keycloak") export class ServiceController extends Controller { - @Get() + @Get("stats") async getServiceStats() { return await prisma.service.count(); } From e82f3f37b2a6858a3891af877c66c0c667ef7af6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 09:42:42 +0700 Subject: [PATCH 050/157] feat: also update customer status to active --- src/controllers/employee-controller.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index e13c628..8fad526 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -392,6 +392,16 @@ export class EmployeeController extends Controller { data: { status: Status.ACTIVE }, }); + await prisma.customer.updateMany({ + where: { + branch: { + some: { id: customerBranchId }, + }, + status: Status.CREATED, + }, + data: { status: Status.ACTIVE }, + }); + this.setStatus(HttpStatus.CREATED); return Object.assign(record, { From c079f43e8d217b03571e1f077ea143841ad22cd8 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 09:48:11 +0700 Subject: [PATCH 051/157] feat: count employee --- src/controllers/employee-controller.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 8fad526..6f7f297 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -200,6 +200,13 @@ type EmployeeUpdate = { @Tags("Employee") @Security("keycloak") export class EmployeeController extends Controller { + @Get("stats") + async getEmployeeStats(@Query() customerBranchId?: string) { + return await prisma.employee.count({ + where: { customerBranchId }, + }); + } + @Get() async list( @Query() zipCode?: string, From af4489dccc589867d883008afc99b7e7e7558eb0 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 11:27:00 +0700 Subject: [PATCH 052/157] feat: update field --- .../migration.sql | 31 +++++ .../20240611042536_add_field/migration.sql | 10 ++ prisma/schema.prisma | 53 ++++---- .../employee-checkup-controller.ts | 36 ++---- src/controllers/employee-controller.ts | 113 +++++++++--------- .../employee-other-info-controller.ts | 43 +++---- src/controllers/employee-work-controller.ts | 36 ++---- 7 files changed, 162 insertions(+), 160 deletions(-) create mode 100644 prisma/migrations/20240611040600_make_field_optional/migration.sql create mode 100644 prisma/migrations/20240611042536_add_field/migration.sql diff --git a/prisma/migrations/20240611040600_make_field_optional/migration.sql b/prisma/migrations/20240611040600_make_field_optional/migration.sql new file mode 100644 index 0000000..595a50d --- /dev/null +++ b/prisma/migrations/20240611040600_make_field_optional/migration.sql @@ -0,0 +1,31 @@ +-- AlterTable +ALTER TABLE "EmployeeCheckup" ALTER COLUMN "checkupResult" DROP NOT NULL, +ALTER COLUMN "checkupType" DROP NOT NULL, +ALTER COLUMN "hospitalName" DROP NOT NULL, +ALTER COLUMN "remark" DROP NOT NULL, +ALTER COLUMN "medicalBenefitScheme" DROP NOT NULL, +ALTER COLUMN "insuranceCompany" DROP NOT NULL, +ALTER COLUMN "coverageStartDate" DROP NOT NULL, +ALTER COLUMN "coverageExpireDate" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "EmployeeOtherInfo" ALTER COLUMN "citizenId" DROP NOT NULL, +ALTER COLUMN "fatherFirstName" DROP NOT NULL, +ALTER COLUMN "fatherFirstNameEN" DROP NOT NULL, +ALTER COLUMN "fatherLastName" DROP NOT NULL, +ALTER COLUMN "fatherLastNameEN" DROP NOT NULL, +ALTER COLUMN "motherFirstName" DROP NOT NULL, +ALTER COLUMN "motherFirstNameEN" DROP NOT NULL, +ALTER COLUMN "motherLastName" DROP NOT NULL, +ALTER COLUMN "motherLastNameEN" DROP NOT NULL, +ALTER COLUMN "birthPlace" DROP NOT NULL; + +-- AlterTable +ALTER TABLE "EmployeeWork" ALTER COLUMN "ownerName" DROP NOT NULL, +ALTER COLUMN "positionName" DROP NOT NULL, +ALTER COLUMN "jobType" DROP NOT NULL, +ALTER COLUMN "workplace" DROP NOT NULL, +ALTER COLUMN "workPermitNo" DROP NOT NULL, +ALTER COLUMN "workPermitIssuDate" DROP NOT NULL, +ALTER COLUMN "workPermitExpireDate" DROP NOT NULL, +ALTER COLUMN "workEndDate" DROP NOT NULL; diff --git a/prisma/migrations/20240611042536_add_field/migration.sql b/prisma/migrations/20240611042536_add_field/migration.sql new file mode 100644 index 0000000..d98d0b1 --- /dev/null +++ b/prisma/migrations/20240611042536_add_field/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - You are about to drop the column `birthPlace` on the `EmployeeOtherInfo` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlace", +ADD COLUMN "fatherBirthPlace" TEXT, +ADD COLUMN "motherBirthPlace" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index a93e1dc..f8bf42e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -467,18 +467,18 @@ model EmployeeCheckup { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - checkupResult String - checkupType String + checkupResult String? + checkupType String? province Province? @relation(fields: [provinceId], references: [id], onDelete: SetNull) provinceId String? - hospitalName String - remark String - medicalBenefitScheme String - insuranceCompany String - coverageStartDate DateTime - coverageExpireDate DateTime + hospitalName String? + remark String? + medicalBenefitScheme String? + insuranceCompany String? + coverageStartDate DateTime? + coverageExpireDate DateTime? createdBy String? createdAt DateTime @default(now()) @@ -492,14 +492,14 @@ model EmployeeWork { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - ownerName String - positionName String - jobType String - workplace String - workPermitNo String - workPermitIssuDate DateTime - workPermitExpireDate DateTime - workEndDate DateTime + ownerName String? + positionName String? + jobType String? + workplace String? + workPermitNo String? + workPermitIssuDate DateTime? + workPermitExpireDate DateTime? + workEndDate DateTime? remark String? createdBy String? @@ -514,17 +514,18 @@ model EmployeeOtherInfo { employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade) employeeId String - citizenId String - birthPlace String - fatherFirstName String - fatherLastName String - motherFirstName String - motherLastName String + citizenId String? + fatherBirthPlace String? + fatherFirstName String? + fatherLastName String? + motherBirthPlace String? + motherFirstName String? + motherLastName String? - fatherFirstNameEN String - fatherLastNameEN String - motherFirstNameEN String - motherLastNameEN String + fatherFirstNameEN String? + fatherLastNameEN String? + motherFirstNameEN String? + motherLastNameEN String? createdBy String? createdAt DateTime @default(now()) diff --git a/src/controllers/employee-checkup-controller.ts b/src/controllers/employee-checkup-controller.ts index eff4b5c..ede52f4 100644 --- a/src/controllers/employee-checkup-controller.ts +++ b/src/controllers/employee-checkup-controller.ts @@ -16,32 +16,18 @@ import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -type EmployeeCheckupCreate = { - checkupType: string; - checkupResult: string; +type EmployeeCheckupPayload = { + checkupType?: string | null; + checkupResult?: string | null; provinceId?: string | null; - hospitalName: string; - remark: string; - medicalBenefitScheme: string; - insuranceCompany: string; - coverageStartDate: Date; - coverageExpireDate: Date; -}; - -type EmployeeCheckupEdit = { - checkupType?: string; - checkupResult?: string; - - provinceId?: string | null; - - hospitalName?: string; - remark?: string; - medicalBenefitScheme?: string; - insuranceCompany?: string; - coverageStartDate?: Date; - coverageExpireDate?: Date; + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; }; @Route("api/v1/employee/{employeeId}/checkup") @@ -75,7 +61,7 @@ export class EmployeeCheckupController extends Controller { async create( @Request() req: RequestWithUser, @Path() employeeId: string, - @Body() body: EmployeeCheckupCreate, + @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId || employeeId) { const [province, employee] = await prisma.$transaction([ @@ -119,7 +105,7 @@ export class EmployeeCheckupController extends Controller { @Request() req: RequestWithUser, @Path() employeeId: string, @Path() checkupId: string, - @Body() body: EmployeeCheckupEdit, + @Body() body: EmployeeCheckupPayload, ) { if (body.provinceId || employeeId) { const [province, employee] = await prisma.$transaction([ diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 6f7f297..966f437 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -26,7 +26,7 @@ if (!process.env.MINIO_BUCKET) { const MINIO_BUCKET = process.env.MINIO_BUCKET; function imageLocation(id: string) { - return `employee/profile-img-${id}`; + return `employee/${id}/profile-image`; } type EmployeeCreate = { @@ -72,43 +72,43 @@ type EmployeeCreate = { provinceId?: string | null; employeeWork?: { - ownerName: string; - positionName: string; - jobType: string; - workplace: string; - workPermitNo: string; - workPermitIssuDate: Date; - workPermitExpireDate: Date; - workEndDate: Date; - remark?: string; + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; }[]; employeeCheckup?: { - checkupType: string; - checkupResult: string; + checkupType?: string | null; + checkupResult?: string | null; provinceId?: string | null; - hospitalName: string; - remark: string; - medicalBenefitScheme: string; - insuranceCompany: string; - coverageStartDate: Date; - coverageExpireDate: Date; + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; }[]; - employeeOtherInfo: { - citizenId: string; - fatherFirstName: string; - fatherLastName: string; - motherFirstName: string; - motherLastName: string; + employeeOtherInfo?: { + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; - fatherFirstNameEN: string; - fatherLastNameEN: string; - motherFirstNameEN: string; - motherLastNameEN: string; - birthPlace: string; + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; + birthPlace?: string | null; }; }; @@ -155,44 +155,45 @@ type EmployeeUpdate = { employeeWork?: { id?: string; - ownerName: string; - positionName: string; - jobType: string; - workplace: string; - workPermitNo: string; - workPermitIssuDate: Date; - workPermitExpireDate: Date; - workEndDate: Date; - remark?: string; + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; }[]; employeeCheckup?: { id?: string; - checkupType: string; - checkupResult: string; + checkupType?: string | null; + checkupResult?: string | null; provinceId?: string | null; - hospitalName: string; - remark: string; - medicalBenefitScheme: string; - insuranceCompany: string; - coverageStartDate: Date; - coverageExpireDate: Date; + hospitalName?: string | null; + remark?: string | null; + medicalBenefitScheme?: string | null; + insuranceCompany?: string | null; + coverageStartDate?: Date | null; + coverageExpireDate?: Date | null; }[]; employeeOtherInfo: { - citizenId: string; - fatherFirstName: string; - fatherLastName: string; - motherFirstName: string; - motherLastName: string; + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + fatherBirthPlace?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; + motherBirthPlace?: string | null; - fatherFirstNameEN: string; - fatherLastNameEN: string; - motherFirstNameEN: string; - motherLastNameEN: string; - birthPlace: string; + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; }; }; diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index c866678..58e0ff5 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -1,4 +1,3 @@ -import { Prisma, Status } from "@prisma/client"; import { Body, Controller, @@ -7,7 +6,6 @@ import { Put, Path, Post, - Query, Request, Route, Security, @@ -19,32 +17,19 @@ import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; import { RequestWithUser } from "../interfaces/user"; -type EmployeeOtherInfoCreate = { - citizenId: string; - fatherFirstName: string; - fatherLastName: string; - motherFirstName: string; - motherLastName: string; +type EmployeeOtherInfoPayload = { + citizenId?: string | null; + fatherFirstName?: string | null; + fatherLastName?: string | null; + fatherBirthPlace?: string | null; + motherFirstName?: string | null; + motherLastName?: string | null; + motherBirthPlace?: string | null; - fatherFirstNameEN: string; - fatherLastNameEN: string; - motherFirstNameEN: string; - motherLastNameEN: string; - birthPlace: string; -}; - -type EmployeeOtherInfoUpdate = { - citizenId: string; - fatherFirstName: string; - fatherLastName: string; - motherFirstName: string; - motherLastName: string; - - fatherFirstNameEN: string; - fatherLastNameEN: string; - motherFirstNameEN: string; - motherLastNameEN: string; - birthPlace: string; + fatherFirstNameEN?: string | null; + fatherLastNameEN?: string | null; + motherFirstNameEN?: string | null; + motherLastNameEN?: string | null; }; @Route("api/v1/employee/{employeeId}/other-info") @@ -74,7 +59,7 @@ export class EmployeeOtherInfo extends Controller { async create( @Request() req: RequestWithUser, @Path() employeeId: string, - @Body() body: EmployeeOtherInfoCreate, + @Body() body: EmployeeOtherInfoPayload, ) { if (!(await prisma.employee.findUnique({ where: { id: employeeId } }))) throw new HttpError( @@ -102,7 +87,7 @@ export class EmployeeOtherInfo extends Controller { @Request() req: RequestWithUser, @Path() employeeId: string, @Path() otherInfoId: string, - @Body() body: EmployeeOtherInfoUpdate, + @Body() body: EmployeeOtherInfoPayload, ) { if (!(await prisma.employeeOtherInfo.findUnique({ where: { id: otherInfoId, employeeId } }))) { throw new HttpError( diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts index 0b48fbb..90f1c8b 100644 --- a/src/controllers/employee-work-controller.ts +++ b/src/controllers/employee-work-controller.ts @@ -16,28 +16,16 @@ import prisma from "../db"; import HttpStatus from "../interfaces/http-status"; import HttpError from "../interfaces/http-error"; -type EmployeeWorkCreate = { - ownerName: string; - positionName: string; - jobType: string; - workplace: string; - workPermitNo: string; - workPermitIssuDate: Date; - workPermitExpireDate: Date; - workEndDate: Date; - remark?: string; -}; - -type EmployeeWorkUpdate = { - ownerName?: string; - positionName?: string; - jobType?: string; - workplace?: string; - workPermitNo?: string; - workPermitIssuDate?: Date; - workPermitExpireDate?: Date; - workEndDate?: Date; - remark?: string; +type EmployeeWorkPayload = { + ownerName?: string | null; + positionName?: string | null; + jobType?: string | null; + workplace?: string | null; + workPermitNo?: string | null; + workPermitIssuDate?: Date | null; + workPermitExpireDate?: Date | null; + workEndDate?: Date | null; + remark?: string | null; }; @Route("api/v1/employee/{employeeId}/work") @@ -67,7 +55,7 @@ export class EmployeeWorkController extends Controller { async create( @Request() req: RequestWithUser, @Path() employeeId: string, - @Body() body: EmployeeWorkCreate, + @Body() body: EmployeeWorkPayload, ) { if (!(await prisma.employee.findUnique({ where: { id: employeeId } }))) throw new HttpError( @@ -95,7 +83,7 @@ export class EmployeeWorkController extends Controller { @Request() req: RequestWithUser, @Path() employeeId: string, @Path() workId: string, - @Body() body: EmployeeWorkUpdate, + @Body() body: EmployeeWorkPayload, ) { if (!(await prisma.employeeWork.findUnique({ where: { id: workId, employeeId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); From f7c916b84a1acb62fa026333632519e9657de60d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:01:20 +0700 Subject: [PATCH 053/157] feat: relation and auto gen code --- .../migration.sql | 25 +++++++++++ prisma/schema.prisma | 19 +++++---- src/controllers/product/group-controller.ts | 28 +++++++++---- src/controllers/product/type-controller.ts | 42 +++++++++++++++---- 4 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 prisma/migrations/20240611060055_change_relation/migration.sql diff --git a/prisma/migrations/20240611060055_change_relation/migration.sql b/prisma/migrations/20240611060055_change_relation/migration.sql new file mode 100644 index 0000000..dc100a6 --- /dev/null +++ b/prisma/migrations/20240611060055_change_relation/migration.sql @@ -0,0 +1,25 @@ +/* + Warnings: + + - You are about to drop the column `productGroupId` on the `Product` table. All the data in the column will be lost. + - Added the required column `productGroupId` to the `ProductType` table without a default value. This is not possible if the table is not empty. + - Added the required column `productId` to the `WorkProduct` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "Product" DROP CONSTRAINT "Product_productGroupId_fkey"; + +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "productGroupId"; + +-- AlterTable +ALTER TABLE "ProductType" ADD COLUMN "productGroupId" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "WorkProduct" ADD COLUMN "productId" TEXT NOT NULL; + +-- AddForeignKey +ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "ProductType" ADD CONSTRAINT "ProductType_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f8bf42e..85230f2 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -570,8 +570,10 @@ model Work { model WorkProduct { id String @id @default(uuid()) - work Work @relation(fields: [workId], references: [id], onDelete: Cascade) - workId String + work Work @relation(fields: [workId], references: [id], onDelete: Cascade) + workId String + product Product @relation(fields: [productId], references: [id], onDelete: Cascade) + productId String createdBy String? createdAt DateTime @default(now()) @@ -590,10 +592,11 @@ model ProductGroup { status Status @default(CREATED) createdBy String? - createdAt DateTime @default(now()) + createdAt DateTime @default(now()) updateBy String? - updatedAt DateTime @updatedAt - Product Product[] + updatedAt DateTime @updatedAt + + type ProductType[] } model ProductType { @@ -611,6 +614,9 @@ model ProductType { updateBy String? updatedAt DateTime @updatedAt + productGroup ProductGroup @relation(fields: [productGroupId], references: [id], onDelete: Cascade) + productGroupId String + product Product[] } @@ -630,8 +636,7 @@ model Product { productType ProductType? @relation(fields: [productTypeId], references: [id], onDelete: SetNull) productTypeId String? - productGroup ProductGroup? @relation(fields: [productGroupId], references: [id], onDelete: SetNull) - productGroupId String? + workProduct WorkProduct[] createdBy String? createdAt DateTime @default(now()) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index cea4f52..eaaa1ab 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -20,14 +20,12 @@ import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; type ProductGroupCreate = { - code: string; name: string; detail: string; remark: string; }; type ProductGroupUpdate = { - code?: string; name?: string; detail?: string; remark?: string; @@ -65,12 +63,26 @@ export class ProductGroup extends Controller { @Post() async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { - const record = await prisma.productGroup.create({ - data: { - ...body, - createdBy: req.user.name, - updateBy: req.user.name, - }, + const record = await prisma.$transaction(async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODGRP`, + }, + create: { + key: `PRODGRP`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await tx.productGroup.create({ + data: { + ...body, + code: `G${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); }); this.setStatus(HttpStatus.CREATED); diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index e1c5bb8..e570a7d 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -20,14 +20,14 @@ import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; type ProductTypeCreate = { - code: string; + productGroupId: string; name: string; detail: string; remark: string; }; type ProductTypeUpdate = { - code?: string; + productGroupId?: string; name?: string; detail?: string; remark?: string; @@ -65,12 +65,38 @@ export class ProductType extends Controller { @Post() async createProductType(@Request() req: RequestWithUser, @Body() body: ProductTypeCreate) { - const record = await prisma.productType.create({ - data: { - ...body, - createdBy: req.user.name, - updateBy: req.user.name, - }, + const productGroup = await prisma.productGroup.findFirst({ + where: { id: body.productGroupId }, + }); + + if (!productGroup) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product group associated cannot be found.", + "missing_or_invalid_parameter", + ); + } + + const record = await prisma.$transaction(async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODTYP_T${productGroup.code}`, + }, + create: { + key: `PRODTYP_T${productGroup.code}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return await tx.productGroup.create({ + data: { + ...body, + code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); }); this.setStatus(HttpStatus.CREATED); From 2c6586d9eebd20954b2755722173608f851001a3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:03:24 +0700 Subject: [PATCH 054/157] fix: typo --- src/controllers/product/type-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index e570a7d..51ed992 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -89,7 +89,7 @@ export class ProductType extends Controller { update: { value: { increment: 1 } }, }); - return await tx.productGroup.create({ + return await tx.productType.create({ data: { ...body, code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, From 784c24555781d76c6dae3a33aef341b7906dcc8f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 13:35:54 +0700 Subject: [PATCH 055/157] fix: missing v1 prefix --- src/controllers/product/group-controller.ts | 2 +- src/controllers/product/type-controller.ts | 2 +- src/controllers/service/service-controller.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index eaaa1ab..dd4873f 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -31,7 +31,7 @@ type ProductGroupUpdate = { remark?: string; }; -@Route("api/product-group") +@Route("api/v1/product-group") @Tags("Product Group") @Security("keycloak") export class ProductGroup extends Controller { diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 51ed992..d27d834 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -33,7 +33,7 @@ type ProductTypeUpdate = { remark?: string; }; -@Route("api/product-type") +@Route("api/v1/product-type") @Tags("Product Type") @Security("keycloak") export class ProductType extends Controller { diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index d8a9583..d0a31db 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -42,7 +42,7 @@ function imageLocation(id: string) { return `service/img-${id}`; } -@Route("api/service") +@Route("api/v1/service") @Tags("Service") @Security("keycloak") export class ServiceController extends Controller { From 73265c8965e4381400f8c3ddeda8b1de6341a4c1 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:00:45 +0700 Subject: [PATCH 056/157] refactor: update isolation level --- src/controllers/product/group-controller.ts | 43 +++++++++++---------- src/controllers/product/type-controller.ts | 43 +++++++++++---------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index dd4873f..fb6ace0 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -63,27 +63,30 @@ export class ProductGroup extends Controller { @Post() async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { - const record = await prisma.$transaction(async (tx) => { - const last = await tx.runningNo.upsert({ - where: { - key: `PRODGRP`, - }, - create: { - key: `PRODGRP`, - value: 1, - }, - update: { value: { increment: 1 } }, - }); + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODGRP`, + }, + create: { + key: `PRODGRP`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); - return await tx.productGroup.create({ - data: { - ...body, - code: `G${last.value.toString().padStart(2, "0")}`, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); - }); + return await tx.productGroup.create({ + data: { + ...body, + code: `G${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); this.setStatus(HttpStatus.CREATED); diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index d27d834..c450cd5 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -77,27 +77,30 @@ export class ProductType extends Controller { ); } - const record = await prisma.$transaction(async (tx) => { - const last = await tx.runningNo.upsert({ - where: { - key: `PRODTYP_T${productGroup.code}`, - }, - create: { - key: `PRODTYP_T${productGroup.code}`, - value: 1, - }, - update: { value: { increment: 1 } }, - }); + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODTYP_T${productGroup.code}`, + }, + create: { + key: `PRODTYP_T${productGroup.code}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); - return await tx.productType.create({ - data: { - ...body, - code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, - createdBy: req.user.name, - updateBy: req.user.name, - }, - }); - }); + return await tx.productType.create({ + data: { + ...body, + code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); this.setStatus(HttpStatus.CREATED); From 8a1354ac2bc269f3a7136e4e509b430dadee24f6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:30:55 +0700 Subject: [PATCH 057/157] feat: search branch by customer code --- src/controllers/customer-branch-controller.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 43254c4..7d1ab5a 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -121,6 +121,11 @@ export class CustomerBranchController extends Controller { { nameEN: { contains: query }, zipCode }, { name: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, + { + customer: { + code: { contains: query }, + }, + }, ], AND: { customerId }, } satisfies Prisma.CustomerBranchWhereInput; From 88ac8c4b81524f072e48b5770af72b1a98190f2e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 14:44:55 +0700 Subject: [PATCH 058/157] fix: fixed branch no digit --- src/controllers/employee-controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 966f437..e24969a 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -345,10 +345,10 @@ export class EmployeeController extends Controller { async (tx) => { const last = await tx.runningNo.upsert({ where: { - key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, }, create: { - key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, value: 1, }, update: { value: { increment: 1 } }, @@ -369,7 +369,7 @@ export class EmployeeController extends Controller { }, data: { ...rest, - code: `${customerBranch.customer.code}-${customerBranch.branchNo}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, + code: `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, employeeWork: { createMany: { data: employeeWork || [], From 7e104a00207a404ba2f056484be2ec8fe8e43657 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:11:08 +0700 Subject: [PATCH 059/157] feat: add code to customer branch for query purpose --- src/controllers/customer-branch-controller.ts | 69 +++++++++---------- src/controllers/customer-controller.ts | 7 +- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 7d1ab5a..3801f19 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -121,11 +121,7 @@ export class CustomerBranchController extends Controller { { nameEN: { contains: query }, zipCode }, { name: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, - { - customer: { - code: { contains: query }, - }, - }, + { code: { contains: query }, zipCode }, ], AND: { customerId }, } satisfies Prisma.CustomerBranchWhereInput; @@ -219,38 +215,36 @@ export class CustomerBranchController extends Controller { @Post() async create(@Request() req: RequestWithUser, @Body() body: CustomerBranchCreate) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerId) { - const [province, district, subDistrict, customer] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), - ]); - if (body.provinceId && !province) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerId && !customer) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer cannot be found.", - "missing_or_invalid_parameter", - ); - } + const [province, district, subDistrict, customer] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customer.findFirst({ where: { id: body.customerId || undefined } }), + ]); + if (body.provinceId && !province) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.districtId && !district) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.subDistrictId && !subDistrict) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "missing_or_invalid_parameter", + ); + if (!customer) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer cannot be found.", + "missing_or_invalid_parameter", + ); const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; @@ -269,6 +263,7 @@ export class CustomerBranchController extends Controller { data: { ...rest, branchNo: count + 1, + code: `${customer.code}-${(count + 1).toString().padStart(2, "0")}`, customer: { connect: { id: customerId } }, province: { connect: provinceId ? { id: provinceId } : undefined }, district: { connect: districtId ? { id: districtId } : undefined }, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 4da54e8..a037e22 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -290,6 +290,7 @@ export class CustomerController extends Controller { customerBranch?.map((v, i) => ({ ...v, branchNo: i + 1, + code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}-${(i + 1).toString().padStart(2, "0")}`, createdBy: req.user.name, updateBy: req.user.name, })) || [], @@ -325,7 +326,9 @@ export class CustomerController extends Controller { @Request() req: RequestWithUser, @Body() body: CustomerUpdate, ) { - if (!(await prisma.customer.findUnique({ where: { id: customerId } }))) { + const customer = await prisma.customer.findUnique({ where: { id: customerId } }); + + if (!customer) { throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); } @@ -417,6 +420,7 @@ export class CustomerController extends Controller { create: { ...v, branchNo: i + 1, + code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, createdBy: req.user.name, updateBy: req.user.name, id: undefined, @@ -424,6 +428,7 @@ export class CustomerController extends Controller { update: { ...v, branchNo: i + 1, + code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, updateBy: req.user.name, }, })), From b57cd6ac95a88e04a4c1e57eb68e4236a2b27eb3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:12:09 +0700 Subject: [PATCH 060/157] chore: update migration --- .../20240611081013_restructure_database/migration.sql | 11 +++++++++++ prisma/schema.prisma | 3 +++ 2 files changed, 14 insertions(+) create mode 100644 prisma/migrations/20240611081013_restructure_database/migration.sql diff --git a/prisma/migrations/20240611081013_restructure_database/migration.sql b/prisma/migrations/20240611081013_restructure_database/migration.sql new file mode 100644 index 0000000..075d9b2 --- /dev/null +++ b/prisma/migrations/20240611081013_restructure_database/migration.sql @@ -0,0 +1,11 @@ +/* + Warnings: + + - Added the required column `code` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "CustomerBranch" ADD COLUMN "code" TEXT NOT NULL; + +-- AlterTable +ALTER TABLE "Product" ADD COLUMN "attributes" JSONB; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 85230f2..432e0e6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -350,6 +350,7 @@ model Customer { model CustomerBranch { id String @id @default(uuid()) branchNo Int + code String legalPersonNo String name String @@ -638,6 +639,8 @@ model Product { workProduct WorkProduct[] + attributes Json? + createdBy String? createdAt DateTime @default(now()) updateBy String? From 52b04bdc593b3420af87b6c64a16a17f884375d2 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:23:51 +0700 Subject: [PATCH 061/157] chore: reorder swagger endpoints --- tsoa.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tsoa.json b/tsoa.json index 694176c..a5becec 100644 --- a/tsoa.json +++ b/tsoa.json @@ -29,10 +29,11 @@ { "name": "Employee Checkup" }, { "name": "Employee Work" }, { "name": "Employee Other Info" }, - { "name": "Service" }, - { "name": "Work" }, + { "name": "Product Group" }, { "name": "Product Type" }, - { "name": "Product Group" } + { "name": "Product" }, + { "name": "Service" }, + { "name": "Work" } ] } }, From ce9f5d89ac6a2fa480170d7e54cbc14fa0e3dfc6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:13:43 +0700 Subject: [PATCH 062/157] fix: input validation --- src/controllers/employee-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index e24969a..ed46e4e 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -101,14 +101,15 @@ type EmployeeCreate = { citizenId?: string | null; fatherFirstName?: string | null; fatherLastName?: string | null; + fatherBirthPlace?: string | null; motherFirstName?: string | null; motherLastName?: string | null; + motherBirthPlace?: string | null; fatherFirstNameEN?: string | null; fatherLastNameEN?: string | null; motherFirstNameEN?: string | null; motherLastNameEN?: string | null; - birthPlace?: string | null; }; }; From 69edca97b577949c6740bfe0c168b956c3a894e5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:16:22 +0700 Subject: [PATCH 063/157] fix: wrong table ref --- src/controllers/product/group-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index fb6ace0..ae3667a 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -99,11 +99,11 @@ export class ProductGroup extends Controller { @Body() body: ProductGroupUpdate, @Path() groupId: string, ) { - if (!(await prisma.work.findUnique({ where: { id: groupId } }))) { + if (!(await prisma.productGroup.findUnique({ where: { id: groupId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); } - const record = await prisma.work.update({ + const record = await prisma.productGroup.update({ data: { ...body, updateBy: req.user.name }, where: { id: groupId }, }); From 1cae220655e8d1e9965f33c43d9c2b4bdb91e37b Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 11 Jun 2024 16:41:39 +0700 Subject: [PATCH 064/157] feat: prevent empty foreign id --- src/controllers/employee-controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index ed46e4e..8b29f8a 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -326,6 +326,7 @@ export class EmployeeController extends Controller { const listProvinceId = employeeCheckup?.reduce((acc, cur) => { if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + if (!cur.provinceId) cur.provinceId = null; return acc; }, []); From ff9fdb1cd0d305ffa75d85ee23c2a5415b325e83 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:01:22 +0700 Subject: [PATCH 065/157] feat: work endpoints --- src/controllers/work/work-controller.ts | 172 ++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 src/controllers/work/work-controller.ts diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts new file mode 100644 index 0000000..8df4ddc --- /dev/null +++ b/src/controllers/work/work-controller.ts @@ -0,0 +1,172 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Query, + Request, + Route, + Security, + Tags, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +type WorkCreate = { + order: number; + name: string; + serviceId: string; +}; + +type WorkUpdate = { + order?: number; + name?: string; + serviceId?: string; +}; + +@Route("api/v1/work") +@Tags("Work") +@Security("keycloak") +export class WorkController extends Controller { + @Get() + async getWork( + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + OR: [{ name: { contains: query } }], + } satisfies Prisma.WorkWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.work.findMany({ + orderBy: { createdAt: "asc" }, + include: { service: true }, + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.work.count({ where }), + ]); + + return { result, page, pageSize, total }; + } + + @Get("{workId}") + async getWorkById(@Path() workId: string) { + const record = await prisma.work.findFirst({ + include: { service: true }, + where: { id: workId }, + }); + + if (!record) + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + + return record; + } + @Get("{workId}/product") + async getProductOfWork( + @Path() workId: string, + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const where = { + AND: [ + { + workProduct: { + some: { workId }, + }, + }, + { + OR: [{ name: { contains: query } }], + }, + ], + } satisfies Prisma.ProductWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.product.findMany({ + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.product.count({ + where, + }), + ]); + + return { result, page, pageSize, total }; + } + + @Post() + async createWork(@Request() req: RequestWithUser, @Body() body: WorkCreate) { + const service = await prisma.service.findFirst({ + where: { id: body.serviceId }, + }); + + if (!service) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Service not found.", + "missing_or_invalid_parameter", + ); + } + + const record = await prisma.work.create({ + data: { + ...body, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + + await prisma.service.updateMany({ + where: { id: service.id }, + data: { status: Status.ACTIVE }, + }); + + this.setStatus(HttpStatus.CREATED); + + return record; + } + + @Put("{workId}") + async editService( + @Request() req: RequestWithUser, + @Body() body: WorkUpdate, + @Path() workId: string, + ) { + if (!(await prisma.work.findUnique({ where: { id: workId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + } + + const record = await prisma.work.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: workId }, + }); + + return record; + } + + @Delete("{workId}") + async deleteWork(@Path() workId: string) { + const record = await prisma.work.findFirst({ where: { id: workId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Work is in used.", "missing_or_invalid_parameter"); + } + + return await prisma.work.delete({ where: { id: workId } }); + } +} From 96f49ab12ccdbac11c07b272ac282b9ea1f9f5c0 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 09:01:56 +0700 Subject: [PATCH 066/157] chore: deps ver --- package.json | 2 +- pnpm-lock.yaml | 3022 +++++++++++++++++++++++++++--------------------- 2 files changed, 1696 insertions(+), 1328 deletions(-) diff --git a/package.json b/package.json index b2e63ea..68c01c0 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@types/express": "^4.17.21", "@types/node": "^20.12.2", "@types/swagger-ui-express": "^4.1.6", - "nodemon": "^3.1.0", + "nodemon": "^3.1.3", "prettier": "^3.2.5", "prisma": "^5.12.1", "ts-node": "^10.9.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 244f837..2c08993 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,95 +1,1372 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@elastic/elasticsearch': - specifier: ^8.13.0 - version: 8.13.0 - '@prisma/client': - specifier: 5.12.1 - version: 5.12.1(prisma@5.12.1) - '@tsoa/runtime': - specifier: ^6.2.0 - version: 6.2.0 - cors: - specifier: ^2.8.5 - version: 2.8.5 - dotenv: - specifier: ^16.4.5 - version: 16.4.5 - express: - specifier: ^4.19.2 - version: 4.19.2 - fast-jwt: - specifier: ^4.0.0 - version: 4.0.0 - minio: - specifier: ^7.1.3 - version: 7.1.3 - promise.any: - specifier: ^2.0.6 - version: 2.0.6 - swagger-ui-express: - specifier: ^5.0.0 - version: 5.0.0(express@4.19.2) - tsoa: - specifier: ^6.2.0 - version: 6.2.0 +importers: -devDependencies: - '@types/cors': - specifier: ^2.8.17 - version: 2.8.17 - '@types/express': - specifier: ^4.17.21 - version: 4.17.21 - '@types/node': - specifier: ^20.12.2 - version: 20.12.2 - '@types/swagger-ui-express': - specifier: ^4.1.6 - version: 4.1.6 - nodemon: - specifier: ^3.1.0 - version: 3.1.0 - prettier: - specifier: ^3.2.5 - version: 3.2.5 - prisma: - specifier: ^5.12.1 - version: 5.12.1 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@types/node@20.12.2)(typescript@5.4.3) - typescript: - specifier: ^5.4.3 - version: 5.4.3 + .: + dependencies: + '@elastic/elasticsearch': + specifier: ^8.13.0 + version: 8.13.0 + '@prisma/client': + specifier: 5.12.1 + version: 5.12.1(prisma@5.12.1) + '@tsoa/runtime': + specifier: ^6.2.0 + version: 6.2.0 + cors: + specifier: ^2.8.5 + version: 2.8.5 + dotenv: + specifier: ^16.4.5 + version: 16.4.5 + express: + specifier: ^4.19.2 + version: 4.19.2 + fast-jwt: + specifier: ^4.0.0 + version: 4.0.0 + minio: + specifier: ^7.1.3 + version: 7.1.3 + promise.any: + specifier: ^2.0.6 + version: 2.0.6 + swagger-ui-express: + specifier: ^5.0.0 + version: 5.0.0(express@4.19.2) + tsoa: + specifier: ^6.2.0 + version: 6.2.0 + devDependencies: + '@types/cors': + specifier: ^2.8.17 + version: 2.8.17 + '@types/express': + specifier: ^4.17.21 + version: 4.17.21 + '@types/node': + specifier: ^20.12.2 + version: 20.12.2 + '@types/swagger-ui-express': + specifier: ^4.1.6 + version: 4.1.6 + nodemon: + specifier: ^3.1.3 + version: 3.1.3 + prettier: + specifier: ^3.2.5 + version: 3.2.5 + prisma: + specifier: ^5.12.1 + version: 5.12.1 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.12.2)(typescript@5.4.3) + typescript: + specifier: ^5.4.3 + version: 5.4.3 packages: - /@cspotcode/source-map-support@0.8.1: + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - /@elastic/elasticsearch@8.13.0: + '@elastic/elasticsearch@8.13.0': resolution: {integrity: sha512-OAYgzqArPqgDaIJ1yT0RX31YCgr1lleo53zL+36i23PFjHu08CA6Uq+BmBzEV05yEidl+ILPdeSfF3G8hPG/JQ==} engines: {node: '>=18'} + + '@elastic/transport@8.5.0': + resolution: {integrity: sha512-T+zSUHXBfrqlj/E9pJiaEgKoTdGykBCohzNBt6omDfI6EQtaNT240oMO03oXo35T8rwrCVonSMSoedbmToncVA==} + engines: {node: '>=18'} + + '@hapi/accept@6.0.3': + resolution: {integrity: sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==} + + '@hapi/ammo@6.0.1': + resolution: {integrity: sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==} + + '@hapi/b64@6.0.1': + resolution: {integrity: sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==} + + '@hapi/boom@10.0.1': + resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + + '@hapi/bounce@3.0.1': + resolution: {integrity: sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA==} + + '@hapi/bourne@3.0.0': + resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} + + '@hapi/call@9.0.1': + resolution: {integrity: sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==} + + '@hapi/catbox-memory@6.0.1': + resolution: {integrity: sha512-sVb+/ZxbZIvaMtJfAbdyY+QJUQg9oKTwamXpEg/5xnfG5WbJLTjvEn4kIGKz9pN3ENNbIL/bIdctmHmqi/AdGA==} + + '@hapi/catbox@12.1.1': + resolution: {integrity: sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==} + + '@hapi/content@6.0.0': + resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} + + '@hapi/cryptiles@6.0.1': + resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} + engines: {node: '>=14.0.0'} + + '@hapi/file@3.0.0': + resolution: {integrity: sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==} + + '@hapi/hapi@21.3.7': + resolution: {integrity: sha512-33J0nreMfqkhY7wwRAZRy+9J+7J4QOH1JtICMjIUmxfaOYSJL/d8JJCtg57SX60944bhlCeu7isb7qyr2jT2oA==} + engines: {node: '>=14.15.0'} + + '@hapi/heavy@8.0.1': + resolution: {integrity: sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==} + + '@hapi/hoek@11.0.4': + resolution: {integrity: sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==} + + '@hapi/iron@7.0.1': + resolution: {integrity: sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==} + + '@hapi/mimos@7.0.1': + resolution: {integrity: sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==} + + '@hapi/nigel@5.0.1': + resolution: {integrity: sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==} + engines: {node: '>=14.0.0'} + + '@hapi/pez@6.1.0': + resolution: {integrity: sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg==} + + '@hapi/podium@5.0.1': + resolution: {integrity: sha512-eznFTw6rdBhAijXFIlBOMJJd+lXTvqbrBIS4Iu80r2KTVIo4g+7fLy4NKp/8+UnSt5Ox6mJtAlKBU/Sf5080TQ==} + + '@hapi/shot@6.0.1': + resolution: {integrity: sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==} + + '@hapi/somever@4.1.1': + resolution: {integrity: sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==} + + '@hapi/statehood@8.1.1': + resolution: {integrity: sha512-YbK7PSVUA59NArAW5Np0tKRoIZ5VNYUicOk7uJmWZF6XyH5gGL+k62w77SIJb0AoAJ0QdGQMCQ/WOGL1S3Ydow==} + + '@hapi/subtext@8.1.0': + resolution: {integrity: sha512-PyaN4oSMtqPjjVxLny1k0iYg4+fwGusIhaom9B2StinBclHs7v46mIW706Y+Wo21lcgulGyXbQrmT/w4dus6ww==} + + '@hapi/teamwork@6.0.0': + resolution: {integrity: sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==} + engines: {node: '>=14.0.0'} + + '@hapi/topo@6.0.2': + resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + + '@hapi/validate@2.0.1': + resolution: {integrity: sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==} + + '@hapi/vise@5.0.1': + resolution: {integrity: sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==} + + '@hapi/wreck@18.0.1': + resolution: {integrity: sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/trace-mapping@0.3.9': + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + + '@lukeed/ms@2.0.2': + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@prisma/client@5.12.1': + resolution: {integrity: sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==} + engines: {node: '>=16.13'} + peerDependencies: + prisma: '*' + peerDependenciesMeta: + prisma: + optional: true + + '@prisma/debug@5.12.1': + resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==} + + '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': + resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==} + + '@prisma/engines@5.12.1': + resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==} + + '@prisma/fetch-engine@5.12.1': + resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==} + + '@prisma/get-platform@5.12.1': + resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==} + + '@tsconfig/node10@1.0.11': + resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} + + '@tsconfig/node12@1.0.11': + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + '@tsconfig/node14@1.0.3': + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + '@tsconfig/node16@1.0.4': + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + '@tsoa/cli@6.2.0': + resolution: {integrity: sha512-kzr10MsARpuivJl59XD33+sdMA18Rx9KBu7NCp18nV6kPQ1LDrVBwVgLL96w7lBgUGsCgVJ1/cUePW313uTZCw==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + + '@tsoa/runtime@6.2.0': + resolution: {integrity: sha512-iXSi5rDZWcPRcLKa9WaMBUdh4SdDN+9Cmy+R7i/DSCtFtbtUqE+ui+IMV9o6+759N6J3FqGBaPWa9kAtOrL4sA==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + + '@types/accepts@1.3.7': + resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/content-disposition@0.5.8': + resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==} + + '@types/cookies@0.9.0': + resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + + '@types/express-serve-static-core@4.17.43': + resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/http-assert@1.5.5': + resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/keygrip@1.0.6': + resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} + + '@types/koa-compose@3.2.8': + resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} + + '@types/koa@2.15.0': + resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/mime@4.0.0': + resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==} + deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed. + + '@types/multer@1.4.11': + resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} + + '@types/node@20.12.2': + resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + + '@types/qs@6.9.14': + resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.5': + resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + + '@types/swagger-ui-express@4.1.6': + resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + + '@zxing/text-encoding@0.9.0': + resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} + + abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array.prototype.map@1.0.7: + resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.3: + resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} + engines: {node: '>= 0.4'} + + asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + block-stream2@2.1.0: + resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} + + bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + + body-parser@1.20.2: + resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + browser-or-node@2.1.1: + resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} + engines: {node: '>= 0.6'} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + data-view-buffer@1.0.1: + resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.1: + resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.0: + resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} + engines: {node: '>= 0.4'} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + es-abstract@1.23.3: + resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} + engines: {node: '>= 0.4'} + + es-aggregate-error@1.0.13: + resolution: {integrity: sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==} + engines: {node: '>= 0.4'} + + es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + + es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + + es-object-atoms@1.0.0: + resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.0.3: + resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + express@4.19.2: + resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} + engines: {node: '>= 0.10.0'} + + fast-jwt@4.0.0: + resolution: {integrity: sha512-CnI93Tmk7eSzfw4e0Jlc5ZcWiN+/zK7xAKAhtXS8PAcKmYqfcXqxJl1hMyhk3iEt0M9JLo7DCYRDV2XcIacWAw==} + engines: {node: '>=16 <22'} + + fast-xml-parser@4.3.6: + resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} + hasBin: true + + fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + + filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + + finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + + for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + + foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + + get-symbol-description@1.0.2: + resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@10.3.12: + resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + + gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + + has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + + has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hpagent@1.2.0: + resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} + engines: {node: '>=14'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.1.0: + resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} + engines: {node: '>= 10'} + + is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + + is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + + is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.1: + resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} + engines: {node: '>= 0.4'} + + is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-function@1.0.10: + resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-negative-zero@2.0.3: + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} + + is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + + is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + + is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.13: + resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} + engines: {node: '>= 0.4'} + + is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + + is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + iterate-iterator@1.0.2: + resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} + + iterate-value@1.0.2: + resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==} + + jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + + json-stream@1.0.0: + resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + lru-cache@10.2.0: + resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} + engines: {node: 14 || >=16.14} + + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + + merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mime@4.0.1: + resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==} + engines: {node: '>=16'} + hasBin: true + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minio@7.1.3: + resolution: {integrity: sha512-xPrLjWkTT5E7H7VnzOjF//xBp9I40jYB4aWhb2xTFopXXfw+Wo82DDWngdUju7Doy3Wk7R8C4LAgwhLHHnf0wA==} + engines: {node: ^16 || ^18 || >=20} + + minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + + mnemonist@0.39.8: + resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + nodemon@3.1.3: + resolution: {integrity: sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==} + engines: {node: '>=10'} + hasBin: true + + nopt@1.0.10: + resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} + hasBin: true + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + + obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-scurry@1.10.2: + resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} + engines: {node: '>=16 || 14 >=14.17'} + + path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + + prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + + prisma@5.12.1: + resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==} + engines: {node: '>=16.13'} + hasBin: true + + promise.any@2.0.6: + resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} + engines: {node: '>= 0.4'} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + + qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + + query-string@7.1.3: + resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} + engines: {node: '>=6'} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + + regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + safe-array-concat@1.1.2: + resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-regex-test@1.0.3: + resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + + secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + + semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + + send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + + serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + + strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string.prototype.trim@1.2.9: + resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.8: + resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + swagger-ui-dist@5.13.0: + resolution: {integrity: sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==} + + swagger-ui-express@5.0.0: + resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + + through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + touch@3.1.0: + resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + hasBin: true + + ts-deepmerge@7.0.0: + resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} + engines: {node: '>=14.13.1'} + + ts-node@10.9.2: + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + + tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + + tsoa@6.2.0: + resolution: {integrity: sha512-EX/RyoU+4hD1rLM5NjYG+I7lEhqx1yuLgcHs/gyWQpkX/RL9cVR9hFA9LKQrK6PE+WTg1SEahn1MK3l/+6pVKw==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.2: + resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.1: + resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.2: + resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.6: + resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} + engines: {node: '>= 0.4'} + + typescript@5.4.3: + resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==} + engines: {node: '>=14.17'} + hasBin: true + + uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + + unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + + undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + undici@6.11.1: + resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} + engines: {node: '>=18.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util@0.12.5: + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + web-encoding@1.1.5: + resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + + which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + + which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + xml2js@0.5.0: + resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} + engines: {node: '>=4.0.0'} + + xml@1.0.1: + resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} + + xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + yaml@2.4.1: + resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + +snapshots: + + '@cspotcode/source-map-support@0.8.1': + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + '@elastic/elasticsearch@8.13.0': dependencies: '@elastic/transport': 8.5.0 tslib: 2.6.2 transitivePeerDependencies: - supports-color - dev: false - /@elastic/transport@8.5.0: - resolution: {integrity: sha512-T+zSUHXBfrqlj/E9pJiaEgKoTdGykBCohzNBt6omDfI6EQtaNT240oMO03oXo35T8rwrCVonSMSoedbmToncVA==} - engines: {node: '>=18'} + '@elastic/transport@8.5.0': dependencies: debug: 4.3.4(supports-color@5.5.0) hpagent: 1.2.0 @@ -99,87 +1376,59 @@ packages: undici: 6.11.1 transitivePeerDependencies: - supports-color - dev: false - /@hapi/accept@6.0.3: - resolution: {integrity: sha512-p72f9k56EuF0n3MwlBNThyVE5PXX40g+aQh+C/xbKrfzahM2Oispv3AXmOIU51t3j77zay1qrX7IIziZXspMlw==} + '@hapi/accept@6.0.3': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/ammo@6.0.1: - resolution: {integrity: sha512-pmL+nPod4g58kXrMcsGLp05O2jF4P2Q3GiL8qYV7nKYEh3cGf+rV4P5Jyi2Uq0agGhVU63GtaSAfBEZOlrJn9w==} + '@hapi/ammo@6.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/b64@6.0.1: - resolution: {integrity: sha512-ZvjX4JQReUmBheeCq+S9YavcnMMHWqx3S0jHNXWIM1kQDxB9cyfSycpVvjfrKcIS8Mh5N3hmu/YKo4Iag9g2Kw==} + '@hapi/b64@6.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/boom@10.0.1: - resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==} + '@hapi/boom@10.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/bounce@3.0.1: - resolution: {integrity: sha512-G+/Pp9c1Ha4FDP+3Sy/Xwg2O4Ahaw3lIZFSX+BL4uWi64CmiETuZPxhKDUD4xBMOUZbBlzvO8HjiK8ePnhBadA==} + '@hapi/bounce@3.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/bourne@3.0.0: - resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} - dev: false + '@hapi/bourne@3.0.0': {} - /@hapi/call@9.0.1: - resolution: {integrity: sha512-uPojQRqEL1GRZR4xXPqcLMujQGaEpyVPRyBlD8Pp5rqgIwLhtveF9PkixiKru2THXvuN8mUrLeet5fqxKAAMGg==} + '@hapi/call@9.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/catbox-memory@6.0.1: - resolution: {integrity: sha512-sVb+/ZxbZIvaMtJfAbdyY+QJUQg9oKTwamXpEg/5xnfG5WbJLTjvEn4kIGKz9pN3ENNbIL/bIdctmHmqi/AdGA==} + '@hapi/catbox-memory@6.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/catbox@12.1.1: - resolution: {integrity: sha512-hDqYB1J+R0HtZg4iPH3LEnldoaBsar6bYp0EonBmNQ9t5CO+1CqgCul2ZtFveW1ReA5SQuze9GPSU7/aecERhw==} + '@hapi/catbox@12.1.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 '@hapi/podium': 5.0.1 '@hapi/validate': 2.0.1 - dev: false - /@hapi/content@6.0.0: - resolution: {integrity: sha512-CEhs7j+H0iQffKfe5Htdak5LBOz/Qc8TRh51cF+BFv0qnuph3Em4pjGVzJMkI2gfTDdlJKWJISGWS1rK34POGA==} + '@hapi/content@6.0.0': dependencies: '@hapi/boom': 10.0.1 - dev: false - /@hapi/cryptiles@6.0.1: - resolution: {integrity: sha512-9GM9ECEHfR8lk5ASOKG4+4ZsEzFqLfhiryIJ2ISePVB92OHLp/yne4m+zn7z9dgvM98TLpiFebjDFQ0UHcqxXQ==} - engines: {node: '>=14.0.0'} + '@hapi/cryptiles@6.0.1': dependencies: '@hapi/boom': 10.0.1 - dev: false - /@hapi/file@3.0.0: - resolution: {integrity: sha512-w+lKW+yRrLhJu620jT3y+5g2mHqnKfepreykvdOcl9/6up8GrQQn+l3FRTsjHTKbkbfQFkuksHpdv2EcpKcJ4Q==} - dev: false + '@hapi/file@3.0.0': {} - /@hapi/hapi@21.3.7: - resolution: {integrity: sha512-33J0nreMfqkhY7wwRAZRy+9J+7J4QOH1JtICMjIUmxfaOYSJL/d8JJCtg57SX60944bhlCeu7isb7qyr2jT2oA==} - engines: {node: '>=14.15.0'} + '@hapi/hapi@21.3.7': dependencies: '@hapi/accept': 6.0.3 '@hapi/ammo': 6.0.1 @@ -199,79 +1448,58 @@ packages: '@hapi/teamwork': 6.0.0 '@hapi/topo': 6.0.2 '@hapi/validate': 2.0.1 - dev: false - /@hapi/heavy@8.0.1: - resolution: {integrity: sha512-gBD/NANosNCOp6RsYTsjo2vhr5eYA3BEuogk6cxY0QdhllkkTaJFYtTXv46xd6qhBVMbMMqcSdtqey+UQU3//w==} + '@hapi/heavy@8.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/hoek': 11.0.4 '@hapi/validate': 2.0.1 - dev: false - /@hapi/hoek@11.0.4: - resolution: {integrity: sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==} - dev: false + '@hapi/hoek@11.0.4': {} - /@hapi/iron@7.0.1: - resolution: {integrity: sha512-tEZnrOujKpS6jLKliyWBl3A9PaE+ppuL/+gkbyPPDb/l2KSKQyH4lhMkVb+sBhwN+qaxxlig01JRqB8dk/mPxQ==} + '@hapi/iron@7.0.1': dependencies: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 '@hapi/cryptiles': 6.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/mimos@7.0.1: - resolution: {integrity: sha512-b79V+BrG0gJ9zcRx1VGcCI6r6GEzzZUgiGEJVoq5gwzuB2Ig9Cax8dUuBauQCFKvl2YWSWyOc8mZ8HDaJOtkew==} + '@hapi/mimos@7.0.1': dependencies: '@hapi/hoek': 11.0.4 mime-db: 1.52.0 - dev: false - /@hapi/nigel@5.0.1: - resolution: {integrity: sha512-uv3dtYuB4IsNaha+tigWmN8mQw/O9Qzl5U26Gm4ZcJVtDdB1AVJOwX3X5wOX+A07qzpEZnOMBAm8jjSqGsU6Nw==} - engines: {node: '>=14.0.0'} + '@hapi/nigel@5.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/vise': 5.0.1 - dev: false - /@hapi/pez@6.1.0: - resolution: {integrity: sha512-+FE3sFPYuXCpuVeHQ/Qag1b45clR2o54QoonE/gKHv9gukxQ8oJJZPR7o3/ydDTK6racnCJXxOyT1T93FCJMIg==} + '@hapi/pez@6.1.0': dependencies: '@hapi/b64': 6.0.1 '@hapi/boom': 10.0.1 '@hapi/content': 6.0.0 '@hapi/hoek': 11.0.4 '@hapi/nigel': 5.0.1 - dev: false - /@hapi/podium@5.0.1: - resolution: {integrity: sha512-eznFTw6rdBhAijXFIlBOMJJd+lXTvqbrBIS4Iu80r2KTVIo4g+7fLy4NKp/8+UnSt5Ox6mJtAlKBU/Sf5080TQ==} + '@hapi/podium@5.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/teamwork': 6.0.0 '@hapi/validate': 2.0.1 - dev: false - /@hapi/shot@6.0.1: - resolution: {integrity: sha512-s5ynMKZXYoDd3dqPw5YTvOR/vjHvMTxc388+0qL0jZZP1+uwXuUD32o9DuuuLsmTlyXCWi02BJl1pBpwRuUrNA==} + '@hapi/shot@6.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/validate': 2.0.1 - dev: false - /@hapi/somever@4.1.1: - resolution: {integrity: sha512-lt3QQiDDOVRatS0ionFDNrDIv4eXz58IibQaZQDOg4DqqdNme8oa0iPWcE0+hkq/KTeBCPtEOjDOBKBKwDumVg==} + '@hapi/somever@4.1.1': dependencies: '@hapi/bounce': 3.0.1 '@hapi/hoek': 11.0.4 - dev: false - /@hapi/statehood@8.1.1: - resolution: {integrity: sha512-YbK7PSVUA59NArAW5Np0tKRoIZ5VNYUicOk7uJmWZF6XyH5gGL+k62w77SIJb0AoAJ0QdGQMCQ/WOGL1S3Ydow==} + '@hapi/statehood@8.1.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/bounce': 3.0.1 @@ -280,10 +1508,8 @@ packages: '@hapi/hoek': 11.0.4 '@hapi/iron': 7.0.1 '@hapi/validate': 2.0.1 - dev: false - /@hapi/subtext@8.1.0: - resolution: {integrity: sha512-PyaN4oSMtqPjjVxLny1k0iYg4+fwGusIhaom9B2StinBclHs7v46mIW706Y+Wo21lcgulGyXbQrmT/w4dus6ww==} + '@hapi/subtext@8.1.0': dependencies: '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 @@ -292,140 +1518,85 @@ packages: '@hapi/hoek': 11.0.4 '@hapi/pez': 6.1.0 '@hapi/wreck': 18.0.1 - dev: false - /@hapi/teamwork@6.0.0: - resolution: {integrity: sha512-05HumSy3LWfXpmJ9cr6HzwhAavrHkJ1ZRCmNE2qJMihdM5YcWreWPfyN0yKT2ZjCM92au3ZkuodjBxOibxM67A==} - engines: {node: '>=14.0.0'} - dev: false + '@hapi/teamwork@6.0.0': {} - /@hapi/topo@6.0.2: - resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==} + '@hapi/topo@6.0.2': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/validate@2.0.1: - resolution: {integrity: sha512-NZmXRnrSLK8MQ9y/CMqE9WSspgB9xA41/LlYR0k967aSZebWr4yNrpxIbov12ICwKy4APSlWXZga9jN5p6puPA==} + '@hapi/validate@2.0.1': dependencies: '@hapi/hoek': 11.0.4 '@hapi/topo': 6.0.2 - dev: false - /@hapi/vise@5.0.1: - resolution: {integrity: sha512-XZYWzzRtINQLedPYlIkSkUr7m5Ddwlu99V9elh8CSygXstfv3UnWIXT0QD+wmR0VAG34d2Vx3olqcEhRRoTu9A==} + '@hapi/vise@5.0.1': dependencies: '@hapi/hoek': 11.0.4 - dev: false - /@hapi/wreck@18.0.1: - resolution: {integrity: sha512-OLHER70+rZxvDl75xq3xXOfd3e8XIvz8fWY0dqg92UvhZ29zo24vQgfqgHSYhB5ZiuFpSLeriOisAlxAo/1jWg==} + '@hapi/wreck@18.0.1': dependencies: '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 '@hapi/hoek': 11.0.4 - dev: false - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 + strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: false + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true + '@jridgewell/resolve-uri@3.1.2': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + '@jridgewell/sourcemap-codec@1.4.15': {} - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@jridgewell/trace-mapping@0.3.9': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: true - /@lukeed/ms@2.0.2: - resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} - engines: {node: '>=8'} - dev: false + '@lukeed/ms@2.0.2': {} - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: false + '@pkgjs/parseargs@0.11.0': optional: true - /@prisma/client@5.12.1(prisma@5.12.1): - resolution: {integrity: sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==} - engines: {node: '>=16.13'} - requiresBuild: true - peerDependencies: - prisma: '*' - peerDependenciesMeta: - prisma: - optional: true - dependencies: + '@prisma/client@5.12.1(prisma@5.12.1)': + optionalDependencies: prisma: 5.12.1 - dev: false - /@prisma/debug@5.12.1: - resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==} + '@prisma/debug@5.12.1': {} - /@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab: - resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==} + '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': {} - /@prisma/engines@5.12.1: - resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==} - requiresBuild: true + '@prisma/engines@5.12.1': dependencies: '@prisma/debug': 5.12.1 '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab '@prisma/fetch-engine': 5.12.1 '@prisma/get-platform': 5.12.1 - /@prisma/fetch-engine@5.12.1: - resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==} + '@prisma/fetch-engine@5.12.1': dependencies: '@prisma/debug': 5.12.1 '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab '@prisma/get-platform': 5.12.1 - /@prisma/get-platform@5.12.1: - resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==} + '@prisma/get-platform@5.12.1': dependencies: '@prisma/debug': 5.12.1 - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true + '@tsconfig/node10@1.0.11': {} - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true + '@tsconfig/node12@1.0.11': {} - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true + '@tsconfig/node14@1.0.3': {} - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true + '@tsconfig/node16@1.0.4': {} - /@tsoa/cli@6.2.0: - resolution: {integrity: sha512-kzr10MsARpuivJl59XD33+sdMA18Rx9KBu7NCp18nV6kPQ1LDrVBwVgLL96w7lBgUGsCgVJ1/cUePW313uTZCw==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} - hasBin: true + '@tsoa/cli@6.2.0': dependencies: '@tsoa/runtime': 6.2.0 '@types/multer': 1.4.11 @@ -441,11 +1612,8 @@ packages: yargs: 17.7.2 transitivePeerDependencies: - supports-color - dev: false - /@tsoa/runtime@6.2.0: - resolution: {integrity: sha512-iXSi5rDZWcPRcLKa9WaMBUdh4SdDN+9Cmy+R7i/DSCtFtbtUqE+ui+IMV9o6+759N6J3FqGBaPWa9kAtOrL4sA==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + '@tsoa/runtime@6.2.0': dependencies: '@hapi/boom': 10.0.1 '@hapi/hapi': 21.3.7 @@ -456,79 +1624,58 @@ packages: validator: 13.11.0 transitivePeerDependencies: - supports-color - dev: false - /@types/accepts@1.3.7: - resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + '@types/accepts@1.3.7': dependencies: '@types/node': 20.12.2 - dev: false - /@types/body-parser@1.19.5: - resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 '@types/node': 20.12.2 - /@types/connect@3.4.38: - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + '@types/connect@3.4.38': dependencies: '@types/node': 20.12.2 - /@types/content-disposition@0.5.8: - resolution: {integrity: sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==} - dev: false + '@types/content-disposition@0.5.8': {} - /@types/cookies@0.9.0: - resolution: {integrity: sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==} + '@types/cookies@0.9.0': dependencies: '@types/connect': 3.4.38 '@types/express': 4.17.21 '@types/keygrip': 1.0.6 '@types/node': 20.12.2 - dev: false - /@types/cors@2.8.17: - resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/cors@2.8.17': dependencies: '@types/node': 20.12.2 - dev: true - /@types/express-serve-static-core@4.17.43: - resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} + '@types/express-serve-static-core@4.17.43': dependencies: '@types/node': 20.12.2 '@types/qs': 6.9.14 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 - /@types/express@4.17.21: - resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + '@types/express@4.17.21': dependencies: '@types/body-parser': 1.19.5 '@types/express-serve-static-core': 4.17.43 '@types/qs': 6.9.14 '@types/serve-static': 1.15.5 - /@types/http-assert@1.5.5: - resolution: {integrity: sha512-4+tE/lwdAahgZT1g30Jkdm9PzFRde0xwxBNUyRsCitRvCQB90iuA2uJYdUnhnANRcqGXaWOGY4FEoxeElNAK2g==} - dev: false + '@types/http-assert@1.5.5': {} - /@types/http-errors@2.0.4: - resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/http-errors@2.0.4': {} - /@types/keygrip@1.0.6: - resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} - dev: false + '@types/keygrip@1.0.6': {} - /@types/koa-compose@3.2.8: - resolution: {integrity: sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==} + '@types/koa-compose@3.2.8': dependencies: '@types/koa': 2.15.0 - dev: false - /@types/koa@2.15.0: - resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + '@types/koa@2.15.0': dependencies: '@types/accepts': 1.3.7 '@types/content-disposition': 0.5.8 @@ -538,132 +1685,80 @@ packages: '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 '@types/node': 20.12.2 - dev: false - /@types/mime@1.3.5: - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/mime@1.3.5': {} - /@types/mime@4.0.0: - resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==} - deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed. + '@types/mime@4.0.0': dependencies: mime: 4.0.1 - /@types/multer@1.4.11: - resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} + '@types/multer@1.4.11': dependencies: '@types/express': 4.17.21 - dev: false - /@types/node@20.12.2: - resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + '@types/node@20.12.2': dependencies: undici-types: 5.26.5 - /@types/qs@6.9.14: - resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} + '@types/qs@6.9.14': {} - /@types/range-parser@1.2.7: - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/range-parser@1.2.7': {} - /@types/send@0.17.4: - resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 '@types/node': 20.12.2 - /@types/serve-static@1.15.5: - resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + '@types/serve-static@1.15.5': dependencies: '@types/http-errors': 2.0.4 '@types/mime': 4.0.0 '@types/node': 20.12.2 - /@types/swagger-ui-express@4.1.6: - resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + '@types/swagger-ui-express@4.1.6': dependencies: '@types/express': 4.17.21 '@types/serve-static': 1.15.5 - dev: true - /@zxing/text-encoding@0.9.0: - resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==} - requiresBuild: true - dev: false + '@zxing/text-encoding@0.9.0': optional: true - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true + abbrev@1.1.1: {} - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + accepts@1.3.8: dependencies: mime-types: 2.1.35 negotiator: 0.6.3 - dev: false - /acorn-walk@8.3.2: - resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} - engines: {node: '>=0.4.0'} - dev: true + acorn-walk@8.3.2: {} - /acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true + acorn@8.11.3: {} - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false + ansi-regex@5.0.1: {} - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: false + ansi-regex@6.0.1: {} - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: false - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: false + ansi-styles@6.2.1: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: true - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true + arg@4.1.3: {} - /array-buffer-byte-length@1.0.1: - resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} - engines: {node: '>= 0.4'} + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 is-array-buffer: 3.0.4 - dev: false - /array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - dev: false + array-flatten@1.1.1: {} - /array.prototype.map@1.0.7: - resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} - engines: {node: '>= 0.4'} + array.prototype.map@1.0.7: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 @@ -671,11 +1766,8 @@ packages: es-array-method-boxes-properly: 1.0.0 es-object-atoms: 1.0.0 is-string: 1.0.7 - dev: false - /arraybuffer.prototype.slice@1.0.3: - resolution: {integrity: sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==} - engines: {node: '>= 0.4'} + arraybuffer.prototype.slice@1.0.3: dependencies: array-buffer-byte-length: 1.0.1 call-bind: 1.0.7 @@ -685,49 +1777,31 @@ packages: get-intrinsic: 1.2.4 is-array-buffer: 3.0.4 is-shared-array-buffer: 1.0.3 - dev: false - /asn1.js@5.4.1: - resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + asn1.js@5.4.1: dependencies: bn.js: 4.12.0 inherits: 2.0.4 minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 - dev: false - /async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} - dev: false + async@3.2.5: {} - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 - dev: false - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + balanced-match@1.0.2: {} - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true + binary-extensions@2.3.0: {} - /block-stream2@2.1.0: - resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} + block-stream2@2.1.0: dependencies: readable-stream: 3.6.2 - dev: false - /bn.js@4.12.0: - resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - dev: false + bn.js@4.12.0: {} - /body-parser@1.20.2: - resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + body-parser@1.20.2: dependencies: bytes: 3.1.2 content-type: 1.0.5 @@ -743,55 +1817,35 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: false - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: true - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: false - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.0.1 - dev: true - /browser-or-node@2.1.1: - resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} - dev: false + browser-or-node@2.1.1: {} - /buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - dev: false + buffer-crc32@0.2.13: {} - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false + bytes@3.1.2: {} - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} + call-bind@1.0.7: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 function-bind: 1.1.2 get-intrinsic: 1.2.4 set-function-length: 1.2.2 - dev: false - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 braces: 3.0.2 @@ -802,197 +1856,109 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: true - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 - dev: false - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: false - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false + color-name@1.1.4: {} - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: true + concat-map@0.0.1: {} - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + content-disposition@0.5.4: dependencies: safe-buffer: 5.2.1 - dev: false - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - dev: false + content-type@1.0.5: {} - /cookie-signature@1.0.6: - resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} - dev: false + cookie-signature@1.0.6: {} - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: false + cookie@0.6.0: {} - /cors@2.8.5: - resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} - engines: {node: '>= 0.10'} + cors@2.8.5: dependencies: object-assign: 4.1.1 vary: 1.1.2 - dev: false - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true + create-require@1.1.1: {} - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: false - /data-view-buffer@1.0.1: - resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} - engines: {node: '>= 0.4'} + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /data-view-byte-length@1.0.1: - resolution: {integrity: sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==} - engines: {node: '>= 0.4'} + data-view-byte-length@1.0.1: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /data-view-byte-offset@1.0.0: - resolution: {integrity: sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==} - engines: {node: '>= 0.4'} + data-view-byte-offset@1.0.0: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-data-view: 1.0.1 - dev: false - /debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@2.6.9: dependencies: ms: 2.0.0 - dev: false - /debug@4.3.4(supports-color@5.5.0): - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.3.4(supports-color@5.5.0): dependencies: ms: 2.1.2 + optionalDependencies: supports-color: 5.5.0 - /decode-uri-component@0.2.2: - resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} - engines: {node: '>=0.10'} - dev: false + decode-uri-component@0.2.2: {} - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} + define-data-property@1.1.4: dependencies: es-define-property: 1.0.0 es-errors: 1.3.0 gopd: 1.0.1 - dev: false - /define-properties@1.2.1: - resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} - engines: {node: '>= 0.4'} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 has-property-descriptors: 1.0.2 object-keys: 1.1.1 - dev: false - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false + depd@2.0.0: {} - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false + destroy@1.2.0: {} - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true + diff@4.0.2: {} - /dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} - engines: {node: '>=12'} - dev: false + dotenv@16.4.5: {} - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: false + eastasianwidth@0.2.0: {} - /ecdsa-sig-formatter@1.0.11: - resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 - dev: false - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false + ee-first@1.1.1: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false + emoji-regex@8.0.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: false + emoji-regex@9.2.2: {} - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} - dev: false + encodeurl@1.0.2: {} - /es-abstract@1.23.3: - resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} - engines: {node: '>= 0.4'} + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 arraybuffer.prototype.slice: 1.0.3 @@ -1040,11 +2006,8 @@ packages: typed-array-length: 1.0.6 unbox-primitive: 1.0.2 which-typed-array: 1.1.15 - dev: false - /es-aggregate-error@1.0.13: - resolution: {integrity: sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==} - engines: {node: '>= 0.4'} + es-aggregate-error@1.0.13: dependencies: define-data-property: 1.1.4 define-properties: 1.2.1 @@ -1054,26 +2017,16 @@ packages: globalthis: 1.0.3 has-property-descriptors: 1.0.2 set-function-name: 2.0.2 - dev: false - /es-array-method-boxes-properly@1.0.0: - resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} - dev: false + es-array-method-boxes-properly@1.0.0: {} - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} + es-define-property@1.0.0: dependencies: get-intrinsic: 1.2.4 - dev: false - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: false + es-errors@1.3.0: {} - /es-get-iterator@1.1.3: - resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + es-get-iterator@1.1.3: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 @@ -1084,50 +2037,30 @@ packages: is-string: 1.0.7 isarray: 2.0.5 stop-iteration-iterator: 1.0.0 - dev: false - /es-object-atoms@1.0.0: - resolution: {integrity: sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==} - engines: {node: '>= 0.4'} + es-object-atoms@1.0.0: dependencies: es-errors: 1.3.0 - dev: false - /es-set-tostringtag@2.0.3: - resolution: {integrity: sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==} - engines: {node: '>= 0.4'} + es-set-tostringtag@2.0.3: dependencies: get-intrinsic: 1.2.4 has-tostringtag: 1.0.2 hasown: 2.0.2 - dev: false - /es-to-primitive@1.2.1: - resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} - engines: {node: '>= 0.4'} + es-to-primitive@1.2.1: dependencies: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: false - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: false + escalade@3.1.2: {} - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false + escape-html@1.0.3: {} - /etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - dev: false + etag@1.8.1: {} - /express@4.19.2: - resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} - engines: {node: '>= 0.10.0'} + express@4.19.2: dependencies: accepts: 1.3.8 array-flatten: 1.1.1 @@ -1162,40 +2095,25 @@ packages: vary: 1.1.2 transitivePeerDependencies: - supports-color - dev: false - /fast-jwt@4.0.0: - resolution: {integrity: sha512-CnI93Tmk7eSzfw4e0Jlc5ZcWiN+/zK7xAKAhtXS8PAcKmYqfcXqxJl1hMyhk3iEt0M9JLo7DCYRDV2XcIacWAw==} - engines: {node: '>=16 <22'} + fast-jwt@4.0.0: dependencies: '@lukeed/ms': 2.0.2 asn1.js: 5.4.1 ecdsa-sig-formatter: 1.0.11 mnemonist: 0.39.8 - dev: false - /fast-xml-parser@4.3.6: - resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} - hasBin: true + fast-xml-parser@4.3.6: dependencies: strnum: 1.0.5 - dev: false - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 - dev: true - /filter-obj@1.1.0: - resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} - engines: {node: '>=0.10.0'} - dev: false + filter-obj@1.1.0: {} - /finalhandler@1.2.0: - resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} - engines: {node: '>= 0.8'} + finalhandler@1.2.0: dependencies: debug: 2.6.9 encodeurl: 1.0.2 @@ -1206,132 +2124,79 @@ packages: unpipe: 1.0.0 transitivePeerDependencies: - supports-color - dev: false - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + for-each@0.3.3: dependencies: is-callable: 1.2.7 - dev: false - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} + foreground-child@3.1.1: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: false - /forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - dev: false + forwarded@0.2.0: {} - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false + fresh@0.5.2: {} - /fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} + fs-extra@11.2.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: false - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true + fsevents@2.3.3: optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false + function-bind@1.1.2: {} - /function.prototype.name@1.1.6: - resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} - engines: {node: '>= 0.4'} + function.prototype.name@1.1.6: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 functions-have-names: 1.2.3 - dev: false - /functions-have-names@1.2.3: - resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: false + functions-have-names@1.2.3: {} - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: false + get-caller-file@2.0.5: {} - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} + get-intrinsic@1.2.4: dependencies: es-errors: 1.3.0 function-bind: 1.1.2 has-proto: 1.0.3 has-symbols: 1.0.3 hasown: 2.0.2 - dev: false - /get-symbol-description@1.0.2: - resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} - engines: {node: '>= 0.4'} + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 - dev: false - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: true - /glob@10.3.12: - resolution: {integrity: sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + glob@10.3.12: dependencies: foreground-child: 3.1.1 jackspeak: 2.3.6 minimatch: 9.0.4 minipass: 7.0.4 path-scurry: 1.10.2 - dev: false - /globalthis@1.0.3: - resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} - engines: {node: '>= 0.4'} + globalthis@1.0.3: dependencies: define-properties: 1.2.1 - dev: false - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 - dev: false - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - dev: false + graceful-fs@4.2.11: {} - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true + handlebars@4.7.8: dependencies: minimist: 1.2.8 neo-async: 2.6.2 @@ -1339,378 +2204,207 @@ packages: wordwrap: 1.0.0 optionalDependencies: uglify-js: 3.17.4 - dev: false - /has-bigints@1.0.2: - resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: false + has-bigints@1.0.2: {} - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + has-flag@3.0.0: {} - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 - dev: false - /has-proto@1.0.3: - resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} - engines: {node: '>= 0.4'} - dev: false + has-proto@1.0.3: {} - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false + has-symbols@1.0.3: {} - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} + has-tostringtag@1.0.2: dependencies: has-symbols: 1.0.3 - dev: false - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} + hasown@2.0.2: dependencies: function-bind: 1.1.2 - dev: false - /hpagent@1.2.0: - resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} - engines: {node: '>=14'} - dev: false + hpagent@1.2.0: {} - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} + http-errors@2.0.0: dependencies: depd: 2.0.0 inherits: 2.0.4 setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: false - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 - dev: false - /ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - dev: true + ignore-by-default@1.0.1: {} - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false + inherits@2.0.4: {} - /internal-slot@1.0.7: - resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} - engines: {node: '>= 0.4'} + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 hasown: 2.0.2 side-channel: 1.0.6 - dev: false - /ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - dev: false + ipaddr.js@1.9.1: {} - /ipaddr.js@2.1.0: - resolution: {integrity: sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==} - engines: {node: '>= 10'} - dev: false + ipaddr.js@2.1.0: {} - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} + is-arguments@1.1.1: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-array-buffer@3.0.4: - resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} - engines: {node: '>= 0.4'} + is-array-buffer@3.0.4: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 - dev: false - /is-bigint@1.0.4: - resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 - dev: false - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 - dev: true - /is-boolean-object@1.1.2: - resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} - engines: {node: '>= 0.4'} + is-boolean-object@1.1.2: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: false + is-callable@1.2.7: {} - /is-data-view@1.0.1: - resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} - engines: {node: '>= 0.4'} + is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 - dev: false - /is-date-object@1.0.5: - resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} - engines: {node: '>= 0.4'} + is-date-object@1.0.5: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false + is-fullwidth-code-point@3.0.0: {} - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} + is-generator-function@1.0.10: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: true - /is-map@2.0.3: - resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} - engines: {node: '>= 0.4'} - dev: false + is-map@2.0.3: {} - /is-negative-zero@2.0.3: - resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} - engines: {node: '>= 0.4'} - dev: false + is-negative-zero@2.0.3: {} - /is-number-object@1.0.7: - resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} - engines: {node: '>= 0.4'} + is-number-object@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true + is-number@7.0.0: {} - /is-regex@1.1.4: - resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} - engines: {node: '>= 0.4'} + is-regex@1.1.4: dependencies: call-bind: 1.0.7 has-tostringtag: 1.0.2 - dev: false - /is-set@2.0.3: - resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} - engines: {node: '>= 0.4'} - dev: false + is-set@2.0.3: {} - /is-shared-array-buffer@1.0.3: - resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} - engines: {node: '>= 0.4'} + is-shared-array-buffer@1.0.3: dependencies: call-bind: 1.0.7 - dev: false - /is-string@1.0.7: - resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} - engines: {node: '>= 0.4'} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 - dev: false - /is-symbol@1.0.4: - resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} - engines: {node: '>= 0.4'} + is-symbol@1.0.4: dependencies: has-symbols: 1.0.3 - dev: false - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} + is-typed-array@1.1.13: dependencies: which-typed-array: 1.1.15 - dev: false - /is-weakref@1.0.2: - resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + is-weakref@1.0.2: dependencies: call-bind: 1.0.7 - dev: false - /is-what@4.1.16: - resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} - engines: {node: '>=12.13'} - dev: false + is-what@4.1.16: {} - /isarray@2.0.5: - resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: false + isarray@2.0.5: {} - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false + isexe@2.0.0: {} - /iterate-iterator@1.0.2: - resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} - dev: false + iterate-iterator@1.0.2: {} - /iterate-value@1.0.2: - resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==} + iterate-value@1.0.2: dependencies: es-get-iterator: 1.1.3 iterate-iterator: 1.0.2 - dev: false - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} + jackspeak@2.3.6: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: false - /json-stream@1.0.0: - resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} - dev: false + json-stream@1.0.0: {} - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + jsonfile@6.1.0: dependencies: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: false - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: false + lodash@4.17.21: {} - /lru-cache@10.2.0: - resolution: {integrity: sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==} - engines: {node: 14 || >=16.14} - dev: false + lru-cache@10.2.0: {} - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} + lru-cache@6.0.0: dependencies: yallist: 4.0.0 - dev: true - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true + make-error@1.3.6: {} - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: false + media-typer@0.3.0: {} - /merge-anything@5.1.7: - resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} - engines: {node: '>=12.13'} + merge-anything@5.1.7: dependencies: is-what: 4.1.16 - dev: false - /merge-descriptors@1.0.1: - resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} - dev: false + merge-descriptors@1.0.1: {} - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: false + methods@1.1.2: {} - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: false + mime-db@1.52.0: {} - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} + mime-types@2.1.35: dependencies: mime-db: 1.52.0 - dev: false - /mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - dev: false + mime@1.6.0: {} - /mime@4.0.1: - resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==} - engines: {node: '>=16'} - hasBin: true + mime@4.0.1: {} - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: false + minimalistic-assert@1.0.1: {} - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 - dev: true - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 - dev: false - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - dev: false + minimist@1.2.8: {} - /minio@7.1.3: - resolution: {integrity: sha512-xPrLjWkTT5E7H7VnzOjF//xBp9I40jYB4aWhb2xTFopXXfw+Wo82DDWngdUju7Doy3Wk7R8C4LAgwhLHHnf0wA==} - engines: {node: ^16 || ^18 || >=20} + minio@7.1.3: dependencies: async: 3.2.5 block-stream2: 2.1.0 @@ -1726,43 +2420,24 @@ packages: web-encoding: 1.1.5 xml: 1.0.1 xml2js: 0.5.0 - dev: false - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: false + minipass@7.0.4: {} - /mnemonist@0.39.8: - resolution: {integrity: sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==} + mnemonist@0.39.8: dependencies: obliterator: 2.0.4 - dev: false - /ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - dev: false + ms@2.0.0: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + ms@2.1.2: {} - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: false + ms@2.1.3: {} - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: false + negotiator@0.6.3: {} - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: false + neo-async@2.6.2: {} - /nodemon@3.1.0: - resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} - engines: {node: '>=10'} - hasBin: true + nodemon@3.1.3: dependencies: chokidar: 3.6.0 debug: 4.3.4(supports-color@5.5.0) @@ -1774,104 +2449,54 @@ packages: supports-color: 5.5.0 touch: 3.1.0 undefsafe: 2.0.5 - dev: true - /nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true + nopt@1.0.10: dependencies: abbrev: 1.1.1 - dev: true - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true + normalize-path@3.0.0: {} - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false + object-assign@4.1.1: {} - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: false + object-inspect@1.13.1: {} - /object-keys@1.1.1: - resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} - engines: {node: '>= 0.4'} - dev: false + object-keys@1.1.1: {} - /object.assign@4.1.5: - resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} - engines: {node: '>= 0.4'} + object.assign@4.1.5: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: false - /obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - dev: false + obliterator@2.0.4: {} - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} + on-finished@2.4.1: dependencies: ee-first: 1.1.1 - dev: false - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false + parseurl@1.3.3: {} - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: false + path-key@3.1.1: {} - /path-scurry@1.10.2: - resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} - engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.10.2: dependencies: lru-cache: 10.2.0 minipass: 7.0.4 - dev: false - /path-to-regexp@0.1.7: - resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} - dev: false + path-to-regexp@0.1.7: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true + picomatch@2.3.1: {} - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: false + possible-typed-array-names@1.0.0: {} - /prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} - engines: {node: '>=14'} - hasBin: true - dev: true + prettier@3.2.5: {} - /prisma@5.12.1: - resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==} - engines: {node: '>=16.13'} - hasBin: true - requiresBuild: true + prisma@5.12.1: dependencies: '@prisma/engines': 5.12.1 - /promise.any@2.0.6: - resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} - engines: {node: '>= 0.4'} + promise.any@2.0.6: dependencies: array.prototype.map: 1.0.7 call-bind: 1.0.7 @@ -1880,133 +2505,81 @@ packages: es-aggregate-error: 1.0.13 get-intrinsic: 1.2.4 iterate-value: 1.0.2 - dev: false - /proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 ipaddr.js: 1.9.1 - dev: false - /pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - dev: true + pstree.remy@1.1.8: {} - /qs@6.11.0: - resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} - engines: {node: '>=0.6'} + qs@6.11.0: dependencies: side-channel: 1.0.6 - dev: false - /query-string@7.1.3: - resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} - engines: {node: '>=6'} + query-string@7.1.3: dependencies: decode-uri-component: 0.2.2 filter-obj: 1.1.0 split-on-first: 1.1.0 strict-uri-encode: 2.0.0 - dev: false - /range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - dev: false + range-parser@1.2.1: {} - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} + raw-body@2.5.2: dependencies: bytes: 3.1.2 http-errors: 2.0.0 iconv-lite: 0.4.24 unpipe: 1.0.0 - dev: false - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - dev: false - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@3.6.0: dependencies: picomatch: 2.3.1 - dev: true - /reflect-metadata@0.2.2: - resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} - dev: false + reflect-metadata@0.2.2: {} - /regexp.prototype.flags@1.5.2: - resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} - engines: {node: '>= 0.4'} + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-errors: 1.3.0 set-function-name: 2.0.2 - dev: false - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: false + require-directory@2.1.1: {} - /safe-array-concat@1.1.2: - resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} - engines: {node: '>=0.4'} + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 get-intrinsic: 1.2.4 has-symbols: 1.0.3 isarray: 2.0.5 - dev: false - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - dev: false + safe-buffer@5.2.1: {} - /safe-regex-test@1.0.3: - resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} - engines: {node: '>= 0.4'} + safe-regex-test@1.0.3: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-regex: 1.1.4 - dev: false - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false + safer-buffer@2.1.2: {} - /sax@1.3.0: - resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} - dev: false + sax@1.3.0: {} - /secure-json-parse@2.7.0: - resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} - dev: false + secure-json-parse@2.7.0: {} - /semver@7.6.0: - resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} - engines: {node: '>=10'} - hasBin: true + semver@7.6.0: dependencies: lru-cache: 6.0.0 - dev: true - /send@0.18.0: - resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} - engines: {node: '>= 0.8.0'} + send@0.18.0: dependencies: debug: 2.6.9 depd: 2.0.0 @@ -2023,11 +2596,8 @@ packages: statuses: 2.0.1 transitivePeerDependencies: - supports-color - dev: false - /serve-static@1.15.0: - resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} - engines: {node: '>= 0.8.0'} + serve-static@1.15.0: dependencies: encodeurl: 1.0.2 escape-html: 1.0.3 @@ -2035,11 +2605,8 @@ packages: send: 0.18.0 transitivePeerDependencies: - supports-color - dev: false - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} + set-function-length@1.2.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 @@ -2047,215 +2614,120 @@ packages: get-intrinsic: 1.2.4 gopd: 1.0.1 has-property-descriptors: 1.0.2 - dev: false - /set-function-name@2.0.2: - resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} - engines: {node: '>= 0.4'} + set-function-name@2.0.2: dependencies: define-data-property: 1.1.4 es-errors: 1.3.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.2 - dev: false - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false + setprototypeof@1.2.0: {} - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: false - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: false + shebang-regex@3.0.0: {} - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} + side-channel@1.0.6: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 get-intrinsic: 1.2.4 object-inspect: 1.13.1 - dev: false - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: false + signal-exit@4.1.0: {} - /simple-update-notifier@2.0.0: - resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} - engines: {node: '>=10'} + simple-update-notifier@2.0.0: dependencies: semver: 7.6.0 - dev: true - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: false + source-map@0.6.1: {} - /split-on-first@1.1.0: - resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} - engines: {node: '>=6'} - dev: false + split-on-first@1.1.0: {} - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false + statuses@2.0.1: {} - /stop-iteration-iterator@1.0.0: - resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} - engines: {node: '>= 0.4'} + stop-iteration-iterator@1.0.0: dependencies: internal-slot: 1.0.7 - dev: false - /strict-uri-encode@2.0.0: - resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} - engines: {node: '>=4'} - dev: false + strict-uri-encode@2.0.0: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: false - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: false - /string.prototype.trim@1.2.9: - resolution: {integrity: sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==} - engines: {node: '>= 0.4'} + string.prototype.trim@1.2.9: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-abstract: 1.23.3 es-object-atoms: 1.0.0 - dev: false - /string.prototype.trimend@1.0.8: - resolution: {integrity: sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==} + string.prototype.trimend@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false - /string.prototype.trimstart@1.0.8: - resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} - engines: {node: '>= 0.4'} + string.prototype.trimstart@1.0.8: dependencies: call-bind: 1.0.7 define-properties: 1.2.1 es-object-atoms: 1.0.0 - dev: false - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - dev: false - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: false - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.0.1 - dev: false - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false + strnum@1.0.5: {} - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 - /swagger-ui-dist@5.13.0: - resolution: {integrity: sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==} - dev: false + swagger-ui-dist@5.13.0: {} - /swagger-ui-express@5.0.0(express@4.19.2): - resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} - engines: {node: '>= v0.10.32'} - peerDependencies: - express: '>=4.0.0 || >=5.0.0-beta' + swagger-ui-express@5.0.0(express@4.19.2): dependencies: express: 4.19.2 swagger-ui-dist: 5.13.0 - dev: false - /through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + through2@4.0.2: dependencies: readable-stream: 3.6.2 - dev: false - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: true - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: false + toidentifier@1.0.1: {} - /touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} - hasBin: true + touch@3.1.0: dependencies: nopt: 1.0.10 - dev: true - /ts-deepmerge@7.0.0: - resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} - engines: {node: '>=14.13.1'} - dev: false + ts-deepmerge@7.0.0: {} - /ts-node@10.9.2(@types/node@20.12.2)(typescript@5.4.3): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true + ts-node@10.9.2(@types/node@20.12.2)(typescript@5.4.3): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 @@ -2272,54 +2744,36 @@ packages: typescript: 5.4.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: true - /tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: false + tslib@2.6.2: {} - /tsoa@6.2.0: - resolution: {integrity: sha512-EX/RyoU+4hD1rLM5NjYG+I7lEhqx1yuLgcHs/gyWQpkX/RL9cVR9hFA9LKQrK6PE+WTg1SEahn1MK3l/+6pVKw==} - engines: {node: '>=18.0.0', yarn: '>=1.9.4'} - hasBin: true + tsoa@6.2.0: dependencies: '@tsoa/cli': 6.2.0 '@tsoa/runtime': 6.2.0 transitivePeerDependencies: - supports-color - dev: false - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} + type-is@1.6.18: dependencies: media-typer: 0.3.0 mime-types: 2.1.35 - dev: false - /typed-array-buffer@1.0.2: - resolution: {integrity: sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==} - engines: {node: '>= 0.4'} + typed-array-buffer@1.0.2: dependencies: call-bind: 1.0.7 es-errors: 1.3.0 is-typed-array: 1.1.13 - dev: false - /typed-array-byte-length@1.0.1: - resolution: {integrity: sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==} - engines: {node: '>= 0.4'} + typed-array-byte-length@1.0.1: dependencies: call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: false - /typed-array-byte-offset@1.0.2: - resolution: {integrity: sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==} - engines: {node: '>= 0.4'} + typed-array-byte-offset@1.0.2: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 @@ -2327,11 +2781,8 @@ packages: gopd: 1.0.1 has-proto: 1.0.3 is-typed-array: 1.1.13 - dev: false - /typed-array-length@1.0.6: - resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==} - engines: {node: '>= 0.4'} + typed-array-length@1.0.6: dependencies: call-bind: 1.0.7 for-each: 0.3.3 @@ -2339,184 +2790,105 @@ packages: has-proto: 1.0.3 is-typed-array: 1.1.13 possible-typed-array-names: 1.0.0 - dev: false - /typescript@5.4.3: - resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==} - engines: {node: '>=14.17'} - hasBin: true + typescript@5.4.3: {} - /uglify-js@3.17.4: - resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: false + uglify-js@3.17.4: optional: true - /unbox-primitive@1.0.2: - resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + unbox-primitive@1.0.2: dependencies: call-bind: 1.0.7 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: false - /undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - dev: true + undefsafe@2.0.5: {} - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@5.26.5: {} - /undici@6.11.1: - resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} - engines: {node: '>=18.0'} - dev: false + undici@6.11.1: {} - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: false + universalify@2.0.1: {} - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: false + unpipe@1.0.0: {} - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - dev: false + util-deprecate@1.0.2: {} - /util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} + util@0.12.5: dependencies: inherits: 2.0.4 is-arguments: 1.1.1 is-generator-function: 1.0.10 is-typed-array: 1.1.13 which-typed-array: 1.1.15 - dev: false - /utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - dev: false + utils-merge@1.0.1: {} - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true + v8-compile-cache-lib@3.0.1: {} - /validator@13.11.0: - resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} - engines: {node: '>= 0.10'} - dev: false + validator@13.11.0: {} - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: false + vary@1.1.2: {} - /web-encoding@1.1.5: - resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + web-encoding@1.1.5: dependencies: util: 0.12.5 optionalDependencies: '@zxing/text-encoding': 0.9.0 - dev: false - /which-boxed-primitive@1.0.2: - resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 - dev: false - /which-typed-array@1.1.15: - resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} - engines: {node: '>= 0.4'} + which-typed-array@1.1.15: dependencies: available-typed-arrays: 1.0.7 call-bind: 1.0.7 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.2 - dev: false - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: false - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: false + wordwrap@1.0.0: {} - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: false - /xml2js@0.5.0: - resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} - engines: {node: '>=4.0.0'} + xml2js@0.5.0: dependencies: sax: 1.3.0 xmlbuilder: 11.0.1 - dev: false - /xml@1.0.1: - resolution: {integrity: sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==} - dev: false + xml@1.0.1: {} - /xmlbuilder@11.0.1: - resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} - engines: {node: '>=4.0'} - dev: false + xmlbuilder@11.0.1: {} - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: false + y18n@5.0.8: {} - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: true + yallist@4.0.0: {} - /yaml@2.4.1: - resolution: {integrity: sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==} - engines: {node: '>= 14'} - hasBin: true - dev: false + yaml@2.4.1: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false + yargs-parser@21.1.1: {} - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} + yargs@17.7.2: dependencies: cliui: 8.0.1 escalade: 3.1.2 @@ -2525,9 +2897,5 @@ packages: string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 21.1.1 - dev: false - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true + yn@3.1.1: {} From e6dd2c6e6ee62b9179d014bfae159f2f4da33f2f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:16:40 +0700 Subject: [PATCH 067/157] feat: scope type by productGroupId --- src/controllers/product/type-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index c450cd5..9f02628 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -43,8 +43,9 @@ export class ProductType extends Controller { } @Get() - async getProductType(@Query() query: string = "") { + async getProductType(@Query() query: string = "", @Query() productGroupId?: string) { const where = { + AND: { productGroupId }, OR: [{ name: { contains: query } }, { detail: { contains: query } }], } satisfies Prisma.ProductTypeWhereInput; const result = prisma.productType.findMany({ orderBy: { createdAt: "asc" }, where }); From 4c60c81bace91ce7277e52e3dc9fb2c75940eed0 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:42:03 +0700 Subject: [PATCH 068/157] fix: wrong table ref --- src/controllers/product/type-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 9f02628..2395b96 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -118,7 +118,7 @@ export class ProductType extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); } - const record = await prisma.work.update({ + const record = await prisma.productType.update({ data: { ...body, updateBy: req.user.name }, where: { id: typeId }, }); From f1245316a21e6ee9da228d692aa3b922f1166944 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 13:46:22 +0700 Subject: [PATCH 069/157] feat: prevent invalid groupId sent --- src/controllers/product/type-controller.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 2395b96..ef859da 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -114,6 +114,17 @@ export class ProductType extends Controller { @Body() body: ProductTypeUpdate, @Path() typeId: string, ) { + if ( + body.productGroupId && + !(await prisma.productType.findFirst({ where: { id: body.productGroupId } })) + ) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product group cannot be found.", + "missing_or_invalid_parameter", + ); + } + if (!(await prisma.productType.findUnique({ where: { id: typeId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); } From fc8e81b780200e1a85e35560ea3a8c42b3477c9d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:08:18 +0700 Subject: [PATCH 070/157] feat: add count of relation(s) to each record --- src/controllers/customer-branch-controller.ts | 1 + src/controllers/customer-controller.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 3801f19..39e0848 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -134,6 +134,7 @@ export class CustomerBranchController extends Controller { province: true, district: true, subDistrict: true, + _count: true, }, where, take: pageSize, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index a037e22..251146a 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -152,6 +152,7 @@ export class CustomerController extends Controller { const [result, total] = await prisma.$transaction([ prisma.customer.findMany({ include: { + _count: true, branch: includeBranch ? { include: { From 0bca85d4603e32a469239b70d8d8943d4a87ed61 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:41:07 +0700 Subject: [PATCH 071/157] feat: return only one record --- src/controllers/employee-other-info-controller.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index 58e0ff5..3cb6284 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -38,23 +38,12 @@ type EmployeeOtherInfoPayload = { export class EmployeeOtherInfo extends Controller { @Get() async list(@Path() employeeId: string) { - return prisma.employeeOtherInfo.findMany({ + return prisma.employeeOtherInfo.findFirst({ orderBy: { createdAt: "asc" }, where: { employeeId }, }); } - @Get("{otherInfoId}") - async getById(@Path() employeeId: string, @Path() otherInfoId: string) { - const record = await prisma.employeeOtherInfo.findFirst({ - where: { id: otherInfoId, employeeId }, - }); - if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee info cannot be found.", "data_not_found"); - } - return record; - } - @Post() async create( @Request() req: RequestWithUser, From fc2d06ad5d57fdad32881a2e71d365008be58b2f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 15:52:57 +0700 Subject: [PATCH 072/157] feat: count employee by gender --- src/controllers/employee-controller.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 8b29f8a..54d90cf 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -209,6 +209,22 @@ export class EmployeeController extends Controller { }); } + @Get("stats/gender") + async getEmployeeStatsGender(@Query() customerBranchId?: string) { + return await prisma.employee + .groupBy({ + _count: true, + by: ["gender"], + where: { customerBranchId }, + }) + .then((res) => + res.reduce>((a, c) => { + a[c.gender] = c._count; + return a; + }, {}), + ); + } + @Get() async list( @Query() zipCode?: string, From 28d002ad65c67fcda9be2c07bfe1f4f25c2567f1 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:16:06 +0700 Subject: [PATCH 073/157] feat: product endpoints --- src/controllers/product/product-controller.ts | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 src/controllers/product/product-controller.ts diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts new file mode 100644 index 0000000..8b8fbbe --- /dev/null +++ b/src/controllers/product/product-controller.ts @@ -0,0 +1,244 @@ +import { + Body, + Controller, + Delete, + Get, + Put, + Path, + Post, + Request, + Route, + Security, + Tags, + Queries, +} from "tsoa"; +import { Prisma, Status } from "@prisma/client"; + +import prisma from "../../db"; +import minio, { presignedGetObjectIfExist } from "../../services/minio"; +import { RequestWithUser } from "../../interfaces/user"; +import HttpError from "../../interfaces/http-error"; +import HttpStatus from "../../interfaces/http-status"; + +if (!process.env.MINIO_BUCKET) { + throw Error("Require MinIO bucket."); +} + +const MINIO_BUCKET = process.env.MINIO_BUCKET; + +type ProductCreate = { + code: "AC" | "DO" | "ac" | "do"; + name: string; + detail: string; + process: string; + price: number; + agentPrice: number; + serviceCharge: number; + attributes?: { + [key: string]: Date | string | number | null; + }; +}; + +type ProductUpdate = { + name: string; + detail: string; + process?: string; + price: number; + agentPrice: number; + serviceCharge: number; + attributes?: { + [key: string]: Date | string | number | null; + }; +}; + +function imageLocation(id: string) { + return `product/${id}/image`; +} + +@Route("api/v1/product") +@Tags("Product") +@Security("keycloak") +export class ProductController extends Controller { + @Get() + async getProduct( + @Queries() + qs: { + query?: string; + page?: number; + pageSize?: number; + filter?: string[]; + }, + ) { + qs.page = qs.page ?? 1; + qs.pageSize = qs.pageSize ?? 30; + qs.query = qs.query ?? ""; + + const { query, page, pageSize, filter } = qs; + + const where = { + OR: [{ name: { contains: query } }, { detail: { contains: query } }], + AND: filter + ?.map((v) => { + const match = /[\w\-]+:[\W\w]+$/.exec(v); + + if (!match) return []; + + const [key, ...rest] = v.split(":"); + const val = rest.join(); + + return { + OR: [ + { + attributes: { + path: [key], + string_contains: val, + }, + }, + { + attributes: { + path: [key], + equals: Number.isFinite(+val) + ? +val + : val === "true" + ? true + : val === "false" + ? false + : val, + }, + }, + ], + }; + }) + .flat(), + } satisfies Prisma.ProductWhereInput; + + const [result, total] = await prisma.$transaction([ + prisma.product.findMany({ + orderBy: { createdAt: "asc" }, + where, + take: pageSize, + skip: (page - 1) * pageSize, + }), + prisma.product.count({ where }), + ]); + + return { + result: await Promise.all( + result.map(async (v) => ({ + ...v, + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), + })), + ), + page, + pageSize, + total, + }; + } + + @Get("{productId}") + async getProductById(@Path() productId: string) { + const record = await prisma.product.findFirst({ + where: { id: productId }, + }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + } + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), + }); + } + + @Post() + async createProduct(@Request() req: RequestWithUser, @Body() body: ProductCreate) { + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `PRODUCT_${body.code.toLocaleUpperCase()}`, + }, + create: { + key: `PRODUCT_${body.code.toLocaleUpperCase()}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + return await prisma.product.create({ + data: { + ...body, + code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, + attributes: body.attributes, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + }, + { + isolationLevel: Prisma.TransactionIsolationLevel.Serializable, + }, + ); + + this.setStatus(HttpStatus.CREATED); + + return Object.assign(record, { + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + imageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Put("{productId}") + async editProduct( + @Request() req: RequestWithUser, + @Body() body: ProductUpdate, + @Path() productId: string, + ) { + if (!(await prisma.product.findUnique({ where: { id: productId } }))) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + } + + const record = await prisma.product.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: productId }, + }); + return Object.assign(record, { + profileImageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + profileImageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); + } + + @Delete("{productId}") + async deleteProduct(@Path() productId: string) { + const record = await prisma.product.findFirst({ where: { id: productId } }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + } + + if (record.status !== Status.CREATED) { + throw new HttpError(HttpStatus.FORBIDDEN, "Product is in used.", "data_in_used"); + } + + return await prisma.product.delete({ where: { id: productId } }); + } +} From 31ed48d190675aa810db6ac3df478735cd2961b5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 14:09:08 +0700 Subject: [PATCH 074/157] chore: update migration --- .../migration.sql | 36 ++++++++++++++++ .../migration.sql | 8 ++++ .../migration.sql | 18 ++++++++ prisma/schema.prisma | 42 +++++++++++++------ 4 files changed, 91 insertions(+), 13 deletions(-) create mode 100644 prisma/migrations/20240612042722_overhaul_service_table/migration.sql create mode 100644 prisma/migrations/20240612045512_remove_order_from_work/migration.sql create mode 100644 prisma/migrations/20240612065711_composite_key_m2m/migration.sql diff --git a/prisma/migrations/20240612042722_overhaul_service_table/migration.sql b/prisma/migrations/20240612042722_overhaul_service_table/migration.sql new file mode 100644 index 0000000..3549d90 --- /dev/null +++ b/prisma/migrations/20240612042722_overhaul_service_table/migration.sql @@ -0,0 +1,36 @@ +/* + Warnings: + + - You are about to drop the column `serviceId` on the `Work` table. All the data in the column will be lost. + - Added the required column `order` to the `WorkProduct` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "Work" DROP CONSTRAINT "Work_serviceId_fkey"; + +-- AlterTable +ALTER TABLE "Work" DROP COLUMN "serviceId"; + +-- AlterTable +ALTER TABLE "WorkProduct" ADD COLUMN "order" INTEGER NOT NULL; + +-- CreateTable +CREATE TABLE "WorkService" ( + "id" TEXT NOT NULL, + "order" INTEGER NOT NULL, + "workId" TEXT NOT NULL, + "serviceId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updateBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + "productId" TEXT, + + CONSTRAINT "WorkService_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "WorkService" ADD CONSTRAINT "WorkService_workId_fkey" FOREIGN KEY ("workId") REFERENCES "Work"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "WorkService" ADD CONSTRAINT "WorkService_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240612045512_remove_order_from_work/migration.sql b/prisma/migrations/20240612045512_remove_order_from_work/migration.sql new file mode 100644 index 0000000..7255159 --- /dev/null +++ b/prisma/migrations/20240612045512_remove_order_from_work/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `order` on the `Work` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Work" DROP COLUMN "order"; diff --git a/prisma/migrations/20240612065711_composite_key_m2m/migration.sql b/prisma/migrations/20240612065711_composite_key_m2m/migration.sql new file mode 100644 index 0000000..027089e --- /dev/null +++ b/prisma/migrations/20240612065711_composite_key_m2m/migration.sql @@ -0,0 +1,18 @@ +/* + Warnings: + + - The primary key for the `WorkProduct` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `id` on the `WorkProduct` table. All the data in the column will be lost. + - The primary key for the `WorkService` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `id` on the `WorkService` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "WorkProduct" DROP CONSTRAINT "WorkProduct_pkey", +DROP COLUMN "id", +ADD CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("workId", "productId"); + +-- AlterTable +ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_pkey", +DROP COLUMN "id", +ADD CONSTRAINT "WorkService_pkey" PRIMARY KEY ("workId", "serviceId"); diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 432e0e6..1f67779 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -547,30 +547,44 @@ model Service { createdAt DateTime @default(now()) updateBy String? updatedAt DateTime @updatedAt - work Work[] + + workOnService WorkService[] } model Work { id String @id @default(uuid()) - order Int - name String - - service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade) - serviceId String + name String status Status @default(CREATED) - createdBy String? - createdAt DateTime @default(now()) - updateBy String? - updatedAt DateTime @updatedAt - WorkProduct WorkProduct[] + createdBy String? + createdAt DateTime @default(now()) + updateBy String? + updatedAt DateTime @updatedAt + + productOnWork WorkProduct[] + serviceOnWork WorkService[] +} + +model WorkService { + order Int + work Work @relation(fields: [workId], references: [id], onDelete: Cascade) + workId String + service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade) + serviceId String + + createdBy String? + createdAt DateTime @default(now()) + updateBy String? + updatedAt DateTime @updatedAt + productId String? + + @@id([workId, serviceId]) } model WorkProduct { - id String @id @default(uuid()) - + order Int work Work @relation(fields: [workId], references: [id], onDelete: Cascade) workId String product Product @relation(fields: [productId], references: [id], onDelete: Cascade) @@ -580,6 +594,8 @@ model WorkProduct { createdAt DateTime @default(now()) updateBy String? updatedAt DateTime @updatedAt + + @@id([workId, productId]) } model ProductGroup { From ee3ae91957113a7dca0f8cd428fc0c982cf58dde Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:32:17 +0700 Subject: [PATCH 075/157] feat: service and product with work relation --- src/controllers/service/service-controller.ts | 118 ++++++++++-- src/controllers/work/work-controller.ts | 171 ++++++++++++++++-- 2 files changed, 259 insertions(+), 30 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index d0a31db..b05120f 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -27,19 +27,20 @@ if (!process.env.MINIO_BUCKET) { const MINIO_BUCKET = process.env.MINIO_BUCKET; type ServiceCreate = { - code: string; + code: "MOU" | "mou"; name: string; detail: string; + workId: string[]; }; type ServiceUpdate = { - code: string; name: string; detail: string; + workId: string[]; }; function imageLocation(id: string) { - return `service/img-${id}`; + return `service/${id}/product-image`; } @Route("api/v1/service") @@ -63,6 +64,13 @@ export class ServiceController extends Controller { const [result, total] = await prisma.$transaction([ prisma.service.findMany({ + include: { + workOnService: { + include: { + service: true, + }, + }, + }, orderBy: { createdAt: "asc" }, where, take: pageSize, @@ -87,6 +95,23 @@ export class ServiceController extends Controller { @Get("{serviceId}") async getServiceById(@Path() serviceId: string) { const record = await prisma.service.findFirst({ + include: { + workOnService: { + orderBy: { order: "asc" }, + include: { + work: { + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { order: "asc" }, + }, + }, + }, + }, + }, + }, where: { id: serviceId }, }); @@ -94,7 +119,7 @@ export class ServiceController extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); return Object.assign(record, { - imageUrl: await minio.presignedGetObject(MINIO_BUCKET, `service/img-${record.id}`, 60 * 60), + imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(record.id), 60 * 60), }); } @@ -104,27 +129,96 @@ export class ServiceController extends Controller { @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const where = { + serviceOnWork: { + some: { serviceId }, + }, + } satisfies Prisma.WorkWhereInput; + const [result, total] = await prisma.$transaction([ prisma.work.findMany({ - where: { serviceId }, + include: { + productOnWork: { + include: { + product: true, + }, + }, + }, + where, take: pageSize, skip: (page - 1) * pageSize, }), - prisma.work.count({ where: { serviceId } }), + prisma.work.count({ where }), ]); return { result, page, pageSize, total }; } @Post() async createService(@Request() req: RequestWithUser, @Body() body: ServiceCreate) { - const record = await prisma.service.create({ - data: { - ...body, - createdBy: req.user.name, - updateBy: req.user.name, - }, + const { workId, ...payload } = body; + + const workList = await prisma.work.findMany({ + where: { id: { in: workId } }, }); + if (workList.length !== workList.length) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Some product not found.", + "missing_or_invalid_parameter", + ); + } + + const record = await prisma.$transaction( + async (tx) => { + const last = await tx.runningNo.upsert({ + where: { + key: `SERVICE_${body.code.toLocaleUpperCase()}`, + }, + create: { + key: `SERVICE_${body.code.toLocaleUpperCase()}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + + return tx.service.create({ + include: { + workOnService: { + orderBy: { order: "asc" }, + include: { + work: { + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { order: "asc" }, + }, + }, + }, + }, + }, + }, + data: { + ...payload, + code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, + workOnService: { + createMany: { + data: workId.map((v, i) => ({ + order: i + 1, + workId: v, + })), + }, + }, + createdBy: req.user.name, + updateBy: req.user.name, + }, + }); + }, + { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, + ); + this.setStatus(HttpStatus.CREATED); return Object.assign(record, { diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index 8df4ddc..8702cf8 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -20,15 +20,13 @@ import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; type WorkCreate = { - order: number; name: string; - serviceId: string; + productId: string[]; }; type WorkUpdate = { - order?: number; name?: string; - serviceId?: string; + productId?: string[]; }; @Route("api/v1/work") @@ -47,8 +45,17 @@ export class WorkController extends Controller { const [result, total] = await prisma.$transaction([ prisma.work.findMany({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, orderBy: { createdAt: "asc" }, - include: { service: true }, where, take: pageSize, skip: (page - 1) * pageSize, @@ -62,7 +69,6 @@ export class WorkController extends Controller { @Get("{workId}") async getWorkById(@Path() workId: string) { const record = await prisma.work.findFirst({ - include: { service: true }, where: { id: workId }, }); @@ -71,6 +77,7 @@ export class WorkController extends Controller { return record; } + @Get("{workId}/product") async getProductOfWork( @Path() workId: string, @@ -81,9 +88,7 @@ export class WorkController extends Controller { const where = { AND: [ { - workProduct: { - some: { workId }, - }, + workProduct: { some: { workId } }, }, { OR: [{ name: { contains: query } }], @@ -107,28 +112,85 @@ export class WorkController extends Controller { @Post() async createWork(@Request() req: RequestWithUser, @Body() body: WorkCreate) { - const service = await prisma.service.findFirst({ - where: { id: body.serviceId }, + const { productId, ...payload } = body; + + const exist = await prisma.work.findFirst({ + include: { + productOnWork: { + include: { + product: true, + }, + }, + }, + where: { + productOnWork: { + every: { + productId: { in: productId }, + }, + }, + NOT: { + OR: [ + { + productOnWork: { + some: { + productId: { notIn: productId }, + }, + }, + }, + { + productOnWork: { + none: {}, + }, + }, + ], + }, + }, }); - if (!service) { + if (exist) return exist; + + const productList = await prisma.product.findMany({ + where: { id: { in: productId } }, + }); + + if (productList.length !== productId.length) { throw new HttpError( HttpStatus.BAD_REQUEST, - "Service not found.", + "Some product not found.", "missing_or_invalid_parameter", ); } const record = await prisma.work.create({ + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, data: { - ...body, + ...payload, + productOnWork: { + createMany: { + data: productId.map((v, i) => ({ + order: i + 1, + productId: v, + createdBy: req.user.name, + updateBy: req.user.name, + })), + }, + }, createdBy: req.user.name, updateBy: req.user.name, }, }); - await prisma.service.updateMany({ - where: { id: service.id }, + await prisma.product.updateMany({ + where: { id: { in: body.productId }, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); @@ -138,18 +200,91 @@ export class WorkController extends Controller { } @Put("{workId}") - async editService( + async editWork( @Request() req: RequestWithUser, @Body() body: WorkUpdate, @Path() workId: string, ) { + const { productId, ...payload } = body; + if (!(await prisma.work.findUnique({ where: { id: workId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); } + const exist = await prisma.work.findFirst({ + include: { + productOnWork: { + include: { + product: true, + }, + }, + }, + where: { + productOnWork: { + every: { + productId: { in: productId }, + }, + }, + NOT: { + OR: [ + { id: workId }, + { + productOnWork: { + some: { + productId: { notIn: productId }, + }, + }, + }, + { + productOnWork: { + none: {}, + }, + }, + ], + }, + }, + }); + + if (exist) return exist; + const record = await prisma.work.update({ - data: { ...body, updateBy: req.user.name }, + include: { + productOnWork: { + include: { + product: true, + }, + orderBy: { + order: "asc", + }, + }, + }, where: { id: workId }, + data: { + ...payload, + productOnWork: productId + ? { + deleteMany: { + productId: { notIn: productId }, + }, + upsert: productId.map((v, i) => ({ + where: { + workId_productId: { + workId, + productId: v, + }, + }, + update: { order: i + 1 }, + create: { + order: i + 1, + productId: v, + createdBy: req.user.name, + updateBy: req.user.name, + }, + })), + } + : undefined, + updateBy: req.user.name, + }, }); return record; From 374644a691326b09908a1eb8160fdb25ce18cadc Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 16:37:56 +0700 Subject: [PATCH 076/157] feat: only get url if object exists --- src/controllers/service/service-controller.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index b05120f..ff8f49c 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -15,7 +15,7 @@ import { import { Prisma, Status } from "@prisma/client"; import prisma from "../../db"; -import minio from "../../services/minio"; +import minio, { presignedGetObjectIfExist } from "../../services/minio"; import { RequestWithUser } from "../../interfaces/user"; import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; @@ -83,7 +83,11 @@ export class ServiceController extends Controller { result: await Promise.all( result.map(async (v) => ({ ...v, - imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(v.id), 12 * 60 * 60), + imageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(v.id), + 12 * 60 * 60, + ), })), ), page, @@ -119,7 +123,7 @@ export class ServiceController extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); return Object.assign(record, { - imageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(record.id), 60 * 60), + imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), }); } @@ -222,7 +226,7 @@ export class ServiceController extends Controller { this.setStatus(HttpStatus.CREATED); return Object.assign(record, { - imageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, @@ -250,12 +254,12 @@ export class ServiceController extends Controller { where: { id: serviceId }, }); return Object.assign(record, { - profileImageUrl: await minio.presignedGetObject( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, ), - profileImageUploadUrl: await minio.presignedPutObject( + imageUploadUrl: await minio.presignedPutObject( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From 119fd02d220fb8598fdcbc2fd5feea626b10e585 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 12 Jun 2024 17:01:42 +0700 Subject: [PATCH 077/157] feat: change some field to optional --- .../migration.sql | 12 +++++++ prisma/schema.prisma | 22 ++++++------ src/controllers/employee-controller.ts | 36 +++++++++---------- 3 files changed, 41 insertions(+), 29 deletions(-) create mode 100644 prisma/migrations/20240612100121_update_field_to_optional/migration.sql diff --git a/prisma/migrations/20240612100121_update_field_to_optional/migration.sql b/prisma/migrations/20240612100121_update_field_to_optional/migration.sql new file mode 100644 index 0000000..72c9e76 --- /dev/null +++ b/prisma/migrations/20240612100121_update_field_to_optional/migration.sql @@ -0,0 +1,12 @@ +-- AlterTable +ALTER TABLE "Employee" ALTER COLUMN "address" DROP NOT NULL, +ALTER COLUMN "addressEN" DROP NOT NULL, +ALTER COLUMN "entryDate" DROP NOT NULL, +ALTER COLUMN "tm6Number" DROP NOT NULL, +ALTER COLUMN "visaExpiryDate" DROP NOT NULL, +ALTER COLUMN "visaIssueDate" DROP NOT NULL, +ALTER COLUMN "visaIssuingPlace" DROP NOT NULL, +ALTER COLUMN "visaNumber" DROP NOT NULL, +ALTER COLUMN "visaStayUntilDate" DROP NOT NULL, +ALTER COLUMN "visaType" DROP NOT NULL, +ALTER COLUMN "workerStatus" DROP NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 1f67779..7a695e3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -415,8 +415,8 @@ model Employee { gender String nationality String - address String - addressEN String + address String? + addressEN String? province Province? @relation(fields: [provinceId], references: [id], onDelete: SetNull) provinceId String? @@ -437,15 +437,15 @@ model Employee { passportIssuingPlace String previousPassportReference String? - visaType String - visaNumber String - visaIssueDate DateTime - visaExpiryDate DateTime - visaIssuingPlace String - visaStayUntilDate DateTime - tm6Number String - entryDate DateTime - workerStatus String + visaType String? + visaNumber String? + visaIssueDate DateTime? + visaExpiryDate DateTime? + visaIssuingPlace String? + visaStayUntilDate DateTime? + tm6Number String? + entryDate DateTime? + workerStatus String? customerBranch CustomerBranch? @relation(fields: [customerBranchId], references: [id], onDelete: SetNull) customerBranchId String? diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 54d90cf..c436d2e 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -57,15 +57,15 @@ type EmployeeCreate = { passportIssuingPlace: string; previousPassportReference?: string; - visaType: string; - visaNumber: string; - visaIssueDate: Date; - visaExpiryDate: Date; - visaIssuingPlace: string; - visaStayUntilDate: Date; - tm6Number: string; - entryDate: Date; - workerStatus: string; + visaType?: string | null; + visaNumber?: string | null; + visaIssueDate?: Date | null; + visaExpiryDate?: Date | null; + visaIssuingPlace?: string | null; + visaStayUntilDate?: Date | null; + tm6Number?: string | null; + entryDate?: Date | null; + workerStatus?: string | null; subDistrictId?: string | null; districtId?: string | null; @@ -140,15 +140,15 @@ type EmployeeUpdate = { passportIssuingPlace?: string; previousPassportReference?: string; - visaType?: string; - visaNumber?: string; - visaIssueDate?: Date; - visaExpiryDate?: Date; - visaIssuingPlace?: string; - visaStayUntilDate?: Date; - tm6Number?: string; - entryDate?: Date; - workerStatus?: string; + visaType?: string | null; + visaNumber?: string | null; + visaIssueDate?: Date | null; + visaExpiryDate?: Date | null; + visaIssuingPlace?: string | null; + visaStayUntilDate?: Date | null; + tm6Number?: string | null; + entryDate?: Date | null; + workerStatus?: string | null; subDistrictId?: string | null; districtId?: string | null; From a16ad32a1fff898af22b26265adb1e4acf525bda Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:05:39 +0700 Subject: [PATCH 078/157] fix: missing image url --- src/controllers/employee-controller.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index c436d2e..c04090b 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -599,7 +599,18 @@ export class EmployeeController extends Controller { this.setStatus(HttpStatus.CREATED); - return record; + return Object.assign(record, { + profileImageUrl: await presignedGetObjectIfExist( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + profileImageUploadUrl: await minio.presignedPutObject( + MINIO_BUCKET, + imageLocation(record.id), + 12 * 60 * 60, + ), + }); } @Delete("{employeeId}") From ea10a5c3d9adff367bf55e5d5beca7a089f7e1d2 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:41:02 +0700 Subject: [PATCH 079/157] feat: also customer all related field --- src/controllers/customer-branch-controller.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 39e0848..ae5c350 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -122,6 +122,19 @@ export class CustomerBranchController extends Controller { { name: { contains: query }, zipCode }, { email: { contains: query }, zipCode }, { code: { contains: query }, zipCode }, + { address: { contains: query }, zipCode }, + { addressEN: { contains: query }, zipCode }, + { province: { name: { contains: query } }, zipCode }, + { province: { nameEN: { contains: query } }, zipCode }, + { district: { name: { contains: query } }, zipCode }, + { district: { nameEN: { contains: query } }, zipCode }, + { subDistrict: { name: { contains: query } }, zipCode }, + { subDistrict: { nameEN: { contains: query } }, zipCode }, + { + customer: { + OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], + }, + }, ], AND: { customerId }, } satisfies Prisma.CustomerBranchWhereInput; From 96618c6e064cf605ed36c15142f74f923f92c3f9 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:47:11 +0700 Subject: [PATCH 080/157] fix: wrong understanding of system --- .../migration.sql | 14 +++++ prisma/schema.prisma | 12 ++-- src/controllers/product/product-controller.ts | 58 ++----------------- src/controllers/service/service-controller.ts | 6 ++ src/controllers/work/work-controller.ts | 6 ++ 5 files changed, 36 insertions(+), 60 deletions(-) create mode 100644 prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql diff --git a/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql b/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql new file mode 100644 index 0000000..cadf124 --- /dev/null +++ b/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql @@ -0,0 +1,14 @@ +/* + Warnings: + + - You are about to drop the column `attributes` on the `Product` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "Product" DROP COLUMN "attributes"; + +-- AlterTable +ALTER TABLE "Service" ADD COLUMN "attributes" JSONB; + +-- AlterTable +ALTER TABLE "Work" ADD COLUMN "attributes" JSONB; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7a695e3..20a2c4e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -537,9 +537,10 @@ model EmployeeOtherInfo { model Service { id String @id @default(uuid()) - code String - name String - detail String + code String + name String + detail String + attributes Json? status Status @default(CREATED) @@ -554,7 +555,8 @@ model Service { model Work { id String @id @default(uuid()) - name String + name String + attributes Json? status Status @default(CREATED) @@ -655,8 +657,6 @@ model Product { workProduct WorkProduct[] - attributes Json? - createdBy String? createdAt DateTime @default(now()) updateBy String? diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 8b8fbbe..59e550e 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -10,7 +10,7 @@ import { Route, Security, Tags, - Queries, + Query, } from "tsoa"; import { Prisma, Status } from "@prisma/client"; @@ -34,9 +34,6 @@ type ProductCreate = { price: number; agentPrice: number; serviceCharge: number; - attributes?: { - [key: string]: Date | string | number | null; - }; }; type ProductUpdate = { @@ -46,9 +43,6 @@ type ProductUpdate = { price: number; agentPrice: number; serviceCharge: number; - attributes?: { - [key: string]: Date | string | number | null; - }; }; function imageLocation(id: string) { @@ -61,55 +55,12 @@ function imageLocation(id: string) { export class ProductController extends Controller { @Get() async getProduct( - @Queries() - qs: { - query?: string; - page?: number; - pageSize?: number; - filter?: string[]; - }, + @Query() query: string = "", + @Query() page: number = 1, + @Query() pageSize: number = 30, ) { - qs.page = qs.page ?? 1; - qs.pageSize = qs.pageSize ?? 30; - qs.query = qs.query ?? ""; - - const { query, page, pageSize, filter } = qs; - const where = { OR: [{ name: { contains: query } }, { detail: { contains: query } }], - AND: filter - ?.map((v) => { - const match = /[\w\-]+:[\W\w]+$/.exec(v); - - if (!match) return []; - - const [key, ...rest] = v.split(":"); - const val = rest.join(); - - return { - OR: [ - { - attributes: { - path: [key], - string_contains: val, - }, - }, - { - attributes: { - path: [key], - equals: Number.isFinite(+val) - ? +val - : val === "true" - ? true - : val === "false" - ? false - : val, - }, - }, - ], - }; - }) - .flat(), } satisfies Prisma.ProductWhereInput; const [result, total] = await prisma.$transaction([ @@ -172,7 +123,6 @@ export class ProductController extends Controller { data: { ...body, code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, - attributes: body.attributes, createdBy: req.user.name, updateBy: req.user.name, }, diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index ff8f49c..e5ac894 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -30,6 +30,9 @@ type ServiceCreate = { code: "MOU" | "mou"; name: string; detail: string; + attributes?: { + [key: string]: any; + }; workId: string[]; }; @@ -37,6 +40,9 @@ type ServiceUpdate = { name: string; detail: string; workId: string[]; + attributes?: { + [key: string]: any; + }; }; function imageLocation(id: string) { diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index 8702cf8..8bd491f 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -22,11 +22,17 @@ import HttpStatus from "../../interfaces/http-status"; type WorkCreate = { name: string; productId: string[]; + attributes?: { + [key: string]: any; + }; }; type WorkUpdate = { name?: string; productId?: string[]; + attributes?: { + [key: string]: any; + }; }; @Route("api/v1/work") From aec90e4644fa7ffcaba8ca7f7dcbbf5fcab5a858 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:53:39 +0700 Subject: [PATCH 081/157] fix: wrong relation join --- src/controllers/service/service-controller.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index e5ac894..ec88f63 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -72,9 +72,7 @@ export class ServiceController extends Controller { prisma.service.findMany({ include: { workOnService: { - include: { - service: true, - }, + include: { work: true }, }, }, orderBy: { createdAt: "asc" }, From c302eafb8301cb330a5f9c2d7bd67751b551a764 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:45:08 +0700 Subject: [PATCH 082/157] feat: feat update employee code --- src/controllers/employee-controller.ts | 252 +++++++++++++------------ 1 file changed, 136 insertions(+), 116 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index c04090b..5b98bda 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -298,10 +298,8 @@ export class EmployeeController extends Controller { prisma.district.findFirst({ where: { id: body.districtId || undefined } }), prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), prisma.customerBranch.findFirst({ - where: { id: body.customerBranchId || undefined }, - include: { - customer: true, - }, + where: { id: body.customerBranchId }, + include: { customer: true }, }), ]); if (body.provinceId && !province) @@ -450,37 +448,42 @@ export class EmployeeController extends Controller { @Body() body: EmployeeUpdate, @Path() employeeId: string, ) { - if (body.provinceId || body.districtId || body.subDistrictId || body.customerBranchId) { - const [province, district, subDistrict, customerBranch] = await prisma.$transaction([ - prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), - prisma.district.findFirst({ where: { id: body.districtId || undefined } }), - prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), - prisma.customerBranch.findFirst({ where: { id: body.customerBranchId || undefined } }), - ]); - if (body.provinceId && !province) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Province cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.districtId && !district) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "District cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.subDistrictId && !subDistrict) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Sub-district cannot be found.", - "missing_or_invalid_parameter", - ); - if (body.customerBranchId && !customerBranch) - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Customer cannot be found.", - "missing_or_invalid_parameter", - ); + const [province, district, subDistrict, customerBranch, employee] = await prisma.$transaction([ + prisma.province.findFirst({ where: { id: body.provinceId || undefined } }), + prisma.district.findFirst({ where: { id: body.districtId || undefined } }), + prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }), + prisma.customerBranch.findFirst({ + where: { id: body.customerBranchId || undefined }, + include: { customer: true }, + }), + prisma.employee.findFirst({ where: { id: employeeId } }), + ]); + if (body.provinceId && !province) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.districtId && !district) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.subDistrictId && !subDistrict) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "missing_or_invalid_parameter", + ); + if (body.customerBranchId && !customerBranch) + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Customer cannot be found.", + "missing_or_invalid_parameter", + ); + if (!employee) { + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); } const { @@ -512,93 +515,110 @@ export class EmployeeController extends Controller { } } - const record = await prisma.employee.update({ - where: { id: employeeId }, - include: { - province: true, - district: true, - subDistrict: true, - employeeOtherInfo: true, - employeeCheckup: { - include: { - province: true, + const record = await prisma.$transaction(async (tx) => { + let code: string | undefined; + + if (customerBranch && customerBranch.id !== customerBranchId) { + const last = await tx.runningNo.upsert({ + where: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, }, - }, - employeeWork: true, - }, - data: { - ...rest, - customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, - employeeWork: employeeWork - ? { - deleteMany: { - id: { - notIn: employeeWork.map((v) => v.id).filter((v): v is string => !!v) || [], - }, - }, - upsert: employeeWork.map((v) => ({ - where: { id: v.id || "" }, - create: { - ...v, - createdBy: req.user.name, - updateBy: req.user.name, - id: undefined, - }, - update: { - ...v, - updateBy: req.user.name, - }, - })), - } - : undefined, + create: { + key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, + value: 1, + }, + update: { value: { increment: 1 } }, + }); + code = `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`; + } - employeeCheckup: employeeCheckup - ? { - deleteMany: { - id: { - notIn: employeeCheckup.map((v) => v.id).filter((v): v is string => !!v) || [], - }, - }, - upsert: employeeCheckup.map((v) => ({ - where: { id: v.id || "" }, - create: { - ...v, - createdBy: req.user.name, - updateBy: req.user.name, - id: undefined, - }, - update: { - ...v, - updateBy: req.user.name, - }, - })), - } - : undefined, - employeeOtherInfo: employeeOtherInfo - ? { - deleteMany: {}, - create: employeeOtherInfo, - } - : undefined, - province: { - connect: provinceId ? { id: provinceId } : undefined, - disconnect: provinceId === null || undefined, + return await prisma.employee.update({ + where: { id: employeeId }, + include: { + province: true, + district: true, + subDistrict: true, + employeeOtherInfo: true, + employeeCheckup: { + include: { + province: true, + }, + }, + employeeWork: true, }, - district: { - connect: districtId ? { id: districtId } : undefined, - disconnect: districtId === null || undefined, + data: { + ...rest, + code, + customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, + employeeWork: employeeWork + ? { + deleteMany: { + id: { + notIn: employeeWork.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeWork.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + createdBy: req.user.name, + updateBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updateBy: req.user.name, + }, + })), + } + : undefined, + + employeeCheckup: employeeCheckup + ? { + deleteMany: { + id: { + notIn: employeeCheckup.map((v) => v.id).filter((v): v is string => !!v) || [], + }, + }, + upsert: employeeCheckup.map((v) => ({ + where: { id: v.id || "" }, + create: { + ...v, + createdBy: req.user.name, + updateBy: req.user.name, + id: undefined, + }, + update: { + ...v, + updateBy: req.user.name, + }, + })), + } + : undefined, + employeeOtherInfo: employeeOtherInfo + ? { + deleteMany: {}, + create: employeeOtherInfo, + } + : undefined, + province: { + connect: provinceId ? { id: provinceId } : undefined, + disconnect: provinceId === null || undefined, + }, + district: { + connect: districtId ? { id: districtId } : undefined, + disconnect: districtId === null || undefined, + }, + subDistrict: { + connect: subDistrictId ? { id: subDistrictId } : undefined, + disconnect: subDistrictId === null || undefined, + }, + createdBy: req.user.name, + updateBy: req.user.name, }, - subDistrict: { - connect: subDistrictId ? { id: subDistrictId } : undefined, - disconnect: subDistrictId === null || undefined, - }, - createdBy: req.user.name, - updateBy: req.user.name, - }, + }); }); - this.setStatus(HttpStatus.CREATED); - return Object.assign(record, { profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, From c9d92c43f9368e65c2b1d52300a8093de00c3803 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:54:42 +0700 Subject: [PATCH 083/157] fix: wrong cond --- src/controllers/employee-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 5b98bda..ed3df82 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -518,7 +518,7 @@ export class EmployeeController extends Controller { const record = await prisma.$transaction(async (tx) => { let code: string | undefined; - if (customerBranch && customerBranch.id !== customerBranchId) { + if (customerBranch && customerBranch.id !== employee.customerBranchId) { const last = await tx.runningNo.upsert({ where: { key: `EMPLOYEE_${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}`, From 0747fca92e29f786f0adebe7bfa35eb52495f282 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:18:47 +0700 Subject: [PATCH 084/157] feat: filter gender --- src/controllers/employee-controller.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index ed3df82..e6bdaff 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -228,16 +228,17 @@ export class EmployeeController extends Controller { @Get() async list( @Query() zipCode?: string, + @Query() gender?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { OR: [ - { firstName: { contains: query }, zipCode }, - { firstNameEN: { contains: query }, zipCode }, - { lastName: { contains: query }, zipCode }, - { lastNameEN: { contains: query }, zipCode }, + { firstName: { contains: query }, zipCode, gender }, + { firstNameEN: { contains: query }, zipCode, gender }, + { lastName: { contains: query }, zipCode, gender }, + { lastNameEN: { contains: query }, zipCode, gender }, ], } satisfies Prisma.EmployeeWhereInput; From 5b6c7e7ac82ff19424736dcdcb512ba8195b2bc7 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 13 Jun 2024 17:21:22 +0700 Subject: [PATCH 085/157] feat: add query string --- src/controllers/customer-branch-controller.ts | 27 ++++++++++--------- src/controllers/customer-controller.ts | 5 ++-- src/controllers/employee-controller.ts | 9 ++++--- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index ae5c350..9ae3615 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -111,6 +111,7 @@ export class CustomerBranchController extends Controller { async list( @Query() zipCode?: string, @Query() customerId?: string, + @Query() status?: Status, @Query() includeCustomer?: boolean, @Query() query: string = "", @Query() page: number = 1, @@ -118,22 +119,24 @@ export class CustomerBranchController extends Controller { ) { const where = { OR: [ - { nameEN: { contains: query }, zipCode }, - { name: { contains: query }, zipCode }, - { email: { contains: query }, zipCode }, - { code: { contains: query }, zipCode }, - { address: { contains: query }, zipCode }, - { addressEN: { contains: query }, zipCode }, - { province: { name: { contains: query } }, zipCode }, - { province: { nameEN: { contains: query } }, zipCode }, - { district: { name: { contains: query } }, zipCode }, - { district: { nameEN: { contains: query } }, zipCode }, - { subDistrict: { name: { contains: query } }, zipCode }, - { subDistrict: { nameEN: { contains: query } }, zipCode }, + { nameEN: { contains: query }, zipCode, status }, + { name: { contains: query }, zipCode, status }, + { email: { contains: query }, zipCode, status }, + { code: { contains: query }, zipCode, status }, + { address: { contains: query }, zipCode, status }, + { addressEN: { contains: query }, zipCode, status }, + { province: { name: { contains: query } }, zipCode, status }, + { province: { nameEN: { contains: query } }, zipCode, status }, + { district: { name: { contains: query } }, zipCode, status }, + { district: { nameEN: { contains: query } }, zipCode, status }, + { subDistrict: { name: { contains: query } }, zipCode, status }, + { subDistrict: { nameEN: { contains: query } }, zipCode, status }, { customer: { OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], }, + zipCode, + status, }, ], AND: { customerId }, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 251146a..a9554f5 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -138,14 +138,15 @@ export class CustomerController extends Controller { async list( @Query() customerType?: CustomerType, @Query() query: string = "", + @Query() status?: Status, @Query() page: number = 1, @Query() pageSize: number = 30, @Query() includeBranch: boolean = false, ) { const where = { OR: [ - { customerName: { contains: query }, customerType }, - { customerNameEN: { contains: query }, customerType }, + { customerName: { contains: query }, customerType, status }, + { customerNameEN: { contains: query }, customerType, status }, ], } satisfies Prisma.CustomerWhereInput; diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index e6bdaff..24408ae 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -229,16 +229,17 @@ export class EmployeeController extends Controller { async list( @Query() zipCode?: string, @Query() gender?: string, + @Query() status?: Status, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { OR: [ - { firstName: { contains: query }, zipCode, gender }, - { firstNameEN: { contains: query }, zipCode, gender }, - { lastName: { contains: query }, zipCode, gender }, - { lastNameEN: { contains: query }, zipCode, gender }, + { firstName: { contains: query }, zipCode, gender, status }, + { firstNameEN: { contains: query }, zipCode, gender, status }, + { lastName: { contains: query }, zipCode, gender, status }, + { lastNameEN: { contains: query }, zipCode, gender, status }, ], } satisfies Prisma.EmployeeWhereInput; From ddec8275d85e806b17c2cc81ba2d80fc906b0e74 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 09:45:23 +0700 Subject: [PATCH 086/157] fix: relation --- src/controllers/employee-controller.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 24408ae..69ec871 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -304,19 +304,19 @@ export class EmployeeController extends Controller { include: { customer: true }, }), ]); - if (body.provinceId && !province) + if (body.provinceId !== province?.id) throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", "missing_or_invalid_parameter", ); - if (body.districtId && !district) + if (body.districtId !== district?.id) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", "missing_or_invalid_parameter", ); - if (body.subDistrictId && !subDistrict) + if (body.subDistrictId !== subDistrict?.id) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", @@ -395,7 +395,11 @@ export class EmployeeController extends Controller { }, employeeCheckup: { createMany: { - data: employeeCheckup || [], + data: + employeeCheckup?.map((v) => ({ + ...v, + provinceId: !!v.provinceId ? null : v.provinceId, + })) || [], }, }, employeeOtherInfo: { From 9722fab1492b01e0565055608a5046da523194d7 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 04:39:48 +0000 Subject: [PATCH 087/157] fix: change dev message to code --- src/interfaces/http-error.ts | 15 +++------------ src/middlewares/error.ts | 6 +++--- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/interfaces/http-error.ts b/src/interfaces/http-error.ts index e9f34fd..e4820bc 100644 --- a/src/interfaces/http-error.ts +++ b/src/interfaces/http-error.ts @@ -1,29 +1,20 @@ import HttpStatus from "./http-status"; -type DevMessage = - | "missing_or_invalid_parameter" - | "data_exists" - | "data_in_used" - | "no_permission" - | "unknown_url" - | "data_not_found" - | "unauthorized"; - class HttpError extends Error { /** * HTTP Status Code */ status: HttpStatus; message: string; - devMessage?: DevMessage; + code?: string; - constructor(status: HttpStatus, message: string, devMessage?: DevMessage) { + constructor(status: HttpStatus, message: string, code?: string) { super(message); this.name = "HttpError"; this.status = status; this.message = message; - this.devMessage = devMessage; + this.code = code; } } diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts index d80ceb3..177e363 100644 --- a/src/middlewares/error.ts +++ b/src/middlewares/error.ts @@ -8,7 +8,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(error.status).json({ status: error.status, message: error.message, - devMessage: error.devMessage, + code: error.code, }); } @@ -17,7 +17,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) status: HttpStatus.UNPROCESSABLE_ENTITY, message: "Validation error(s).", detail: error.fields, - devMessage: "missing_or_invalid_parameter", + code: "validateError", }); } @@ -26,7 +26,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ status: HttpStatus.INTERNAL_SERVER_ERROR, message: error.message, - devMessage: "system_error", + code: "system_error", }); } From 5dbc261a7910f499cd3fc25e17d0e6c64b283da5 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 04:40:10 +0000 Subject: [PATCH 088/157] fix: group code --- src/controllers/product/group-controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index ae3667a..317f4f9 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -56,7 +56,7 @@ export class ProductGroup extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); return record; } @@ -100,7 +100,7 @@ export class ProductGroup extends Controller { @Path() groupId: string, ) { if (!(await prisma.productGroup.findUnique({ where: { id: groupId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); } const record = await prisma.productGroup.update({ @@ -116,11 +116,11 @@ export class ProductGroup extends Controller { const record = await prisma.productGroup.findFirst({ where: { id: groupId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Product group is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Product group is in used.", "productGroupInUsed"); } return await prisma.productGroup.delete({ where: { id: groupId } }); From fa8e21166bf540b923fc53931ef0cfe25e17ddf8 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 04:41:03 +0000 Subject: [PATCH 089/157] fix: product code --- src/controllers/product/product-controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 59e550e..aabdbc5 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -97,7 +97,7 @@ export class ProductController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); } return Object.assign(record, { @@ -156,7 +156,7 @@ export class ProductController extends Controller { @Path() productId: string, ) { if (!(await prisma.product.findUnique({ where: { id: productId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); } const record = await prisma.product.update({ @@ -182,11 +182,11 @@ export class ProductController extends Controller { const record = await prisma.product.findFirst({ where: { id: productId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Product is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Product is in used.", "productInUsed"); } return await prisma.product.delete({ where: { id: productId } }); From af6d9151068c57c1f25c7bf7750d903fa1cc9e11 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:54:13 +0700 Subject: [PATCH 090/157] feat: filter status created and active treated as same --- src/controllers/customer-branch-controller.ts | 32 ++++++++++++------- src/controllers/customer-controller.ts | 11 +++++-- src/controllers/employee-controller.ts | 16 +++++++--- src/controllers/product/group-controller.ts | 18 ++++++++--- src/controllers/product/product-controller.ts | 14 +++++++- src/controllers/product/type-controller.ts | 18 +++++++++-- 6 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 9ae3615..2d40baf 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -117,20 +117,28 @@ export class CustomerBranchController extends Controller { @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { OR: [ - { nameEN: { contains: query }, zipCode, status }, - { name: { contains: query }, zipCode, status }, - { email: { contains: query }, zipCode, status }, - { code: { contains: query }, zipCode, status }, - { address: { contains: query }, zipCode, status }, - { addressEN: { contains: query }, zipCode, status }, - { province: { name: { contains: query } }, zipCode, status }, - { province: { nameEN: { contains: query } }, zipCode, status }, - { district: { name: { contains: query } }, zipCode, status }, - { district: { nameEN: { contains: query } }, zipCode, status }, - { subDistrict: { name: { contains: query } }, zipCode, status }, - { subDistrict: { nameEN: { contains: query } }, zipCode, status }, + { nameEN: { contains: query }, zipCode, ...filterStatus(status) }, + { name: { contains: query }, zipCode, ...filterStatus(status) }, + { email: { contains: query }, zipCode, ...filterStatus(status) }, + { code: { contains: query }, zipCode, ...filterStatus(status) }, + { address: { contains: query }, zipCode, ...filterStatus(status) }, + { addressEN: { contains: query }, zipCode, ...filterStatus(status) }, + { province: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { province: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, + { district: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { district: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, + { subDistrict: { name: { contains: query } }, zipCode, ...filterStatus(status) }, + { subDistrict: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) }, { customer: { OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }], diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index a9554f5..d43fecd 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -143,10 +143,17 @@ export class CustomerController extends Controller { @Query() pageSize: number = 30, @Query() includeBranch: boolean = false, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; const where = { OR: [ - { customerName: { contains: query }, customerType, status }, - { customerNameEN: { contains: query }, customerType, status }, + { customerName: { contains: query }, customerType, status, ...filterStatus(status) }, + { customerNameEN: { contains: query }, customerType, status, ...filterStatus(status) }, ], } satisfies Prisma.CustomerWhereInput; diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 69ec871..2dc9614 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -234,12 +234,20 @@ export class EmployeeController extends Controller { @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { OR: [ - { firstName: { contains: query }, zipCode, gender, status }, - { firstNameEN: { contains: query }, zipCode, gender, status }, - { lastName: { contains: query }, zipCode, gender, status }, - { lastNameEN: { contains: query }, zipCode, gender, status }, + { firstName: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { firstNameEN: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { lastName: { contains: query }, zipCode, gender, ...filterStatus(status) }, + { lastNameEN: { contains: query }, zipCode, gender, ...filterStatus(status) }, ], } satisfies Prisma.EmployeeWhereInput; diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index 317f4f9..9f7735d 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -41,12 +41,22 @@ export class ProductGroup extends Controller { } @Get() - async getProductGroup(@Query() query: string = "") { + async getProductGroup(@Query() query: string = "", @Query() status?: Status) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { - OR: [{ name: { contains: query } }, { detail: { contains: query } }], + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], } satisfies Prisma.ProductGroupWhereInput; - const result = prisma.productGroup.findMany({ orderBy: { createdAt: "asc" }, where }); - return result; + return prisma.productGroup.findMany({ orderBy: { createdAt: "asc" }, where }); } @Get("{groupId}") diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index aabdbc5..954f1a4 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -55,12 +55,24 @@ function imageLocation(id: string) { export class ProductController extends Controller { @Get() async getProduct( + @Query() status?: Status, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { - OR: [{ name: { contains: query } }, { detail: { contains: query } }], + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], } satisfies Prisma.ProductWhereInput; const [result, total] = await prisma.$transaction([ diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index ef859da..93db012 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -43,10 +43,24 @@ export class ProductType extends Controller { } @Get() - async getProductType(@Query() query: string = "", @Query() productGroupId?: string) { + async getProductType( + @Query() query: string = "", + @Query() productGroupId?: string, + @Query() status?: Status, + ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; const where = { AND: { productGroupId }, - OR: [{ name: { contains: query } }, { detail: { contains: query } }], + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], } satisfies Prisma.ProductTypeWhereInput; const result = prisma.productType.findMany({ orderBy: { createdAt: "asc" }, where }); return result; From 5fa8b00d4f6f7e18fd292d4f90188047207ff28e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 11:54:26 +0700 Subject: [PATCH 091/157] chore: update migration --- .../20240614025514_remove_unintended_field/migration.sql | 8 ++++++++ prisma/schema.prisma | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20240614025514_remove_unintended_field/migration.sql diff --git a/prisma/migrations/20240614025514_remove_unintended_field/migration.sql b/prisma/migrations/20240614025514_remove_unintended_field/migration.sql new file mode 100644 index 0000000..f97abe5 --- /dev/null +++ b/prisma/migrations/20240614025514_remove_unintended_field/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the column `productId` on the `WorkService` table. All the data in the column will be lost. + +*/ +-- AlterTable +ALTER TABLE "WorkService" DROP COLUMN "productId"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 20a2c4e..64f3b60 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -580,7 +580,6 @@ model WorkService { createdAt DateTime @default(now()) updateBy String? updatedAt DateTime @updatedAt - productId String? @@id([workId, serviceId]) } From e7e090ecbd69e4e0cf517c297787e971ff55fb1a Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 05:42:43 +0000 Subject: [PATCH 092/157] fix: type code --- src/controllers/product/type-controller.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 93db012..a764c76 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -73,7 +73,7 @@ export class ProductType extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); return record; } @@ -88,7 +88,7 @@ export class ProductType extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Product group associated cannot be found.", - "missing_or_invalid_parameter", + "productGroupAssociatedBadReq", ); } @@ -135,12 +135,12 @@ export class ProductType extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Product group cannot be found.", - "missing_or_invalid_parameter", + "productGroupBadReq", ); } if (!(await prisma.productType.findUnique({ where: { id: typeId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); } const record = await prisma.productType.update({ @@ -156,11 +156,11 @@ export class ProductType extends Controller { const record = await prisma.productType.findFirst({ where: { id: typeId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Product type is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Product type is in used.", "productTypeInUsed"); } return await prisma.productType.delete({ where: { id: typeId } }); From c978d3adec8a3d75175da4afc7f3183bdd83d4d9 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 05:43:32 +0000 Subject: [PATCH 093/157] fix: work & service code --- src/controllers/service/service-controller.ts | 10 +++++----- src/controllers/work/work-controller.ts | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index ec88f63..60c926b 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -124,7 +124,7 @@ export class ServiceController extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); return Object.assign(record, { imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), @@ -173,7 +173,7 @@ export class ServiceController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some product not found.", - "missing_or_invalid_parameter", + "someProductBadReq", ); } @@ -250,7 +250,7 @@ export class ServiceController extends Controller { @Path() serviceId: string, ) { if (!(await prisma.service.findUnique({ where: { id: serviceId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); } const record = await prisma.service.update({ @@ -276,11 +276,11 @@ export class ServiceController extends Controller { const record = await prisma.service.findFirst({ where: { id: serviceId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Service is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Service is in used.", "serviceInUsed"); } return await prisma.service.delete({ where: { id: serviceId } }); diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index 8bd491f..455e5d5 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -79,7 +79,7 @@ export class WorkController extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); return record; } @@ -163,7 +163,7 @@ export class WorkController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some product not found.", - "missing_or_invalid_parameter", + "someProductBadReq", ); } @@ -214,7 +214,7 @@ export class WorkController extends Controller { const { productId, ...payload } = body; if (!(await prisma.work.findUnique({ where: { id: workId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); } const exist = await prisma.work.findFirst({ @@ -301,11 +301,11 @@ export class WorkController extends Controller { const record = await prisma.work.findFirst({ where: { id: workId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Work is in used.", "missing_or_invalid_parameter"); + throw new HttpError(HttpStatus.FORBIDDEN, "Work is in used.", "workInUsed"); } return await prisma.work.delete({ where: { id: workId } }); From 5cc0f1c65900fc7167f7a23dbc3c4da37ba7b2ee Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 05:44:03 +0000 Subject: [PATCH 094/157] fix: branch code --- src/controllers/branch-contact-controller.ts | 10 +++--- src/controllers/branch-controller.ts | 32 ++++++++++---------- src/controllers/branch-user-controller.ts | 6 ++-- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/controllers/branch-contact-controller.ts b/src/controllers/branch-contact-controller.ts index 473fd51..e2e3d6c 100644 --- a/src/controllers/branch-contact-controller.ts +++ b/src/controllers/branch-contact-controller.ts @@ -62,7 +62,7 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } @@ -78,8 +78,8 @@ export class BranchContactController extends Controller { if (!(await prisma.branch.findFirst({ where: { id: branchId } }))) { throw new HttpError( HttpStatus.BAD_REQUEST, - "Branch not found.", - "missing_or_invalid_parameter", + "Branch cannot be found.", + "branchBadReq", ); } const record = await prisma.branchContact.create({ @@ -106,7 +106,7 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } @@ -125,7 +125,7 @@ export class BranchContactController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Branch contact cannot be found.", - "data_not_found", + "branchContactNotFound", ); } } diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 889c5a1..bf61974 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -208,7 +208,7 @@ export class BranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } return Object.assign(record, { @@ -229,25 +229,25 @@ export class BranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.headOfficeId && !head) throw new HttpError( HttpStatus.BAD_REQUEST, - "Head branch cannot be found.", - "missing_or_invalid_parameter", + "Headquaters cannot be found.", + "relationHQNotFound", ); const { provinceId, districtId, subDistrictId, headOfficeId, contact, ...rest } = body; @@ -337,8 +337,8 @@ export class BranchController extends Controller { if (body.headOfficeId === branchId) throw new HttpError( HttpStatus.BAD_REQUEST, - "Cannot make this as head office and branch at the same time.", - "missing_or_invalid_parameter", + "Cannot make this as headquaters and branch at the same time.", + "cantMakeHQAndBranchSameTime", ); if (body.subDistrictId || body.districtId || body.provinceId || body.headOfficeId) { @@ -352,32 +352,32 @@ export class BranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.headOfficeId && !branch) throw new HttpError( HttpStatus.BAD_REQUEST, - "Head branch cannot be found.", - "missing_or_invalid_parameter", + "Headquaters cannot be found.", + "relationHQNotFound", ); } const { provinceId, districtId, subDistrictId, headOfficeId, contact, ...rest } = body; if (!(await prisma.branch.findUnique({ where: { id: branchId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const record = await prisma.branch.update({ @@ -445,11 +445,11 @@ export class BranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used.", "branchInUsed"); } await minio.removeObject(MINIO_BUCKET, lineImageLoc(branchId), { diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index a12c546..539dd2e 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -116,7 +116,7 @@ export class BranchUserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Branch cannot be found.", - "missing_or_invalid_parameter", + "branchBadReq", ); } @@ -124,7 +124,7 @@ export class BranchUserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more user cannot be found.", - "missing_or_invalid_parameter", + "oneOrMoreUserBadReq", ); } @@ -234,7 +234,7 @@ export class UserBranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more branch cannot be found.", - "missing_or_invalid_parameter", + "oneOrMoreBranchBadReq", ); } From d97b1260cf8dabaf5f56c3f61d0fa749176b1703 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 05:58:14 +0000 Subject: [PATCH 095/157] fix: customer branch code --- src/controllers/customer-branch-controller.ts | 30 +++++++++---------- src/controllers/customer-controller.ts | 22 +++++++------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 2d40baf..5bd51c4 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -182,7 +182,7 @@ export class CustomerBranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } return record; @@ -250,25 +250,25 @@ export class CustomerBranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (!customer) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", - "missing_or_invalid_parameter", + "relationCustomerNotFound", ); const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; @@ -328,32 +328,32 @@ export class CustomerBranchController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.customerId && !customer) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", - "missing_or_invalid_parameter", + "relationCustomerNotFound", ); } const { provinceId, districtId, subDistrictId, customerId, ...rest } = body; if (!(await prisma.customerBranch.findUnique({ where: { id: branchId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const record = await prisma.customerBranch.update({ @@ -398,12 +398,12 @@ export class CustomerBranchController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Customer branch cannot be found.", - "data_not_found", + "customerBranchNotFound", ); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Customer branch is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Customer branch is in used.", "customerBranchInUsed"); } return await prisma.customerBranch.delete({ where: { id: branchId } }).then((v) => { @@ -444,7 +444,7 @@ export class CustomerAttachmentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Customer branch cannot be found.", - "data_not_found", + "customerBranchNotFound", ); } @@ -479,7 +479,7 @@ export class CustomerAttachmentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Customer branch cannot be found.", - "data_not_found", + "customerBranchNotFound", ); } @@ -509,7 +509,7 @@ export class CustomerAttachmentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Customer branch cannot be found.", - "data_not_found", + "customerBranchNotFound", ); } diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index d43fecd..0774a5a 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -211,7 +211,7 @@ export class CustomerController extends Controller { where: { id: customerId }, }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); return Object.assign(record, { imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, @@ -249,21 +249,21 @@ export class CustomerController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); } if (districtId && district.length !== districtId?.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "Some district cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); } if (subDistrictId && subDistrict.length !== subDistrictId?.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "Some sub district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); } @@ -338,7 +338,7 @@ export class CustomerController extends Controller { const customer = await prisma.customer.findUnique({ where: { id: customerId } }); if (!customer) { - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); } const provinceId = body.customerBranch?.reduce((acc, cur) => { @@ -365,21 +365,21 @@ export class CustomerController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); } if (districtId && district.length !== districtId?.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "Some district cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); } if (subDistrictId && subDistrict.length !== subDistrictId?.length) { throw new HttpError( HttpStatus.BAD_REQUEST, "Some sub district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); } @@ -398,7 +398,7 @@ export class CustomerController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "One or more branch cannot be delete and is missing.", - "missing_or_invalid_parameter", + "oneOrMoreBranchMissing", ); } @@ -490,11 +490,11 @@ export class CustomerController extends Controller { const record = await prisma.customer.findFirst({ where: { id: customerId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "customerInUsed"); } return await prisma.customer.delete({ where: { id: customerId } }).then((v) => { From d8a6565abe1c3c3fdae067ab09c28ecc6661bdd7 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 06:19:15 +0000 Subject: [PATCH 096/157] fix: employee code --- .../employee-checkup-controller.ts | 14 +++++----- src/controllers/employee-controller.ts | 28 +++++++++---------- .../employee-other-info-controller.ts | 6 ++-- src/controllers/employee-work-controller.ts | 8 +++--- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/controllers/employee-checkup-controller.ts b/src/controllers/employee-checkup-controller.ts index ede52f4..07bf28c 100644 --- a/src/controllers/employee-checkup-controller.ts +++ b/src/controllers/employee-checkup-controller.ts @@ -51,7 +51,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } return record; @@ -72,13 +72,13 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "provinceNotFound", ); if (!employee) throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeNotFound", ); } @@ -116,13 +116,13 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "provinceNotFound", ); if (!employee) throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeNotFound", ); } @@ -132,7 +132,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } @@ -160,7 +160,7 @@ export class EmployeeCheckupController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee checkup cannot be found.", - "data_not_found", + "employeeCheckupNotFound", ); } diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 2dc9614..ab43b07 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -295,7 +295,7 @@ export class EmployeeController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } return record; @@ -316,25 +316,25 @@ export class EmployeeController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId !== district?.id) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId !== subDistrict?.id) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (!customerBranch) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer Branch cannot be found.", - "missing_or_invalid_parameter", + "relationCustomerBranchNotFound", ); const { @@ -362,7 +362,7 @@ export class EmployeeController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some province cannot be found.", - "missing_or_invalid_parameter", + "someProvinceNotFound", ); } } @@ -476,28 +476,28 @@ export class EmployeeController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); if (body.districtId && !district) throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); if (body.subDistrictId && !subDistrict) throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); if (body.customerBranchId && !customerBranch) throw new HttpError( HttpStatus.BAD_REQUEST, "Customer cannot be found.", - "missing_or_invalid_parameter", + "relationCustomerNotFound", ); if (!employee) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } const { @@ -524,7 +524,7 @@ export class EmployeeController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Some province cannot be found.", - "missing_or_invalid_parameter", + "someProvinceNotFound", ); } } @@ -652,14 +652,14 @@ export class EmployeeController extends Controller { const record = await prisma.employee.findFirst({ where: { id: employeeId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee cannot be found.", "employeeNotFound"); } if (record.status !== Status.CREATED) { throw new HttpError( HttpStatus.FORBIDDEN, "Employee is in used.", - "missing_or_invalid_parameter", + "employeeInUsed", ); } diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index 3cb6284..4a2afd3 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -54,7 +54,7 @@ export class EmployeeOtherInfo extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeBadReq", ); const record = await prisma.employeeOtherInfo.create({ @@ -82,7 +82,7 @@ export class EmployeeOtherInfo extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee other info cannot be found.", - "data_not_found", + "employeeOtherNotFound", ); } @@ -106,7 +106,7 @@ export class EmployeeOtherInfo extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Employee other info cannot be found.", - "data_not_found", + "employeeOtherNotFound", ); } diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts index 90f1c8b..2336874 100644 --- a/src/controllers/employee-work-controller.ts +++ b/src/controllers/employee-work-controller.ts @@ -46,7 +46,7 @@ export class EmployeeWorkController extends Controller { where: { id: workId, employeeId }, }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); } return record; } @@ -61,7 +61,7 @@ export class EmployeeWorkController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Employee cannot be found.", - "missing_or_invalid_parameter", + "employeeBadReq", ); const record = await prisma.employeeWork.create({ @@ -86,7 +86,7 @@ export class EmployeeWorkController extends Controller { @Body() body: EmployeeWorkPayload, ) { if (!(await prisma.employeeWork.findUnique({ where: { id: workId, employeeId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); } const record = await prisma.employeeWork.update({ @@ -104,7 +104,7 @@ export class EmployeeWorkController extends Controller { const record = await prisma.employeeWork.findFirst({ where: { id: workId, employeeId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Employee work cannot be found.", "employeeWorkNotFound"); } return await prisma.employeeWork.delete({ where: { id: workId, employeeId } }); From 10489447736c883c1f99c298d6326522c25c6f5e Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 06:26:09 +0000 Subject: [PATCH 097/157] fix: permission & user code --- src/controllers/permission-controller.ts | 26 ++++++++++++------------ src/controllers/user-controller.ts | 18 ++++++++-------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/controllers/permission-controller.ts b/src/controllers/permission-controller.ts index 0ea14e0..d10c649 100644 --- a/src/controllers/permission-controller.ts +++ b/src/controllers/permission-controller.ts @@ -41,7 +41,7 @@ export class MenuController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Parent menu not found.", - "missing_or_invalid_parameter", + "parentMenuBadReq", ); } } @@ -66,7 +66,7 @@ export class MenuController extends Controller { }) .catch((e) => { if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { - throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "menuNotFound"); } throw new Error(e); }); @@ -78,7 +78,7 @@ export class MenuController extends Controller { async deleteMenu(@Path("menuId") id: string) { const record = await prisma.menu.deleteMany({ where: { id } }); if (record.count <= 0) { - throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Menu cannot be found.", "menuNotFound"); } } } @@ -114,7 +114,7 @@ export class RoleMenuController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } @@ -140,7 +140,7 @@ export class RoleMenuController extends Controller { }) .catch((e) => { if (e instanceof PrismaClientKnownRequestError && e.code === "P2025") { - throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "roleMenuNotFound"); } throw new Error(e); }); @@ -154,7 +154,7 @@ export class RoleMenuController extends Controller { where: { id, menuId }, }); if (record.count <= 0) { - throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Role menu cannot be found.", "roleMenuNotFound"); } } } @@ -193,7 +193,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } @@ -215,7 +215,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } } @@ -231,7 +231,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Menu component cannot be found.", - "data_not_found", + "menuComponentNotFound", ); } throw new Error(e); @@ -247,7 +247,7 @@ export class MenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Menu component cannot be found.", - "data_not_found", + "menuComponentNotFound", ); } } @@ -287,7 +287,7 @@ export class RoleMenuComponentController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Menu not found.", - "missing_or_invalid_parameter", + "menuBadReq", ); } @@ -316,7 +316,7 @@ export class RoleMenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Role menu component cannot be found.", - "data_not_found", + "roleMenuNotFound", ); } throw new Error(e); @@ -337,7 +337,7 @@ export class RoleMenuComponentController extends Controller { throw new HttpError( HttpStatus.NOT_FOUND, "Role menu component cannot be found.", - "data_not_found", + "roleMenuNotFound", ); } } diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 2e0951a..06e58e8 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -210,7 +210,7 @@ export class UserController extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); return Object.assign(record, { profileImageUrl: await minio.presignedGetObject( @@ -233,21 +233,21 @@ export class UserController extends Controller { throw new HttpError( HttpStatus.BAD_REQUEST, "Province cannot be found.", - "missing_or_invalid_parameter", + "relationProvinceNotFound", ); } if (body.districtId && !district) { throw new HttpError( HttpStatus.BAD_REQUEST, "District cannot be found.", - "missing_or_invalid_parameter", + "relationDistrictNotFound", ); } if (body.subDistrictId && !subDistrict) { throw new HttpError( HttpStatus.BAD_REQUEST, "Sub-district cannot be found.", - "missing_or_invalid_parameter", + "relationSubDistrictNotFound", ); } } @@ -396,7 +396,7 @@ export class UserController extends Controller { }); if (!user) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound"); } const lastUserOfType = @@ -463,11 +463,11 @@ export class UserController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "User is in used.", "data_in_used"); + throw new HttpError(HttpStatus.FORBIDDEN, "User is in used.", "userInUsed"); } await minio.removeObject(MINIO_BUCKET, imageLocation(userId), { @@ -521,7 +521,7 @@ export class UserAttachmentController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } const list = await new Promise((resolve, reject) => { @@ -554,7 +554,7 @@ export class UserAttachmentController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "data_not_found"); + throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); } return await Promise.all( From be46aa3cffe4b0fb85cec4fbf741f410510ecc59 Mon Sep 17 00:00:00 2001 From: puriphat Date: Fri, 14 Jun 2024 06:30:10 +0000 Subject: [PATCH 098/157] fix: auth & role code --- src/middlewares/auth.ts | 2 +- src/middlewares/role.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index ad0bb1e..5aecde8 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -12,6 +12,6 @@ export async function expressAuthentication( case "keycloak": return keycloakAuth(request, scopes); default: - throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "ไม่ทราบวิธียืนยันตัวตน"); + throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "Unknown how to verify identity.", "unknowHowToVerify"); } } diff --git a/src/middlewares/role.ts b/src/middlewares/role.ts index d02d316..dd2ec2f 100644 --- a/src/middlewares/role.ts +++ b/src/middlewares/role.ts @@ -5,14 +5,14 @@ import HttpStatus from "../interfaces/http-status"; export function role( role: string | string[], - errorMessage: string = "คุณไม่มีสิทธิในการเข้าถึงทรัพยากรดังกล่าว", + errorMessage: string = "You do not have permission to access this resource.", ) { return (req: RequestWithUser, _res: Response, next: NextFunction) => { if (!Array.isArray(role) && !req.user.role.includes(role) && !req.user.role.includes("*")) { - throw new HttpError(HttpStatus.FORBIDDEN, errorMessage); + throw new HttpError(HttpStatus.FORBIDDEN, errorMessage, "noPermissionToAccess"); } if (role !== "*" && !req.user.role.some((v) => role.includes(v))) { - throw new HttpError(HttpStatus.FORBIDDEN, errorMessage); + throw new HttpError(HttpStatus.FORBIDDEN, errorMessage, "noPermissionToAccess"); } return next(); }; From 39206a6d76a6c659d14d1f1ce6727c5027878dd3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:13:03 +0700 Subject: [PATCH 099/157] refactor: update log --- src/middlewares/log.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/middlewares/log.ts b/src/middlewares/log.ts index 3cd45f5..5e8eb01 100644 --- a/src/middlewares/log.ts +++ b/src/middlewares/log.ts @@ -54,12 +54,7 @@ async function logMiddleware(req: Request, res: Response, next: NextFunction) { method: req.method, endpoint: req.url, responseCode: res.statusCode, - responseDescription: - data?.devMessage !== undefined - ? data.devMessage - : { 200: "success", 201: "created_success", 204: "no_content", 304: "success" }[ - res.statusCode - ], + responseDescription: data?.code, input: (level === 4 && JSON.stringify(req.body, null, 2)) || undefined, output: (level === 4 && JSON.stringify(data, null, 2)) || undefined, ...req.app.locals.logData, From 51fd6b05898acfdf144d636cc43e59a174829d40 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:49:05 +0700 Subject: [PATCH 100/157] feat: update work endpoints --- .../migration.sql | 22 +++++ prisma/schema.prisma | 23 +---- src/controllers/service/service-controller.ts | 92 +++++++++---------- src/controllers/work/work-controller.ts | 11 +-- 4 files changed, 76 insertions(+), 72 deletions(-) create mode 100644 prisma/migrations/20240614084850_update_work_table/migration.sql diff --git a/prisma/migrations/20240614084850_update_work_table/migration.sql b/prisma/migrations/20240614084850_update_work_table/migration.sql new file mode 100644 index 0000000..fc91684 --- /dev/null +++ b/prisma/migrations/20240614084850_update_work_table/migration.sql @@ -0,0 +1,22 @@ +/* + Warnings: + + - You are about to drop the `WorkService` table. If the table is not empty, all the data it contains will be lost. + - Added the required column `order` to the `Work` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropForeignKey +ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_serviceId_fkey"; + +-- DropForeignKey +ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_workId_fkey"; + +-- AlterTable +ALTER TABLE "Work" ADD COLUMN "order" INTEGER NOT NULL, +ADD COLUMN "serviceId" TEXT; + +-- DropTable +DROP TABLE "WorkService"; + +-- AddForeignKey +ALTER TABLE "Work" ADD CONSTRAINT "Work_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 64f3b60..b731ce5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -543,45 +543,32 @@ model Service { attributes Json? status Status @default(CREATED) + work Work[] createdBy String? createdAt DateTime @default(now()) updateBy String? updatedAt DateTime @updatedAt - - workOnService WorkService[] } model Work { id String @id @default(uuid()) + order Int name String attributes Json? status Status @default(CREATED) + service Service? @relation(fields: [serviceId], references: [id], onDelete: Cascade) + serviceId String? + createdBy String? createdAt DateTime @default(now()) updateBy String? updatedAt DateTime @updatedAt productOnWork WorkProduct[] - serviceOnWork WorkService[] -} - -model WorkService { - order Int - work Work @relation(fields: [workId], references: [id], onDelete: Cascade) - workId String - service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade) - serviceId String - - createdBy String? - createdAt DateTime @default(now()) - updateBy String? - updatedAt DateTime @updatedAt - - @@id([workId, serviceId]) } model WorkProduct { diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 60c926b..784736b 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -33,20 +33,28 @@ type ServiceCreate = { attributes?: { [key: string]: any; }; - workId: string[]; + work?: { + name: string; + productId: string[]; + attributes?: { [key: string]: any }; + }[]; }; type ServiceUpdate = { name: string; detail: string; - workId: string[]; attributes?: { [key: string]: any; }; + work?: { + name: string; + productId: string[]; + attributes?: { [key: string]: any }; + }[]; }; function imageLocation(id: string) { - return `service/${id}/product-image`; + return `service/${id}/service-image`; } @Route("api/v1/service") @@ -71,9 +79,7 @@ export class ServiceController extends Controller { const [result, total] = await prisma.$transaction([ prisma.service.findMany({ include: { - workOnService: { - include: { work: true }, - }, + work: true, }, orderBy: { createdAt: "asc" }, where, @@ -104,18 +110,12 @@ export class ServiceController extends Controller { async getServiceById(@Path() serviceId: string) { const record = await prisma.service.findFirst({ include: { - workOnService: { + work: { orderBy: { order: "asc" }, include: { - work: { - include: { - productOnWork: { - include: { - product: true, - }, - orderBy: { order: "asc" }, - }, - }, + productOnWork: { + include: { product: true }, + orderBy: { order: "asc" }, }, }, }, @@ -138,9 +138,7 @@ export class ServiceController extends Controller { @Query() pageSize: number = 30, ) { const where = { - serviceOnWork: { - some: { serviceId }, - }, + serviceId, } satisfies Prisma.WorkWhereInput; const [result, total] = await prisma.$transaction([ @@ -150,6 +148,7 @@ export class ServiceController extends Controller { include: { product: true, }, + orderBy: { order: "asc" }, }, }, where, @@ -163,19 +162,7 @@ export class ServiceController extends Controller { @Post() async createService(@Request() req: RequestWithUser, @Body() body: ServiceCreate) { - const { workId, ...payload } = body; - - const workList = await prisma.work.findMany({ - where: { id: { in: workId } }, - }); - - if (workList.length !== workList.length) { - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Some product not found.", - "someProductBadReq", - ); - } + const { work, ...payload } = body; const record = await prisma.$transaction( async (tx) => { @@ -192,18 +179,13 @@ export class ServiceController extends Controller { return tx.service.create({ include: { - workOnService: { - orderBy: { order: "asc" }, + work: { include: { - work: { + productOnWork: { include: { - productOnWork: { - include: { - product: true, - }, - orderBy: { order: "asc" }, - }, + product: true, }, + orderBy: { order: "asc" }, }, }, }, @@ -211,12 +193,13 @@ export class ServiceController extends Controller { data: { ...payload, code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, - workOnService: { + work: { createMany: { - data: workId.map((v, i) => ({ - order: i + 1, - workId: v, - })), + data: + work?.map((v, i) => ({ + ...v, + order: i + 1, + })) || [], }, }, createdBy: req.user.name, @@ -253,8 +236,23 @@ export class ServiceController extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); } + const { work, ...payload } = body; + const record = await prisma.service.update({ - data: { ...body, updateBy: req.user.name }, + data: { + ...payload, + work: { + deleteMany: {}, + createMany: { + data: + work?.map((v, i) => ({ + order: i + 1, + ...v, + })) || [], + }, + }, + updateBy: req.user.name, + }, where: { id: serviceId }, }); return Object.assign(record, { diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index 455e5d5..bff06fe 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -20,6 +20,7 @@ import HttpError from "../../interfaces/http-error"; import HttpStatus from "../../interfaces/http-status"; type WorkCreate = { + order: number; name: string; productId: string[]; attributes?: { @@ -28,6 +29,7 @@ type WorkCreate = { }; type WorkUpdate = { + order?: number; name?: string; productId?: string[]; attributes?: { @@ -78,8 +80,7 @@ export class WorkController extends Controller { where: { id: workId }, }); - if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "Work cannot be found.", "workNotFound"); return record; } @@ -160,11 +161,7 @@ export class WorkController extends Controller { }); if (productList.length !== productId.length) { - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Some product not found.", - "someProductBadReq", - ); + throw new HttpError(HttpStatus.BAD_REQUEST, "Some product not found.", "someProductBadReq"); } const record = await prisma.work.create({ From d86a209639b8f0cfa3afea6e9721e75bf88383fb Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:53:48 +0700 Subject: [PATCH 101/157] feat: update product fields --- .../migration.sql | 10 ++++++++++ prisma/schema.prisma | 4 +++- src/controllers/product/product-controller.ts | 16 +++++++++------- 3 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 prisma/migrations/20240614095339_update_product_fields/migration.sql diff --git a/prisma/migrations/20240614095339_update_product_fields/migration.sql b/prisma/migrations/20240614095339_update_product_fields/migration.sql new file mode 100644 index 0000000..94cf800 --- /dev/null +++ b/prisma/migrations/20240614095339_update_product_fields/migration.sql @@ -0,0 +1,10 @@ +/* + Warnings: + + - Changed the type of `process` on the `Product` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. + +*/ +-- AlterTable +ALTER TABLE "Product" ADD COLUMN "remark" TEXT, +DROP COLUMN "process", +ADD COLUMN "process" INTEGER NOT NULL; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b731ce5..549218b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -631,13 +631,15 @@ model Product { code String name String detail String - process String + process Int price Int agentPrice Int serviceCharge Int status Status @default(CREATED) + remark String? + productType ProductType? @relation(fields: [productTypeId], references: [id], onDelete: SetNull) productTypeId String? diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 954f1a4..49a5092 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -30,19 +30,21 @@ type ProductCreate = { code: "AC" | "DO" | "ac" | "do"; name: string; detail: string; - process: string; + process: number; price: number; agentPrice: number; serviceCharge: number; + remark?: string; }; type ProductUpdate = { - name: string; - detail: string; - process?: string; - price: number; - agentPrice: number; - serviceCharge: number; + name?: string; + detail?: string; + process?: number; + price?: number; + agentPrice?: number; + serviceCharge?: number; + remark?: string; }; function imageLocation(id: string) { From f8a317235fc24b689786c895e6f54ef69bfb6529 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 14 Jun 2024 17:57:58 +0700 Subject: [PATCH 102/157] chore: add bracket --- src/controllers/service/service-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 784736b..edba6d1 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -123,8 +123,9 @@ export class ServiceController extends Controller { where: { id: serviceId }, }); - if (!record) + if (!record) { throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); + } return Object.assign(record, { imageUrl: await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(record.id), 60 * 60), @@ -209,7 +210,6 @@ export class ServiceController extends Controller { }, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, ); - this.setStatus(HttpStatus.CREATED); return Object.assign(record, { From 09097df5f82817d02e418b8d3885defc431743f4 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 17 Jun 2024 09:26:01 +0700 Subject: [PATCH 103/157] fix: filter not as expected --- src/controllers/customer-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 0774a5a..73e662d 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -152,8 +152,8 @@ export class CustomerController extends Controller { }; const where = { OR: [ - { customerName: { contains: query }, customerType, status, ...filterStatus(status) }, - { customerNameEN: { contains: query }, customerType, status, ...filterStatus(status) }, + { customerName: { contains: query }, customerType, ...filterStatus(status) }, + { customerNameEN: { contains: query }, customerType, ...filterStatus(status) }, ], } satisfies Prisma.CustomerWhereInput; From e0184631dafc27aa418c7eeb150a473d44ad6be3 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:52:06 +0700 Subject: [PATCH 104/157] feat: add productType relation i/o --- src/controllers/product/product-controller.ts | 42 ++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 49a5092..d9b035b 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -34,6 +34,7 @@ type ProductCreate = { price: number; agentPrice: number; serviceCharge: number; + productTypeId: string; remark?: string; }; @@ -45,6 +46,7 @@ type ProductUpdate = { agentPrice?: number; serviceCharge?: number; remark?: string; + productTypeId?: string; }; function imageLocation(id: string) { @@ -58,6 +60,7 @@ export class ProductController extends Controller { @Get() async getProduct( @Query() status?: Status, + @Query() productTypeId?: string, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, @@ -72,8 +75,8 @@ export class ProductController extends Controller { const where = { OR: [ - { name: { contains: query }, ...filterStatus(status) }, - { detail: { contains: query }, ...filterStatus(status) }, + { name: { contains: query }, productTypeId, ...filterStatus(status) }, + { detail: { contains: query }, productTypeId, ...filterStatus(status) }, ], } satisfies Prisma.ProductWhereInput; @@ -119,8 +122,30 @@ export class ProductController extends Controller { }); } + @Get("{productId}/image") + async getProductImageById(@Request() req: RequestWithUser, @Path() productId: string) { + const url = await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(productId), 60 * 60); + if (!url) { + throw new HttpError(HttpStatus.NOT_FOUND, "Image cannot be found", "imageNotFound"); + } + + return; + } + @Post() async createProduct(@Request() req: RequestWithUser, @Body() body: ProductCreate) { + const productType = await prisma.productType.findFirst({ + where: { id: body.productTypeId }, + }); + + if (!productType) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product Type cannot be found.", + "relationProductTypeNotFound", + ); + } + const record = await prisma.$transaction( async (tx) => { const last = await tx.runningNo.upsert({ @@ -177,6 +202,19 @@ export class ProductController extends Controller { data: { ...body, updateBy: req.user.name }, where: { id: productId }, }); + + const productType = await prisma.productType.findFirst({ + where: { id: body.productTypeId }, + }); + + if (!productType) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Product Type cannot be found.", + "relationProductTypeNotFound", + ); + } + return Object.assign(record, { profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, From 1f54d5d1dfd24803c1bda653737ea850f4d25fb0 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:32:44 +0700 Subject: [PATCH 105/157] feat: image endpoint --- src/controllers/product/product-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index d9b035b..6bb2aeb 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -125,11 +125,12 @@ export class ProductController extends Controller { @Get("{productId}/image") async getProductImageById(@Request() req: RequestWithUser, @Path() productId: string) { const url = await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(productId), 60 * 60); + if (!url) { throw new HttpError(HttpStatus.NOT_FOUND, "Image cannot be found", "imageNotFound"); } - return; + return req.res?.redirect(url); } @Post() From 077edee0399a296deba7c64d6b425e6f80f330ff Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:58:30 +0700 Subject: [PATCH 106/157] feat: add fields --- prisma/migrations/20240617105818_add_field/migration.sql | 9 +++++++++ prisma/schema.prisma | 2 ++ src/controllers/customer-controller.ts | 4 ++++ 3 files changed, 15 insertions(+) create mode 100644 prisma/migrations/20240617105818_add_field/migration.sql diff --git a/prisma/migrations/20240617105818_add_field/migration.sql b/prisma/migrations/20240617105818_add_field/migration.sql new file mode 100644 index 0000000..0aa2292 --- /dev/null +++ b/prisma/migrations/20240617105818_add_field/migration.sql @@ -0,0 +1,9 @@ +/* + Warnings: + + - Added the required column `personName` to the `Customer` table without a default value. This is not possible if the table is not empty. + +*/ +-- AlterTable +ALTER TABLE "Customer" ADD COLUMN "personName" TEXT NOT NULL, +ADD COLUMN "personNameEN" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 549218b..ee0089d 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -332,6 +332,8 @@ enum CustomerType { model Customer { id String @id @default(uuid()) code String + personName String + personNameEN String? customerType CustomerType customerName String customerNameEN String diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 73e662d..bb459c7 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -27,6 +27,8 @@ const MINIO_BUCKET = process.env.MINIO_BUCKET; export type CustomerCreate = { status?: Status; + personName: string; + personNameEN?: string; customerType: CustomerType; customerName: string; customerNameEN: string; @@ -67,6 +69,8 @@ export type CustomerCreate = { export type CustomerUpdate = { status?: "ACTIVE" | "INACTIVE"; + personName: string; + personNameEN?: string; customerType?: CustomerType; customerName?: string; customerNameEN?: string; From 4d63ede738bfe1aba88ecbc6f5f48e169c5e62ca Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:19:15 +0700 Subject: [PATCH 107/157] fix: error not found (wrong table) --- src/controllers/product/type-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index a764c76..b207deb 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -130,7 +130,7 @@ export class ProductType extends Controller { ) { if ( body.productGroupId && - !(await prisma.productType.findFirst({ where: { id: body.productGroupId } })) + !(await prisma.productGroup.findFirst({ where: { id: body.productGroupId } })) ) { throw new HttpError( HttpStatus.BAD_REQUEST, From b423f3b3560df2e2034bbd17be2c64629674f62b Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:19:35 +0700 Subject: [PATCH 108/157] feat: update status on used --- src/controllers/product/type-controller.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index b207deb..d6fa9c1 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -117,6 +117,13 @@ export class ProductType extends Controller { { isolationLevel: Prisma.TransactionIsolationLevel.Serializable }, ); + if (productGroup.status === "CREATED") { + await prisma.productGroup.update({ + where: { id: body.productGroupId }, + data: { status: Status.ACTIVE }, + }); + } + this.setStatus(HttpStatus.CREATED); return record; From 212fec4f14c644bea163a455cfa969805625f08c Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 09:19:59 +0700 Subject: [PATCH 109/157] chore: add format --- src/controllers/product/type-controller.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index d6fa9c1..24d5d4f 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -73,7 +73,11 @@ export class ProductType extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); return record; } @@ -147,7 +151,11 @@ export class ProductType extends Controller { } if (!(await prisma.productType.findUnique({ where: { id: typeId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); } const record = await prisma.productType.update({ @@ -163,7 +171,11 @@ export class ProductType extends Controller { const record = await prisma.productType.findFirst({ where: { id: typeId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product type cannot be found.", "productTypeNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product type cannot be found.", + "productTypeNotFound", + ); } if (record.status !== Status.CREATED) { From a018f69f91f92ee15381e5532cbbd93a55afa859 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:56:28 +0700 Subject: [PATCH 110/157] feat: expose image endpoint to public --- src/controllers/product/product-controller.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 6bb2aeb..68b3208 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -55,9 +55,9 @@ function imageLocation(id: string) { @Route("api/v1/product") @Tags("Product") -@Security("keycloak") export class ProductController extends Controller { @Get() + @Security("keycloak") async getProduct( @Query() status?: Status, @Query() productTypeId?: string, @@ -108,6 +108,7 @@ export class ProductController extends Controller { } @Get("{productId}") + @Security("keycloak") async getProductById(@Path() productId: string) { const record = await prisma.product.findFirst({ where: { id: productId }, @@ -134,6 +135,7 @@ export class ProductController extends Controller { } @Post() + @Security("keycloak") async createProduct(@Request() req: RequestWithUser, @Body() body: ProductCreate) { const productType = await prisma.productType.findFirst({ where: { id: body.productTypeId }, @@ -190,6 +192,7 @@ export class ProductController extends Controller { } @Put("{productId}") + @Security("keycloak") async editProduct( @Request() req: RequestWithUser, @Body() body: ProductUpdate, @@ -231,6 +234,7 @@ export class ProductController extends Controller { } @Delete("{productId}") + @Security("keycloak") async deleteProduct(@Path() productId: string) { const record = await prisma.product.findFirst({ where: { id: productId } }); From 865497bf292cfb2b53030578aa8252e193a7505d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:07:24 +0700 Subject: [PATCH 111/157] feat: add product stats --- src/controllers/product/product-controller.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 68b3208..e37b989 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -56,6 +56,11 @@ function imageLocation(id: string) { @Route("api/v1/product") @Tags("Product") export class ProductController extends Controller { + @Get("stats") + async getProductStats(@Query() productTypeId?: string) { + return await prisma.product.count({ where: { productTypeId } }); + } + @Get() @Security("keycloak") async getProduct( From 5a33c129c18f7e9411ac115d081db31eeed71d42 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:35:06 +0700 Subject: [PATCH 112/157] fix: error productId --- src/controllers/service/service-controller.ts | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index edba6d1..bdbb259 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -178,6 +178,26 @@ export class ServiceController extends Controller { update: { value: { increment: 1 } }, }); + const workList = await Promise.all( + (work || []).map(async (w, wIdx) => + tx.work.create({ + data: { + name: w.name, + order: wIdx + 1, + attributes: w.attributes, + productOnWork: { + createMany: { + data: w.productId.map((p, pIdx) => ({ + productId: p, + order: pIdx + 1, + })), + }, + }, + }, + }), + ), + ); + return tx.service.create({ include: { work: { @@ -194,15 +214,7 @@ export class ServiceController extends Controller { data: { ...payload, code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, - work: { - createMany: { - data: - work?.map((v, i) => ({ - ...v, - order: i + 1, - })) || [], - }, - }, + work: { connect: workList.map((v) => ({ id: v.id })) }, createdBy: req.user.name, updateBy: req.user.name, }, From 886cae7f94431a76f2a4b503fd50cc66c1d44156 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:35:45 +0700 Subject: [PATCH 113/157] fix: typo --- src/controllers/product/product-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index e37b989..b0fcf80 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -225,12 +225,12 @@ export class ProductController extends Controller { } return Object.assign(record, { - profileImageUrl: await presignedGetObjectIfExist( + imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, ), - profileImageUploadUrl: await minio.presignedPutObject( + imageUploadUrl: await minio.presignedPutObject( MINIO_BUCKET, imageLocation(record.id), 12 * 60 * 60, From a3207ea0269e2173221d4ddbb1458a18f55c8d15 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 14:10:31 +0700 Subject: [PATCH 114/157] feat: make field optional --- src/controllers/customer-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index bb459c7..c421f95 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -69,7 +69,7 @@ export type CustomerCreate = { export type CustomerUpdate = { status?: "ACTIVE" | "INACTIVE"; - personName: string; + personName?: string; personNameEN?: string; customerType?: CustomerType; customerName?: string; From 9ebbb5260f7ce309b3c53f54eea332ff7e40f708 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 16:11:02 +0700 Subject: [PATCH 115/157] feat: make field optional --- src/controllers/employee-controller.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index ab43b07..a4800fd 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -182,7 +182,7 @@ type EmployeeUpdate = { coverageExpireDate?: Date | null; }[]; - employeeOtherInfo: { + employeeOtherInfo?: { citizenId?: string | null; fatherFirstName?: string | null; fatherLastName?: string | null; @@ -656,11 +656,7 @@ export class EmployeeController extends Controller { } if (record.status !== Status.CREATED) { - throw new HttpError( - HttpStatus.FORBIDDEN, - "Employee is in used.", - "employeeInUsed", - ); + throw new HttpError(HttpStatus.FORBIDDEN, "Employee is in used.", "employeeInUsed"); } return await prisma.employee.delete({ where: { id: employeeId } }); From 9c56d4ad91e9be95c69a2584e29011620e5eff16 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:06:52 +0700 Subject: [PATCH 116/157] feat: update add status --- src/controllers/product/group-controller.ts | 20 +++++++++++++++++--- src/controllers/product/type-controller.ts | 17 +++++++++++++---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index 9f7735d..30e742e 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -23,12 +23,14 @@ type ProductGroupCreate = { name: string; detail: string; remark: string; + status?: Status; }; type ProductGroupUpdate = { name?: string; detail?: string; remark?: string; + status?: "ACTIVE" | "INACTIVE"; }; @Route("api/v1/product-group") @@ -66,7 +68,11 @@ export class ProductGroup extends Controller { }); if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); return record; } @@ -110,7 +116,11 @@ export class ProductGroup extends Controller { @Path() groupId: string, ) { if (!(await prisma.productGroup.findUnique({ where: { id: groupId } }))) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); } const record = await prisma.productGroup.update({ @@ -126,7 +136,11 @@ export class ProductGroup extends Controller { const record = await prisma.productGroup.findFirst({ where: { id: groupId } }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Product group cannot be found.", "productGroupNotFound"); + throw new HttpError( + HttpStatus.NOT_FOUND, + "Product group cannot be found.", + "productGroupNotFound", + ); } if (record.status !== Status.CREATED) { diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 24d5d4f..24eec0a 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -24,6 +24,7 @@ type ProductTypeCreate = { name: string; detail: string; remark: string; + status?: Status; }; type ProductTypeUpdate = { @@ -31,6 +32,7 @@ type ProductTypeUpdate = { name?: string; detail?: string; remark?: string; + status?: "ACTIVE" | "INACTIVE"; }; @Route("api/v1/product-type") @@ -139,10 +141,10 @@ export class ProductType extends Controller { @Body() body: ProductTypeUpdate, @Path() typeId: string, ) { - if ( - body.productGroupId && - !(await prisma.productGroup.findFirst({ where: { id: body.productGroupId } })) - ) { + const productGroup = await prisma.productGroup.findFirst({ + where: { id: body.productGroupId }, + }); + if (body.productGroupId && !productGroup) { throw new HttpError( HttpStatus.BAD_REQUEST, "Product group cannot be found.", @@ -163,6 +165,13 @@ export class ProductType extends Controller { where: { id: typeId }, }); + if (productGroup?.status === "CREATED") { + await prisma.productGroup.update({ + where: { id: body.productGroupId }, + data: { status: Status.ACTIVE }, + }); + } + return record; } From bf7676be7758929f042eceb41f5e4090084d2914 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:08:47 +0700 Subject: [PATCH 117/157] feat: change status of product type after used --- src/controllers/product/product-controller.ts | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index b0fcf80..1cb86f7 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -180,6 +180,13 @@ export class ProductController extends Controller { }, ); + if (productType.status === "CREATED") { + await prisma.productType.update({ + where: { id: body.productTypeId }, + data: { status: Status.ACTIVE }, + }); + } + this.setStatus(HttpStatus.CREATED); return Object.assign(record, { @@ -207,11 +214,6 @@ export class ProductController extends Controller { throw new HttpError(HttpStatus.NOT_FOUND, "Product cannot be found.", "productNotFound"); } - const record = await prisma.product.update({ - data: { ...body, updateBy: req.user.name }, - where: { id: productId }, - }); - const productType = await prisma.productType.findFirst({ where: { id: body.productTypeId }, }); @@ -224,6 +226,18 @@ export class ProductController extends Controller { ); } + const record = await prisma.product.update({ + data: { ...body, updateBy: req.user.name }, + where: { id: productId }, + }); + + if (productType.status === "CREATED") { + await prisma.productType.update({ + where: { id: body.productTypeId }, + data: { status: Status.ACTIVE }, + }); + } + return Object.assign(record, { imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, From 0edc4e4e9606019beb140ae2db3d3fb077368f80 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:59:48 +0700 Subject: [PATCH 118/157] chore: change swagger order --- tsoa.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsoa.json b/tsoa.json index a5becec..b6acbc9 100644 --- a/tsoa.json +++ b/tsoa.json @@ -32,8 +32,8 @@ { "name": "Product Group" }, { "name": "Product Type" }, { "name": "Product" }, - { "name": "Service" }, - { "name": "Work" } + { "name": "Work" }, + { "name": "Service" } ] } }, From efc37ad80f6d0c89cd12e5d88c8c141d441cca15 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 20 Jun 2024 13:31:07 +0700 Subject: [PATCH 119/157] fix: missing input field --- src/controllers/product/product-controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 1cb86f7..a74b0f5 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -27,6 +27,7 @@ if (!process.env.MINIO_BUCKET) { const MINIO_BUCKET = process.env.MINIO_BUCKET; type ProductCreate = { + status?: Status; code: "AC" | "DO" | "ac" | "do"; name: string; detail: string; @@ -39,6 +40,7 @@ type ProductCreate = { }; type ProductUpdate = { + status?: "ACTIVE" | "INACTIVE"; name?: string; detail?: string; process?: number; From dc21fc434d7734c1291e7d46f80db9868ea2bdac Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:32:15 +0700 Subject: [PATCH 120/157] feat: add parameter for base only work --- src/controllers/work/work-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index bff06fe..547f8a8 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -43,12 +43,13 @@ type WorkUpdate = { export class WorkController extends Controller { @Get() async getWork( + @Query() baseOnly?: boolean, @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, ) { const where = { - OR: [{ name: { contains: query } }], + OR: [{ name: { contains: query }, serviceId: baseOnly ? null : undefined }], } satisfies Prisma.WorkWhereInput; const [result, total] = await prisma.$transaction([ From 3b045ecf5020d203575791fa12b6c116c400af6a Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:14:10 +0700 Subject: [PATCH 121/157] fix: update service --- src/controllers/service/service-controller.ts | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index bdbb259..95f7d4d 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -247,26 +247,40 @@ export class ServiceController extends Controller { if (!(await prisma.service.findUnique({ where: { id: serviceId } }))) { throw new HttpError(HttpStatus.NOT_FOUND, "Service cannot be found.", "serviceNotFound"); } - const { work, ...payload } = body; - - const record = await prisma.service.update({ - data: { - ...payload, - work: { - deleteMany: {}, - createMany: { - data: - work?.map((v, i) => ({ - order: i + 1, - ...v, - })) || [], + const record = await prisma.$transaction(async (tx) => { + const workList = await Promise.all( + (work || []).map(async (w, wIdx) => + tx.work.create({ + data: { + name: w.name, + order: wIdx + 1, + attributes: w.attributes, + productOnWork: { + createMany: { + data: w.productId.map((p, pIdx) => ({ + productId: p, + order: pIdx + 1, + })), + }, + }, + }, + }), + ), + ); + return await prisma.service.update({ + data: { + ...payload, + work: { + deleteMany: {}, + connect: workList.map((v) => ({ id: v.id })), }, + updateBy: req.user.name, }, - updateBy: req.user.name, - }, - where: { id: serviceId }, + where: { id: serviceId }, + }); }); + return Object.assign(record, { imageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, From 6c70966a21f483a708f6973391f3bf70f59bc20f Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:23:03 +0700 Subject: [PATCH 122/157] fix: wrong instance use --- src/controllers/service/service-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 95f7d4d..6eb29d8 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -268,7 +268,8 @@ export class ServiceController extends Controller { }), ), ); - return await prisma.service.update({ + + return await tx.service.update({ data: { ...payload, work: { From aa8dcdaf86e6943277c470b81c6f0455b08cff6b Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 21 Jun 2024 14:39:00 +0700 Subject: [PATCH 123/157] feat: separate service image endpoint --- src/controllers/service/service-controller.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 6eb29d8..ddfdee2 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -59,14 +59,15 @@ function imageLocation(id: string) { @Route("api/v1/service") @Tags("Service") -@Security("keycloak") export class ServiceController extends Controller { @Get("stats") + @Security("keycloak") async getServiceStats() { return await prisma.service.count(); } @Get() + @Security("keycloak") async getService( @Query() query: string = "", @Query() page: number = 1, @@ -107,6 +108,7 @@ export class ServiceController extends Controller { } @Get("{serviceId}") + @Security("keycloak") async getServiceById(@Path() serviceId: string) { const record = await prisma.service.findFirst({ include: { @@ -133,6 +135,7 @@ export class ServiceController extends Controller { } @Get("{serviceId}/work") + @Security("keycloak") async getWorkOfService( @Path() serviceId: string, @Query() page: number = 1, @@ -161,7 +164,19 @@ export class ServiceController extends Controller { return { result, page, pageSize, total }; } + @Get("{serviceId}/image") + async getServiceImageById(@Request() req: RequestWithUser, @Path() serviceId: string) { + const url = await presignedGetObjectIfExist(MINIO_BUCKET, imageLocation(serviceId), 60 * 60); + + if (!url) { + throw new HttpError(HttpStatus.NOT_FOUND, "Image cannot be found", "imageNotFound"); + } + + return req.res?.redirect(url); + } + @Post() + @Security("keycloak") async createService(@Request() req: RequestWithUser, @Body() body: ServiceCreate) { const { work, ...payload } = body; @@ -239,6 +254,7 @@ export class ServiceController extends Controller { } @Put("{serviceId}") + @Security("keycloak") async editService( @Request() req: RequestWithUser, @Body() body: ServiceUpdate, @@ -297,6 +313,7 @@ export class ServiceController extends Controller { } @Delete("{serviceId}") + @Security("keycloak") async deleteService(@Path() serviceId: string) { const record = await prisma.service.findFirst({ where: { id: serviceId } }); From 0bd2c1ecf2cfc013c4848fdd8810887ea6ca2122 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:14:44 +0700 Subject: [PATCH 124/157] feat: add order field --- .../migration.sql | 29 ++++++++++++++++ prisma/schema.prisma | 33 ++++++++++++------- src/controllers/branch-contact-controller.ts | 6 +--- src/controllers/branch-controller.ts | 2 ++ src/controllers/customer-branch-controller.ts | 8 ++++- src/controllers/customer-controller.ts | 2 ++ src/controllers/employee-controller.ts | 2 ++ src/controllers/product/group-controller.ts | 3 +- src/controllers/product/product-controller.ts | 7 ++-- src/controllers/product/type-controller.ts | 5 +-- src/controllers/user-controller.ts | 8 +++-- 11 files changed, 79 insertions(+), 26 deletions(-) create mode 100644 prisma/migrations/20240624061417_add_order_status/migration.sql diff --git a/prisma/migrations/20240624061417_add_order_status/migration.sql b/prisma/migrations/20240624061417_add_order_status/migration.sql new file mode 100644 index 0000000..436649e --- /dev/null +++ b/prisma/migrations/20240624061417_add_order_status/migration.sql @@ -0,0 +1,29 @@ +-- AlterTable +ALTER TABLE "Branch" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Customer" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "CustomerBranch" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Employee" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Product" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "ProductGroup" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "ProductType" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Service" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "User" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; + +-- AlterTable +ALTER TABLE "Work" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index ee0089d..69329b8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -212,7 +212,8 @@ model Branch { headOffice Branch? @relation(name: "HeadOfficeRelation", fields: [headOfficeId], references: [id]) headOfficeId String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -312,7 +313,8 @@ model User { birthDate DateTime? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -339,7 +341,8 @@ model Customer { customerNameEN String taxNo String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -393,7 +396,8 @@ model CustomerBranch { payDate DateTime wageRate Int - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -452,7 +456,8 @@ model Employee { customerBranch CustomerBranch? @relation(fields: [customerBranchId], references: [id], onDelete: SetNull) customerBranchId String? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -544,8 +549,10 @@ model Service { detail String attributes Json? - status Status @default(CREATED) - work Work[] + status Status @default(CREATED) + statusOrder Int @default(0) + + work Work[] createdBy String? createdAt DateTime @default(now()) @@ -560,7 +567,8 @@ model Work { name String attributes Json? - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) service Service? @relation(fields: [serviceId], references: [id], onDelete: Cascade) serviceId String? @@ -596,7 +604,8 @@ model ProductGroup { detail String remark String - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -614,7 +623,8 @@ model ProductType { detail String remark String - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) createdBy String? createdAt DateTime @default(now()) @@ -638,7 +648,8 @@ model Product { agentPrice Int serviceCharge Int - status Status @default(CREATED) + status Status @default(CREATED) + statusOrder Int @default(0) remark String? diff --git a/src/controllers/branch-contact-controller.ts b/src/controllers/branch-contact-controller.ts index e2e3d6c..701e4b3 100644 --- a/src/controllers/branch-contact-controller.ts +++ b/src/controllers/branch-contact-controller.ts @@ -76,11 +76,7 @@ export class BranchContactController extends Controller { @Body() body: BranchContactCreate, ) { if (!(await prisma.branch.findFirst({ where: { id: branchId } }))) { - throw new HttpError( - HttpStatus.BAD_REQUEST, - "Branch cannot be found.", - "branchBadReq", - ); + throw new HttpError(HttpStatus.BAD_REQUEST, "Branch cannot be found.", "branchBadReq"); } const record = await prisma.branchContact.create({ data: { ...body, branchId, createdBy: req.user.name, updateBy: req.user.name }, diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index bf61974..8008edb 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -279,6 +279,7 @@ export class BranchController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), code, isHeadOffice: !headOfficeId, province: { connect: provinceId ? { id: provinceId } : undefined }, @@ -384,6 +385,7 @@ export class BranchController extends Controller { include: { province: true, district: true, subDistrict: true }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), isHeadOffice: headOfficeId !== undefined ? headOfficeId === null : undefined, province: { connect: provinceId ? { id: provinceId } : undefined, diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 5bd51c4..0b6b5cb 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -287,6 +287,7 @@ export class CustomerBranchController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), branchNo: count + 1, code: `${customer.code}-${(count + 1).toString().padStart(2, "0")}`, customer: { connect: { id: customerId } }, @@ -365,6 +366,7 @@ export class CustomerBranchController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), customer: { connect: customerId ? { id: customerId } : undefined }, province: { connect: provinceId ? { id: provinceId } : undefined, @@ -403,7 +405,11 @@ export class CustomerBranchController extends Controller { } if (record.status !== Status.CREATED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Customer branch is in used.", "customerBranchInUsed"); + throw new HttpError( + HttpStatus.FORBIDDEN, + "Customer branch is in used.", + "customerBranchInUsed", + ); } return await prisma.customerBranch.delete({ where: { id: branchId } }).then((v) => { diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index c421f95..3798e89 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -296,6 +296,7 @@ export class CustomerController extends Controller { }, data: { ...payload, + statusOrder: +(payload.status === "INACTIVE"), code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}`, branch: { createMany: { @@ -420,6 +421,7 @@ export class CustomerController extends Controller { where: { id: customerId }, data: { ...payload, + statusOrder: +(payload.status === "INACTIVE"), branch: (customerBranch && { deleteMany: { diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index a4800fd..f0e11db 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -395,6 +395,7 @@ export class EmployeeController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), code: `${customerBranch.customer.code}-${customerBranch.branchNo.toString().padStart(2, "0")}-${new Date().getFullYear().toString().slice(-2).padStart(2, "0")}${last.value.toString().padStart(4, "0")}`, employeeWork: { createMany: { @@ -562,6 +563,7 @@ export class EmployeeController extends Controller { }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), code, customerBranch: { connect: customerBranchId ? { id: customerBranchId } : undefined }, employeeWork: employeeWork diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index 30e742e..f27b7e1 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -95,6 +95,7 @@ export class ProductGroup extends Controller { return await tx.productGroup.create({ data: { ...body, + statusOrder: +(body.status === "INACTIVE"), code: `G${last.value.toString().padStart(2, "0")}`, createdBy: req.user.name, updateBy: req.user.name, @@ -124,7 +125,7 @@ export class ProductGroup extends Controller { } const record = await prisma.productGroup.update({ - data: { ...body, updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, where: { id: groupId }, }); diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index a74b0f5..3c71ad2 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -171,6 +171,7 @@ export class ProductController extends Controller { return await prisma.product.create({ data: { ...body, + statusOrder: +(body.status === "INACTIVE"), code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, createdBy: req.user.name, updateBy: req.user.name, @@ -229,13 +230,13 @@ export class ProductController extends Controller { } const record = await prisma.product.update({ - data: { ...body, updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, where: { id: productId }, }); if (productType.status === "CREATED") { - await prisma.productType.update({ - where: { id: body.productTypeId }, + await prisma.productType.updateMany({ + where: { id: body.productTypeId, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); } diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 24eec0a..89d5a22 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -114,6 +114,7 @@ export class ProductType extends Controller { return await tx.productType.create({ data: { ...body, + statusOrder: +(body.status === "INACTIVE"), code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, createdBy: req.user.name, updateBy: req.user.name, @@ -161,13 +162,13 @@ export class ProductType extends Controller { } const record = await prisma.productType.update({ - data: { ...body, updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, where: { id: typeId }, }); if (productGroup?.status === "CREATED") { await prisma.productGroup.update({ - where: { id: body.productGroupId }, + where: { id: body.productGroupId, status: Status.CREATED }, data: { status: Status.ACTIVE }, }); } diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 06e58e8..fdfb338 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -209,8 +209,7 @@ export class UserController extends Controller { where: { id: userId }, }); - if (!record) - throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); + if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found.", "userNotFound"); return Object.assign(record, { profileImageUrl: await minio.presignedGetObject( @@ -268,6 +267,7 @@ export class UserController extends Controller { firstName: body.firstName, lastName: body.lastName, requiredActions: ["UPDATE_PASSWORD"], + enabled: rest.status !== "INACTIVE", }); if (!userId || typeof userId !== "string") { @@ -288,6 +288,7 @@ export class UserController extends Controller { data: { id: userId, ...rest, + statusOrder: +(rest.status === "INACTIVE"), username, userRole: role.name, province: { connect: provinceId ? { id: provinceId } : undefined }, @@ -386,7 +387,7 @@ export class UserController extends Controller { } if (body.username) { - await editUser(userId, { username: body.username }); + await editUser(userId, { username: body.username, enabled: body.status !== "INACTIVE" }); } const { provinceId, districtId, subDistrictId, ...rest } = body; @@ -415,6 +416,7 @@ export class UserController extends Controller { include: { province: true, district: true, subDistrict: true }, data: { ...rest, + statusOrder: +(rest.status === "INACTIVE"), userRole, code: (lastUserOfType && From 09cf32d3c7ebdc8da78c384c87bff2889a97879e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 13:20:59 +0700 Subject: [PATCH 125/157] feat: order by status field --- src/controllers/customer-branch-controller.ts | 2 +- src/controllers/customer-controller.ts | 2 +- src/controllers/employee-controller.ts | 2 +- src/controllers/product/group-controller.ts | 5 ++++- src/controllers/product/product-controller.ts | 2 +- src/controllers/product/type-controller.ts | 5 ++++- src/controllers/service/service-controller.ts | 2 +- src/controllers/user-controller.ts | 2 +- 8 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index 0b6b5cb..ff7eac6 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -152,7 +152,7 @@ export class CustomerBranchController extends Controller { const [result, total] = await prisma.$transaction([ prisma.customerBranch.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { customer: includeCustomer, province: true, diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 3798e89..6b712cc 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -175,7 +175,7 @@ export class CustomerController extends Controller { } : undefined, }, - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, skip: (page - 1) * pageSize, diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index f0e11db..edb780b 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -253,7 +253,7 @@ export class EmployeeController extends Controller { const [result, total] = await prisma.$transaction([ prisma.employee.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { province: true, district: true, diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index f27b7e1..c57e767 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -58,7 +58,10 @@ export class ProductGroup extends Controller { { detail: { contains: query }, ...filterStatus(status) }, ], } satisfies Prisma.ProductGroupWhereInput; - return prisma.productGroup.findMany({ orderBy: { createdAt: "asc" }, where }); + return prisma.productGroup.findMany({ + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + }); } @Get("{groupId}") diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 3c71ad2..79bf0da 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -89,7 +89,7 @@ export class ProductController extends Controller { const [result, total] = await prisma.$transaction([ prisma.product.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, skip: (page - 1) * pageSize, diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 89d5a22..b88d668 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -64,7 +64,10 @@ export class ProductType extends Controller { { detail: { contains: query }, ...filterStatus(status) }, ], } satisfies Prisma.ProductTypeWhereInput; - const result = prisma.productType.findMany({ orderBy: { createdAt: "asc" }, where }); + const result = prisma.productType.findMany({ + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + }); return result; } diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index ddfdee2..70ea3bf 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -82,7 +82,7 @@ export class ServiceController extends Controller { include: { work: true, }, - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, skip: (page - 1) * pageSize, diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index fdfb338..73f0ef4 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -166,7 +166,7 @@ export class UserController extends Controller { const [result, total] = await prisma.$transaction([ prisma.user.findMany({ - orderBy: { createdAt: "asc" }, + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], include: { province: true, district: true, From bf5d72a43da2a0d751703b063bb81d6d50c548a4 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:17:17 +0700 Subject: [PATCH 126/157] fix: make optional --- src/controllers/service/service-controller.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 70ea3bf..9df9f42 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -41,8 +41,8 @@ type ServiceCreate = { }; type ServiceUpdate = { - name: string; - detail: string; + name?: string; + detail?: string; attributes?: { [key: string]: any; }; From 8918c8f2d63a48d6bd8986fb6e60874b8b65ebb5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:22:14 +0700 Subject: [PATCH 127/157] fix: missing type --- src/controllers/service/service-controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 9df9f42..594ec8e 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -33,6 +33,7 @@ type ServiceCreate = { attributes?: { [key: string]: any; }; + status?: Status; work?: { name: string; productId: string[]; @@ -46,6 +47,7 @@ type ServiceUpdate = { attributes?: { [key: string]: any; }; + status: "ACTIVE" | "INACTIVE"; work?: { name: string; productId: string[]; From 784528eabb6ae91faa76713856d1495f9d18f75c Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:23:10 +0700 Subject: [PATCH 128/157] fix: update status order --- src/controllers/service/service-controller.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 594ec8e..72fb3da 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -230,6 +230,7 @@ export class ServiceController extends Controller { }, data: { ...payload, + statusOrder: +(body.status === "INACTIVE"), code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, work: { connect: workList.map((v) => ({ id: v.id })) }, createdBy: req.user.name, @@ -290,6 +291,7 @@ export class ServiceController extends Controller { return await tx.service.update({ data: { ...payload, + statusOrder: +(payload.status === "INACTIVE"), work: { deleteMany: {}, connect: workList.map((v) => ({ id: v.id })), From ce328658e4342c362a576f28d5ba901b77767b38 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 16:19:49 +0700 Subject: [PATCH 129/157] fix: make optional --- src/controllers/service/service-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 72fb3da..8a507c6 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -47,7 +47,7 @@ type ServiceUpdate = { attributes?: { [key: string]: any; }; - status: "ACTIVE" | "INACTIVE"; + status?: "ACTIVE" | "INACTIVE"; work?: { name: string; productId: string[]; From acec110c513efa45ffaca347973a81b31480ebef Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 24 Jun 2024 20:20:02 +0700 Subject: [PATCH 130/157] feat: add query product service together --- src/controllers/product-service-controller.ts | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/controllers/product-service-controller.ts diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts new file mode 100644 index 0000000..13585ac --- /dev/null +++ b/src/controllers/product-service-controller.ts @@ -0,0 +1,88 @@ +import { Controller, Get, Query, Route } from "tsoa"; +import prisma from "../db"; +import { Prisma, Product, Service } from "@prisma/client"; + +@Route("product-service") +export class ProductServiceController extends Controller { + @Get() + async getProductService( + @Query() status?: "ACTIVE" | "INACTIVE", + @Query() productTypeId?: string, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { + const union = Prisma.sql` + SELECT + "id", + "code", + "name", + "detail", + "price", + "agentPrice", + "serviceCharge", + "process", + "remark", + "status", + "statusOrder", + "productTypeId", + "createdBy", + "createdAt", + "updateBy", + "updatedAt", + 'product' as "type" + FROM "Product" + UNION ALL + SELECT + "id", + "code", + "name", + "detail", + null as "price", + null as "agentPrice", + null as "serviceCharge", + null as "process", + null as "remark", + "status", + "statusOrder", + null as "productTypeId", + "createdBy", + "createdAt", + "updateBy", + "updatedAt", + 'service' as "type" + FROM "Service" + `; + + const or: Prisma.Sql[] = []; + const and: Prisma.Sql[] = []; + + if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); + if (productTypeId) and.push(Prisma.sql`"productTypeId" = ${productTypeId}`); + + const where = Prisma.sql` + ${or.length > 0 || and.length > 0 ? Prisma.sql`WHERE ` : Prisma.empty} + ${or.length > 0 ? Prisma.join(or, " OR ", "(", ")") : Prisma.empty} + ${or.length > 0 && and.length > 0 ? Prisma.sql` AND ` : Prisma.empty} + ${and.length > 0 ? Prisma.join(and, " AND ", "(", ")") : Prisma.empty} + `; + + const [result, { total }] = await prisma.$transaction([ + prisma.$queryRaw<((Product & { type: "product" }) | (Service & { type: "service" }))[]>` + SELECT * FROM (${union}) AS "ProductService" + ${where} + ORDER BY "ProductService"."statusOrder" ASC, "ProductService"."createdAt" ASC + LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize} + `, + prisma.$queryRaw<{ total: number }>` + SELECT COUNT( * ) AS "total" FROM (${union}) as "ProductService" + ${where} + `, + ]); + return { + result, + page, + pageSize, + total, + }; + } +} From c79851d0746090ab2861f74db0d31ce06a2e72d7 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:30:08 +0700 Subject: [PATCH 131/157] fix: total count bigint cannot be serialize --- src/controllers/product-service-controller.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index 13585ac..c2aab92 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -66,15 +66,15 @@ export class ProductServiceController extends Controller { ${and.length > 0 ? Prisma.join(and, " AND ", "(", ")") : Prisma.empty} `; - const [result, { total }] = await prisma.$transaction([ + const [result, [{ total }]] = await prisma.$transaction([ prisma.$queryRaw<((Product & { type: "product" }) | (Service & { type: "service" }))[]>` SELECT * FROM (${union}) AS "ProductService" ${where} ORDER BY "ProductService"."statusOrder" ASC, "ProductService"."createdAt" ASC LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize} `, - prisma.$queryRaw<{ total: number }>` - SELECT COUNT( * ) AS "total" FROM (${union}) as "ProductService" + prisma.$queryRaw<[{ total: number }]>` + SELECT COUNT(*) AS "total" FROM (${union}) as "ProductService" ${where} `, ]); @@ -82,7 +82,7 @@ export class ProductServiceController extends Controller { result, page, pageSize, - total, + total: +String(total), }; } } From d6fa6dfee1b7203a472fd463bd050960e7c46be5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:54:59 +0700 Subject: [PATCH 132/157] feata: add relation to service --- src/controllers/product-service-controller.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index c2aab92..d6b9810 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -78,8 +78,15 @@ export class ProductServiceController extends Controller { ${where} `, ]); + + const work = await prisma.work.findMany({ + where: { serviceId: { in: result.flatMap((v) => (v.type === "service" ? v.id : [])) } }, + }); + return { - result, + result: result.map((v) => + v.type === "service" ? { ...v, work: work.filter((w) => w.serviceId === v.id) || [] } : v, + ), page, pageSize, total: +String(total), From 6550ce1bb388195852e44028112c9da5b1e70bb7 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:53:13 +0700 Subject: [PATCH 133/157] feat: add query --- src/controllers/product-service-controller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index d6b9810..7a976f2 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -2,11 +2,12 @@ import { Controller, Get, Query, Route } from "tsoa"; import prisma from "../db"; import { Prisma, Product, Service } from "@prisma/client"; -@Route("product-service") +@Route("/api/v1/product-service") export class ProductServiceController extends Controller { @Get() async getProductService( @Query() status?: "ACTIVE" | "INACTIVE", + @Query() query = "", @Query() productTypeId?: string, @Query() page: number = 1, @Query() pageSize: number = 30, @@ -56,6 +57,7 @@ export class ProductServiceController extends Controller { const or: Prisma.Sql[] = []; const and: Prisma.Sql[] = []; + if (query) or.push(Prisma.sql`"name" LIKE '%${query}%'`); if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); if (productTypeId) and.push(Prisma.sql`"productTypeId" = ${productTypeId}`); From e3e44d03b59d83258d57dd26be545f79e447b9e2 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:00:15 +0700 Subject: [PATCH 134/157] fix: service not included in result --- src/controllers/product-service-controller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index 7a976f2..c7954b7 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -59,7 +59,9 @@ export class ProductServiceController extends Controller { if (query) or.push(Prisma.sql`"name" LIKE '%${query}%'`); if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); - if (productTypeId) and.push(Prisma.sql`"productTypeId" = ${productTypeId}`); + if (productTypeId) { + and.push(Prisma.sql`("productTypeId" = ${productTypeId} OR ("type" = 'service'))`); + } const where = Prisma.sql` ${or.length > 0 || and.length > 0 ? Prisma.sql`WHERE ` : Prisma.empty} From cd47863f2a2a206e3248f6508f3be059f5d306df Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:10:42 +0700 Subject: [PATCH 135/157] feat: inject sessionId for logging purpose --- src/middlewares/auth.ts | 10 ++++++++-- src/middlewares/log.ts | 3 ++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index 5aecde8..783e933 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -10,8 +10,14 @@ export async function expressAuthentication( ) { switch (securityName) { case "keycloak": - return keycloakAuth(request, scopes); + const authData = await keycloakAuth(request, scopes); + request.app.locals.logData.sessionId = authData.session_state; + return authData; default: - throw new HttpError(HttpStatus.NOT_IMPLEMENTED, "Unknown how to verify identity.", "unknowHowToVerify"); + throw new HttpError( + HttpStatus.NOT_IMPLEMENTED, + "Unknown how to verify identity.", + "unknowHowToVerify", + ); } } diff --git a/src/middlewares/log.ts b/src/middlewares/log.ts index 5e8eb01..d7ab8db 100644 --- a/src/middlewares/log.ts +++ b/src/middlewares/log.ts @@ -1,5 +1,6 @@ import { NextFunction, Request, Response } from "express"; import elasticsearch from "../services/elasticsearch"; +import { randomUUID } from "crypto"; if (!process.env.ELASTICSEARCH_INDEX) { throw new Error("Require ELASTICSEARCH_INDEX to store log."); @@ -50,7 +51,7 @@ async function logMiddleware(req: Request, res: Response, next: NextFunction) { host: req.hostname, sessionId: req.headers["x-session-id"], rtId: req.headers["x-rtid"], - tId: req.headers["x-tid"], + tId: randomUUID(), method: req.method, endpoint: req.url, responseCode: res.statusCode, From 71fcc30f427175dd9fa8765d85175d2c637ed192 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:09:54 +0700 Subject: [PATCH 136/157] feat: add status query string param --- src/controllers/service/service-controller.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 8a507c6..171869f 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -74,9 +74,21 @@ export class ServiceController extends Controller { @Query() query: string = "", @Query() page: number = 1, @Query() pageSize: number = 30, + @Query() status?: Status, ) { + const filterStatus = (val?: Status) => { + if (!val) return {}; + + return val !== Status.CREATED && val !== Status.ACTIVE + ? { status: val } + : { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] }; + }; + const where = { - OR: [{ name: { contains: query } }, { detail: { contains: query } }], + OR: [ + { name: { contains: query }, ...filterStatus(status) }, + { detail: { contains: query }, ...filterStatus(status) }, + ], } satisfies Prisma.ServiceWhereInput; const [result, total] = await prisma.$transaction([ From 7cf75edf761695e829d1ad521c207e19f798d706 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:54:48 +0700 Subject: [PATCH 137/157] feat: add security --- src/controllers/product-service-controller.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index c7954b7..669079f 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -1,10 +1,11 @@ -import { Controller, Get, Query, Route } from "tsoa"; +import { Controller, Get, Query, Route, Security } from "tsoa"; import prisma from "../db"; import { Prisma, Product, Service } from "@prisma/client"; @Route("/api/v1/product-service") export class ProductServiceController extends Controller { @Get() + @Security("keycloak") async getProductService( @Query() status?: "ACTIVE" | "INACTIVE", @Query() query = "", From 3211cbe8b70804060467f07f1e2900bb071159f6 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:54:58 +0700 Subject: [PATCH 138/157] fix: query --- src/controllers/product-service-controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index 669079f..95bb9ff 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -58,7 +58,7 @@ export class ProductServiceController extends Controller { const or: Prisma.Sql[] = []; const and: Prisma.Sql[] = []; - if (query) or.push(Prisma.sql`"name" LIKE '%${query}%'`); + if (query) or.push(Prisma.sql`"name" LIKE ${`%${query}%`}`); if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); if (productTypeId) { and.push(Prisma.sql`("productTypeId" = ${productTypeId} OR ("type" = 'service'))`); From e3dac5529f2eff95a7d3cf7d20be36aa5b931389 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:12:53 +0700 Subject: [PATCH 139/157] feat: paging group / type product --- src/controllers/product/group-controller.ts | 21 ++++++++++++++++----- src/controllers/product/type-controller.ts | 16 +++++++++++----- 2 files changed, 27 insertions(+), 10 deletions(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index c57e767..fb5b568 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -43,7 +43,12 @@ export class ProductGroup extends Controller { } @Get() - async getProductGroup(@Query() query: string = "", @Query() status?: Status) { + async getProductGroup( + @Query() query: string = "", + @Query() status?: Status, + @Query() page: number = 1, + @Query() pageSize: number = 30, + ) { const filterStatus = (val?: Status) => { if (!val) return {}; @@ -58,10 +63,16 @@ export class ProductGroup extends Controller { { detail: { contains: query }, ...filterStatus(status) }, ], } satisfies Prisma.ProductGroupWhereInput; - return prisma.productGroup.findMany({ - orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], - where, - }); + + const [result, total] = await prisma.$transaction([ + prisma.productGroup.findMany({ + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + }), + prisma.productGroup.count({ where }), + ]); + + return { result, page, pageSize, total }; } @Get("{groupId}") diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index b88d668..4d5bc9c 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -49,6 +49,8 @@ export class ProductType extends Controller { @Query() query: string = "", @Query() productGroupId?: string, @Query() status?: Status, + @Query() page: number = 1, + @Query() pageSize: number = 30, ) { const filterStatus = (val?: Status) => { if (!val) return {}; @@ -64,11 +66,15 @@ export class ProductType extends Controller { { detail: { contains: query }, ...filterStatus(status) }, ], } satisfies Prisma.ProductTypeWhereInput; - const result = prisma.productType.findMany({ - orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], - where, - }); - return result; + const [result, total] = await prisma.$transaction([ + prisma.productType.findMany({ + orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], + where, + }), + prisma.productType.count({ where }), + ]); + + return { result, page, pageSize, total }; } @Get("{typeId}") From 05dfe42b2ee6808c376d06a05b6ad44c03bd77fb Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:22:48 +0700 Subject: [PATCH 140/157] feat: adjust data type --- package.json | 3 + pnpm-lock.yaml | 1622 +++++++++++++++++ prisma/generated/types.ts | 459 +++++ .../20240626042218_adjust_type/migration.sql | 4 + prisma/schema.prisma | 10 +- src/db.ts | 18 +- 6 files changed, 2112 insertions(+), 4 deletions(-) create mode 100644 prisma/generated/types.ts create mode 100644 prisma/migrations/20240626042218_adjust_type/migration.sql diff --git a/package.json b/package.json index 68c01c0..63fdf94 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "nodemon": "^3.1.3", "prettier": "^3.2.5", "prisma": "^5.12.1", + "prisma-kysely": "^1.8.0", "ts-node": "^10.9.2", "typescript": "^5.4.3" }, @@ -36,7 +37,9 @@ "dotenv": "^16.4.5", "express": "^4.19.2", "fast-jwt": "^4.0.0", + "kysely": "^0.27.3", "minio": "^7.1.3", + "prisma-extension-kysely": "^2.1.0", "promise.any": "^2.0.6", "swagger-ui-express": "^5.0.0", "tsoa": "^6.2.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2c08993..796cb0f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,9 +29,15 @@ importers: fast-jwt: specifier: ^4.0.0 version: 4.0.0 + kysely: + specifier: ^0.27.3 + version: 0.27.3 minio: specifier: ^7.1.3 version: 7.1.3 + prisma-extension-kysely: + specifier: ^2.1.0 + version: 2.1.0(@prisma/client@5.12.1(prisma@5.12.1)) promise.any: specifier: ^2.0.6 version: 2.0.6 @@ -63,6 +69,9 @@ importers: prisma: specifier: ^5.12.1 version: 5.12.1 + prisma-kysely: + specifier: ^1.8.0 + version: 1.8.0 ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@20.12.2)(typescript@5.4.3) @@ -72,6 +81,34 @@ importers: packages: + '@antfu/ni@0.21.8': + resolution: {integrity: sha512-90X8pU2szlvw0AJo9EZMbYc2eQKkmO7mAdC4tD4r5co2Mm56MT37MIG8EyB7p4WRheuzGxuLDxJ63mF6+Zajiw==} + hasBin: true + + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + + '@chevrotain/cst-dts-gen@10.5.0': + resolution: {integrity: sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==} + + '@chevrotain/gast@10.5.0': + resolution: {integrity: sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==} + + '@chevrotain/types@10.5.0': + resolution: {integrity: sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==} + + '@chevrotain/utils@10.5.0': + resolution: {integrity: sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -193,6 +230,26 @@ packages: resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} engines: {node: '>=8'} + '@mrleebo/prisma-ast@0.7.0': + resolution: {integrity: sha512-GTPkYf1meO2UXXIrz/SIDFWz+P4kXo2PTt36LYh/oNxV1PieYi7ZgenQk4IV0ut71Je3Z8ZoNZ8Tr7v2c1X1pg==} + engines: {node: '>=16'} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@opentelemetry/api@1.4.1': + resolution: {integrity: sha512-O2yRJce1GOc6PAy3QxFM4NzFiWzvScDC1/5ihYBL6BUEVdq0XMWN01sppE+H6bBXbaFYipjwFLEWLg5PaSOThA==} + engines: {node: '>=8.0.0'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -209,18 +266,39 @@ packages: '@prisma/debug@5.12.1': resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==} + '@prisma/debug@5.3.1': + resolution: {integrity: sha512-eYrxqslEKf+wpMFIIHgbcNYuZBXUdiJLA85Or3TwOhgPIN1ZoXT9CwJph3ynW8H1Xg0LkdYLwVmuULCwiMoU5A==} + '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==} '@prisma/engines@5.12.1': resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==} + '@prisma/engines@5.3.1': + resolution: {integrity: sha512-6QkILNyfeeN67BNEPEtkgh3Xo2tm6D7V+UhrkBbRHqKw9CTaz/vvTP/ROwYSP/3JT2MtIutZm/EnhxUiuOPVDA==} + '@prisma/fetch-engine@5.12.1': resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==} + '@prisma/fetch-engine@5.3.1': + resolution: {integrity: sha512-w1yk1YiK8N82Pobdq58b85l6e8akyrkxuzwV9DoiUTRf3gpsuhJJesHc4Yi0WzUC9/3znizl1UfCsI6dhkj3Vw==} + + '@prisma/generator-helper@5.3.1': + resolution: {integrity: sha512-zrYS0iHLgPlOJjYnd5KvVMMvSS+ktOL39EwooS5EnyvfzwfzxlKCeOUgxTfiKYs0WUWqzEvyNAYtramYgSknsQ==} + '@prisma/get-platform@5.12.1': resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==} + '@prisma/get-platform@5.3.1': + resolution: {integrity: sha512-3IiZY2BUjKnAuZ0569zppZE6/rZbVAM09//c2nvPbbkGG9MqrirA8fbhhF7tfVmhyVfdmVCHnf/ujWPHJ8B46Q==} + + '@prisma/internals@5.3.1': + resolution: {integrity: sha512-zkW73hPHHNrMD21PeYgCTBfMu71vzJf+WtfydtJbS0JVJKyLfOel0iWSQg7wjNeQfccKp+NdHJ/5rTJ4NEUzgA==} + + '@prisma/prisma-schema-wasm@5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59': + resolution: {integrity: sha512-+zUI7NQDXfcNnU8HgrAj4jRMv8yRfITLzcfv0Urf0adKimM+hkkVG4rX38i9zWMlxekkEBw7NLFx3Gxxy8d3iQ==} + '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -260,6 +338,12 @@ packages: '@types/cors@2.8.17': resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/cross-spawn@6.0.2': + resolution: {integrity: sha512-KuwNhp3eza+Rhu8IFI5HUXRP0LIhqH5cAjubUvGXXthh4YYBuP2ntwEX+Cz8GJoZUHlKo247wPWOfA9LYEq4cw==} + + '@types/debug@4.1.8': + resolution: {integrity: sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==} + '@types/express-serve-static-core@4.17.43': resolution: {integrity: sha512-oaYtiBirUOPQGSWNGPWnzyAFJ0BP3cwvN4oWZQY+zUBwpVIGsKUkpBpSztp74drYcjavs7SKFZ4DX1V2QeN8rg==} @@ -288,18 +372,27 @@ packages: resolution: {integrity: sha512-5eEkJZ/BLvTE3vXGKkWlyTSUVZuzj23Wj8PoyOq2lt5I3CYbiLBOPb3XmCW6QcuOibIUE6emHXHt9E/F/rCa6w==} deprecated: This is a stub types definition. mime provides its own type definitions, so you do not need this installed. + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + '@types/multer@1.4.11': resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} '@types/node@20.12.2': resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + '@types/qs@6.9.14': resolution: {integrity: sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==} '@types/range-parser@1.2.7': resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + '@types/send@0.17.4': resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} @@ -328,6 +421,18 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + + aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -336,6 +441,10 @@ packages: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -348,9 +457,24 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + archiver-utils@2.1.0: + resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} + engines: {node: '>= 6'} + + archiver-utils@3.0.4: + resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==} + engines: {node: '>= 10'} + + archiver@5.3.2: + resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==} + engines: {node: '>= 10'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + array-buffer-byte-length@1.0.1: resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} engines: {node: '>= 0.4'} @@ -358,6 +482,10 @@ packages: array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + array.prototype.map@1.0.7: resolution: {integrity: sha512-XpcFfLoBEAhezrrNw1V+yLXkE7M6uR7xJEsxbG6c/V9v043qurwVJB9r9UTnoSioFDoz1i1VOydpWGmJpfVZbg==} engines: {node: '>= 0.4'} @@ -369,6 +497,10 @@ packages: asn1.js@5.4.1: resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} @@ -379,10 +511,16 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + block-stream2@2.1.0: resolution: {integrity: sha512-suhjmLI57Ewpmq00qaygS8UgEq2ly2PCItenIyhMqVjo4t4pGzqMvfgJuX8iWTeSDdfSSqS6j38fL4ToNL7Pfg==} @@ -403,12 +541,19 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + browser-or-node@2.1.1: resolution: {integrity: sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==} buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -417,21 +562,56 @@ packages: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + checkpoint-client@1.1.27: + resolution: {integrity: sha512-xstymfUalJOv6ZvTtmkwP4ORJN36ikT4PvrIoLe3wstbYf87XIXCcZrSmbFQOjyB0v1qbBnCsAscDpfdZlCkFA==} + + chevrotain@10.5.0: + resolution: {integrity: sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + ci-info@3.8.0: + resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + engines: {node: '>=8'} + + clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + + cli-truncate@2.1.0: + resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==} + engines: {node: '>=8'} + cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compress-commons@4.1.2: + resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==} + engines: {node: '>= 10'} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -450,10 +630,22 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cors@2.8.5: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} + crc-32@1.2.2: + resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} + engines: {node: '>=0.8'} + hasBin: true + + crc32-stream@4.0.3: + resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==} + engines: {node: '>= 10'} + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} @@ -461,6 +653,10 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -502,6 +698,10 @@ packages: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} + del@6.1.1: + resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} + engines: {node: '>=10'} + depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} @@ -514,6 +714,14 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dotenv@16.0.3: + resolution: {integrity: sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==} + engines: {node: '>=12'} + dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} @@ -537,6 +745,16 @@ packages: resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} engines: {node: '>= 0.8'} + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + es-abstract@1.23.3: resolution: {integrity: sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==} engines: {node: '>= 0.4'} @@ -578,14 +796,30 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + etag@1.8.1: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + express@4.19.2: resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} engines: {node: '>= 0.10.0'} + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + fast-jwt@4.0.0: resolution: {integrity: sha512-CnI93Tmk7eSzfw4e0Jlc5ZcWiN+/zK7xAKAhtXS8PAcKmYqfcXqxJl1hMyhk3iEt0M9JLo7DCYRDV2XcIacWAw==} engines: {node: '>=16 <22'} @@ -594,10 +828,17 @@ packages: resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==} hasBin: true + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + filter-obj@1.1.0: resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} engines: {node: '>=0.10.0'} @@ -606,6 +847,18 @@ packages: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -617,14 +870,30 @@ packages: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} + fp-ts@2.16.1: + resolution: {integrity: sha512-by7U5W8dkIzcvDofUcO42yl9JbnHTEDBrzu3pt5fKT+Z4Oy85I21K80EYJYdjQGC2qum4Vo55Ag57iiIK4FYuA==} + fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + + fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} + fs-jetpack@5.1.0: + resolution: {integrity: sha512-Xn4fDhLydXkuzepZVsr02jakLlmoARPy+YWIclo4kh0GyNGUHnTqeH/w/qIsVn50dFxtp8otPL2t/HcPJBbxUA==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -648,6 +917,10 @@ packages: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} engines: {node: '>= 0.4'} + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -661,10 +934,27 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + + global-dirs@3.0.1: + resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} + engines: {node: '>=10'} + globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} @@ -683,6 +973,10 @@ packages: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -698,10 +992,17 @@ packages: resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} engines: {node: '>= 0.4'} + hasha@5.2.2: + resolution: {integrity: sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==} + engines: {node: '>=8'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + hpagent@1.2.0: resolution: {integrity: sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==} engines: {node: '>=14'} @@ -710,16 +1011,51 @@ packages: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} + http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + ignore-by-default@1.0.1: resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + ignore-walk@5.0.1: + resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + ini@2.0.0: + resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} + engines: {node: '>=10'} + internal-slot@1.0.7: resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} engines: {node: '>= 0.4'} @@ -740,6 +1076,9 @@ packages: resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} engines: {node: '>= 0.4'} + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} @@ -755,6 +1094,10 @@ packages: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} + is-core-module@2.14.0: + resolution: {integrity: sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==} + engines: {node: '>= 0.4'} + is-data-view@1.0.1: resolution: {integrity: sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==} engines: {node: '>= 0.4'} @@ -763,6 +1106,11 @@ packages: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -795,6 +1143,14 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} + is-path-cwd@2.2.0: + resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} + engines: {node: '>=6'} + + is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -807,6 +1163,10 @@ packages: resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} engines: {node: '>= 0.4'} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -826,6 +1186,17 @@ packages: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} + is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -842,12 +1213,64 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-stream@1.0.0: resolution: {integrity: sha512-H/ZGY0nIAg3QcOwE1QN/rK/Fa7gJn7Ii5obwp6zyPO4xiPNwpIMjqy2gwjBEGqzkF/vSWEIBQCBuN19hYiL6Qg==} jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + kysely@0.27.3: + resolution: {integrity: sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==} + engines: {node: '>=14.0.0'} + + lazystream@1.0.1: + resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==} + engines: {node: '>= 0.6.3'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.defaults@4.2.0: + resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==} + + lodash.difference@4.5.0: + resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==} + + lodash.flatten@4.4.0: + resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.union@4.6.0: + resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -859,6 +1282,14 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -873,10 +1304,21 @@ packages: merge-descriptors@1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} @@ -895,12 +1337,24 @@ packages: engines: {node: '>=16'} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -935,6 +1389,28 @@ packages: neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + new-github-issue-url@0.2.1: + resolution: {integrity: sha512-md4cGoxuT4T4d/HDOXbrUHkTKrp/vp+m3aOA7XXVYwNsUNMK49g3SQicTSeV5GIz/5QVGAeYRAOlyp9OvlgsYA==} + engines: {node: '>=10'} + + node-fetch@2.6.12: + resolution: {integrity: sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + nodemon@3.1.3: resolution: {integrity: sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w==} engines: {node: '>=10'} @@ -944,10 +1420,30 @@ packages: resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} hasBin: true + normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} + npm-bundled@2.0.1: + resolution: {integrity: sha512-gZLxXdjEzE/+mOstGDqR6b0EkhJ+kM6fxM6vUuckuctuVPh80Q6pw/rSZj9s4Gex9GxWtIicO1pc8DB9KZWudw==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-normalize-package-bin@2.0.0: + resolution: {integrity: sha512-awzfKUO7v0FscrSpRoogyNm0sajikhBWpU0QMrW09AMi9n1PoKU6WaIqUzuJSQnpciZZmJ/jMZ2Egfmb/9LiWQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + + npm-packlist@5.1.3: + resolution: {integrity: sha512-263/0NGrn32YFYi4J533qzrQ/krmmrWwhKkzwTuM4f/07ug51odoaNjUexxO4vxlzURHcmYMH1QjvHjsNDKLVg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + hasBin: true + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -970,14 +1466,76 @@ packages: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@7.4.2: + resolution: {integrity: sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==} + engines: {node: '>=8'} + + p-filter@2.1.0: + resolution: {integrity: sha512-ZBxxZ5sL2HghephhpGAQdoskxplTwr7ICaehZwLIlfL6acuVgZPm8yBNuRAFBGEqtD/hmUeq9eqLg2ys9Xr/yw==} + engines: {node: '>=8'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-map@2.1.0: + resolution: {integrity: sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==} + engines: {node: '>=6'} + + p-map@4.0.0: + resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} + engines: {node: '>=10'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.10.2: resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} engines: {node: '>=16 || 14 >=14.17'} @@ -985,10 +1543,21 @@ packages: path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + possible-typed-array-names@1.0.0: resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} engines: {node: '>= 0.4'} @@ -998,15 +1567,35 @@ packages: engines: {node: '>=14'} hasBin: true + prisma-extension-kysely@2.1.0: + resolution: {integrity: sha512-s1hujYjrNzfQc9Z79s93464mkTkkt9ZPqPELDRFe9jEmiIlM/JRXZtqIyyN3FM0GDkN/BDPVtpPtdC52XnjAcQ==} + peerDependencies: + '@prisma/client': latest + + prisma-kysely@1.8.0: + resolution: {integrity: sha512-VpNpolZ8RXRgfU+j4R+fPZmX8EE95w3vJ2tt7+FwuiQc0leNTfLK5QLf3KbbPDes2rfjh3g20AjDxefQIo5GIA==} + hasBin: true + prisma@5.12.1: resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==} engines: {node: '>=16.13'} hasBin: true + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + promise.any@2.0.6: resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} engines: {node: '>= 0.4'} + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -1022,6 +1611,9 @@ packages: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -1030,10 +1622,24 @@ packages: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} + read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + + read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdir-glob@1.1.3: + resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -1041,18 +1647,48 @@ packages: reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + regexp-to-ast@0.5.0: + resolution: {integrity: sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==} + regexp.prototype.flags@1.5.2: resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} engines: {node: '>= 0.4'} + replace-string@3.1.0: + resolution: {integrity: sha512-yPpxc4ZR2makceA9hy/jHNqc7QVkd4Je/N0WRHm6bs3PtivPuPynxE5ejU/mp5EhnCv8+uZL7vhz8rkluSlx+Q==} + engines: {node: '>=8'} + require-directory@2.1.1: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + resolve@1.22.4: + resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-array-concat@1.1.2: resolution: {integrity: sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==} engines: {node: '>=0.4'} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1069,6 +1705,14 @@ packages: secure-json-parse@2.7.0: resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.6.0: resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} @@ -1105,6 +1749,9 @@ packages: resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} engines: {node: '>= 0.4'} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -1113,10 +1760,33 @@ packages: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@3.0.0: + resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} + engines: {node: '>=8'} + source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + + spdx-exceptions@2.5.0: + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} + + spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + + spdx-license-ids@3.0.18: + resolution: {integrity: sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==} + split-on-first@1.1.0: resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} engines: {node: '>=6'} @@ -1152,6 +1822,9 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -1163,6 +1836,14 @@ packages: resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} engines: {node: '>=12'} + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strnum@1.0.5: resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} @@ -1170,6 +1851,18 @@ packages: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + swagger-ui-dist@5.13.0: resolution: {integrity: sha512-uaWhh6j18IIs5tOX0arvIBnVINAzpTXaQXkr7qAk8zoupegJVg0UU/5+S/FgsgVCnzVsJ9d7QLjIxkswEeTg0Q==} @@ -1179,9 +1872,29 @@ packages: peerDependencies: express: '>=4.0.0 || >=5.0.0-beta' + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@1.0.1: + resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} + engines: {node: '>=10'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + through2@4.0.2: resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + tmp@0.2.1: + resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==} + engines: {node: '>=8.17.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1194,6 +1907,9 @@ packages: resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} hasBin: true + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + ts-deepmerge@7.0.0: resolution: {integrity: sha512-WZ/iAJrKDhdINv1WG6KZIGHrZDar6VfhftG1QJFpVbOYZMYJLJOvZOo1amictRXVdBXZIgBHKswMTXzElngprA==} engines: {node: '>=14.13.1'} @@ -1212,6 +1928,9 @@ packages: '@swc/wasm': optional: true + ts-pattern@4.3.0: + resolution: {integrity: sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg==} + tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} @@ -1220,6 +1939,22 @@ packages: engines: {node: '>=18.0.0', yarn: '>=1.9.4'} hasBin: true + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + + type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + type-is@1.6.18: resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} engines: {node: '>= 0.6'} @@ -1263,6 +1998,10 @@ packages: resolution: {integrity: sha512-KyhzaLJnV1qa3BSHdj4AZ2ndqI0QWPxYzaIOio0WzcEJB9gvuysprJSLtpvc2D9mhR9jPDUk7xlJlZbH2KR5iw==} engines: {node: '>=18.0'} + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -1281,9 +2020,16 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@9.0.0: + resolution: {integrity: sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==} + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + validator@13.11.0: resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} engines: {node: '>= 0.10'} @@ -1295,6 +2041,12 @@ packages: web-encoding@1.1.5: resolution: {integrity: sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA==} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -1318,6 +2070,9 @@ packages: resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} engines: {node: '>=12'} + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + xml2js@0.5.0: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} @@ -1353,8 +2108,50 @@ packages: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zip-stream@4.1.1: + resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==} + engines: {node: '>= 10'} + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + snapshots: + '@antfu/ni@0.21.8': {} + + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.1 + + '@babel/helper-validator-identifier@7.24.7': {} + + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.1 + + '@chevrotain/cst-dts-gen@10.5.0': + dependencies: + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + + '@chevrotain/gast@10.5.0': + dependencies: + '@chevrotain/types': 10.5.0 + lodash: 4.17.21 + + '@chevrotain/types@10.5.0': {} + + '@chevrotain/utils@10.5.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -1560,6 +2357,25 @@ snapshots: '@lukeed/ms@2.0.2': {} + '@mrleebo/prisma-ast@0.7.0': + dependencies: + chevrotain: 10.5.0 + lilconfig: 2.1.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@opentelemetry/api@1.4.1': {} + '@pkgjs/parseargs@0.11.0': optional: true @@ -1569,6 +2385,14 @@ snapshots: '@prisma/debug@5.12.1': {} + '@prisma/debug@5.3.1': + dependencies: + '@types/debug': 4.1.8 + debug: 4.3.4(supports-color@5.5.0) + strip-ansi: 6.0.1 + transitivePeerDependencies: + - supports-color + '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': {} '@prisma/engines@5.12.1': @@ -1578,16 +2402,115 @@ snapshots: '@prisma/fetch-engine': 5.12.1 '@prisma/get-platform': 5.12.1 + '@prisma/engines@5.3.1': {} + '@prisma/fetch-engine@5.12.1': dependencies: '@prisma/debug': 5.12.1 '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab '@prisma/get-platform': 5.12.1 + '@prisma/fetch-engine@5.3.1': + dependencies: + '@prisma/debug': 5.3.1 + '@prisma/get-platform': 5.3.1 + execa: 5.1.1 + find-cache-dir: 3.3.2 + fs-extra: 11.1.1 + hasha: 5.2.2 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + kleur: 4.1.5 + node-fetch: 2.7.0 + p-filter: 2.1.0 + p-map: 4.0.0 + p-retry: 4.6.2 + progress: 2.0.3 + rimraf: 3.0.2 + temp-dir: 2.0.0 + tempy: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + '@prisma/generator-helper@5.3.1': + dependencies: + '@prisma/debug': 5.3.1 + '@types/cross-spawn': 6.0.2 + cross-spawn: 7.0.3 + kleur: 4.1.5 + transitivePeerDependencies: + - supports-color + '@prisma/get-platform@5.12.1': dependencies: '@prisma/debug': 5.12.1 + '@prisma/get-platform@5.3.1': + dependencies: + '@prisma/debug': 5.3.1 + escape-string-regexp: 4.0.0 + execa: 5.1.1 + fs-jetpack: 5.1.0 + kleur: 4.1.5 + replace-string: 3.1.0 + strip-ansi: 6.0.1 + tempy: 1.0.1 + terminal-link: 2.1.1 + ts-pattern: 4.3.0 + transitivePeerDependencies: + - supports-color + + '@prisma/internals@5.3.1': + dependencies: + '@antfu/ni': 0.21.8 + '@opentelemetry/api': 1.4.1 + '@prisma/debug': 5.3.1 + '@prisma/engines': 5.3.1 + '@prisma/fetch-engine': 5.3.1 + '@prisma/generator-helper': 5.3.1 + '@prisma/get-platform': 5.3.1 + '@prisma/prisma-schema-wasm': 5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59 + archiver: 5.3.2 + arg: 5.0.2 + checkpoint-client: 1.1.27 + cli-truncate: 2.1.0 + dotenv: 16.0.3 + escape-string-regexp: 4.0.0 + execa: 5.1.1 + find-up: 5.0.0 + fp-ts: 2.16.1 + fs-extra: 11.1.1 + fs-jetpack: 5.1.0 + global-dirs: 3.0.1 + globby: 11.1.0 + indent-string: 4.0.0 + is-windows: 1.0.2 + is-wsl: 2.2.0 + kleur: 4.1.5 + new-github-issue-url: 0.2.1 + node-fetch: 2.7.0 + npm-packlist: 5.1.3 + open: 7.4.2 + p-map: 4.0.0 + prompts: 2.4.2 + read-pkg-up: 7.0.1 + replace-string: 3.1.0 + resolve: 1.22.4 + string-width: 4.2.3 + strip-ansi: 6.0.1 + strip-indent: 3.0.0 + temp-dir: 2.0.0 + tempy: 1.0.1 + terminal-link: 2.1.1 + tmp: 0.2.1 + ts-pattern: 4.3.0 + transitivePeerDependencies: + - encoding + - supports-color + + '@prisma/prisma-schema-wasm@5.3.1-2.61e140623197a131c2a6189271ffee05a7aa9a59': {} + '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -1651,6 +2574,14 @@ snapshots: dependencies: '@types/node': 20.12.2 + '@types/cross-spawn@6.0.2': + dependencies: + '@types/node': 20.12.2 + + '@types/debug@4.1.8': + dependencies: + '@types/ms': 0.7.34 + '@types/express-serve-static-core@4.17.43': dependencies: '@types/node': 20.12.2 @@ -1692,6 +2623,8 @@ snapshots: dependencies: mime: 4.0.1 + '@types/ms@0.7.34': {} + '@types/multer@1.4.11': dependencies: '@types/express': 4.17.21 @@ -1700,10 +2633,14 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/normalize-package-data@2.4.4': {} + '@types/qs@6.9.14': {} '@types/range-parser@1.2.7': {} + '@types/retry@0.12.0': {} + '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 @@ -1734,10 +2671,29 @@ snapshots: acorn@8.11.3: {} + agent-base@7.1.1: + dependencies: + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + aggregate-error@3.1.0: + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + ansi-regex@5.0.1: {} ansi-regex@6.0.1: {} + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -1749,8 +2705,46 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + archiver-utils@2.1.0: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 2.3.8 + + archiver-utils@3.0.4: + dependencies: + glob: 7.2.3 + graceful-fs: 4.2.11 + lazystream: 1.0.1 + lodash.defaults: 4.2.0 + lodash.difference: 4.5.0 + lodash.flatten: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.union: 4.6.0 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + + archiver@5.3.2: + dependencies: + archiver-utils: 2.1.0 + async: 3.2.5 + buffer-crc32: 0.2.13 + readable-stream: 3.6.2 + readdir-glob: 1.1.3 + tar-stream: 2.2.0 + zip-stream: 4.1.1 + arg@4.1.3: {} + arg@5.0.2: {} + array-buffer-byte-length@1.0.1: dependencies: call-bind: 1.0.7 @@ -1758,6 +2752,8 @@ snapshots: array-flatten@1.1.1: {} + array-union@2.1.0: {} + array.prototype.map@1.0.7: dependencies: call-bind: 1.0.7 @@ -1785,6 +2781,8 @@ snapshots: minimalistic-assert: 1.0.1 safer-buffer: 2.1.2 + astral-regex@2.0.0: {} + async@3.2.5: {} available-typed-arrays@1.0.7: @@ -1793,8 +2791,16 @@ snapshots: balanced-match@1.0.2: {} + base64-js@1.5.1: {} + binary-extensions@2.3.0: {} + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + block-stream2@2.1.0: dependencies: readable-stream: 3.6.2 @@ -1831,10 +2837,19 @@ snapshots: dependencies: fill-range: 7.0.1 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + browser-or-node@2.1.1: {} buffer-crc32@0.2.13: {} + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bytes@3.1.2: {} call-bind@1.0.7: @@ -1845,6 +2860,32 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.2 + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + checkpoint-client@1.1.27: + dependencies: + ci-info: 3.8.0 + env-paths: 2.2.1 + make-dir: 4.0.0 + ms: 2.1.3 + node-fetch: 2.6.12 + uuid: 9.0.0 + transitivePeerDependencies: + - encoding + + chevrotain@10.5.0: + dependencies: + '@chevrotain/cst-dts-gen': 10.5.0 + '@chevrotain/gast': 10.5.0 + '@chevrotain/types': 10.5.0 + '@chevrotain/utils': 10.5.0 + lodash: 4.17.21 + regexp-to-ast: 0.5.0 + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -1857,18 +2898,42 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + ci-info@3.8.0: {} + + clean-stack@2.2.0: {} + + cli-truncate@2.1.0: + dependencies: + slice-ansi: 3.0.0 + string-width: 4.2.3 + cliui@8.0.1: dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + commondir@1.0.1: {} + + compress-commons@4.1.2: + dependencies: + buffer-crc32: 0.2.13 + crc32-stream: 4.0.3 + normalize-path: 3.0.0 + readable-stream: 3.6.2 + concat-map@0.0.1: {} content-disposition@0.5.4: @@ -1881,11 +2946,20 @@ snapshots: cookie@0.6.0: {} + core-util-is@1.0.3: {} + cors@2.8.5: dependencies: object-assign: 4.1.1 vary: 1.1.2 + crc-32@1.2.2: {} + + crc32-stream@4.0.3: + dependencies: + crc-32: 1.2.2 + readable-stream: 3.6.2 + create-require@1.1.1: {} cross-spawn@7.0.3: @@ -1894,6 +2968,8 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + crypto-random-string@2.0.0: {} + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.7 @@ -1936,12 +3012,29 @@ snapshots: has-property-descriptors: 1.0.2 object-keys: 1.1.1 + del@6.1.1: + dependencies: + globby: 11.1.0 + graceful-fs: 4.2.11 + is-glob: 4.0.3 + is-path-cwd: 2.2.0 + is-path-inside: 3.0.3 + p-map: 4.0.0 + rimraf: 3.0.2 + slash: 3.0.0 + depd@2.0.0: {} destroy@1.2.0: {} diff@4.0.2: {} + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dotenv@16.0.3: {} + dotenv@16.4.5: {} eastasianwidth@0.2.0: {} @@ -1958,6 +3051,16 @@ snapshots: encodeurl@1.0.2: {} + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + + env-paths@2.2.1: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + es-abstract@1.23.3: dependencies: array-buffer-byte-length: 1.0.1 @@ -2058,8 +3161,24 @@ snapshots: escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + etag@1.8.1: {} + execa@5.1.1: + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + express@4.19.2: dependencies: accepts: 1.3.8 @@ -2096,6 +3215,14 @@ snapshots: transitivePeerDependencies: - supports-color + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.7 + fast-jwt@4.0.0: dependencies: '@lukeed/ms': 2.0.2 @@ -2107,10 +3234,18 @@ snapshots: dependencies: strnum: 1.0.5 + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + filter-obj@1.1.0: {} finalhandler@1.2.0: @@ -2125,6 +3260,22 @@ snapshots: transitivePeerDependencies: - supports-color + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -2136,14 +3287,30 @@ snapshots: forwarded@0.2.0: {} + fp-ts@2.16.1: {} + fresh@0.5.2: {} + fs-constants@1.0.0: {} + + fs-extra@11.1.1: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs-extra@11.2.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 + fs-jetpack@5.1.0: + dependencies: + minimatch: 5.1.6 + + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true @@ -2168,6 +3335,8 @@ snapshots: has-symbols: 1.0.3 hasown: 2.0.2 + get-stream@6.0.1: {} + get-symbol-description@1.0.2: dependencies: call-bind: 1.0.7 @@ -2186,10 +3355,40 @@ snapshots: minipass: 7.0.4 path-scurry: 1.10.2 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + + global-dirs@3.0.1: + dependencies: + ini: 2.0.0 + globalthis@1.0.3: dependencies: define-properties: 1.2.1 + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 @@ -2209,6 +3408,8 @@ snapshots: has-flag@3.0.0: {} + has-flag@4.0.0: {} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 @@ -2221,10 +3422,17 @@ snapshots: dependencies: has-symbols: 1.0.3 + hasha@5.2.2: + dependencies: + is-stream: 2.0.1 + type-fest: 0.8.1 + hasown@2.0.2: dependencies: function-bind: 1.1.2 + hosted-git-info@2.8.9: {} + hpagent@1.2.0: {} http-errors@2.0.0: @@ -2235,14 +3443,47 @@ snapshots: statuses: 2.0.1 toidentifier: 1.0.1 + http-proxy-agent@7.0.0: + dependencies: + agent-base: 7.1.1 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1 + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 + ieee754@1.2.1: {} + ignore-by-default@1.0.1: {} + ignore-walk@5.0.1: + dependencies: + minimatch: 5.1.6 + + ignore@5.3.1: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + inherits@2.0.4: {} + ini@2.0.0: {} + internal-slot@1.0.7: dependencies: es-errors: 1.3.0 @@ -2263,6 +3504,8 @@ snapshots: call-bind: 1.0.7 get-intrinsic: 1.2.4 + is-arrayish@0.2.1: {} + is-bigint@1.0.4: dependencies: has-bigints: 1.0.2 @@ -2278,6 +3521,10 @@ snapshots: is-callable@1.2.7: {} + is-core-module@2.14.0: + dependencies: + hasown: 2.0.2 + is-data-view@1.0.1: dependencies: is-typed-array: 1.1.13 @@ -2286,6 +3533,8 @@ snapshots: dependencies: has-tostringtag: 1.0.2 + is-docker@2.2.1: {} + is-extglob@2.1.1: {} is-fullwidth-code-point@3.0.0: {} @@ -2308,6 +3557,10 @@ snapshots: is-number@7.0.0: {} + is-path-cwd@2.2.0: {} + + is-path-inside@3.0.3: {} + is-regex@1.1.4: dependencies: call-bind: 1.0.7 @@ -2319,6 +3572,8 @@ snapshots: dependencies: call-bind: 1.0.7 + is-stream@2.0.1: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.2 @@ -2337,6 +3592,14 @@ snapshots: is-what@4.1.16: {} + is-windows@1.0.2: {} + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + isarray@2.0.5: {} isexe@2.0.0: {} @@ -2354,6 +3617,10 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + js-tokens@4.0.0: {} + + json-parse-even-better-errors@2.3.1: {} + json-stream@1.0.0: {} jsonfile@6.1.0: @@ -2362,6 +3629,38 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + kleur@3.0.3: {} + + kleur@4.1.5: {} + + kysely@0.27.3: {} + + lazystream@1.0.1: + dependencies: + readable-stream: 2.3.8 + + lilconfig@2.1.0: {} + + lines-and-columns@1.2.4: {} + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.defaults@4.2.0: {} + + lodash.difference@4.5.0: {} + + lodash.flatten@4.4.0: {} + + lodash.isplainobject@4.0.6: {} + + lodash.union@4.6.0: {} + lodash@4.17.21: {} lru-cache@10.2.0: {} @@ -2370,6 +3669,14 @@ snapshots: dependencies: yallist: 4.0.0 + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-dir@4.0.0: + dependencies: + semver: 7.6.0 + make-error@1.3.6: {} media-typer@0.3.0: {} @@ -2380,8 +3687,17 @@ snapshots: merge-descriptors@1.0.1: {} + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + methods@1.1.2: {} + micromatch@4.0.7: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + mime-db@1.52.0: {} mime-types@2.1.35: @@ -2392,12 +3708,20 @@ snapshots: mime@4.0.1: {} + mimic-fn@2.1.0: {} + + min-indent@1.0.1: {} + minimalistic-assert@1.0.1: {} minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 @@ -2437,6 +3761,16 @@ snapshots: neo-async@2.6.2: {} + new-github-issue-url@0.2.1: {} + + node-fetch@2.6.12: + dependencies: + whatwg-url: 5.0.0 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + nodemon@3.1.3: dependencies: chokidar: 3.6.0 @@ -2454,8 +3788,32 @@ snapshots: dependencies: abbrev: 1.1.1 + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.4 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + normalize-path@3.0.0: {} + npm-bundled@2.0.1: + dependencies: + npm-normalize-package-bin: 2.0.0 + + npm-normalize-package-bin@2.0.0: {} + + npm-packlist@5.1.3: + dependencies: + glob: 8.1.0 + ignore-walk: 5.0.1 + npm-bundled: 2.0.1 + npm-normalize-package-bin: 2.0.0 + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + object-assign@4.1.1: {} object-inspect@1.13.1: {} @@ -2475,10 +3833,69 @@ snapshots: dependencies: ee-first: 1.1.1 + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@7.4.2: + dependencies: + is-docker: 2.2.1 + is-wsl: 2.2.0 + + p-filter@2.1.0: + dependencies: + p-map: 2.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-map@2.1.0: {} + + p-map@4.0.0: + dependencies: + aggregate-error: 3.1.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-try@2.2.0: {} + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.24.7 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + parseurl@1.3.3: {} + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} + path-parse@1.0.7: {} + path-scurry@1.10.2: dependencies: lru-cache: 10.2.0 @@ -2486,16 +3903,43 @@ snapshots: path-to-regexp@0.1.7: {} + path-type@4.0.0: {} + + picocolors@1.0.1: {} + picomatch@2.3.1: {} + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + possible-typed-array-names@1.0.0: {} prettier@3.2.5: {} + prisma-extension-kysely@2.1.0(@prisma/client@5.12.1(prisma@5.12.1)): + dependencies: + '@prisma/client': 5.12.1(prisma@5.12.1) + + prisma-kysely@1.8.0: + dependencies: + '@mrleebo/prisma-ast': 0.7.0 + '@prisma/generator-helper': 5.3.1 + '@prisma/internals': 5.3.1 + typescript: 5.4.3 + zod: 3.23.8 + transitivePeerDependencies: + - encoding + - supports-color + prisma@5.12.1: dependencies: '@prisma/engines': 5.12.1 + process-nextick-args@2.0.1: {} + + progress@2.0.3: {} + promise.any@2.0.6: dependencies: array.prototype.map: 1.0.7 @@ -2506,6 +3950,11 @@ snapshots: get-intrinsic: 1.2.4 iterate-value: 1.0.2 + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -2524,6 +3973,8 @@ snapshots: split-on-first: 1.1.0 strict-uri-encode: 2.0.0 + queue-microtask@1.2.3: {} + range-parser@1.2.1: {} raw-body@2.5.2: @@ -2533,18 +3984,47 @@ snapshots: iconv-lite: 0.4.24 unpipe: 1.0.0 + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdir-glob@1.1.3: + dependencies: + minimatch: 5.1.6 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 reflect-metadata@0.2.2: {} + regexp-to-ast@0.5.0: {} + regexp.prototype.flags@1.5.2: dependencies: call-bind: 1.0.7 @@ -2552,8 +4032,28 @@ snapshots: es-errors: 1.3.0 set-function-name: 2.0.2 + replace-string@3.1.0: {} + require-directory@2.1.1: {} + resolve@1.22.4: + dependencies: + is-core-module: 2.14.0 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + reusify@1.0.4: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + safe-array-concat@1.1.2: dependencies: call-bind: 1.0.7 @@ -2561,6 +4061,8 @@ snapshots: has-symbols: 1.0.3 isarray: 2.0.5 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safe-regex-test@1.0.3: @@ -2575,6 +4077,10 @@ snapshots: secure-json-parse@2.7.0: {} + semver@5.7.2: {} + + semver@6.3.1: {} + semver@7.6.0: dependencies: lru-cache: 6.0.0 @@ -2637,14 +4143,40 @@ snapshots: get-intrinsic: 1.2.4 object-inspect: 1.13.1 + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-update-notifier@2.0.0: dependencies: semver: 7.6.0 + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slice-ansi@3.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + source-map@0.6.1: {} + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.18 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.18 + + spdx-license-ids@3.0.18: {} + split-on-first@1.1.0: {} statuses@2.0.1: {} @@ -2686,6 +4218,10 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -2698,12 +4234,29 @@ snapshots: dependencies: ansi-regex: 6.0.1 + strip-final-newline@2.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strnum@1.0.5: {} supports-color@5.5.0: dependencies: has-flag: 3.0.0 + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + swagger-ui-dist@5.13.0: {} swagger-ui-express@5.0.0(express@4.19.2): @@ -2711,10 +4264,37 @@ snapshots: express: 4.19.2 swagger-ui-dist: 5.13.0 + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + + temp-dir@2.0.0: {} + + tempy@1.0.1: + dependencies: + del: 6.1.1 + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + through2@4.0.2: dependencies: readable-stream: 3.6.2 + tmp@0.2.1: + dependencies: + rimraf: 3.0.2 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2725,6 +4305,8 @@ snapshots: dependencies: nopt: 1.0.10 + tr46@0.0.3: {} + ts-deepmerge@7.0.0: {} ts-node@10.9.2(@types/node@20.12.2)(typescript@5.4.3): @@ -2745,6 +4327,8 @@ snapshots: v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + ts-pattern@4.3.0: {} + tslib@2.6.2: {} tsoa@6.2.0: @@ -2754,6 +4338,14 @@ snapshots: transitivePeerDependencies: - supports-color + type-fest@0.16.0: {} + + type-fest@0.21.3: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + type-is@1.6.18: dependencies: media-typer: 0.3.0 @@ -2809,6 +4401,10 @@ snapshots: undici@6.11.1: {} + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + universalify@2.0.1: {} unpipe@1.0.0: {} @@ -2825,8 +4421,15 @@ snapshots: utils-merge@1.0.1: {} + uuid@9.0.0: {} + v8-compile-cache-lib@3.0.1: {} + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + validator@13.11.0: {} vary@1.1.2: {} @@ -2837,6 +4440,13 @@ snapshots: optionalDependencies: '@zxing/text-encoding': 0.9.0 + webidl-conversions@3.0.1: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + which-boxed-primitive@1.0.2: dependencies: is-bigint: 1.0.4 @@ -2871,6 +4481,8 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 + wrappy@1.0.2: {} + xml2js@0.5.0: dependencies: sax: 1.3.0 @@ -2899,3 +4511,13 @@ snapshots: yargs-parser: 21.1.1 yn@3.1.1: {} + + yocto-queue@0.1.0: {} + + zip-stream@4.1.1: + dependencies: + archiver-utils: 3.0.4 + compress-commons: 4.1.2 + readable-stream: 3.6.2 + + zod@3.23.8: {} diff --git a/prisma/generated/types.ts b/prisma/generated/types.ts new file mode 100644 index 0000000..00946c7 --- /dev/null +++ b/prisma/generated/types.ts @@ -0,0 +1,459 @@ +import type { ColumnType } from "kysely"; +export type Generated = T extends ColumnType + ? ColumnType + : ColumnType; +export type Timestamp = ColumnType; + +export const Status = { + CREATED: "CREATED", + ACTIVE: "ACTIVE", + INACTIVE: "INACTIVE" +} as const; +export type Status = (typeof Status)[keyof typeof Status]; +export const UserType = { + USER: "USER", + MESSENGER: "MESSENGER", + DELEGATE: "DELEGATE", + AGENCY: "AGENCY" +} as const; +export type UserType = (typeof UserType)[keyof typeof UserType]; +export const CustomerType = { + CORP: "CORP", + PERS: "PERS" +} as const; +export type CustomerType = (typeof CustomerType)[keyof typeof CustomerType]; +export type Branch = { + id: string; + code: string; + taxNo: string; + name: string; + nameEN: string; + address: string; + addressEN: string; + telephoneNo: string; + provinceId: string | null; + districtId: string | null; + subDistrictId: string | null; + zipCode: string; + email: string; + contactName: string | null; + lineId: string | null; + latitude: string; + longitude: string; + isHeadOffice: Generated; + headOfficeId: string | null; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type BranchContact = { + id: string; + telephoneNo: string; + branchId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type BranchUser = { + id: string; + branchId: string; + userId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type Customer = { + id: string; + code: string; + personName: string; + personNameEN: string | null; + customerType: CustomerType; + customerName: string; + customerNameEN: string; + taxNo: string | null; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type CustomerBranch = { + id: string; + branchNo: number; + code: string; + legalPersonNo: string; + name: string; + nameEN: string; + customerId: string; + taxNo: string | null; + registerName: string; + registerDate: Timestamp; + authorizedCapital: string; + address: string; + addressEN: string; + provinceId: string | null; + districtId: string | null; + subDistrictId: string | null; + zipCode: string; + email: string; + telephoneNo: string; + employmentOffice: string; + bussinessType: string; + bussinessTypeEN: string; + jobPosition: string; + jobPositionEN: string; + jobDescription: string; + saleEmployee: string; + payDate: Timestamp; + wageRate: number; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type District = { + id: string; + name: string; + nameEN: string; + provinceId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type Employee = { + id: string; + code: string; + nrcNo: string; + firstName: string; + firstNameEN: string; + lastName: string; + lastNameEN: string; + dateOfBirth: Timestamp; + gender: string; + nationality: string; + address: string | null; + addressEN: string | null; + provinceId: string | null; + districtId: string | null; + subDistrictId: string | null; + zipCode: string; + passportType: string; + passportNumber: string; + passportIssueDate: Timestamp; + passportExpiryDate: Timestamp; + passportIssuingCountry: string; + passportIssuingPlace: string; + previousPassportReference: string | null; + visaType: string | null; + visaNumber: string | null; + visaIssueDate: Timestamp | null; + visaExpiryDate: Timestamp | null; + visaIssuingPlace: string | null; + visaStayUntilDate: Timestamp | null; + tm6Number: string | null; + entryDate: Timestamp | null; + workerStatus: string | null; + customerBranchId: string | null; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type EmployeeCheckup = { + id: string; + employeeId: string; + checkupResult: string | null; + checkupType: string | null; + provinceId: string | null; + hospitalName: string | null; + remark: string | null; + medicalBenefitScheme: string | null; + insuranceCompany: string | null; + coverageStartDate: Timestamp | null; + coverageExpireDate: Timestamp | null; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type EmployeeOtherInfo = { + id: string; + employeeId: string; + citizenId: string | null; + fatherBirthPlace: string | null; + fatherFirstName: string | null; + fatherLastName: string | null; + motherBirthPlace: string | null; + motherFirstName: string | null; + motherLastName: string | null; + fatherFirstNameEN: string | null; + fatherLastNameEN: string | null; + motherFirstNameEN: string | null; + motherLastNameEN: string | null; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type EmployeeWork = { + id: string; + employeeId: string; + ownerName: string | null; + positionName: string | null; + jobType: string | null; + workplace: string | null; + workPermitNo: string | null; + workPermitIssuDate: Timestamp | null; + workPermitExpireDate: Timestamp | null; + workEndDate: Timestamp | null; + remark: string | null; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type Menu = { + id: string; + caption: string; + captionEN: string; + menuType: string; + url: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; + parentId: string | null; +}; +export type MenuComponent = { + id: string; + componentId: string; + componentTag: string; + menuId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type Product = { + id: string; + code: string; + name: string; + detail: string; + process: number; + price: number; + agentPrice: number; + serviceCharge: number; + status: Generated; + statusOrder: Generated; + remark: string | null; + productTypeId: string | null; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type ProductGroup = { + id: string; + code: string; + name: string; + detail: string; + remark: string; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type ProductType = { + id: string; + code: string; + name: string; + detail: string; + remark: string; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; + productGroupId: string; +}; +export type Province = { + id: string; + name: string; + nameEN: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type RoleMenuComponentPermission = { + id: string; + userRole: string; + permission: string; + menuComponentId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type RoleMenuPermission = { + id: string; + userRole: string; + permission: string; + menuId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type RunningNo = { + key: string; + value: number; +}; +export type Service = { + id: string; + code: string; + name: string; + detail: string; + attributes: unknown | null; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type SubDistrict = { + id: string; + name: string; + nameEN: string; + zipCode: string; + districtId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type User = { + id: string; + code: string | null; + firstName: string; + firstNameEN: string; + lastName: string; + lastNameEN: string; + username: string; + gender: string; + address: string; + addressEN: string; + provinceId: string | null; + districtId: string | null; + subDistrictId: string | null; + zipCode: string; + email: string; + telephoneNo: string; + registrationNo: string | null; + startDate: Timestamp | null; + retireDate: Timestamp | null; + checkpoint: string | null; + checkpointEN: string | null; + userType: UserType; + userRole: string; + discountCondition: string | null; + licenseNo: string | null; + licenseIssueDate: Timestamp | null; + licenseExpireDate: Timestamp | null; + sourceNationality: string | null; + importNationality: string | null; + trainingPlace: string | null; + responsibleArea: string | null; + birthDate: Timestamp | null; + status: Generated; + statusOrder: Generated; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type UserMenuComponentPermission = { + id: string; + userId: string; + menuComponentId: string; + permission: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type UserMenuPermission = { + id: string; + permission: string; + menuId: string; + userId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type Work = { + id: string; + order: number; + name: string; + attributes: unknown | null; + status: Generated; + statusOrder: Generated; + serviceId: string | null; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type WorkProduct = { + order: number; + workId: string; + productId: string; + createdBy: string | null; + createdAt: Generated; + updateBy: string | null; + updatedAt: Timestamp; +}; +export type DB = { + Branch: Branch; + BranchContact: BranchContact; + BranchUser: BranchUser; + Customer: Customer; + CustomerBranch: CustomerBranch; + District: District; + Employee: Employee; + EmployeeCheckup: EmployeeCheckup; + EmployeeOtherInfo: EmployeeOtherInfo; + EmployeeWork: EmployeeWork; + Menu: Menu; + MenuComponent: MenuComponent; + Product: Product; + ProductGroup: ProductGroup; + ProductType: ProductType; + Province: Province; + RoleMenuComponentPermission: RoleMenuComponentPermission; + RoleMenuPermission: RoleMenuPermission; + RunningNo: RunningNo; + Service: Service; + SubDistrict: SubDistrict; + User: User; + UserMenuComponentPermission: UserMenuComponentPermission; + UserMenuPermission: UserMenuPermission; + Work: Work; + WorkProduct: WorkProduct; +}; diff --git a/prisma/migrations/20240626042218_adjust_type/migration.sql b/prisma/migrations/20240626042218_adjust_type/migration.sql new file mode 100644 index 0000000..15fde59 --- /dev/null +++ b/prisma/migrations/20240626042218_adjust_type/migration.sql @@ -0,0 +1,4 @@ +-- AlterTable +ALTER TABLE "Product" ALTER COLUMN "price" SET DATA TYPE DOUBLE PRECISION, +ALTER COLUMN "agentPrice" SET DATA TYPE DOUBLE PRECISION, +ALTER COLUMN "serviceCharge" SET DATA TYPE DOUBLE PRECISION; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 69329b8..aa1bed9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -2,6 +2,10 @@ generator client { provider = "prisma-client-js" } +generator kysely { + provider = "prisma-kysely" +} + datasource db { provider = "postgresql" url = env("DATABASE_URL") @@ -644,9 +648,9 @@ model Product { name String detail String process Int - price Int - agentPrice Int - serviceCharge Int + price Float + agentPrice Float + serviceCharge Float status Status @default(CREATED) statusOrder Int @default(0) diff --git a/src/db.ts b/src/db.ts index 7298c40..f63bece 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,7 +1,23 @@ import { PrismaClient } from "@prisma/client"; +import kyselyExtension from "prisma-extension-kysely"; +import type { DB } from "../prisma/generated/types.ts"; +import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from "kysely"; const prisma = new PrismaClient({ errorFormat: process.env.NODE_ENV === "production" ? "minimal" : "pretty", -}); +}).$extends( + kyselyExtension({ + kysely: (driver) => + new Kysely({ + dialect: { + createDriver: () => driver, + createAdapter: () => new PostgresAdapter(), + createIntrospector: (db: Kysely) => new PostgresIntrospector(db), + createQueryCompiler: () => new PostgresQueryCompiler(), + }, + plugins: [], + }), + }), +); export default prisma; From eed7ffa9d171551a12438b50c5a8002a4d512da1 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:34:14 +0700 Subject: [PATCH 141/157] chore: add prisma kysely for query builder --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c8d8da5..85f8ccd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable RUN apt-get update && apt-get install -y openssl -RUN pnpm i -g prisma +RUN pnpm i -g prisma prisma-kysely WORKDIR /app From 3ba52dead5eebe5afa832966a7c3de58ab67dc9e Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:53:02 +0700 Subject: [PATCH 142/157] feat: add git ignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 395a731..e90ad5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .DS_S node_modules +/src/generated .env .env.* From 415d12dd4b9e9807ebb959addb9874249958ae54 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:53:10 +0700 Subject: [PATCH 143/157] chore: bumps deps ver --- package.json | 4 +-- pnpm-lock.yaml | 76 +++++++++++++++++++++++++------------------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 63fdf94..2502949 100644 --- a/package.json +++ b/package.json @@ -24,14 +24,14 @@ "@types/swagger-ui-express": "^4.1.6", "nodemon": "^3.1.3", "prettier": "^3.2.5", - "prisma": "^5.12.1", + "prisma": "^5.16.0", "prisma-kysely": "^1.8.0", "ts-node": "^10.9.2", "typescript": "^5.4.3" }, "dependencies": { "@elastic/elasticsearch": "^8.13.0", - "@prisma/client": "5.12.1", + "@prisma/client": "^5.16.0", "@tsoa/runtime": "^6.2.0", "cors": "^2.8.5", "dotenv": "^16.4.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 796cb0f..08a3c9d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ importers: specifier: ^8.13.0 version: 8.13.0 '@prisma/client': - specifier: 5.12.1 - version: 5.12.1(prisma@5.12.1) + specifier: ^5.16.0 + version: 5.16.0(prisma@5.16.0) '@tsoa/runtime': specifier: ^6.2.0 version: 6.2.0 @@ -37,7 +37,7 @@ importers: version: 7.1.3 prisma-extension-kysely: specifier: ^2.1.0 - version: 2.1.0(@prisma/client@5.12.1(prisma@5.12.1)) + version: 2.1.0(@prisma/client@5.16.0(prisma@5.16.0)) promise.any: specifier: ^2.0.6 version: 2.0.6 @@ -67,8 +67,8 @@ importers: specifier: ^3.2.5 version: 3.2.5 prisma: - specifier: ^5.12.1 - version: 5.12.1 + specifier: ^5.16.0 + version: 5.16.0 prisma-kysely: specifier: ^1.8.0 version: 1.8.0 @@ -254,8 +254,8 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@prisma/client@5.12.1': - resolution: {integrity: sha512-6/JnizEdlSBxDIdiLbrBdMW5NqDxOmhXAJaNXiPpgzAPr/nLZResT6MMpbOHLo5yAbQ1Vv5UU8PTPRzb0WIxdA==} + '@prisma/client@5.16.0': + resolution: {integrity: sha512-8NOQSzgrSgpU2YcNm4MsPR4/vNvZdUBPuyX89PwWlClSKZeDjPSZ8+eds/ffu1Ttrjnm8V8D0hjgqpyc6wyqDg==} engines: {node: '>=16.13'} peerDependencies: prisma: '*' @@ -263,23 +263,23 @@ packages: prisma: optional: true - '@prisma/debug@5.12.1': - resolution: {integrity: sha512-kd/wNsR0klrv79o1ITsbWxYyh4QWuBidvxsXSParPsYSu0ircUmNk3q4ojsgNc3/81b0ozg76iastOG43tbf8A==} + '@prisma/debug@5.16.0': + resolution: {integrity: sha512-pfdOGxMShqZKkNNskYB0yXICsqL6rOkQUKNktouUZ9Y9ASd5736+ae2fpzif7onwJiIyEpu/yvOO3rFUbliKTA==} '@prisma/debug@5.3.1': resolution: {integrity: sha512-eYrxqslEKf+wpMFIIHgbcNYuZBXUdiJLA85Or3TwOhgPIN1ZoXT9CwJph3ynW8H1Xg0LkdYLwVmuULCwiMoU5A==} - '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': - resolution: {integrity: sha512-6yvO8s80Tym61aB4QNtYZfWVmE3pwqe807jEtzm8C5VDe7nw8O1FGX3TXUaXmWV0fQTIAfRbeL2Gwrndabp/0g==} + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': + resolution: {integrity: sha512-HkT2WbfmFZ9WUPyuJHhkiADxazHg8Y4gByrTSVeb3OikP6tjQ7txtSUGu9OBOBH0C13dPKN2qqH12xKtHu/Hiw==} - '@prisma/engines@5.12.1': - resolution: {integrity: sha512-HQDdglLw2bZR/TXD2Y+YfDMvi5Q8H+acbswqOsWyq9pPjBLYJ6gzM+ptlTU/AV6tl0XSZLU1/7F4qaWa8bqpJA==} + '@prisma/engines@5.16.0': + resolution: {integrity: sha512-OGvi/GvLX3XwTWQ+k/57kLyHGidQ8rC8zB+Zq9nEE7gegjazyzgLYN9qzfdcCfyI8ilc6IMxOyX4sspwkv98hg==} '@prisma/engines@5.3.1': resolution: {integrity: sha512-6QkILNyfeeN67BNEPEtkgh3Xo2tm6D7V+UhrkBbRHqKw9CTaz/vvTP/ROwYSP/3JT2MtIutZm/EnhxUiuOPVDA==} - '@prisma/fetch-engine@5.12.1': - resolution: {integrity: sha512-qSs3KcX1HKcea1A+hlJVK/ljj0PNIUHDxAayGMvgJBqmaN32P9tCidlKz1EGv6WoRFICYnk3Dd/YFLBwnFIozA==} + '@prisma/fetch-engine@5.16.0': + resolution: {integrity: sha512-8C8y6J9eWRl+R/aO3vQ2HlmM9IbjAmrZaaEAdC0OJfG3CHvbTOcL7VRY6CEUKo8RwZ8bdATOePaSMS634fHWgw==} '@prisma/fetch-engine@5.3.1': resolution: {integrity: sha512-w1yk1YiK8N82Pobdq58b85l6e8akyrkxuzwV9DoiUTRf3gpsuhJJesHc4Yi0WzUC9/3znizl1UfCsI6dhkj3Vw==} @@ -287,8 +287,8 @@ packages: '@prisma/generator-helper@5.3.1': resolution: {integrity: sha512-zrYS0iHLgPlOJjYnd5KvVMMvSS+ktOL39EwooS5EnyvfzwfzxlKCeOUgxTfiKYs0WUWqzEvyNAYtramYgSknsQ==} - '@prisma/get-platform@5.12.1': - resolution: {integrity: sha512-pgIR+pSvhYHiUcqXVEZS31NrFOTENC9yFUdEAcx7cdQBoZPmHVjtjN4Ss6NzVDMYPrKJJ51U14EhEoeuBlMioQ==} + '@prisma/get-platform@5.16.0': + resolution: {integrity: sha512-ynp2jAYfYdd7OObX+uWaFRpvhPVmpF0nsRMhbrWdVVUj39q3Zr8dGz5WDj2g+BTUE++u1T1Am3RyM3PBQdDZXA==} '@prisma/get-platform@5.3.1': resolution: {integrity: sha512-3IiZY2BUjKnAuZ0569zppZE6/rZbVAM09//c2nvPbbkGG9MqrirA8fbhhF7tfVmhyVfdmVCHnf/ujWPHJ8B46Q==} @@ -1576,8 +1576,8 @@ packages: resolution: {integrity: sha512-VpNpolZ8RXRgfU+j4R+fPZmX8EE95w3vJ2tt7+FwuiQc0leNTfLK5QLf3KbbPDes2rfjh3g20AjDxefQIo5GIA==} hasBin: true - prisma@5.12.1: - resolution: {integrity: sha512-SkMnb6wyIxTv9ACqiHBI2u9gD6y98qXRoCoLEnZsF6yee5Qg828G+ARrESN+lQHdw4maSZFFSBPPDpvSiVTo0Q==} + prisma@5.16.0: + resolution: {integrity: sha512-T1ZWJT/vgzp3rtRmd1iCSnPPsgOItXnnny+/cfpHraowiBEvUMD2pEI6yEOL6CP2EelTmq4wKDbXbYucy4Fd+A==} engines: {node: '>=16.13'} hasBin: true @@ -2379,11 +2379,11 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@prisma/client@5.12.1(prisma@5.12.1)': + '@prisma/client@5.16.0(prisma@5.16.0)': optionalDependencies: - prisma: 5.12.1 + prisma: 5.16.0 - '@prisma/debug@5.12.1': {} + '@prisma/debug@5.16.0': {} '@prisma/debug@5.3.1': dependencies: @@ -2393,22 +2393,22 @@ snapshots: transitivePeerDependencies: - supports-color - '@prisma/engines-version@5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab': {} + '@prisma/engines-version@5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303': {} - '@prisma/engines@5.12.1': + '@prisma/engines@5.16.0': dependencies: - '@prisma/debug': 5.12.1 - '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab - '@prisma/fetch-engine': 5.12.1 - '@prisma/get-platform': 5.12.1 + '@prisma/debug': 5.16.0 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/fetch-engine': 5.16.0 + '@prisma/get-platform': 5.16.0 '@prisma/engines@5.3.1': {} - '@prisma/fetch-engine@5.12.1': + '@prisma/fetch-engine@5.16.0': dependencies: - '@prisma/debug': 5.12.1 - '@prisma/engines-version': 5.12.0-21.473ed3124229e22d881cb7addf559799debae1ab - '@prisma/get-platform': 5.12.1 + '@prisma/debug': 5.16.0 + '@prisma/engines-version': 5.16.0-24.34ace0eb2704183d2c05b60b52fba5c43c13f303 + '@prisma/get-platform': 5.16.0 '@prisma/fetch-engine@5.3.1': dependencies: @@ -2442,9 +2442,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@prisma/get-platform@5.12.1': + '@prisma/get-platform@5.16.0': dependencies: - '@prisma/debug': 5.12.1 + '@prisma/debug': 5.16.0 '@prisma/get-platform@5.3.1': dependencies: @@ -3917,9 +3917,9 @@ snapshots: prettier@3.2.5: {} - prisma-extension-kysely@2.1.0(@prisma/client@5.12.1(prisma@5.12.1)): + prisma-extension-kysely@2.1.0(@prisma/client@5.16.0(prisma@5.16.0)): dependencies: - '@prisma/client': 5.12.1(prisma@5.12.1) + '@prisma/client': 5.16.0(prisma@5.16.0) prisma-kysely@1.8.0: dependencies: @@ -3932,9 +3932,9 @@ snapshots: - encoding - supports-color - prisma@5.12.1: + prisma@5.16.0: dependencies: - '@prisma/engines': 5.12.1 + '@prisma/engines': 5.16.0 process-nextick-args@2.0.1: {} From cf317c7d19b2748a6db63f494cddd59fc0895b4d Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:53:25 +0700 Subject: [PATCH 144/157] fix: import --- prisma/generated/types.ts | 459 -------------------------------------- prisma/schema.prisma | 1 + src/db.ts | 4 +- 3 files changed, 3 insertions(+), 461 deletions(-) delete mode 100644 prisma/generated/types.ts diff --git a/prisma/generated/types.ts b/prisma/generated/types.ts deleted file mode 100644 index 00946c7..0000000 --- a/prisma/generated/types.ts +++ /dev/null @@ -1,459 +0,0 @@ -import type { ColumnType } from "kysely"; -export type Generated = T extends ColumnType - ? ColumnType - : ColumnType; -export type Timestamp = ColumnType; - -export const Status = { - CREATED: "CREATED", - ACTIVE: "ACTIVE", - INACTIVE: "INACTIVE" -} as const; -export type Status = (typeof Status)[keyof typeof Status]; -export const UserType = { - USER: "USER", - MESSENGER: "MESSENGER", - DELEGATE: "DELEGATE", - AGENCY: "AGENCY" -} as const; -export type UserType = (typeof UserType)[keyof typeof UserType]; -export const CustomerType = { - CORP: "CORP", - PERS: "PERS" -} as const; -export type CustomerType = (typeof CustomerType)[keyof typeof CustomerType]; -export type Branch = { - id: string; - code: string; - taxNo: string; - name: string; - nameEN: string; - address: string; - addressEN: string; - telephoneNo: string; - provinceId: string | null; - districtId: string | null; - subDistrictId: string | null; - zipCode: string; - email: string; - contactName: string | null; - lineId: string | null; - latitude: string; - longitude: string; - isHeadOffice: Generated; - headOfficeId: string | null; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type BranchContact = { - id: string; - telephoneNo: string; - branchId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type BranchUser = { - id: string; - branchId: string; - userId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type Customer = { - id: string; - code: string; - personName: string; - personNameEN: string | null; - customerType: CustomerType; - customerName: string; - customerNameEN: string; - taxNo: string | null; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type CustomerBranch = { - id: string; - branchNo: number; - code: string; - legalPersonNo: string; - name: string; - nameEN: string; - customerId: string; - taxNo: string | null; - registerName: string; - registerDate: Timestamp; - authorizedCapital: string; - address: string; - addressEN: string; - provinceId: string | null; - districtId: string | null; - subDistrictId: string | null; - zipCode: string; - email: string; - telephoneNo: string; - employmentOffice: string; - bussinessType: string; - bussinessTypeEN: string; - jobPosition: string; - jobPositionEN: string; - jobDescription: string; - saleEmployee: string; - payDate: Timestamp; - wageRate: number; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type District = { - id: string; - name: string; - nameEN: string; - provinceId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type Employee = { - id: string; - code: string; - nrcNo: string; - firstName: string; - firstNameEN: string; - lastName: string; - lastNameEN: string; - dateOfBirth: Timestamp; - gender: string; - nationality: string; - address: string | null; - addressEN: string | null; - provinceId: string | null; - districtId: string | null; - subDistrictId: string | null; - zipCode: string; - passportType: string; - passportNumber: string; - passportIssueDate: Timestamp; - passportExpiryDate: Timestamp; - passportIssuingCountry: string; - passportIssuingPlace: string; - previousPassportReference: string | null; - visaType: string | null; - visaNumber: string | null; - visaIssueDate: Timestamp | null; - visaExpiryDate: Timestamp | null; - visaIssuingPlace: string | null; - visaStayUntilDate: Timestamp | null; - tm6Number: string | null; - entryDate: Timestamp | null; - workerStatus: string | null; - customerBranchId: string | null; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type EmployeeCheckup = { - id: string; - employeeId: string; - checkupResult: string | null; - checkupType: string | null; - provinceId: string | null; - hospitalName: string | null; - remark: string | null; - medicalBenefitScheme: string | null; - insuranceCompany: string | null; - coverageStartDate: Timestamp | null; - coverageExpireDate: Timestamp | null; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type EmployeeOtherInfo = { - id: string; - employeeId: string; - citizenId: string | null; - fatherBirthPlace: string | null; - fatherFirstName: string | null; - fatherLastName: string | null; - motherBirthPlace: string | null; - motherFirstName: string | null; - motherLastName: string | null; - fatherFirstNameEN: string | null; - fatherLastNameEN: string | null; - motherFirstNameEN: string | null; - motherLastNameEN: string | null; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type EmployeeWork = { - id: string; - employeeId: string; - ownerName: string | null; - positionName: string | null; - jobType: string | null; - workplace: string | null; - workPermitNo: string | null; - workPermitIssuDate: Timestamp | null; - workPermitExpireDate: Timestamp | null; - workEndDate: Timestamp | null; - remark: string | null; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type Menu = { - id: string; - caption: string; - captionEN: string; - menuType: string; - url: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; - parentId: string | null; -}; -export type MenuComponent = { - id: string; - componentId: string; - componentTag: string; - menuId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type Product = { - id: string; - code: string; - name: string; - detail: string; - process: number; - price: number; - agentPrice: number; - serviceCharge: number; - status: Generated; - statusOrder: Generated; - remark: string | null; - productTypeId: string | null; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type ProductGroup = { - id: string; - code: string; - name: string; - detail: string; - remark: string; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type ProductType = { - id: string; - code: string; - name: string; - detail: string; - remark: string; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; - productGroupId: string; -}; -export type Province = { - id: string; - name: string; - nameEN: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type RoleMenuComponentPermission = { - id: string; - userRole: string; - permission: string; - menuComponentId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type RoleMenuPermission = { - id: string; - userRole: string; - permission: string; - menuId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type RunningNo = { - key: string; - value: number; -}; -export type Service = { - id: string; - code: string; - name: string; - detail: string; - attributes: unknown | null; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type SubDistrict = { - id: string; - name: string; - nameEN: string; - zipCode: string; - districtId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type User = { - id: string; - code: string | null; - firstName: string; - firstNameEN: string; - lastName: string; - lastNameEN: string; - username: string; - gender: string; - address: string; - addressEN: string; - provinceId: string | null; - districtId: string | null; - subDistrictId: string | null; - zipCode: string; - email: string; - telephoneNo: string; - registrationNo: string | null; - startDate: Timestamp | null; - retireDate: Timestamp | null; - checkpoint: string | null; - checkpointEN: string | null; - userType: UserType; - userRole: string; - discountCondition: string | null; - licenseNo: string | null; - licenseIssueDate: Timestamp | null; - licenseExpireDate: Timestamp | null; - sourceNationality: string | null; - importNationality: string | null; - trainingPlace: string | null; - responsibleArea: string | null; - birthDate: Timestamp | null; - status: Generated; - statusOrder: Generated; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type UserMenuComponentPermission = { - id: string; - userId: string; - menuComponentId: string; - permission: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type UserMenuPermission = { - id: string; - permission: string; - menuId: string; - userId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type Work = { - id: string; - order: number; - name: string; - attributes: unknown | null; - status: Generated; - statusOrder: Generated; - serviceId: string | null; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type WorkProduct = { - order: number; - workId: string; - productId: string; - createdBy: string | null; - createdAt: Generated; - updateBy: string | null; - updatedAt: Timestamp; -}; -export type DB = { - Branch: Branch; - BranchContact: BranchContact; - BranchUser: BranchUser; - Customer: Customer; - CustomerBranch: CustomerBranch; - District: District; - Employee: Employee; - EmployeeCheckup: EmployeeCheckup; - EmployeeOtherInfo: EmployeeOtherInfo; - EmployeeWork: EmployeeWork; - Menu: Menu; - MenuComponent: MenuComponent; - Product: Product; - ProductGroup: ProductGroup; - ProductType: ProductType; - Province: Province; - RoleMenuComponentPermission: RoleMenuComponentPermission; - RoleMenuPermission: RoleMenuPermission; - RunningNo: RunningNo; - Service: Service; - SubDistrict: SubDistrict; - User: User; - UserMenuComponentPermission: UserMenuComponentPermission; - UserMenuPermission: UserMenuPermission; - Work: Work; - WorkProduct: WorkProduct; -}; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index aa1bed9..14d9d71 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -4,6 +4,7 @@ generator client { generator kysely { provider = "prisma-kysely" + output = "../src/generated/kysely" } datasource db { diff --git a/src/db.ts b/src/db.ts index f63bece..1e2206b 100644 --- a/src/db.ts +++ b/src/db.ts @@ -1,7 +1,7 @@ import { PrismaClient } from "@prisma/client"; -import kyselyExtension from "prisma-extension-kysely"; -import type { DB } from "../prisma/generated/types.ts"; import { Kysely, PostgresAdapter, PostgresIntrospector, PostgresQueryCompiler } from "kysely"; +import kyselyExtension from "prisma-extension-kysely"; +import type { DB } from "./generated/kysely/types"; const prisma = new PrismaClient({ errorFormat: process.env.NODE_ENV === "production" ? "minimal" : "pretty", From 8af1ace0d0f88db5a3bbc8c6e8c6d729d6f3cffc Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Wed, 26 Jun 2024 13:01:01 +0700 Subject: [PATCH 145/157] fix: missing paging param --- src/controllers/product/group-controller.ts | 2 ++ src/controllers/product/type-controller.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index fb5b568..61937cf 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -68,6 +68,8 @@ export class ProductGroup extends Controller { prisma.productGroup.findMany({ orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, + take: pageSize, + skip: (page - 1) * pageSize, }), prisma.productGroup.count({ where }), ]); diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 4d5bc9c..4945deb 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -70,6 +70,8 @@ export class ProductType extends Controller { prisma.productType.findMany({ orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, + take: pageSize, + skip: (page - 1) * pageSize, }), prisma.productType.count({ where }), ]); From 8ac252721744de1f3a8a8d4d5e1a0c1fc5668b10 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Thu, 27 Jun 2024 09:01:20 +0700 Subject: [PATCH 146/157] feat: add user name to log data --- src/middlewares/auth.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts index 783e933..1809e73 100644 --- a/src/middlewares/auth.ts +++ b/src/middlewares/auth.ts @@ -12,6 +12,7 @@ export async function expressAuthentication( case "keycloak": const authData = await keycloakAuth(request, scopes); request.app.locals.logData.sessionId = authData.session_state; + request.app.locals.logData.user = authData.preffered_username; return authData; default: throw new HttpError( From 3e3d2cf01cae8cdd53f14216518f5f68a8d4fadf Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 08:57:53 +0700 Subject: [PATCH 147/157] feat: employee history --- prisma/schema.prisma | 14 +++++++++++ src/controllers/employee-controller.ts | 33 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 14d9d71..6a2e62b 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -472,6 +472,20 @@ model Employee { employeeCheckup EmployeeCheckup[] employeeWork EmployeeWork[] employeeOtherInfo EmployeeOtherInfo[] + + editHistory EmployeeHistory[] +} + +model EmployeeHistory { + id String @id @default(uuid()) + field String + valueBefore Json + valueAfter Json + + timestamp DateTime @default(now()) + + masterId String + master Employee @relation(fields: [masterId], references: [id], onDelete: Cascade) } model EmployeeCheckup { diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index edb780b..abd7c83 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -635,6 +635,32 @@ export class EmployeeController extends Controller { }); }); + const historyEntries: { field: string; valueBefore: string; valueAfter: string }[] = []; + + for (const k of Object.keys(body)) { + const field = k as keyof typeof body; + + if (field === "employeeCheckup") continue; + if (field === "employeeOtherInfo") continue; + if (field === "employeeWork") continue; + + let valueBefore = employee[field]; + let valueAfter = body[field]; + + if (valueBefore === undefined && valueAfter === undefined) continue; + + if (valueBefore instanceof Date) valueBefore = valueBefore.toISOString(); + if (valueBefore === null || valueBefore === undefined) valueBefore = ""; + if (valueAfter instanceof Date) valueAfter = valueAfter.toISOString(); + if (valueAfter === null || valueAfter === undefined) valueAfter = ""; + + if (valueBefore !== valueAfter) historyEntries.push({ field, valueBefore, valueAfter }); + } + + await prisma.employeeHistory.createMany({ + data: historyEntries.map((v) => ({ ...v, masterId: employee.id })), + }); + return Object.assign(record, { profileImageUrl: await presignedGetObjectIfExist( MINIO_BUCKET, @@ -663,4 +689,11 @@ export class EmployeeController extends Controller { return await prisma.employee.delete({ where: { id: employeeId } }); } + + @Get("{employeeId}/edit-history") + async editHistory(@Path() employeeId: string) { + return await prisma.employeeHistory.findMany({ + where: { masterId: employeeId }, + }); + } } From 123210c2dd01dfc79acf0f7ac5f1b4ca8efc4a71 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:31:17 +0700 Subject: [PATCH 148/157] feat: add user update info to history --- .../migration.sql | 14 ++++++++++++++ .../migration.sql | 7 +++++++ prisma/schema.prisma | 6 ++++++ 3 files changed, 27 insertions(+) create mode 100644 prisma/migrations/20240628020143_add_history_employee/migration.sql create mode 100644 prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql diff --git a/prisma/migrations/20240628020143_add_history_employee/migration.sql b/prisma/migrations/20240628020143_add_history_employee/migration.sql new file mode 100644 index 0000000..b6840b8 --- /dev/null +++ b/prisma/migrations/20240628020143_add_history_employee/migration.sql @@ -0,0 +1,14 @@ +-- CreateTable +CREATE TABLE "EmployeeHistory" ( + "id" TEXT NOT NULL, + "field" TEXT NOT NULL, + "valueBefore" JSONB NOT NULL, + "valueAfter" JSONB NOT NULL, + "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "masterId" TEXT NOT NULL, + + CONSTRAINT "EmployeeHistory_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_masterId_fkey" FOREIGN KEY ("masterId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql b/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql new file mode 100644 index 0000000..6ff205f --- /dev/null +++ b/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql @@ -0,0 +1,7 @@ +-- AlterTable +ALTER TABLE "EmployeeHistory" ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedBy" TEXT, +ADD COLUMN "updatedByUserId" TEXT; + +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_updatedByUserId_fkey" FOREIGN KEY ("updatedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6a2e62b..2a3caac 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -329,6 +329,7 @@ model User { branch BranchUser[] userMenuPermission UserMenuPermission[] userMenuComponentPermission UserMenuComponentPermission[] + employeeHistory EmployeeHistory[] } enum CustomerType { @@ -484,6 +485,11 @@ model EmployeeHistory { timestamp DateTime @default(now()) + updatedByUserId String? + updatedByUser User? @relation(fields: [updatedByUserId], references: [id]) + updatedBy String? + updatedAt DateTime @default(now()) + masterId String master Employee @relation(fields: [masterId], references: [id], onDelete: Cascade) } From d0d59cea0d167ab987253dc05afbc38c3319fde8 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:32:36 +0700 Subject: [PATCH 149/157] refactor: move security to route by route --- src/controllers/user-controller.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index 73f0ef4..db756fb 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -121,9 +121,9 @@ function imageLocation(id: string) { @Route("api/v1/user") @Tags("User") -@Security("keycloak") export class UserController extends Controller { @Get("type-stats") + @Security("keycloak") async getUserTypeStats() { const list = await prisma.user.groupBy({ by: "userType", @@ -145,6 +145,7 @@ export class UserController extends Controller { } @Get() + @Security("keycloak") async getUser( @Query() userType?: UserType, @Query() zipCode?: string, @@ -199,6 +200,7 @@ export class UserController extends Controller { } @Get("{userId}") + @Security("keycloak") async getUserById(@Path() userId: string) { const record = await prisma.user.findFirst({ include: { @@ -221,6 +223,7 @@ export class UserController extends Controller { } @Post() + @Security("keycloak") async createUser(@Request() req: RequestWithUser, @Body() body: UserCreate) { if (body.provinceId || body.districtId || body.subDistrictId) { const [province, district, subDistrict] = await prisma.$transaction([ @@ -316,6 +319,7 @@ export class UserController extends Controller { } @Put("{userId}") + @Security("keycloak") async editUser( @Request() req: RequestWithUser, @Body() body: UserUpdate, @@ -454,6 +458,7 @@ export class UserController extends Controller { } @Delete("{userId}") + @Security("keycloak") async deleteUser(@Path() userId: string) { const record = await prisma.user.findFirst({ include: { From 0e2cc3cb21af1e1a560608ec920006cfb9835979 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 09:35:32 +0700 Subject: [PATCH 150/157] refactor!: change typo field and reset migration --- .../migration.sql | 14 - .../migration.sql | 3 - .../20240410053228_fix_typo/migration.sql | 9 - .../20240417020614_remove_field/migration.sql | 8 - .../20240417041541_move_field/migration.sql | 11 - .../20240417063829_update_table/migration.sql | 119 ------- .../migration.sql | 2 - .../migration.sql | 3 - .../migration.sql | 8 - .../migration.sql | 12 - .../migration.sql | 2 - .../migration.sql | 8 - .../20240418061959_rename_field/migration.sql | 9 - .../migration.sql | 8 - .../migration.sql | 10 - .../migration.sql | 28 -- .../migration.sql | 10 - .../migration.sql | 15 - .../migration.sql | 10 - .../20240610061629_add_field/migration.sql | 30 -- .../migration.sql | 10 - .../20240610074721_update_field/migration.sql | 11 - .../migration.sql | 45 --- .../migration.sql | 31 -- .../20240611042536_add_field/migration.sql | 10 - .../migration.sql | 25 -- .../migration.sql | 11 - .../migration.sql | 36 -- .../migration.sql | 8 - .../migration.sql | 18 - .../migration.sql | 12 - .../migration.sql | 14 - .../migration.sql | 8 - .../migration.sql | 22 -- .../migration.sql | 10 - .../20240617105818_add_field/migration.sql | 9 - .../migration.sql | 29 -- .../20240626042218_adjust_type/migration.sql | 4 - .../migration.sql | 14 - .../migration.sql | 7 - .../migration.sql | 326 ++++++++++++++---- prisma/schema.prisma | 50 +-- src/controllers/branch-contact-controller.ts | 4 +- src/controllers/branch-controller.ts | 4 +- src/controllers/branch-user-controller.ts | 4 +- src/controllers/customer-branch-controller.ts | 4 +- src/controllers/customer-controller.ts | 10 +- .../employee-checkup-controller.ts | 4 +- src/controllers/employee-controller.ts | 12 +- .../employee-other-info-controller.ts | 4 +- src/controllers/employee-work-controller.ts | 4 +- src/controllers/product-service-controller.ts | 4 +- src/controllers/product/group-controller.ts | 4 +- src/controllers/product/product-controller.ts | 4 +- src/controllers/product/type-controller.ts | 4 +- src/controllers/service/service-controller.ts | 4 +- src/controllers/user-controller.ts | 4 +- src/controllers/work/work-controller.ts | 8 +- 58 files changed, 327 insertions(+), 784 deletions(-) delete mode 100644 prisma/migrations/20240409065557_update_customer/migration.sql delete mode 100644 prisma/migrations/20240410043453_add_missing_user_field/migration.sql delete mode 100644 prisma/migrations/20240410053228_fix_typo/migration.sql delete mode 100644 prisma/migrations/20240417020614_remove_field/migration.sql delete mode 100644 prisma/migrations/20240417041541_move_field/migration.sql delete mode 100644 prisma/migrations/20240417063829_update_table/migration.sql delete mode 100644 prisma/migrations/20240417064127_add_missing_user_field/migration.sql delete mode 100644 prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql delete mode 100644 prisma/migrations/20240417094807_add_username_field/migration.sql delete mode 100644 prisma/migrations/20240418042147_fix_missing_field/migration.sql delete mode 100644 prisma/migrations/20240418060611_add_hq_tel_field/migration.sql delete mode 100644 prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql delete mode 100644 prisma/migrations/20240418061959_rename_field/migration.sql delete mode 100644 prisma/migrations/20240418062042_remove_optional/migration.sql delete mode 100644 prisma/migrations/20240422092016_add_running_no_table/migration.sql delete mode 100644 prisma/migrations/20240423104607_add_missing_field/migration.sql delete mode 100644 prisma/migrations/20240424030115_add_missing_field_en/migration.sql delete mode 100644 prisma/migrations/20240607065019_update_data_type/migration.sql delete mode 100644 prisma/migrations/20240607070114_fix_wrong_field/migration.sql delete mode 100644 prisma/migrations/20240610061629_add_field/migration.sql delete mode 100644 prisma/migrations/20240610062435_fix_prev_typo/migration.sql delete mode 100644 prisma/migrations/20240610074721_update_field/migration.sql delete mode 100644 prisma/migrations/20240610094945_change_employee_fields/migration.sql delete mode 100644 prisma/migrations/20240611040600_make_field_optional/migration.sql delete mode 100644 prisma/migrations/20240611042536_add_field/migration.sql delete mode 100644 prisma/migrations/20240611060055_change_relation/migration.sql delete mode 100644 prisma/migrations/20240611081013_restructure_database/migration.sql delete mode 100644 prisma/migrations/20240612042722_overhaul_service_table/migration.sql delete mode 100644 prisma/migrations/20240612045512_remove_order_from_work/migration.sql delete mode 100644 prisma/migrations/20240612065711_composite_key_m2m/migration.sql delete mode 100644 prisma/migrations/20240612100121_update_field_to_optional/migration.sql delete mode 100644 prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql delete mode 100644 prisma/migrations/20240614025514_remove_unintended_field/migration.sql delete mode 100644 prisma/migrations/20240614084850_update_work_table/migration.sql delete mode 100644 prisma/migrations/20240614095339_update_product_fields/migration.sql delete mode 100644 prisma/migrations/20240617105818_add_field/migration.sql delete mode 100644 prisma/migrations/20240624061417_add_order_status/migration.sql delete mode 100644 prisma/migrations/20240626042218_adjust_type/migration.sql delete mode 100644 prisma/migrations/20240628020143_add_history_employee/migration.sql delete mode 100644 prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql rename prisma/migrations/{20240409061231_init => 20240628023502_init}/migration.sql (60%) diff --git a/prisma/migrations/20240409065557_update_customer/migration.sql b/prisma/migrations/20240409065557_update_customer/migration.sql deleted file mode 100644 index f5291b9..0000000 --- a/prisma/migrations/20240409065557_update_customer/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `imageUrl` on the `Customer` table. All the data in the column will be lost. - - Changed the type of `customerType` on the `Customer` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - -*/ --- CreateEnum -CREATE TYPE "CustomerType" AS ENUM ('CORP', 'PERS'); - --- AlterTable -ALTER TABLE "Customer" DROP COLUMN "imageUrl", -DROP COLUMN "customerType", -ADD COLUMN "customerType" "CustomerType" NOT NULL; diff --git a/prisma/migrations/20240410043453_add_missing_user_field/migration.sql b/prisma/migrations/20240410043453_add_missing_user_field/migration.sql deleted file mode 100644 index a32f678..0000000 --- a/prisma/migrations/20240410043453_add_missing_user_field/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "birtDate" TIMESTAMP(3), -ADD COLUMN "responsibleArea" TEXT; diff --git a/prisma/migrations/20240410053228_fix_typo/migration.sql b/prisma/migrations/20240410053228_fix_typo/migration.sql deleted file mode 100644 index 59c29dd..0000000 --- a/prisma/migrations/20240410053228_fix_typo/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `birtDate` on the `User` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "User" DROP COLUMN "birtDate", -ADD COLUMN "birthDate" TIMESTAMP(3); diff --git a/prisma/migrations/20240417020614_remove_field/migration.sql b/prisma/migrations/20240417020614_remove_field/migration.sql deleted file mode 100644 index 3cb801f..0000000 --- a/prisma/migrations/20240417020614_remove_field/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `keycloakId` on the `User` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "User" DROP COLUMN "keycloakId"; diff --git a/prisma/migrations/20240417041541_move_field/migration.sql b/prisma/migrations/20240417041541_move_field/migration.sql deleted file mode 100644 index 3b720dc..0000000 --- a/prisma/migrations/20240417041541_move_field/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `lineId` on the `BranchContact` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "lineId" TEXT; - --- AlterTable -ALTER TABLE "BranchContact" DROP COLUMN "lineId"; diff --git a/prisma/migrations/20240417063829_update_table/migration.sql b/prisma/migrations/20240417063829_update_table/migration.sql deleted file mode 100644 index 8b7bd17..0000000 --- a/prisma/migrations/20240417063829_update_table/migration.sql +++ /dev/null @@ -1,119 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `telephoneNo` on the `Branch` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" DROP COLUMN "telephoneNo"; - --- CreateTable -CREATE TABLE "Menu" ( - "id" TEXT NOT NULL, - "caption" TEXT NOT NULL, - "captionEN" TEXT NOT NULL, - "menuType" TEXT NOT NULL, - "url" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - "parentId" TEXT, - - CONSTRAINT "Menu_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "RoleMenuPermission" ( - "id" TEXT NOT NULL, - "userRole" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "RoleMenuPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "UserMenuPermission" ( - "id" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "UserMenuPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "MenuComponent" ( - "id" TEXT NOT NULL, - "componentId" TEXT NOT NULL, - "componentTag" TEXT NOT NULL, - "menuId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "MenuComponent_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "RoleMenuComponentPermission" ( - "id" TEXT NOT NULL, - "componentId" TEXT NOT NULL, - "componentTag" TEXT NOT NULL, - "menuComponentId" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "RoleMenuComponentPermission_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "UserMenuComponentPermission" ( - "id" TEXT NOT NULL, - "userId" TEXT NOT NULL, - "menuComponentId" TEXT NOT NULL, - "permission" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "UserMenuComponentPermission_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Menu"("id") ON DELETE SET NULL ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "RoleMenuPermission" ADD CONSTRAINT "RoleMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "MenuComponent" ADD CONSTRAINT "MenuComponent_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "RoleMenuComponentPermission" ADD CONSTRAINT "RoleMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20240417064127_add_missing_user_field/migration.sql b/prisma/migrations/20240417064127_add_missing_user_field/migration.sql deleted file mode 100644 index b0b8442..0000000 --- a/prisma/migrations/20240417064127_add_missing_user_field/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "contactName" TEXT; diff --git a/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql b/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql deleted file mode 100644 index 30b641e..0000000 --- a/prisma/migrations/20240417091605_add_missing_user_field_checkpoint/migration.sql +++ /dev/null @@ -1,3 +0,0 @@ --- AlterTable -ALTER TABLE "User" ADD COLUMN "checkpoint" TEXT, -ADD COLUMN "checkpointEN" TEXT; diff --git a/prisma/migrations/20240417094807_add_username_field/migration.sql b/prisma/migrations/20240417094807_add_username_field/migration.sql deleted file mode 100644 index 2d730b3..0000000 --- a/prisma/migrations/20240417094807_add_username_field/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Added the required column `username` to the `User` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "User" ADD COLUMN "username" TEXT NOT NULL; diff --git a/prisma/migrations/20240418042147_fix_missing_field/migration.sql b/prisma/migrations/20240418042147_fix_missing_field/migration.sql deleted file mode 100644 index c22f622..0000000 --- a/prisma/migrations/20240418042147_fix_missing_field/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `componentId` on the `RoleMenuComponentPermission` table. All the data in the column will be lost. - - You are about to drop the column `componentTag` on the `RoleMenuComponentPermission` table. All the data in the column will be lost. - - Added the required column `userRole` to the `RoleMenuComponentPermission` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "RoleMenuComponentPermission" DROP COLUMN "componentId", -DROP COLUMN "componentTag", -ADD COLUMN "userRole" TEXT NOT NULL; diff --git a/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql b/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql deleted file mode 100644 index ae17c14..0000000 --- a/prisma/migrations/20240418060611_add_hq_tel_field/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "telephoneHq" TEXT; diff --git a/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql b/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql deleted file mode 100644 index 922dfa6..0000000 --- a/prisma/migrations/20240418060739_remove_optional_hq_tel/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Made the column `telephoneHq` on table `Branch` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "Branch" ALTER COLUMN "telephoneHq" SET NOT NULL; diff --git a/prisma/migrations/20240418061959_rename_field/migration.sql b/prisma/migrations/20240418061959_rename_field/migration.sql deleted file mode 100644 index 6233aa1..0000000 --- a/prisma/migrations/20240418061959_rename_field/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `telephoneHq` on the `Branch` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Branch" DROP COLUMN "telephoneHq", -ADD COLUMN "telephoneNo" TEXT; diff --git a/prisma/migrations/20240418062042_remove_optional/migration.sql b/prisma/migrations/20240418062042_remove_optional/migration.sql deleted file mode 100644 index ca8ae37..0000000 --- a/prisma/migrations/20240418062042_remove_optional/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - Made the column `telephoneNo` on table `Branch` required. This step will fail if there are existing NULL values in that column. - -*/ --- AlterTable -ALTER TABLE "Branch" ALTER COLUMN "telephoneNo" SET NOT NULL; diff --git a/prisma/migrations/20240422092016_add_running_no_table/migration.sql b/prisma/migrations/20240422092016_add_running_no_table/migration.sql deleted file mode 100644 index ad777a0..0000000 --- a/prisma/migrations/20240422092016_add_running_no_table/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ --- CreateTable -CREATE TABLE "RunningNo" ( - "key" TEXT NOT NULL, - "value" INTEGER NOT NULL, - - CONSTRAINT "RunningNo_pkey" PRIMARY KEY ("key") -); - --- CreateIndex -CREATE UNIQUE INDEX "RunningNo_key_key" ON "RunningNo"("key"); diff --git a/prisma/migrations/20240423104607_add_missing_field/migration.sql b/prisma/migrations/20240423104607_add_missing_field/migration.sql deleted file mode 100644 index 6c8a704..0000000 --- a/prisma/migrations/20240423104607_add_missing_field/migration.sql +++ /dev/null @@ -1,28 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `latitude` on the `CustomerBranch` table. All the data in the column will be lost. - - You are about to drop the column `longitude` on the `CustomerBranch` table. All the data in the column will be lost. - - Added the required column `bussinessType` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `employmentOffice` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `jobDescription` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `jobPosition` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `payDate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `saleEmployee` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `wageDate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Customer" ADD COLUMN "taxNo" TEXT; - --- AlterTable -ALTER TABLE "CustomerBranch" DROP COLUMN "latitude", -DROP COLUMN "longitude", -ADD COLUMN "bussinessType" TEXT NOT NULL, -ADD COLUMN "employmentOffice" TEXT NOT NULL, -ADD COLUMN "jobDescription" TEXT NOT NULL, -ADD COLUMN "jobPosition" TEXT NOT NULL, -ADD COLUMN "payDate" TEXT NOT NULL, -ADD COLUMN "saleEmployee" TEXT NOT NULL, -ADD COLUMN "wageDate" TEXT NOT NULL, -ALTER COLUMN "taxNo" DROP NOT NULL; diff --git a/prisma/migrations/20240424030115_add_missing_field_en/migration.sql b/prisma/migrations/20240424030115_add_missing_field_en/migration.sql deleted file mode 100644 index d3726ca..0000000 --- a/prisma/migrations/20240424030115_add_missing_field_en/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - Added the required column `bussinessTypeEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - - Added the required column `jobPositionEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "CustomerBranch" ADD COLUMN "bussinessTypeEN" TEXT NOT NULL, -ADD COLUMN "jobPositionEN" TEXT NOT NULL; diff --git a/prisma/migrations/20240607065019_update_data_type/migration.sql b/prisma/migrations/20240607065019_update_data_type/migration.sql deleted file mode 100644 index b72dc89..0000000 --- a/prisma/migrations/20240607065019_update_data_type/migration.sql +++ /dev/null @@ -1,15 +0,0 @@ -/* - Warnings: - - - Changed the type of `branchNo` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - - Changed the type of `payDate` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - - Changed the type of `wageDate` on the `CustomerBranch` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - -*/ --- AlterTable -ALTER TABLE "CustomerBranch" DROP COLUMN "branchNo", -ADD COLUMN "branchNo" INTEGER NOT NULL, -DROP COLUMN "payDate", -ADD COLUMN "payDate" TIMESTAMP(3) NOT NULL, -DROP COLUMN "wageDate", -ADD COLUMN "wageDate" TIMESTAMP(3) NOT NULL; diff --git a/prisma/migrations/20240607070114_fix_wrong_field/migration.sql b/prisma/migrations/20240607070114_fix_wrong_field/migration.sql deleted file mode 100644 index a5494e8..0000000 --- a/prisma/migrations/20240607070114_fix_wrong_field/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `wageDate` on the `CustomerBranch` table. All the data in the column will be lost. - - Added the required column `wageRate` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "CustomerBranch" DROP COLUMN "wageDate", -ADD COLUMN "wageRate" INTEGER NOT NULL; diff --git a/prisma/migrations/20240610061629_add_field/migration.sql b/prisma/migrations/20240610061629_add_field/migration.sql deleted file mode 100644 index bea038e..0000000 --- a/prisma/migrations/20240610061629_add_field/migration.sql +++ /dev/null @@ -1,30 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `birthPlace` on the `EmployeeOtherInfo` table. All the data in the column will be lost. - - You are about to drop the column `fatherFullName` on the `EmployeeOtherInfo` table. All the data in the column will be lost. - - You are about to drop the column `motherFullName` on the `EmployeeOtherInfo` table. All the data in the column will be lost. - - Added the required column `birthPlaceEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `fatherFirstName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `fatherFirstNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `fatherLastName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `fatherLastNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `motherFirstName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `motherFirstNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `motherLastName` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - - Added the required column `motherLastNameEN` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlace", -DROP COLUMN "fatherFullName", -DROP COLUMN "motherFullName", -ADD COLUMN "birthPlaceEN" TEXT NOT NULL, -ADD COLUMN "fatherFirstName" TEXT NOT NULL, -ADD COLUMN "fatherFirstNameEN" TEXT NOT NULL, -ADD COLUMN "fatherLastName" TEXT NOT NULL, -ADD COLUMN "fatherLastNameEN" TEXT NOT NULL, -ADD COLUMN "motherFirstName" TEXT NOT NULL, -ADD COLUMN "motherFirstNameEN" TEXT NOT NULL, -ADD COLUMN "motherLastName" TEXT NOT NULL, -ADD COLUMN "motherLastNameEN" TEXT NOT NULL; diff --git a/prisma/migrations/20240610062435_fix_prev_typo/migration.sql b/prisma/migrations/20240610062435_fix_prev_typo/migration.sql deleted file mode 100644 index 23b59f5..0000000 --- a/prisma/migrations/20240610062435_fix_prev_typo/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `birthPlaceEN` on the `EmployeeOtherInfo` table. All the data in the column will be lost. - - Added the required column `birthPlace` to the `EmployeeOtherInfo` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlaceEN", -ADD COLUMN "birthPlace" TEXT NOT NULL; diff --git a/prisma/migrations/20240610074721_update_field/migration.sql b/prisma/migrations/20240610074721_update_field/migration.sql deleted file mode 100644 index d6e7653..0000000 --- a/prisma/migrations/20240610074721_update_field/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `imageUrl` on the `Product` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "EmployeeWork" ADD COLUMN "remark" TEXT; - --- AlterTable -ALTER TABLE "Product" DROP COLUMN "imageUrl"; diff --git a/prisma/migrations/20240610094945_change_employee_fields/migration.sql b/prisma/migrations/20240610094945_change_employee_fields/migration.sql deleted file mode 100644 index e20d1e0..0000000 --- a/prisma/migrations/20240610094945_change_employee_fields/migration.sql +++ /dev/null @@ -1,45 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `arrivalBarricade` on the `Employee` table. All the data in the column will be lost. - - You are about to drop the column `arrivalCardNo` on the `Employee` table. All the data in the column will be lost. - - You are about to drop the column `email` on the `Employee` table. All the data in the column will be lost. - - You are about to drop the column `telephoneNo` on the `Employee` table. All the data in the column will be lost. - - Added the required column `entryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportExpiryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportIssueDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportIssuingCountry` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportIssuingPlace` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportNumber` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `passportType` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `tm6Number` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaExpiryDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaIssueDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaIssuingPlace` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaNumber` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaStayUntilDate` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `visaType` to the `Employee` table without a default value. This is not possible if the table is not empty. - - Added the required column `workerStatus` to the `Employee` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Employee" DROP COLUMN "arrivalBarricade", -DROP COLUMN "arrivalCardNo", -DROP COLUMN "email", -DROP COLUMN "telephoneNo", -ADD COLUMN "entryDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "passportExpiryDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "passportIssueDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "passportIssuingCountry" TEXT NOT NULL, -ADD COLUMN "passportIssuingPlace" TEXT NOT NULL, -ADD COLUMN "passportNumber" TEXT NOT NULL, -ADD COLUMN "passportType" TEXT NOT NULL, -ADD COLUMN "previousPassportReference" TEXT, -ADD COLUMN "tm6Number" TEXT NOT NULL, -ADD COLUMN "visaExpiryDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "visaIssueDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "visaIssuingPlace" TEXT NOT NULL, -ADD COLUMN "visaNumber" TEXT NOT NULL, -ADD COLUMN "visaStayUntilDate" TIMESTAMP(3) NOT NULL, -ADD COLUMN "visaType" TEXT NOT NULL, -ADD COLUMN "workerStatus" TEXT NOT NULL; diff --git a/prisma/migrations/20240611040600_make_field_optional/migration.sql b/prisma/migrations/20240611040600_make_field_optional/migration.sql deleted file mode 100644 index 595a50d..0000000 --- a/prisma/migrations/20240611040600_make_field_optional/migration.sql +++ /dev/null @@ -1,31 +0,0 @@ --- AlterTable -ALTER TABLE "EmployeeCheckup" ALTER COLUMN "checkupResult" DROP NOT NULL, -ALTER COLUMN "checkupType" DROP NOT NULL, -ALTER COLUMN "hospitalName" DROP NOT NULL, -ALTER COLUMN "remark" DROP NOT NULL, -ALTER COLUMN "medicalBenefitScheme" DROP NOT NULL, -ALTER COLUMN "insuranceCompany" DROP NOT NULL, -ALTER COLUMN "coverageStartDate" DROP NOT NULL, -ALTER COLUMN "coverageExpireDate" DROP NOT NULL; - --- AlterTable -ALTER TABLE "EmployeeOtherInfo" ALTER COLUMN "citizenId" DROP NOT NULL, -ALTER COLUMN "fatherFirstName" DROP NOT NULL, -ALTER COLUMN "fatherFirstNameEN" DROP NOT NULL, -ALTER COLUMN "fatherLastName" DROP NOT NULL, -ALTER COLUMN "fatherLastNameEN" DROP NOT NULL, -ALTER COLUMN "motherFirstName" DROP NOT NULL, -ALTER COLUMN "motherFirstNameEN" DROP NOT NULL, -ALTER COLUMN "motherLastName" DROP NOT NULL, -ALTER COLUMN "motherLastNameEN" DROP NOT NULL, -ALTER COLUMN "birthPlace" DROP NOT NULL; - --- AlterTable -ALTER TABLE "EmployeeWork" ALTER COLUMN "ownerName" DROP NOT NULL, -ALTER COLUMN "positionName" DROP NOT NULL, -ALTER COLUMN "jobType" DROP NOT NULL, -ALTER COLUMN "workplace" DROP NOT NULL, -ALTER COLUMN "workPermitNo" DROP NOT NULL, -ALTER COLUMN "workPermitIssuDate" DROP NOT NULL, -ALTER COLUMN "workPermitExpireDate" DROP NOT NULL, -ALTER COLUMN "workEndDate" DROP NOT NULL; diff --git a/prisma/migrations/20240611042536_add_field/migration.sql b/prisma/migrations/20240611042536_add_field/migration.sql deleted file mode 100644 index d98d0b1..0000000 --- a/prisma/migrations/20240611042536_add_field/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `birthPlace` on the `EmployeeOtherInfo` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "EmployeeOtherInfo" DROP COLUMN "birthPlace", -ADD COLUMN "fatherBirthPlace" TEXT, -ADD COLUMN "motherBirthPlace" TEXT; diff --git a/prisma/migrations/20240611060055_change_relation/migration.sql b/prisma/migrations/20240611060055_change_relation/migration.sql deleted file mode 100644 index dc100a6..0000000 --- a/prisma/migrations/20240611060055_change_relation/migration.sql +++ /dev/null @@ -1,25 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `productGroupId` on the `Product` table. All the data in the column will be lost. - - Added the required column `productGroupId` to the `ProductType` table without a default value. This is not possible if the table is not empty. - - Added the required column `productId` to the `WorkProduct` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "Product" DROP CONSTRAINT "Product_productGroupId_fkey"; - --- AlterTable -ALTER TABLE "Product" DROP COLUMN "productGroupId"; - --- AlterTable -ALTER TABLE "ProductType" ADD COLUMN "productGroupId" TEXT NOT NULL; - --- AlterTable -ALTER TABLE "WorkProduct" ADD COLUMN "productId" TEXT NOT NULL; - --- AddForeignKey -ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "ProductType" ADD CONSTRAINT "ProductType_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240611081013_restructure_database/migration.sql b/prisma/migrations/20240611081013_restructure_database/migration.sql deleted file mode 100644 index 075d9b2..0000000 --- a/prisma/migrations/20240611081013_restructure_database/migration.sql +++ /dev/null @@ -1,11 +0,0 @@ -/* - Warnings: - - - Added the required column `code` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "CustomerBranch" ADD COLUMN "code" TEXT NOT NULL; - --- AlterTable -ALTER TABLE "Product" ADD COLUMN "attributes" JSONB; diff --git a/prisma/migrations/20240612042722_overhaul_service_table/migration.sql b/prisma/migrations/20240612042722_overhaul_service_table/migration.sql deleted file mode 100644 index 3549d90..0000000 --- a/prisma/migrations/20240612042722_overhaul_service_table/migration.sql +++ /dev/null @@ -1,36 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `serviceId` on the `Work` table. All the data in the column will be lost. - - Added the required column `order` to the `WorkProduct` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "Work" DROP CONSTRAINT "Work_serviceId_fkey"; - --- AlterTable -ALTER TABLE "Work" DROP COLUMN "serviceId"; - --- AlterTable -ALTER TABLE "WorkProduct" ADD COLUMN "order" INTEGER NOT NULL; - --- CreateTable -CREATE TABLE "WorkService" ( - "id" TEXT NOT NULL, - "order" INTEGER NOT NULL, - "workId" TEXT NOT NULL, - "serviceId" TEXT NOT NULL, - "createdBy" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, - "updatedAt" TIMESTAMP(3) NOT NULL, - "productId" TEXT, - - CONSTRAINT "WorkService_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "WorkService" ADD CONSTRAINT "WorkService_workId_fkey" FOREIGN KEY ("workId") REFERENCES "Work"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "WorkService" ADD CONSTRAINT "WorkService_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240612045512_remove_order_from_work/migration.sql b/prisma/migrations/20240612045512_remove_order_from_work/migration.sql deleted file mode 100644 index 7255159..0000000 --- a/prisma/migrations/20240612045512_remove_order_from_work/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `order` on the `Work` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Work" DROP COLUMN "order"; diff --git a/prisma/migrations/20240612065711_composite_key_m2m/migration.sql b/prisma/migrations/20240612065711_composite_key_m2m/migration.sql deleted file mode 100644 index 027089e..0000000 --- a/prisma/migrations/20240612065711_composite_key_m2m/migration.sql +++ /dev/null @@ -1,18 +0,0 @@ -/* - Warnings: - - - The primary key for the `WorkProduct` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `id` on the `WorkProduct` table. All the data in the column will be lost. - - The primary key for the `WorkService` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `id` on the `WorkService` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "WorkProduct" DROP CONSTRAINT "WorkProduct_pkey", -DROP COLUMN "id", -ADD CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("workId", "productId"); - --- AlterTable -ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_pkey", -DROP COLUMN "id", -ADD CONSTRAINT "WorkService_pkey" PRIMARY KEY ("workId", "serviceId"); diff --git a/prisma/migrations/20240612100121_update_field_to_optional/migration.sql b/prisma/migrations/20240612100121_update_field_to_optional/migration.sql deleted file mode 100644 index 72c9e76..0000000 --- a/prisma/migrations/20240612100121_update_field_to_optional/migration.sql +++ /dev/null @@ -1,12 +0,0 @@ --- AlterTable -ALTER TABLE "Employee" ALTER COLUMN "address" DROP NOT NULL, -ALTER COLUMN "addressEN" DROP NOT NULL, -ALTER COLUMN "entryDate" DROP NOT NULL, -ALTER COLUMN "tm6Number" DROP NOT NULL, -ALTER COLUMN "visaExpiryDate" DROP NOT NULL, -ALTER COLUMN "visaIssueDate" DROP NOT NULL, -ALTER COLUMN "visaIssuingPlace" DROP NOT NULL, -ALTER COLUMN "visaNumber" DROP NOT NULL, -ALTER COLUMN "visaStayUntilDate" DROP NOT NULL, -ALTER COLUMN "visaType" DROP NOT NULL, -ALTER COLUMN "workerStatus" DROP NOT NULL; diff --git a/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql b/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql deleted file mode 100644 index cadf124..0000000 --- a/prisma/migrations/20240613084622_add_custom_attributes_json/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `attributes` on the `Product` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "Product" DROP COLUMN "attributes"; - --- AlterTable -ALTER TABLE "Service" ADD COLUMN "attributes" JSONB; - --- AlterTable -ALTER TABLE "Work" ADD COLUMN "attributes" JSONB; diff --git a/prisma/migrations/20240614025514_remove_unintended_field/migration.sql b/prisma/migrations/20240614025514_remove_unintended_field/migration.sql deleted file mode 100644 index f97abe5..0000000 --- a/prisma/migrations/20240614025514_remove_unintended_field/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ -/* - Warnings: - - - You are about to drop the column `productId` on the `WorkService` table. All the data in the column will be lost. - -*/ --- AlterTable -ALTER TABLE "WorkService" DROP COLUMN "productId"; diff --git a/prisma/migrations/20240614084850_update_work_table/migration.sql b/prisma/migrations/20240614084850_update_work_table/migration.sql deleted file mode 100644 index fc91684..0000000 --- a/prisma/migrations/20240614084850_update_work_table/migration.sql +++ /dev/null @@ -1,22 +0,0 @@ -/* - Warnings: - - - You are about to drop the `WorkService` table. If the table is not empty, all the data it contains will be lost. - - Added the required column `order` to the `Work` table without a default value. This is not possible if the table is not empty. - -*/ --- DropForeignKey -ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_serviceId_fkey"; - --- DropForeignKey -ALTER TABLE "WorkService" DROP CONSTRAINT "WorkService_workId_fkey"; - --- AlterTable -ALTER TABLE "Work" ADD COLUMN "order" INTEGER NOT NULL, -ADD COLUMN "serviceId" TEXT; - --- DropTable -DROP TABLE "WorkService"; - --- AddForeignKey -ALTER TABLE "Work" ADD CONSTRAINT "Work_serviceId_fkey" FOREIGN KEY ("serviceId") REFERENCES "Service"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240614095339_update_product_fields/migration.sql b/prisma/migrations/20240614095339_update_product_fields/migration.sql deleted file mode 100644 index 94cf800..0000000 --- a/prisma/migrations/20240614095339_update_product_fields/migration.sql +++ /dev/null @@ -1,10 +0,0 @@ -/* - Warnings: - - - Changed the type of `process` on the `Product` table. No cast exists, the column would be dropped and recreated, which cannot be done if there is data, since the column is required. - -*/ --- AlterTable -ALTER TABLE "Product" ADD COLUMN "remark" TEXT, -DROP COLUMN "process", -ADD COLUMN "process" INTEGER NOT NULL; diff --git a/prisma/migrations/20240617105818_add_field/migration.sql b/prisma/migrations/20240617105818_add_field/migration.sql deleted file mode 100644 index 0aa2292..0000000 --- a/prisma/migrations/20240617105818_add_field/migration.sql +++ /dev/null @@ -1,9 +0,0 @@ -/* - Warnings: - - - Added the required column `personName` to the `Customer` table without a default value. This is not possible if the table is not empty. - -*/ --- AlterTable -ALTER TABLE "Customer" ADD COLUMN "personName" TEXT NOT NULL, -ADD COLUMN "personNameEN" TEXT; diff --git a/prisma/migrations/20240624061417_add_order_status/migration.sql b/prisma/migrations/20240624061417_add_order_status/migration.sql deleted file mode 100644 index 436649e..0000000 --- a/prisma/migrations/20240624061417_add_order_status/migration.sql +++ /dev/null @@ -1,29 +0,0 @@ --- AlterTable -ALTER TABLE "Branch" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Customer" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "CustomerBranch" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Employee" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Product" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "ProductGroup" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "ProductType" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Service" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "User" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; - --- AlterTable -ALTER TABLE "Work" ADD COLUMN "statusOrder" INTEGER NOT NULL DEFAULT 0; diff --git a/prisma/migrations/20240626042218_adjust_type/migration.sql b/prisma/migrations/20240626042218_adjust_type/migration.sql deleted file mode 100644 index 15fde59..0000000 --- a/prisma/migrations/20240626042218_adjust_type/migration.sql +++ /dev/null @@ -1,4 +0,0 @@ --- AlterTable -ALTER TABLE "Product" ALTER COLUMN "price" SET DATA TYPE DOUBLE PRECISION, -ALTER COLUMN "agentPrice" SET DATA TYPE DOUBLE PRECISION, -ALTER COLUMN "serviceCharge" SET DATA TYPE DOUBLE PRECISION; diff --git a/prisma/migrations/20240628020143_add_history_employee/migration.sql b/prisma/migrations/20240628020143_add_history_employee/migration.sql deleted file mode 100644 index b6840b8..0000000 --- a/prisma/migrations/20240628020143_add_history_employee/migration.sql +++ /dev/null @@ -1,14 +0,0 @@ --- CreateTable -CREATE TABLE "EmployeeHistory" ( - "id" TEXT NOT NULL, - "field" TEXT NOT NULL, - "valueBefore" JSONB NOT NULL, - "valueAfter" JSONB NOT NULL, - "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "masterId" TEXT NOT NULL, - - CONSTRAINT "EmployeeHistory_pkey" PRIMARY KEY ("id") -); - --- AddForeignKey -ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_masterId_fkey" FOREIGN KEY ("masterId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql b/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql deleted file mode 100644 index 6ff205f..0000000 --- a/prisma/migrations/20240628023020_add_updated_by_user_field/migration.sql +++ /dev/null @@ -1,7 +0,0 @@ --- AlterTable -ALTER TABLE "EmployeeHistory" ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, -ADD COLUMN "updatedBy" TEXT, -ADD COLUMN "updatedByUserId" TEXT; - --- AddForeignKey -ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_updatedByUserId_fkey" FOREIGN KEY ("updatedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/migrations/20240409061231_init/migration.sql b/prisma/migrations/20240628023502_init/migration.sql similarity index 60% rename from prisma/migrations/20240409061231_init/migration.sql rename to prisma/migrations/20240628023502_init/migration.sql index 9c0ad32..c8b655b 100644 --- a/prisma/migrations/20240409061231_init/migration.sql +++ b/prisma/migrations/20240628023502_init/migration.sql @@ -4,6 +4,103 @@ CREATE TYPE "Status" AS ENUM ('CREATED', 'ACTIVE', 'INACTIVE'); -- CreateEnum CREATE TYPE "UserType" AS ENUM ('USER', 'MESSENGER', 'DELEGATE', 'AGENCY'); +-- CreateEnum +CREATE TYPE "CustomerType" AS ENUM ('CORP', 'PERS'); + +-- CreateTable +CREATE TABLE "Menu" ( + "id" TEXT NOT NULL, + "caption" TEXT NOT NULL, + "captionEN" TEXT NOT NULL, + "menuType" TEXT NOT NULL, + "url" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + "parentId" TEXT, + + CONSTRAINT "Menu_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RoleMenuPermission" ( + "id" TEXT NOT NULL, + "userRole" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "RoleMenuPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "UserMenuPermission" ( + "id" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "UserMenuPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "MenuComponent" ( + "id" TEXT NOT NULL, + "componentId" TEXT NOT NULL, + "componentTag" TEXT NOT NULL, + "menuId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "MenuComponent_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RoleMenuComponentPermission" ( + "id" TEXT NOT NULL, + "userRole" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "menuComponentId" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "RoleMenuComponentPermission_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "RunningNo" ( + "key" TEXT NOT NULL, + "value" INTEGER NOT NULL, + + CONSTRAINT "RunningNo_pkey" PRIMARY KEY ("key") +); + +-- CreateTable +CREATE TABLE "UserMenuComponentPermission" ( + "id" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "menuComponentId" TEXT NOT NULL, + "permission" TEXT NOT NULL, + "createdBy" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "UserMenuComponentPermission_pkey" PRIMARY KEY ("id") +); + -- CreateTable CREATE TABLE "Province" ( "id" TEXT NOT NULL, @@ -11,7 +108,7 @@ CREATE TABLE "Province" ( "nameEN" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Province_pkey" PRIMARY KEY ("id") @@ -25,7 +122,7 @@ CREATE TABLE "District" ( "provinceId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "District_pkey" PRIMARY KEY ("id") @@ -40,7 +137,7 @@ CREATE TABLE "SubDistrict" ( "districtId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "SubDistrict_pkey" PRIMARY KEY ("id") @@ -55,20 +152,23 @@ CREATE TABLE "Branch" ( "nameEN" TEXT NOT NULL, "address" TEXT NOT NULL, "addressEN" TEXT NOT NULL, + "telephoneNo" TEXT NOT NULL, "provinceId" TEXT, "districtId" TEXT, "subDistrictId" TEXT, "zipCode" TEXT NOT NULL, "email" TEXT NOT NULL, - "telephoneNo" TEXT NOT NULL, + "contactName" TEXT, + "lineId" TEXT, "latitude" TEXT NOT NULL, "longitude" TEXT NOT NULL, "isHeadOffice" BOOLEAN NOT NULL DEFAULT false, "headOfficeId" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Branch_pkey" PRIMARY KEY ("id") @@ -78,11 +178,10 @@ CREATE TABLE "Branch" ( CREATE TABLE "BranchContact" ( "id" TEXT NOT NULL, "telephoneNo" TEXT NOT NULL, - "lineId" TEXT NOT NULL, "branchId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "BranchContact_pkey" PRIMARY KEY ("id") @@ -95,7 +194,7 @@ CREATE TABLE "BranchUser" ( "userId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "BranchUser_pkey" PRIMARY KEY ("id") @@ -104,12 +203,12 @@ CREATE TABLE "BranchUser" ( -- CreateTable CREATE TABLE "User" ( "id" TEXT NOT NULL, - "keycloakId" TEXT NOT NULL, "code" TEXT, "firstName" TEXT NOT NULL, "firstNameEN" TEXT NOT NULL, "lastName" TEXT NOT NULL, "lastNameEN" TEXT NOT NULL, + "username" TEXT NOT NULL, "gender" TEXT NOT NULL, "address" TEXT NOT NULL, "addressEN" TEXT NOT NULL, @@ -122,6 +221,8 @@ CREATE TABLE "User" ( "registrationNo" TEXT, "startDate" TIMESTAMP(3), "retireDate" TIMESTAMP(3), + "checkpoint" TEXT, + "checkpointEN" TEXT, "userType" "UserType" NOT NULL, "userRole" TEXT NOT NULL, "discountCondition" TEXT, @@ -131,10 +232,13 @@ CREATE TABLE "User" ( "sourceNationality" TEXT, "importNationality" TEXT, "trainingPlace" TEXT, + "responsibleArea" TEXT, + "birthDate" TIMESTAMP(3), "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id") @@ -144,14 +248,17 @@ CREATE TABLE "User" ( CREATE TABLE "Customer" ( "id" TEXT NOT NULL, "code" TEXT NOT NULL, - "customerType" TEXT NOT NULL, + "personName" TEXT NOT NULL, + "personNameEN" TEXT, + "customerType" "CustomerType" NOT NULL, "customerName" TEXT NOT NULL, "customerNameEN" TEXT NOT NULL, - "imageUrl" TEXT, + "taxNo" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Customer_pkey" PRIMARY KEY ("id") @@ -160,12 +267,13 @@ CREATE TABLE "Customer" ( -- CreateTable CREATE TABLE "CustomerBranch" ( "id" TEXT NOT NULL, - "branchNo" TEXT NOT NULL, + "branchNo" INTEGER NOT NULL, + "code" TEXT NOT NULL, "legalPersonNo" TEXT NOT NULL, "name" TEXT NOT NULL, "nameEN" TEXT NOT NULL, "customerId" TEXT NOT NULL, - "taxNo" TEXT NOT NULL, + "taxNo" TEXT, "registerName" TEXT NOT NULL, "registerDate" TIMESTAMP(3) NOT NULL, "authorizedCapital" TEXT NOT NULL, @@ -177,12 +285,20 @@ CREATE TABLE "CustomerBranch" ( "zipCode" TEXT NOT NULL, "email" TEXT NOT NULL, "telephoneNo" TEXT NOT NULL, - "latitude" TEXT NOT NULL, - "longitude" TEXT NOT NULL, + "employmentOffice" TEXT NOT NULL, + "bussinessType" TEXT NOT NULL, + "bussinessTypeEN" TEXT NOT NULL, + "jobPosition" TEXT NOT NULL, + "jobPositionEN" TEXT NOT NULL, + "jobDescription" TEXT NOT NULL, + "saleEmployee" TEXT NOT NULL, + "payDate" TIMESTAMP(3) NOT NULL, + "wageRate" INTEGER NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "CustomerBranch_pkey" PRIMARY KEY ("id") @@ -200,42 +316,70 @@ CREATE TABLE "Employee" ( "dateOfBirth" TIMESTAMP(3) NOT NULL, "gender" TEXT NOT NULL, "nationality" TEXT NOT NULL, - "address" TEXT NOT NULL, - "addressEN" TEXT NOT NULL, + "address" TEXT, + "addressEN" TEXT, "provinceId" TEXT, "districtId" TEXT, "subDistrictId" TEXT, "zipCode" TEXT NOT NULL, - "email" TEXT NOT NULL, - "telephoneNo" TEXT NOT NULL, - "arrivalBarricade" TEXT NOT NULL, - "arrivalCardNo" TEXT NOT NULL, + "passportType" TEXT NOT NULL, + "passportNumber" TEXT NOT NULL, + "passportIssueDate" TIMESTAMP(3) NOT NULL, + "passportExpiryDate" TIMESTAMP(3) NOT NULL, + "passportIssuingCountry" TEXT NOT NULL, + "passportIssuingPlace" TEXT NOT NULL, + "previousPassportReference" TEXT, + "visaType" TEXT, + "visaNumber" TEXT, + "visaIssueDate" TIMESTAMP(3), + "visaExpiryDate" TIMESTAMP(3), + "visaIssuingPlace" TEXT, + "visaStayUntilDate" TIMESTAMP(3), + "tm6Number" TEXT, + "entryDate" TIMESTAMP(3), + "workerStatus" TEXT, "customerBranchId" TEXT, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Employee_pkey" PRIMARY KEY ("id") ); +-- CreateTable +CREATE TABLE "EmployeeHistory" ( + "id" TEXT NOT NULL, + "field" TEXT NOT NULL, + "valueBefore" JSONB NOT NULL, + "valueAfter" JSONB NOT NULL, + "timestamp" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedByUserId" TEXT, + "updatedBy" TEXT, + "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "masterId" TEXT NOT NULL, + + CONSTRAINT "EmployeeHistory_pkey" PRIMARY KEY ("id") +); + -- CreateTable CREATE TABLE "EmployeeCheckup" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "checkupResult" TEXT NOT NULL, - "checkupType" TEXT NOT NULL, + "checkupResult" TEXT, + "checkupType" TEXT, "provinceId" TEXT, - "hospitalName" TEXT NOT NULL, - "remark" TEXT NOT NULL, - "medicalBenefitScheme" TEXT NOT NULL, - "insuranceCompany" TEXT NOT NULL, - "coverageStartDate" TIMESTAMP(3) NOT NULL, - "coverageExpireDate" TIMESTAMP(3) NOT NULL, + "hospitalName" TEXT, + "remark" TEXT, + "medicalBenefitScheme" TEXT, + "insuranceCompany" TEXT, + "coverageStartDate" TIMESTAMP(3), + "coverageExpireDate" TIMESTAMP(3), "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeCheckup_pkey" PRIMARY KEY ("id") @@ -245,17 +389,18 @@ CREATE TABLE "EmployeeCheckup" ( CREATE TABLE "EmployeeWork" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "ownerName" TEXT NOT NULL, - "positionName" TEXT NOT NULL, - "jobType" TEXT NOT NULL, - "workplace" TEXT NOT NULL, - "workPermitNo" TEXT NOT NULL, - "workPermitIssuDate" TIMESTAMP(3) NOT NULL, - "workPermitExpireDate" TIMESTAMP(3) NOT NULL, - "workEndDate" TIMESTAMP(3) NOT NULL, + "ownerName" TEXT, + "positionName" TEXT, + "jobType" TEXT, + "workplace" TEXT, + "workPermitNo" TEXT, + "workPermitIssuDate" TIMESTAMP(3), + "workPermitExpireDate" TIMESTAMP(3), + "workEndDate" TIMESTAMP(3), + "remark" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeWork_pkey" PRIMARY KEY ("id") @@ -265,13 +410,20 @@ CREATE TABLE "EmployeeWork" ( CREATE TABLE "EmployeeOtherInfo" ( "id" TEXT NOT NULL, "employeeId" TEXT NOT NULL, - "citizenId" TEXT NOT NULL, - "fatherFullName" TEXT NOT NULL, - "motherFullName" TEXT NOT NULL, - "birthPlace" TEXT NOT NULL, + "citizenId" TEXT, + "fatherBirthPlace" TEXT, + "fatherFirstName" TEXT, + "fatherLastName" TEXT, + "motherBirthPlace" TEXT, + "motherFirstName" TEXT, + "motherLastName" TEXT, + "fatherFirstNameEN" TEXT, + "fatherLastNameEN" TEXT, + "motherFirstNameEN" TEXT, + "motherLastNameEN" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "EmployeeOtherInfo_pkey" PRIMARY KEY ("id") @@ -283,10 +435,12 @@ CREATE TABLE "Service" ( "code" TEXT NOT NULL, "name" TEXT NOT NULL, "detail" TEXT NOT NULL, + "attributes" JSONB, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Service_pkey" PRIMARY KEY ("id") @@ -297,11 +451,13 @@ CREATE TABLE "Work" ( "id" TEXT NOT NULL, "order" INTEGER NOT NULL, "name" TEXT NOT NULL, - "serviceId" TEXT NOT NULL, + "attributes" JSONB, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, + "serviceId" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Work_pkey" PRIMARY KEY ("id") @@ -309,14 +465,15 @@ CREATE TABLE "Work" ( -- CreateTable CREATE TABLE "WorkProduct" ( - "id" TEXT NOT NULL, + "order" INTEGER NOT NULL, "workId" TEXT NOT NULL, + "productId" TEXT NOT NULL, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, - CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("id") + CONSTRAINT "WorkProduct_pkey" PRIMARY KEY ("workId","productId") ); -- CreateTable @@ -327,9 +484,10 @@ CREATE TABLE "ProductGroup" ( "detail" TEXT NOT NULL, "remark" TEXT NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "ProductGroup_pkey" PRIMARY KEY ("id") @@ -343,10 +501,12 @@ CREATE TABLE "ProductType" ( "detail" TEXT NOT NULL, "remark" TEXT NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, + "productGroupId" TEXT NOT NULL, CONSTRAINT "ProductType_pkey" PRIMARY KEY ("id") ); @@ -357,22 +517,49 @@ CREATE TABLE "Product" ( "code" TEXT NOT NULL, "name" TEXT NOT NULL, "detail" TEXT NOT NULL, - "process" TEXT NOT NULL, - "price" INTEGER NOT NULL, - "agentPrice" INTEGER NOT NULL, - "serviceCharge" INTEGER NOT NULL, - "imageUrl" TEXT NOT NULL, + "process" INTEGER NOT NULL, + "price" DOUBLE PRECISION NOT NULL, + "agentPrice" DOUBLE PRECISION NOT NULL, + "serviceCharge" DOUBLE PRECISION NOT NULL, "status" "Status" NOT NULL DEFAULT 'CREATED', + "statusOrder" INTEGER NOT NULL DEFAULT 0, + "remark" TEXT, "productTypeId" TEXT, - "productGroupId" TEXT, "createdBy" TEXT, "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, - "updateBy" TEXT, + "updatedBy" TEXT, "updatedAt" TIMESTAMP(3) NOT NULL, CONSTRAINT "Product_pkey" PRIMARY KEY ("id") ); +-- CreateIndex +CREATE UNIQUE INDEX "RunningNo_key_key" ON "RunningNo"("key"); + +-- AddForeignKey +ALTER TABLE "Menu" ADD CONSTRAINT "Menu_parentId_fkey" FOREIGN KEY ("parentId") REFERENCES "Menu"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RoleMenuPermission" ADD CONSTRAINT "RoleMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuPermission" ADD CONSTRAINT "UserMenuPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "MenuComponent" ADD CONSTRAINT "MenuComponent_menuId_fkey" FOREIGN KEY ("menuId") REFERENCES "Menu"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "RoleMenuComponentPermission" ADD CONSTRAINT "RoleMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "UserMenuComponentPermission" ADD CONSTRAINT "UserMenuComponentPermission_menuComponentId_fkey" FOREIGN KEY ("menuComponentId") REFERENCES "MenuComponent"("id") ON DELETE RESTRICT ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "District" ADD CONSTRAINT "District_provinceId_fkey" FOREIGN KEY ("provinceId") REFERENCES "Province"("id") ON DELETE CASCADE ON UPDATE CASCADE; @@ -433,6 +620,12 @@ ALTER TABLE "Employee" ADD CONSTRAINT "Employee_subDistrictId_fkey" FOREIGN KEY -- AddForeignKey ALTER TABLE "Employee" ADD CONSTRAINT "Employee_customerBranchId_fkey" FOREIGN KEY ("customerBranchId") REFERENCES "CustomerBranch"("id") ON DELETE SET NULL ON UPDATE CASCADE; +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_updatedByUserId_fkey" FOREIGN KEY ("updatedByUserId") REFERENCES "User"("id") ON DELETE SET NULL ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "EmployeeHistory" ADD CONSTRAINT "EmployeeHistory_masterId_fkey" FOREIGN KEY ("masterId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; + -- AddForeignKey ALTER TABLE "EmployeeCheckup" ADD CONSTRAINT "EmployeeCheckup_employeeId_fkey" FOREIGN KEY ("employeeId") REFERENCES "Employee"("id") ON DELETE CASCADE ON UPDATE CASCADE; @@ -452,7 +645,10 @@ ALTER TABLE "Work" ADD CONSTRAINT "Work_serviceId_fkey" FOREIGN KEY ("serviceId" ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_workId_fkey" FOREIGN KEY ("workId") REFERENCES "Work"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "Product" ADD CONSTRAINT "Product_productTypeId_fkey" FOREIGN KEY ("productTypeId") REFERENCES "ProductType"("id") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "WorkProduct" ADD CONSTRAINT "WorkProduct_productId_fkey" FOREIGN KEY ("productId") REFERENCES "Product"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "Product" ADD CONSTRAINT "Product_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE SET NULL ON UPDATE CASCADE; +ALTER TABLE "ProductType" ADD CONSTRAINT "ProductType_productGroupId_fkey" FOREIGN KEY ("productGroupId") REFERENCES "ProductGroup"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "Product" ADD CONSTRAINT "Product_productTypeId_fkey" FOREIGN KEY ("productTypeId") REFERENCES "ProductType"("id") ON DELETE SET NULL ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2a3caac..3912749 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -22,7 +22,7 @@ model Menu { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt parent Menu? @relation(name: "MenuRelation", fields: [parentId], references: [id]) @@ -45,7 +45,7 @@ model RoleMenuPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -62,7 +62,7 @@ model UserMenuPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -77,7 +77,7 @@ model MenuComponent { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt roleMenuComponentPermission RoleMenuComponentPermission[] userMennuComponentPermission UserMenuComponentPermission[] @@ -94,7 +94,7 @@ model RoleMenuComponentPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -116,7 +116,7 @@ model UserMenuComponentPermission { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -127,7 +127,7 @@ model Province { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt district District[] @@ -148,7 +148,7 @@ model District { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt subDistrict SubDistrict[] @@ -169,7 +169,7 @@ model SubDistrict { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch Branch[] @@ -222,7 +222,7 @@ model Branch { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch Branch[] @relation(name: "HeadOfficeRelation") @@ -239,7 +239,7 @@ model BranchContact { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -254,7 +254,7 @@ model BranchUser { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -323,7 +323,7 @@ model User { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch BranchUser[] @@ -352,7 +352,7 @@ model Customer { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt branch CustomerBranch[] @@ -407,7 +407,7 @@ model CustomerBranch { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt employee Employee[] @@ -467,7 +467,7 @@ model Employee { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt employeeCheckup EmployeeCheckup[] @@ -515,7 +515,7 @@ model EmployeeCheckup { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -537,7 +537,7 @@ model EmployeeWork { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -562,7 +562,7 @@ model EmployeeOtherInfo { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -581,7 +581,7 @@ model Service { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } @@ -600,7 +600,7 @@ model Work { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt productOnWork WorkProduct[] @@ -615,7 +615,7 @@ model WorkProduct { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt @@id([workId, productId]) @@ -634,7 +634,7 @@ model ProductGroup { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt type ProductType[] @@ -653,7 +653,7 @@ model ProductType { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt productGroup ProductGroup @relation(fields: [productGroupId], references: [id], onDelete: Cascade) @@ -685,6 +685,6 @@ model Product { createdBy String? createdAt DateTime @default(now()) - updateBy String? + updatedBy String? updatedAt DateTime @updatedAt } diff --git a/src/controllers/branch-contact-controller.ts b/src/controllers/branch-contact-controller.ts index 701e4b3..d98c966 100644 --- a/src/controllers/branch-contact-controller.ts +++ b/src/controllers/branch-contact-controller.ts @@ -79,7 +79,7 @@ export class BranchContactController extends Controller { throw new HttpError(HttpStatus.BAD_REQUEST, "Branch cannot be found.", "branchBadReq"); } const record = await prisma.branchContact.create({ - data: { ...body, branchId, createdBy: req.user.name, updateBy: req.user.name }, + data: { ...body, branchId, createdBy: req.user.name, updatedBy: req.user.name }, }); this.setStatus(HttpStatus.CREATED); @@ -107,7 +107,7 @@ export class BranchContactController extends Controller { } const record = await prisma.branchContact.update({ - data: { ...body, updateBy: req.user.name }, + data: { ...body, updatedBy: req.user.name }, where: { id: contactId, branchId }, }); diff --git a/src/controllers/branch-controller.ts b/src/controllers/branch-controller.ts index 8008edb..50bce01 100644 --- a/src/controllers/branch-controller.ts +++ b/src/controllers/branch-controller.ts @@ -287,7 +287,7 @@ export class BranchController extends Controller { subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, headOffice: { connect: headOfficeId ? { id: headOfficeId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -403,7 +403,7 @@ export class BranchController extends Controller { connect: headOfficeId ? { id: headOfficeId } : undefined, disconnect: headOfficeId === null || undefined, }, - updateBy: req.user.name, + updatedBy: req.user.name, }, where: { id: branchId }, }); diff --git a/src/controllers/branch-user-controller.ts b/src/controllers/branch-user-controller.ts index 539dd2e..7dfed95 100644 --- a/src/controllers/branch-user-controller.ts +++ b/src/controllers/branch-user-controller.ts @@ -140,7 +140,7 @@ export class BranchUserController extends Controller { branchId, userId: v.id, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })), }), ]); @@ -250,7 +250,7 @@ export class UserBranchController extends Controller { branchId: v.id, userId, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })), }); diff --git a/src/controllers/customer-branch-controller.ts b/src/controllers/customer-branch-controller.ts index ff7eac6..d07d7b4 100644 --- a/src/controllers/customer-branch-controller.ts +++ b/src/controllers/customer-branch-controller.ts @@ -295,7 +295,7 @@ export class CustomerBranchController extends Controller { district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -381,7 +381,7 @@ export class CustomerBranchController extends Controller { disconnect: subDistrictId === null || undefined, }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); diff --git a/src/controllers/customer-controller.ts b/src/controllers/customer-controller.ts index 6b712cc..23b1e8d 100644 --- a/src/controllers/customer-controller.ts +++ b/src/controllers/customer-controller.ts @@ -306,12 +306,12 @@ export class CustomerController extends Controller { branchNo: i + 1, code: `${last.key.slice(9)}${last.value.toString().padStart(6, "0")}-${(i + 1).toString().padStart(2, "0")}`, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })) || [], }, }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -437,19 +437,19 @@ export class CustomerController extends Controller { branchNo: i + 1, code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, id: undefined, }, update: { ...v, branchNo: i + 1, code: `${customer.code}-${(i + 1).toString().padStart(2, "0")}`, - updateBy: req.user.name, + updatedBy: req.user.name, }, })), }) || undefined, - updateBy: req.user.name, + updatedBy: req.user.name, }, }) .then((v) => { diff --git a/src/controllers/employee-checkup-controller.ts b/src/controllers/employee-checkup-controller.ts index 07bf28c..21fb896 100644 --- a/src/controllers/employee-checkup-controller.ts +++ b/src/controllers/employee-checkup-controller.ts @@ -91,7 +91,7 @@ export class EmployeeCheckupController extends Controller { province: { connect: provinceId ? { id: provinceId } : undefined }, employee: { connect: { id: employeeId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -143,7 +143,7 @@ export class EmployeeCheckupController extends Controller { ...rest, province: { connect: provinceId ? { id: provinceId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index abd7c83..2845ae2 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -419,7 +419,7 @@ export class EmployeeController extends Controller { subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, customerBranch: { connect: { id: customerBranchId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -578,12 +578,12 @@ export class EmployeeController extends Controller { create: { ...v, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, id: undefined, }, update: { ...v, - updateBy: req.user.name, + updatedBy: req.user.name, }, })), } @@ -601,12 +601,12 @@ export class EmployeeController extends Controller { create: { ...v, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, id: undefined, }, update: { ...v, - updateBy: req.user.name, + updatedBy: req.user.name, }, })), } @@ -630,7 +630,7 @@ export class EmployeeController extends Controller { disconnect: subDistrictId === null || undefined, }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }); diff --git a/src/controllers/employee-other-info-controller.ts b/src/controllers/employee-other-info-controller.ts index 4a2afd3..a479de7 100644 --- a/src/controllers/employee-other-info-controller.ts +++ b/src/controllers/employee-other-info-controller.ts @@ -62,7 +62,7 @@ export class EmployeeOtherInfo extends Controller { ...body, employee: { connect: { id: employeeId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -88,7 +88,7 @@ export class EmployeeOtherInfo extends Controller { const record = await prisma.employeeOtherInfo.update({ where: { id: otherInfoId, employeeId }, - data: { ...body, createdBy: req.user.name, updateBy: req.user.name }, + data: { ...body, createdBy: req.user.name, updatedBy: req.user.name }, }); this.setStatus(HttpStatus.CREATED); diff --git a/src/controllers/employee-work-controller.ts b/src/controllers/employee-work-controller.ts index 2336874..85c12f4 100644 --- a/src/controllers/employee-work-controller.ts +++ b/src/controllers/employee-work-controller.ts @@ -69,7 +69,7 @@ export class EmployeeWorkController extends Controller { ...body, employee: { connect: { id: employeeId } }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -91,7 +91,7 @@ export class EmployeeWorkController extends Controller { const record = await prisma.employeeWork.update({ where: { id: workId, employeeId }, - data: { ...body, createdBy: req.user.name, updateBy: req.user.name }, + data: { ...body, createdBy: req.user.name, updatedBy: req.user.name }, }); this.setStatus(HttpStatus.CREATED); diff --git a/src/controllers/product-service-controller.ts b/src/controllers/product-service-controller.ts index 95bb9ff..8671c3d 100644 --- a/src/controllers/product-service-controller.ts +++ b/src/controllers/product-service-controller.ts @@ -29,7 +29,7 @@ export class ProductServiceController extends Controller { "productTypeId", "createdBy", "createdAt", - "updateBy", + "updatedBy", "updatedAt", 'product' as "type" FROM "Product" @@ -49,7 +49,7 @@ export class ProductServiceController extends Controller { null as "productTypeId", "createdBy", "createdAt", - "updateBy", + "updatedBy", "updatedAt", 'service' as "type" FROM "Service" diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index 61937cf..12ef7c5 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -114,7 +114,7 @@ export class ProductGroup extends Controller { statusOrder: +(body.status === "INACTIVE"), code: `G${last.value.toString().padStart(2, "0")}`, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -141,7 +141,7 @@ export class ProductGroup extends Controller { } const record = await prisma.productGroup.update({ - data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, where: { id: groupId }, }); diff --git a/src/controllers/product/product-controller.ts b/src/controllers/product/product-controller.ts index 79bf0da..340ab9f 100644 --- a/src/controllers/product/product-controller.ts +++ b/src/controllers/product/product-controller.ts @@ -174,7 +174,7 @@ export class ProductController extends Controller { statusOrder: +(body.status === "INACTIVE"), code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -230,7 +230,7 @@ export class ProductController extends Controller { } const record = await prisma.product.update({ - data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, where: { id: productId }, }); diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 4945deb..4739130 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -128,7 +128,7 @@ export class ProductType extends Controller { statusOrder: +(body.status === "INACTIVE"), code: `T${productGroup.code}${last.value.toString().padStart(2, "0")}`, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -173,7 +173,7 @@ export class ProductType extends Controller { } const record = await prisma.productType.update({ - data: { ...body, statusOrder: +(body.status === "INACTIVE"), updateBy: req.user.name }, + data: { ...body, statusOrder: +(body.status === "INACTIVE"), updatedBy: req.user.name }, where: { id: typeId }, }); diff --git a/src/controllers/service/service-controller.ts b/src/controllers/service/service-controller.ts index 171869f..a565620 100644 --- a/src/controllers/service/service-controller.ts +++ b/src/controllers/service/service-controller.ts @@ -246,7 +246,7 @@ export class ServiceController extends Controller { code: `${body.code.toLocaleUpperCase()}${last.value.toString().padStart(3, "0")}`, work: { connect: workList.map((v) => ({ id: v.id })) }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); }, @@ -308,7 +308,7 @@ export class ServiceController extends Controller { deleteMany: {}, connect: workList.map((v) => ({ id: v.id })), }, - updateBy: req.user.name, + updatedBy: req.user.name, }, where: { id: serviceId }, }); diff --git a/src/controllers/user-controller.ts b/src/controllers/user-controller.ts index db756fb..9f88d73 100644 --- a/src/controllers/user-controller.ts +++ b/src/controllers/user-controller.ts @@ -298,7 +298,7 @@ export class UserController extends Controller { district: { connect: districtId ? { id: districtId } : undefined }, subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -438,7 +438,7 @@ export class UserController extends Controller { connect: subDistrictId ? { id: subDistrictId } : undefined, disconnect: subDistrictId === null || undefined, }, - updateBy: req.user.name, + updatedBy: req.user.name, }, where: { id: userId }, }); diff --git a/src/controllers/work/work-controller.ts b/src/controllers/work/work-controller.ts index 547f8a8..24577b7 100644 --- a/src/controllers/work/work-controller.ts +++ b/src/controllers/work/work-controller.ts @@ -184,12 +184,12 @@ export class WorkController extends Controller { order: i + 1, productId: v, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, })), }, }, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); @@ -282,12 +282,12 @@ export class WorkController extends Controller { order: i + 1, productId: v, createdBy: req.user.name, - updateBy: req.user.name, + updatedBy: req.user.name, }, })), } : undefined, - updateBy: req.user.name, + updatedBy: req.user.name, }, }); From f753f8dec2bab172d7f044d9e3291dfb3d5e3222 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:22:07 +0700 Subject: [PATCH 151/157] refactor: add field to type --- src/interfaces/user.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/interfaces/user.ts b/src/interfaces/user.ts index 12c5d59..a35cdc4 100644 --- a/src/interfaces/user.ts +++ b/src/interfaces/user.ts @@ -2,6 +2,7 @@ import type { Request } from "express"; export type RequestWithUser = Request & { user: { + sub: string; name: string; given_name: string; familiy_name: string; From fb47a11712619b2499ae380c3794643ca932c532 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:00:07 +0700 Subject: [PATCH 152/157] feat: stats relation --- src/controllers/product/group-controller.ts | 32 ++++++++++++++++++++- src/controllers/product/type-controller.ts | 5 ++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/controllers/product/group-controller.ts b/src/controllers/product/group-controller.ts index 12ef7c5..2d676c4 100644 --- a/src/controllers/product/group-controller.ts +++ b/src/controllers/product/group-controller.ts @@ -66,6 +66,13 @@ export class ProductGroup extends Controller { const [result, total] = await prisma.$transaction([ prisma.productGroup.findMany({ + include: { + _count: { + select: { + type: true, + }, + }, + }, orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, @@ -74,7 +81,30 @@ export class ProductGroup extends Controller { prisma.productGroup.count({ where }), ]); - return { result, page, pageSize, total }; + const statsProduct = await prisma.productType.findMany({ + include: { + _count: { select: { product: true } }, + }, + where: { + productGroupId: { in: result.map((v) => v.id) }, + }, + }); + + return { + result: result.map((v) => ({ + ...v, + _count: { + ...v._count, + product: statsProduct.reduce( + (a, c) => (c.productGroupId === v.id ? a + c._count.product : a), + 0, + ), + }, + })), + page, + pageSize, + total, + }; } @Get("{groupId}") diff --git a/src/controllers/product/type-controller.ts b/src/controllers/product/type-controller.ts index 4739130..786c1da 100644 --- a/src/controllers/product/type-controller.ts +++ b/src/controllers/product/type-controller.ts @@ -68,6 +68,11 @@ export class ProductType extends Controller { } satisfies Prisma.ProductTypeWhereInput; const [result, total] = await prisma.$transaction([ prisma.productType.findMany({ + include: { + _count: { + select: { product: true }, + }, + }, orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }], where, take: pageSize, From 8ba4f23d146d65bde1ffaf8f54ac1720ab8096f2 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:00:13 +0700 Subject: [PATCH 153/157] fix: error relation --- src/controllers/employee-controller.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index 2845ae2..d0169ff 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -514,6 +514,7 @@ export class EmployeeController extends Controller { const listProvinceId = employeeCheckup?.reduce((acc, cur) => { if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId); + if (!cur.provinceId) cur.provinceId = null; return acc; }, []); @@ -658,7 +659,12 @@ export class EmployeeController extends Controller { } await prisma.employeeHistory.createMany({ - data: historyEntries.map((v) => ({ ...v, masterId: employee.id })), + data: historyEntries.map((v) => ({ + ...v, + updatedByUserId: req.user.sub, + updatedBy: req.user.preferred_username, + masterId: employee.id, + })), }); return Object.assign(record, { From f4fcec6b5a2b1bfd94acbbf627c050b1ed672477 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Fri, 28 Jun 2024 18:02:39 +0700 Subject: [PATCH 154/157] fix: fk --- src/controllers/employee-controller.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/controllers/employee-controller.ts b/src/controllers/employee-controller.ts index d0169ff..c366aa2 100644 --- a/src/controllers/employee-controller.ts +++ b/src/controllers/employee-controller.ts @@ -601,6 +601,7 @@ export class EmployeeController extends Controller { where: { id: v.id || "" }, create: { ...v, + provinceId: !v.provinceId ? undefined : v.provinceId, createdBy: req.user.name, updatedBy: req.user.name, id: undefined, From d08e4fe6d303a2eb28925a0bd5bb8f26368270b5 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:49:48 +0700 Subject: [PATCH 155/157] chore: update env example --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 511dbe2..cadcd6d 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,8 @@ KC_URL=http://192.168.1.20:8080 KC_REALM=dev -KC_SERVICE_ACCOUNT_CLIENT_ID=dev-service -KC_SERVICE_ACCOUNT_SECRET= +KC_ADMIN_USERNAME=admin +KC_ADMIN_PASSWORD= APP_HOST=0.0.0.0 APP_PORT=3000 From 5d6b61b46f498f9e421dcbd32ce0115c7e8bf131 Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:50:46 +0700 Subject: [PATCH 156/157] fix: cannot disable user --- src/services/keycloak.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/keycloak.ts b/src/services/keycloak.ts index b83a522..984817f 100644 --- a/src/services/keycloak.ts +++ b/src/services/keycloak.ts @@ -75,7 +75,7 @@ export async function createUser(username: string, password: string, opts?: Reco }, method: "POST", body: JSON.stringify({ - enabled: true, + enabled: opts?.enabled !== undefined ? opts.enabled : true, credentials: [{ type: "password", value: password }], username, ...opts, @@ -110,7 +110,7 @@ export async function editUser(userId: string, opts: Record) { }, method: "PUT", body: JSON.stringify({ - enabled: true, + enabled: opts?.enabled !== undefined ? opts.enabled : true, credentials: (password && [{ type: "password", value: opts?.password }]) || undefined, ...rest, }), From f861edc6bacd6d94434d6a9192e4bbff0a3abffc Mon Sep 17 00:00:00 2001 From: Methapon2001 <61303214+Methapon2001@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:52:07 +0700 Subject: [PATCH 157/157] feat: add minio util function --- src/services/minio.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/services/minio.ts b/src/services/minio.ts index 36d2d11..1204c72 100644 --- a/src/services/minio.ts +++ b/src/services/minio.ts @@ -10,6 +10,43 @@ const minio = new Client({ export default minio; +// minio typescript does not support include version +type BucketItemWithVersion = { + name: string; + lastModified: string; + etag: string; + size: number; + versionId: string; + isLatest: boolean; + isDeleteMarker: boolean; +}; + +export async function listObjectVersion(bucket: string, obj: string) { + return await new Promise((resolve, reject) => { + const data: BucketItemWithVersion[] = []; + // @ts-ignore + let stream = minio.listObjects(bucket, obj, true, { + IncludeVersion: true, // type error (ts not support) - expected 3 args but got 4 + }); + stream.on("data", (obj) => data.push(obj as unknown as BucketItemWithVersion)); + stream.on("error", (err) => reject(err)); + stream.on("end", () => resolve(data)); + }); +} + +export async function deleteObjectAllVersion(bucket: string, obj: string) { + const item = await listObjectVersion(bucket, obj); + + return await new Promise((resolve, reject) => { + minio.removeObjects( + bucket, + // @ts-ignore + item.map(({ name, versionId }) => ({ name, versionId })), // type error (ts not support) - expected "string[]" + (e) => (e && reject(e)) || resolve(true), + ); + }); +} + export async function presignedGetObjectIfExist(bucket: string, obj: string, exp?: number) { if ( await minio.statObject(bucket, obj).catch((e) => {