import { Controller, Get, Query, Route, Security } from "tsoa"; import prisma from "../db"; import { Prisma, Product, Service } from "@prisma/client"; @Route("/api/v1/product-service") export class ProductServiceController extends Controller { @Get() @Security("keycloak") async getProductService( @Query() status?: "ACTIVE" | "INACTIVE", @Query() query = "", @Query() productTypeId?: string, @Query() page: number = 1, @Query() pageSize: number = 30, @Query() registeredBranchId?: string, ) { const union = Prisma.sql` SELECT "id", "code", "name", "detail", "price", "agentPrice", "serviceCharge", "process", "remark", "status", "statusOrder", "productTypeId", "registeredBranchId", "createdByUserId", "createdAt", "updatedByUserId", "updatedAt", 'product' as "type" FROM "Product" UNION ALL SELECT "id", "code", "name", "detail", null as "price", null as "agentPrice", null as "serviceCharge", null as "process", null as "remark", "status", "statusOrder", "productTypeId", "registeredBranchId", "createdByUserId", "createdAt", "updatedByUserId", "updatedAt", 'service' as "type" FROM "Service" `; const or: Prisma.Sql[] = []; const and: Prisma.Sql[] = []; if (query) or.push(Prisma.sql`"name" LIKE ${`%${query}%`}`); if (status) and.push(Prisma.sql`"status" = ${status}::"Status"`); if (productTypeId) { and.push(Prisma.sql`"productTypeId" = ${productTypeId}`); } if (registeredBranchId) { and.push( Prisma.sql`("registeredBranchId" = ${registeredBranchId} OR "registeredBranchId" IS NULL)`, ); } const where = Prisma.sql` ${or.length > 0 || and.length > 0 ? Prisma.sql`WHERE ` : Prisma.empty} ${or.length > 0 ? Prisma.join(or, " OR ", "(", ")") : Prisma.empty} ${or.length > 0 && and.length > 0 ? Prisma.sql` AND ` : Prisma.empty} ${and.length > 0 ? Prisma.join(and, " AND ", "(", ")") : Prisma.empty} `; console.log(where.sql); const [result, [{ total }]] = await prisma.$transaction([ prisma.$queryRaw<((Product & { type: "product" }) | (Service & { type: "service" }))[]>` SELECT * FROM (${union}) AS "ProductService" ${where} ORDER BY "ProductService"."statusOrder" ASC, "ProductService"."createdAt" ASC LIMIT ${pageSize} OFFSET ${(page - 1) * pageSize} `, prisma.$queryRaw<[{ total: number }]>` SELECT COUNT(*) AS "total" FROM (${union}) as "ProductService" ${where} `, ]); const work = await prisma.work.findMany({ where: { serviceId: { in: result.flatMap((v) => (v.type === "service" ? v.id : [])) } }, }); return { result: result.map((v) => v.type === "service" ? { ...v, work: work.filter((w) => w.serviceId === v.id) || [] } : v, ), page, pageSize, total: +String(total), }; } }