회사별 메뉴 분리 및 권한 관리
This commit is contained in:
@@ -21,14 +21,22 @@ export class CommonCodeController {
|
||||
async getCategories(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { search, isActive, page = "1", size = "20" } = req.query;
|
||||
const userCompanyCode = req.user?.companyCode;
|
||||
|
||||
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),
|
||||
});
|
||||
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),
|
||||
},
|
||||
userCompanyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -54,14 +62,23 @@ export class CommonCodeController {
|
||||
try {
|
||||
const { categoryCode } = req.params;
|
||||
const { search, isActive, page, size } = req.query;
|
||||
const userCompanyCode = req.user?.companyCode;
|
||||
|
||||
const result = await this.commonCodeService.getCodes(categoryCode, {
|
||||
search: search as string,
|
||||
isActive:
|
||||
isActive === "true" ? true : isActive === "false" ? false : undefined,
|
||||
page: page ? parseInt(page as string) : undefined,
|
||||
size: size ? parseInt(size as string) : undefined,
|
||||
});
|
||||
const result = await this.commonCodeService.getCodes(
|
||||
categoryCode,
|
||||
{
|
||||
search: search as string,
|
||||
isActive:
|
||||
isActive === "true"
|
||||
? true
|
||||
: isActive === "false"
|
||||
? false
|
||||
: undefined,
|
||||
page: page ? parseInt(page as string) : undefined,
|
||||
size: size ? parseInt(size as string) : undefined,
|
||||
},
|
||||
userCompanyCode
|
||||
);
|
||||
|
||||
// 프론트엔드가 기대하는 형식으로 데이터 변환
|
||||
const transformedData = result.data.map((code: any) => ({
|
||||
@@ -73,7 +90,8 @@ export class CommonCodeController {
|
||||
sortOrder: code.sort_order,
|
||||
isActive: code.is_active,
|
||||
useYn: code.is_active,
|
||||
|
||||
companyCode: code.company_code, // 추가
|
||||
|
||||
// 기존 필드명도 유지 (하위 호환성)
|
||||
code_category: code.code_category,
|
||||
code_value: code.code_value,
|
||||
@@ -81,6 +99,7 @@ export class CommonCodeController {
|
||||
code_name_eng: code.code_name_eng,
|
||||
sort_order: code.sort_order,
|
||||
is_active: code.is_active,
|
||||
company_code: code.company_code, // 추가
|
||||
created_date: code.created_date,
|
||||
created_by: code.created_by,
|
||||
updated_date: code.updated_date,
|
||||
@@ -110,7 +129,8 @@ export class CommonCodeController {
|
||||
async createCategory(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const categoryData: CreateCategoryData = req.body;
|
||||
const userId = req.user?.userId || "SYSTEM"; // 인증 미들웨어에서 설정된 사용자 ID
|
||||
const userId = req.user?.userId || "SYSTEM";
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
// 입력값 검증
|
||||
if (!categoryData.categoryCode || !categoryData.categoryName) {
|
||||
@@ -122,7 +142,8 @@ export class CommonCodeController {
|
||||
|
||||
const category = await this.commonCodeService.createCategory(
|
||||
categoryData,
|
||||
userId
|
||||
userId,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.status(201).json({
|
||||
@@ -135,7 +156,7 @@ export class CommonCodeController {
|
||||
|
||||
// PostgreSQL 에러 처리
|
||||
if (
|
||||
((error as any)?.code === "23505") || // PostgreSQL unique_violation
|
||||
(error as any)?.code === "23505" || // PostgreSQL unique_violation
|
||||
(error instanceof Error && error.message.includes("Unique constraint"))
|
||||
) {
|
||||
return res.status(409).json({
|
||||
@@ -161,11 +182,13 @@ export class CommonCodeController {
|
||||
const { categoryCode } = req.params;
|
||||
const categoryData: Partial<CreateCategoryData> = req.body;
|
||||
const userId = req.user?.userId || "SYSTEM";
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
const category = await this.commonCodeService.updateCategory(
|
||||
categoryCode,
|
||||
categoryData,
|
||||
userId
|
||||
userId,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
@@ -201,8 +224,9 @@ export class CommonCodeController {
|
||||
async deleteCategory(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { categoryCode } = req.params;
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
await this.commonCodeService.deleteCategory(categoryCode);
|
||||
await this.commonCodeService.deleteCategory(categoryCode, companyCode);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -238,6 +262,7 @@ export class CommonCodeController {
|
||||
const { categoryCode } = req.params;
|
||||
const codeData: CreateCodeData = req.body;
|
||||
const userId = req.user?.userId || "SYSTEM";
|
||||
const companyCode = req.user?.companyCode || "*";
|
||||
|
||||
// 입력값 검증
|
||||
if (!codeData.codeValue || !codeData.codeName) {
|
||||
@@ -250,7 +275,8 @@ export class CommonCodeController {
|
||||
const code = await this.commonCodeService.createCode(
|
||||
categoryCode,
|
||||
codeData,
|
||||
userId
|
||||
userId,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.status(201).json({
|
||||
@@ -288,12 +314,14 @@ export class CommonCodeController {
|
||||
const { categoryCode, codeValue } = req.params;
|
||||
const codeData: Partial<CreateCodeData> = req.body;
|
||||
const userId = req.user?.userId || "SYSTEM";
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
const code = await this.commonCodeService.updateCode(
|
||||
categoryCode,
|
||||
codeValue,
|
||||
codeData,
|
||||
userId
|
||||
userId,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
@@ -332,8 +360,13 @@ export class CommonCodeController {
|
||||
async deleteCode(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { categoryCode, codeValue } = req.params;
|
||||
const companyCode = req.user?.companyCode;
|
||||
|
||||
await this.commonCodeService.deleteCode(categoryCode, codeValue);
|
||||
await this.commonCodeService.deleteCode(
|
||||
categoryCode,
|
||||
codeValue,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
@@ -370,8 +403,12 @@ export class CommonCodeController {
|
||||
async getCodeOptions(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const { categoryCode } = req.params;
|
||||
const userCompanyCode = req.user?.companyCode;
|
||||
|
||||
const options = await this.commonCodeService.getCodeOptions(categoryCode);
|
||||
const options = await this.commonCodeService.getCodeOptions(
|
||||
categoryCode,
|
||||
userCompanyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
|
||||
@@ -383,6 +383,79 @@ export class DDLController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /api/ddl/tables/:tableName - 테이블 삭제 (최고 관리자 전용)
|
||||
*/
|
||||
static async dropTable(
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
): Promise<void> {
|
||||
try {
|
||||
const { tableName } = req.params;
|
||||
const userId = req.user!.userId;
|
||||
const userCompanyCode = req.user!.companyCode;
|
||||
|
||||
// 입력값 기본 검증
|
||||
if (!tableName) {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: "INVALID_INPUT",
|
||||
details: "테이블명이 필요합니다.",
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
logger.info("테이블 삭제 요청", {
|
||||
tableName,
|
||||
userId,
|
||||
userCompanyCode,
|
||||
ip: req.ip,
|
||||
});
|
||||
|
||||
// DDL 실행 서비스 호출
|
||||
const ddlService = new DDLExecutionService();
|
||||
const result = await ddlService.dropTable(
|
||||
tableName,
|
||||
userCompanyCode,
|
||||
userId
|
||||
);
|
||||
|
||||
if (result.success) {
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: result.message,
|
||||
data: {
|
||||
tableName,
|
||||
executedQuery: result.executedQuery,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
res.status(400).json({
|
||||
success: false,
|
||||
message: result.message,
|
||||
error: result.error,
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("테이블 삭제 컨트롤러 오류:", {
|
||||
error: (error as Error).message,
|
||||
stack: (error as Error).stack,
|
||||
userId: req.user?.userId,
|
||||
tableName: req.params.tableName,
|
||||
});
|
||||
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
error: {
|
||||
code: "INTERNAL_SERVER_ERROR",
|
||||
details: "테이블 삭제 중 서버 오류가 발생했습니다.",
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DELETE /api/ddl/logs/cleanup - 오래된 DDL 로그 정리
|
||||
*/
|
||||
|
||||
@@ -551,6 +551,76 @@ export class FlowController {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 플로우 스텝의 컬럼 라벨 조회
|
||||
*/
|
||||
getStepColumnLabels = async (req: Request, res: Response): Promise<void> => {
|
||||
try {
|
||||
const { flowId, stepId } = req.params;
|
||||
|
||||
const step = await this.flowStepService.getById(parseInt(stepId));
|
||||
if (!step) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "Step not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const flowDef = await this.flowDefinitionService.getById(
|
||||
parseInt(flowId)
|
||||
);
|
||||
if (!flowDef) {
|
||||
res.status(404).json({
|
||||
success: false,
|
||||
message: "Flow definition not found",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 테이블명 결정 (스텝 테이블 우선, 없으면 플로우 테이블)
|
||||
const tableName = step.tableName || flowDef.tableName;
|
||||
if (!tableName) {
|
||||
res.json({
|
||||
success: true,
|
||||
data: {},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// column_labels 테이블에서 라벨 정보 조회
|
||||
const { query } = await import("../config/database");
|
||||
const labelRows = await query<{
|
||||
column_name: string;
|
||||
column_label: string | null;
|
||||
}>(
|
||||
`SELECT column_name, column_label
|
||||
FROM column_labels
|
||||
WHERE table_name = $1 AND column_label IS NOT NULL`,
|
||||
[tableName]
|
||||
);
|
||||
|
||||
// { columnName: label } 형태의 객체로 변환
|
||||
const labels: Record<string, string> = {};
|
||||
labelRows.forEach((row) => {
|
||||
if (row.column_label) {
|
||||
labels[row.column_name] = row.column_label;
|
||||
}
|
||||
});
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: labels,
|
||||
});
|
||||
} catch (error: any) {
|
||||
console.error("Error getting step column labels:", error);
|
||||
res.status(500).json({
|
||||
success: false,
|
||||
message: error.message || "Failed to get step column labels",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 플로우의 모든 단계별 카운트 조회
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user