summaryrefslogtreecommitdiff
path: root/lib/general-contracts/main
diff options
context:
space:
mode:
Diffstat (limited to 'lib/general-contracts/main')
-rw-r--r--lib/general-contracts/main/create-general-contract-dialog.tsx156
-rw-r--r--lib/general-contracts/main/general-contract-update-sheet.tsx98
-rw-r--r--lib/general-contracts/main/general-contracts-table-columns.tsx45
-rw-r--r--lib/general-contracts/main/general-contracts-table.tsx17
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" },