diff options
Diffstat (limited to 'lib/general-contracts/main')
4 files changed, 126 insertions, 190 deletions
diff --git a/lib/general-contracts/main/create-general-contract-dialog.tsx b/lib/general-contracts/main/create-general-contract-dialog.tsx index 3eb8b11c..2c3fc8bc 100644 --- a/lib/general-contracts/main/create-general-contract-dialog.tsx +++ b/lib/general-contracts/main/create-general-contract-dialog.tsx @@ -24,7 +24,7 @@ import { CalendarIcon } from "lucide-react" import { format } from "date-fns"
import { ko } from "date-fns/locale"
import { cn } from "@/lib/utils"
-import { createContract, getVendors } from "@/lib/general-contracts/service"
+import { createContract, getVendors, getProjects } from "@/lib/general-contracts/service"
import {
GENERAL_CONTRACT_CATEGORIES,
GENERAL_CONTRACT_TYPES,
@@ -38,17 +38,12 @@ interface CreateContractForm { category: string
type: string
executionMethod: string
- selectionMethod: string
vendorId: number | null
+ projectId: number | null
startDate: Date | undefined
endDate: Date | undefined
validityEndDate: Date | undefined
- // contractScope: string
- // specificationType: string
notes: string
- linkedRfqOrItb: string
- linkedBidNumber: string
- linkedPoNumber: string
}
export function CreateGeneralContractDialog() {
@@ -57,24 +52,20 @@ export function CreateGeneralContractDialog() { const [open, setOpen] = React.useState(false)
const [isLoading, setIsLoading] = React.useState(false)
const [vendors, setVendors] = React.useState<Array<{ id: number; vendorName: string; vendorCode: string | null }>>([])
-
+ const [projects, setProjects] = React.useState<Array<{ id: number; code: string; name: string; type: string }>>([])
+
const [form, setForm] = React.useState<CreateContractForm>({
contractNumber: '',
name: '',
category: '',
type: '',
executionMethod: '',
- selectionMethod: '',
vendorId: null,
+ projectId: null,
startDate: undefined,
endDate: undefined,
validityEndDate: undefined,
- // contractScope: '',
- // specificationType: '',
notes: '',
- linkedRfqOrItb: '',
- linkedBidNumber: '',
- linkedPoNumber: '',
})
// 업체 목록 조회
@@ -90,6 +81,20 @@ export function CreateGeneralContractDialog() { fetchVendors()
}, [])
+ // 프로젝트 목록 조회
+ React.useEffect(() => {
+ const fetchProjects = async () => {
+ try {
+ const projectList = await getProjects()
+ console.log(projectList)
+ setProjects(projectList)
+ } catch (error) {
+ console.error('Error fetching projects:', error)
+ }
+ }
+ fetchProjects()
+ }, [])
+
const handleSubmit = async () => {
// 필수 필드 검증
if (!form.name || !form.category || !form.type || !form.executionMethod ||
@@ -111,23 +116,19 @@ export function CreateGeneralContractDialog() { category: form.category,
type: form.type,
executionMethod: form.executionMethod,
- selectionMethod: form.selectionMethod,
+ projectId: form.projectId,
+ contractSourceType: 'manual',
vendorId: form.vendorId!,
startDate: form.startDate!.toISOString().split('T')[0],
endDate: form.endDate!.toISOString().split('T')[0],
validityEndDate: (form.validityEndDate || form.endDate!).toISOString().split('T')[0],
- // contractScope: form.contractScope,
- // specificationType: form.specificationType,
status: 'Draft',
registeredById: session?.user?.id || 1,
lastUpdatedById: session?.user?.id || 1,
notes: form.notes,
- linkedRfqOrItb: form.linkedRfqOrItb,
- linkedBidNumber: form.linkedBidNumber,
- linkedPoNumber: form.linkedPoNumber,
}
- const newContract = await createContract(contractData)
+ await createContract(contractData)
toast.success("새 계약이 생성되었습니다.")
setOpen(false)
@@ -150,17 +151,12 @@ export function CreateGeneralContractDialog() { category: '',
type: '',
executionMethod: '',
- selectionMethod: '',
vendorId: null,
+ projectId: null,
startDate: undefined,
endDate: undefined,
validityEndDate: undefined,
- // contractScope: '',
- // specificationType: '',
notes: '',
- linkedRfqOrItb: '',
- linkedBidNumber: '',
- linkedPoNumber: '',
})
}
@@ -185,16 +181,6 @@ export function CreateGeneralContractDialog() { <div className="grid gap-4 py-4">
<div className="grid grid-cols-1 gap-4">
- {/* <div className="grid gap-2">
- <Label htmlFor="contractNumber">계약번호</Label>
- <Input
- id="contractNumber"
- value={form.contractNumber}
- onChange={(e) => setForm(prev => ({ ...prev, contractNumber: e.target.value }))}
- placeholder="자동 생성됩니다"
- />
- </div> */}
-
<div className="grid gap-2">
<Label htmlFor="name">계약명 *</Label>
<Input
@@ -214,11 +200,18 @@ export function CreateGeneralContractDialog() { <SelectValue placeholder="계약구분 선택" />
</SelectTrigger>
<SelectContent>
- {GENERAL_CONTRACT_CATEGORIES.map((category) => (
+ {GENERAL_CONTRACT_CATEGORIES.map((category) => {
+ const categoryLabels = {
+ 'unit_price': '단가계약',
+ 'general': '일반계약',
+ 'sale': '매각계약'
+ }
+ return (
<SelectItem key={category} value={category}>
- {category}
- </SelectItem>
- ))}
+ {category} - {categoryLabels[category as keyof typeof categoryLabels]}
+ </SelectItem>
+ )
+ })}
</SelectContent>
</Select>
</div>
@@ -276,6 +269,22 @@ export function CreateGeneralContractDialog() { </div>
<div className="grid gap-2">
+ <Label htmlFor="project">프로젝트</Label>
+ <Select value={form.projectId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, projectId: parseInt(value) }))}>
+ <SelectTrigger>
+ <SelectValue placeholder="프로젝트 선택 (선택사항)" />
+ </SelectTrigger>
+ <SelectContent>
+ {projects.map((project) => (
+ <SelectItem key={project.id} value={project.id.toString()}>
+ {project.name} ({project.code})
+ </SelectItem>
+ ))}
+ </SelectContent>
+ </Select>
+ </div>
+
+ <div className="grid gap-2">
<Label htmlFor="vendor">협력업체 *</Label>
<Select value={form.vendorId?.toString()} onValueChange={(value) => setForm(prev => ({ ...prev, vendorId: parseInt(value) }))}>
<SelectTrigger>
@@ -370,71 +379,6 @@ export function CreateGeneralContractDialog() { </Popover>
</div>
</div>
-
- {/* <div className="grid grid-cols-2 gap-4">
- <div className="grid gap-2">
- <Label htmlFor="contractScope">계약확정범위 *</Label>
- <Select value={form.contractScope} onValueChange={(value) => setForm(prev => ({ ...prev, contractScope: value }))}>
- <SelectTrigger>
- <SelectValue placeholder="계약확정범위 선택" />
- </SelectTrigger>
- <SelectContent>
- {GENERAL_CONTRACT_SCOPES.map((scope) => (
- <SelectItem key={scope} value={scope}>
- {scope}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="specificationType">사양 *</Label>
- <Select value={form.specificationType} onValueChange={(value) => setForm(prev => ({ ...prev, specificationType: value }))}>
- <SelectTrigger>
- <SelectValue placeholder="사양 선택" />
- </SelectTrigger>
- <SelectContent>
- <SelectItem value="첨부파일">첨부파일</SelectItem>
- <SelectItem value="직접입력">직접입력</SelectItem>
- <SelectItem value="기타">기타</SelectItem>
- </SelectContent>
- </Select>
- </div>
- </div> */}
-
- <div className="grid grid-cols-2 gap-4">
- <div className="grid gap-2">
- <Label htmlFor="linkedRfqOrItb">연계 견적/입찰번호</Label>
- <Input
- id="linkedRfqOrItb"
- value={form.linkedRfqOrItb}
- onChange={(e) => setForm(prev => ({ ...prev, linkedRfqOrItb: e.target.value }))}
- placeholder="연계 견적/입찰번호를 입력하세요"
- />
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="linkedBidNumber">연계 BID번호</Label>
- <Input
- id="linkedBidNumber"
- value={form.linkedBidNumber}
- onChange={(e) => setForm(prev => ({ ...prev, linkedBidNumber: e.target.value }))}
- placeholder="연계 BID번호를 입력하세요"
- />
- </div>
- </div>
-
- <div className="grid gap-2">
- <Label htmlFor="linkedPoNumber">연계PO번호</Label>
- <Input
- id="linkedPoNumber"
- value={form.linkedPoNumber}
- onChange={(e) => setForm(prev => ({ ...prev, linkedPoNumber: e.target.value }))}
- placeholder="연계PO번호를 입력하세요"
- />
- </div>
-
<div className="grid gap-2">
<Label htmlFor="notes">비고</Label>
<Textarea
diff --git a/lib/general-contracts/main/general-contract-update-sheet.tsx b/lib/general-contracts/main/general-contract-update-sheet.tsx index 064fded3..54f4ae4e 100644 --- a/lib/general-contracts/main/general-contract-update-sheet.tsx +++ b/lib/general-contracts/main/general-contract-update-sheet.tsx @@ -83,8 +83,6 @@ export function GeneralContractUpdateSheet({ endDate: "", validityEndDate: "", contractScope: "", - specificationType: "", - specificationManualText: "", notes: "", linkedRfqOrItb: "", linkedPoNumber: "", @@ -109,8 +107,6 @@ export function GeneralContractUpdateSheet({ endDate: contract.endDate || "", validityEndDate: contract.validityEndDate || "", contractScope: contract.contractScope || "", - specificationType: contract.specificationType || "", - specificationManualText: contract.specificationManualText || "", notes: contract.notes || "", linkedRfqOrItb: contract.linkedRfqOrItb || "", linkedPoNumber: contract.linkedPoNumber || "", @@ -136,8 +132,6 @@ export function GeneralContractUpdateSheet({ endDate: data.endDate, validityEndDate: data.validityEndDate, contractScope: data.contractScope, - specificationType: data.specificationType, - specificationManualText: data.specificationManualText, notes: data.notes, linkedRfqOrItb: data.linkedRfqOrItb, linkedPoNumber: data.linkedPoNumber, @@ -185,11 +179,17 @@ export function GeneralContractUpdateSheet({ </SelectTrigger> </FormControl> <SelectContent> - {GENERAL_CONTRACT_CATEGORIES.map((category) => ( + {GENERAL_CONTRACT_CATEGORIES.map((category) => { + const categoryLabels = { + 'unit_price': '단가계약', + 'general': '일반계약', + 'sale': '매각계약' + } + return ( <SelectItem key={category} value={category}> - {category} + {category} - {categoryLabels[category as keyof typeof categoryLabels]} </SelectItem> - ))} + )})} </SelectContent> </Select> <FormMessage /> @@ -211,11 +211,29 @@ export function GeneralContractUpdateSheet({ </SelectTrigger> </FormControl> <SelectContent> - {GENERAL_CONTRACT_TYPES.map((type) => ( + {GENERAL_CONTRACT_TYPES.map((type) => { + const typeLabels = { + 'UP': '자재단가계약', + 'LE': '임대차계약', + 'IL': '개별운송계약', + 'AL': '연간운송계약', + 'OS': '외주용역계약', + 'OW': '도급계약', + 'IS': '검사계약', + 'LO': 'LOI', + 'FA': 'FA', + 'SC': '납품합의계약', + 'OF': '클레임상계계약', + 'AW': '사전작업합의', + 'AD': '사전납품합의', + 'AM': '설계계약', + 'SC_SELL': '폐기물매각계약' + } + return ( <SelectItem key={type} value={type}> - {type} + {type} - {typeLabels[type as keyof typeof typeLabels]} </SelectItem> - ))} + )})} </SelectContent> </Select> <FormMessage /> @@ -237,11 +255,16 @@ export function GeneralContractUpdateSheet({ </SelectTrigger> </FormControl> <SelectContent> - {GENERAL_EXECUTION_METHODS.map((method) => ( + {GENERAL_EXECUTION_METHODS.map((method) => { + const methodLabels = { + '전자계약': '전자계약', + '오프라인계약': '오프라인계약' + } + return ( <SelectItem key={method} value={method}> - {method} + {method} - {methodLabels[method as keyof typeof methodLabels]} </SelectItem> - ))} + )})} </SelectContent> </Select> <FormMessage /> @@ -336,51 +359,6 @@ export function GeneralContractUpdateSheet({ )} /> - {/* 연계 견적/입찰번호 */} - <FormField - control={form.control} - name="linkedRfqOrItb" - render={({ field }) => ( - <FormItem> - <FormLabel>연계 견적/입찰번호</FormLabel> - <FormControl> - <Input placeholder="연계 견적/입찰번호를 입력하세요" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 연계 PO번호 */} - <FormField - control={form.control} - name="linkedPoNumber" - render={({ field }) => ( - <FormItem> - <FormLabel>연계 PO번호</FormLabel> - <FormControl> - <Input placeholder="연계 PO번호를 입력하세요" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - - {/* 연계 BID번호 */} - <FormField - control={form.control} - name="linkedBidNumber" - render={({ field }) => ( - <FormItem> - <FormLabel>연계 BID번호</FormLabel> - <FormControl> - <Input placeholder="연계 BID번호를 입력하세요" {...field} /> - </FormControl> - <FormMessage /> - </FormItem> - )} - /> - {/* 비고 */} <FormField control={form.control} diff --git a/lib/general-contracts/main/general-contracts-table-columns.tsx b/lib/general-contracts/main/general-contracts-table-columns.tsx index d7854ee6..a08d8b81 100644 --- a/lib/general-contracts/main/general-contracts-table-columns.tsx +++ b/lib/general-contracts/main/general-contracts-table-columns.tsx @@ -12,7 +12,6 @@ import { DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
- DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { DataTableColumnHeaderSimple } from "@/components/data-table/data-table-column-simple-header"
@@ -29,7 +28,7 @@ export interface GeneralContractListItem { type: string
executionMethod: string
name: string
- selectionMethod?: string
+ contractSourceType?: string
startDate: string
endDate: string
validityEndDate?: string
@@ -49,6 +48,9 @@ export interface GeneralContractListItem { vendorId?: number
vendorName?: string
vendorCode?: string
+ projectId?: number
+ projectName?: string
+ projectCode?: string
managerName?: string
lastUpdatedByName?: string
}
@@ -110,11 +112,11 @@ const getStatusText = (status: string) => { // 계약구분 텍스트 변환
const getCategoryText = (category: string) => {
switch (category) {
- case '단가계약':
+ case 'unit_price':
return '단가계약'
- case '일반계약':
+ case 'general':
return '일반계약'
- case '매각계약':
+ case 'sale':
return '매각계약'
default:
return category
@@ -172,15 +174,15 @@ const getExecutionMethodText = (method: string) => { }
// 업체선정방법 텍스트 변환
-const getSelectionMethodText = (method?: string) => {
+const getcontractSourceTypeText = (method?: string) => {
if (!method) return '-'
switch (method) {
- case '견적':
+ case 'estimate':
return '견적'
- case '입찰':
+ case 'bid':
return '입찰'
- case '기타':
- return '기타'
+ case 'manual':
+ return '자체생성'
default:
return method
}
@@ -325,12 +327,12 @@ export function getGeneralContractsColumns({ setRowAction }: GetColumnsProps): C },
{
- accessorKey: "selectionMethod",
+ accessorKey: "contractSourceType",
header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="업체선정방법" />,
cell: ({ row }) => (
- <span className="text-sm">
- {getSelectionMethodText(row.original.selectionMethod)}
- </span>
+ <Badge variant="outline">
+ {getcontractSourceTypeText(row.original.contractSourceType)}
+ </Badge>
),
size: 200,
meta: { excelHeader: "업체선정방법" },
@@ -359,6 +361,21 @@ export function getGeneralContractsColumns({ setRowAction }: GetColumnsProps): C meta: { excelHeader: "협력업체명" },
},
+ {
+ accessorKey: "projectName",
+ header: ({ column }) => <DataTableColumnHeaderSimple column={column} title="프로젝트명" />,
+ cell: ({ row }) => (
+ <div className="flex flex-col">
+ <span className="font-medium">{row.original.projectName || '-'}</span>
+ <span className="text-xs text-muted-foreground">
+ {row.original.projectCode ? row.original.projectCode : "-"}
+ </span>
+ </div>
+ ),
+ size: 150,
+ meta: { excelHeader: "프로젝트명" },
+ },
+
]
},
diff --git a/lib/general-contracts/main/general-contracts-table.tsx b/lib/general-contracts/main/general-contracts-table.tsx index 962bb61e..e4c96ee3 100644 --- a/lib/general-contracts/main/general-contracts-table.tsx +++ b/lib/general-contracts/main/general-contracts-table.tsx @@ -16,11 +16,7 @@ import { getGeneralContracts, getGeneralContractStatusCounts } from "@/lib/gener import { GeneralContractsTableToolbarActions } from "./general-contracts-table-toolbar-actions"
import { GeneralContractUpdateSheet } from "./general-contract-update-sheet"
import {
- GENERAL_CONTRACT_STATUSES,
- GENERAL_CONTRACT_CATEGORIES,
- GENERAL_CONTRACT_TYPES,
- GENERAL_EXECUTION_METHODS,
- GENERAL_SELECTION_METHODS
+ GENERAL_EXECUTION_METHODS
} from "@/lib/general-contracts/types"
// 상태 라벨 매핑
@@ -155,13 +151,14 @@ export function GeneralContractsTable({ promises }: GeneralContractsTableProps) })),
},
{
- id: "selectionMethod",
+ id: "contractSourceType",
label: "업체선정방법",
type: "select",
- options: GENERAL_SELECTION_METHODS.map(value => ({
- label: value,
- value: value,
- })),
+ options: [
+ { label: "estimate", value: "견적" },
+ { label: "bid", value: "입찰" },
+ { label: "manual", value: "자체생성" },
+ ],
},
{ id: "registeredAt", label: "계약등록일", type: "date" },
{ id: "signedAt", label: "계약체결일", type: "date" },
|
