From ad6bde0250cfe014d5f78747ec76ac59df95a25d Mon Sep 17 00:00:00 2001 From: dujinkim Date: Wed, 5 Nov 2025 02:55:31 +0000 Subject: (최겸) 구매 PQ 수정, 기본계약 수정하기 내 drm 추가 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/[lng]/admin/ecc/page.tsx | 32 +-- app/[lng]/partners/(partners)/pq_new/[id]/page.tsx | 206 ++++++++++++++ app/[lng]/partners/(partners)/pq_new/page.tsx | 298 +++++++++++++++++++++ app/[lng]/partners/(partners)/site-visit/page.tsx | 30 +++ app/[lng]/partners/pq_new/[id]/page.tsx | 206 -------------- app/[lng]/partners/pq_new/page.tsx | 298 --------------------- app/[lng]/partners/site-visit/page.tsx | 30 --- components/pq-input/pq-input-tabs.tsx | 94 +++---- lib/basic-contract/service.ts | 14 +- lib/vendor-evaluation-submit/service.ts | 1 + 10 files changed, 601 insertions(+), 608 deletions(-) create mode 100644 app/[lng]/partners/(partners)/pq_new/[id]/page.tsx create mode 100644 app/[lng]/partners/(partners)/pq_new/page.tsx create mode 100644 app/[lng]/partners/(partners)/site-visit/page.tsx delete mode 100644 app/[lng]/partners/pq_new/[id]/page.tsx delete mode 100644 app/[lng]/partners/pq_new/page.tsx delete mode 100644 app/[lng]/partners/site-visit/page.tsx 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() { PCR 확인 - RFQ 취소 + RFQ 삭제 RFQ 정보 PO 생성 @@ -345,7 +345,7 @@ export default function ECCSenderTestPage() { - {/* RFQ 취소 탭 */} + {/* RFQ 삭제 탭 */} @@ -354,7 +354,7 @@ export default function ECCSenderTestPage() { RFQ (Request for Quotation) 취소 - RFQ 취소 요청을 ECC로 전송합니다. (IF_ECC_EVCP_CANCEL_RFQ) + RFQ 삭제 요청을 ECC로 전송합니다. (IF_ECC_EVCP_CANCEL_RFQ) @@ -372,34 +372,34 @@ export default function ECCSenderTestPage() {
{/* 테스트 결과 표시 */} - {(testResults['RFQ 취소 (샘플)'] || testResults['RFQ 취소 (사용자)']) && ( + {(testResults['RFQ 삭제 (샘플)'] || testResults['RFQ 삭제 (사용자)']) && (

테스트 결과

- {testResults['RFQ 취소 (샘플)'] && ( - + {testResults['RFQ 삭제 (샘플)'] && ( + )} - {testResults['RFQ 취소 (사용자)'] && ( - + {testResults['RFQ 삭제 (사용자)'] && ( + )}
)} diff --git a/app/[lng]/partners/(partners)/pq_new/[id]/page.tsx b/app/[lng]/partners/(partners)/pq_new/[id]/page.tsx new file mode 100644 index 00000000..5a8313cc --- /dev/null +++ b/app/[lng]/partners/(partners)/pq_new/[id]/page.tsx @@ -0,0 +1,206 @@ +import { Metadata } from "next"; +import Link from "next/link"; +import { getServerSession } from "next-auth/next"; +import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import { Button } from "@/components/ui/button"; +import { ArrowLeft, LogIn } from "lucide-react"; +import { Shell } from "@/components/shell"; +import { getPQById, getPQDataByVendorId } from "@/lib/pq/service"; +import { unstable_noStore as noStore } from 'next/cache'; +import { Alert, AlertDescription } from "@/components/ui/alert"; +import { PQInputTabs } from "@/components/pq-input/pq-input-tabs"; + +export const metadata: Metadata = { + title: "사전 평가 (PQ) 작성", + description: "사전 평가 항목을 작성합니다.", +}; + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic"; + +interface PQEditPageProps { + params: Promise<{ id: string }>; +} + +export default async function PQEditPage(props: PQEditPageProps) { + // 캐시 비활성화 + noStore(); + + const params = await props.params; + const pqSubmissionId = parseInt(params.id, 10); + + // 인증 확인 + const session = await getServerSession(authOptions); + + // 로그인 확인 + if (!session || !session.user) { + return ( + +
+
+

+ 사전 평가 (PQ) 작성 +

+
+
+ +
+
+

로그인이 필요합니다

+

+ 사전 평가를 작성하려면 먼저 로그인하세요. +

+ +
+
+
+ ); + } + + // 세션에서 vendorId 가져오기 + const vendorId = session.user.companyId; + + // 벤더 권한 확인 + if (session.user.domain !== "partners" || !vendorId) { + return ( + +
+
+

+ 접근 권한 없음 +

+
+
+
+
+

벤더 계정이 필요합니다

+

+ 벤더 계정으로 로그인해주세요. +

+
+
+
+ ); + } + + const idAsNumber = Number(vendorId); + + try { + // PQ Submission 정보 조회 (vendorPQSubmissions 테이블에서) + const pqSubmission = await getPQById(pqSubmissionId, idAsNumber); + + // 이 PQ가 현재 로그인한 벤더의 것인지 확인 + if (pqSubmission.vendorId !== idAsNumber) { + throw new Error("Access denied - This PQ belongs to another vendor"); + } + + // PQ 데이터 조회 (pqCriterias와 답변) + const pqData = await getPQDataByVendorId(idAsNumber, pqSubmission.projectId || undefined); + + // 상태에 따른 읽기 전용 모드 결정 + const isReadOnly = [ "APPROVED"].includes(pqSubmission.status); + const statusText = pqSubmission.status === "SUBMITTED" ? "제출됨" : + pqSubmission.status === "APPROVED" ? "승인됨" : + pqSubmission.status === "REJECTED" ? "거부됨" : "작성 중"; + + const pageTitle = pqSubmission.type === "PROJECT" + ? `프로젝트 PQ - ${pqSubmission.projectName || pqSubmission.projectCode}` + : pqSubmission.type === "NON_INSPECTION" + ? "미실사 PQ" + : "일반 PQ"; + + // 프로젝트 정보 (프로젝트 PQ인 경우) + const projectPQ = pqSubmission.projectId ? { + id: pqSubmission.projectId, + projectId: pqSubmission.projectId, + projectCode: pqSubmission.projectCode || '', + projectName: pqSubmission.projectName || '', + status: pqSubmission.status, + submittedAt: pqSubmission.submittedAt, + } : null; + + return ( + +
+
+ +
+

+ {pageTitle} +

+

+ 상태: {statusText} + {pqSubmission.status === "REJECTED" && pqSubmission.rejectReason && ( + + (거부 사유: {pqSubmission.rejectReason}) + + )} +

+
+
+
+ + {/* 읽기 전용 모드 알림 */} + {/* {isReadOnly && ( + + + 이 PQ는 현재 제출된 상태입니다. SHI 코멘트를 확인 후 재제출이 가능합니다. + + + )} */} + + {/* PQ 입력 컴포넌트 */} + +
+ ); + } catch (error) { + console.error("Error loading PQ:", error); + + return ( + +
+
+

+ 오류 발생 +

+
+
+
+
+

PQ를 불러올 수 없습니다

+

+ 요청하신 PQ를 찾을 수 없거나 접근 권한이 없습니다. +

+ +
+
+
+ ); + } +} \ No newline at end of file diff --git a/app/[lng]/partners/(partners)/pq_new/page.tsx b/app/[lng]/partners/(partners)/pq_new/page.tsx new file mode 100644 index 00000000..eea5b21d --- /dev/null +++ b/app/[lng]/partners/(partners)/pq_new/page.tsx @@ -0,0 +1,298 @@ +import * as React from "react"; +import Link from "next/link"; +import { Metadata } from "next"; +import { getServerSession } from "next-auth/next"; +import { authOptions } from "@/app/api/auth/[...nextauth]/route"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { LogIn, Edit, Eye, Ellipsis } from "lucide-react"; +import { Shell } from "@/components/shell"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { unstable_noStore as noStore } from 'next/cache'; +import { getAllPQsByVendorId, getPQStatusCounts } from "@/lib/pq/service"; +import { InformationButton } from "@/components/information/information-button"; +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; + +export const metadata: Metadata = { + title: "사전 평가 (PQ) 목록", + description: "요청된 사전 평가 목록을 확인하고 작성합니다.", +}; + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic"; + +function getStatusBadge(status: string) { + switch (status) { + case "REQUESTED": + return 요청됨; + case "IN_PROGRESS": + return 진행 중; + case "SUBMITTED": + return 제출됨; + case "APPROVED": + return 승인됨; + case "REJECTED": + return 거부됨; + default: + return {status}; + } +} + +function getFormattedDate(date: Date | null) { + if (!date) return "-"; + return new Intl.DateTimeFormat("ko-KR", { + year: "numeric", + month: "2-digit", + day: "2-digit", + }).format(new Date(date)); +} + +export default async function PQListPage() { + // 캐시 비활성화 + noStore(); + + // 인증 확인 + const session = await getServerSession(authOptions); + + // 로그인 확인 + if (!session || !session.user) { + return ( + +
+
+

+ 사전 평가 (PQ) 목록 +

+

+ 요청된 사전 평가 목록을 확인하고 작성합니다. +

+
+
+ +
+
+

로그인이 필요합니다

+

+ 사전 평가를 확인하려면 먼저 로그인하세요. +

+ +
+
+
+ ); + } + + // 세션에서 vendorId 가져오기 + const vendorId = session.user.companyId; + + // 벤더 권한 확인 + if (session.user.domain !== "partners" || !vendorId) { + return ( + +
+
+

+ 접근 권한 없음 +

+
+
+
+
+

벤더 계정이 필요합니다

+

+ 벤더 계정으로 로그인해주세요. +

+
+
+
+ ); + } + + const idAsNumber = Number(vendorId); + + // 데이터 가져오기 (병렬 실행) + const [pqList, pqStatusCounts] = await Promise.all([ + getAllPQsByVendorId(idAsNumber), + getPQStatusCounts(idAsNumber), + ]); + + return ( + +
+
+
+

사전 평가 (PQ) 목록

+ +
+

+ 요청된 사전 평가 목록을 확인하고 작성합니다. +

+
+
+ + {/* PQ 상태 요약 카드 */} +
+ + + 총 PQ + + +
+ {Object.values(pqStatusCounts).reduce((sum, count) => sum + count, 0)}건 +
+
+
+ + + 작성 대기 + + +
+ {(pqStatusCounts.REQUESTED || 0) + (pqStatusCounts.IN_PROGRESS || 0)}건 +
+
+
+ + + 제출됨 + + +
+ {pqStatusCounts.SUBMITTED || 0}건 +
+
+
+ + + 승인됨 + + +
+ {pqStatusCounts.APPROVED || 0}건 +
+
+
+
+ + {/* PQ 목록 테이블 */} + + + PQ 목록 + + + + + + 유형 + PQ 번호 + 프로젝트 + 상태 + 요청일 + 제출일 + 승인일 + 액션 + + + + {pqList.length === 0 ? ( + + + 요청된 PQ가 없습니다. + + + ) : ( + pqList.map((pq) => { + const canEdit = ["REQUESTED", "IN_PROGRESS", "REJECTED"].includes(pq.status); + const canView = ["SUBMITTED", "APPROVED"].includes(pq.status); + + return ( + + + + {pq.type === "PROJECT" ? "프로젝트" : + pq.type === "NON_INSPECTION" ? "미실사" : + "일반"} + + + + {pq.pqNumber || "-"} + + + {pq.projectName || "-"} + + + {getStatusBadge(pq.status)} + + + {getFormattedDate(pq.createdAt)} + + + {getFormattedDate(pq.submittedAt)} + + + {getFormattedDate(pq.approvedAt)} + + + + + + + + {canEdit && ( + + + + 작성 + + + )} + {canView && ( + + + + 보기 + + + )} + + + + + ); + }) + )} + +
+
+
+
+ ); +} \ No newline at end of file diff --git a/app/[lng]/partners/(partners)/site-visit/page.tsx b/app/[lng]/partners/(partners)/site-visit/page.tsx new file mode 100644 index 00000000..92580b35 --- /dev/null +++ b/app/[lng]/partners/(partners)/site-visit/page.tsx @@ -0,0 +1,30 @@ +import { getServerSession } from "next-auth" +import { authOptions } from "@/app/api/auth/[...nextauth]/route" +import { getSiteVisitRequestsByVendorId } from "@/lib/site-visit/service" +import { ClientSiteVisitWrapper } from "@/lib/site-visit/client-site-visit-wrapper" +import { unstable_noStore as noStore } from 'next/cache' + +// 페이지가 기본적으로 동적임을 나타냄 +export const dynamic = "force-dynamic" + +export default async function SiteVisitPage() { + // Opt out of caching for this route + noStore() + + // 세션 + const session = await getServerSession(authOptions) + // 세션에서 vendorId 가져오기 + const vendorId = session?.user.companyId + const idAsNumber = Number(vendorId) + + // 방문실사 요청 목록 가져오기 + const siteVisitRequests = await getSiteVisitRequestsByVendorId(idAsNumber) + + // 클라이언트 컴포넌트로 데이터 전달 + return ( + + ) +} \ No newline at end of file diff --git a/app/[lng]/partners/pq_new/[id]/page.tsx b/app/[lng]/partners/pq_new/[id]/page.tsx deleted file mode 100644 index 5a8313cc..00000000 --- a/app/[lng]/partners/pq_new/[id]/page.tsx +++ /dev/null @@ -1,206 +0,0 @@ -import { Metadata } from "next"; -import Link from "next/link"; -import { getServerSession } from "next-auth/next"; -import { authOptions } from "@/app/api/auth/[...nextauth]/route"; -import { Button } from "@/components/ui/button"; -import { ArrowLeft, LogIn } from "lucide-react"; -import { Shell } from "@/components/shell"; -import { getPQById, getPQDataByVendorId } from "@/lib/pq/service"; -import { unstable_noStore as noStore } from 'next/cache'; -import { Alert, AlertDescription } from "@/components/ui/alert"; -import { PQInputTabs } from "@/components/pq-input/pq-input-tabs"; - -export const metadata: Metadata = { - title: "사전 평가 (PQ) 작성", - description: "사전 평가 항목을 작성합니다.", -}; - -// 페이지가 기본적으로 동적임을 나타냄 -export const dynamic = "force-dynamic"; - -interface PQEditPageProps { - params: Promise<{ id: string }>; -} - -export default async function PQEditPage(props: PQEditPageProps) { - // 캐시 비활성화 - noStore(); - - const params = await props.params; - const pqSubmissionId = parseInt(params.id, 10); - - // 인증 확인 - const session = await getServerSession(authOptions); - - // 로그인 확인 - if (!session || !session.user) { - return ( - -
-
-

- 사전 평가 (PQ) 작성 -

-
-
- -
-
-

로그인이 필요합니다

-

- 사전 평가를 작성하려면 먼저 로그인하세요. -

- -
-
-
- ); - } - - // 세션에서 vendorId 가져오기 - const vendorId = session.user.companyId; - - // 벤더 권한 확인 - if (session.user.domain !== "partners" || !vendorId) { - return ( - -
-
-

- 접근 권한 없음 -

-
-
-
-
-

벤더 계정이 필요합니다

-

- 벤더 계정으로 로그인해주세요. -

-
-
-
- ); - } - - const idAsNumber = Number(vendorId); - - try { - // PQ Submission 정보 조회 (vendorPQSubmissions 테이블에서) - const pqSubmission = await getPQById(pqSubmissionId, idAsNumber); - - // 이 PQ가 현재 로그인한 벤더의 것인지 확인 - if (pqSubmission.vendorId !== idAsNumber) { - throw new Error("Access denied - This PQ belongs to another vendor"); - } - - // PQ 데이터 조회 (pqCriterias와 답변) - const pqData = await getPQDataByVendorId(idAsNumber, pqSubmission.projectId || undefined); - - // 상태에 따른 읽기 전용 모드 결정 - const isReadOnly = [ "APPROVED"].includes(pqSubmission.status); - const statusText = pqSubmission.status === "SUBMITTED" ? "제출됨" : - pqSubmission.status === "APPROVED" ? "승인됨" : - pqSubmission.status === "REJECTED" ? "거부됨" : "작성 중"; - - const pageTitle = pqSubmission.type === "PROJECT" - ? `프로젝트 PQ - ${pqSubmission.projectName || pqSubmission.projectCode}` - : pqSubmission.type === "NON_INSPECTION" - ? "미실사 PQ" - : "일반 PQ"; - - // 프로젝트 정보 (프로젝트 PQ인 경우) - const projectPQ = pqSubmission.projectId ? { - id: pqSubmission.projectId, - projectId: pqSubmission.projectId, - projectCode: pqSubmission.projectCode || '', - projectName: pqSubmission.projectName || '', - status: pqSubmission.status, - submittedAt: pqSubmission.submittedAt, - } : null; - - return ( - -
-
- -
-

- {pageTitle} -

-

- 상태: {statusText} - {pqSubmission.status === "REJECTED" && pqSubmission.rejectReason && ( - - (거부 사유: {pqSubmission.rejectReason}) - - )} -

-
-
-
- - {/* 읽기 전용 모드 알림 */} - {/* {isReadOnly && ( - - - 이 PQ는 현재 제출된 상태입니다. SHI 코멘트를 확인 후 재제출이 가능합니다. - - - )} */} - - {/* PQ 입력 컴포넌트 */} - -
- ); - } catch (error) { - console.error("Error loading PQ:", error); - - return ( - -
-
-

- 오류 발생 -

-
-
-
-
-

PQ를 불러올 수 없습니다

-

- 요청하신 PQ를 찾을 수 없거나 접근 권한이 없습니다. -

- -
-
-
- ); - } -} \ No newline at end of file diff --git a/app/[lng]/partners/pq_new/page.tsx b/app/[lng]/partners/pq_new/page.tsx deleted file mode 100644 index eea5b21d..00000000 --- a/app/[lng]/partners/pq_new/page.tsx +++ /dev/null @@ -1,298 +0,0 @@ -import * as React from "react"; -import Link from "next/link"; -import { Metadata } from "next"; -import { getServerSession } from "next-auth/next"; -import { authOptions } from "@/app/api/auth/[...nextauth]/route"; -import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; -import { Button } from "@/components/ui/button"; -import { Badge } from "@/components/ui/badge"; -import { LogIn, Edit, Eye, Ellipsis } from "lucide-react"; -import { Shell } from "@/components/shell"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; -import { unstable_noStore as noStore } from 'next/cache'; -import { getAllPQsByVendorId, getPQStatusCounts } from "@/lib/pq/service"; -import { InformationButton } from "@/components/information/information-button"; -import { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, -} from "@/components/ui/dropdown-menu"; - -export const metadata: Metadata = { - title: "사전 평가 (PQ) 목록", - description: "요청된 사전 평가 목록을 확인하고 작성합니다.", -}; - -// 페이지가 기본적으로 동적임을 나타냄 -export const dynamic = "force-dynamic"; - -function getStatusBadge(status: string) { - switch (status) { - case "REQUESTED": - return 요청됨; - case "IN_PROGRESS": - return 진행 중; - case "SUBMITTED": - return 제출됨; - case "APPROVED": - return 승인됨; - case "REJECTED": - return 거부됨; - default: - return {status}; - } -} - -function getFormattedDate(date: Date | null) { - if (!date) return "-"; - return new Intl.DateTimeFormat("ko-KR", { - year: "numeric", - month: "2-digit", - day: "2-digit", - }).format(new Date(date)); -} - -export default async function PQListPage() { - // 캐시 비활성화 - noStore(); - - // 인증 확인 - const session = await getServerSession(authOptions); - - // 로그인 확인 - if (!session || !session.user) { - return ( - -
-
-

- 사전 평가 (PQ) 목록 -

-

- 요청된 사전 평가 목록을 확인하고 작성합니다. -

-
-
- -
-
-

로그인이 필요합니다

-

- 사전 평가를 확인하려면 먼저 로그인하세요. -

- -
-
-
- ); - } - - // 세션에서 vendorId 가져오기 - const vendorId = session.user.companyId; - - // 벤더 권한 확인 - if (session.user.domain !== "partners" || !vendorId) { - return ( - -
-
-

- 접근 권한 없음 -

-
-
-
-
-

벤더 계정이 필요합니다

-

- 벤더 계정으로 로그인해주세요. -

-
-
-
- ); - } - - const idAsNumber = Number(vendorId); - - // 데이터 가져오기 (병렬 실행) - const [pqList, pqStatusCounts] = await Promise.all([ - getAllPQsByVendorId(idAsNumber), - getPQStatusCounts(idAsNumber), - ]); - - return ( - -
-
-
-

사전 평가 (PQ) 목록

- -
-

- 요청된 사전 평가 목록을 확인하고 작성합니다. -

-
-
- - {/* PQ 상태 요약 카드 */} -
- - - 총 PQ - - -
- {Object.values(pqStatusCounts).reduce((sum, count) => sum + count, 0)}건 -
-
-
- - - 작성 대기 - - -
- {(pqStatusCounts.REQUESTED || 0) + (pqStatusCounts.IN_PROGRESS || 0)}건 -
-
-
- - - 제출됨 - - -
- {pqStatusCounts.SUBMITTED || 0}건 -
-
-
- - - 승인됨 - - -
- {pqStatusCounts.APPROVED || 0}건 -
-
-
-
- - {/* PQ 목록 테이블 */} - - - PQ 목록 - - - - - - 유형 - PQ 번호 - 프로젝트 - 상태 - 요청일 - 제출일 - 승인일 - 액션 - - - - {pqList.length === 0 ? ( - - - 요청된 PQ가 없습니다. - - - ) : ( - pqList.map((pq) => { - const canEdit = ["REQUESTED", "IN_PROGRESS", "REJECTED"].includes(pq.status); - const canView = ["SUBMITTED", "APPROVED"].includes(pq.status); - - return ( - - - - {pq.type === "PROJECT" ? "프로젝트" : - pq.type === "NON_INSPECTION" ? "미실사" : - "일반"} - - - - {pq.pqNumber || "-"} - - - {pq.projectName || "-"} - - - {getStatusBadge(pq.status)} - - - {getFormattedDate(pq.createdAt)} - - - {getFormattedDate(pq.submittedAt)} - - - {getFormattedDate(pq.approvedAt)} - - - - - - - - {canEdit && ( - - - - 작성 - - - )} - {canView && ( - - - - 보기 - - - )} - - - - - ); - }) - )} - -
-
-
-
- ); -} \ No newline at end of file diff --git a/app/[lng]/partners/site-visit/page.tsx b/app/[lng]/partners/site-visit/page.tsx deleted file mode 100644 index 92580b35..00000000 --- a/app/[lng]/partners/site-visit/page.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { getServerSession } from "next-auth" -import { authOptions } from "@/app/api/auth/[...nextauth]/route" -import { getSiteVisitRequestsByVendorId } from "@/lib/site-visit/service" -import { ClientSiteVisitWrapper } from "@/lib/site-visit/client-site-visit-wrapper" -import { unstable_noStore as noStore } from 'next/cache' - -// 페이지가 기본적으로 동적임을 나타냄 -export const dynamic = "force-dynamic" - -export default async function SiteVisitPage() { - // Opt out of caching for this route - noStore() - - // 세션 - const session = await getServerSession(authOptions) - // 세션에서 vendorId 가져오기 - const vendorId = session?.user.companyId - const idAsNumber = Number(vendorId) - - // 방문실사 요청 목록 가져오기 - const siteVisitRequests = await getSiteVisitRequestsByVendorId(idAsNumber) - - // 클라이언트 컴포넌트로 데이터 전달 - return ( - - ) -} \ No newline at end of file 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 ( -
- - - {code} - {checkPoint} @@ -882,7 +875,6 @@ export function PQInputTabs({
- {/* 프로젝트별 추가 필드 (contractInfo, additionalRequirement) */} {projectId && contractInfo && ( @@ -1298,9 +1290,7 @@ export function PQInputTabs({ /> - - ) })}
@@ -1323,51 +1313,45 @@ export function PQInputTabs({
- {data.map((group) => ( - - -
-

{group.groupName}

- -
-
- - - {group.items.map((item) => { - const answerObj = form - .getValues() - .answers.find((a) => a.criteriaId === item.criteriaId) - - if (!answerObj) return null - - return ( -
- {/* code & checkPoint */} -

- {item.code} - {item.checkPoint} -

- - {/* user's typed answer */} -

Answer:

-

- {answerObj.answer || "(no answer)"} -

- {/* attachments */} -

Attachments:

- {answerObj.uploadedFiles.length > 0 ? ( -
    - {answerObj.uploadedFiles.map((file, idx) => ( -
  • {file.fileName}
  • - ))} -
- ) : ( -

(none)

- )} -
- ) - })} -
-
+ {data.map((group, groupIndex) => ( +
+ {group.items.map((item) => { + const answerObj = form + .getValues() + .answers.find((a) => a.criteriaId === item.criteriaId); + + if (!answerObj) return null; + + return ( +
+ {/* code & checkPoint */} +

+ {item.code} - {item.checkPoint} +

+ + {/* user's typed answer */} +

Answer:

+

+ {answerObj.answer || "(no answer)"} +

+ {/* attachments */} +

Attachments:

+ {answerObj.uploadedFiles && answerObj.uploadedFiles.length > 0 ? ( +
    + {answerObj.uploadedFiles.map((file, idx) => ( +
  • {file.fileName}
  • + ))} +
+ ) : ( +

(none)

+ )} +
+ ); + })} +
))}
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)); -- cgit v1.2.3