From fd542b5ad4bf94b82d872f87b96aa2e7514ffbc3 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Fri, 19 Sep 2025 09:40:38 +0000 Subject: (최겸) 구매 일반계약 수정, 견적 입찰 계약 세금코드 select 적용 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/general-contract-basic-info.tsx | 29 ++++--- lib/general-contracts/service.ts | 99 +++++++++++++++++++--- 2 files changed, 105 insertions(+), 23 deletions(-) (limited to 'lib/general-contracts') diff --git a/lib/general-contracts/detail/general-contract-basic-info.tsx b/lib/general-contracts/detail/general-contract-basic-info.tsx index 882ed8b2..d891fe63 100644 --- a/lib/general-contracts/detail/general-contract-basic-info.tsx +++ b/lib/general-contracts/detail/general-contract-basic-info.tsx @@ -15,6 +15,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { GeneralContract } from '@/db/schema' import { ContractDocuments } from './general-contract-documents' import { getPaymentTermsForSelection, getIncotermsForSelection, getPlaceOfShippingForSelection, getPlaceOfDestinationForSelection } from '@/lib/procurement-select/service' +import { TAX_CONDITIONS, getTaxConditionName } from '@/lib/tax-conditions/types' interface ContractBasicInfoProps { contractId: number @@ -46,7 +47,7 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { 작업후: { enabled: false, period: 0, maxPeriod: 0 }, 기타: { enabled: false, period: 0, maxPeriod: 0 }, }, - contractAmount: null, + contractAmount: null as number | null, currency: 'KRW', linkedPoNumber: '', linkedBidNumber: '', @@ -57,7 +58,7 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { paymentAfterDelivery: {} as any, paymentTerm: '', taxType: '', - liquidatedDamages: false, + liquidatedDamages: false as boolean, liquidatedDamagesPercent: '', deliveryType: '', deliveryTerm: '', @@ -130,7 +131,7 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { 작업후: { enabled: false, period: 0, maxPeriod: 0 }, 기타: { enabled: false, period: 0, maxPeriod: 0 }, }, - contractAmount: contractData?.contractAmount || null as number | null, + contractAmount: contractData?.contractAmount || null, currency: contractData?.currency || 'KRW', linkedPoNumber: contractData?.linkedPoNumber || '', linkedBidNumber: contractData?.linkedBidNumber || '', @@ -141,7 +142,7 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) { paymentAfterDelivery: paymentAfterDelivery || {} as any, paymentTerm: contractData?.paymentTerm || '', taxType: contractData?.taxType || '', - liquidatedDamages: contractData?.liquidatedDamages || false, + liquidatedDamages: Boolean(contractData?.liquidatedDamages), liquidatedDamagesPercent: contractData?.liquidatedDamagesPercent || '', deliveryType: contractData?.deliveryType || '', deliveryTerm: contractData?.deliveryTerm || '', @@ -838,13 +839,21 @@ export function ContractBasicInfo({ contractId }: ContractBasicInfoProps) {
- setFormData(prev => ({ ...prev, taxType: e.target.value }))} - placeholder="세금조건을 입력하세요" - className={errors.taxType ? 'border-red-500' : ''} - /> + onValueChange={(value) => setFormData(prev => ({ ...prev, taxType: value }))} + > + + + + + {TAX_CONDITIONS.map((condition) => ( + + {condition.name} + + ))} + + {errors.taxType && (

세금조건은 필수값입니다.

)} diff --git a/lib/general-contracts/service.ts b/lib/general-contracts/service.ts index 52301dae..2422706a 100644 --- a/lib/general-contracts/service.ts +++ b/lib/general-contracts/service.ts @@ -11,6 +11,7 @@ import { basicContract, basicContractTemplates } from '@/db/schema/basicContract import { vendors } from '@/db/schema/vendors' import { users } from '@/db/schema/users' import { projects } from '@/db/schema/projects' +import { items } from '@/db/schema/items' import { filterColumns } from '@/lib/filter-columns' import { saveDRMFile } from '@/lib/file-stroage' import { decryptWithServerAction } from '@/components/drm/drmUtils' @@ -1312,13 +1313,73 @@ export async function sendContractApprovalRequest( const contractId = newContract.id + // const items: { + // id: number; + // createdAt: Date; + // updatedAt: Date; + // contractId: number; + // itemCode: string | null; + // quantity: string | null; + // contractAmount: string | null; + // contractCurrency: string | null; + // contractDeliveryDate: string | null; + // specification: string | null; + // itemInfo: string | null; + // quantityUnit: string | null; + // totalWeight: string | null; + // weightUnit: string | null; + // contractUnitPrice: string | null; + // }[] + // contractItems 테이블에 품목 정보 저장 (general-contract-items가 있을 때만) if (contractSummary.items && contractSummary.items.length > 0) { - // 새 품목 추가 + const projectNo = contractSummary.basicInfo?.projectCode || contractSummary.basicInfo?.projectId?.toString() || 'NULL' + for (const item of contractSummary.items) { + let itemId: number + + // 1. items 테이블에서 itemCode로 기존 아이템 검색 + if (item.itemCode) { + // const existingItem = await db + // .select({ id: items.id }) + // .from(items) + // .where(and( + // eq(items.itemCode, item.itemCode), + // eq(items.ProjectNo, projectNo) + // )) + // .limit(1) + const existingItem = await db + .select({ id: items.id }) + .from(items) + .where( + eq(items.itemCode, item.itemCode) + ) + .limit(1) + + if (existingItem.length > 0) { + // 기존 아이템이 있으면 해당 ID 사용 + itemId = existingItem[0].id + } else { + // 기존 아이템이 없으면 새로 생성 + const newItem = await db.insert(items).values({ + ProjectNo: projectNo, + itemCode: item.itemCode, + itemName: item.itemInfo || item.description || item.itemCode, + packageCode: item.itemCode, + description: item.specification || item.description || '', + unitOfMeasure: item.quantityUnit || 'EA', + createdAt: new Date(), + updatedAt: new Date(), + }).returning({ id: items.id }) + + itemId = newItem[0].id + } + + + // 2. contractItems에 저장 await db.insert(contractItems).values({ contractId, - itemId: item.itemId || 2602, // 기본값 설정 + itemId: itemId, description: item.itemInfo || item.description || '', quantity: Math.floor(Number(item.quantity) || 1), // 정수로 변환 unitPrice: item.contractUnitPrice || item.unitPrice || 0, @@ -1327,6 +1388,10 @@ export async function sendContractApprovalRequest( totalLineAmount: item.contractAmount || item.totalLineAmount || 0, remark: item.remark || '', }) + }else{ + //아이템코드가 없으니 pass + continue + } } } @@ -1409,21 +1474,29 @@ export async function sendContractApprovalRequest( language: "ko", }, }) + // 계약 상태 업데이트 + await db.update(generalContracts) + .set({ + status: 'Contract Accept Request', + lastUpdatedAt: new Date() + }) + .where(eq(generalContracts.id, generalContractId)) + } catch (error) { console.error('계약승인요청 전송 오류:', error) - + } - //계약상태변경 - revalidatePath('/evcp/general-contracts') - revalidatePath('/evcp/general-contracts/detail') - revalidatePath('/evcp/general-contracts/detail/contract-approval-request-dialog') - revalidatePath('/evcp/general-contracts/detail/contract-approval-request-dialog') - return { - success: true, - message: '계약승인요청이 성공적으로 전송되었습니다.', - pdfPath: saveResult.publicPath - } + + revalidatePath('/evcp/general-contracts') + revalidatePath('/evcp/general-contracts/detail') + revalidatePath('/evcp/general-contracts/detail/contract-approval-request-dialog') + + return { + success: true, + message: '계약승인요청이 성공적으로 전송되었습니다.', + pdfPath: saveResult.publicPath + } } catch (error: any) { console.error('계약승인요청 전송 오류:', error) -- cgit v1.2.3