456 lines
12 KiB
TypeScript
456 lines
12 KiB
TypeScript
|
|
import { Request, Response } from "express";
|
||
|
|
import { ScreenManagementService } from "../services/screenManagementService";
|
||
|
|
import {
|
||
|
|
CreateScreenRequest,
|
||
|
|
UpdateScreenRequest,
|
||
|
|
SaveLayoutRequest,
|
||
|
|
MenuAssignmentRequest,
|
||
|
|
ColumnWebTypeSetting,
|
||
|
|
WebType,
|
||
|
|
} from "../types/screen";
|
||
|
|
import { logger } from "../utils/logger";
|
||
|
|
|
||
|
|
export class ScreenManagementController {
|
||
|
|
private screenService: ScreenManagementService;
|
||
|
|
|
||
|
|
constructor() {
|
||
|
|
this.screenService = new ScreenManagementService();
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// 화면 정의 관리
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면 목록 조회 (회사별)
|
||
|
|
*/
|
||
|
|
async getScreens(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { page = 1, size = 20 } = req.query;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
|
||
|
|
const result = await this.screenService.getScreensByCompany(
|
||
|
|
userCompanyCode,
|
||
|
|
Number(page),
|
||
|
|
Number(size)
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: result.data,
|
||
|
|
pagination: result.pagination,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("화면 목록 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "화면 목록을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면 생성
|
||
|
|
*/
|
||
|
|
async createScreen(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const screenData: CreateScreenRequest = req.body;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
const userId = (req as any).user?.user_id || "system";
|
||
|
|
|
||
|
|
// 사용자 회사 코드 자동 설정
|
||
|
|
if (userCompanyCode !== "*") {
|
||
|
|
screenData.companyCode = userCompanyCode;
|
||
|
|
}
|
||
|
|
screenData.createdBy = userId;
|
||
|
|
|
||
|
|
const screen = await this.screenService.createScreen(
|
||
|
|
screenData,
|
||
|
|
userCompanyCode
|
||
|
|
);
|
||
|
|
|
||
|
|
res.status(201).json({
|
||
|
|
success: true,
|
||
|
|
data: screen,
|
||
|
|
message: "화면이 성공적으로 생성되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("화면 생성 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error ? error.message : "화면 생성에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면 조회
|
||
|
|
*/
|
||
|
|
async getScreen(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const screen = await this.screenService.getScreenById(Number(screenId));
|
||
|
|
|
||
|
|
if (!screen) {
|
||
|
|
res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "화면을 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: screen,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("화면 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "화면을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면 수정
|
||
|
|
*/
|
||
|
|
async updateScreen(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const updateData: UpdateScreenRequest = req.body;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
const userId = (req as any).user?.user_id || "system";
|
||
|
|
|
||
|
|
updateData.updatedBy = userId;
|
||
|
|
|
||
|
|
const screen = await this.screenService.updateScreen(
|
||
|
|
Number(screenId),
|
||
|
|
updateData,
|
||
|
|
userCompanyCode
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: screen,
|
||
|
|
message: "화면이 성공적으로 수정되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("화면 수정 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error ? error.message : "화면 수정에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면 삭제
|
||
|
|
*/
|
||
|
|
async deleteScreen(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
|
||
|
|
await this.screenService.deleteScreen(Number(screenId), userCompanyCode);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
message: "화면이 성공적으로 삭제되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("화면 삭제 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error ? error.message : "화면 삭제에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// 레이아웃 관리
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 레이아웃 조회
|
||
|
|
*/
|
||
|
|
async getLayout(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const layout = await this.screenService.getLayout(Number(screenId));
|
||
|
|
|
||
|
|
if (!layout) {
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: {
|
||
|
|
components: [],
|
||
|
|
gridSettings: {
|
||
|
|
columns: 12,
|
||
|
|
gap: 16,
|
||
|
|
padding: 16,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: layout,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("레이아웃 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "레이아웃을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 레이아웃 저장
|
||
|
|
*/
|
||
|
|
async saveLayout(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const layoutData: SaveLayoutRequest = req.body;
|
||
|
|
|
||
|
|
await this.screenService.saveLayout(Number(screenId), layoutData);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
message: "레이아웃이 성공적으로 저장되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("레이아웃 저장 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error
|
||
|
|
? error.message
|
||
|
|
: "레이아웃 저장에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// 템플릿 관리
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 템플릿 목록 조회
|
||
|
|
*/
|
||
|
|
async getTemplates(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { type, isPublic } = req.query;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
|
||
|
|
const templates = await this.screenService.getTemplatesByCompany(
|
||
|
|
userCompanyCode,
|
||
|
|
type as string,
|
||
|
|
isPublic === "true"
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: templates,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("템플릿 목록 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "템플릿 목록을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 템플릿 생성
|
||
|
|
*/
|
||
|
|
async createTemplate(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const templateData = req.body;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
const userId = (req as any).user?.user_id || "system";
|
||
|
|
|
||
|
|
templateData.company_code = userCompanyCode;
|
||
|
|
templateData.created_by = userId;
|
||
|
|
|
||
|
|
const template = await this.screenService.createTemplate(templateData);
|
||
|
|
|
||
|
|
res.status(201).json({
|
||
|
|
success: true,
|
||
|
|
data: template,
|
||
|
|
message: "템플릿이 성공적으로 생성되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("템플릿 생성 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error
|
||
|
|
? error.message
|
||
|
|
: "템플릿 생성에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// 메뉴 할당 관리
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 화면-메뉴 할당
|
||
|
|
*/
|
||
|
|
async assignScreenToMenu(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { screenId } = req.params;
|
||
|
|
const assignmentData: MenuAssignmentRequest = req.body;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
const userId = (req as any).user?.user_id || "system";
|
||
|
|
|
||
|
|
// 사용자 회사 코드 자동 설정
|
||
|
|
if (userCompanyCode !== "*") {
|
||
|
|
assignmentData.companyCode = userCompanyCode;
|
||
|
|
}
|
||
|
|
assignmentData.createdBy = userId;
|
||
|
|
|
||
|
|
await this.screenService.assignScreenToMenu(
|
||
|
|
Number(screenId),
|
||
|
|
assignmentData
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
message: "화면이 메뉴에 성공적으로 할당되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("메뉴 할당 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error ? error.message : "메뉴 할당에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 메뉴별 화면 목록 조회
|
||
|
|
*/
|
||
|
|
async getScreensByMenu(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { menuObjid } = req.params;
|
||
|
|
const userCompanyCode = (req as any).user?.company_code || "*";
|
||
|
|
|
||
|
|
const screens = await this.screenService.getScreensByMenu(
|
||
|
|
Number(menuObjid),
|
||
|
|
userCompanyCode
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: screens,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("메뉴별 화면 목록 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "메뉴별 화면 목록을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ========================================
|
||
|
|
// 테이블 타입 연계
|
||
|
|
// ========================================
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블 컬럼 정보 조회
|
||
|
|
*/
|
||
|
|
async getTableColumns(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { tableName } = req.params;
|
||
|
|
const columns = await this.screenService.getColumnInfo(tableName);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: columns,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("테이블 컬럼 정보 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "테이블 컬럼 정보를 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 컬럼 웹 타입 설정
|
||
|
|
*/
|
||
|
|
async setColumnWebType(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
const { tableName, columnName } = req.params;
|
||
|
|
const { webType, ...additionalSettings } = req.body;
|
||
|
|
|
||
|
|
await this.screenService.setColumnWebType(
|
||
|
|
tableName,
|
||
|
|
columnName,
|
||
|
|
webType as WebType,
|
||
|
|
additionalSettings
|
||
|
|
);
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
message: "컬럼 웹 타입이 성공적으로 설정되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("컬럼 웹 타입 설정 실패:", error);
|
||
|
|
res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message:
|
||
|
|
error instanceof Error
|
||
|
|
? error.message
|
||
|
|
: "컬럼 웹 타입 설정에 실패했습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 테이블 목록 조회 (화면 생성용)
|
||
|
|
*/
|
||
|
|
async getTables(req: Request, res: Response): Promise<void> {
|
||
|
|
try {
|
||
|
|
// PostgreSQL에서 사용 가능한 테이블 목록 조회
|
||
|
|
const tables = await (this.screenService as any).prisma.$queryRaw`
|
||
|
|
SELECT table_name
|
||
|
|
FROM information_schema.tables
|
||
|
|
WHERE table_schema = 'public'
|
||
|
|
AND table_type = 'BASE TABLE'
|
||
|
|
ORDER BY table_name
|
||
|
|
`;
|
||
|
|
|
||
|
|
res.json({
|
||
|
|
success: true,
|
||
|
|
data: tables,
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
logger.error("테이블 목록 조회 실패:", error);
|
||
|
|
res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "테이블 목록을 조회하는 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "Unknown error",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|