diff options
Diffstat (limited to 'lib/knox-sync')
| -rw-r--r-- | lib/knox-sync/employee-sync-service.ts | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/knox-sync/employee-sync-service.ts b/lib/knox-sync/employee-sync-service.ts new file mode 100644 index 00000000..c517be14 --- /dev/null +++ b/lib/knox-sync/employee-sync-service.ts @@ -0,0 +1,151 @@ +'use server'; + +import * as cron from 'node-cron'; +import db from '@/db/db'; +import { employee as employeeTable } from '@/db/schema/knox/employee'; +import { + searchEmployees, + getDepartmentsByCompany, + Employee, +} from '@/lib/knox-api/employee/employee'; +import { sql } from 'drizzle-orm'; + +// 동기화 대상 회사 코드 (쉼표로 구분된 ENV) +const COMPANIES = (process.env.KNOX_COMPANY_CODES || 'P2') + .split(',') + .map((c) => c.trim()) + .filter(Boolean); + +const CRON_STRING = process.env.KNOX_EMPLOYEE_SYNC_CRON || '0 4 * * *'; + +const DO_FIRST_RUN = process.env.KNOX_EMPLOYEE_SYNC_FIRST_RUN === 'true'; + +async function upsertEmployees(employees: Employee[]) { + if (!employees.length) return; + + const rows = employees.map((e) => ({ + epId: e.epId, + employeeNumber: e.employeeNumber, + userId: e.userId, + fullName: e.fullName, + givenName: e.givenName, + sirName: e.sirName, + companyCode: e.companyCode, + companyName: e.companyName, + departmentCode: e.departmentCode, + departmentName: e.departmentName, + titleCode: e.titleCode, + titleName: e.titleName, + emailAddress: e.emailAddress, + mobile: e.mobile, + employeeStatus: e.employeeStatus, + employeeType: e.employeeType, + accountStatus: e.accountStatus, + securityLevel: e.securityLevel, + preferredLanguage: e.preferredLanguage, + description: e.description, + raw: e as unknown as Record<string, unknown>, + enCompanyName: e.enCompanyName, + enDepartmentName: e.enDepartmentName, + enDiscription: e.enDiscription, + enFullName: e.enFullName, + enGivenName: e.enGivenName, + enGradeName: e.enGradeName, + enSirName: e.enSirName, + enTitleName: e.enTitleName, + gradeName: e.gradeName, + gradeTitleIndiCode: e.gradeTitleIndiCode, + jobName: e.jobName, + realNameYn: e.realNameYn, + serverLocation: e.serverLocation, + titleSortOrder: e.titleSortOrder, + })); + + await db + .insert(employeeTable) + .values(rows) + .onConflictDoUpdate({ + target: employeeTable.epId, + set: { + fullName: sql.raw('excluded.full_name'), + givenName: sql.raw('excluded.given_name'), + sirName: sql.raw('excluded.sir_name'), + companyCode: sql.raw('excluded.company_code'), + companyName: sql.raw('excluded.company_name'), + departmentCode: sql.raw('excluded.department_code'), + departmentName: sql.raw('excluded.department_name'), + titleCode: sql.raw('excluded.title_code'), + titleName: sql.raw('excluded.title_name'), + emailAddress: sql.raw('excluded.email_address'), + mobile: sql.raw('excluded.mobile'), + employeeStatus: sql.raw('excluded.employee_status'), + employeeType: sql.raw('excluded.employee_type'), + accountStatus: sql.raw('excluded.account_status'), + securityLevel: sql.raw('excluded.security_level'), + preferredLanguage: sql.raw('excluded.preferred_language'), + description: sql.raw('excluded.description'), + raw: sql.raw('excluded.raw'), + updatedAt: sql.raw('CURRENT_TIMESTAMP'), + }, + }); +} + +export async function syncKnoxEmployees(): Promise<void> { + console.log('[KNOX-SYNC] 임직원 동기화 시작'); + + for (const companyCode of COMPANIES) { + try { + const departments = await getDepartmentsByCompany(companyCode); + console.log(`[KNOX-SYNC] ${companyCode}: 부서 ${departments.length}개`); + + for (const dept of departments) { + let page = 1; + let totalPage = 1; + do { + const resp = await searchEmployees({ + companyCode, + departmentCode: dept.departmentCode, + page: String(page), + resultType: 'basic', + }); + + if (resp.result === 'success') { + await upsertEmployees(resp.employees); + totalPage = resp.totalPage; + console.log( + `[KNOX-SYNC] 임직원 동기화 ${companyCode}/${dept.departmentCode} ${page}/${totalPage} 페이지 처리` + ); + } else { + console.warn( + `[KNOX-SYNC] 임직원 동기화 실패: ${companyCode}/${dept.departmentCode} page ${page}` + ); + break; + } + + page += 1; + } while (page <= totalPage); + } + } catch (err) { + console.error( + `[KNOX-SYNC] 임직원 동기화 오류 (company ${companyCode})`, + err + ); + } + } + + console.log('[KNOX-SYNC] 임직원 동기화 완료'); +} + +export async function startKnoxEmployeeSyncScheduler() { + // 환경 변수에 따라 실행시 즉시 실행 여부 결정 (없으면 false) + if (DO_FIRST_RUN) { + syncKnoxEmployees().catch(console.error); + } + + // CRON JOB 등록 + cron.schedule(CRON_STRING, () => { + syncKnoxEmployees().catch(console.error); + }); + + console.log(`[KNOX-SYNC] 임직원 동기화 스케줄러 등록 (${CRON_STRING})`); +} |
