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

@@ -31,9 +31,9 @@ const getAnalysisFilters = asyncHandler(async (req, res) => {
// 작업자 목록
const [workers] = await db.query(`
SELECT DISTINCT w.worker_id, w.worker_name
SELECT DISTINCT w.user_id, w.worker_name
FROM workers w
INNER JOIN daily_work_reports dwr ON w.worker_id = dwr.worker_id
INNER JOIN daily_work_reports dwr ON w.user_id = dwr.user_id
ORDER BY w.worker_name
`);
@@ -79,7 +79,7 @@ const getAnalysisFilters = asyncHandler(async (req, res) => {
* 기간별 작업 분석 데이터 조회
*/
const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
const { start_date, end_date, project_id, worker_id } = req.query;
const { start_date, end_date, project_id, user_id } = req.query;
if (!start_date || !end_date) {
throw new ValidationError('start_date와 end_date가 필요합니다', {
@@ -93,7 +93,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
start_date,
end_date,
project_id,
worker_id
user_id
});
const db = await getDb();
@@ -108,9 +108,9 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
queryParams.push(project_id);
}
if (worker_id) {
whereConditions.push('dwr.worker_id = ?');
queryParams.push(worker_id);
if (user_id) {
whereConditions.push('dwr.user_id = ?');
queryParams.push(user_id);
}
const whereClause = whereConditions.join(' AND ');
@@ -120,7 +120,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
SELECT
COUNT(*) as total_entries,
SUM(dwr.work_hours) as total_hours,
COUNT(DISTINCT dwr.worker_id) as unique_workers,
COUNT(DISTINCT dwr.user_id) as unique_workers,
COUNT(DISTINCT dwr.project_id) as unique_projects,
COUNT(DISTINCT dwr.report_date) as working_days,
AVG(dwr.work_hours) as avg_hours_per_entry,
@@ -139,7 +139,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
dwr.report_date,
SUM(dwr.work_hours) as daily_hours,
COUNT(*) as daily_entries,
COUNT(DISTINCT dwr.worker_id) as daily_workers
COUNT(DISTINCT dwr.user_id) as daily_workers
FROM daily_work_reports dwr
WHERE ${whereClause}
GROUP BY dwr.report_date
@@ -202,7 +202,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
// 6. 작업자별 성과 분석
const workerAnalysisSql = `
SELECT
w.worker_id,
w.user_id,
w.worker_name,
COUNT(*) as total_entries,
SUM(dwr.work_hours) as total_hours,
@@ -212,9 +212,9 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count,
ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate
FROM daily_work_reports dwr
LEFT JOIN workers w ON dwr.worker_id = w.worker_id
LEFT JOIN workers w ON dwr.user_id = w.user_id
WHERE ${whereClause}
GROUP BY w.worker_id, w.worker_name
GROUP BY w.user_id, w.worker_name
ORDER BY total_hours DESC
`;
@@ -227,7 +227,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
p.project_name,
COUNT(*) as total_entries,
SUM(dwr.work_hours) as total_hours,
COUNT(DISTINCT dwr.worker_id) as workers_count,
COUNT(DISTINCT dwr.user_id) as workers_count,
COUNT(DISTINCT dwr.report_date) as working_days,
AVG(dwr.work_hours) as avg_hours_per_entry,
COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count,
@@ -259,7 +259,7 @@ const getAnalyticsByPeriod = asyncHandler(async (req, res) => {
workerAnalysis,
projectAnalysis,
period: { start_date, end_date },
filters: { project_id, worker_id }
filters: { project_id, user_id }
},
message: '기간별 분석 데이터 조회 성공'
});
@@ -311,7 +311,7 @@ const getProjectAnalysis = asyncHandler(async (req, res) => {
p.project_name,
SUM(dwr.work_hours) as total_hours,
COUNT(*) as total_entries,
COUNT(DISTINCT dwr.worker_id) as workers_count,
COUNT(DISTINCT dwr.user_id) as workers_count,
COUNT(DISTINCT dwr.report_date) as working_days,
AVG(dwr.work_hours) as avg_hours_per_entry
FROM daily_work_reports dwr
@@ -351,7 +351,7 @@ const getProjectAnalysis = asyncHandler(async (req, res) => {
* 작업자별 상세 분석
*/
const getWorkerAnalysis = asyncHandler(async (req, res) => {
const { start_date, end_date, worker_id } = req.query;
const { start_date, end_date, user_id } = req.query;
if (!start_date || !end_date) {
throw new ValidationError('start_date와 end_date가 필요합니다', {
@@ -363,7 +363,7 @@ const getWorkerAnalysis = asyncHandler(async (req, res) => {
logger.info('작업자별 분석 조회 요청', {
start_date,
end_date,
worker_id
user_id
});
const db = await getDb();
@@ -372,16 +372,16 @@ const getWorkerAnalysis = asyncHandler(async (req, res) => {
let whereConditions = ['dwr.report_date BETWEEN ? AND ?'];
let queryParams = [start_date, end_date];
if (worker_id) {
whereConditions.push('dwr.worker_id = ?');
queryParams.push(worker_id);
if (user_id) {
whereConditions.push('dwr.user_id = ?');
queryParams.push(user_id);
}
const whereClause = whereConditions.join(' AND ');
const workerStatsSql = `
SELECT
dwr.worker_id,
dwr.user_id,
w.worker_name,
SUM(dwr.work_hours) as total_hours,
COUNT(*) as total_entries,
@@ -389,9 +389,9 @@ const getWorkerAnalysis = asyncHandler(async (req, res) => {
COUNT(DISTINCT dwr.report_date) as working_days,
AVG(dwr.work_hours) as avg_hours_per_entry
FROM daily_work_reports dwr
LEFT JOIN workers w ON dwr.worker_id = w.worker_id
LEFT JOIN workers w ON dwr.user_id = w.user_id
WHERE ${whereClause}
GROUP BY dwr.worker_id
GROUP BY dwr.user_id
ORDER BY total_hours DESC
`;