summaryrefslogtreecommitdiff
path: root/lib/rfq-last/vendor-response
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-11-04 10:03:32 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-11-04 10:03:32 +0000
commit47fb72704161b4b58a27c7f5c679fc44618de9a1 (patch)
treeaf4fe1517352784d1876c164171f6dba2e40403a /lib/rfq-last/vendor-response
parent1a034c7f6f50e443bc9f97c3d84bfb0a819af6ce (diff)
(최겸) 구매 견적 내 RFQ Cancel/Delete, 연동제 적용, MRC Type 개발
Diffstat (limited to 'lib/rfq-last/vendor-response')
-rw-r--r--lib/rfq-last/vendor-response/editor/commercial-terms-form.tsx271
-rw-r--r--lib/rfq-last/vendor-response/editor/vendor-response-editor.tsx63
2 files changed, 312 insertions, 22 deletions
diff --git a/lib/rfq-last/vendor-response/editor/commercial-terms-form.tsx b/lib/rfq-last/vendor-response/editor/commercial-terms-form.tsx
index b8b3a830..f479b48d 100644
--- a/lib/rfq-last/vendor-response/editor/commercial-terms-form.tsx
+++ b/lib/rfq-last/vendor-response/editor/commercial-terms-form.tsx
@@ -707,29 +707,256 @@ export default function CommercialTermsForm({ rfqDetail, rfq }: CommercialTermsF
{/* 연동제 적용 */}
{rfqDetail.materialPriceRelatedYn && (
- <div className="space-y-4">
- <div className="flex items-center justify-between">
- <Label>연동제 적용 요청</Label>
- <Badge variant="secondary">요청됨</Badge>
- </div>
- <div className="flex items-center space-x-2">
- <Checkbox
- id="vendorMaterialPriceRelatedYn"
- checked={vendorMaterialPriceRelatedYn}
- onCheckedChange={(checked) => setValue("vendorMaterialPriceRelatedYn", checked)}
- />
- <Label htmlFor="vendorMaterialPriceRelatedYn">연동제 적용 동의</Label>
+ <>
+ <div className="space-y-4">
+ <div className="flex items-center justify-between">
+ <Label>연동제 적용 요청</Label>
+ <Badge variant="secondary">요청됨</Badge>
+ </div>
+ <div className="flex items-center space-x-2">
+ <Checkbox
+ id="vendorMaterialPriceRelatedYn"
+ checked={vendorMaterialPriceRelatedYn}
+ onCheckedChange={(checked) => {
+ setValue("vendorMaterialPriceRelatedYn", checked)
+ // 체크박스 해제 시 연동제 정보도 초기화
+ if (!checked) {
+ setValue("priceAdjustmentForm.priceAdjustmentResponse", null)
+ }
+ }}
+ />
+ <Label htmlFor="vendorMaterialPriceRelatedYn">연동제 적용 동의</Label>
+ </div>
+ <div className="space-y-2">
+ <Label htmlFor="vendorMaterialPriceRelatedReason">연동제 관련 의견</Label>
+ <Textarea
+ id="vendorMaterialPriceRelatedReason"
+ {...register("vendorMaterialPriceRelatedReason")}
+ placeholder="연동제 적용에 대한 의견을 입력하세요"
+ className="min-h-[100px]"
+ />
+ </div>
</div>
- <div className="space-y-2">
- <Label htmlFor="vendorMaterialPriceRelatedReason">연동제 관련 의견</Label>
- <Textarea
- id="vendorMaterialPriceRelatedReason"
- {...register("vendorMaterialPriceRelatedReason")}
- placeholder="연동제 적용에 대한 의견을 입력하세요"
- className="min-h-[100px]"
- />
- </div>
- </div>
+
+ {/* 연동제 상세 정보 */}
+ {vendorMaterialPriceRelatedYn && (
+ <Card className="mt-6">
+ <CardHeader>
+ <CardTitle className="text-lg">하도급대금등 연동표</CardTitle>
+ </CardHeader>
+ <CardContent className="space-y-4">
+ {/* 연동제 적용 여부 선택 */}
+ <div className="space-y-3 p-4 border rounded-lg bg-muted/30">
+ <Label className="font-semibold text-base">연동제 적용 여부 *</Label>
+ <RadioGroup
+ value={watch("priceAdjustmentForm.priceAdjustmentResponse") === null || watch("priceAdjustmentForm.priceAdjustmentResponse") === undefined ? 'none' : watch("priceAdjustmentForm.priceAdjustmentResponse") === true ? 'apply' : 'not-apply'}
+ onValueChange={(value) => {
+ const newValue = value === 'apply' ? true : value === 'not-apply' ? false : null
+ setValue("priceAdjustmentForm.priceAdjustmentResponse", newValue)
+ }}
+ >
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="apply" id="price-adjustment-apply" />
+ <Label htmlFor="price-adjustment-apply" className="font-normal cursor-pointer">
+ 연동제 적용
+ </Label>
+ </div>
+ <div className="flex items-center space-x-2">
+ <RadioGroupItem value="not-apply" id="price-adjustment-not-apply" />
+ <Label htmlFor="price-adjustment-not-apply" className="font-normal cursor-pointer">
+ 연동제 미적용
+ </Label>
+ </div>
+ </RadioGroup>
+ </div>
+
+ {/* 공통 필드 - 품목등의 명칭 */}
+ {watch("priceAdjustmentForm.priceAdjustmentResponse") !== null && watch("priceAdjustmentForm.priceAdjustmentResponse") !== undefined && (
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.itemName">품목등의 명칭 *</Label>
+ <Input
+ id="priceAdjustmentForm.itemName"
+ {...register("priceAdjustmentForm.itemName")}
+ placeholder="품목명을 입력하세요"
+ required
+ />
+ </div>
+ )}
+
+ {/* 연동제 적용 시 - 모든 필드 표시 */}
+ {watch("priceAdjustmentForm.priceAdjustmentResponse") === true && (
+ <>
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentReflectionPoint">조정대금 반영시점 *</Label>
+ <Input
+ id="priceAdjustmentForm.adjustmentReflectionPoint"
+ {...register("priceAdjustmentForm.adjustmentReflectionPoint")}
+ placeholder="반영시점을 입력하세요"
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentRatio">연동 비율 (%) *</Label>
+ <Input
+ id="priceAdjustmentForm.adjustmentRatio"
+ type="number"
+ step="0.01"
+ {...register("priceAdjustmentForm.adjustmentRatio", { valueAsNumber: true })}
+ placeholder="비율을 입력하세요"
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentPeriod">조정주기 *</Label>
+ <Input
+ id="priceAdjustmentForm.adjustmentPeriod"
+ {...register("priceAdjustmentForm.adjustmentPeriod")}
+ placeholder="조정주기를 입력하세요"
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.referenceDate">기준시점 *</Label>
+ <Input
+ id="priceAdjustmentForm.referenceDate"
+ type="date"
+ {...register("priceAdjustmentForm.referenceDate")}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.comparisonDate">비교시점 *</Label>
+ <Input
+ id="priceAdjustmentForm.comparisonDate"
+ type="date"
+ {...register("priceAdjustmentForm.comparisonDate")}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.contractorWriter">수탁기업(협력사) 작성자 *</Label>
+ <Input
+ id="priceAdjustmentForm.contractorWriter"
+ {...register("priceAdjustmentForm.contractorWriter")}
+ placeholder="작성자명을 입력하세요"
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentDate">조정일 *</Label>
+ <Input
+ id="priceAdjustmentForm.adjustmentDate"
+ type="date"
+ {...register("priceAdjustmentForm.adjustmentDate")}
+ required
+ />
+ </div>
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.majorApplicableRawMaterial">연동대상 주요 원재료 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.majorApplicableRawMaterial"
+ {...register("priceAdjustmentForm.majorApplicableRawMaterial")}
+ placeholder="연동 대상 원재료를 입력하세요"
+ rows={3}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentFormula">하도급대금등 연동 산식 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.adjustmentFormula"
+ {...register("priceAdjustmentForm.adjustmentFormula")}
+ placeholder="연동 산식을 입력하세요"
+ rows={3}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.rawMaterialPriceIndex">원재료 가격 기준지표 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.rawMaterialPriceIndex"
+ {...register("priceAdjustmentForm.rawMaterialPriceIndex")}
+ placeholder="가격 기준지표를 입력하세요"
+ rows={2}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.adjustmentConditions">조정요건 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.adjustmentConditions"
+ {...register("priceAdjustmentForm.adjustmentConditions")}
+ placeholder="조정요건을 입력하세요"
+ rows={2}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.notes">기타 사항</Label>
+ <Textarea
+ id="priceAdjustmentForm.notes"
+ {...register("priceAdjustmentForm.notes")}
+ placeholder="기타 사항을 입력하세요"
+ rows={2}
+ />
+ </div>
+ </>
+ )}
+
+ {/* 연동제 미적용 시 - 제한된 필드만 표시 */}
+ {watch("priceAdjustmentForm.priceAdjustmentResponse") === false && (
+ <>
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.majorNonApplicableRawMaterial">연동제 미적용 주요 원재료 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.majorNonApplicableRawMaterial"
+ {...register("priceAdjustmentForm.majorNonApplicableRawMaterial")}
+ placeholder="연동 미적용 원재료를 입력하세요"
+ rows={2}
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.contractorWriterNonApplicable">수탁기업(협력사) 작성자 *</Label>
+ <Input
+ id="priceAdjustmentForm.contractorWriterNonApplicable"
+ {...register("priceAdjustmentForm.contractorWriter")}
+ placeholder="작성자명을 입력하세요"
+ required
+ />
+ </div>
+
+ <div className="space-y-2">
+ <Label htmlFor="priceAdjustmentForm.nonApplicableReason">연동제 미희망 사유 *</Label>
+ <Textarea
+ id="priceAdjustmentForm.nonApplicableReason"
+ {...register("priceAdjustmentForm.nonApplicableReason")}
+ placeholder="미희망 사유를 입력하세요"
+ rows={3}
+ required
+ />
+ </div>
+ </>
+ )}
+
+ </CardContent>
+ </Card>
+ )}
+ </>
)}
</CardContent>
</Card>
diff --git a/lib/rfq-last/vendor-response/editor/vendor-response-editor.tsx b/lib/rfq-last/vendor-response/editor/vendor-response-editor.tsx
index 48ebeb47..c983dd55 100644
--- a/lib/rfq-last/vendor-response/editor/vendor-response-editor.tsx
+++ b/lib/rfq-last/vendor-response/editor/vendor-response-editor.tsx
@@ -66,6 +66,24 @@ const vendorResponseSchema = z.object({
// 연동제
vendorMaterialPriceRelatedYn: z.boolean().optional(),
vendorMaterialPriceRelatedReason: z.string().optional(),
+ priceAdjustmentForm: z.object({
+ priceAdjustmentResponse: z.boolean().nullable().optional(),
+ itemName: z.string().optional(),
+ adjustmentReflectionPoint: z.string().optional(),
+ adjustmentRatio: z.number().optional(),
+ adjustmentPeriod: z.string().optional(),
+ referenceDate: z.string().optional(),
+ comparisonDate: z.string().optional(),
+ adjustmentDate: z.string().optional(),
+ contractorWriter: z.string().optional(),
+ majorApplicableRawMaterial: z.string().optional(),
+ adjustmentFormula: z.string().optional(),
+ rawMaterialPriceIndex: z.string().optional(),
+ adjustmentConditions: z.string().optional(),
+ notes: z.string().optional(),
+ majorNonApplicableRawMaterial: z.string().optional(),
+ nonApplicableReason: z.string().optional(),
+ }).optional(),
// 변경 사유
currencyReason: z.string().optional(),
@@ -162,6 +180,51 @@ export default function VendorResponseEditor({
vendorMaterialPriceRelatedYn: existingResponse?.vendorMaterialPriceRelatedYn ?? rfqDetail.materialPriceRelatedYn,
vendorMaterialPriceRelatedReason: existingResponse?.vendorMaterialPriceRelatedReason || "",
+ priceAdjustmentForm: existingResponse?.priceAdjustmentForm ? {
+ priceAdjustmentResponse: existingResponse.priceAdjustmentForm.majorApplicableRawMaterial ? true :
+ existingResponse.priceAdjustmentForm.majorNonApplicableRawMaterial ? false : null,
+ itemName: existingResponse.priceAdjustmentForm.itemName || "",
+ adjustmentReflectionPoint: existingResponse.priceAdjustmentForm.adjustmentReflectionPoint || "",
+ adjustmentRatio: existingResponse.priceAdjustmentForm.adjustmentRatio ? Number(existingResponse.priceAdjustmentForm.adjustmentRatio) : undefined,
+ adjustmentPeriod: existingResponse.priceAdjustmentForm.adjustmentPeriod || "",
+ referenceDate: existingResponse.priceAdjustmentForm.referenceDate ?
+ (typeof existingResponse.priceAdjustmentForm.referenceDate === 'string'
+ ? existingResponse.priceAdjustmentForm.referenceDate
+ : existingResponse.priceAdjustmentForm.referenceDate.toISOString().split('T')[0]) : "",
+ comparisonDate: existingResponse.priceAdjustmentForm.comparisonDate ?
+ (typeof existingResponse.priceAdjustmentForm.comparisonDate === 'string'
+ ? existingResponse.priceAdjustmentForm.comparisonDate
+ : existingResponse.priceAdjustmentForm.comparisonDate.toISOString().split('T')[0]) : "",
+ adjustmentDate: existingResponse.priceAdjustmentForm.adjustmentDate ?
+ (typeof existingResponse.priceAdjustmentForm.adjustmentDate === 'string'
+ ? existingResponse.priceAdjustmentForm.adjustmentDate
+ : existingResponse.priceAdjustmentForm.adjustmentDate.toISOString().split('T')[0]) : "",
+ contractorWriter: existingResponse.priceAdjustmentForm.contractorWriter || "",
+ majorApplicableRawMaterial: existingResponse.priceAdjustmentForm.majorApplicableRawMaterial || "",
+ adjustmentFormula: existingResponse.priceAdjustmentForm.adjustmentFormula || "",
+ rawMaterialPriceIndex: existingResponse.priceAdjustmentForm.rawMaterialPriceIndex || "",
+ adjustmentConditions: existingResponse.priceAdjustmentForm.adjustmentConditions || "",
+ notes: existingResponse.priceAdjustmentForm.notes || "",
+ majorNonApplicableRawMaterial: existingResponse.priceAdjustmentForm.majorNonApplicableRawMaterial || "",
+ nonApplicableReason: existingResponse.priceAdjustmentForm.nonApplicableReason || "",
+ } : {
+ priceAdjustmentResponse: null,
+ itemName: "",
+ adjustmentReflectionPoint: "",
+ adjustmentRatio: undefined,
+ adjustmentPeriod: "",
+ referenceDate: "",
+ comparisonDate: "",
+ adjustmentDate: "",
+ contractorWriter: "",
+ majorApplicableRawMaterial: "",
+ adjustmentFormula: "",
+ rawMaterialPriceIndex: "",
+ adjustmentConditions: "",
+ notes: "",
+ majorNonApplicableRawMaterial: "",
+ nonApplicableReason: "",
+ },
currencyReason: existingResponse?.currencyReason || "",
paymentTermsReason: existingResponse?.paymentTermsReason || "",