diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-01 10:31:23 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-10-01 10:31:23 +0000 |
| commit | 74843fe598702a9a55f914f2d2d291368a5abb13 (patch) | |
| tree | a88abdaf039f51dd843e0416321f08877b17ea75 /lib/vendor-document-list/sync-service.ts | |
| parent | 33e8452331c301430191b3506825ebaf3edac93a (diff) | |
(대표님) dolce 수정, spreadjs 수정 등
Diffstat (limited to 'lib/vendor-document-list/sync-service.ts')
| -rw-r--r-- | lib/vendor-document-list/sync-service.ts | 167 |
1 files changed, 97 insertions, 70 deletions
diff --git a/lib/vendor-document-list/sync-service.ts b/lib/vendor-document-list/sync-service.ts index cdbf489f..c3ddfcca 100644 --- a/lib/vendor-document-list/sync-service.ts +++ b/lib/vendor-document-list/sync-service.ts @@ -101,7 +101,7 @@ class SyncService { * 동기화할 변경사항 조회 (증분) */ async getPendingChanges( - vendorId: number, + userId: number, targetSystem: string = 'DOLCE', limit?: number ): Promise<ChangeLog[]> { @@ -109,7 +109,7 @@ class SyncService { .select() .from(changeLogs) .where(and( - eq(changeLogs.vendorId, vendorId), + eq(changeLogs.userId, userId), eq(changeLogs.isSynced, false), lt(changeLogs.syncAttempts, 3), sql`(${changeLogs.targetSystems} IS NULL OR ${changeLogs.targetSystems} @> ${JSON.stringify([targetSystem])})` @@ -176,10 +176,11 @@ class SyncService { } const vendorId = Number(session.user.companyId) + const userId = Number(session.user.id) // 2. 대기 중인 변경사항 조회 (전체) - const pendingChanges = await this.getPendingChanges(vendorId, targetSystem) + const pendingChanges = await this.getPendingChanges(userId, targetSystem) if (pendingChanges.length === 0) { return { @@ -457,79 +458,105 @@ class SyncService { .where(inArray(changeLogs.id, changeIds)) } - /** - * 동기화 상태 조회 - */ - async getSyncStatus(projectId: number, targetSystem: string = 'DOLCE') { - try { +/** + * 동기화 상태 조회 - entityType별 상세 통계 포함 + */ +async getSyncStatus(projectId: number, targetSystem: string = 'DOLCE') { + try { + const session = await getServerSession(authOptions) + if (!session?.user?.companyId) { + throw new Error("인증이 필요합니다.") + } - const session = await getServerSession(authOptions) - if (!session?.user?.companyId) { - throw new Error("인증이 필요합니다.") + const vendorId = Number(session.user.companyId) + const userId = Number(session.user.id) + + // 기본 조건 + const baseConditions = and( + eq(changeLogs.userId, userId), + sql`(${changeLogs.targetSystems} IS NULL OR ${changeLogs.targetSystems} @> ${JSON.stringify([targetSystem])})` + ) + + // entityType별 통계를 위한 쿼리 + const entityStats = await db + .select({ + entityType: changeLogs.entityType, + pendingCount: sql<number>`COUNT(*) FILTER (WHERE ${changeLogs.isSynced} = false AND ${changeLogs.syncAttempts} < 3)`, + syncedCount: sql<number>`COUNT(*) FILTER (WHERE ${changeLogs.isSynced} = true)`, + failedCount: sql<number>`COUNT(*) FILTER (WHERE ${changeLogs.isSynced} = false AND ${changeLogs.syncAttempts} >= 3)`, + totalCount: sql<number>`COUNT(*)` + }) + .from(changeLogs) + .where(baseConditions) + .groupBy(changeLogs.entityType) + + // 전체 통계 계산 + const totals = entityStats.reduce((acc, stat) => ({ + pendingChanges: acc.pendingChanges + Number(stat.pendingCount), + syncedChanges: acc.syncedChanges + Number(stat.syncedCount), + failedChanges: acc.failedChanges + Number(stat.failedCount), + totalChanges: acc.totalChanges + Number(stat.totalCount) + }), { + pendingChanges: 0, + syncedChanges: 0, + failedChanges: 0, + totalChanges: 0 + }) + + // entityType별 상세 정보 구성 + const entityTypeDetails = { + document: { + pending: 0, + synced: 0, + failed: 0, + total: 0 + }, + revision: { + pending: 0, + synced: 0, + failed: 0, + total: 0 + }, + attachment: { + pending: 0, + synced: 0, + failed: 0, + total: 0 } - - const vendorId = Number(session.user.companyId) - - - // 대기 중인 변경사항 수 조회 - const pendingCount = await db.$count( - changeLogs, - and( - eq(changeLogs.vendorId, vendorId), - eq(changeLogs.isSynced, false), - lt(changeLogs.syncAttempts, 3), - sql`(${changeLogs.targetSystems} IS NULL OR ${changeLogs.targetSystems} @> ${JSON.stringify([targetSystem])})` - ) - ) - - // 동기화된 변경사항 수 조회 - const syncedCount = await db.$count( - changeLogs, - and( - eq(changeLogs.vendorId, vendorId), - eq(changeLogs.isSynced, true), - sql`(${changeLogs.targetSystems} IS NULL OR ${changeLogs.targetSystems} @> ${JSON.stringify([targetSystem])})` - ) - ) - - // 실패한 변경사항 수 조회 - const failedCount = await db.$count( - changeLogs, - and( - eq(changeLogs.vendorId, vendorId), - eq(changeLogs.isSynced, false), - sql`${changeLogs.syncAttempts} >= 3`, - sql`(${changeLogs.targetSystems} IS NULL OR ${changeLogs.targetSystems} @> ${JSON.stringify([targetSystem])})` - ) - ) - - // 마지막 성공한 배치 조회 - const [lastSuccessfulBatch] = await db - .select() - .from(syncBatches) - .where(and( - eq(syncBatches.vendorId, vendorId), - eq(syncBatches.targetSystem, targetSystem), - eq(syncBatches.status, 'SUCCESS') - )) - .orderBy(desc(syncBatches.completedAt)) - .limit(1) + } - return { - vendorId, - targetSystem, - totalChanges: pendingCount + syncedCount + failedCount, - pendingChanges: pendingCount, - syncedChanges: syncedCount, - failedChanges: failedCount, - lastSyncAt: lastSuccessfulBatch?.completedAt?.toISOString() || null, - syncEnabled: this.isSyncEnabled(targetSystem) + // 통계 데이터를 entityTypeDetails에 매핑 + entityStats.forEach(stat => { + const entityType = stat.entityType as 'document' | 'revision' | 'attachment' + if (entityTypeDetails[entityType]) { + entityTypeDetails[entityType] = { + pending: Number(stat.pendingCount), + synced: Number(stat.syncedCount), + failed: Number(stat.failedCount), + total: Number(stat.totalCount) + } } - } catch (error) { - console.error('Failed to get sync status:', error) - throw error + }) + + + return { + projectId, + vendorId, + targetSystem, + ...totals, + entityTypeDetails, // entityType별 상세 통계 + syncEnabled: this.isSyncEnabled(targetSystem), + // 추가 메타데이터 + hasPendingChanges: totals.pendingChanges > 0, + hasFailedChanges: totals.failedChanges > 0, + syncHealthy: totals.failedChanges === 0 && totals.pendingChanges < 100, + requiresSync: totals.pendingChanges > 0 } + } catch (error) { + console.error('Failed to get sync status:', error) + throw error } +} /** * 최근 동기화 배치 목록 조회 |
