diff options
| author | joonhoekim <26rote@gmail.com> | 2025-10-23 18:44:19 +0900 |
|---|---|---|
| committer | joonhoekim <26rote@gmail.com> | 2025-10-23 18:44:19 +0900 |
| commit | 04bd1965c3699a4b29ed9c9627574bfeedd3d6c6 (patch) | |
| tree | 691b9a6e844a788937a240d47e77e8cfa848a88a /lib/swp/example-usage.ts | |
| parent | 535e234dbd674bf2e5ecf344e03ed8ae5b2cbd6c (diff) | |
(김준회) SWP 문서 업로드 (Submisssion) 초기 개발건
Diffstat (limited to 'lib/swp/example-usage.ts')
| -rw-r--r-- | lib/swp/example-usage.ts | 347 |
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; + } +} + |
