diff --git a/prisma/migrations/20250704070342_add_relation_seller_in_quotation/migration.sql b/prisma/migrations/20250704070342_add_relation_seller_in_quotation/migration.sql new file mode 100644 index 0000000..ef63931 --- /dev/null +++ b/prisma/migrations/20250704070342_add_relation_seller_in_quotation/migration.sql @@ -0,0 +1,5 @@ +-- AlterTable +ALTER TABLE "Quotation" ADD COLUMN "sellerId" TEXT; + +-- AddForeignKey +ALTER TABLE "Quotation" ADD CONSTRAINT "Quotation_sellerId_fkey" FOREIGN KEY ("sellerId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 7639cf2..72b19a3 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -511,6 +511,7 @@ model User { contactName String? contactTel String? + quotation Quotation[] } model UserResponsibleArea { @@ -1386,6 +1387,9 @@ model Quotation { invoice Invoice[] creditNote CreditNote[] + + seller User? @relation(fields: [sellerId], references: [id], onDelete: Cascade) + sellerId String? } model QuotationPaySplit { diff --git a/src/controllers/01-branch-controller.ts b/src/controllers/01-branch-controller.ts index a10352d..a09e24b 100644 --- a/src/controllers/01-branch-controller.ts +++ b/src/controllers/01-branch-controller.ts @@ -47,16 +47,20 @@ if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); } -const MANAGE_ROLES = ["system", "head_of_admin"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; function globalAllow(user: RequestWithUser["user"]) { - return MANAGE_ROLES.some((v) => user.roles?.includes(v)); -} - -function globalAllowView(user: RequestWithUser["user"]) { - return MANAGE_ROLES.concat("head_of_accountant", "head_of_sale").some((v) => - user.roles?.includes(v), - ); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type BranchCreate = { @@ -147,7 +151,7 @@ type BranchUpdate = { }[]; }; -const permissionCond = createPermCondition(globalAllowView); +const permissionCond = createPermCondition(globalAllow); const permissionCheck = createPermCheck(globalAllow); @Route("api/v1/branch") diff --git a/src/controllers/01-branch-user-controller.ts b/src/controllers/01-branch-user-controller.ts index 05177d2..d74742f 100644 --- a/src/controllers/01-branch-user-controller.ts +++ b/src/controllers/01-branch-user-controller.ts @@ -20,10 +20,19 @@ import { RequestWithUser } from "../interfaces/user"; import { branchRelationPermInclude, createPermCheck } from "../services/permission"; import { queryOrNot, whereDateQuery } from "../utils/relation"; -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "branch_manager"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; function globalAllow(user: RequestWithUser["user"]) { - const listAllowed = ["system", "head_of_admin", "admin"]; + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; return user.roles?.some((v) => listAllowed.includes(v)) || false; } diff --git a/src/controllers/02-user-controller.ts b/src/controllers/02-user-controller.ts index b8b70ac..143eb71 100644 --- a/src/controllers/02-user-controller.ts +++ b/src/controllers/02-user-controller.ts @@ -61,10 +61,17 @@ if (!process.env.MINIO_BUCKET) { throw Error("Require MinIO bucket."); } -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "branch_manager"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "branch_admin", + "branch_manager", +]; function globalAllow(user: RequestWithUser["user"]) { - const listAllowed = ["system", "head_of_admin"]; + const listAllowed = ["system", "head_of_admin", "admin", "executive"]; return user.roles?.some((v) => listAllowed.includes(v)) || false; } diff --git a/src/controllers/03-customer-branch-citizen-controller.ts b/src/controllers/03-customer-branch-citizen-controller.ts index 75110c3..f17b746 100644 --- a/src/controllers/03-customer-branch-citizen-controller.ts +++ b/src/controllers/03-customer-branch-citizen-controller.ts @@ -23,15 +23,16 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", - "sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type CustomerBranchCitizenPayload = { diff --git a/src/controllers/03-customer-branch-controller.ts b/src/controllers/03-customer-branch-controller.ts index 5c94a2f..61852ad 100644 --- a/src/controllers/03-customer-branch-controller.ts +++ b/src/controllers/03-customer-branch-controller.ts @@ -47,15 +47,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); diff --git a/src/controllers/03-customer-controller.ts b/src/controllers/03-customer-controller.ts index 122726f..a52ea71 100644 --- a/src/controllers/03-customer-controller.ts +++ b/src/controllers/03-customer-controller.ts @@ -42,15 +42,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); diff --git a/src/controllers/03-employee-checkup-controller.ts b/src/controllers/03-employee-checkup-controller.ts index a72ad2d..cb3c8ee 100644 --- a/src/controllers/03-employee-checkup-controller.ts +++ b/src/controllers/03-employee-checkup-controller.ts @@ -23,14 +23,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type EmployeeCheckupPayload = { diff --git a/src/controllers/03-employee-controller.ts b/src/controllers/03-employee-controller.ts index 95addd7..bb66f58 100644 --- a/src/controllers/03-employee-controller.ts +++ b/src/controllers/03-employee-controller.ts @@ -51,14 +51,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCond = createPermCondition(globalAllow); @@ -108,7 +112,7 @@ type EmployeeUpdate = { nrcNo?: string | null; - dateOfBirth?: Date; + dateOfBirth?: Date | null; gender?: string; nationality?: string; otherNationality?: string | null; @@ -144,9 +148,18 @@ type EmployeeUpdate = { export class EmployeeController extends Controller { @Get("stats") @Security("keycloak") - async getEmployeeStats(@Query() customerBranchId?: string) { + async getEmployeeStats(@Request() req: RequestWithUser, @Query() customerBranchId?: string) { return await prisma.employee.count({ - where: { customerBranchId }, + where: { + customerBranchId, + customerBranch: { + customer: isSystem(req.user) + ? undefined + : { + registeredBranch: { OR: permissionCond(req.user) }, + }, + }, + }, }); } diff --git a/src/controllers/03-employee-other-info-controller.ts b/src/controllers/03-employee-other-info-controller.ts index d6b73e7..3624f95 100644 --- a/src/controllers/03-employee-other-info-controller.ts +++ b/src/controllers/03-employee-other-info-controller.ts @@ -23,14 +23,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type EmployeeOtherInfoPayload = { diff --git a/src/controllers/03-employee-passport-controller.ts b/src/controllers/03-employee-passport-controller.ts index 6af121c..e0b1769 100644 --- a/src/controllers/03-employee-passport-controller.ts +++ b/src/controllers/03-employee-passport-controller.ts @@ -22,14 +22,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type EmployeePassportPayload = { diff --git a/src/controllers/03-employee-visa-controller.ts b/src/controllers/03-employee-visa-controller.ts index b1fe09d..358a293 100644 --- a/src/controllers/03-employee-visa-controller.ts +++ b/src/controllers/03-employee-visa-controller.ts @@ -22,14 +22,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type EmployeeVisaPayload = { diff --git a/src/controllers/03-employee-work-controller.ts b/src/controllers/03-employee-work-controller.ts index 3704546..8bbfdca 100644 --- a/src/controllers/03-employee-work-controller.ts +++ b/src/controllers/03-employee-work-controller.ts @@ -22,14 +22,18 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", "head_of_sale", + "sale", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } type EmployeeWorkPayload = { diff --git a/src/controllers/04-flow-template-controller.ts b/src/controllers/04-flow-template-controller.ts index 940fd1d..85ab0b3 100644 --- a/src/controllers/04-flow-template-controller.ts +++ b/src/controllers/04-flow-template-controller.ts @@ -44,14 +44,30 @@ type WorkflowPayload = { status?: Status; }; -const permissionCondCompany = createPermCondition((_) => true); -const permissionCheckCompany = createPermCheck((_) => true); +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; + +function globalAllow(user: RequestWithUser["user"]) { + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; +} + +const permissionCondCompany = createPermCondition(globalAllow); +const permissionCheckCompany = createPermCheck(globalAllow); @Route("api/v1/workflow-template") @Tags("Workflow") -@Security("keycloak") export class FlowTemplateController extends Controller { @Get() + @Security("keycloak") async getFlowTemplate( @Request() req: RequestWithUser, @Query() page: number = 1, @@ -118,6 +134,7 @@ export class FlowTemplateController extends Controller { } @Get("{templateId}") + @Security("keycloak") async getFlowTemplateById(@Request() _req: RequestWithUser, @Path() templateId: string) { const record = await prisma.workflowTemplate.findFirst({ include: { @@ -150,6 +167,7 @@ export class FlowTemplateController extends Controller { } @Post() + @Security("keycloak", MANAGE_ROLES) async createFlowTemplate(@Request() req: RequestWithUser, @Body() body: WorkflowPayload) { const where = { OR: [ @@ -230,6 +248,7 @@ export class FlowTemplateController extends Controller { } @Put("{templateId}") + @Security("keycloak", MANAGE_ROLES) async updateFlowTemplate( @Request() req: RequestWithUser, @Path() templateId: string, @@ -315,6 +334,7 @@ export class FlowTemplateController extends Controller { } @Delete("{templateId}") + @Security("keycloak", MANAGE_ROLES) async deleteFlowTemplateById(@Request() req: RequestWithUser, @Path() templateId: string) { const record = await prisma.workflowTemplate.findUnique({ where: { id: templateId }, diff --git a/src/controllers/04-institution-controller.ts b/src/controllers/04-institution-controller.ts index 21611a7..7121f3c 100644 --- a/src/controllers/04-institution-controller.ts +++ b/src/controllers/04-institution-controller.ts @@ -95,6 +95,17 @@ type InstitutionUpdatePayload = { }[]; }; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; + @Route("api/v1/institution") @Tags("Institution") export class InstitutionController extends Controller { @@ -185,7 +196,7 @@ export class InstitutionController extends Controller { } @Post() - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) @OperationId("createInstitution") async createInstitution( @Body() @@ -229,7 +240,7 @@ export class InstitutionController extends Controller { } @Put("{institutionId}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) @OperationId("updateInstitution") async updateInstitution( @Path() institutionId: string, @@ -278,7 +289,7 @@ export class InstitutionController extends Controller { } @Delete("{institutionId}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) @OperationId("deleteInstitution") async deleteInstitution(@Path() institutionId: string) { return await prisma.$transaction(async (tx) => { @@ -350,7 +361,7 @@ export class InstitutionFileController extends Controller { } @Put("image/{name}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async putImage( @Request() req: RequestWithUser, @Path() institutionId: string, @@ -364,7 +375,7 @@ export class InstitutionFileController extends Controller { } @Delete("image/{name}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async delImage( @Request() req: RequestWithUser, @Path() institutionId: string, @@ -394,7 +405,7 @@ export class InstitutionFileController extends Controller { } @Put("attachment/{name}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async putAttachment( @Request() req: RequestWithUser, @Path() institutionId: string, @@ -405,7 +416,7 @@ export class InstitutionFileController extends Controller { } @Delete("attachment/{name}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async delAttachment( @Request() req: RequestWithUser, @Path() institutionId: string, @@ -436,7 +447,7 @@ export class InstitutionFileController extends Controller { } @Put("bank-qr/{bankId}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async putBankImage( @Request() req: RequestWithUser, @Path() institutionId: string, @@ -450,7 +461,7 @@ export class InstitutionFileController extends Controller { } @Delete("bank-qr/{bankId}") - @Security("keycloak") + @Security("keycloak", MANAGE_ROLES) async delBankImage( @Request() req: RequestWithUser, @Path() institutionId: string, diff --git a/src/controllers/04-invoice-controller.ts b/src/controllers/04-invoice-controller.ts index fb3fdf0..5902521 100644 --- a/src/controllers/04-invoice-controller.ts +++ b/src/controllers/04-invoice-controller.ts @@ -29,14 +29,23 @@ type InvoicePayload = { installmentNo: number[]; }; -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "head_of_accountant", "accountant"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } -const permissionCondCompany = createPermCondition((_) => true); +const permissionCondCompany = createPermCondition(globalAllow); const permissionCheck = createPermCheck(globalAllow); @Route("/api/v1/invoice") @@ -184,7 +193,7 @@ export class InvoiceController extends Controller { @Post() @OperationId("createInvoice") - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak", MANAGE_ROLES.concat(["head_of_sale", "sale"])) async createInvoice(@Request() req: RequestWithUser, @Body() body: InvoicePayload) { const [quotation] = await prisma.$transaction([ prisma.quotation.findUnique({ @@ -229,7 +238,7 @@ export class InvoiceController extends Controller { title: "ใบแจ้งหนี้ใหม่ / New Invoice", detail: "รหัส / code : " + record.code, registeredBranchId: record.registeredBranchId, - groupReceiver: { create: { name: "accountant" } }, + groupReceiver: { create: { name: "branch_accountant" } }, }, }); diff --git a/src/controllers/04-product-controller.ts b/src/controllers/04-product-controller.ts index 3f2ff4e..0a3bbdd 100644 --- a/src/controllers/04-product-controller.ts +++ b/src/controllers/04-product-controller.ts @@ -35,14 +35,16 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); diff --git a/src/controllers/04-product-group-controller.ts b/src/controllers/04-product-group-controller.ts index ecd4ac6..2cb47b3 100644 --- a/src/controllers/04-product-group-controller.ts +++ b/src/controllers/04-product-group-controller.ts @@ -35,7 +35,7 @@ type ProductGroupCreate = { remark: string; status?: Status; shared?: boolean; - registeredBranchId: string; + registeredBranchId?: string; }; type ProductGroupUpdate = { @@ -51,14 +51,16 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCond = createPermCondition((_) => true); @@ -157,7 +159,23 @@ export class ProductGroup extends Controller { @Post() @Security("keycloak", MANAGE_ROLES) async createProductGroup(@Request() req: RequestWithUser, @Body() body: ProductGroupCreate) { - let company = await permissionCheck(req.user, body.registeredBranchId).then( + const userAffiliatedBranch = await prisma.branch.findFirst({ + include: branchRelationPermInclude(req.user), + where: body.registeredBranchId + ? { id: body.registeredBranchId } + : { + user: { some: { userId: req.user.sub } }, + }, + }); + if (!userAffiliatedBranch) { + throw new HttpError( + HttpStatus.BAD_REQUEST, + "You must be affilated with at least one branch or specify branch to be registered (System permission required).", + "reqMinAffilatedBranch", + ); + } + + let company = await permissionCheck(req.user, userAffiliatedBranch).then( (v) => (v.headOffice || v).code, ); @@ -181,6 +199,7 @@ export class ProductGroup extends Controller { }, data: { ...body, + registeredBranchId: userAffiliatedBranch.id, statusOrder: +(body.status === "INACTIVE"), code: `G${last.value.toString().padStart(2, "0")}`, createdByUserId: req.user.sub, diff --git a/src/controllers/04-service-controller.ts b/src/controllers/04-service-controller.ts index ed46c18..9b9253e 100644 --- a/src/controllers/04-service-controller.ts +++ b/src/controllers/04-service-controller.ts @@ -42,14 +42,16 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); diff --git a/src/controllers/05-payment-controller.ts b/src/controllers/05-payment-controller.ts index 711e357..196054f 100644 --- a/src/controllers/05-payment-controller.ts +++ b/src/controllers/05-payment-controller.ts @@ -26,11 +26,20 @@ import flowAccount from "../services/flowaccount"; import HttpError from "../interfaces/http-error"; import HttpStatus from "../interfaces/http-status"; -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "head_of_accountant", "accountant"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", +]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); @@ -101,7 +110,7 @@ export class QuotationPayment extends Controller { } @Put("{paymentId}") - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak", MANAGE_ROLES.concat(["head_of_sale", "sale"])) async updatePayment( @Path() paymentId: string, @Body() body: { amount?: number; date?: Date; paymentStatus?: PaymentStatus }, diff --git a/src/controllers/05-quotation-controller.ts b/src/controllers/05-quotation-controller.ts index 7d27e2e..5a375e5 100644 --- a/src/controllers/05-quotation-controller.ts +++ b/src/controllers/05-quotation-controller.ts @@ -84,6 +84,8 @@ type QuotationCreate = { installmentNo?: number; workerIndex?: number[]; }[]; + + sellerId?: string; }; type QuotationUpdate = { @@ -142,6 +144,8 @@ type QuotationUpdate = { installmentNo?: number; workerIndex?: number[]; }[]; + + sellerId?: string; }; const VAT_DEFAULT = config.vat; @@ -150,15 +154,16 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", - "sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCheckCompany = createPermCheck((_) => true); @@ -210,6 +215,7 @@ export class QuotationController extends Controller { @Query() query = "", @Query() startDate?: Date, @Query() endDate?: Date, + @Query() sellerId?: string, ) { const where = { OR: queryOrNot(query, [ @@ -258,6 +264,7 @@ export class QuotationController extends Controller { } : undefined, ...whereDateQuery(startDate, endDate), + sellerId: sellerId, } satisfies Prisma.QuotationWhereInput; const [result, total] = await prisma.$transaction([ @@ -415,7 +422,7 @@ export class QuotationController extends Controller { } @Post() - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak", MANAGE_ROLES.concat(["head_of_sale", "sale"])) async createQuotation(@Request() req: RequestWithUser, @Body() body: QuotationCreate) { const ids = { employee: body.worker.filter((v) => typeof v === "string"), @@ -666,7 +673,7 @@ export class QuotationController extends Controller { } @Put("{quotationId}") - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak", MANAGE_ROLES.concat(["head_of_sale", "sale"])) async editQuotation( @Request() req: RequestWithUser, @Path() quotationId: string, diff --git a/src/controllers/06-request-list-controller.ts b/src/controllers/06-request-list-controller.ts index ca5398f..a20020f 100644 --- a/src/controllers/06-request-list-controller.ts +++ b/src/controllers/06-request-list-controller.ts @@ -977,7 +977,7 @@ export class RequestListController extends Controller { }); if (record.responsibleUserId === null) { - await prisma.requestWorkStepStatus.update({ + await tx.requestWorkStepStatus.update({ where: { step_requestWorkId: { step: step, diff --git a/src/controllers/07-task-controller.ts b/src/controllers/07-task-controller.ts index da3c13d..bac70dd 100644 --- a/src/controllers/07-task-controller.ts +++ b/src/controllers/07-task-controller.ts @@ -44,11 +44,21 @@ import { } from "../utils/minio"; import { queryOrNot, whereDateQuery } from "../utils/relation"; -const MANAGE_ROLES = ["system", "head_of_admin", "admin", "document_checker"]; +const MANAGE_ROLES = [ + "system", + "head_of_admin", + "admin", + "executive", + "accountant", + "branch_admin", + "branch_manager", + "branch_accountant", + "data_entry", +]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } const permissionCondCompany = createPermCondition((_) => true); diff --git a/src/controllers/08-credit-note-controller.ts b/src/controllers/08-credit-note-controller.ts index 4a6f622..f1bef3c 100644 --- a/src/controllers/08-credit-note-controller.ts +++ b/src/controllers/08-credit-note-controller.ts @@ -42,22 +42,20 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", - "sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } -// NOTE: permission condition/check in requestWork -> requestData -> quotation -> registeredBranch const permissionCond = createPermCondition(globalAllow); -const permissionCondCompany = createPermCondition((_) => true); const permissionCheck = createPermCheck(globalAllow); -const permissionCheckCompany = createPermCheck((_) => true); type CreditNoteCreate = { requestWorkId: string[]; @@ -94,7 +92,7 @@ export class CreditNoteController extends Controller { request: { quotationId, quotation: { - registeredBranch: { OR: permissionCondCompany(req.user) }, + registeredBranch: { OR: permissionCond(req.user) }, }, }, }, @@ -200,7 +198,7 @@ export class CreditNoteController extends Controller { request: { quotationId, quotation: { - registeredBranch: { OR: permissionCondCompany(req.user) }, + registeredBranch: { OR: permissionCond(req.user) }, }, }, }, @@ -243,7 +241,7 @@ export class CreditNoteController extends Controller { some: { request: { quotation: { - registeredBranch: { OR: permissionCondCompany(req.user) }, + registeredBranch: { OR: permissionCond(req.user) }, }, }, }, @@ -402,7 +400,7 @@ export class CreditNoteController extends Controller { } @Put("{creditNoteId}") - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak") async updateCreditNote( @Request() req: RequestWithUser, @Path() creditNoteId: string, diff --git a/src/controllers/09-debit-note-controller.ts b/src/controllers/09-debit-note-controller.ts index 9c247be..badb52e 100644 --- a/src/controllers/09-debit-note-controller.ts +++ b/src/controllers/09-debit-note-controller.ts @@ -44,22 +44,20 @@ const MANAGE_ROLES = [ "system", "head_of_admin", "admin", - "head_of_accountant", + "executive", "accountant", - "head_of_sale", - "sale", + "branch_admin", + "branch_manager", + "branch_accountant", ]; function globalAllow(user: RequestWithUser["user"]) { - const allowList = ["system", "head_of_admin", "head_of_accountant", "head_of_sale"]; - return allowList.some((v) => user.roles?.includes(v)); + const listAllowed = ["system", "head_of_admin", "admin", "executive", "accountant"]; + return user.roles?.some((v) => listAllowed.includes(v)) || false; } -// NOTE: permission condition/check in registeredBranch const permissionCond = createPermCondition(globalAllow); -const permissionCondCompany = createPermCondition((_) => true); const permissionCheck = createPermCheck(globalAllow); -const permissionCheckCompany = createPermCheck((_) => true); type DebitNoteCreate = { quotationId: string; @@ -581,7 +579,7 @@ export class DebitNoteController extends Controller { } @Put("{debitNoteId}") - @Security("keycloak", MANAGE_ROLES) + @Security("keycloak") async updateDebitNote( @Request() req: RequestWithUser, @Path() debitNoteId: string, @@ -605,7 +603,7 @@ export class DebitNoteController extends Controller { if (!record) throw notFoundError("Debit Note"); - await permissionCheckCompany(req.user, record.registeredBranch); + await permissionCheck(req.user, record.registeredBranch); const { productServiceList: _productServiceList, ...rest } = body; const ids = {