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

@@ -12,7 +12,7 @@ class WorkAnalysis {
COALESCE(SUM(work_hours), 0) as total_hours,
COUNT(*) as total_reports,
COUNT(DISTINCT project_id) as active_projects,
COUNT(DISTINCT worker_id) as active_workers,
COUNT(DISTINCT user_id) as active_workers,
SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as error_reports,
ROUND(AVG(work_hours), 2) as avg_hours_per_report
FROM daily_work_reports
@@ -47,7 +47,7 @@ class WorkAnalysis {
report_date as date,
SUM(work_hours) as hours,
COUNT(*) as reports,
COUNT(DISTINCT worker_id) as workers,
COUNT(DISTINCT user_id) as workers,
SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as errors
FROM daily_work_reports
WHERE report_date BETWEEN ? AND ?
@@ -73,7 +73,7 @@ class WorkAnalysis {
async getWorkerStats(startDate, endDate) {
const query = `
SELECT
dwr.worker_id,
dwr.user_id,
w.worker_name,
SUM(dwr.work_hours) as totalHours,
COUNT(*) as totalReports,
@@ -82,17 +82,17 @@ class WorkAnalysis {
SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount,
COUNT(DISTINCT dwr.report_date) as workingDays
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 dwr.report_date BETWEEN ? AND ?
GROUP BY dwr.worker_id, w.worker_name
GROUP BY dwr.user_id, w.worker_name
ORDER BY totalHours DESC
`;
try {
const [results] = await this.db.execute(query, [startDate, endDate]);
return results.map(row => ({
worker_id: row.worker_id,
worker_name: row.worker_name || `작업자 ${row.worker_id}`,
user_id: row.user_id,
worker_name: row.worker_name || `작업자 ${row.user_id}`,
totalHours: parseFloat(row.totalHours) || 0,
totalReports: parseInt(row.totalReports) || 0,
avgHours: parseFloat(row.avgHours) || 0,
@@ -114,7 +114,7 @@ class WorkAnalysis {
p.project_name,
SUM(dwr.work_hours) as totalHours,
COUNT(*) as totalReports,
COUNT(DISTINCT dwr.worker_id) as workerCount,
COUNT(DISTINCT dwr.user_id) as workerCount,
ROUND(AVG(dwr.work_hours), 2) as avgHours,
SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount,
COUNT(DISTINCT dwr.report_date) as activeDays
@@ -152,7 +152,7 @@ class WorkAnalysis {
SUM(dwr.work_hours) as totalHours,
COUNT(*) as totalReports,
ROUND(AVG(dwr.work_hours), 2) as avgHours,
COUNT(DISTINCT dwr.worker_id) as workerCount,
COUNT(DISTINCT dwr.user_id) as workerCount,
SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount,
COUNT(DISTINCT dwr.project_id) as projectCount
FROM daily_work_reports dwr
@@ -190,7 +190,7 @@ class WorkAnalysis {
SELECT
dwr.id,
dwr.report_date,
dwr.worker_id,
dwr.user_id,
w.worker_name,
dwr.project_id,
p.project_name,
@@ -215,7 +215,7 @@ class WorkAnalysis {
u.name as created_by_name,
dwr.created_at
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
LEFT JOIN projects p ON dwr.project_id = p.project_id
LEFT JOIN work_types wt ON dwr.work_type_id = wt.id
LEFT JOIN tasks t ON dwr.work_type_id = t.task_id
@@ -234,8 +234,8 @@ class WorkAnalysis {
return results.map(row => ({
id: row.id,
report_date: row.report_date,
worker_id: row.worker_id,
worker_name: row.worker_name || `작업자 ${row.worker_id}`,
user_id: row.user_id,
worker_name: row.worker_name || `작업자 ${row.user_id}`,
project_id: row.project_id,
project_name: row.project_name || `프로젝트 ${row.project_id}`,
job_no: row.job_no || 'N/A',
@@ -274,7 +274,7 @@ class WorkAnalysis {
SUM(work_hours) as total_hours,
COUNT(*) as total_reports,
ROUND(AVG(work_hours), 2) as avg_hours,
COUNT(DISTINCT worker_id) as active_workers
COUNT(DISTINCT user_id) as active_workers
FROM daily_work_reports
WHERE report_date BETWEEN ? AND ?
GROUP BY DAYOFWEEK(report_date)
@@ -306,7 +306,7 @@ class WorkAnalysis {
irc.category_name as error_category_name,
COUNT(*) as error_count,
SUM(dwr.work_hours) as total_hours,
COUNT(DISTINCT dwr.worker_id) as affected_workers,
COUNT(DISTINCT dwr.user_id) as affected_workers,
COUNT(DISTINCT dwr.project_id) as affected_projects
FROM daily_work_reports dwr
LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id
@@ -341,7 +341,7 @@ class WorkAnalysis {
MONTHNAME(report_date) as month_name,
SUM(work_hours) as total_hours,
COUNT(*) as total_reports,
COUNT(DISTINCT worker_id) as active_workers,
COUNT(DISTINCT user_id) as active_workers,
COUNT(DISTINCT project_id) as active_projects,
SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as error_count
FROM daily_work_reports
@@ -371,7 +371,7 @@ class WorkAnalysis {
async getWorkerSpecialization(startDate, endDate) {
const query = `
SELECT
dwr.worker_id,
dwr.user_id,
w.worker_name,
dwr.work_type_id,
wt.name as work_type_name,
@@ -382,24 +382,24 @@ class WorkAnalysis {
ROUND((SUM(dwr.work_hours) / (
SELECT SUM(work_hours)
FROM daily_work_reports
WHERE worker_id = dwr.worker_id
WHERE user_id = dwr.user_id
AND report_date BETWEEN ? AND ?
)) * 100, 2) as percentage
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
LEFT JOIN work_types wt ON dwr.work_type_id = wt.id
LEFT JOIN projects p ON dwr.project_id = p.project_id
WHERE dwr.report_date BETWEEN ? AND ?
GROUP BY dwr.worker_id, w.worker_name, dwr.work_type_id, wt.name, dwr.project_id, p.project_name
GROUP BY dwr.user_id, w.worker_name, dwr.work_type_id, wt.name, dwr.project_id, p.project_name
HAVING totalHours > 0
ORDER BY dwr.worker_id, totalHours DESC
ORDER BY dwr.user_id, totalHours DESC
`;
try {
const [results] = await this.db.execute(query, [startDate, endDate, startDate, endDate]);
return results.map(row => ({
worker_id: row.worker_id,
worker_name: row.worker_name || `작업자 ${row.worker_id}`,
user_id: row.user_id,
worker_name: row.worker_name || `작업자 ${row.user_id}`,
work_type_id: row.work_type_id,
work_type_name: row.work_type_name || `작업유형 ${row.work_type_id}`,
project_id: row.project_id,