feat: Enhance table data addition with inserted ID response

- Updated the `addTableData` method in `TableManagementService` to return the inserted ID after adding data to the table.
- Modified the `addTableData` controller to log the inserted ID and include it in the API response, improving client-side data handling.
- Enhanced the `BomTreeComponent` to support additional configurations and improve data loading logic.
- Updated the `ButtonActionExecutor` to handle deferred saves with level-based grouping, ensuring proper ID mapping during master-detail saves.
This commit is contained in:
DDD1542
2026-02-25 13:59:51 +09:00
parent 2b175a21f4
commit ed9e36c213
6 changed files with 1413 additions and 322 deletions

View File

@@ -1791,7 +1791,7 @@ export class ButtonActionExecutor {
// 🔧 formData를 리피터에 전달하여 각 행에 병합 저장
const savedId = saveResult?.data?.id || saveResult?.data?.data?.id || formData.id || context.formData?.id;
// _deferSave 데이터 처리 (마스터-디테일 순차 저장: 메인 저장 후 디테일 저장)
// _deferSave 데이터 처리 (마스터-디테일 순차 저장: 레벨별 저장 + temp→real ID 매핑)
if (savedId) {
for (const [fieldKey, fieldValue] of Object.entries(context.formData)) {
let parsedData = fieldValue;
@@ -1804,27 +1804,47 @@ export class ButtonActionExecutor {
const targetTable = parsedData[0]?._targetTable;
if (!targetTable) continue;
for (const item of parsedData) {
const { _targetTable: _, _isNew, _deferSave: __, _fkColumn: fkCol, tempId: ___, ...data } = item;
if (!data.id || data.id === "") delete data.id;
// 레벨별 그룹핑 (레벨 0 먼저 저장 → 레벨 1 → ...)
const maxLevel = Math.max(...parsedData.map((item: any) => Number(item.level) || 0));
const tempIdToRealId = new Map<string, string>();
// FK 주입
if (fkCol) data[fkCol] = savedId;
for (let lvl = 0; lvl <= maxLevel; lvl++) {
const levelItems = parsedData.filter((item: any) => (Number(item.level) || 0) === lvl);
// 시스템 필드 추가
data.created_by = context.userId;
data.updated_by = context.userId;
data.company_code = context.companyCode;
for (const item of levelItems) {
const { _targetTable: _, _isNew, _deferSave: __, _fkColumn: fkCol, tempId, ...data } = item;
if (!data.id || data.id === "") delete data.id;
try {
const isNew = _isNew || !item.id || item.id === "";
if (isNew) {
await apiClient.post(`/table-management/tables/${targetTable}/add`, data);
} else {
await apiClient.put(`/table-management/tables/${targetTable}/${item.id}`, data);
// FK 주입 (bom_id 등)
if (fkCol) data[fkCol] = savedId;
// parent_detail_id의 temp 참조를 실제 ID로 교체
if (data.parent_detail_id && tempIdToRealId.has(data.parent_detail_id)) {
data.parent_detail_id = tempIdToRealId.get(data.parent_detail_id);
}
// 시스템 필드 추가
data.created_by = context.userId;
data.updated_by = context.userId;
data.company_code = context.companyCode;
try {
const isNew = _isNew || !item.id || item.id === "";
if (isNew) {
const res = await apiClient.post(`/table-management/tables/${targetTable}/add`, data);
const newId = res.data?.data?.id || res.data?.id;
if (newId && tempId) {
tempIdToRealId.set(tempId, newId);
}
} else {
await apiClient.put(`/table-management/tables/${targetTable}/${item.id}`, data);
if (item.id && tempId) {
tempIdToRealId.set(tempId, item.id);
}
}
} catch (err: any) {
console.error(`[handleSave] 디테일 저장 실패 (${targetTable}):`, err.response?.data || err.message);
}
} catch (err: any) {
console.error(`[handleSave] 디테일 저장 실패 (${targetTable}):`, err.response?.data || err.message);
}
}
}