- buttonActions.ts: formData가 배열인 경우 일반 저장 건너뜀
- SelectedItemsDetailInput이 UPSERT를 완료한 후 일반 저장이 실행되어 null 레코드가 삽입되던 문제 해결
- ScreenModal에서 그룹 레코드를 배열로 전달하는 경우 감지하여 처리
- skipDefaultSave 플래그가 제대로 작동하지 않던 문제 근본 해결
- 필드 자동 매핑 기능 구현
* FieldMapping 타입 추가 (sourceField → targetField)
* applyFieldMappings() 함수로 선택 시 자동 입력
* 여러 필드를 한 번에 자동으로 채움 (거래처 선택 → 주소/전화 자동 입력)
- 값 필드 저장 위치 선택 기능 추가
* ValueFieldStorage 타입 추가 (targetTable, targetColumn)
* 기본값(화면 연결 테이블) 또는 명시적 테이블/컬럼 지정 가능
* 중간 테이블, 이력 테이블 등 다중 테이블 저장 지원
- UI/UX 개선
* 모든 선택 필드를 Combobox 스타일로 통일
* 각 필드 아래 간략한 사용 설명 추가
* 저장 위치 동작 미리보기 박스 추가
- 문서 작성
* 사용_가이드.md 신규 작성 (실전 예제 3개 포함)
* 빠른 시작 가이드, FAQ, 체크리스트 제공
- 하드코딩 제거: 필드명 패턴을 동적으로 처리
- 민감한 필드(id, password, token, company_code)만 제외하고 모두 표시
- 그룹 삭제 기능: 중복 제거 활성화 시 관련된 모든 레코드 삭제
- URL 파라미터 초기화: 모달 닫을 때 자동으로 초기화
- 백엔드: deleteGroupRecords API 추가
- 프론트엔드: dataApi.deleteGroupRecords 클라이언트 추가
- SelectedItemsDetailInput 컴포넌트 수정 모드 지원
- 그룹화된 데이터 UPSERT API 추가 (/api/data/upsert-grouped)
- 부모 키 기준으로 기존 레코드 조회 후 INSERT/UPDATE/DELETE
- 각 레코드의 모든 필드 조합을 고유 키로 사용
- created_date 보존 (UPDATE 시)
- 수정 모드에서 groupByColumns 기준으로 관련 레코드 조회
- 날짜 타입 ISO 형식 자동 감지 및 포맷팅 (YYYY.MM.DD)
주요 변경사항:
- backend: dataService.upsertGroupedRecords() 메서드 구현
- backend: dataRoutes POST /api/data/upsert-grouped 엔드포인트 추가
- frontend: ScreenModal에서 groupByColumns 파라미터 전달
- frontend: SelectedItemsDetailInput 수정 모드 로직 추가
- frontend: 날짜 필드 타임존 제거 및 포맷팅 개선
문제:
- reference 매핑 시 조인 조건의 소스 필드 값이 undefined
- API 호출 시 filters 파라미터를 백엔드가 인식 못함
해결:
- 컬럼 처리를 2단계로 분리 (source/manual → reference)
- API 파라미터 변경 (filters→search, limit/offset→size/page)
- 응답 경로 수정 (data.data → data.data.data)
결과:
- 외부 테이블 참조 매핑 정상 작동
- 품목 선택 시 customer_item_mapping에서 단가 자동 조회 성공
새로운 기능
- 컬럼별 독립적인 소스 테이블 선택 기능
- SourceColumnSelector, ReferenceColumnSelector 컴포넌트 추가
- 계산 규칙 자동 동기화 로직 (cleanupInitialConfig)
UI/UX 개선
- 컬럼 설정 UI를 세로 레이아웃으로 재구성 (h-10 통일)
- 매핑 타입별 색상 구분 (파란색/보라색/초록색)
- 계산 규칙 섹션 재디자인 (안내 박스, 번호 배지, 빈 상태)
- 현재 설정 시각화 (코드 스타일 표시)
버그 수정
- 계산 규칙 삭제 시 컬럼이 수정 불가능 상태로 남는 문제 해결
- 결과 필드 변경 시 이전 필드의 calculated 속성 제거
- 초기 로드 시 계산 규칙과 컬럼 속성 동기화
개선 사항
- 모든 입력 필드의 높이와 텍스트 크기 일관성 확보
- 섹션별 명확한 제목과 설명 추가
- 접근성 향상 (ARIA 레이블, 포커스 스타일)
변경사항:
- handleBatchSave의 모든 console.log 제거
- 핵심 로직만 유지 (데이터 매핑, 조합 생성, 저장)
- 코드 가독성 향상
제거된 로그:
- modalDataStore 데이터 확인 로그
- parentDataMapping 설정 로그
- 품목/그룹 처리 로그
- 조합 생성/병합 로그
- 데이터 소스 상세 로그
- 저장 요청/결과 로그
유지된 기능:
- Zustand modalDataStore에서 부모 데이터 가져오기
- 무한 깊이 모달 지원
- 완전히 설정 기반 parentDataMapping
- 카티션 곱 조합 생성
- 하드코딩 없는 동적 매핑
문제:
- modalDataStore가 window 전역 변수가 아닌 Zustand store임
- window.__modalDataRegistry로 접근 시도했으나 빈 객체 반환
- 거래처 데이터를 찾을 수 없어 customer_code 매핑 실패
해결:
- useModalDataStore.getState().dataRegistry로 Zustand store 직접 접근
- ModalDataItem[] 배열에서 originalData 추출
- 각 테이블별 데이터를 modalDataStore 객체로 변환
- 거래처(customer_mng), 품목(item_info) 데이터 모두 접근 가능
기술적 변경:
- dynamic import로 Zustand store 로드
- ModalDataItem 구조 이해 및 originalData 추출
- 에러 핸들링 (store 로드 실패 시)
- 상세한 디버깅 로그 (테이블별 데이터 count)
문제:
- 메인 화면(거래처 선택) → 첫 번째 모달(품목 선택) → 두 번째 모달(상세 입력)
- selectedRowsData는 바로 이전 화면 데이터만 제공하여 2단계 이전 데이터 접근 불가
- customer_id가 NULL로 저장됨
해결:
- modalDataStore의 전역 레지스트리에서 모든 누적 데이터 접근
- sourceTable에 따라 적절한 데이터 소스 자동 선택
- 거래처 데이터(customer_mng)를 modalDataStore에서 직접 가져옴
기술적 변경:
- ButtonPrimaryComponent: allComponents에서 componentConfigs 수집 및 전달
- ButtonActionContext: componentConfigs 속성 추가
- handleBatchSave: modalDataStore에서 테이블별 데이터 조회
- parentDataMapping 로직: sourceTable 기반 데이터 소스 자동 감지
- 디버깅 로그 강화 (modalDataStore 키, 데이터 소스 추적)
- 여러 테이블(거래처, 품목 등)에서 데이터를 가져와 자동 매핑 가능
- 각 매핑마다 소스 테이블, 원본 필드, 저장 필드를 독립적으로 설정
- 검색 가능한 Combobox로 테이블 및 컬럼 선택 UX 개선
- 소스 테이블 선택 시 해당 테이블의 컬럼 자동 로드
- 라벨, 컬럼명, 데이터 타입으로 검색 가능
- 세로 레이아웃으로 가독성 향상
기술적 변경사항:
- ParentDataMapping 인터페이스 추가 (sourceTable, sourceField, targetField)
- buttonActions.ts의 handleBatchSave에서 소스 테이블 기반 데이터 소스 자동 판단
- tableManagementApi.getColumnList() 사용하여 테이블 컬럼 동적 로드
- Command + Popover 조합으로 검색 가능한 Select 구현
- 각 매핑별 독립적인 컬럼 상태 관리 (mappingSourceColumns)
문제:
- 조건부 컨테이너 내부의 modal-repeater-table 컴포넌트가 데이터 업데이트 불가
- ConditionalSectionViewer가 RealtimePreview에 formData/onFormDataChange 미전달
해결:
- ConditionalSectionViewer.tsx: RealtimePreview에 formData, onFormDataChange props 추가
- DynamicComponentRenderer.tsx: 디버깅 로그 정리
- ScreenModal.tsx: 디버깅 로그 정리
영향:
- 수주 등록 화면 품목 추가 기능 정상 작동
- 조건부 컨테이너 내부 모든 폼 컴포넌트 데이터 바인딩 정상화
Refs: #수주관리 #modal-repeater-table #ConditionalContainer
- ResizableDialog 콘텐츠 영역에 pointer-events 및 z-index 설정 추가
- TextInputComponent를 제어 컴포넌트에서 비제어 컴포넌트로 변경 (value → defaultValue)
- ItemSelectionModal 및 TextInputComponent 디버그 로그 제거
수정 파일:
- frontend/components/ui/resizable-dialog.tsx
- frontend/lib/registry/components/text-input/TextInputComponent.tsx
- frontend/lib/registry/components/modal-repeater-table/ItemSelectionModal.tsx
- uniqueField 값이 undefined일 때 객체 참조 비교로 폴백
- 멀티셀렉트 모드에서 선택/해제 로직 안정화
- 체크박스 클릭 이벤트 전파 개선
- 유효한 컬럼만 렌더링하도록 필터링 추가
- 디버깅을 위한 콘솔 로그 추가
- 선택된 항목의 uniqueField 값 표시