feat: webTypeStandardController & fileController Prisma 전환 완료
컨트롤러 레이어 전환: webTypeStandardController.ts (11개): - ✅ getWebTypes: findMany → query (동적 WHERE, ILIKE) - ✅ getWebType: findUnique → queryOne - ✅ createWebType: findUnique + create → queryOne (중복 체크 + INSERT) - ✅ updateWebType: update → query (동적 UPDATE, 11개 필드) - ✅ deleteWebType: delete → query (RETURNING) - ✅ updateSortOrder: $transaction → transaction (batch update) - ✅ getCategories: groupBy → query (GROUP BY, COUNT) fileController.ts (1개): - ✅ downloadFile: findUnique → queryOne 기술적 구현: - 동적 WHERE 절: ILIKE를 사용한 검색 - 동적 UPDATE: 11개 필드 조건부 업데이트 - 트랜잭션: transaction 함수로 batch update - GROUP BY: 카테고리별 집계 전체 진행률: 42/29 (145%) - 컨트롤러 완료 남은 작업: Routes(4), Service(4), Config(4)
This commit is contained in:
@@ -723,11 +723,10 @@ export const downloadFile = async (
|
||||
try {
|
||||
const { objid } = req.params;
|
||||
|
||||
const fileRecord = await prisma.attach_file_info.findUnique({
|
||||
where: {
|
||||
objid: parseInt(objid),
|
||||
},
|
||||
});
|
||||
const fileRecord = await queryOne<any>(
|
||||
`SELECT * FROM attach_file_info WHERE objid = $1`,
|
||||
[parseInt(objid)]
|
||||
);
|
||||
|
||||
if (!fileRecord || fileRecord.status !== "ACTIVE") {
|
||||
res.status(404).json({
|
||||
|
||||
@@ -1,39 +1,51 @@
|
||||
import { Request, Response } from "express";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { query, queryOne, transaction } from "../database/db";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export class WebTypeStandardController {
|
||||
// 웹타입 목록 조회
|
||||
static async getWebTypes(req: Request, res: Response) {
|
||||
try {
|
||||
const { active, category, search } = req.query;
|
||||
|
||||
const where: any = {};
|
||||
// 동적 WHERE 절 생성
|
||||
const whereConditions: string[] = [];
|
||||
const queryParams: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
if (active) {
|
||||
where.is_active = active as string;
|
||||
whereConditions.push(`is_active = $${paramIndex}`);
|
||||
queryParams.push(active);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (category) {
|
||||
where.category = category as string;
|
||||
whereConditions.push(`category = $${paramIndex}`);
|
||||
queryParams.push(category);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (search) {
|
||||
where.OR = [
|
||||
{ type_name: { contains: search as string, mode: "insensitive" } },
|
||||
{
|
||||
type_name_eng: { contains: search as string, mode: "insensitive" },
|
||||
},
|
||||
{ description: { contains: search as string, mode: "insensitive" } },
|
||||
];
|
||||
if (search && typeof search === "string") {
|
||||
whereConditions.push(`(
|
||||
type_name ILIKE $${paramIndex} OR
|
||||
type_name_eng ILIKE $${paramIndex} OR
|
||||
description ILIKE $${paramIndex}
|
||||
)`);
|
||||
queryParams.push(`%${search}%`);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
const webTypes = await prisma.web_type_standards.findMany({
|
||||
where,
|
||||
orderBy: [{ sort_order: "asc" }, { web_type: "asc" }],
|
||||
});
|
||||
const whereClause =
|
||||
whereConditions.length > 0
|
||||
? `WHERE ${whereConditions.join(" AND ")}`
|
||||
: "";
|
||||
|
||||
const webTypes = await query<any>(
|
||||
`SELECT * FROM web_type_standards
|
||||
${whereClause}
|
||||
ORDER BY sort_order ASC, web_type ASC`,
|
||||
queryParams
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -55,9 +67,10 @@ export class WebTypeStandardController {
|
||||
try {
|
||||
const { webType } = req.params;
|
||||
|
||||
const webTypeData = await prisma.web_type_standards.findUnique({
|
||||
where: { web_type: webType },
|
||||
});
|
||||
const webTypeData = await queryOne<any>(
|
||||
`SELECT * FROM web_type_standards WHERE web_type = $1`,
|
||||
[webType]
|
||||
);
|
||||
|
||||
if (!webTypeData) {
|
||||
return res.status(404).json({
|
||||
@@ -109,9 +122,10 @@ export class WebTypeStandardController {
|
||||
}
|
||||
|
||||
// 중복 체크
|
||||
const existingWebType = await prisma.web_type_standards.findUnique({
|
||||
where: { web_type },
|
||||
});
|
||||
const existingWebType = await queryOne<any>(
|
||||
`SELECT web_type FROM web_type_standards WHERE web_type = $1`,
|
||||
[web_type]
|
||||
);
|
||||
|
||||
if (existingWebType) {
|
||||
return res.status(409).json({
|
||||
@@ -120,8 +134,15 @@ export class WebTypeStandardController {
|
||||
});
|
||||
}
|
||||
|
||||
const newWebType = await prisma.web_type_standards.create({
|
||||
data: {
|
||||
const [newWebType] = await query<any>(
|
||||
`INSERT INTO web_type_standards (
|
||||
web_type, type_name, type_name_eng, description, category,
|
||||
component_name, config_panel, default_config, validation_rules,
|
||||
default_style, input_properties, sort_order, is_active,
|
||||
created_by, created_date, updated_by, updated_date
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, NOW(), $15, NOW())
|
||||
RETURNING *`,
|
||||
[
|
||||
web_type,
|
||||
type_name,
|
||||
type_name_eng,
|
||||
@@ -135,10 +156,10 @@ export class WebTypeStandardController {
|
||||
input_properties,
|
||||
sort_order,
|
||||
is_active,
|
||||
created_by: req.user?.userId || "system",
|
||||
updated_by: req.user?.userId || "system",
|
||||
},
|
||||
});
|
||||
req.user?.userId || "system",
|
||||
req.user?.userId || "system",
|
||||
]
|
||||
);
|
||||
|
||||
return res.status(201).json({
|
||||
success: true,
|
||||
@@ -174,37 +195,106 @@ export class WebTypeStandardController {
|
||||
is_active,
|
||||
} = req.body;
|
||||
|
||||
// 존재 여부 확인
|
||||
const existingWebType = await prisma.web_type_standards.findUnique({
|
||||
where: { web_type: webType },
|
||||
});
|
||||
// 동적 UPDATE 쿼리 생성
|
||||
const updateFields: string[] = [];
|
||||
const updateValues: any[] = [];
|
||||
let paramIndex = 1;
|
||||
|
||||
if (!existingWebType) {
|
||||
if (type_name !== undefined) {
|
||||
updateFields.push(`type_name = $${paramIndex}`);
|
||||
updateValues.push(type_name);
|
||||
paramIndex++;
|
||||
}
|
||||
if (type_name_eng !== undefined) {
|
||||
updateFields.push(`type_name_eng = $${paramIndex}`);
|
||||
updateValues.push(type_name_eng);
|
||||
paramIndex++;
|
||||
}
|
||||
if (description !== undefined) {
|
||||
updateFields.push(`description = $${paramIndex}`);
|
||||
updateValues.push(description);
|
||||
paramIndex++;
|
||||
}
|
||||
if (category !== undefined) {
|
||||
updateFields.push(`category = $${paramIndex}`);
|
||||
updateValues.push(category);
|
||||
paramIndex++;
|
||||
}
|
||||
if (component_name !== undefined) {
|
||||
updateFields.push(`component_name = $${paramIndex}`);
|
||||
updateValues.push(component_name);
|
||||
paramIndex++;
|
||||
}
|
||||
if (config_panel !== undefined) {
|
||||
updateFields.push(`config_panel = $${paramIndex}`);
|
||||
updateValues.push(config_panel);
|
||||
paramIndex++;
|
||||
}
|
||||
if (default_config !== undefined) {
|
||||
updateFields.push(`default_config = $${paramIndex}`);
|
||||
updateValues.push(default_config);
|
||||
paramIndex++;
|
||||
}
|
||||
if (validation_rules !== undefined) {
|
||||
updateFields.push(`validation_rules = $${paramIndex}`);
|
||||
updateValues.push(validation_rules);
|
||||
paramIndex++;
|
||||
}
|
||||
if (default_style !== undefined) {
|
||||
updateFields.push(`default_style = $${paramIndex}`);
|
||||
updateValues.push(default_style);
|
||||
paramIndex++;
|
||||
}
|
||||
if (input_properties !== undefined) {
|
||||
updateFields.push(`input_properties = $${paramIndex}`);
|
||||
updateValues.push(input_properties);
|
||||
paramIndex++;
|
||||
}
|
||||
if (sort_order !== undefined) {
|
||||
updateFields.push(`sort_order = $${paramIndex}`);
|
||||
updateValues.push(sort_order);
|
||||
paramIndex++;
|
||||
}
|
||||
if (is_active !== undefined) {
|
||||
updateFields.push(`is_active = $${paramIndex}`);
|
||||
updateValues.push(is_active);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
// updated_by, updated_date는 항상 추가
|
||||
updateFields.push(`updated_by = $${paramIndex}`);
|
||||
updateValues.push(req.user?.userId || "system");
|
||||
paramIndex++;
|
||||
|
||||
updateFields.push(`updated_date = NOW()`);
|
||||
|
||||
if (updateFields.length === 2) {
|
||||
// updated_by, updated_date만 있는 경우 = 수정할 내용이 없음
|
||||
return res.status(400).json({
|
||||
success: false,
|
||||
message: "수정할 내용이 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
// WHERE 조건용 파라미터 추가
|
||||
updateValues.push(webType);
|
||||
|
||||
const result = await query<any>(
|
||||
`UPDATE web_type_standards
|
||||
SET ${updateFields.join(", ")}
|
||||
WHERE web_type = $${paramIndex}
|
||||
RETURNING *`,
|
||||
updateValues
|
||||
);
|
||||
|
||||
if (result.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "해당 웹타입을 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
const updatedWebType = await prisma.web_type_standards.update({
|
||||
where: { web_type: webType },
|
||||
data: {
|
||||
type_name,
|
||||
type_name_eng,
|
||||
description,
|
||||
category,
|
||||
component_name,
|
||||
config_panel,
|
||||
default_config,
|
||||
validation_rules,
|
||||
default_style,
|
||||
input_properties,
|
||||
sort_order,
|
||||
is_active,
|
||||
updated_by: req.user?.userId || "system",
|
||||
updated_date: new Date(),
|
||||
},
|
||||
});
|
||||
const updatedWebType = result[0];
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -226,22 +316,18 @@ export class WebTypeStandardController {
|
||||
try {
|
||||
const { webType } = req.params;
|
||||
|
||||
// 존재 여부 확인
|
||||
const existingWebType = await prisma.web_type_standards.findUnique({
|
||||
where: { web_type: webType },
|
||||
});
|
||||
const result = await query<any>(
|
||||
`DELETE FROM web_type_standards WHERE web_type = $1 RETURNING *`,
|
||||
[webType]
|
||||
);
|
||||
|
||||
if (!existingWebType) {
|
||||
if (result.length === 0) {
|
||||
return res.status(404).json({
|
||||
success: false,
|
||||
message: "해당 웹타입을 찾을 수 없습니다.",
|
||||
});
|
||||
}
|
||||
|
||||
await prisma.web_type_standards.delete({
|
||||
where: { web_type: webType },
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
message: "웹타입이 성공적으로 삭제되었습니다.",
|
||||
@@ -272,18 +358,16 @@ export class WebTypeStandardController {
|
||||
}
|
||||
|
||||
// 트랜잭션으로 일괄 업데이트
|
||||
await prisma.$transaction(
|
||||
webTypes.map((item) =>
|
||||
prisma.web_type_standards.update({
|
||||
where: { web_type: item.web_type },
|
||||
data: {
|
||||
sort_order: item.sort_order,
|
||||
updated_by: req.user?.userId || "system",
|
||||
updated_date: new Date(),
|
||||
},
|
||||
})
|
||||
)
|
||||
);
|
||||
await transaction(async (client) => {
|
||||
for (const item of webTypes) {
|
||||
await client.query(
|
||||
`UPDATE web_type_standards
|
||||
SET sort_order = $1, updated_by = $2, updated_date = NOW()
|
||||
WHERE web_type = $3`,
|
||||
[item.sort_order, req.user?.userId || "system", item.web_type]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -302,19 +386,17 @@ export class WebTypeStandardController {
|
||||
// 웹타입 카테고리 목록 조회
|
||||
static async getWebTypeCategories(req: Request, res: Response) {
|
||||
try {
|
||||
const categories = await prisma.web_type_standards.groupBy({
|
||||
by: ["category"],
|
||||
where: {
|
||||
is_active: "Y",
|
||||
},
|
||||
_count: {
|
||||
category: true,
|
||||
},
|
||||
});
|
||||
const categories = await query<{ category: string; count: string }>(
|
||||
`SELECT category, COUNT(*) as count
|
||||
FROM web_type_standards
|
||||
WHERE is_active = 'Y'
|
||||
GROUP BY category`,
|
||||
[]
|
||||
);
|
||||
|
||||
const categoryList = categories.map((item) => ({
|
||||
category: item.category,
|
||||
count: item._count.category,
|
||||
count: parseInt(item.count, 10),
|
||||
}));
|
||||
|
||||
return res.json({
|
||||
|
||||
Reference in New Issue
Block a user