feat: Enhance category column handling and data mapping

- Updated the `getCategoryColumnsByCompany` and `getCategoryColumnsByMenu` functions to exclude reference columns from category column queries, improving data integrity.
- Modified the `TableManagementService` to include `category_ref` in the column management logic, ensuring proper handling of category references during data operations.
- Enhanced the frontend components to support category reference mapping, allowing for better data representation and user interaction.
- Implemented category label conversion in various components to improve the display of category data, ensuring a seamless user experience.
This commit is contained in:
kjs
2026-02-26 11:31:49 +09:00
parent 863ec614f4
commit eb27f01616
16 changed files with 1269 additions and 485 deletions

View File

@@ -1769,6 +1769,7 @@ export async function getCategoryColumnsByCompany(
let columnsResult;
// 최고 관리자인 경우 company_code = '*'인 카테고리 컬럼 조회
// category_ref가 설정된 컬럼은 제외 (참조 컬럼은 자체 값 관리 안 함)
if (companyCode === "*") {
const columnsQuery = `
SELECT DISTINCT
@@ -1788,15 +1789,15 @@ export async function getCategoryColumnsByCompany(
ON ttc.table_name = tl.table_name
WHERE ttc.input_type = 'category'
AND ttc.company_code = '*'
AND (ttc.category_ref IS NULL OR ttc.category_ref = '')
ORDER BY ttc.table_name, ttc.column_name
`;
columnsResult = await pool.query(columnsQuery);
logger.info("최고 관리자: 전체 카테고리 컬럼 조회 완료", {
logger.info("최고 관리자: 전체 카테고리 컬럼 조회 완료 (참조 제외)", {
rowCount: columnsResult.rows.length
});
} else {
// 일반 회사: 해당 회사의 카테고리 컬럼만 조회
const columnsQuery = `
SELECT DISTINCT
ttc.table_name AS "tableName",
@@ -1815,11 +1816,12 @@ export async function getCategoryColumnsByCompany(
ON ttc.table_name = tl.table_name
WHERE ttc.input_type = 'category'
AND ttc.company_code = $1
AND (ttc.category_ref IS NULL OR ttc.category_ref = '')
ORDER BY ttc.table_name, ttc.column_name
`;
columnsResult = await pool.query(columnsQuery, [companyCode]);
logger.info("회사별 카테고리 컬럼 조회 완료", {
logger.info("회사별 카테고리 컬럼 조회 완료 (참조 제외)", {
companyCode,
rowCount: columnsResult.rows.length
});
@@ -1880,13 +1882,10 @@ export async function getCategoryColumnsByMenu(
const { getPool } = await import("../database/db");
const pool = getPool();
// 🆕 table_type_columns에서 직접 input_type = 'category' 컬럼들을 조회
// category_column_mapping 대신 table_type_columns 기준으로 조회
logger.info("🔍 table_type_columns 기반 카테고리 컬럼 조회", { menuObjid, companyCode });
// table_type_columns에서 input_type = 'category' 컬럼 조회
// category_ref가 설정된 컬럼은 제외 (참조 컬럼은 자체 값 관리 안 함)
let columnsResult;
// 최고 관리자인 경우 모든 회사의 카테고리 컬럼 조회
if (companyCode === "*") {
const columnsQuery = `
SELECT DISTINCT
@@ -1906,15 +1905,15 @@ export async function getCategoryColumnsByMenu(
ON ttc.table_name = tl.table_name
WHERE ttc.input_type = 'category'
AND ttc.company_code = '*'
AND (ttc.category_ref IS NULL OR ttc.category_ref = '')
ORDER BY ttc.table_name, ttc.column_name
`;
columnsResult = await pool.query(columnsQuery);
logger.info("최고 관리자: 전체 카테고리 컬럼 조회 완료", {
logger.info("최고 관리자: 메뉴별 카테고리 컬럼 조회 완료 (참조 제외)", {
rowCount: columnsResult.rows.length
});
} else {
// 일반 회사: 해당 회사의 카테고리 컬럼만 조회
const columnsQuery = `
SELECT DISTINCT
ttc.table_name AS "tableName",
@@ -1933,11 +1932,12 @@ export async function getCategoryColumnsByMenu(
ON ttc.table_name = tl.table_name
WHERE ttc.input_type = 'category'
AND ttc.company_code = $1
AND (ttc.category_ref IS NULL OR ttc.category_ref = '')
ORDER BY ttc.table_name, ttc.column_name
`;
columnsResult = await pool.query(columnsQuery, [companyCode]);
logger.info("회사별 카테고리 컬럼 조회 완료", {
logger.info("회사별 메뉴 카테고리 컬럼 조회 완료 (참조 제외)", {
companyCode,
rowCount: columnsResult.rows.length
});

View File

@@ -518,8 +518,8 @@ export class TableManagementService {
table_name, column_name, column_label, input_type, detail_settings,
code_category, code_value, reference_table, reference_column,
display_column, display_order, is_visible, is_nullable,
company_code, created_date, updated_date
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, 'Y', $13, NOW(), NOW())
company_code, category_ref, created_date, updated_date
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, 'Y', $13, $14, NOW(), NOW())
ON CONFLICT (table_name, column_name, company_code)
DO UPDATE SET
column_label = COALESCE(EXCLUDED.column_label, table_type_columns.column_label),
@@ -532,6 +532,7 @@ export class TableManagementService {
display_column = COALESCE(EXCLUDED.display_column, table_type_columns.display_column),
display_order = COALESCE(EXCLUDED.display_order, table_type_columns.display_order),
is_visible = COALESCE(EXCLUDED.is_visible, table_type_columns.is_visible),
category_ref = EXCLUDED.category_ref,
updated_date = NOW()`,
[
tableName,
@@ -547,6 +548,7 @@ export class TableManagementService {
settings.displayOrder || 0,
settings.isVisible !== undefined ? settings.isVisible : true,
companyCode,
settings.categoryRef || null,
]
);
@@ -4553,7 +4555,8 @@ export class TableManagementService {
END as "detailSettings",
ttc.is_nullable as "isNullable",
ic.data_type as "dataType",
ttc.company_code as "companyCode"
ttc.company_code as "companyCode",
ttc.category_ref as "categoryRef"
FROM table_type_columns ttc
LEFT JOIN information_schema.columns ic
ON ttc.table_name = ic.table_name AND ttc.column_name = ic.column_name
@@ -4630,20 +4633,24 @@ export class TableManagementService {
}
const inputTypes: ColumnTypeInfo[] = rawInputTypes.map((col) => {
const baseInfo = {
const baseInfo: any = {
tableName: tableName,
columnName: col.columnName,
displayName: col.displayName,
dataType: col.dataType || "varchar",
inputType: col.inputType,
detailSettings: col.detailSettings,
description: "", // 필수 필드 추가
isNullable: col.isNullable === "Y" ? "Y" : "N", // 🔥 FIX: string 타입으로 변환
description: "",
isNullable: col.isNullable === "Y" ? "Y" : "N",
isPrimaryKey: false,
displayOrder: 0,
isVisible: true,
};
if (col.categoryRef) {
baseInfo.categoryRef = col.categoryRef;
}
// 카테고리 타입인 경우 categoryMenus 추가
if (
col.inputType === "category" &&