# 구매그룹코드 선택기 (Purchase Group Code Selector) 구매그룹코드를 선택할 수 있는 컴포넌트들입니다. Oracle DB의 CMCTB_CDNM, CMCTB_CD 테이블에서 CD_CLF='MMA070' 조건으로 구매그룹 정보를 조회하며, 선택 시 해당 사번의 사용자 정보도 함께 반환합니다. ## 컴포넌트 구조 - `purchase-group-code-service.ts`: 구매그룹코드 데이터 조회 서버 액션 (Oracle DB 조회 + 사용자 정보 포함) - `purchase-group-code-selector.tsx`: 기본 구매그룹코드 선택기 (트리거 버튼 포함) - `purchase-group-code-single-selector.tsx`: 단일 선택 다이얼로그 - `purchase-group-code-multi-selector.tsx`: 다중 선택 다이얼로그 ## 데이터 구조 ```typescript // 기본 구매그룹코드 정보 interface PurchaseGroupCode { PURCHASE_GROUP_CODE: string // 구매그룹코드 DISPLAY_NAME: string // 표시명 (이름_부서_퇴직/전배정보) EMPLOYEE_NUMBER: string // 사번 } // 사용자 정보를 포함한 구매그룹코드 interface PurchaseGroupCodeWithUser extends PurchaseGroupCode { user?: { id: number name: string email: string employeeNumber: string | null userCode: string | null } | null } ``` ## 사용 예제 ### 1. 기본 구매그룹코드 선택기 ```tsx import { useState } from 'react' import { PurchaseGroupCodeSelector, PurchaseGroupCodeWithUser } from '@/components/common/selectors/purchase-group-code' function MyComponent() { const [selectedCode, setSelectedCode] = useState() const handleSelect = (code: PurchaseGroupCodeWithUser) => { console.log('선택된 구매그룹코드:', code.PURCHASE_GROUP_CODE) console.log('표시명:', code.DISPLAY_NAME) console.log('사번:', code.EMPLOYEE_NUMBER) console.log('사용자 정보:', code.user) setSelectedCode(code) } return ( ) } ``` ### 2. 단일 선택 다이얼로그 ```tsx import { useState } from 'react' import { Button } from '@/components/ui/button' import { PurchaseGroupCodeSingleSelector, PurchaseGroupCodeWithUser } from '@/components/common/selectors/purchase-group-code' function MyComponent() { const [open, setOpen] = useState(false) const [selectedCode, setSelectedCode] = useState() return ( <> { console.log('선택 완료:', code) if (code?.user) { console.log('연결된 사용자:', code.user.name) } }} onCancel={() => { console.log('선택 취소됨') }} /> ) } ``` ### 3. 다중 선택 다이얼로그 ```tsx import { useState } from 'react' import { Button } from '@/components/ui/button' import { PurchaseGroupCodeMultiSelector, PurchaseGroupCodeWithUser } from '@/components/common/selectors/purchase-group-code' function MyComponent() { const [open, setOpen] = useState(false) const [selectedCodes, setSelectedCodes] = useState([]) return ( <> { console.log('선택된 구매그룹코드들:', codes) codes.forEach(code => { console.log(`${code.PURCHASE_GROUP_CODE}: ${code.user?.name}`) }) }} onCancel={() => { console.log('선택 취소됨') }} /> ) } ``` ### 4. 서버 액션 직접 사용 ```tsx import { getPurchaseGroupCodes, getPurchaseGroupCodeWithUser, getPurchaseGroupCodeByEmployeeNumber } from '@/components/common/selectors/purchase-group-code' // 모든 구매그룹코드 조회 const result = await getPurchaseGroupCodes() if (result.success) { console.log('구매그룹코드 목록:', result.data) } // 검색 조건으로 조회 const searchResult = await getPurchaseGroupCodes({ searchTerm: '홍길동', limit: 50 }) // 특정 구매그룹코드로 조회 (사용자 정보 포함) const codeWithUser = await getPurchaseGroupCodeWithUser('PG001') if (codeWithUser) { console.log('구매그룹코드:', codeWithUser.PURCHASE_GROUP_CODE) console.log('사용자:', codeWithUser.user?.name) } // 사번으로 구매그룹코드 조회 (사용자 정보 포함) const byEmployeeNumber = await getPurchaseGroupCodeByEmployeeNumber('1234567') if (byEmployeeNumber) { console.log('해당 사번의 구매그룹코드:', byEmployeeNumber.PURCHASE_GROUP_CODE) } ``` ## Props 옵션 ### PurchaseGroupCodeSelector - `selectedCode?: PurchaseGroupCodeWithUser` - 선택된 구매그룹코드 - `onCodeSelect: (code: PurchaseGroupCodeWithUser) => void` - 구매그룹코드 선택 콜백 - `disabled?: boolean` - 비활성화 여부 - `placeholder?: string` - 플레이스홀더 텍스트 - `className?: string` - 추가 CSS 클래스 - `searchOptions?: Partial` - 검색 옵션 ### PurchaseGroupCodeSingleSelector - `open: boolean` - 다이얼로그 열림 상태 - `onOpenChange: (open: boolean) => void` - 다이얼로그 상태 변경 콜백 - `selectedCode?: PurchaseGroupCodeWithUser` - 선택된 구매그룹코드 - `onCodeSelect: (code: PurchaseGroupCodeWithUser) => void` - 구매그룹코드 선택 콜백 - `onConfirm?: (code: PurchaseGroupCodeWithUser | undefined) => void` - 확인 버튼 콜백 - `onCancel?: () => void` - 취소 버튼 콜백 - `title?: string` - 다이얼로그 제목 - `description?: string` - 다이얼로그 설명 - `showConfirmButtons?: boolean` - 확인/취소 버튼 표시 여부 ### PurchaseGroupCodeMultiSelector - `open: boolean` - 다이얼로그 열림 상태 - `onOpenChange: (open: boolean) => void` - 다이얼로그 상태 변경 콜백 - `selectedCodes?: PurchaseGroupCodeWithUser[]` - 선택된 구매그룹코드들 - `onCodesSelect: (codes: PurchaseGroupCodeWithUser[]) => void` - 구매그룹코드들 선택 콜백 - `onConfirm?: (codes: PurchaseGroupCodeWithUser[]) => void` - 확인 버튼 콜백 - `onCancel?: () => void` - 취소 버튼 콜백 - `title?: string` - 다이얼로그 제목 - `description?: string` - 다이얼로그 설명 - `maxSelection?: number` - 최대 선택 가능 개수 ## 특징 - **Oracle DB 연동**: Oracle NonSAP 데이터베이스에서 실시간 조회 - **폴백 테스트 데이터**: Oracle DB 연결 실패 시 자동으로 테스트 데이터 사용 - **사용자 정보 통합**: 선택 시 사번으로 연결된 사용자 정보 자동 조회 - **검색 기능**: 구매그룹코드, 이름, 사번으로 실시간 검색 - **페이지네이션**: 대량의 데이터를 페이지별로 표시 - **디바운스**: 검색 성능 최적화 - **다중 선택 지원**: 여러 구매그룹코드 동시 선택 가능 - **접근성**: 키보드 네비게이션 및 스크린 리더 지원 - **반응형**: 다양한 화면 크기에 대응 ## 데이터 소스 구매그룹코드는 Oracle DB의 다음 테이블에서 조회됩니다: ```sql SELECT CD.CD AS PURCHASE_GROUP_CODE, NM.CDNM AS DISPLAY_NAME, CD.USR_DF_CHAR_9 AS EMPLOYEE_NUMBER FROM CMCTB_CDNM NM JOIN CMCTB_CD CD ON NM.CD_CLF = CD.CD_CLF AND NM.CD = CD.CD AND NM.CD2 = CD.CD3 WHERE NM.CD_CLF = 'MMA070' AND CD.USR_DF_CHAR_9 IS NOT NULL ``` 사용자 정보는 PostgreSQL DB의 `users` 테이블에서 `employeeNumber`로 조회됩니다. ## 주의사항 1. **Oracle DB 연결 필요**: 이 컴포넌트는 Oracle DB 연결이 필요합니다. 환경 변수가 올바르게 설정되어 있는지 확인하세요. 2. **폴백 테스트 데이터**: Oracle DB 연결 실패 시 하드코딩된 10개의 테스트 데이터가 자동으로 사용됩니다. 테스트 환경에서 유용합니다. 3. **사용자 정보 매칭**: 사번으로 사용자 정보를 조회하므로, 사용자 테이블에 해당 사번이 존재해야 합니다. 4. **성능**: 검색 시 Oracle DB를 직접 조회하므로, 대량 데이터 환경에서는 인덱스 설정이 중요합니다. ## 폴백 테스트 데이터 Oracle DB 연결이 불가능한 테스트 환경에서는 다음 10개의 구매그룹코드가 자동으로 제공됩니다: - `12L` - 김철수_구매팀_재직 - `32F` - 이영희_자재팀_재직 - `45A` - 박민수_조달팀_재직 - `67K` - 정수진_구매1팀_재직 - `89D` - 최동욱_구매2팀_재직 - `11B` - 강미라_자재관리팀_재직 - `23G` - 윤성호_구매기획팀_재직 - `56H` - 임지훈_조달지원팀_재직 - `78M` - 한소희_구매운영팀_재직 - `90C` - 오준석_전략구매팀_재직 ## 관련 서비스 - 구매그룹코드 동기화: `lib/nonsap-sync/purchase-group-code/purchase-group-code-sync.ts` - 사용자 서비스: `lib/users/service.ts`