diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-05 02:55:31 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-11-05 02:55:31 +0000 |
| commit | ad6bde0250cfe014d5f78747ec76ac59df95a25d (patch) | |
| tree | 10cf65130b20a21caef0961215f8f6645a68c76d | |
| parent | 70aada2ef189467d1bc62dc892c629a71196e755 (diff) | |
(최겸) 구매 PQ 수정, 기본계약 수정하기 내 drm 추가
| -rw-r--r-- | app/[lng]/admin/ecc/page.tsx | 32 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/pq_new/[id]/page.tsx (renamed from app/[lng]/partners/pq_new/[id]/page.tsx) | 0 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/pq_new/page.tsx (renamed from app/[lng]/partners/pq_new/page.tsx) | 0 | ||||
| -rw-r--r-- | app/[lng]/partners/(partners)/site-visit/page.tsx (renamed from app/[lng]/partners/site-visit/page.tsx) | 0 | ||||
| -rw-r--r-- | components/pq-input/pq-input-tabs.tsx | 94 | ||||
| -rw-r--r-- | lib/basic-contract/service.ts | 14 | ||||
| -rw-r--r-- | lib/vendor-evaluation-submit/service.ts | 1 |
7 files changed, 67 insertions, 74 deletions
diff --git a/app/[lng]/admin/ecc/page.tsx b/app/[lng]/admin/ecc/page.tsx index cd09e213..a3e4eba4 100644 --- a/app/[lng]/admin/ecc/page.tsx +++ b/app/[lng]/admin/ecc/page.tsx @@ -15,7 +15,7 @@ import { toast } from 'sonner' // SOAP 송신 함수들 import import { confirmTestPCR, confirmPCR } from '@/lib/soap/ecc/send/pcr-confirm' -import { cancelTestRFQ, cancelRFQ } from '@/lib/soap/ecc/send/cancel-rfq' +import { cancelTestRFQ, cancelRFQ } from '@/lib/soap/ecc/send/delete-rfq' import { sendTestRFQInformation, sendRFQInformation } from '@/lib/soap/ecc/send/rfq-info' import { createTestPurchaseOrder, createPurchaseOrder } from '@/lib/soap/ecc/send/create-po' @@ -97,7 +97,7 @@ export default function ECCSenderTestPage() { CONFIRM_RSN: '테스트 확인' }) - // RFQ 취소 테스트 + // RFQ 삭제 테스트 const [rfqCancelData, setRfqCancelData] = useState({ ANFNR: 'TEST_RFQ_001' }) @@ -232,7 +232,7 @@ export default function ECCSenderTestPage() { <Tabs defaultValue="pcr-confirm" className="w-full"> <TabsList className="grid w-full grid-cols-4"> <TabsTrigger value="pcr-confirm">PCR 확인</TabsTrigger> - <TabsTrigger value="rfq-cancel">RFQ 취소</TabsTrigger> + <TabsTrigger value="rfq-cancel">RFQ 삭제</TabsTrigger> <TabsTrigger value="rfq-info">RFQ 정보</TabsTrigger> <TabsTrigger value="po-create">PO 생성</TabsTrigger> </TabsList> @@ -345,7 +345,7 @@ export default function ECCSenderTestPage() { </Card> </TabsContent> - {/* RFQ 취소 탭 */} + {/* RFQ 삭제 탭 */} <TabsContent value="rfq-cancel" className="space-y-6"> <Card> <CardHeader> @@ -354,7 +354,7 @@ export default function ECCSenderTestPage() { RFQ (Request for Quotation) 취소 </CardTitle> <CardDescription> - RFQ 취소 요청을 ECC로 전송합니다. (IF_ECC_EVCP_CANCEL_RFQ) + RFQ 삭제 요청을 ECC로 전송합니다. (IF_ECC_EVCP_CANCEL_RFQ) </CardDescription> </CardHeader> <CardContent className="space-y-4"> @@ -372,34 +372,34 @@ export default function ECCSenderTestPage() { <div className="flex gap-4"> <Button - onClick={() => runTest('RFQ 취소 (샘플)', () => cancelTestRFQ())} - disabled={isLoading['RFQ 취소 (샘플)']} + onClick={() => runTest('RFQ 삭제 (샘플)', () => cancelTestRFQ())} + disabled={isLoading['RFQ 삭제 (샘플)']} variant="outline" > - {isLoading['RFQ 취소 (샘플)'] && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} + {isLoading['RFQ 삭제 (샘플)'] && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} <Play className="mr-2 h-4 w-4" /> 샘플 데이터로 테스트 </Button> <Button - onClick={() => runTest('RFQ 취소 (사용자)', () => cancelRFQ(rfqCancelData.ANFNR))} - disabled={isLoading['RFQ 취소 (사용자)']} + onClick={() => runTest('RFQ 삭제 (사용자)', () => cancelRFQ(rfqCancelData.ANFNR))} + disabled={isLoading['RFQ 삭제 (사용자)']} variant="destructive" > - {isLoading['RFQ 취소 (사용자)'] && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} + {isLoading['RFQ 삭제 (사용자)'] && <Loader2 className="mr-2 h-4 w-4 animate-spin" />} <Send className="mr-2 h-4 w-4" /> 사용자 데이터로 취소 </Button> </div> {/* 테스트 결과 표시 */} - {(testResults['RFQ 취소 (샘플)'] || testResults['RFQ 취소 (사용자)']) && ( + {(testResults['RFQ 삭제 (샘플)'] || testResults['RFQ 삭제 (사용자)']) && ( <div className="space-y-2"> <h4 className="font-semibold">테스트 결과</h4> - {testResults['RFQ 취소 (샘플)'] && ( - <TestResultCard result={testResults['RFQ 취소 (샘플)']} title="샘플 테스트" /> + {testResults['RFQ 삭제 (샘플)'] && ( + <TestResultCard result={testResults['RFQ 삭제 (샘플)']} title="샘플 테스트" /> )} - {testResults['RFQ 취소 (사용자)'] && ( - <TestResultCard result={testResults['RFQ 취소 (사용자)']} title="사용자 테스트" /> + {testResults['RFQ 삭제 (사용자)'] && ( + <TestResultCard result={testResults['RFQ 삭제 (사용자)']} title="사용자 테스트" /> )} </div> )} diff --git a/app/[lng]/partners/pq_new/[id]/page.tsx b/app/[lng]/partners/(partners)/pq_new/[id]/page.tsx index 5a8313cc..5a8313cc 100644 --- a/app/[lng]/partners/pq_new/[id]/page.tsx +++ b/app/[lng]/partners/(partners)/pq_new/[id]/page.tsx diff --git a/app/[lng]/partners/pq_new/page.tsx b/app/[lng]/partners/(partners)/pq_new/page.tsx index eea5b21d..eea5b21d 100644 --- a/app/[lng]/partners/pq_new/page.tsx +++ b/app/[lng]/partners/(partners)/pq_new/page.tsx diff --git a/app/[lng]/partners/site-visit/page.tsx b/app/[lng]/partners/(partners)/site-visit/page.tsx index 92580b35..92580b35 100644 --- a/app/[lng]/partners/site-visit/page.tsx +++ b/app/[lng]/partners/(partners)/site-visit/page.tsx diff --git a/components/pq-input/pq-input-tabs.tsx b/components/pq-input/pq-input-tabs.tsx index 8d5aa2ab..f0d44d04 100644 --- a/components/pq-input/pq-input-tabs.tsx +++ b/components/pq-input/pq-input-tabs.tsx @@ -822,18 +822,11 @@ export function PQInputTabs({ if (!shouldShowItem(isSaved)) return null return ( - <Collapsible key={criteriaId} defaultOpen={isReadOnly || !isSaved} className="w-full"> <Card className={`${isSaved ? "border-green-200" : ""} h-fit min-h-[400px]`}> <CardHeader className="pb-1"> <div className="flex justify-between"> <div className="flex-1"> <div className="flex items-center gap-2"> - <CollapsibleTrigger asChild> - <Button variant="ghost" size="sm" className="p-0 h-7 w-7"> - <ChevronsUpDown className="h-4 w-4" /> - <span className="sr-only">Toggle</span> - </Button> - </CollapsibleTrigger> <CardTitle className="text-md"> {code} - {checkPoint} </CardTitle> @@ -882,7 +875,6 @@ export function PQInputTabs({ </div> </CardHeader> - <CollapsibleContent> <CardContent className="pt-3 space-y-3 h-full flex flex-col"> {/* 프로젝트별 추가 필드 (contractInfo, additionalRequirement) */} {projectId && contractInfo && ( @@ -1298,9 +1290,7 @@ export function PQInputTabs({ /> </CardContent> - </CollapsibleContent> </Card> - </Collapsible> ) })} </div> @@ -1323,51 +1313,45 @@ export function PQInputTabs({ </DialogHeader> <div className="space-y-4 max-h-[600px] overflow-y-auto "> - {data.map((group) => ( - <Collapsible key={group.groupName} defaultOpen> - <CollapsibleTrigger asChild> - <div className="flex justify-between items-center p-2 mb-1 cursor-pointer "> - <p className="font-semibold">{group.groupName}</p> - <ChevronsUpDown className="h-4 w-4 ml-2" /> - </div> - </CollapsibleTrigger> - - <CollapsibleContent> - {group.items.map((item) => { - const answerObj = form - .getValues() - .answers.find((a) => a.criteriaId === item.criteriaId) - - if (!answerObj) return null - - return ( - <div key={item.criteriaId} className="mb-2 p-2 ml-2 border rounded-md text-sm"> - {/* code & checkPoint */} - <p className="font-semibold"> - {item.code} - {item.checkPoint} - </p> - - {/* user's typed answer */} - <p className="text-sm font-medium mt-2">Answer:</p> - <p className="whitespace-pre-wrap text-sm"> - {answerObj.answer || "(no answer)"} - </p> - {/* attachments */} - <p>Attachments:</p> - {answerObj.uploadedFiles.length > 0 ? ( - <ul className="list-disc list-inside ml-4 text-xs"> - {answerObj.uploadedFiles.map((file, idx) => ( - <li key={idx}>{file.fileName}</li> - ))} - </ul> - ) : ( - <p className="text-xs text-muted-foreground">(none)</p> - )} - </div> - ) - })} - </CollapsibleContent> - </Collapsible> + {data.map((group, groupIndex) => ( + <div key={groupIndex}> + {group.items.map((item) => { + const answerObj = form + .getValues() + .answers.find((a) => a.criteriaId === item.criteriaId); + + if (!answerObj) return null; + + return ( + <div + key={item.criteriaId} + className="mb-2 p-2 ml-2 border rounded-md text-sm" + > + {/* code & checkPoint */} + <p className="font-semibold"> + {item.code} - {item.checkPoint} + </p> + + {/* user's typed answer */} + <p className="text-sm font-medium mt-2">Answer:</p> + <p className="whitespace-pre-wrap text-sm"> + {answerObj.answer || "(no answer)"} + </p> + {/* attachments */} + <p>Attachments:</p> + {answerObj.uploadedFiles && answerObj.uploadedFiles.length > 0 ? ( + <ul className="list-disc list-inside ml-4 text-xs"> + {answerObj.uploadedFiles.map((file, idx) => ( + <li key={idx}>{file.fileName}</li> + ))} + </ul> + ) : ( + <p className="text-xs text-muted-foreground">(none)</p> + )} + </div> + ); + })} + </div> ))} </div> diff --git a/lib/basic-contract/service.ts b/lib/basic-contract/service.ts index 123d2367..8c29dbf2 100644 --- a/lib/basic-contract/service.ts +++ b/lib/basic-contract/service.ts @@ -65,7 +65,8 @@ import { sendEmail } from "../mail/sendEmail"; import { headers } from 'next/headers';
import { filterColumns } from "@/lib/filter-columns";
import { differenceInDays, addYears, isBefore } from "date-fns";
-import { deleteFile, saveBuffer, saveFile } from "@/lib/file-stroage";
+import { deleteFile, saveBuffer, saveFile, saveDRMFile } from "@/lib/file-stroage";
+import { decryptWithServerAction } from "@/components/drm/drmUtils";
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
@@ -430,8 +431,15 @@ export async function updateTemplate({ let filePath: string | undefined = undefined;
if (file) {
- // 1) 새 파일 저장
- const saveResult = await saveFile({ file, directory: "basicContract/template" });
+ // 1) 새 파일 저장 (DRM 해제 로직 적용)
+
+ const saveResult = await saveDRMFile(
+ file,
+ decryptWithServerAction,
+ 'basicContract/template'
+ );
+
+
if (!saveResult.success) {
return { success: false, error: saveResult.error };
}
diff --git a/lib/vendor-evaluation-submit/service.ts b/lib/vendor-evaluation-submit/service.ts index 3a31b380..c7fe7122 100644 --- a/lib/vendor-evaluation-submit/service.ts +++ b/lib/vendor-evaluation-submit/service.ts @@ -451,6 +451,7 @@ export async function updateEvaluationSubmissionStatus( .set({ documentsSubmitted: true, submissionDate: new Date(), + status: 'SUBMITTED', updatedAt: new Date(), }) .where(eq(periodicEvaluations.id, updatedSubmission.periodicEvaluationId)); |
