feat: Enhance dynamic form and BOM item editor functionality
- Added support for updating the `updated_date` field in the DynamicFormService, ensuring accurate timestamp management. - Refactored the BomItemEditorComponent to improve data handling by filtering valid fields before saving, enhancing data integrity. - Introduced a mechanism to track existing item IDs to prevent duplicates during item addition, improving user experience and data consistency. - Streamlined the save process in ButtonActionExecutor by reorganizing the event handling logic, ensuring better integration with EditModal components.
This commit is contained in:
@@ -1033,6 +1033,9 @@ export class DynamicFormService {
|
||||
if (tableColumns.includes("updated_at")) {
|
||||
dataToUpdate.updated_at = new Date();
|
||||
}
|
||||
if (tableColumns.includes("updated_date")) {
|
||||
dataToUpdate.updated_date = new Date();
|
||||
}
|
||||
if (tableColumns.includes("regdate") && !dataToUpdate.regdate) {
|
||||
dataToUpdate.regdate = new Date();
|
||||
}
|
||||
|
||||
271
bom-save-console-logs.txt
Normal file
271
bom-save-console-logs.txt
Normal file
@@ -0,0 +1,271 @@
|
||||
[info] %cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[warning] Image with src "/images/vexplor.png" has either width or height modified, but not the other. If you use CSS to change the size of your image, also include the styles 'width: "auto"' or 'height: "auto"' to maintain the aspect ratio.
|
||||
[log] 첫 번째 접근 가능한 메뉴로 이동: /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[log] 📦 메인 테이블 데이터 자동 로드: company_mng {company_code: COMPANY_7, company_name: 탑씰 테스트, writer: wace, regdate: 2026-02-27T09:28:35.342Z, status: active}
|
||||
[log] 📦 메인 테이블 데이터 자동 로드: company_mng {company_code: COMPANY_7, company_name: 탑씰 테스트, writer: wace, regdate: 2026-02-27T09:28:35.342Z, status: active}
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/138) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 1030135068124796000, error: 404}
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 666667496384701400, error: 404}
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 88591267128165600, error: 404}
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 1030135068124796000, error: 404}
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 666667496384701400, error: 404}
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[error] Failed to load resource: the server responded with a status of 404 (Not Found)
|
||||
[error] ❌ 대표 이미지 로드 실패: {file: clideo_editor_cb93b93c55584c3780a53ef149e62ee5.gif, objid: 88591267128165600, error: 404}
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/138
|
||||
[info] %cDownload the React DevTools for a better development experience: https://react.dev/link/react-devtools font-weight:bold
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 0 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 0 leftGroupSumConfig: null
|
||||
[log] 📦 [SplitPanelLayout] Context에 분할 패널 등록: {splitPanelId: split-panel-comp_split_panel, panelInfo: Object}
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] 🔗 [분할패널] 좌측 additionalJoinColumns: [Object, Object, Object]
|
||||
[log] 🔗 [분할패널] 좌측 additionalJoinColumns: [Object, Object, Object]
|
||||
[log] 📦 [SplitPanelLayout] Context에서 분할 패널 해제: split-panel-comp_split_panel
|
||||
[log] 📦 [SplitPanelLayout] Context에 분할 패널 등록: {splitPanelId: split-panel-comp_split_panel, panelInfo: Object}
|
||||
[log] 🔗 [분할패널] 좌측 additionalJoinColumns: [Object, Object, Object]
|
||||
[log] 🔗 [분할패널] 좌측 additionalJoinColumns: [Object, Object, Object]
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] ✅ 좌측 컬럼 라벨 로드: {id: ID, created_date: 생성일시, updated_date: 수정일시, writer: 작성자, company_code: 회사코드}
|
||||
[log] ✅ 좌측 컬럼 라벨 로드: {id: ID, created_date: 생성일시, updated_date: 수정일시, writer: 작성자, company_code: 회사코드}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] ✅ 좌측 카테고리 매핑 로드 [status]: {CAT_MM3XFDT6_YULY: Object, CAT_MM3XFA7B_ZFD6: Object}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] ✅ 좌측 카테고리 매핑 로드 [status]: {CAT_MM3XFDT6_YULY: Object, CAT_MM3XFA7B_ZFD6: Object}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터 키: [id, created_date, updated_date, writer, company_code, bom_number, item_id, item_code, item_name, item_type, base_qty, unit, version, revision, status, effective_date, expired_date, remark, current_version_id, writer_sabun, writer_user_id, writer_user_password, writer_user_name, writer_user_name_eng, writer_user_name_cn, writer_dept_code, writer_dept_name, writer_position_code, writer_position_name, writer_email, writer_tel, writer_cell_phone, writer_user_type, writer_user_type_name, writer_regdate, writer_status, writer_end_date, writer_fax_no, writer_partner_objid, writer_photo, writer_locale, writer_data_type, writer_license_number, writer_vehicle_number, writer_signup_type, writer_branch_name, writer_department_history, writer_label, item_id_id, item_id_status, item_id_item_name, item_id_size, item_id_material, item_id_inventory_unit, item_id_weight, item_id_unit, item_id_image, item_id_division, item_id_type, item_id_meno, item_id_item_number, item_id_selling_price, item_id_standard_price, item_id_currency_code, item_id_volum, item_id_specific_gravity, item_id_user_type01, item_id_user_type02, item_id_label]
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터: {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터 키: [id, created_date, updated_date, writer, company_code, bom_number, item_id, item_code, item_name, item_type, base_qty, unit, version, revision, status, effective_date, expired_date, remark, current_version_id, writer_sabun, writer_user_id, writer_user_password, writer_user_name, writer_user_name_eng, writer_user_name_cn, writer_dept_code, writer_dept_name, writer_position_code, writer_position_name, writer_email, writer_tel, writer_cell_phone, writer_user_type, writer_user_type_name, writer_regdate, writer_status, writer_end_date, writer_fax_no, writer_partner_objid, writer_photo, writer_locale, writer_data_type, writer_license_number, writer_vehicle_number, writer_signup_type, writer_branch_name, writer_department_history, writer_label, item_id_id, item_id_status, item_id_item_name, item_id_size, item_id_material, item_id_inventory_unit, item_id_weight, item_id_unit, item_id_image, item_id_division, item_id_type, item_id_meno, item_id_item_number, item_id_selling_price, item_id_standard_price, item_id_currency_code, item_id_volum, item_id_specific_gravity, item_id_user_type01, item_id_user_type02, item_id_label]
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터: {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터 키: [id, created_date, updated_date, writer, company_code, bom_number, item_id, item_code, item_name, item_type, base_qty, unit, version, revision, status, effective_date, expired_date, remark, current_version_id, writer_sabun, writer_user_id, writer_user_password, writer_user_name, writer_user_name_eng, writer_user_name_cn, writer_dept_code, writer_dept_name, writer_position_code, writer_position_name, writer_email, writer_tel, writer_cell_phone, writer_user_type, writer_user_type_name, writer_regdate, writer_status, writer_end_date, writer_fax_no, writer_partner_objid, writer_photo, writer_locale, writer_data_type, writer_license_number, writer_vehicle_number, writer_signup_type, writer_branch_name, writer_department_history, writer_label, item_id_id, item_id_status, item_id_item_name, item_id_size, item_id_material, item_id_inventory_unit, item_id_weight, item_id_unit, item_id_image, item_id_division, item_id_type, item_id_meno, item_id_item_number, item_id_selling_price, item_id_standard_price, item_id_currency_code, item_id_volum, item_id_specific_gravity, item_id_user_type01, item_id_user_type02, item_id_label]
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터: {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터 키: [id, created_date, updated_date, writer, company_code, bom_number, item_id, item_code, item_name, item_type, base_qty, unit, version, revision, status, effective_date, expired_date, remark, current_version_id, writer_sabun, writer_user_id, writer_user_password, writer_user_name, writer_user_name_eng, writer_user_name_cn, writer_dept_code, writer_dept_name, writer_position_code, writer_position_name, writer_email, writer_tel, writer_cell_phone, writer_user_type, writer_user_type_name, writer_regdate, writer_status, writer_end_date, writer_fax_no, writer_partner_objid, writer_photo, writer_locale, writer_data_type, writer_license_number, writer_vehicle_number, writer_signup_type, writer_branch_name, writer_department_history, writer_label, item_id_id, item_id_status, item_id_item_name, item_id_size, item_id_material, item_id_inventory_unit, item_id_weight, item_id_unit, item_id_image, item_id_division, item_id_type, item_id_meno, item_id_item_number, item_id_selling_price, item_id_standard_price, item_id_currency_code, item_id_volum, item_id_specific_gravity, item_id_user_type01, item_id_user_type02, item_id_label]
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터: {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] ✅ 분할 패널 좌측 선택: bom {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔴 [ButtonPrimary] 저장 시 formData 디버그: {propsFormDataKeys: Array(70), screenContextFormDataKeys: Array(0), effectiveFormDataKeys: Array(70), process_code: undefined, equipment_code: undefined}
|
||||
[log] [BomTree] openEditModal 가로채기 - editData 보정 {oldVersion: 1.0, newVersion: 1.0, oldCurrentVersionId: de575ae5-266c-42f0-be49-bcc65de89ebd, newCurrentVersionId: de575ae5-266c-42f0-be49-bcc65de89ebd}
|
||||
[log] 🔄 [SplitPanel] refreshTable 이벤트 수신 - 데이터 새로고침
|
||||
[log] 🔗 [분할패널] 좌측 additionalJoinColumns: [Object, Object, Object]
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] [EditModal] 모달 열림: {mode: UPDATE (수정), hasEditData: true, editDataId: 64617576-fec9-4caa-8e72-653f9e83ba45, isCreateMode: false}
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] ⚠️ [ScreenModal] getModalStyle: screenDimensions가 null - 기본 스타일 사용
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] [EditModal] 화면 데이터 로드 완료, 조건부 레이어 로드 시작: 4154
|
||||
[log] [EditModal] loadConditionalLayersAndZones 호출됨: 4154
|
||||
[log] [EditModal] API 호출 시작: getScreenLayers, getScreenZones
|
||||
[log] [EditModal] API 응답: {layers: 1, zones: 0}
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: 초기 인증 확인: 유효한 토큰 존재 (경로: /screens/4168) | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_START: refreshUserData: API로 인증 상태 확인 시작 | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터 키: [id, created_date, updated_date, writer, company_code, bom_number, item_id, item_code, item_name, item_type, base_qty, unit, version, revision, status, effective_date, expired_date, remark, current_version_id, writer_sabun, writer_user_id, writer_user_password, writer_user_name, writer_user_name_eng, writer_user_name_cn, writer_dept_code, writer_dept_name, writer_position_code, writer_position_name, writer_email, writer_tel, writer_cell_phone, writer_user_type, writer_user_type_name, writer_regdate, writer_status, writer_end_date, writer_fax_no, writer_partner_objid, writer_photo, writer_locale, writer_data_type, writer_license_number, writer_vehicle_number, writer_signup_type, writer_branch_name, writer_department_history, writer_label, item_id_id, item_id_status, item_id_item_name, item_id_size, item_id_material, item_id_inventory_unit, item_id_weight, item_id_unit, item_id_image, item_id_division, item_id_type, item_id_meno, item_id_item_number, item_id_selling_price, item_id_standard_price, item_id_currency_code, item_id_volum, item_id_specific_gravity, item_id_user_type01, item_id_user_type02, item_id_label]
|
||||
[log] 🔗 [분할패널] API 응답 첫 번째 데이터: {id: 64617576-fec9-4caa-8e72-653f9e83ba45, created_date: 2026-02-27 10:22:39.485, updated_date: 2026-02-27 03:15:10.819, writer: wace, company_code: COMPANY_7}
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [그룹합산] leftGroupSumConfig: null
|
||||
[log] 🔍 [그룹합산] 그룹핑 비활성화 - 원본 데이터 반환
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[log] 🔗 [SplitPanelLayout] Context 연결 상태: {componentId: comp_split_panel, splitPanelId: split-panel-comp_split_panel, hasRegisterFunc: true, splitPanelsSize: 0}
|
||||
[log] 🔍 [SplitPanel] 왼쪽 패널 displayMode: table isDesignMode: false
|
||||
[log] 🔍 [테이블모드 렌더링] dataSource 개수: 9 leftGroupSumConfig: null
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
[debug] [AuthLog] AUTH_CHECK_SUCCESS: 사용자: topseal_admin, 인증: true | 토큰: 유효(24h0m 남음, user:topseal_admin) | /screens/4168
|
||||
@@ -812,7 +812,7 @@ export function BomItemEditorComponent({
|
||||
: null;
|
||||
|
||||
if (node._isNew) {
|
||||
const payload: Record<string, any> = {
|
||||
const raw: Record<string, any> = {
|
||||
...node.data,
|
||||
[fkColumn]: bomId,
|
||||
[parentKeyColumn]: realParentId,
|
||||
@@ -821,10 +821,16 @@ export function BomItemEditorComponent({
|
||||
company_code: companyCode || undefined,
|
||||
version_id: saveVersionId || undefined,
|
||||
};
|
||||
delete payload.id;
|
||||
delete payload.tempId;
|
||||
delete payload._isNew;
|
||||
delete payload._isDeleted;
|
||||
// bom_detail에 유효한 필드만 남기기 (item_info 조인 필드 제거)
|
||||
const payload: Record<string, any> = {};
|
||||
const validKeys = new Set([
|
||||
fkColumn, parentKeyColumn, "seq_no", "level", "child_item_id",
|
||||
"quantity", "unit", "loss_rate", "remark", "process_type",
|
||||
"base_qty", "revision", "version_id", "company_code", "writer",
|
||||
]);
|
||||
Object.keys(raw).forEach((k) => {
|
||||
if (validKeys.has(k)) payload[k] = raw[k];
|
||||
});
|
||||
|
||||
const resp = await apiClient.post(
|
||||
`/table-management/tables/${mainTableName}/add`,
|
||||
@@ -835,17 +841,14 @@ export function BomItemEditorComponent({
|
||||
savedCount++;
|
||||
} else if (node.id) {
|
||||
const updatedData: Record<string, any> = {
|
||||
...node.data,
|
||||
id: node.id,
|
||||
[fkColumn]: bomId,
|
||||
[parentKeyColumn]: realParentId,
|
||||
seq_no: String(seqNo),
|
||||
level: String(level),
|
||||
};
|
||||
delete updatedData.tempId;
|
||||
delete updatedData._isNew;
|
||||
delete updatedData._isDeleted;
|
||||
Object.keys(updatedData).forEach((k) => {
|
||||
if (k.startsWith(`${sourceFk}_`)) delete updatedData[k];
|
||||
["quantity", "unit", "loss_rate", "remark", "process_type", "base_qty", "revision", "child_item_id", "version_id", "company_code"].forEach((k) => {
|
||||
if (node.data[k] !== undefined) updatedData[k] = node.data[k];
|
||||
});
|
||||
|
||||
await apiClient.put(
|
||||
@@ -934,6 +937,20 @@ export function BomItemEditorComponent({
|
||||
setItemSearchOpen(true);
|
||||
}, []);
|
||||
|
||||
// 이미 추가된 품목 ID 목록 (중복 방지용)
|
||||
const existingItemIds = useMemo(() => {
|
||||
const ids = new Set<string>();
|
||||
const collect = (nodes: BomItemNode[]) => {
|
||||
for (const n of nodes) {
|
||||
const fk = n.data[cfg.dataSource?.foreignKey || "child_item_id"];
|
||||
if (fk) ids.add(fk);
|
||||
collect(n.children);
|
||||
}
|
||||
};
|
||||
collect(treeData);
|
||||
return ids;
|
||||
}, [treeData, cfg]);
|
||||
|
||||
// 루트 품목 추가 시작
|
||||
const handleAddRoot = useCallback(() => {
|
||||
setAddTargetParentId(null);
|
||||
@@ -1353,18 +1370,7 @@ export function BomItemEditorComponent({
|
||||
onClose={() => setItemSearchOpen(false)}
|
||||
onSelect={handleItemSelect}
|
||||
companyCode={companyCode}
|
||||
existingItemIds={useMemo(() => {
|
||||
const ids = new Set<string>();
|
||||
const collect = (nodes: BomItemNode[]) => {
|
||||
for (const n of nodes) {
|
||||
const fk = n.data[cfg.dataSource?.foreignKey || "child_item_id"];
|
||||
if (fk) ids.add(fk);
|
||||
collect(n.children);
|
||||
}
|
||||
};
|
||||
collect(treeData);
|
||||
return ids;
|
||||
}, [treeData, cfg])}
|
||||
existingItemIds={existingItemIds}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -558,31 +558,7 @@ export class ButtonActionExecutor {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 🆕 EditModal 등에서 전달된 onSave 콜백이 있으면 우선 사용
|
||||
// EditModal이 내부에서 직접 repeaterSave 이벤트를 발행하고 완료를 기다림
|
||||
if (onSave) {
|
||||
try {
|
||||
await onSave();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("❌ [handleSave] onSave 콜백 실행 오류:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("⚠️ [handleSave] onSave 콜백 없음 - 기본 저장 로직 실행");
|
||||
|
||||
// 🆕 저장 전 이벤트 발생 (SelectedItemsDetailInput 등에서 최신 데이터 수집)
|
||||
// context.formData를 이벤트 detail에 포함하여 직접 수정 가능하게 함
|
||||
// skipDefaultSave 플래그를 통해 기본 저장 로직을 건너뛸 수 있음
|
||||
|
||||
// 🔧 디버그: beforeFormSave 이벤트 전 formData 확인
|
||||
console.log("🔍 [handleSave] beforeFormSave 이벤트 전:", {
|
||||
keys: Object.keys(context.formData || {}),
|
||||
hasCompanyImage: "company_image" in (context.formData || {}),
|
||||
companyImageValue: context.formData?.company_image,
|
||||
});
|
||||
|
||||
// beforeFormSave 이벤트 발송 (BomItemEditor 등 서브 컴포넌트의 저장 처리)
|
||||
const beforeSaveEventDetail = {
|
||||
formData: context.formData,
|
||||
skipDefaultSave: false,
|
||||
@@ -596,22 +572,28 @@ export class ButtonActionExecutor {
|
||||
}),
|
||||
);
|
||||
|
||||
// 비동기 핸들러가 등록한 Promise들 대기 + 동기 핸들러를 위한 최소 대기
|
||||
if (beforeSaveEventDetail.pendingPromises.length > 0) {
|
||||
console.log(
|
||||
`[handleSave] 비동기 beforeFormSave 핸들러 ${beforeSaveEventDetail.pendingPromises.length}건 대기 중...`,
|
||||
);
|
||||
await Promise.all(beforeSaveEventDetail.pendingPromises);
|
||||
} else {
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
// 검증 실패 시 저장 중단
|
||||
if (beforeSaveEventDetail.validationFailed) {
|
||||
console.log("❌ [handleSave] 검증 실패로 저장 중단:", beforeSaveEventDetail.validationErrors);
|
||||
return false;
|
||||
}
|
||||
|
||||
// EditModal 등에서 전달된 onSave 콜백이 있으면 우선 사용
|
||||
if (onSave) {
|
||||
try {
|
||||
await onSave();
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("❌ [handleSave] onSave 콜백 실행 오류:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 🆕 EditModal 등에서 전달된 onSave 콜백이 있으면 우선 사용
|
||||
// 단, _tableSection_ 데이터가 있으면 건너뛰기 (handleUniversalFormModalTableSectionSave가 처리)
|
||||
// EditModal이 내부에서 직접 repeaterSave 이벤트를 발행하고 완료를 기다림
|
||||
|
||||
Reference in New Issue
Block a user