summaryrefslogtreecommitdiff
path: root/lib/swp/example-usage.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-10-23 18:44:19 +0900
committerjoonhoekim <26rote@gmail.com>2025-10-23 18:44:19 +0900
commit04bd1965c3699a4b29ed9c9627574bfeedd3d6c6 (patch)
tree691b9a6e844a788937a240d47e77e8cfa848a88a /lib/swp/example-usage.ts
parent535e234dbd674bf2e5ecf344e03ed8ae5b2cbd6c (diff)
(김준회) SWP 문서 업로드 (Submisssion) 초기 개발건
Diffstat (limited to 'lib/swp/example-usage.ts')
-rw-r--r--lib/swp/example-usage.ts347
1 files changed, 347 insertions, 0 deletions
diff --git a/lib/swp/example-usage.ts b/lib/swp/example-usage.ts
new file mode 100644
index 00000000..8e1791f7
--- /dev/null
+++ b/lib/swp/example-usage.ts
@@ -0,0 +1,347 @@
+"use server";
+
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+/**
+ * SWP 문서 관리 시스템 사용 예제
+ *
+ * 이 파일은 실제 사용 시나리오를 보여주는 예제입니다.
+ */
+
+import {
+ fetchSwpProjectData,
+ analyzeSwpData,
+ getSwpFileDownloadUrl,
+} from "./api-client";
+import {
+ syncSwpProject,
+ getProjectDocumentsHierarchy,
+ getDocumentRevisions,
+ getRevisionFiles,
+ getProjectSyncStatus,
+} from "./sync-service";
+import db from "@/db/db";
+import { sql } from "drizzle-orm";
+
+// ============================================================================
+// 예제 1: 프로젝트 전체 동기화
+// ============================================================================
+
+export async function example1_FullProjectSync(projectNo: string) {
+ console.log("=== 예제 1: 프로젝트 전체 동기화 ===\n");
+
+ // 1. API에서 데이터 조회
+ console.log(`📡 API 호출 중...`);
+ const { documents, files } = await fetchSwpProjectData(projectNo, "V");
+
+ // 2. 데이터 분석
+ const stats: Awaited<ReturnType<typeof analyzeSwpData>> = await analyzeSwpData(projectNo, documents, files);
+ console.log(`📊 데이터 분석:`);
+ console.log(` - 문서: ${stats.documentCount}개`);
+ console.log(` - 리비전: ${stats.revisionCount}개`);
+ console.log(` - 파일: ${stats.fileCount}개`);
+ console.log(` - 평균 파일/문서: ${stats.avgFilesPerDoc.toFixed(2)}개`);
+ console.log(
+ ` - 총 용량: ${(stats.totalFileSize / 1024 / 1024).toFixed(2)} MB`
+ );
+ console.log(` - 스테이지:`, stats.stages);
+ console.log(` - 파일 타입:`, stats.fileTypes);
+
+ // 3. 동기화 실행
+ console.log(`\n💾 동기화 시작...`);
+ const syncResult = await syncSwpProject(projectNo, documents, files);
+
+ if (syncResult.success) {
+ console.log(`✅ 동기화 완료 (${syncResult.duration}ms)`);
+ console.log(` - 문서: +${syncResult.stats.documents.inserted}개`);
+ console.log(` - 리비전: +${syncResult.stats.revisions.inserted}개`);
+ console.log(` - 파일: +${syncResult.stats.files.inserted}개`);
+ } else {
+ console.error(`❌ 동기화 실패:`);
+ syncResult.errors.forEach((err) => console.error(` - ${err}`));
+ }
+
+ return syncResult;
+}
+
+// ============================================================================
+// 예제 2: 계층 구조 조회 및 UI 렌더링
+// ============================================================================
+
+export async function example2_HierarchyView(projectNo: string) {
+ console.log("=== 예제 2: 계층 구조 조회 ===\n");
+
+ // 1. 계층 뷰 조회
+ const result = await getProjectDocumentsHierarchy(projectNo);
+ const documents = result.rows as any[];
+
+ console.log(`📁 문서 ${documents.length}개 조회됨\n`);
+
+ // 2. 첫 3개 문서만 출력 (예제)
+ documents.slice(0, 3).forEach((doc) => {
+ console.log(`📄 ${doc.doc_no}`);
+ console.log(` 제목: ${doc.doc_title}`);
+ console.log(` 최신 리비전: ${doc.ltst_rev_no}`);
+ console.log(` 리비전 수: ${doc.revision_count}개`);
+
+ const revisions = JSON.parse(doc.revisions || "[]");
+ revisions.slice(0, 2).forEach((rev: any) => {
+ console.log(` 📋 REV ${rev.revNo} (${rev.stage})`);
+ console.log(` 파일: ${rev.fileCount}개`);
+
+ const files = rev.files || [];
+ files.forEach((file: any) => {
+ console.log(` 📎 ${file.fileNm} (${file.fileSz} bytes)`);
+ });
+ });
+ console.log();
+ });
+
+ return documents;
+}
+
+// ============================================================================
+// 예제 3: 특정 문서의 리비전 조회
+// ============================================================================
+
+export async function example3_DocumentRevisions(docNo: string) {
+ console.log("=== 예제 3: 문서 리비전 조회 ===\n");
+
+ // 1. 리비전 목록 조회
+ const revisions = await getDocumentRevisions(docNo);
+
+ console.log(`📄 문서: ${docNo}`);
+ console.log(`📋 리비전: ${revisions.length}개\n`);
+
+ // 2. 각 리비전별 파일 조회
+ for (const rev of revisions) {
+ const files = await getRevisionFiles(rev.id);
+
+ console.log(`REV ${rev.REV_NO} (${rev.STAGE})`);
+ console.log(` 파일: ${files.length}개`);
+ console.log(` Activity: ${rev.ACTV_NO || "N/A"}`);
+ console.log(` OFDC: ${rev.OFDC_NO}`);
+ console.log(` 동기화: ${rev.sync_status} (${rev.last_synced_at})`);
+
+ files.forEach((file) => {
+ console.log(` 📎 ${file.FILE_NM}`);
+ console.log(` 크기: ${file.FILE_SZ} bytes`);
+ console.log(` 경로: ${file.FLD_PATH}`);
+ console.log(` 상태: ${file.STAT_NM}`);
+ });
+ console.log();
+ }
+
+ return revisions;
+}
+
+// ============================================================================
+// 예제 4: 파일 검색 (플랫 뷰 활용)
+// ============================================================================
+
+export async function example4_SearchFiles(
+ projectNo: string,
+ fileNamePattern: string
+) {
+ console.log("=== 예제 4: 파일 검색 ===\n");
+
+ // 1. 플랫 뷰에서 검색
+ const result = await db.execute(sql`
+ SELECT
+ "DOC_NO",
+ "DOC_TITLE",
+ "REV_NO",
+ "STAGE",
+ "FILE_NM",
+ "FILE_SZ",
+ "FLD_PATH",
+ "STAT_NM"
+ FROM swp.v_swp_documents_flat
+ WHERE "PROJ_NO" = ${projectNo}
+ AND "FILE_NM" ILIKE ${`%${fileNamePattern}%`}
+ ORDER BY "DOC_NO", "REV_NO" DESC
+ LIMIT 20
+ `);
+
+ console.log(`🔍 검색어: "${fileNamePattern}"`);
+ console.log(`📊 결과: ${result.rowCount}개\n`);
+
+ result.rows.forEach((row: any) => {
+ console.log(`📄 ${row.DOC_NO} (${row.DOC_TITLE})`);
+ console.log(` REV ${row.REV_NO} (${row.STAGE})`);
+ console.log(` 📎 ${row.FILE_NM} (${row.FILE_SZ} bytes)`);
+ console.log(` 상태: ${row.STAT_NM}`);
+ console.log();
+ });
+
+ return result.rows;
+}
+
+// ============================================================================
+// 예제 5: 파일 다운로드 URL 생성
+// ============================================================================
+
+export async function example5_FileDownload(revisionId: number) {
+ console.log("=== 예제 5: 파일 다운로드 ===\n");
+
+ // 1. 리비전의 파일 조회
+ const files = await getRevisionFiles(revisionId);
+
+ console.log(`📋 리비전 ID: ${revisionId}`);
+ console.log(`📎 파일: ${files.length}개\n`);
+
+ // 2. 다운로드 URL 생성
+ const fileUrls = await Promise.all(
+ files
+ .filter((file) => file.FLD_PATH && file.FILE_NM)
+ .map(async (file) => ({
+ fileName: file.FILE_NM,
+ downloadUrl: await getSwpFileDownloadUrl({
+ FLD_PATH: file.FLD_PATH!,
+ FILE_NM: file.FILE_NM,
+ }),
+ size: file.FILE_SZ,
+ }))
+ );
+
+ fileUrls.forEach((item) => {
+ console.log(`📎 ${item.fileName}`);
+ console.log(` URL: ${item.downloadUrl}`);
+ console.log(` 크기: ${item.size} bytes`);
+ console.log();
+ });
+
+ return fileUrls;
+}
+
+// ============================================================================
+// 예제 6: 동기화 상태 모니터링
+// ============================================================================
+
+export async function example6_SyncMonitoring(projectNo: string) {
+ console.log("=== 예제 6: 동기화 상태 모니터링 ===\n");
+
+ // 1. 프로젝트 동기화 상태 조회
+ const result = await getProjectSyncStatus(projectNo);
+ const status = result.rows[0] as any;
+
+ console.log(`📊 프로젝트: ${status.proj_no} (${status.proj_nm})`);
+ console.log(`\n📈 통계:`);
+ console.log(` - 문서: ${status.total_documents}개`);
+ console.log(` - 리비전: ${status.total_revisions}개`);
+ console.log(` - 파일: ${status.total_files}개`);
+
+ console.log(`\n✅ 동기화 상태:`);
+ console.log(` - 문서: ${status.docs_synced}개 완료`);
+ console.log(` - 대기: ${status.docs_pending}개`);
+ console.log(` - 오류: ${status.docs_error}개`);
+
+ console.log(`\n🕐 마지막 동기화: ${status.last_sync_time}`);
+
+ return status;
+}
+
+// ============================================================================
+// 예제 7: 스테이지별 문서 통계
+// ============================================================================
+
+export async function example7_StageStatistics(projectNo: string) {
+ console.log("=== 예제 7: 스테이지별 통계 ===\n");
+
+ const result = await db.execute(sql`
+ SELECT
+ "STAGE",
+ COUNT(DISTINCT "DOC_NO")::int as doc_count,
+ COUNT(DISTINCT "REV_NO")::int as rev_count,
+ COUNT(*)::int as file_count
+ FROM swp.v_swp_documents_flat
+ WHERE "PROJ_NO" = ${projectNo}
+ AND "STAGE" IS NOT NULL
+ GROUP BY "STAGE"
+ ORDER BY "STAGE"
+ `);
+
+ console.log(`📊 프로젝트: ${projectNo}\n`);
+
+ result.rows.forEach((row: any) => {
+ console.log(`📌 ${row.STAGE}`);
+ console.log(` 문서: ${row.doc_count}개`);
+ console.log(` 리비전: ${row.rev_count}개`);
+ console.log(` 파일: ${row.file_count}개`);
+ console.log();
+ });
+
+ return result.rows;
+}
+
+// ============================================================================
+// 예제 8: 증분 동기화 (변경된 항목만)
+// ============================================================================
+
+export async function example8_IncrementalSync(projectNo: string) {
+ console.log("=== 예제 8: 증분 동기화 ===\n");
+
+ // 1. 마지막 동기화 시간 확인
+ const lastSyncResult = await db.execute(sql`
+ SELECT MAX(last_synced_at) as last_sync
+ FROM swp.swp_documents
+ WHERE "PROJ_NO" = ${projectNo}
+ `);
+
+ const lastSync = lastSyncResult.rows[0] as any;
+ console.log(`🕐 마지막 동기화: ${lastSync.last_sync || "없음"}`);
+
+ // 2. 전체 동기화 (API는 증분 제공 안하므로)
+ console.log(`📡 전체 데이터 조회 중...`);
+ const { documents, files } = await fetchSwpProjectData(projectNo, "V");
+
+ // 3. 동기화 (upsert로 변경된 항목만 업데이트됨)
+ console.log(`💾 동기화 시작...`);
+ const syncResult = await syncSwpProject(projectNo, documents, files);
+
+ console.log(`\n📊 결과:`);
+ console.log(
+ ` - 신규 문서: ${syncResult.stats.documents.inserted}개 (기존: ${syncResult.stats.documents.updated}개)`
+ );
+ console.log(
+ ` - 신규 리비전: ${syncResult.stats.revisions.inserted}개 (기존: ${syncResult.stats.revisions.updated}개)`
+ );
+ console.log(
+ ` - 신규 파일: ${syncResult.stats.files.inserted}개 (기존: ${syncResult.stats.files.updated}개)`
+ );
+
+ return syncResult;
+}
+
+// ============================================================================
+// 전체 시나리오 실행
+// ============================================================================
+
+export async function runAllExamples(projectNo: string = "SN2190") {
+ console.log("╔═══════════════════════════════════════════╗");
+ console.log("║ SWP 문서 관리 시스템 사용 예제 ║");
+ console.log("╚═══════════════════════════════════════════╝\n");
+
+ try {
+ // 예제 1: 전체 동기화
+ await example1_FullProjectSync(projectNo);
+ console.log("\n" + "=".repeat(50) + "\n");
+
+ // 예제 2: 계층 구조 조회
+ await example2_HierarchyView(projectNo);
+ console.log("\n" + "=".repeat(50) + "\n");
+
+ // 예제 6: 동기화 상태
+ await example6_SyncMonitoring(projectNo);
+ console.log("\n" + "=".repeat(50) + "\n");
+
+ // 예제 7: 스테이지별 통계
+ await example7_StageStatistics(projectNo);
+
+ console.log("\n✅ 모든 예제 실행 완료!");
+ } catch (error) {
+ console.error("\n❌ 오류 발생:", error);
+ throw error;
+ }
+}
+