fix: SelectedItemsDetailInput 수정 모드에서 null 레코드 삽입 방지

- buttonActions.ts: formData가 배열인 경우 일반 저장 건너뜀
- SelectedItemsDetailInput이 UPSERT를 완료한 후 일반 저장이 실행되어 null 레코드가 삽입되던 문제 해결
- ScreenModal에서 그룹 레코드를 배열로 전달하는 경우 감지하여 처리
- skipDefaultSave 플래그가 제대로 작동하지 않던 문제 근본 해결
This commit is contained in:
kjs
2025-11-20 15:07:26 +09:00
parent 640351d812
commit 86313c5e89
5 changed files with 1011 additions and 809 deletions

View File

@@ -134,23 +134,32 @@ export class EntityJoinService {
`🔧 기존 display_column 사용: ${column.column_name}${displayColumn}`
);
} else {
// display_column이 "none"이거나 없는 경우 기본 표시 컬럼 설정
let defaultDisplayColumn = referenceColumn;
if (referenceTable === "dept_info") {
defaultDisplayColumn = "dept_name";
} else if (referenceTable === "company_info") {
defaultDisplayColumn = "company_name";
} else if (referenceTable === "user_info") {
defaultDisplayColumn = "user_name";
} else if (referenceTable === "category_values") {
defaultDisplayColumn = "category_name";
}
// display_column이 "none"이거나 없는 경우 참조 테이블의 모든 컬럼 가져오기
logger.info(`🔍 ${referenceTable}의 모든 컬럼 조회 중...`);
displayColumns = [defaultDisplayColumn];
logger.info(
`🔧 Entity 조인 기본 표시 컬럼 설정: ${column.column_name}${defaultDisplayColumn} (${referenceTable})`
// 참조 테이블의 모든 컬럼 이름 가져오기
const tableColumnsResult = await query<{ column_name: string }>(
`SELECT column_name
FROM information_schema.columns
WHERE table_name = $1
AND table_schema = 'public'
ORDER BY ordinal_position`,
[referenceTable]
);
logger.info(`🔍 생성된 displayColumns 배열:`, displayColumns);
if (tableColumnsResult.length > 0) {
displayColumns = tableColumnsResult.map((col) => col.column_name);
logger.info(
`${referenceTable}의 모든 컬럼 자동 포함 (${displayColumns.length}개):`,
displayColumns.join(", ")
);
} else {
// 테이블 컬럼을 못 찾으면 기본값 사용
displayColumns = [referenceColumn];
logger.warn(
`⚠️ ${referenceTable}의 컬럼 조회 실패, 기본값 사용: ${referenceColumn}`
);
}
}
// 별칭 컬럼명 생성 (writer -> writer_name)
@@ -346,25 +355,26 @@ export class EntityJoinService {
);
}
} else {
// 여러 컬럼인 경우 CONCAT으로 연결
// 기본 테이블과 조인 테이블의 컬럼을 구분해서 처리
const concatParts = displayColumns
.map((col) => {
// ✅ 개선: referenceTable이 설정되어 있으면 조인 테이블에서 가져옴
const isJoinTableColumn =
config.referenceTable && config.referenceTable !== tableName;
// 🆕 여러 컬럼인 경우 각 컬럼을 개별 alias로 반환 (합치지 않음)
// 예: item_info.standard_price → sourceColumn_standard_price (item_id_standard_price)
displayColumns.forEach((col) => {
const isJoinTableColumn =
config.referenceTable && config.referenceTable !== tableName;
if (isJoinTableColumn) {
// 조인 테이블 컬럼은 조인 별칭 사용
return `COALESCE(${alias}.${col}::TEXT, '')`;
} else {
// 기본 테이블 컬럼은 main 별칭 사용
return `COALESCE(main.${col}::TEXT, '')`;
}
})
.join(` || '${separator}' || `);
const individualAlias = `${config.sourceColumn}_${col}`;
resultColumns.push(`(${concatParts}) AS ${config.aliasColumn}`);
if (isJoinTableColumn) {
// 조인 테이블 컬럼은 조인 별칭 사용
resultColumns.push(
`COALESCE(${alias}.${col}::TEXT, '') AS ${individualAlias}`
);
} else {
// 기본 테이블 컬럼은 main 별칭 사용
resultColumns.push(
`COALESCE(main.${col}::TEXT, '') AS ${individualAlias}`
);
}
});
// 🆕 referenceColumn (PK)도 함께 SELECT (parentDataMapping용)
const isJoinTableColumn =