M-BOM, 구매리스트 엑셀 업로드 머지 로직 정밀화

- 노란색(편집 가능) 컬럼만 머지 대상, 그 외 컬럼은 base 값 보존 → 비-노란 컬럼(가공품의서일 등) 빈 값 덮어쓰기 위험 차단
- highlighted 판정 통합: title HTML 배경색 / titleFormatter editable-header / downloadHighlighted 옵션 / 필드 화이트리스트
- M-BOM 소재품번(RAW_MATERIAL_NO)을 필드 화이트리스트로 강제 highlighted 처리 → 다운 헤더 노란색 + 사용자 입력 머지 반영

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-24 18:47:47 +09:00
parent 62a1afb5e3
commit 02415fcd1c
2 changed files with 77 additions and 4 deletions

View File

@@ -1481,6 +1481,17 @@ function getMbomTreeData() {
return mbomData;
}
// 화면에서 노란색(편집 가능) 헤더인지 판정 - 엑셀 다운로드/업로드 머지 기준 동일
// field 화이트리스트: 그리드에선 흰색이지만 엑셀에서는 사용자가 직접 입력해야 하는 컬럼
var FORCE_HIGHLIGHTED_FIELDS = { 'RAW_MATERIAL_NO': true };
function fn_isHighlighted(c) {
if(c.field && FORCE_HIGHLIGHTED_FIELDS[c.field]) return true;
if(c.downloadHighlighted === true) return true;
if(c.title && /background-color/.test(String(c.title))) return true;
if(c.titleFormatter && /editable-header/.test(String(c.titleFormatter))) return true;
return false;
}
// 컬럼 정의로부터 다운로드/업로드에 사용할 헤더 텍스트 결정 (titleDownload 우선)
function fn_getHeaderText(c) {
if(c.titleDownload) return c.titleDownload;
@@ -1509,7 +1520,7 @@ function fn_excel() {
field: c.field,
header: fn_getHeaderText(c),
accessorDownload: c.accessorDownload || null,
highlighted: c.downloadHighlighted === true || (typeof c.editor === 'function' || c.editor === true) || (c.title && /background-color/.test(String(c.title)))
highlighted: fn_isHighlighted(c)
});
}
}
@@ -1600,6 +1611,24 @@ function fn_excel() {
});
}
// 노란색(편집 가능 + downloadHighlighted) 필드 집합 - 머지 시 이것만 base에 덮어쓰기
function fn_buildEditableFields() {
var editable = {};
var cols = _tabulGrid.getColumnDefinitions();
function walk(arr) {
for(var i = 0; i < arr.length; i++) {
var c = arr[i];
if(c.columns) walk(c.columns);
if(c.field) {
var hi = fn_isHighlighted(c);
if(hi) editable[c.field] = true;
}
}
}
walk(cols);
return editable;
}
// columns 정의에서 헤더(title) → field 매핑 자동 생성 (titleDownload 우선)
function fn_buildHeaderFieldMap() {
var map = {};
@@ -1707,6 +1736,9 @@ function fn_excelUpload(file) {
return;
}
// 편집 가능 컬럼 집합 (이것만 머지 시 덮어쓰기, 그 외는 base 보존)
var editableFields = fn_buildEditableFields();
// 3) PART_NO 우선 매칭 (중복 시 OBJID disambiguate)
var usedObjids = {};
function pickMatch(uploadRow) {
@@ -1753,7 +1785,13 @@ function fn_excelUpload(file) {
unmatched.push({ row: i + 2, partNo: String(out.PART_NO || '') });
continue;
}
merged.push($.extend({}, base, out));
var mergedRow = $.extend({}, base);
for(var k in out) {
if(out.hasOwnProperty(k) && editableFields[k]) {
mergedRow[k] = out[k];
}
}
merged.push(mergedRow);
}
if(unmatched.length > 0) {
var msg = '기존에 없는 행이 포함되어 업로드를 중단합니다.\n신규 행은 추가할 수 없습니다.\n\n';

View File

@@ -1266,6 +1266,14 @@ function fn_mergeSavedData(savedList){
});
}
// 화면에서 노란색(편집 가능) 헤더인지 판정 - 엑셀 다운로드/업로드 머지 기준 동일
function fn_isHighlighted(c) {
if(c.downloadHighlighted === true) return true;
if(c.title && /background-color/.test(String(c.title))) return true;
if(c.titleFormatter && /editable-header/.test(String(c.titleFormatter))) return true;
return false;
}
// 컬럼 정의로부터 다운로드/업로드에 사용할 헤더 텍스트 결정 (titleDownload 우선)
function fn_getHeaderText(c) {
if(c.titleDownload) return c.titleDownload;
@@ -1294,7 +1302,7 @@ function fn_excelDownload() {
field: c.field,
header: fn_getHeaderText(c),
accessorDownload: c.accessorDownload || null,
highlighted: c.downloadHighlighted === true || (typeof c.editor === 'function' || c.editor === true) || (c.title && /background-color/.test(String(c.title)))
highlighted: fn_isHighlighted(c)
});
}
}
@@ -1386,6 +1394,24 @@ function fn_excelDownload() {
});
}
// 노란색(편집 가능 + downloadHighlighted) 필드 집합 - 머지 시 이것만 base에 덮어쓰기
function fn_buildEditableFields() {
var editable = {};
var cols = _tabulGrid.getColumnDefinitions();
function walk(arr) {
for(var i = 0; i < arr.length; i++) {
var c = arr[i];
if(c.columns) walk(c.columns);
if(c.field) {
var hi = fn_isHighlighted(c);
if(hi) editable[c.field] = true;
}
}
}
walk(cols);
return editable;
}
// columns 정의에서 헤더(title) → field 매핑 자동 생성 (titleDownload 우선)
function fn_buildHeaderFieldMap() {
var map = {};
@@ -1487,6 +1513,9 @@ function fn_excelUpload(file) {
return;
}
// 편집 가능 컬럼 집합 (이것만 머지 시 덮어쓰기, 그 외는 base 보존)
var editableFields = fn_buildEditableFields();
// 3) PART_NO 우선 매칭 (중복 시 OBJID disambiguate)
var usedObjids = {};
function pickMatch(uploadRow) {
@@ -1531,7 +1560,13 @@ function fn_excelUpload(file) {
unmatched.push({ row: i + 2, partNo: String(out.PART_NO || '') });
continue;
}
merged.push($.extend({}, base, out));
var mergedRow = $.extend({}, base);
for(var k in out) {
if(out.hasOwnProperty(k) && editableFields[k]) {
mergedRow[k] = out[k];
}
}
merged.push(mergedRow);
}
if(unmatched.length > 0) {
var msg = '기존에 없는 행이 포함되어 업로드를 중단합니다.\n신규 행은 추가할 수 없습니다.\n\n';