창고 렉 구조 등록 컴포넌트 중복 방지기능 추가
This commit is contained in:
@@ -527,6 +527,53 @@ export const deleteColumnMappingsByColumn = async (req: AuthenticatedRequest, re
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 카테고리 코드로 라벨 조회
|
||||
*
|
||||
* POST /api/table-categories/labels-by-codes
|
||||
*
|
||||
* Body:
|
||||
* - valueCodes: 카테고리 코드 배열 (예: ["CATEGORY_767659DCUF", "CATEGORY_8292565608"])
|
||||
*
|
||||
* Response:
|
||||
* - { [code]: label } 형태의 매핑 객체
|
||||
*/
|
||||
export const getCategoryLabelsByCodes = async (req: AuthenticatedRequest, res: Response) => {
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const { valueCodes } = req.body;
|
||||
|
||||
if (!valueCodes || !Array.isArray(valueCodes) || valueCodes.length === 0) {
|
||||
return res.json({
|
||||
success: true,
|
||||
data: {},
|
||||
});
|
||||
}
|
||||
|
||||
logger.info("카테고리 코드로 라벨 조회", {
|
||||
valueCodes,
|
||||
companyCode,
|
||||
});
|
||||
|
||||
const labels = await tableCategoryValueService.getCategoryLabelsByCodes(
|
||||
valueCodes,
|
||||
companyCode
|
||||
);
|
||||
|
||||
return res.json({
|
||||
success: true,
|
||||
data: labels,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error(`카테고리 라벨 조회 실패: ${error.message}`);
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
message: "카테고리 라벨 조회 중 오류가 발생했습니다",
|
||||
error: error.message,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 2레벨 메뉴 목록 조회
|
||||
*
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
deleteColumnMapping,
|
||||
deleteColumnMappingsByColumn,
|
||||
getSecondLevelMenus,
|
||||
getCategoryLabelsByCodes,
|
||||
} from "../controllers/tableCategoryValueController";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
|
||||
@@ -42,6 +43,9 @@ router.post("/values/bulk-delete", bulkDeleteCategoryValues);
|
||||
// 카테고리 값 순서 변경
|
||||
router.post("/values/reorder", reorderCategoryValues);
|
||||
|
||||
// 카테고리 코드로 라벨 조회
|
||||
router.post("/labels-by-codes", getCategoryLabelsByCodes);
|
||||
|
||||
// ================================================
|
||||
// 컬럼 매핑 관련 라우트 (논리명 ↔ 물리명)
|
||||
// ================================================
|
||||
|
||||
@@ -907,8 +907,27 @@ class DataService {
|
||||
return validation.error!;
|
||||
}
|
||||
|
||||
const columns = Object.keys(data);
|
||||
const values = Object.values(data);
|
||||
// 🆕 테이블에 존재하는 컬럼만 필터링 (존재하지 않는 컬럼 제외)
|
||||
const tableColumns = await this.getTableColumnsSimple(tableName);
|
||||
const validColumnNames = new Set(tableColumns.map((col: any) => col.column_name));
|
||||
|
||||
const invalidColumns: string[] = [];
|
||||
const filteredData = Object.fromEntries(
|
||||
Object.entries(data).filter(([key]) => {
|
||||
if (validColumnNames.has(key)) {
|
||||
return true;
|
||||
}
|
||||
invalidColumns.push(key);
|
||||
return false;
|
||||
})
|
||||
);
|
||||
|
||||
if (invalidColumns.length > 0) {
|
||||
console.log(`⚠️ [createRecord] 테이블에 없는 컬럼 제외: ${invalidColumns.join(", ")}`);
|
||||
}
|
||||
|
||||
const columns = Object.keys(filteredData);
|
||||
const values = Object.values(filteredData);
|
||||
const placeholders = values.map((_, index) => `$${index + 1}`).join(", ");
|
||||
const columnNames = columns.map((col) => `"${col}"`).join(", ");
|
||||
|
||||
@@ -951,9 +970,28 @@ class DataService {
|
||||
|
||||
// _relationInfo 추출 (조인 관계 업데이트용)
|
||||
const relationInfo = data._relationInfo;
|
||||
const cleanData = { ...data };
|
||||
let cleanData = { ...data };
|
||||
delete cleanData._relationInfo;
|
||||
|
||||
// 🆕 테이블에 존재하는 컬럼만 필터링 (존재하지 않는 컬럼 제외)
|
||||
const tableColumns = await this.getTableColumnsSimple(tableName);
|
||||
const validColumnNames = new Set(tableColumns.map((col: any) => col.column_name));
|
||||
|
||||
const invalidColumns: string[] = [];
|
||||
cleanData = Object.fromEntries(
|
||||
Object.entries(cleanData).filter(([key]) => {
|
||||
if (validColumnNames.has(key)) {
|
||||
return true;
|
||||
}
|
||||
invalidColumns.push(key);
|
||||
return false;
|
||||
})
|
||||
);
|
||||
|
||||
if (invalidColumns.length > 0) {
|
||||
console.log(`⚠️ [updateRecord] 테이블에 없는 컬럼 제외: ${invalidColumns.join(", ")}`);
|
||||
}
|
||||
|
||||
// Primary Key 컬럼 찾기
|
||||
const pkResult = await query<{ attname: string }>(
|
||||
`SELECT a.attname
|
||||
|
||||
@@ -1258,6 +1258,70 @@ class TableCategoryValueService {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리 코드로 라벨 조회
|
||||
*
|
||||
* @param valueCodes - 카테고리 코드 배열
|
||||
* @param companyCode - 회사 코드
|
||||
* @returns { [code]: label } 형태의 매핑 객체
|
||||
*/
|
||||
async getCategoryLabelsByCodes(
|
||||
valueCodes: string[],
|
||||
companyCode: string
|
||||
): Promise<Record<string, string>> {
|
||||
try {
|
||||
if (!valueCodes || valueCodes.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
logger.info("카테고리 코드로 라벨 조회", { valueCodes, companyCode });
|
||||
|
||||
const pool = getPool();
|
||||
|
||||
// 동적으로 파라미터 플레이스홀더 생성
|
||||
const placeholders = valueCodes.map((_, i) => `$${i + 1}`).join(", ");
|
||||
|
||||
let query: string;
|
||||
let params: any[];
|
||||
|
||||
if (companyCode === "*") {
|
||||
// 최고 관리자: 모든 카테고리 값 조회
|
||||
query = `
|
||||
SELECT value_code, value_label
|
||||
FROM table_column_category_values
|
||||
WHERE value_code IN (${placeholders})
|
||||
AND is_active = true
|
||||
`;
|
||||
params = valueCodes;
|
||||
} else {
|
||||
// 일반 회사: 자신의 카테고리 값 + 공통 카테고리 값 조회
|
||||
query = `
|
||||
SELECT value_code, value_label
|
||||
FROM table_column_category_values
|
||||
WHERE value_code IN (${placeholders})
|
||||
AND is_active = true
|
||||
AND (company_code = $${valueCodes.length + 1} OR company_code = '*')
|
||||
`;
|
||||
params = [...valueCodes, companyCode];
|
||||
}
|
||||
|
||||
const result = await pool.query(query, params);
|
||||
|
||||
// { [code]: label } 형태로 변환
|
||||
const labels: Record<string, string> = {};
|
||||
for (const row of result.rows) {
|
||||
labels[row.value_code] = row.value_label;
|
||||
}
|
||||
|
||||
logger.info(`카테고리 라벨 ${Object.keys(labels).length}개 조회 완료`, { companyCode });
|
||||
|
||||
return labels;
|
||||
} catch (error: any) {
|
||||
logger.error(`카테고리 코드로 라벨 조회 실패: ${error.message}`, { error });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new TableCategoryValueService();
|
||||
|
||||
Reference in New Issue
Block a user