summaryrefslogtreecommitdiff
path: root/app/api/contracts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-14 05:28:01 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-14 05:28:01 +0000
commit675b4e3d8ffcb57a041db285417d81e61284d900 (patch)
tree254f3d6a6c0ce39ae8fba35618f3810e08945f19 /app/api/contracts
parent39f12cb19f29cbc5568057e154e6adf4789ae736 (diff)
(대표님) RFQ-last, tbe-last, 기본계약 템플릿 내 견적,입찰,계약 추가, env.dev NAS_PATH 수정
Diffstat (limited to 'app/api/contracts')
-rw-r--r--app/api/contracts/get-template/route.ts33
-rw-r--r--app/api/contracts/prepare-template/route.ts83
-rw-r--r--app/api/contracts/template/route.ts32
3 files changed, 148 insertions, 0 deletions
diff --git a/app/api/contracts/get-template/route.ts b/app/api/contracts/get-template/route.ts
new file mode 100644
index 00000000..c987c527
--- /dev/null
+++ b/app/api/contracts/get-template/route.ts
@@ -0,0 +1,33 @@
+import { NextRequest, NextResponse } from "next/server";
+import { readFile } from "fs/promises";
+import path from "path";
+
+export async function POST(request: NextRequest) {
+ try {
+ const { templatePath } = await request.json();
+
+ if (!templatePath) {
+ return NextResponse.json(
+ { error: "템플릿 경로가 필요합니다." },
+ { status: 400 }
+ );
+ }
+
+ const fullPath = path.join(process.cwd(), `${process.env.NAS_PATH}`, templatePath);
+ const fileBuffer = await readFile(fullPath);
+
+ return new NextResponse(fileBuffer, {
+ headers: {
+ 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'Content-Disposition': `attachment; filename="template.docx"`
+ }
+ });
+
+ } catch (error) {
+ console.error("템플릿 파일 읽기 실패:", error);
+ return NextResponse.json(
+ { error: "템플릿 파일을 읽을 수 없습니다." },
+ { status: 500 }
+ );
+ }
+} \ No newline at end of file
diff --git a/app/api/contracts/prepare-template/route.ts b/app/api/contracts/prepare-template/route.ts
new file mode 100644
index 00000000..189643b5
--- /dev/null
+++ b/app/api/contracts/prepare-template/route.ts
@@ -0,0 +1,83 @@
+import { NextRequest, NextResponse } from "next/server";
+import db from "@/db/db";
+import { basicContractTemplates, vendors } from "@/db/schema";
+import { eq, and, ilike } from "drizzle-orm";
+
+export async function POST(request: NextRequest) {
+ try {
+ const { templateName, vendorId } = await request.json();
+
+ // 템플릿 조회
+ const [template] = await db
+ .select()
+ .from(basicContractTemplates)
+ .where(
+ and(
+ ilike(basicContractTemplates.templateName, `%${templateName}%`),
+ eq(basicContractTemplates.status, "ACTIVE")
+ )
+ )
+ .limit(1);
+
+
+
+ if (!template) {
+ return NextResponse.json(
+ { error: "템플릿을 찾을 수 없습니다." },
+ { status: 404 }
+ );
+ }
+
+ // 벤더 정보 조회
+ const [vendor] = await db
+ .select()
+ .from(vendors)
+ .where(eq(vendors.id, vendorId))
+ .limit(1);
+
+ if (!vendor) {
+ return NextResponse.json(
+ { error: "벤더를 찾을 수 없습니다." },
+ { status: 404 }
+ );
+ }
+
+ // 템플릿 데이터 준비
+ const templateData = {
+ company_name: vendor.vendorName || '협력업체명',
+ company_address: vendor.address || '주소',
+ company_address_detail: vendor.addressDetail || '',
+ company_postal_code: vendor.postalCode || '',
+ company_country: vendor.country || '대한민국',
+ representative_name: vendor.representativeName || '대표자명',
+ representative_email: vendor.representativeEmail || '',
+ representative_phone: vendor.representativePhone || '',
+ tax_id: vendor.taxId || '사업자번호',
+ corporate_registration_number: vendor.corporateRegistrationNumber || '',
+ phone_number: vendor.phone || '전화번호',
+ email: vendor.email || '',
+ website: vendor.website || '',
+ signature_date: new Date().toLocaleDateString('ko-KR'),
+ contract_date: new Date().toISOString().split('T')[0],
+ effective_date: new Date().toISOString().split('T')[0],
+ expiry_date: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
+ vendor_code: vendor.vendorCode || '',
+ business_size: vendor.businessSize || '',
+ credit_rating: vendor.creditRating || '',
+ template_type: templateName,
+ contract_number: `BC-${new Date().getFullYear()}-${String(vendorId).padStart(4, '0')}-${Date.now()}`,
+ };
+
+ return NextResponse.json({
+ template,
+ templateData
+ });
+
+ } catch (error) {
+ console.log("템플릿 준비 실패:", error);
+ return NextResponse.json(
+ { error: "템플릿 준비 중 오류가 발생했습니다." },
+ { status: 500 }
+ );
+ }
+} \ No newline at end of file
diff --git a/app/api/contracts/template/route.ts b/app/api/contracts/template/route.ts
new file mode 100644
index 00000000..c66fea0e
--- /dev/null
+++ b/app/api/contracts/template/route.ts
@@ -0,0 +1,32 @@
+import { NextRequest, NextResponse } from "next/server";
+import { readFile } from "fs/promises";
+import path from "path";
+
+export async function POST(request: NextRequest) {
+ try {
+ const { templatePath } = await request.json();
+
+ if (!templatePath) {
+ return NextResponse.json(
+ { error: "템플릿 경로가 필요합니다." },
+ { status: 400 }
+ );
+ }
+
+ const fullPath = path.join(process.cwd(), process.env.NAS_PATH, templatePath);
+ const fileBuffer = await readFile(fullPath);
+
+ return new NextResponse(fileBuffer, {
+ headers: {
+ 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'Content-Disposition': `attachment; filename="template.docx"`
+ }
+ });
+ } catch (error) {
+ console.error("템플릿 파일 읽기 실패:", error);
+ return NextResponse.json(
+ { error: "템플릿 파일을 읽을 수 없습니다." },
+ { status: 500 }
+ );
+ }
+} \ No newline at end of file