카테고리 복사에러 수정
This commit is contained in:
@@ -938,7 +938,9 @@ export class MenuCopyService {
|
|||||||
copiedCategoryMappings = await this.copyCategoryMappingsAndValues(
|
copiedCategoryMappings = await this.copyCategoryMappingsAndValues(
|
||||||
menuObjids,
|
menuObjids,
|
||||||
menuIdMap,
|
menuIdMap,
|
||||||
|
sourceCompanyCode,
|
||||||
targetCompanyCode,
|
targetCompanyCode,
|
||||||
|
Array.from(screenIds),
|
||||||
userId,
|
userId,
|
||||||
client
|
client
|
||||||
);
|
);
|
||||||
@@ -2569,11 +2571,16 @@ export class MenuCopyService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 카테고리 매핑 + 값 복사 (최적화: 배치 조회)
|
* 카테고리 매핑 + 값 복사 (최적화: 배치 조회)
|
||||||
|
*
|
||||||
|
* 화면에서 사용하는 table_name + column_name 조합을 기준으로 카테고리 값 복사
|
||||||
|
* menu_objid 기준이 아닌 화면 컴포넌트 기준으로 복사하여 누락 방지
|
||||||
*/
|
*/
|
||||||
private async copyCategoryMappingsAndValues(
|
private async copyCategoryMappingsAndValues(
|
||||||
menuObjids: number[],
|
menuObjids: number[],
|
||||||
menuIdMap: Map<number, number>,
|
menuIdMap: Map<number, number>,
|
||||||
|
sourceCompanyCode: string,
|
||||||
targetCompanyCode: string,
|
targetCompanyCode: string,
|
||||||
|
screenIds: number[],
|
||||||
userId: string,
|
userId: string,
|
||||||
client: PoolClient
|
client: PoolClient
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
@@ -2697,12 +2704,70 @@ export class MenuCopyService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. 모든 원본 카테고리 값 한 번에 조회
|
// 4. 화면에서 사용하는 카테고리 컬럼 조합 수집
|
||||||
|
// 복사된 화면의 레이아웃에서 webType='category'인 컴포넌트의 tableName, columnName 추출
|
||||||
|
const categoryColumnsResult = await client.query(
|
||||||
|
`SELECT DISTINCT
|
||||||
|
sl.properties->>'tableName' as table_name,
|
||||||
|
sl.properties->>'columnName' as column_name
|
||||||
|
FROM screen_layouts sl
|
||||||
|
JOIN screen_definitions sd ON sl.screen_id = sd.screen_id
|
||||||
|
WHERE sd.screen_id = ANY($1)
|
||||||
|
AND sl.properties->'componentConfig'->>'webType' = 'category'
|
||||||
|
AND sl.properties->>'tableName' IS NOT NULL
|
||||||
|
AND sl.properties->>'columnName' IS NOT NULL`,
|
||||||
|
[screenIds]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 카테고리 매핑에서 사용하는 table_name, column_name도 추가
|
||||||
|
const mappingColumnsResult = await client.query(
|
||||||
|
`SELECT DISTINCT table_name, logical_column_name as column_name
|
||||||
|
FROM category_column_mapping
|
||||||
|
WHERE menu_objid = ANY($1)`,
|
||||||
|
[menuObjids]
|
||||||
|
);
|
||||||
|
|
||||||
|
// 두 결과 합치기
|
||||||
|
const categoryColumns = new Set<string>();
|
||||||
|
for (const row of categoryColumnsResult.rows) {
|
||||||
|
if (row.table_name && row.column_name) {
|
||||||
|
categoryColumns.add(`${row.table_name}|${row.column_name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const row of mappingColumnsResult.rows) {
|
||||||
|
if (row.table_name && row.column_name) {
|
||||||
|
categoryColumns.add(`${row.table_name}|${row.column_name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
` 📋 화면에서 사용하는 카테고리 컬럼: ${categoryColumns.size}개`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (categoryColumns.size === 0) {
|
||||||
|
logger.info(`✅ 카테고리 매핑 + 값 복사 완료: ${copiedCount}개`);
|
||||||
|
return copiedCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. 원본 회사의 카테고리 값 조회 (table_name + column_name 기준)
|
||||||
|
// menu_objid 조건 대신 table_name + column_name + 원본 회사 코드로 조회
|
||||||
|
const columnConditions = Array.from(categoryColumns).map((col, i) => {
|
||||||
|
const [tableName, columnName] = col.split("|");
|
||||||
|
return `(table_name = $${i * 2 + 2} AND column_name = $${i * 2 + 3})`;
|
||||||
|
});
|
||||||
|
|
||||||
|
const columnParams: string[] = [];
|
||||||
|
for (const col of categoryColumns) {
|
||||||
|
const [tableName, columnName] = col.split("|");
|
||||||
|
columnParams.push(tableName, columnName);
|
||||||
|
}
|
||||||
|
|
||||||
const allValuesResult = await client.query(
|
const allValuesResult = await client.query(
|
||||||
`SELECT * FROM table_column_category_values
|
`SELECT * FROM table_column_category_values
|
||||||
WHERE menu_objid = ANY($1)
|
WHERE company_code = $1
|
||||||
|
AND (${columnConditions.join(" OR ")})
|
||||||
ORDER BY depth NULLS FIRST, parent_value_id NULLS FIRST, value_order`,
|
ORDER BY depth NULLS FIRST, parent_value_id NULLS FIRST, value_order`,
|
||||||
[menuObjids]
|
[sourceCompanyCode, ...columnParams]
|
||||||
);
|
);
|
||||||
|
|
||||||
if (allValuesResult.rows.length === 0) {
|
if (allValuesResult.rows.length === 0) {
|
||||||
@@ -2710,6 +2775,8 @@ export class MenuCopyService {
|
|||||||
return copiedCount;
|
return copiedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.info(` 📋 원본 카테고리 값: ${allValuesResult.rows.length}개 발견`);
|
||||||
|
|
||||||
// 5. 대상 회사에 이미 존재하는 값 한 번에 조회
|
// 5. 대상 회사에 이미 존재하는 값 한 번에 조회
|
||||||
const existingValuesResult = await client.query(
|
const existingValuesResult = await client.query(
|
||||||
`SELECT value_id, table_name, column_name, value_code
|
`SELECT value_id, table_name, column_name, value_code
|
||||||
@@ -2763,8 +2830,12 @@ export class MenuCopyService {
|
|||||||
)
|
)
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
|
// 기본 menu_objid: 매핑이 없을 경우 첫 번째 복사된 메뉴 사용
|
||||||
|
const defaultMenuObjid = menuIdMap.values().next().value || 0;
|
||||||
|
|
||||||
const valueParams = values.flatMap((v) => {
|
const valueParams = values.flatMap((v) => {
|
||||||
const newMenuObjid = menuIdMap.get(v.menu_objid);
|
// 원본 menu_objid가 매핑에 있으면 사용, 없으면 기본값 사용
|
||||||
|
const newMenuObjid = menuIdMap.get(v.menu_objid) ?? defaultMenuObjid;
|
||||||
const newParentId = v.parent_value_id
|
const newParentId = v.parent_value_id
|
||||||
? valueIdMap.get(v.parent_value_id) || null
|
? valueIdMap.get(v.parent_value_id) || null
|
||||||
: null;
|
: null;
|
||||||
|
|||||||
Reference in New Issue
Block a user