From 25749225689c3934bc10ad1e8285e13020b61282 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 4 Dec 2025 09:04:09 +0000 Subject: (최겸)구매 입찰, 계약 수정 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/general-contract-basic-info.tsx | 478 +++++++++++++++------ .../detail/general-contract-items-table.tsx | 43 +- 2 files changed, 394 insertions(+), 127 deletions(-) (limited to 'lib/general-contracts/detail') diff --git a/lib/general-contracts/detail/general-contract-basic-info.tsx b/lib/general-contracts/detail/general-contract-basic-info.tsx index b0378912..d7533d2e 100644 --- a/lib/general-contracts/detail/general-contract-basic-info.tsx +++ b/lib/general-contracts/detail/general-contract-basic-info.tsx @@ -8,7 +8,21 @@ import { Label } from '@/components/ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Textarea } from '@/components/ui/textarea' import { Button } from '@/components/ui/button' -import { Save, LoaderIcon } from 'lucide-react' +import { Save, LoaderIcon, Check, ChevronsUpDown } from 'lucide-react' +import { + Popover, + PopoverContent, + PopoverTrigger, +} from '@/components/ui/popover' +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@/components/ui/command' +import { cn } from '@/lib/utils' import { updateContractBasicInfo, getContractBasicInfo } from '../service' import { toast } from 'sonner' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' @@ -140,19 +154,28 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { // paymentDelivery에서 퍼센트와 타입 분리 const paymentDeliveryValue = contractData?.paymentDelivery || '' + console.log(paymentDeliveryValue,"paymentDeliveryValue") let paymentDeliveryType = '' let paymentDeliveryPercentValue = '' - if (paymentDeliveryValue.includes('%')) { + // "60일 이내" 또는 "추가조건"은 그대로 사용 + if (paymentDeliveryValue === '납품완료일로부터 60일 이내 지급' || paymentDeliveryValue === '추가조건') { + paymentDeliveryType = paymentDeliveryValue + } else if (paymentDeliveryValue.includes('%')) { + // 퍼센트가 포함된 경우 (예: "10% L/C") const match = paymentDeliveryValue.match(/(\d+)%\s*(.+)/) if (match) { paymentDeliveryPercentValue = match[1] paymentDeliveryType = match[2] + } else { + paymentDeliveryType = paymentDeliveryValue } } else { + // 일반 지급조건 코드 (예: "P008") paymentDeliveryType = paymentDeliveryValue } - + console.log(paymentDeliveryType,"paymentDeliveryType") + console.log(paymentDeliveryPercentValue,"paymentDeliveryPercentValue") setPaymentDeliveryPercent(paymentDeliveryPercentValue) // 합의계약(AD, AW)인 경우 인도조건 기본값 설정 @@ -309,6 +332,7 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { loadShippingPlaces(); loadDestinationPlaces(); }, [loadPaymentTerms, loadIncoterms, loadShippingPlaces, loadDestinationPlaces]); + const handleSaveContractInfo = async () => { if (!userId) { toast.error('사용자 정보를 찾을 수 없습니다.') @@ -342,12 +366,29 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { return } - // paymentDelivery와 paymentDeliveryPercent 합쳐서 저장 + // paymentDelivery 저장 로직 + // 1. "60일 이내" 또는 "추가조건"은 그대로 저장 + // 2. L/C 또는 T/T이고 퍼센트가 있으면 "퍼센트% 코드" 형식으로 저장 + // 3. 그 외의 경우는 그대로 저장 + let paymentDeliveryToSave = formData.paymentDelivery + + if ( + formData.paymentDelivery !== '납품완료일로부터 60일 이내 지급' && + formData.paymentDelivery !== '추가조건' && + (formData.paymentDelivery === 'L/C' || formData.paymentDelivery === 'T/T') && + paymentDeliveryPercent + ) { + paymentDeliveryToSave = `${paymentDeliveryPercent}% ${formData.paymentDelivery}` + } + console.log(paymentDeliveryToSave,"paymentDeliveryToSave") + const dataToSave = { ...formData, - paymentDelivery: (formData.paymentDelivery === 'L/C' || formData.paymentDelivery === 'T/T') && paymentDeliveryPercent - ? `${paymentDeliveryPercent}% ${formData.paymentDelivery}` - : formData.paymentDelivery + paymentDelivery: paymentDeliveryToSave, + // 추가조건 선택 시에만 추가 텍스트 저장, 그 외에는 빈 문자열 또는 undefined + paymentDeliveryAdditionalText: formData.paymentDelivery === '추가조건' + ? (formData.paymentDeliveryAdditionalText || '') + : '' } await updateContractBasicInfo(contractId, dataToSave, userId as number) @@ -1026,20 +1067,100 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) {
- + + + + + + + + + 검색 결과가 없습니다. + + {paymentTermsOptions.map((option) => ( + { + setFormData(prev => ({ ...prev, paymentDelivery: option.code })) + }} + > + + {option.code} {option.description && `(${option.description})`} + + ))} + { + setFormData(prev => ({ ...prev, paymentDelivery: '납품완료일로부터 60일 이내 지급' })) + }} + > + + 60일 이내 + + { + setFormData(prev => ({ ...prev, paymentDelivery: '추가조건' })) + }} + > + + 추가조건 + + + + + + {formData.paymentDelivery === '추가조건' && (
- {/* 지불조건 -> 세금조건 (지불조건 삭제됨) */} + {/*세금조건*/}
- {/* 지불조건 필드 삭제됨 -
- - -
- */}
- + + + + + + + + + 검색 결과가 없습니다. + + {TAX_CONDITIONS.map((condition) => ( + { + setFormData(prev => ({ ...prev, taxType: condition.code })) + }} + > + + {condition.name} + + ))} + + + + +
@@ -1266,79 +1393,178 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { {/* 인도조건 */}
- + + + + + + + + + 검색 결과가 없습니다. + + {incotermsOptions.length > 0 ? ( + incotermsOptions.map((option) => ( + { + setFormData(prev => ({ ...prev, deliveryTerm: option.code })) + }} + > + + {option.code} {option.description && `(${option.description})`} + + )) + ) : ( + + 로딩중... + + )} + + + + +
{/* 선적지 */}
- + + + + + + + + + 검색 결과가 없습니다. + + {shippingPlaces.length > 0 ? ( + shippingPlaces.map((place) => ( + { + setFormData(prev => ({ ...prev, shippingLocation: place.code })) + }} + > + + {place.code} {place.description && `(${place.description})`} + + )) + ) : ( + + 로딩중... + + )} + + + + +
{/* 하역지 */}
- + + + + + + + + + 검색 결과가 없습니다. + + {destinationPlaces.length > 0 ? ( + destinationPlaces.map((place) => ( + { + setFormData(prev => ({ ...prev, dischargeLocation: place.code })) + }} + > + + {place.code} {place.description && `(${place.description})`} + + )) + ) : ( + + 로딩중... + + )} + + + + +
{/* 계약납기일 */} diff --git a/lib/general-contracts/detail/general-contract-items-table.tsx b/lib/general-contracts/detail/general-contract-items-table.tsx index 15e5c926..e5fc6cf2 100644 --- a/lib/general-contracts/detail/general-contract-items-table.tsx +++ b/lib/general-contracts/detail/general-contract-items-table.tsx @@ -30,6 +30,8 @@ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from import { ProjectSelector } from '@/components/ProjectSelector' import { MaterialGroupSelectorDialogSingle } from '@/components/common/material/material-group-selector-dialog-single' import { MaterialSearchItem } from '@/lib/material/material-group-service' +import { ProcurementItemSelectorDialogSingle } from '@/components/common/selectors/procurement-item/procurement-item-selector-dialog-single' +import { ProcurementSearchItem } from '@/components/common/selectors/procurement-item/procurement-item-service' interface ContractItem { id?: number @@ -174,7 +176,7 @@ export function ContractItemsTable({ const errors: string[] = [] for (let index = 0; index < localItems.length; index++) { const item = localItems[index] - if (!item.itemCode) errors.push(`${index + 1}번째 품목의 품목코드`) + // if (!item.itemCode) errors.push(`${index + 1}번째 품목의 품목코드`) if (!item.itemInfo) errors.push(`${index + 1}번째 품목의 Item 정보`) if (!item.quantity || item.quantity <= 0) errors.push(`${index + 1}번째 품목의 수량`) if (!item.contractUnitPrice || item.contractUnitPrice <= 0) errors.push(`${index + 1}번째 품목의 단가`) @@ -271,6 +273,34 @@ export function ContractItemsTable({ onItemsChange(updatedItems) } + // 1회성 품목 선택 시 행 추가 + const handleOneTimeItemSelect = (item: ProcurementSearchItem | null) => { + if (!item) return + + const newItem: ContractItem = { + projectId: null, + itemCode: item.itemCode, + itemInfo: item.itemName, + materialGroupCode: '', + materialGroupDescription: '', + specification: item.specification || '', + quantity: 0, + quantityUnit: item.unit || 'EA', + totalWeight: 0, + weightUnit: 'KG', + contractDeliveryDate: '', + contractUnitPrice: 0, + contractAmount: 0, + contractCurrency: 'KRW', + isSelected: false + } + + const updatedItems = [...localItems, newItem] + setLocalItems(updatedItems) + onItemsChange(updatedItems) + toast.success('1회성 품목이 추가되었습니다.') + } + // 일괄입력 적용 const applyBatchInput = () => { if (localItems.length === 0) { @@ -382,6 +412,17 @@ export function ContractItemsTable({ 행 추가 +