399 lines
11 KiB
TypeScript
399 lines
11 KiB
TypeScript
|
|
import { Request, Response } from "express";
|
||
|
|
import {
|
||
|
|
CommonCodeService,
|
||
|
|
CreateCategoryData,
|
||
|
|
CreateCodeData,
|
||
|
|
} from "../services/commonCodeService";
|
||
|
|
import { AuthenticatedRequest } from "../types/auth";
|
||
|
|
import { logger } from "../utils/logger";
|
||
|
|
|
||
|
|
export class CommonCodeController {
|
||
|
|
private commonCodeService: CommonCodeService;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.commonCodeService = new CommonCodeService();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 목록 조회
|
||
|
|
* GET /api/common-codes/categories
|
||
|
|
*/
|
||
|
|
async getCategories(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { search, isActive, page = "1", size = "20" } = req.query;
|
||
|
|
|
||
|
|
const categories = await this.commonCodeService.getCategories({
|
||
|
|
search: search as string,
|
||
|
|
isActive:
|
||
|
|
isActive === "true" ? true : isActive === "false" ? false : undefined,
|
||
|
|
page: parseInt(page as string),
|
||
|
|
size: parseInt(size as string),
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: categories.data,
|
||
|
|
total: categories.total,
|
||
|
|
message: "카테고리 목록 조회 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("카테고리 목록 조회 실패:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 목록 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리별 코드 목록 조회
|
||
|
|
* GET /api/common-codes/categories/:categoryCode/codes
|
||
|
|
*/
|
||
|
|
async getCodes(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
const { search, isActive } = req.query;
|
||
|
|
|
||
|
|
const codes = await this.commonCodeService.getCodes(categoryCode, {
|
||
|
|
search: search as string,
|
||
|
|
isActive:
|
||
|
|
isActive === "true" ? true : isActive === "false" ? false : undefined,
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: codes,
|
||
|
|
message: `코드 목록 조회 성공 (${categoryCode})`,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`코드 목록 조회 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 목록 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 생성
|
||
|
|
* POST /api/common-codes/categories
|
||
|
|
*/
|
||
|
|
async createCategory(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const categoryData: CreateCategoryData = req.body;
|
||
|
|
const userId = req.user?.userId || "SYSTEM"; // 인증 미들웨어에서 설정된 사용자 ID
|
||
|
|
|
||
|
|
// 입력값 검증
|
||
|
|
if (!categoryData.categoryCode || !categoryData.categoryName) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 코드와 이름은 필수입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const category = await this.commonCodeService.createCategory(
|
||
|
|
categoryData,
|
||
|
|
userId
|
||
|
|
);
|
||
|
|
|
||
|
|
return res.status(201).json({
|
||
|
|
success: true,
|
||
|
|
data: category,
|
||
|
|
message: "카테고리 생성 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("카테고리 생성 실패:", error);
|
||
|
|
|
||
|
|
// Prisma 에러 처리
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Unique constraint")
|
||
|
|
) {
|
||
|
|
return res.status(409).json({
|
||
|
|
success: false,
|
||
|
|
message: "이미 존재하는 카테고리 코드입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 생성 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 수정
|
||
|
|
* PUT /api/common-codes/categories/:categoryCode
|
||
|
|
*/
|
||
|
|
async updateCategory(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
const categoryData: Partial<CreateCategoryData> = req.body;
|
||
|
|
const userId = req.user?.userId || "SYSTEM";
|
||
|
|
|
||
|
|
const category = await this.commonCodeService.updateCategory(
|
||
|
|
categoryCode,
|
||
|
|
categoryData,
|
||
|
|
userId
|
||
|
|
);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: category,
|
||
|
|
message: "카테고리 수정 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`카테고리 수정 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Record to update not found")
|
||
|
|
) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "존재하지 않는 카테고리입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 수정 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리 삭제
|
||
|
|
* DELETE /api/common-codes/categories/:categoryCode
|
||
|
|
*/
|
||
|
|
async deleteCategory(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
|
||
|
|
await this.commonCodeService.deleteCategory(categoryCode);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "카테고리 삭제 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`카테고리 삭제 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Record to delete does not exist")
|
||
|
|
) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "존재하지 않는 카테고리입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 삭제 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 코드 생성
|
||
|
|
* POST /api/common-codes/categories/:categoryCode/codes
|
||
|
|
*/
|
||
|
|
async createCode(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
const codeData: CreateCodeData = req.body;
|
||
|
|
const userId = req.user?.userId || "SYSTEM";
|
||
|
|
|
||
|
|
// 입력값 검증
|
||
|
|
if (!codeData.codeValue || !codeData.codeName) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드값과 코드명은 필수입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const code = await this.commonCodeService.createCode(
|
||
|
|
categoryCode,
|
||
|
|
codeData,
|
||
|
|
userId
|
||
|
|
);
|
||
|
|
|
||
|
|
return res.status(201).json({
|
||
|
|
success: true,
|
||
|
|
data: code,
|
||
|
|
message: "코드 생성 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`코드 생성 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Unique constraint")
|
||
|
|
) {
|
||
|
|
return res.status(409).json({
|
||
|
|
success: false,
|
||
|
|
message: "이미 존재하는 코드값입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 생성 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 코드 수정
|
||
|
|
* PUT /api/common-codes/categories/:categoryCode/codes/:codeValue
|
||
|
|
*/
|
||
|
|
async updateCode(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode, codeValue } = req.params;
|
||
|
|
const codeData: Partial<CreateCodeData> = req.body;
|
||
|
|
const userId = req.user?.userId || "SYSTEM";
|
||
|
|
|
||
|
|
const code = await this.commonCodeService.updateCode(
|
||
|
|
categoryCode,
|
||
|
|
codeValue,
|
||
|
|
codeData,
|
||
|
|
userId
|
||
|
|
);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: code,
|
||
|
|
message: "코드 수정 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(
|
||
|
|
`코드 수정 실패 (${req.params.categoryCode}.${req.params.codeValue}):`,
|
||
|
|
error
|
||
|
|
);
|
||
|
|
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Record to update not found")
|
||
|
|
) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "존재하지 않는 코드입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 수정 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 코드 삭제
|
||
|
|
* DELETE /api/common-codes/categories/:categoryCode/codes/:codeValue
|
||
|
|
*/
|
||
|
|
async deleteCode(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode, codeValue } = req.params;
|
||
|
|
|
||
|
|
await this.commonCodeService.deleteCode(categoryCode, codeValue);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "코드 삭제 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(
|
||
|
|
`코드 삭제 실패 (${req.params.categoryCode}.${req.params.codeValue}):`,
|
||
|
|
error
|
||
|
|
);
|
||
|
|
|
||
|
|
if (
|
||
|
|
error instanceof Error &&
|
||
|
|
error.message.includes("Record to delete does not exist")
|
||
|
|
) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "존재하지 않는 코드입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 삭제 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 카테고리별 옵션 조회 (화면관리용)
|
||
|
|
* GET /api/common-codes/categories/:categoryCode/options
|
||
|
|
*/
|
||
|
|
async getCodeOptions(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
|
||
|
|
const options = await this.commonCodeService.getCodeOptions(categoryCode);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: options,
|
||
|
|
message: `코드 옵션 조회 성공 (${categoryCode})`,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`코드 옵션 조회 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 옵션 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 코드 순서 변경
|
||
|
|
* PUT /api/common-codes/categories/:categoryCode/codes/reorder
|
||
|
|
*/
|
||
|
|
async reorderCodes(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { categoryCode } = req.params;
|
||
|
|
const { codes } = req.body as {
|
||
|
|
codes: Array<{ codeValue: string; sortOrder: number }>;
|
||
|
|
};
|
||
|
|
const userId = req.user?.userId || "SYSTEM";
|
||
|
|
|
||
|
|
if (!codes || !Array.isArray(codes)) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 순서 정보가 올바르지 않습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
await this.commonCodeService.reorderCodes(categoryCode, codes, userId);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "코드 순서 변경 성공",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error(`코드 순서 변경 실패 (${req.params.categoryCode}):`, error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "코드 순서 변경 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|