diff --git a/src/controllers/05-payment-controller.ts b/src/controllers/05-payment-controller.ts index 1365e27..622ce10 100644 --- a/src/controllers/05-payment-controller.ts +++ b/src/controllers/05-payment-controller.ts @@ -181,7 +181,7 @@ export class QuotationPayment extends Controller { @Route("api/v1/payment/{paymentId}/attachment") @Tags("Payment") -export class PaymentController extends Controller { +export class PaymentFileController extends Controller { private async checkPermission(user: RequestWithUser["user"], id: string) { const data = await prisma.payment.findUnique({ include: { diff --git a/src/controllers/05-quotation-controller.ts b/src/controllers/05-quotation-controller.ts index c2547db..052a558 100644 --- a/src/controllers/05-quotation-controller.ts +++ b/src/controllers/05-quotation-controller.ts @@ -5,6 +5,7 @@ import { Controller, Delete, Get, + Head, Path, Post, Put, @@ -25,6 +26,7 @@ import { isSystem } from "../utils/keycloak"; import { isUsedError, notFoundError, relationError } from "../utils/error"; import { precisionRound } from "../utils/arithmetic"; import { queryOrNot } from "../utils/relation"; +import { deleteFile, fileLocation, getFile, getPresigned, listFile, setFile } from "../utils/minio"; type QuotationCreate = { registeredBranchId: string; @@ -804,3 +806,70 @@ export class QuotationController extends Controller { }); } } + +@Route("api/v1/quotation/{quotationId}/attachment") +@Tags("Quotation") +export class QuotationFileController extends Controller { + private async checkPermission(user: RequestWithUser["user"], id: string) { + const data = await prisma.quotation.findUnique({ + include: { + registeredBranch: { + include: branchRelationPermInclude(user), + }, + }, + where: { id }, + }); + if (!data) throw notFoundError("Payment"); + await permissionCheck(user, data.registeredBranch); + } + + @Get() + @Security("keycloak") + async listAttachment(@Request() req: RequestWithUser, @Path() quotationId: string) { + await this.checkPermission(req.user, quotationId); + return await listFile(fileLocation.quotation.attachment(quotationId)); + } + + @Head("{name}") + async headAttachment( + @Request() req: RequestWithUser, + @Path() quotationId: string, + @Path() name: string, + ) { + return req.res?.redirect( + await getPresigned("head", fileLocation.quotation.attachment(quotationId, name)), + ); + } + + @Get("{name}") + async getAttachment( + @Request() req: RequestWithUser, + @Path() quotationId: string, + @Path() name: string, + ) { + await this.checkPermission(req.user, quotationId); + return req.res?.redirect(await getFile(fileLocation.quotation.attachment(quotationId, name))); + } + + @Put("{name}") + @Security("keycloak", MANAGE_ROLES) + async putAttachment( + @Request() req: RequestWithUser, + @Path() quotationId: string, + @Path() name: string, + ) { + await this.checkPermission(req.user, quotationId); + return await setFile(fileLocation.quotation.attachment(quotationId, name)); + } + + @Delete("{name}") + @Security("keycloak", MANAGE_ROLES) + async deleteAttachment( + @Request() req: RequestWithUser, + @Path() quotationId: string, + @Path() name: string, + ) { + await this.checkPermission(req.user, quotationId); + return await deleteFile(fileLocation.quotation.attachment(quotationId, name)); + } +} diff --git a/src/utils/minio.ts b/src/utils/minio.ts index 7d80569..d582277 100644 --- a/src/utils/minio.ts +++ b/src/utils/minio.ts @@ -95,6 +95,8 @@ export const fileLocation = { img: (serviceId: string, name?: string) => `service/img-${serviceId}/${name || ""}`, }, quotation: { + attachment: (quotationId: string, name?: string) => + `quotation/attachment-${quotationId}/${name || ""}`, payment: (quotationId: string, paymentId: string, name?: string) => `quotation/payment-${quotationId}/${paymentId}/${name || ""}`, },