/** * 페이지 구조 재구성 마이그레이션 * - 페이지 경로 업데이트 (safety/, attendance/ 폴더로 이동) * - 카테고리 재분류 * - 역할별 기본 페이지 권한 테이블 생성 */ exports.up = async function(knex) { // 1. 페이지 경로 업데이트 - safety 폴더로 이동된 페이지들 const safetyPageUpdates = [ { old_key: 'issue-report', new_key: 'safety.issue_report', new_path: '/pages/safety/issue-report.html', new_category: 'safety', new_name: '이슈 신고' }, { old_key: 'issue-list', new_key: 'safety.issue_list', new_path: '/pages/safety/issue-list.html', new_category: 'safety', new_name: '이슈 목록' }, { old_key: 'issue-detail', new_key: 'safety.issue_detail', new_path: '/pages/safety/issue-detail.html', new_category: 'safety', new_name: '이슈 상세' }, { old_key: 'visit-request', new_key: 'safety.visit_request', new_path: '/pages/safety/visit-request.html', new_category: 'safety', new_name: '방문 요청' }, { old_key: 'safety-management', new_key: 'safety.management', new_path: '/pages/safety/management.html', new_category: 'safety', new_name: '안전 관리' }, { old_key: 'safety-training-conduct', new_key: 'safety.training_conduct', new_path: '/pages/safety/training-conduct.html', new_category: 'safety', new_name: '안전교육 진행' } ]; // 2. 페이지 경로 업데이트 - attendance 폴더로 이동된 페이지들 const attendancePageUpdates = [ { old_key: 'daily-attendance', new_key: 'attendance.daily', new_path: '/pages/attendance/daily.html', new_category: 'attendance', new_name: '일일 출퇴근' }, { old_key: 'monthly-attendance', new_key: 'attendance.monthly', new_path: '/pages/attendance/monthly.html', new_category: 'attendance', new_name: '월간 근태' }, { old_key: 'annual-vacation-overview', new_key: 'attendance.annual_overview', new_path: '/pages/attendance/annual-overview.html', new_category: 'attendance', new_name: '연간 휴가 현황' }, { old_key: 'vacation-request', new_key: 'attendance.vacation_request', new_path: '/pages/attendance/vacation-request.html', new_category: 'attendance', new_name: '휴가 신청' }, { old_key: 'vacation-management', new_key: 'attendance.vacation_management', new_path: '/pages/attendance/vacation-management.html', new_category: 'attendance', new_name: '휴가 관리' }, { old_key: 'vacation-allocation', new_key: 'attendance.vacation_allocation', new_path: '/pages/attendance/vacation-allocation.html', new_category: 'attendance', new_name: '휴가 발생 입력' } ]; // 3. admin 폴더 내 파일명 변경 const adminPageUpdates = [ { old_key: 'attendance-report-comparison', new_key: 'admin.attendance_report', new_path: '/pages/admin/attendance-report.html', new_category: 'admin', new_name: '출퇴근-보고서 대조' } ]; // 모든 업데이트 실행 const allUpdates = [...safetyPageUpdates, ...attendancePageUpdates, ...adminPageUpdates]; for (const update of allUpdates) { await knex('pages') .where('page_key', update.old_key) .update({ page_key: update.new_key, page_path: update.new_path, category: update.new_category, page_name: update.new_name }); } // 4. 안전 체크리스트 관리 페이지 추가 (새로 생성된 페이지) const existingChecklistPage = await knex('pages') .where('page_key', 'safety.checklist_manage') .orWhere('page_key', 'safety-checklist-manage') .first(); if (!existingChecklistPage) { await knex('pages').insert({ page_key: 'safety.checklist_manage', page_name: '안전 체크리스트 관리', page_path: '/pages/safety/checklist-manage.html', category: 'safety', description: '안전 체크리스트 항목 관리', is_admin_only: 1, display_order: 50 }); } // 5. 휴가 승인/직접입력 페이지 추가 (새로 생성된 페이지인 경우) const vacationPages = [ { page_key: 'attendance.vacation_approval', page_name: '휴가 승인 관리', page_path: '/pages/attendance/vacation-approval.html', category: 'attendance', description: '휴가 신청 승인/거부', is_admin_only: 1, display_order: 65 }, { page_key: 'attendance.vacation_input', page_name: '휴가 직접 입력', page_path: '/pages/attendance/vacation-input.html', category: 'attendance', description: '관리자 휴가 직접 입력', is_admin_only: 1, display_order: 66 } ]; for (const page of vacationPages) { const existing = await knex('pages').where('page_key', page.page_key).first(); if (!existing) { await knex('pages').insert(page); } } // 6. role_default_pages 테이블 생성 (역할별 기본 페이지 권한) const tableExists = await knex.schema.hasTable('role_default_pages'); if (!tableExists) { await knex.schema.createTable('role_default_pages', (table) => { table.integer('role_id').unsigned().notNullable() .references('id').inTable('roles').onDelete('CASCADE'); table.integer('page_id').unsigned().notNullable() .references('id').inTable('pages').onDelete('CASCADE'); table.primary(['role_id', 'page_id']); table.timestamps(true, true); }); } // 7. 기본 역할-페이지 매핑 데이터 삽입 // 역할 조회 const roles = await knex('roles').select('id', 'name'); const pages = await knex('pages').select('id', 'page_key', 'category'); const roleMap = {}; roles.forEach(r => { roleMap[r.name] = r.id; }); const pageMap = {}; pages.forEach(p => { pageMap[p.page_key] = p.id; }); // Worker 역할 기본 페이지 (대시보드, 작업보고서, 휴가신청) const workerPages = [ 'dashboard', 'work.report_create', 'work.report_view', 'attendance.vacation_request' ]; // Leader 역할 기본 페이지 (Worker + TBM, 안전, 근태 일부) const leaderPages = [ ...workerPages, 'work.tbm', 'work.analysis', 'safety.issue_report', 'safety.issue_list', 'attendance.daily', 'attendance.monthly' ]; // SafetyManager 역할 기본 페이지 (Leader + 안전 전체) const safetyManagerPages = [ ...leaderPages, 'safety.issue_detail', 'safety.visit_request', 'safety.management', 'safety.training_conduct', 'safety.checklist_manage' ]; // 역할별 페이지 매핑 삽입 const rolePageMappings = []; if (roleMap['Worker']) { workerPages.forEach(pageKey => { if (pageMap[pageKey]) { rolePageMappings.push({ role_id: roleMap['Worker'], page_id: pageMap[pageKey] }); } }); } if (roleMap['Leader']) { leaderPages.forEach(pageKey => { if (pageMap[pageKey]) { rolePageMappings.push({ role_id: roleMap['Leader'], page_id: pageMap[pageKey] }); } }); } if (roleMap['SafetyManager']) { safetyManagerPages.forEach(pageKey => { if (pageMap[pageKey]) { rolePageMappings.push({ role_id: roleMap['SafetyManager'], page_id: pageMap[pageKey] }); } }); } // 중복 제거 후 삽입 for (const mapping of rolePageMappings) { const existing = await knex('role_default_pages') .where('role_id', mapping.role_id) .where('page_id', mapping.page_id) .first(); if (!existing) { await knex('role_default_pages').insert(mapping); } } console.log('페이지 구조 재구성 완료'); console.log(`- 업데이트된 페이지: ${allUpdates.length}개`); console.log(`- 역할별 기본 페이지 매핑: ${rolePageMappings.length}개`); }; exports.down = async function(knex) { // 1. role_default_pages 테이블 삭제 await knex.schema.dropTableIfExists('role_default_pages'); // 2. 페이지 경로 원복 - safety → work/admin const safetyRevert = [ { new_key: 'safety.issue_report', old_key: 'issue-report', old_path: '/pages/work/issue-report.html', old_category: 'work' }, { new_key: 'safety.issue_list', old_key: 'issue-list', old_path: '/pages/work/issue-list.html', old_category: 'work' }, { new_key: 'safety.issue_detail', old_key: 'issue-detail', old_path: '/pages/work/issue-detail.html', old_category: 'work' }, { new_key: 'safety.visit_request', old_key: 'visit-request', old_path: '/pages/work/visit-request.html', old_category: 'work' }, { new_key: 'safety.management', old_key: 'safety-management', old_path: '/pages/admin/safety-management.html', old_category: 'admin' }, { new_key: 'safety.training_conduct', old_key: 'safety-training-conduct', old_path: '/pages/admin/safety-training-conduct.html', old_category: 'admin' }, ]; // 3. 페이지 경로 원복 - attendance → common const attendanceRevert = [ { new_key: 'attendance.daily', old_key: 'daily-attendance', old_path: '/pages/common/daily-attendance.html', old_category: 'common' }, { new_key: 'attendance.monthly', old_key: 'monthly-attendance', old_path: '/pages/common/monthly-attendance.html', old_category: 'common' }, { new_key: 'attendance.annual_overview', old_key: 'annual-vacation-overview', old_path: '/pages/common/annual-vacation-overview.html', old_category: 'common' }, { new_key: 'attendance.vacation_request', old_key: 'vacation-request', old_path: '/pages/common/vacation-request.html', old_category: 'common' }, { new_key: 'attendance.vacation_management', old_key: 'vacation-management', old_path: '/pages/common/vacation-management.html', old_category: 'common' }, { new_key: 'attendance.vacation_allocation', old_key: 'vacation-allocation', old_path: '/pages/common/vacation-allocation.html', old_category: 'common' }, ]; // 4. admin 파일명 원복 const adminRevert = [ { new_key: 'admin.attendance_report', old_key: 'attendance-report-comparison', old_path: '/pages/admin/attendance-report-comparison.html', old_category: 'admin' } ]; const allReverts = [...safetyRevert, ...attendanceRevert, ...adminRevert]; for (const revert of allReverts) { await knex('pages') .where('page_key', revert.new_key) .update({ page_key: revert.old_key, page_path: revert.old_path, category: revert.old_category }); } // 5. 새로 추가된 페이지 삭제 await knex('pages').whereIn('page_key', [ 'safety.checklist_manage', 'attendance.vacation_approval', 'attendance.vacation_input' ]).del(); console.log('페이지 구조 재구성 롤백 완료'); };