Merge branch 'develop'
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 4s
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 4s
This commit is contained in:
commit
b55998da4a
9 changed files with 231 additions and 18 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;
|
||||
|
|
@ -493,7 +493,10 @@ model User {
|
|||
|
||||
requestWorkStepStatus RequestWorkStepStatus[]
|
||||
userTask UserTask[]
|
||||
RequestData RequestData[]
|
||||
requestData RequestData[]
|
||||
|
||||
remark String?
|
||||
agencyStatus String?
|
||||
}
|
||||
|
||||
model UserResponsibleArea {
|
||||
|
|
@ -763,14 +766,14 @@ model Employee {
|
|||
nrcNo String?
|
||||
|
||||
namePrefix String?
|
||||
firstName String
|
||||
firstName String?
|
||||
firstNameEN String
|
||||
middleName String?
|
||||
middleNameEN String?
|
||||
lastName String
|
||||
lastName String?
|
||||
lastNameEN String
|
||||
|
||||
dateOfBirth DateTime @db.Date
|
||||
dateOfBirth DateTime? @db.Date
|
||||
gender String
|
||||
nationality String
|
||||
|
||||
|
|
@ -1004,6 +1007,25 @@ model Institution {
|
|||
selectedImage String?
|
||||
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -120,6 +120,9 @@ type UserCreate = {
|
|||
selectedImage?: string;
|
||||
|
||||
branchId: string | string[];
|
||||
|
||||
remark?: string;
|
||||
agencyStatus?: string;
|
||||
};
|
||||
|
||||
type UserUpdate = {
|
||||
|
|
@ -176,6 +179,9 @@ type UserUpdate = {
|
|||
provinceId?: string | null;
|
||||
|
||||
branchId?: string | string[];
|
||||
|
||||
remark?: string;
|
||||
agencyStatus?: string;
|
||||
};
|
||||
|
||||
const permissionCondCompany = createPermCondition((_) => true);
|
||||
|
|
|
|||
|
|
@ -70,16 +70,16 @@ type EmployeeCreate = {
|
|||
|
||||
nrcNo?: string | null;
|
||||
|
||||
dateOfBirth: Date;
|
||||
dateOfBirth?: Date | null;
|
||||
gender: string;
|
||||
nationality: string;
|
||||
|
||||
namePrefix?: string | null;
|
||||
firstName: string;
|
||||
firstName?: string;
|
||||
firstNameEN: string;
|
||||
middleName?: string | null;
|
||||
middleNameEN?: string | null;
|
||||
lastName: string;
|
||||
lastName?: string;
|
||||
lastNameEN: string;
|
||||
|
||||
addressEN: string;
|
||||
|
|
@ -112,11 +112,11 @@ type EmployeeUpdate = {
|
|||
|
||||
namePrefix?: string | null;
|
||||
firstName?: string;
|
||||
firstNameEN?: string;
|
||||
firstNameEN: string;
|
||||
middleName?: string | null;
|
||||
middleNameEN?: string | null;
|
||||
lastName?: string;
|
||||
lastNameEN?: string;
|
||||
lastNameEN: string;
|
||||
|
||||
addressEN?: string;
|
||||
address?: string;
|
||||
|
|
@ -364,9 +364,10 @@ export class EmployeeController extends Controller {
|
|||
},
|
||||
}),
|
||||
]);
|
||||
if (body.provinceId !== province?.id) throw relationError("Province");
|
||||
if (body.districtId !== district?.id) throw relationError("District");
|
||||
if (body.subDistrictId !== subDistrict?.id) throw relationError("SubDistrict");
|
||||
if (!!body.provinceId && body.provinceId !== province?.id) throw relationError("Province");
|
||||
if (!!body.districtId && body.districtId !== district?.id) throw relationError("District");
|
||||
if (!!body.subDistrictId && body.subDistrictId !== subDistrict?.id)
|
||||
throw relationError("SubDistrict");
|
||||
if (!customerBranch) throw relationError("Customer Branch");
|
||||
|
||||
await permissionCheck(req.user, customerBranch.customer.registeredBranch);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,55 @@ type InstitutionPayload = {
|
|||
provinceId: string;
|
||||
|
||||
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")
|
||||
|
|
@ -94,6 +143,7 @@ export class InstitutionController extends Controller {
|
|||
province: true,
|
||||
district: true,
|
||||
subDistrict: true,
|
||||
bank: true,
|
||||
},
|
||||
orderBy: [{ statusOrder: "asc" }, { code: "asc" }],
|
||||
take: pageSize,
|
||||
|
|
@ -114,6 +164,7 @@ export class InstitutionController extends Controller {
|
|||
province: true,
|
||||
district: true,
|
||||
subDistrict: true,
|
||||
bank: true,
|
||||
},
|
||||
where: { id: institutionId, group },
|
||||
});
|
||||
|
|
@ -141,10 +192,18 @@ export class InstitutionController extends Controller {
|
|||
});
|
||||
|
||||
return await tx.institution.create({
|
||||
include: {
|
||||
bank: true,
|
||||
},
|
||||
data: {
|
||||
...body,
|
||||
code: `${body.code}${last.value.toString().padStart(5, "0")}`,
|
||||
group: body.code,
|
||||
bank: {
|
||||
createMany: {
|
||||
data: body.bank ?? [],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
@ -156,13 +215,46 @@ export class InstitutionController extends Controller {
|
|||
async updateInstitution(
|
||||
@Path() institutionId: string,
|
||||
@Body()
|
||||
body: InstitutionPayload & {
|
||||
body: InstitutionUpdatePayload & {
|
||||
status?: "ACTIVE" | "INACTIVE";
|
||||
},
|
||||
) {
|
||||
return await prisma.institution.update({
|
||||
where: { id: institutionId },
|
||||
data: { ...body, statusOrder: +(body.status === "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({
|
||||
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");
|
||||
}
|
||||
|
||||
return await tx.institution.delete({
|
||||
const data = await tx.institution.delete({
|
||||
include: {
|
||||
bank: true,
|
||||
},
|
||||
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);
|
||||
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, [
|
||||
{ code: { contains: query, mode: "insensitive" } },
|
||||
{ quotation: { code: { contains: query, mode: "insensitive" } } },
|
||||
{ quotation: { workName: { contains: query } } },
|
||||
{ quotation: { workName: { contains: query, mode: "insensitive" } } },
|
||||
{
|
||||
quotation: {
|
||||
customerBranch: {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,8 @@ export const fileLocation = {
|
|||
`${ROOT}/institution/attachment-${institutionId}/${name || ""}`,
|
||||
img: (institutionId: string, name?: string) =>
|
||||
`${ROOT}/institution/img-${institutionId}/${name || ""}`,
|
||||
bank: (institutionId: string, bankId: string) =>
|
||||
`${ROOT}/institution/bank-qr-${institutionId}-${bankId}`,
|
||||
},
|
||||
task: {
|
||||
attachment: (taskId: string, name?: string) =>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue