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; + }); } }