From a568da160c14b38402fff141574a59f05a04aee2 Mon Sep 17 00:00:00 2001 From: wangziqi Date: Mon, 6 Jul 2026 09:53:48 +0800 Subject: [PATCH] feat(sync): implement sync stubs with env-var gating and status endpoint --- apps/server/src/sync/sync.controller.ts | 11 ++++++++ apps/server/src/sync/sync.service.ts | 35 ++++++++++++++++++------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/apps/server/src/sync/sync.controller.ts b/apps/server/src/sync/sync.controller.ts index 2bb53f7..b3e3717 100644 --- a/apps/server/src/sync/sync.controller.ts +++ b/apps/server/src/sync/sync.controller.ts @@ -16,6 +16,17 @@ export class SyncController { return { synced: logs.length, logs }; } + @Get('status') + @RequirePermission('sync:read') + async getStatus() { + const lastDingTalk = await this.syncService.getLastSync('dingtalk'); + const lastWeCom = await this.syncService.getLastSync('wecom'); + return { + dingTalk: lastDingTalk ? { lastSyncAt: lastDingTalk.finishedAt, status: lastDingTalk.status } : null, + weCom: lastWeCom ? { lastSyncAt: lastWeCom.finishedAt, status: lastWeCom.status } : null, + }; + } + @Get('logs') @RequirePermission('sync:read') async getLogs( diff --git a/apps/server/src/sync/sync.service.ts b/apps/server/src/sync/sync.service.ts index ecf5bf0..03de116 100644 --- a/apps/server/src/sync/sync.service.ts +++ b/apps/server/src/sync/sync.service.ts @@ -91,6 +91,13 @@ export class SyncService { return this.syncLogRepo.find({ where, order: { createdAt: 'DESC' }, take: limit }); } + async getLastSync(platform: SyncPlatform): Promise { + return this.syncLogRepo.findOne({ + where: { platform }, + order: { createdAt: 'DESC' }, + }); + } + // ── Private helpers ── private async determineSyncType(platform: SyncPlatform): Promise { @@ -145,20 +152,28 @@ export class SyncService { * Pass `lastSyncAt` to the DingTalk API for incremental sync. */ private async performDingTalkSync(_lastSyncAt: Date | null): Promise { - // TODO: Call DingTalk API — e.g. attendance records, user list, etc. - // const records = await this.dingTalkClient.fetchAttendance({ updatedAfter: lastSyncAt }); - // return records.length; + const appKey = process.env.DINGTALK_APP_KEY; + if (!appKey) { + this.logger.warn('DingTalk not configured (DINGTALK_APP_KEY missing), skipping sync'); + return 0; + } + + this.logger.warn( + 'DingTalk integration service not yet implemented — add DingTalkService to SyncModule to enable real sync', + ); return 0; } - /** - * Perform the actual WeCom data pull. - * Pass `lastSyncAt` to the WeCom API for incremental sync. - */ private async performWeComSync(_lastSyncAt: Date | null): Promise { - // TODO: Call WeCom API — e.g. contacts, attendance, etc. - // const records = await this.weComClient.fetchContacts({ updatedAfter: lastSyncAt }); - // return records.length; + const corpId = process.env.WECOM_CORP_ID; + if (!corpId) { + this.logger.warn('WeCom not configured (WECOM_CORP_ID missing), skipping sync'); + return 0; + } + + this.logger.warn( + 'WeCom integration service not yet implemented — add WeComService to SyncModule to enable real sync', + ); return 0; } }