summaryrefslogtreecommitdiff
path: root/lib/knox-sync/employee-sync-service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/knox-sync/employee-sync-service.ts')
-rw-r--r--lib/knox-sync/employee-sync-service.ts151
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})`);
+}