summaryrefslogtreecommitdiff
path: root/components/common
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-11-24 11:16:32 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-11-24 11:16:32 +0000
commita8674e6b91fb4d356c311fad0251878de154da53 (patch)
tree8bdf91ef99b2628f319df37912ccede1e2f5009c /components/common
parent68160eba15a2c8408329b6e14b94d5e44fa7e3ab (diff)
(최겸) 구매 입찰 수정(폐찰, 낙찰 결재 기능 추가 등)
Diffstat (limited to 'components/common')
-rw-r--r--components/common/selectors/cost-center/cost-center-selector.tsx26
-rw-r--r--components/common/selectors/cost-center/cost-center-service.ts40
-rw-r--r--components/common/selectors/cost-center/cost-center-single-selector.tsx24
-rw-r--r--components/common/selectors/gl-account/gl-account-selector.tsx20
-rw-r--r--components/common/selectors/gl-account/gl-account-service.ts32
-rw-r--r--components/common/selectors/gl-account/gl-account-single-selector.tsx14
-rw-r--r--components/common/selectors/procurement-item/procurement-item-selector-dialog-single.tsx2
-rw-r--r--components/common/selectors/wbs-code/wbs-code-selector.tsx37
-rw-r--r--components/common/selectors/wbs-code/wbs-code-service.ts48
-rw-r--r--components/common/selectors/wbs-code/wbs-code-single-selector.tsx40
10 files changed, 67 insertions, 216 deletions
diff --git a/components/common/selectors/cost-center/cost-center-selector.tsx b/components/common/selectors/cost-center/cost-center-selector.tsx
index 3aad5787..f87b6928 100644
--- a/components/common/selectors/cost-center/cost-center-selector.tsx
+++ b/components/common/selectors/cost-center/cost-center-selector.tsx
@@ -77,11 +77,6 @@ export function CostCenterSelector({
const [globalFilter, setGlobalFilter] = useState('')
const [isPending, startTransition] = useTransition()
- // 날짜 포맷 함수 (YYYYMMDD -> YYYY-MM-DD)
- const formatDate = (dateStr: string) => {
- if (!dateStr || dateStr.length !== 8) return dateStr
- return `${dateStr.substring(0, 4)}-${dateStr.substring(4, 6)}-${dateStr.substring(6, 8)}`
- }
// Cost Center 선택 핸들러
const handleCodeSelect = useCallback(async (code: CostCenter) => {
@@ -118,27 +113,6 @@ export function CostCenterSelector({
),
},
{
- accessorKey: 'LTEXT',
- header: '설명',
- cell: ({ row }) => (
- <div>{row.getValue('LTEXT')}</div>
- ),
- },
- {
- accessorKey: 'DATAB',
- header: '시작일',
- cell: ({ row }) => (
- <div className="text-sm">{formatDate(row.getValue('DATAB'))}</div>
- ),
- },
- {
- accessorKey: 'DATBI',
- header: '종료일',
- cell: ({ row }) => (
- <div className="text-sm">{formatDate(row.getValue('DATBI'))}</div>
- ),
- },
- {
id: 'actions',
header: '선택',
cell: ({ row }) => (
diff --git a/components/common/selectors/cost-center/cost-center-service.ts b/components/common/selectors/cost-center/cost-center-service.ts
index 844215f0..1e7e43f5 100644
--- a/components/common/selectors/cost-center/cost-center-service.ts
+++ b/components/common/selectors/cost-center/cost-center-service.ts
@@ -5,19 +5,16 @@ import { oracleKnex } from '@/lib/oracle-db/db'
// Cost Center 타입 정의
export interface CostCenter {
KOSTL: string // Cost Center 코드
- DATAB: string // 시작일
- DATBI: string // 종료일
KTEXT: string // 단축 텍스트
- LTEXT: string // 긴 텍스트
}
// 테스트 환경용 폴백 데이터
const FALLBACK_TEST_DATA: CostCenter[] = [
- { KOSTL: 'D6023930', DATAB: '20230101', DATBI: '99991231', KTEXT: '구매팀', LTEXT: '구매팀 Cost Center(테스트데이터 - 오라클 페칭 실패시)' },
- { KOSTL: 'D6023931', DATAB: '20230101', DATBI: '99991231', KTEXT: '자재팀', LTEXT: '자재팀 Cost Center(테스트데이터 - 오라클 페칭 실패시)' },
- { KOSTL: 'D6023932', DATAB: '20230101', DATBI: '99991231', KTEXT: '조달팀', LTEXT: '조달팀 Cost Center(테스트데이터 - 오라클 페칭 실패시)' },
- { KOSTL: 'D6023933', DATAB: '20230101', DATBI: '99991231', KTEXT: '구매1팀', LTEXT: '구매1팀 Cost Center(테스트데이터 - 오라클 페칭 실패시)' },
- { KOSTL: 'D6023934', DATAB: '20230101', DATBI: '99991231', KTEXT: '구매2팀', LTEXT: '구매2팀 Cost Center(테스트데이터 - 오라클 페칭 실패시)' },
+ { KOSTL: 'D6023930', KTEXT: '구매팀(테스트데이터 - 오라클 페칭 실패시)' },
+ { KOSTL: 'D6023931', KTEXT: '자재팀(테스트데이터 - 오라클 페칭 실패시)' },
+ { KOSTL: 'D6023932', KTEXT: '조달팀(테스트데이터 - 오라클 페칭 실패시)' },
+ { KOSTL: 'D6023933', KTEXT: '구매1팀(테스트데이터 - 오라클 페칭 실패시)' },
+ { KOSTL: 'D6023934', KTEXT: '구매2팀(테스트데이터 - 오라클 페칭 실패시)' },
]
/**
@@ -35,19 +32,11 @@ export async function getCostCenters(): Promise<{
console.log('📋 [getCostCenters] Oracle 쿼리 시작...')
const result = await oracleKnex.raw(`
- SELECT
- KOSTL,
- DATAB,
- DATBI,
- KTEXT,
- LTEXT
- FROM CMCTB_COSTCENTER
- WHERE ROWNUM < 100
- AND NVL(BKZKP,' ') = ' '
- AND TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN DATAB AND DATBI
- AND KOKRS = 'H100'
- ORDER BY KOSTL
+ SELECT KOSTL , KTEXT FROM CMCTB_COSTCENTER
+ WHERE TO_CHAR(SYSDATE,'YYYYMMDD') BETWEEN DATAB AND DATBI AND ROWNUM < 10
`)
+ // KOSTL -> CONTCENTER
+ // KTEXT -> CONTCENTER명
// Oracle raw query의 결과는 rows 배열에 들어있음
const rows = (result.rows || result) as Array<Record<string, unknown>>
@@ -56,17 +45,12 @@ export async function getCostCenters(): Promise<{
// null 값 필터링
const cleanedResult = rows
- .filter((item) =>
- item.KOSTL &&
- item.DATAB &&
- item.DATBI
+ .filter((item) =>
+ item.KOSTL
)
.map((item) => ({
KOSTL: String(item.KOSTL),
- DATAB: String(item.DATAB),
- DATBI: String(item.DATBI),
- KTEXT: String(item.KTEXT || ''),
- LTEXT: String(item.LTEXT || '')
+ KTEXT: String(item.KTEXT || '')
}))
console.log(`✅ [getCostCenters] 필터링 후 ${cleanedResult.length}건`)
diff --git a/components/common/selectors/cost-center/cost-center-single-selector.tsx b/components/common/selectors/cost-center/cost-center-single-selector.tsx
index e09f782b..952fab3f 100644
--- a/components/common/selectors/cost-center/cost-center-single-selector.tsx
+++ b/components/common/selectors/cost-center/cost-center-single-selector.tsx
@@ -134,27 +134,6 @@ export function CostCenterSingleSelector({
),
},
{
- accessorKey: 'LTEXT',
- header: '설명',
- cell: ({ row }) => (
- <div>{row.getValue('LTEXT')}</div>
- ),
- },
- {
- accessorKey: 'DATAB',
- header: '시작일',
- cell: ({ row }) => (
- <div className="text-sm">{formatDate(row.getValue('DATAB'))}</div>
- ),
- },
- {
- accessorKey: 'DATBI',
- header: '종료일',
- cell: ({ row }) => (
- <div className="text-sm">{formatDate(row.getValue('DATBI'))}</div>
- ),
- },
- {
id: 'actions',
header: '선택',
cell: ({ row }) => {
@@ -283,7 +262,6 @@ export function CostCenterSingleSelector({
<div className="flex items-center gap-2 mt-1">
<span className="font-mono text-sm">[{currentSelectedCode.KOSTL}]</span>
<span>{currentSelectedCode.KTEXT}</span>
- <span className="text-muted-foreground">- {currentSelectedCode.LTEXT}</span>
</div>
</div>
)}
@@ -291,7 +269,7 @@ export function CostCenterSingleSelector({
<div className="flex items-center space-x-2">
<Search className="h-4 w-4" />
<Input
- placeholder="코스트센터 코드, 단축명, 설명으로 검색..."
+ placeholder="코스트센터 코드, 단축명으로 검색..."
value={globalFilter}
onChange={(e) => handleSearchChange(e.target.value)}
className="flex-1"
diff --git a/components/common/selectors/gl-account/gl-account-selector.tsx b/components/common/selectors/gl-account/gl-account-selector.tsx
index 7e47a072..63eeede8 100644
--- a/components/common/selectors/gl-account/gl-account-selector.tsx
+++ b/components/common/selectors/gl-account/gl-account-selector.tsx
@@ -5,9 +5,8 @@
*
* @description
* - 오라클에서 GL 계정들을 조회
- * - SAKNR: 계정(G/L)
- * - FIPEX: 세부계정
- * - TEXT1: 계정명
+ * - GL: 계정
+ * - GL명: 계정명
*/
import { useState, useCallback, useMemo, useTransition } from 'react'
@@ -52,7 +51,6 @@ export interface GlAccountSelectorProps {
export interface GlAccountItem {
saknr: string // 계정(G/L)
- fipex: string // 세부계정
text1: string // 계정명
displayText: string // 표시용 텍스트
}
@@ -76,7 +74,7 @@ export function GlAccountSelector({
// GL 계정 선택 핸들러
const handleCodeSelect = useCallback(async (code: GlAccount) => {
// 이미 선택된 계정을 다시 선택하면 선택 해제
- if (selectedCode && selectedCode.SAKNR === code.SAKNR && selectedCode.FIPEX === code.FIPEX) {
+ if (selectedCode && selectedCode.SAKNR === code.SAKNR) {
onCodeSelect(undefined as any) // 선택 해제를 위해 undefined 전달
setOpen(false)
return
@@ -101,13 +99,6 @@ export function GlAccountSelector({
),
},
{
- accessorKey: 'FIPEX',
- header: '세부계정',
- cell: ({ row }) => (
- <div className="font-mono text-sm">{row.getValue('FIPEX')}</div>
- ),
- },
- {
accessorKey: 'TEXT1',
header: '계정명',
cell: ({ row }) => (
@@ -206,7 +197,6 @@ export function GlAccountSelector({
{selectedCode ? (
<div className="flex items-center gap-2 w-full">
<span className="font-mono text-sm">[{selectedCode.SAKNR}]</span>
- <span className="font-mono text-sm">{selectedCode.FIPEX}</span>
<span className="truncate flex-1 text-left">{selectedCode.TEXT1}</span>
<Button
variant="ghost"
@@ -237,7 +227,7 @@ export function GlAccountSelector({
<div className="flex items-center space-x-2">
<Search className="h-4 w-4" />
<Input
- placeholder="계정, 세부계정, 계정명으로 검색..."
+ placeholder="계정, 계정명으로 검색..."
value={globalFilter}
onChange={(e) => handleSearchChange(e.target.value)}
className="flex-1"
@@ -284,7 +274,7 @@ export function GlAccountSelector({
)}
</TableCell>
))}
- {selectedCode && selectedCode.SAKNR === row.original.SAKNR && selectedCode.FIPEX === row.original.FIPEX && (
+ {selectedCode && selectedCode.SAKNR === row.original.SAKNR && (
<TableCell className="text-right">
<span className="text-xs text-muted-foreground">(선택됨)</span>
</TableCell>
diff --git a/components/common/selectors/gl-account/gl-account-service.ts b/components/common/selectors/gl-account/gl-account-service.ts
index 75c82c95..3feaf24a 100644
--- a/components/common/selectors/gl-account/gl-account-service.ts
+++ b/components/common/selectors/gl-account/gl-account-service.ts
@@ -5,17 +5,16 @@ import { oracleKnex } from '@/lib/oracle-db/db'
// GL 계정 타입 정의
export interface GlAccount {
SAKNR: string // 계정 (G/L)
- FIPEX: string // 세부계정
TEXT1: string // 계정명
}
// 테스트 환경용 폴백 데이터
const FALLBACK_TEST_DATA: GlAccount[] = [
- { SAKNR: '53351977', FIPEX: 'FIP001', TEXT1: '원재료 구매(테스트데이터 - 오라클 페칭 실패시)' },
- { SAKNR: '53351978', FIPEX: 'FIP002', TEXT1: '소모품 구매(테스트데이터 - 오라클 페칭 실패시)' },
- { SAKNR: '53351979', FIPEX: 'FIP003', TEXT1: '부품 구매(테스트데이터 - 오라클 페칭 실패시)' },
- { SAKNR: '53351980', FIPEX: 'FIP004', TEXT1: '자재 구매(테스트데이터 - 오라클 페칭 실패시)' },
- { SAKNR: '53351981', FIPEX: 'FIP005', TEXT1: '외주 가공비(테스트데이터 - 오라클 페칭 실패시)' },
+ { SAKNR: '53351977', TEXT1: '원재료 구매(테스트데이터 - 오라클 페칭 실패시)' },
+ { SAKNR: '53351978', TEXT1: '소모품 구매(테스트데이터 - 오라클 페칭 실패시)' },
+ { SAKNR: '53351979', TEXT1: '부품 구매(테스트데이터 - 오라클 페칭 실패시)' },
+ { SAKNR: '53351980', TEXT1: '자재 구매(테스트데이터 - 오라클 페칭 실패시)' },
+ { SAKNR: '53351981', TEXT1: '외주 가공비(테스트데이터 - 오라클 페칭 실패시)' },
]
/**
@@ -32,15 +31,10 @@ export async function getGlAccounts(): Promise<{
console.log('📋 [getGlAccounts] Oracle 쿼리 시작...')
const result = await oracleKnex.raw(`
- SELECT
- SAKNR,
- FIPEX,
- TEXT1"
- FROM CMCTB_BGT_MNG_ITM
- WHERE ROWNUM < 100
- AND BUKRS = 'H100'
- ORDER BY SAKNR
+ SELECT SAKNR , TEXT1 FROM CMCTB_BGT_MNG_ITM WHERE ROWNUM < 10
`)
+ // SAKNR -> GL
+ // TEXT1 -> GL명
// Oracle raw query의 결과는 rows 배열에 들어있음
const rows = (result.rows || result) as Array<Record<string, unknown>>
@@ -49,14 +43,12 @@ export async function getGlAccounts(): Promise<{
// null 값 필터링
const cleanedResult = rows
- .filter((item) =>
- item['계정(G/L)'] &&
- item['세부계정']
+ .filter((item) =>
+ item.SAKNR
)
.map((item) => ({
- SAKNR: String(item['계정(G/L)']),
- FIPEX: String(item['세부계정']),
- TEXT1: String(item['계정명'] || '')
+ SAKNR: String(item.SAKNR),
+ TEXT1: String(item.TEXT1 || '')
}))
console.log(`✅ [getGlAccounts] 필터링 후 ${cleanedResult.length}건`)
diff --git a/components/common/selectors/gl-account/gl-account-single-selector.tsx b/components/common/selectors/gl-account/gl-account-single-selector.tsx
index 55a58a1f..c3237043 100644
--- a/components/common/selectors/gl-account/gl-account-single-selector.tsx
+++ b/components/common/selectors/gl-account/gl-account-single-selector.tsx
@@ -77,7 +77,7 @@ export function GlAccountSingleSelector({
const handleCodeSelect = useCallback((code: GlAccount) => {
// 이미 선택된 계정을 다시 선택하면 선택 해제
const currentSelected = showConfirmButtons ? tempSelectedCode : selectedCode
- if (currentSelected && currentSelected.SAKNR === code.SAKNR && currentSelected.FIPEX === code.FIPEX) {
+ if (currentSelected && currentSelected.SAKNR === code.SAKNR) {
if (showConfirmButtons) {
setTempSelectedCode(undefined)
} else {
@@ -121,13 +121,6 @@ export function GlAccountSingleSelector({
),
},
{
- accessorKey: 'FIPEX',
- header: '세부계정',
- cell: ({ row }) => (
- <div className="font-mono text-sm">{row.getValue('FIPEX')}</div>
- ),
- },
- {
accessorKey: 'TEXT1',
header: '계정명',
cell: ({ row }) => (
@@ -262,8 +255,7 @@ export function GlAccountSingleSelector({
</div>
<div className="flex items-center gap-2 mt-1">
<span className="font-mono text-sm">[{currentSelectedCode.SAKNR}]</span>
- <span className="font-mono text-sm">{currentSelectedCode.FIPEX}</span>
- <span>- {currentSelectedCode.TEXT1}</span>
+ <span>{currentSelectedCode.TEXT1}</span>
</div>
</div>
)}
@@ -271,7 +263,7 @@ export function GlAccountSingleSelector({
<div className="flex items-center space-x-2">
<Search className="h-4 w-4" />
<Input
- placeholder="계정, 세부계정, 계정명으로 검색..."
+ placeholder="계정, 계정명으로 검색..."
value={globalFilter}
onChange={(e) => handleSearchChange(e.target.value)}
className="flex-1"
diff --git a/components/common/selectors/procurement-item/procurement-item-selector-dialog-single.tsx b/components/common/selectors/procurement-item/procurement-item-selector-dialog-single.tsx
index 90d4975b..84fd85ff 100644
--- a/components/common/selectors/procurement-item/procurement-item-selector-dialog-single.tsx
+++ b/components/common/selectors/procurement-item/procurement-item-selector-dialog-single.tsx
@@ -131,7 +131,7 @@ export function ProcurementItemSelectorDialogSingle({
<Button variant={triggerVariant} size={triggerSize}>
{selectedProcurementItem ? (
<span className="truncate">
- {`${selectedProcurementItem.itemCode} - ${selectedProcurementItem.itemName}`}
+ {`${selectedProcurementItem.itemCode}`}
</span>
) : (
<span className="text-muted-foreground">{triggerLabel}</span>
diff --git a/components/common/selectors/wbs-code/wbs-code-selector.tsx b/components/common/selectors/wbs-code/wbs-code-selector.tsx
index aa5a6a64..5356c723 100644
--- a/components/common/selectors/wbs-code/wbs-code-selector.tsx
+++ b/components/common/selectors/wbs-code/wbs-code-selector.tsx
@@ -5,10 +5,8 @@
*
* @description
* - 오라클에서 WBS 코드들을 조회
- * - PROJ_NO: 프로젝트 번호
* - WBS_ELMT: WBS 요소
* - WBS_ELMT_NM: WBS 요소명
- * - WBS_LVL: WBS 레벨
*/
import { useState, useCallback, useMemo, useTransition } from 'react'
@@ -49,7 +47,6 @@ export interface WbsCodeSelectorProps {
disabled?: boolean
placeholder?: string
className?: string
- projNo?: string // 프로젝트 번호 필터
}
export interface WbsCodeItem {
@@ -66,8 +63,7 @@ export function WbsCodeSelector({
onCodeSelect,
disabled,
placeholder = "WBS 코드를 선택하세요",
- className,
- projNo
+ className
}: WbsCodeSelectorProps) {
const [open, setOpen] = useState(false)
const [codes, setCodes] = useState<WbsCode[]>([])
@@ -81,7 +77,7 @@ export function WbsCodeSelector({
// WBS 코드 선택 핸들러
const handleCodeSelect = useCallback(async (code: WbsCode) => {
// 이미 선택된 코드를 다시 선택하면 선택 해제
- if (selectedCode && selectedCode.PROJ_NO === code.PROJ_NO && selectedCode.WBS_ELMT === code.WBS_ELMT) {
+ if (selectedCode && selectedCode.WBS_ELMT === code.WBS_ELMT) {
onCodeSelect(undefined as any) // 선택 해제를 위해 undefined 전달
setOpen(false)
return
@@ -99,34 +95,20 @@ export function WbsCodeSelector({
// 테이블 컬럼 정의
const columns: ColumnDef<WbsCode>[] = useMemo(() => [
{
- accessorKey: 'PROJ_NO',
- header: '프로젝트 번호',
- cell: ({ row }) => (
- <div className="font-mono text-sm">{row.getValue('PROJ_NO')}</div>
- ),
- },
- {
accessorKey: 'WBS_ELMT',
- header: 'WBS 요소',
+ header: 'WBS_ELMT',
cell: ({ row }) => (
<div className="font-mono text-sm">{row.getValue('WBS_ELMT')}</div>
),
},
{
accessorKey: 'WBS_ELMT_NM',
- header: 'WBS 요소명',
+ header: 'WBS_ELMT_NM',
cell: ({ row }) => (
<div>{row.getValue('WBS_ELMT_NM')}</div>
),
},
{
- accessorKey: 'WBS_LVL',
- header: '레벨',
- cell: ({ row }) => (
- <div className="text-center">{row.getValue('WBS_LVL')}</div>
- ),
- },
- {
id: 'actions',
header: '선택',
cell: ({ row }) => (
@@ -170,7 +152,7 @@ export function WbsCodeSelector({
const loadCodes = useCallback(async () => {
startTransition(async () => {
try {
- const result = await getWbsCodes(projNo)
+ const result = await getWbsCodes()
if (result.success) {
setCodes(result.data)
@@ -192,7 +174,7 @@ export function WbsCodeSelector({
setCodes([])
}
})
- }, [projNo])
+ }, [])
// 다이얼로그 열기 핸들러
const handleDialogOpenChange = useCallback((newOpen: boolean) => {
@@ -217,8 +199,7 @@ export function WbsCodeSelector({
>
{selectedCode ? (
<div className="flex items-center gap-2 w-full">
- <span className="font-mono text-sm">[{selectedCode.PROJ_NO}]</span>
- <span className="font-mono text-sm">{selectedCode.WBS_ELMT}</span>
+ <span className="font-mono text-sm">[{selectedCode.WBS_ELMT}]</span>
<span className="truncate flex-1 text-left">{selectedCode.WBS_ELMT_NM}</span>
<Button
variant="ghost"
@@ -249,7 +230,7 @@ export function WbsCodeSelector({
<div className="flex items-center space-x-2">
<Search className="h-4 w-4" />
<Input
- placeholder="프로젝트 번호, WBS 요소, WBS 요소명으로 검색..."
+ placeholder="WBS 요소, WBS 요소명으로 검색..."
value={globalFilter}
onChange={(e) => handleSearchChange(e.target.value)}
className="flex-1"
@@ -296,7 +277,7 @@ export function WbsCodeSelector({
)}
</TableCell>
))}
- {selectedCode && selectedCode.PROJ_NO === row.original.PROJ_NO && selectedCode.WBS_ELMT === row.original.WBS_ELMT && (
+ {selectedCode && selectedCode.WBS_ELMT === row.original.WBS_ELMT && (
<TableCell className="text-right">
<span className="text-xs text-muted-foreground">(선택됨)</span>
</TableCell>
diff --git a/components/common/selectors/wbs-code/wbs-code-service.ts b/components/common/selectors/wbs-code/wbs-code-service.ts
index 7d9c17b1..6ceedcb7 100644
--- a/components/common/selectors/wbs-code/wbs-code-service.ts
+++ b/components/common/selectors/wbs-code/wbs-code-service.ts
@@ -4,54 +4,35 @@ import { oracleKnex } from '@/lib/oracle-db/db'
// WBS 코드 타입 정의
export interface WbsCode {
- PROJ_NO: string // 프로젝트 번호
WBS_ELMT: string // WBS 요소
WBS_ELMT_NM: string // WBS 요소명
- WBS_LVL: string // WBS 레벨
}
// 테스트 환경용 폴백 데이터
const FALLBACK_TEST_DATA: WbsCode[] = [
- { PROJ_NO: 'SN2661', WBS_ELMT: 'WBS001', WBS_ELMT_NM: 'WBS 항목 1(테스트데이터 - 오라클 페칭 실패시)', WBS_LVL: '1' },
- { PROJ_NO: 'SN2661', WBS_ELMT: 'WBS002', WBS_ELMT_NM: 'WBS 항목 2(테스트데이터 - 오라클 페칭 실패시)', WBS_LVL: '2' },
- { PROJ_NO: 'SN2661', WBS_ELMT: 'WBS003', WBS_ELMT_NM: 'WBS 항목 3(테스트데이터 - 오라클 페칭 실패시)', WBS_LVL: '1' },
- { PROJ_NO: 'SN2661', WBS_ELMT: 'WBS004', WBS_ELMT_NM: 'WBS 항목 4(테스트데이터 - 오라클 페칭 실패시)', WBS_LVL: '2' },
- { PROJ_NO: 'SN2661', WBS_ELMT: 'WBS005', WBS_ELMT_NM: 'WBS 항목 5(테스트데이터 - 오라클 페칭 실패시)', WBS_LVL: '3' },
+ { WBS_ELMT: 'WBS001', WBS_ELMT_NM: 'WBS 항목 1' },
+ { WBS_ELMT: 'WBS002', WBS_ELMT_NM: 'WBS 항목 2' },
+ { WBS_ELMT: 'WBS003', WBS_ELMT_NM: 'WBS 항목 3' },
+ { WBS_ELMT: 'WBS004', WBS_ELMT_NM: 'WBS 항목 4' },
+ { WBS_ELMT: 'WBS005', WBS_ELMT_NM: 'WBS 항목 5' },
]
/**
* WBS 코드 목록 조회 (Oracle에서 전체 조회, 실패 시 폴백 데이터 사용)
* CMCTB_PROJ_WBS 테이블에서 조회
- * @param projNo - 프로젝트 번호 (선택적, 없으면 전체 조회)
*/
-export async function getWbsCodes(projNo?: string): Promise<{
+export async function getWbsCodes(): Promise<{
success: boolean
data: WbsCode[]
error?: string
isUsingFallback?: boolean
}> {
try {
- console.log('📋 [getWbsCodes] Oracle 쿼리 시작...', projNo ? `프로젝트: ${projNo}` : '전체')
+ console.log('📋 [getWbsCodes] Oracle 쿼리 시작...')
- let query = `
- SELECT
- PROJ_NO,
- WBS_ELMT,
- WBS_ELMT_NM,
- WBS_LVL
- FROM CMCTB_PROJ_WBS
- WHERE ROWNUM < 100
- `
-
- if (projNo) {
- query += ` AND PROJ_NO = :projNo`
- }
-
- query += ` ORDER BY PROJ_NO, WBS_ELMT`
-
- const result = projNo
- ? await oracleKnex.raw(query, { projNo })
- : await oracleKnex.raw(query)
+ const result = await oracleKnex.raw(`
+ SELECT WBS_ELMT,WBS_ELMT_NM FROM CMCTB_PROJ_WBS WHERE ROWNUM < 30 AND PROJ_NO = 'SN2673'
+ `)
// Oracle raw query의 결과는 rows 배열에 들어있음
const rows = (result.rows || result) as Array<Record<string, unknown>>
@@ -60,16 +41,13 @@ export async function getWbsCodes(projNo?: string): Promise<{
// null 값 필터링
const cleanedResult = rows
- .filter((item) =>
- item.PROJ_NO &&
- item.WBS_ELMT &&
+ .filter((item) =>
+ item.WBS_ELMT &&
item.WBS_ELMT_NM
)
.map((item) => ({
- PROJ_NO: String(item.PROJ_NO),
WBS_ELMT: String(item.WBS_ELMT),
- WBS_ELMT_NM: String(item.WBS_ELMT_NM),
- WBS_LVL: String(item.WBS_LVL || '')
+ WBS_ELMT_NM: String(item.WBS_ELMT_NM)
}))
console.log(`✅ [getWbsCodes] 필터링 후 ${cleanedResult.length}건`)
diff --git a/components/common/selectors/wbs-code/wbs-code-single-selector.tsx b/components/common/selectors/wbs-code/wbs-code-single-selector.tsx
index 77a32afe..5c84b8c2 100644
--- a/components/common/selectors/wbs-code/wbs-code-single-selector.tsx
+++ b/components/common/selectors/wbs-code/wbs-code-single-selector.tsx
@@ -49,7 +49,6 @@ export interface WbsCodeSingleSelectorProps {
title?: string
description?: string
showConfirmButtons?: boolean
- projNo?: string // 프로젝트 번호 필터
}
export function WbsCodeSingleSelector({
@@ -61,8 +60,7 @@ export function WbsCodeSingleSelector({
onCancel,
title = "WBS 코드 선택",
description = "WBS 코드를 선택하세요",
- showConfirmButtons = false,
- projNo
+ showConfirmButtons = false
}: WbsCodeSingleSelectorProps) {
const [codes, setCodes] = useState<WbsCode[]>([])
const [sorting, setSorting] = useState<SortingState>([])
@@ -77,7 +75,7 @@ export function WbsCodeSingleSelector({
const handleCodeSelect = useCallback((code: WbsCode) => {
// 이미 선택된 코드를 다시 선택하면 선택 해제
const currentSelected = showConfirmButtons ? tempSelectedCode : selectedCode
- if (currentSelected && currentSelected.WBS_ELMT === code.WBS_ELMT && currentSelected.PROJ_NO === code.PROJ_NO) {
+ if (currentSelected && currentSelected.WBS_ELMT === code.WBS_ELMT) {
if (showConfirmButtons) {
setTempSelectedCode(undefined)
} else {
@@ -114,40 +112,26 @@ export function WbsCodeSingleSelector({
// 테이블 컬럼 정의
const columns: ColumnDef<WbsCode>[] = useMemo(() => [
{
- accessorKey: 'PROJ_NO',
- header: '프로젝트 번호',
- cell: ({ row }) => (
- <div className="font-mono text-sm">{row.getValue('PROJ_NO')}</div>
- ),
- },
- {
accessorKey: 'WBS_ELMT',
- header: 'WBS 요소',
+ header: 'WBS_ELMT',
cell: ({ row }) => (
<div className="font-mono text-sm">{row.getValue('WBS_ELMT')}</div>
),
},
{
accessorKey: 'WBS_ELMT_NM',
- header: 'WBS 요소명',
+ header: 'WBS_ELMT_NM',
cell: ({ row }) => (
<div>{row.getValue('WBS_ELMT_NM')}</div>
),
},
{
- accessorKey: 'WBS_LVL',
- header: '레벨',
- cell: ({ row }) => (
- <div className="text-center">{row.getValue('WBS_LVL')}</div>
- ),
- },
- {
id: 'actions',
header: '선택',
cell: ({ row }) => {
const isSelected = showConfirmButtons
- ? tempSelectedCode?.WBS_ELMT === row.original.WBS_ELMT && tempSelectedCode?.PROJ_NO === row.original.PROJ_NO
- : selectedCode?.WBS_ELMT === row.original.WBS_ELMT && selectedCode?.PROJ_NO === row.original.PROJ_NO
+ ? tempSelectedCode?.WBS_ELMT === row.original.WBS_ELMT
+ : selectedCode?.WBS_ELMT === row.original.WBS_ELMT
return (
<Button
@@ -191,7 +175,7 @@ export function WbsCodeSingleSelector({
const loadCodes = useCallback(async () => {
startTransition(async () => {
try {
- const result = await getWbsCodes(projNo)
+ const result = await getWbsCodes()
if (result.success) {
setCodes(result.data)
@@ -213,7 +197,7 @@ export function WbsCodeSingleSelector({
setCodes([])
}
})
- }, [projNo])
+ }, [])
// 다이얼로그 열릴 때 코드 로드 (open prop 변화 감지)
useEffect(() => {
@@ -268,8 +252,7 @@ export function WbsCodeSingleSelector({
</Button>
</div>
<div className="flex items-center gap-2 mt-1">
- <span className="font-mono text-sm">[{currentSelectedCode.PROJ_NO}]</span>
- <span className="font-mono text-sm">{currentSelectedCode.WBS_ELMT}</span>
+ <span className="font-mono text-sm">[{currentSelectedCode.WBS_ELMT}]</span>
<span>{currentSelectedCode.WBS_ELMT_NM}</span>
</div>
</div>
@@ -278,7 +261,7 @@ export function WbsCodeSingleSelector({
<div className="flex items-center space-x-2">
<Search className="h-4 w-4" />
<Input
- placeholder="프로젝트 번호, WBS 요소, WBS 요소명으로 검색..."
+ placeholder="WBS 요소, WBS 요소명으로 검색..."
value={globalFilter}
onChange={(e) => handleSearchChange(e.target.value)}
className="flex-1"
@@ -311,8 +294,7 @@ export function WbsCodeSingleSelector({
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => {
- const isRowSelected = currentSelectedCode?.WBS_ELMT === row.original.WBS_ELMT &&
- currentSelectedCode?.PROJ_NO === row.original.PROJ_NO
+ const isRowSelected = currentSelectedCode?.WBS_ELMT === row.original.WBS_ELMT
return (
<TableRow
key={row.id}