refactor: worker_id → user_id 전체 마이그레이션 (Phase 1-4)

sso_users.user_id를 단일 식별자로 통합. JWT에서 worker_id 제거,
department_id/is_production 추가. 백엔드 15개 모델, 11개 컨트롤러,
4개 서비스, 7개 라우트, 프론트엔드 32+ JS/11+ HTML 변환.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-05 13:13:10 +09:00
parent 2197cdb3d5
commit abd7564e6b
90 changed files with 1790 additions and 925 deletions

View File

@@ -32,7 +32,7 @@ router.get('/attendance-types', AttendanceController.getAttendanceTypes);
router.get('/vacation-types', AttendanceController.getVacationTypes);
// 작업자 휴가 잔여 조회
router.get('/vacation-balance/:worker_id', AttendanceController.getWorkerVacationBalance);
router.get('/vacation-balance/:user_id', AttendanceController.getWorkerVacationBalance);
// 월별 근태 통계
router.get('/monthly-stats', AttendanceController.getMonthlyAttendanceStats);

View File

@@ -26,22 +26,22 @@ router.put('/error-types/:id', dailyWorkReportController.updateErrorType);
router.delete('/error-types/:id', dailyWorkReportController.deleteErrorType);
// 🔄 누적 관련 새로운 라우트들 (누적입력 시스템 전용)
router.get('/accumulated', dailyWorkReportController.getAccumulatedReports); // ?date=2024-06-16&worker_id=1
router.get('/contributors', dailyWorkReportController.getContributorsSummary); // ?date=2024-06-16&worker_id=1
router.get('/my-data', dailyWorkReportController.getMyAccumulatedData); // ?date=2024-06-16&worker_id=1
router.get('/accumulated', dailyWorkReportController.getAccumulatedReports); // ?date=2024-06-16&user_id=1
router.get('/contributors', dailyWorkReportController.getContributorsSummary); // ?date=2024-06-16&user_id=1
router.get('/my-data', dailyWorkReportController.getMyAccumulatedData); // ?date=2024-06-16&user_id=1
// ✅ check-overwrite 엔드포인트 추가 (누락된 엔드포인트)
router.get('/check-overwrite', (req, res) => {
const { date, worker_id } = req.query;
if (!date || !worker_id) {
return res.status(400).json({
error: 'date와 worker_id가 필요합니다.',
example: 'date=2025-06-16&worker_id=1'
const { date, user_id } = req.query;
if (!date || !user_id) {
return res.status(400).json({
error: 'date와 user_id가 필요합니다.',
example: 'date=2025-06-16&user_id=1'
});
}
console.log(`🔍 덮어쓰기 권한 확인: 날짜=${date}, 작업자=${worker_id} (누적입력모드)`);
console.log(`🔍 덮어쓰기 권한 확인: 날짜=${date}, 작업자=${user_id} (누적입력모드)`);
// 누적입력 시스템에서는 항상 덮어쓰기 가능 (실제로는 누적만 함)
res.json({
@@ -49,7 +49,7 @@ router.get('/check-overwrite', (req, res) => {
reason: 'accumulate_mode',
message: '누적입력 모드에서는 항상 추가 가능합니다.',
date,
worker_id,
user_id,
timestamp: new Date().toISOString()
});
});
@@ -84,7 +84,7 @@ router.get('/', dailyWorkReportController.getDailyWorkReports);
router.put('/:id', dailyWorkReportController.updateWorkReport);
// 🗑️ 작업자의 특정 날짜 전체 삭제
router.delete('/date/:date/worker/:worker_id', dailyWorkReportController.removeDailyWorkReportByDateAndWorker);
router.delete('/date/:date/worker/:user_id', dailyWorkReportController.removeDailyWorkReportByDateAndWorker);
// 🗑️ 특정 작업보고서 삭제 (항상 가장 마지막에 정의)
router.delete('/:id', dailyWorkReportController.removeDailyWorkReport);

View File

@@ -231,7 +231,7 @@ router.post('/migrations/fix-work-type-id', async (req, res) => {
dwr.report_date
FROM daily_work_reports dwr
INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id
INNER JOIN workers w ON dwr.worker_id = w.worker_id
INNER JOIN workers w ON dwr.user_id = w.user_id
WHERE dwr.tbm_assignment_id IS NOT NULL
AND ta.task_id IS NOT NULL
AND dwr.work_type_id != ta.task_id
@@ -271,7 +271,7 @@ router.post('/migrations/fix-work-type-id', async (req, res) => {
INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id
LEFT JOIN tasks t ON dwr.work_type_id = t.task_id
LEFT JOIN work_types wt ON t.work_type_id = wt.id
LEFT JOIN workers w ON dwr.worker_id = w.worker_id
LEFT JOIN workers w ON dwr.user_id = w.user_id
WHERE dwr.tbm_assignment_id IS NOT NULL
ORDER BY dwr.report_date DESC
LIMIT 10

View File

@@ -48,7 +48,7 @@ router.get('/sessions/:sessionId/team', requireAuth, TbmController.getTeamMember
router.delete('/sessions/:sessionId/team/clear', requireAuth, TbmController.clearAllTeamMembers);
// 팀원 제거
router.delete('/sessions/:sessionId/team/:workerId', requireAuth, TbmController.removeTeamMember);
router.delete('/sessions/:sessionId/team/:userId', requireAuth, TbmController.removeTeamMember);
// ==================== 안전 체크리스트 관련 ====================

View File

@@ -59,7 +59,7 @@ router.get('/me/attendance-records', async (req, res) => {
const AttendanceModel = require('../models/attendanceModel');
const startDate = `${year}-${String(month).padStart(2, '0')}-01`;
const endDate = `${year}-${String(month).padStart(2, '0')}-31`;
const records = await AttendanceModel.getDailyRecords(startDate, endDate, req.user.worker_id);
const records = await AttendanceModel.getDailyRecords(startDate, endDate, req.user.user_id);
res.json({ success: true, data: records });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
@@ -71,7 +71,7 @@ router.get('/me/vacation-balance', async (req, res) => {
try {
const AttendanceModel = require('../models/attendanceModel');
const year = req.query.year || new Date().getFullYear();
const balance = await AttendanceModel.getWorkerVacationBalance(req.user.worker_id, year);
const balance = await AttendanceModel.getWorkerVacationBalance(req.user.user_id, year);
res.json({ success: true, data: balance });
} catch (error) {
res.status(500).json({ success: false, error: error.message });
@@ -84,8 +84,8 @@ router.get('/me/work-reports', async (req, res) => {
const { startDate, endDate } = req.query;
const db = require('../config/database');
const reports = await db.query(
'SELECT * FROM daily_work_reports WHERE worker_id = ? AND report_date BETWEEN ? AND ? ORDER BY report_date DESC',
[req.user.worker_id, startDate, endDate]
'SELECT * FROM daily_work_reports WHERE user_id = ? AND report_date BETWEEN ? AND ? ORDER BY report_date DESC',
[req.user.user_id, startDate, endDate]
);
res.json({ success: true, data: reports });
} catch (error) {
@@ -104,8 +104,8 @@ router.get('/me/monthly-stats', async (req, res) => {
SUM(total_work_hours) as month_hours,
COUNT(DISTINCT record_date) as work_days
FROM daily_attendance_records
WHERE worker_id = ? AND YEAR(record_date) = ? AND MONTH(record_date) = ?`,
[req.user.worker_id, year, month]
WHERE user_id = ? AND YEAR(record_date) = ? AND MONTH(record_date) = ?`,
[req.user.user_id, year, month]
);
res.json({ success: true, data: stats[0] || { month_hours: 0, work_days: 0 } });
} catch (error) {

View File

@@ -11,10 +11,10 @@ const vacationBalanceController = require('../controllers/vacationBalanceControl
router.get('/year/:year', vacationBalanceController.getAllByYear);
// 특정 작업자의 휴가 잔액 조회 (특정 연도)
router.get('/worker/:workerId/year/:year', vacationBalanceController.getByWorkerAndYear);
router.get('/worker/:userId/year/:year', vacationBalanceController.getByWorkerAndYear);
// 작업자의 사용 가능한 휴가 일수 조회
router.get('/worker/:workerId/year/:year/available', vacationBalanceController.getAvailableDays);
router.get('/worker/:userId/year/:year/available', vacationBalanceController.getAvailableDays);
// 근속년수 기반 연차 자동 계산 및 생성 (관리자만)
router.post('/auto-calculate', vacationBalanceController.autoCalculateAndCreate);

View File

@@ -96,7 +96,7 @@ router.get('/', workerController.getAllWorkers);
/**
* @swagger
* /api/workers/{worker_id}:
* /api/workers/{user_id}:
* get:
* tags: [Workers]
* summary: 특정 작업자 조회
@@ -105,7 +105,7 @@ router.get('/', workerController.getAllWorkers);
* - bearerAuth: []
* parameters:
* - in: path
* name: worker_id
* name: user_id
* required: true
* schema:
* type: integer
@@ -142,7 +142,7 @@ router.get('/', workerController.getAllWorkers);
* - bearerAuth: []
* parameters:
* - in: path
* name: worker_id
* name: user_id
* required: true
* schema:
* type: integer
@@ -193,7 +193,7 @@ router.get('/', workerController.getAllWorkers);
* - bearerAuth: []
* parameters:
* - in: path
* name: worker_id
* name: user_id
* required: true
* schema:
* type: integer
@@ -221,8 +221,8 @@ router.get('/', workerController.getAllWorkers);
* 500:
* description: 서버 오류
*/
router.get('/:worker_id', workerController.getWorkerById);
router.put('/:worker_id', workerController.updateWorker);
router.delete('/:worker_id', workerController.removeWorker);
router.get('/:user_id', workerController.getWorkerById);
router.put('/:user_id', workerController.updateWorker);
router.delete('/:user_id', workerController.removeWorker);
module.exports = router;