fix bug in user, employee, institution,requestList
This commit is contained in:
parent
116fa02bd9
commit
709c21082a
9 changed files with 230 additions and 17 deletions
29
prisma/migrations/20250404040202_add/migration.sql
Normal file
29
prisma/migrations/20250404040202_add/migration.sql
Normal 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;
|
||||||
2
prisma/migrations/20250404040846_add/migration.sql
Normal file
2
prisma/migrations/20250404040846_add/migration.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Employee" ALTER COLUMN "dateOfBirth" DROP NOT NULL;
|
||||||
5
prisma/migrations/20250404071034_add/migration.sql
Normal file
5
prisma/migrations/20250404071034_add/migration.sql
Normal 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;
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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";
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
return await prisma.institution.update({
|
const { bank } = body;
|
||||||
where: { id: institutionId },
|
return await prisma.$transaction(async (tx) => {
|
||||||
data: { ...body, statusOrder: +(body.status === "INACTIVE") },
|
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({
|
||||||
|
include: {
|
||||||
|
bank: true,
|
||||||
|
},
|
||||||
|
where: { id: institutionId },
|
||||||
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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: {
|
||||||
|
|
|
||||||
|
|
@ -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) =>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue