fix bug in user, employee, institution,requestList

This commit is contained in:
Kanjana 2025-04-04 14:35:28 +07:00 committed by Methapon Metanipat
parent 116fa02bd9
commit 709c21082a
9 changed files with 230 additions and 17 deletions

View file

@ -0,0 +1,29 @@
-- AlterTable
ALTER TABLE "Employee" ALTER COLUMN "firstName" DROP NOT NULL,
ALTER COLUMN "lastName" DROP NOT NULL;
-- AlterTable
ALTER TABLE "Institution" ADD COLUMN "contactEmail" TEXT,
ADD COLUMN "contactName" TEXT,
ADD COLUMN "contactTel" TEXT;
-- AlterTable
ALTER TABLE "User" ADD COLUMN "agencyStatus" TEXT,
ADD COLUMN "remark" TEXT;
-- CreateTable
CREATE TABLE "InstitutionBank" (
"id" TEXT NOT NULL,
"bankName" TEXT NOT NULL,
"bankBranch" TEXT NOT NULL,
"accountName" TEXT NOT NULL,
"accountNumber" TEXT NOT NULL,
"accountType" TEXT NOT NULL,
"currentlyUse" BOOLEAN NOT NULL,
"institutionId" TEXT NOT NULL,
CONSTRAINT "InstitutionBank_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "InstitutionBank" ADD CONSTRAINT "InstitutionBank_institutionId_fkey" FOREIGN KEY ("institutionId") REFERENCES "Institution"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

View file

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "Employee" ALTER COLUMN "dateOfBirth" DROP NOT NULL;

View file

@ -0,0 +1,5 @@
-- DropForeignKey
ALTER TABLE "InstitutionBank" DROP CONSTRAINT "InstitutionBank_institutionId_fkey";
-- AddForeignKey
ALTER TABLE "InstitutionBank" ADD CONSTRAINT "InstitutionBank_institutionId_fkey" FOREIGN KEY ("institutionId") REFERENCES "Institution"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View file

@ -494,6 +494,9 @@ model User {
requestWorkStepStatus RequestWorkStepStatus[] requestWorkStepStatus RequestWorkStepStatus[]
userTask UserTask[] userTask UserTask[]
RequestData RequestData[] RequestData RequestData[]
remark String?
agencyStatus String?
} }
model UserResponsibleArea { model UserResponsibleArea {
@ -763,14 +766,14 @@ model Employee {
nrcNo String? nrcNo String?
namePrefix String? namePrefix String?
firstName String firstName String?
firstNameEN String firstNameEN String
middleName String? middleName String?
middleNameEN String? middleNameEN String?
lastName String lastName String?
lastNameEN String lastNameEN String
dateOfBirth DateTime @db.Date dateOfBirth DateTime? @db.Date
gender String gender String
nationality String nationality String
@ -1004,6 +1007,25 @@ model Institution {
selectedImage String? selectedImage String?
taskOrder TaskOrder[] taskOrder TaskOrder[]
contactName String?
contactEmail String?
contactTel String?
bank InstitutionBank[]
}
model InstitutionBank {
id String @id @default(cuid())
bankName String
bankBranch String
accountName String
accountNumber String
accountType String
currentlyUse Boolean
institution Institution @relation(fields: [institutionId], references: [id], onDelete: Cascade)
institutionId String
} }
model Property { model Property {

View file

@ -120,6 +120,9 @@ type UserCreate = {
selectedImage?: string; selectedImage?: string;
branchId: string | string[]; branchId: string | string[];
remark?: string;
agencyStatus?: string;
}; };
type UserUpdate = { type UserUpdate = {
@ -176,6 +179,9 @@ type UserUpdate = {
provinceId?: string | null; provinceId?: string | null;
branchId?: string | string[]; branchId?: string | string[];
remark?: string;
agencyStatus?: string;
}; };
const permissionCondCompany = createPermCondition((_) => true); const permissionCondCompany = createPermCondition((_) => true);

View file

@ -70,16 +70,16 @@ type EmployeeCreate = {
nrcNo?: string | null; nrcNo?: string | null;
dateOfBirth: Date; dateOfBirth?: Date | null;
gender: string; gender: string;
nationality: string; nationality: string;
namePrefix?: string | null; namePrefix?: string | null;
firstName: string; firstName?: string;
firstNameEN: string; firstNameEN: string;
middleName?: string | null; middleName?: string | null;
middleNameEN?: string | null; middleNameEN?: string | null;
lastName: string; lastName?: string;
lastNameEN: string; lastNameEN: string;
addressEN: string; addressEN: string;
@ -112,11 +112,11 @@ type EmployeeUpdate = {
namePrefix?: string | null; namePrefix?: string | null;
firstName?: string; firstName?: string;
firstNameEN?: string; firstNameEN: string;
middleName?: string | null; middleName?: string | null;
middleNameEN?: string | null; middleNameEN?: string | null;
lastName?: string; lastName?: string;
lastNameEN?: string; lastNameEN: string;
addressEN?: string; addressEN?: string;
address?: string; address?: string;
@ -364,9 +364,10 @@ export class EmployeeController extends Controller {
}, },
}), }),
]); ]);
if (body.provinceId !== province?.id) throw relationError("Province"); if (!!body.provinceId && body.provinceId !== province?.id) throw relationError("Province");
if (body.districtId !== district?.id) throw relationError("District"); if (!!body.districtId && body.districtId !== district?.id) throw relationError("District");
if (body.subDistrictId !== subDistrict?.id) throw relationError("SubDistrict"); if (!!body.subDistrictId && body.subDistrictId !== subDistrict?.id)
throw relationError("SubDistrict");
if (!customerBranch) throw relationError("Customer Branch"); if (!customerBranch) throw relationError("Customer Branch");
await permissionCheck(req.user, customerBranch.customer.registeredBranch); await permissionCheck(req.user, customerBranch.customer.registeredBranch);

View file

@ -44,6 +44,55 @@ type InstitutionPayload = {
provinceId: string; provinceId: string;
selectedImage?: string | null; selectedImage?: string | null;
contactName?: string;
contactEmail?: string;
contactTel?: string;
bank?: {
bankName: string;
bankBranch: string;
accountName: string;
accountNumber: string;
accountType: string;
currentlyUse: boolean;
}[];
};
type InstitutionUpdatePayload = {
name: string;
nameEN: string;
code: string;
addressEN: string;
address: string;
soi?: string | null;
soiEN?: string | null;
moo?: string | null;
mooEN?: string | null;
street?: string | null;
streetEN?: string | null;
subDistrictId: string;
districtId: string;
provinceId: string;
selectedImage?: string | null;
contactName?: string;
contactEmail?: string;
contactTel?: string;
bank?: {
id?: string;
bankName: string;
bankBranch: string;
accountName: string;
accountNumber: string;
accountType: string;
currentlyUse: boolean;
}[];
}; };
@Route("api/v1/institution") @Route("api/v1/institution")
@ -94,6 +143,7 @@ export class InstitutionController extends Controller {
province: true, province: true,
district: true, district: true,
subDistrict: true, subDistrict: true,
bank: true,
}, },
orderBy: [{ statusOrder: "asc" }, { code: "asc" }], orderBy: [{ statusOrder: "asc" }, { code: "asc" }],
take: pageSize, take: pageSize,
@ -114,6 +164,7 @@ export class InstitutionController extends Controller {
province: true, province: true,
district: true, district: true,
subDistrict: true, subDistrict: true,
bank: true,
}, },
where: { id: institutionId, group }, where: { id: institutionId, group },
}); });
@ -141,10 +192,18 @@ export class InstitutionController extends Controller {
}); });
return await tx.institution.create({ return await tx.institution.create({
include: {
bank: true,
},
data: { data: {
...body, ...body,
code: `${body.code}${last.value.toString().padStart(5, "0")}`, code: `${body.code}${last.value.toString().padStart(5, "0")}`,
group: body.code, group: body.code,
bank: {
createMany: {
data: body.bank ?? [],
},
},
}, },
}); });
}); });
@ -156,13 +215,46 @@ export class InstitutionController extends Controller {
async updateInstitution( async updateInstitution(
@Path() institutionId: string, @Path() institutionId: string,
@Body() @Body()
body: InstitutionPayload & { body: InstitutionUpdatePayload & {
status?: "ACTIVE" | "INACTIVE"; status?: "ACTIVE" | "INACTIVE";
}, },
) { ) {
const { bank } = body;
return await prisma.$transaction(async (tx) => {
const listDeleted = bank
? await tx.institutionBank.findMany({
where: {
id: { not: { in: bank.flatMap((v) => (!!v.id ? v.id : [])) } },
institutionId,
},
})
: [];
await Promise.all(
listDeleted.map((v) => deleteFile(fileLocation.institution.bank(v.institutionId, v.id))),
);
return await prisma.institution.update({ return await prisma.institution.update({
include: {
bank: true,
},
where: { id: institutionId }, where: { id: institutionId },
data: { ...body, statusOrder: +(body.status === "INACTIVE") }, data: {
...body,
statusOrder: +(body.status === "INACTIVE"),
bank: bank
? {
deleteMany:
listDeleted.length > 0 ? { id: { in: listDeleted.map((v) => v.id) } } : undefined,
upsert: bank.map((v) => ({
where: { id: v.id || "" },
create: { ...v, id: undefined },
update: v,
})),
}
: undefined,
},
});
}); });
} }
@ -185,9 +277,18 @@ export class InstitutionController extends Controller {
throw isUsedError("Institution"); throw isUsedError("Institution");
} }
return await tx.institution.delete({ const data = await tx.institution.delete({
include: {
bank: true,
},
where: { id: institutionId }, where: { id: institutionId },
}); });
await Promise.all([
...data.bank.map((v) => deleteFile(fileLocation.institution.bank(institutionId, v.id))),
]);
return data;
}); });
} }
} }
@ -294,4 +395,49 @@ export class InstitutionFileController extends Controller {
await this.checkPermission(req.user, institutionId); await this.checkPermission(req.user, institutionId);
return await deleteFile(fileLocation.institution.attachment(institutionId, name)); return await deleteFile(fileLocation.institution.attachment(institutionId, name));
} }
@Get("bank-qr/{bankId}")
async getBankImage(
@Request() req: RequestWithUser,
@Path() institutionId: string,
@Path() bankId: string,
) {
return req.res?.redirect(await getFile(fileLocation.institution.bank(institutionId, bankId)));
}
@Head("bank-qr/{bankId}")
async headBankImage(
@Request() req: RequestWithUser,
@Path() institutionId: string,
@Path() bankId: string,
) {
return req.res?.redirect(
await getPresigned("head", fileLocation.institution.bank(institutionId, bankId)),
);
}
@Put("bank-qr/{bankId}")
@Security("keycloak")
async putBankImage(
@Request() req: RequestWithUser,
@Path() institutionId: string,
@Path() bankId: string,
) {
if (!req.headers["content-type"]?.startsWith("image/")) {
throw new HttpError(HttpStatus.BAD_REQUEST, "Not a valid image.", "notValidImage");
}
await this.checkPermission(req.user, institutionId);
return req.res?.redirect(await setFile(fileLocation.institution.bank(institutionId, bankId)));
}
@Delete("bank-qr/{bankId}")
@Security("keycloak")
async delBankImage(
@Request() req: RequestWithUser,
@Path() institutionId: string,
@Path() bankId: string,
) {
await this.checkPermission(req.user, institutionId);
return await deleteFile(fileLocation.institution.bank(institutionId, bankId));
}
} }

View file

@ -85,7 +85,7 @@ export class RequestDataController extends Controller {
OR: queryOrNot<Prisma.RequestDataWhereInput[]>(query, [ OR: queryOrNot<Prisma.RequestDataWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } }, { code: { contains: query, mode: "insensitive" } },
{ quotation: { code: { contains: query, mode: "insensitive" } } }, { quotation: { code: { contains: query, mode: "insensitive" } } },
{ quotation: { workName: { contains: query } } }, { quotation: { workName: { contains: query, mode: "insensitive" } } },
{ {
quotation: { quotation: {
customerBranch: { customerBranch: {

View file

@ -127,6 +127,8 @@ export const fileLocation = {
`${ROOT}/institution/attachment-${institutionId}/${name || ""}`, `${ROOT}/institution/attachment-${institutionId}/${name || ""}`,
img: (institutionId: string, name?: string) => img: (institutionId: string, name?: string) =>
`${ROOT}/institution/img-${institutionId}/${name || ""}`, `${ROOT}/institution/img-${institutionId}/${name || ""}`,
bank: (institutionId: string, bankId: string) =>
`${ROOT}/institution/bank-qr-${institutionId}-${bankId}`,
}, },
task: { task: {
attachment: (taskId: string, name?: string) => attachment: (taskId: string, name?: string) =>