refactor: use kysely query builder instead

This commit is contained in:
Methapon Metanipat 2024-09-03 09:24:10 +07:00
parent 7fa99fab8f
commit dfb2ab3928

View file

@ -14,96 +14,93 @@ export class ProductServiceController extends Controller {
@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 union = prisma.$kysely
.selectFrom((eb) =>
eb
.selectFrom("Product")
.select([
"id",
"code",
"name",
"detail",
"price",
"agentPrice",
"serviceCharge",
"process",
"remark",
"status",
"statusOrder",
"productTypeId",
"registeredBranchId",
"createdByUserId",
"createdAt",
"updatedByUserId",
"updatedAt",
sql<string>`'product'`.as("type"),
])
.union((eb) =>
eb
.selectFrom("Service")
.select([
"id",
"code",
"name",
"detail",
sql<number>`-1`.as("price"),
sql<number>`-1`.as("agentPrice"),
sql<number>`-1`.as("serviceCharge"),
sql<number>`-1`.as("process"),
sql<string>`'-'`.as("remark"),
"status",
"statusOrder",
"productTypeId",
"registeredBranchId",
"createdByUserId",
"createdAt",
"updatedByUserId",
"updatedAt",
sql<string>`'service'`.as("type"),
]),
)
.as("p"),
)
.where((eb) => {
const condStatus = status ? eb("status", "=", status) : undefined;
const condQuery = query ? eb("name", "like", `%${query}%`) : undefined;
const condProductTypeId = productTypeId
? eb("productTypeId", "=", productTypeId)
: undefined;
const condRegisteredBranchId = registeredBranchId
? eb("registeredBranchId", "=", registeredBranchId).or("registeredBranchId", "is", null)
: undefined;
const or: Prisma.Sql[] = [];
const and: Prisma.Sql[] = [];
return eb.and(
[condStatus, condQuery, condProductTypeId, condRegisteredBranchId].filter((v) => !!v),
);
});
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 record = await union
.selectAll()
.orderBy("statusOrder asc")
.orderBy("createdAt asc")
.limit(pageSize)
.offset((page - 1) * pageSize)
.execute();
const count = await union
.select((eb) => eb.fn.count<number>("id").as("total"))
.executeTakeFirst();
const work = await prisma.work.findMany({
where: { serviceId: { in: result.flatMap((v) => (v.type === "service" ? v.id : [])) } },
where: { serviceId: { in: record.flatMap((v) => (v.type === "service" ? v.id : [])) } },
});
return {
result: result.map((v) =>
result: record.map((v) =>
v.type === "service" ? { ...v, work: work.filter((w) => w.serviceId === v.id) || [] } : v,
),
page,
pageSize,
total: +String(total),
total: +String(count?.total || 0),
};
}
}