fix: Login 500, DB schema sync, Dashboard missing data, Major Refactoring
This commit is contained in:
@@ -7,7 +7,7 @@ class MonthlyStatusModel {
|
||||
// 월별 일자별 요약 조회 (캘린더용)
|
||||
static async getMonthlySummary(year, month) {
|
||||
const db = await getDb();
|
||||
|
||||
|
||||
try {
|
||||
const [rows] = await db.execute(`
|
||||
SELECT
|
||||
@@ -32,24 +32,24 @@ class MonthlyStatusModel {
|
||||
WHERE year = ? AND month = ?
|
||||
ORDER BY date ASC
|
||||
`, [year, month]);
|
||||
|
||||
|
||||
return rows;
|
||||
} catch (error) {
|
||||
console.error('월별 요약 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 특정 날짜의 작업자별 상태 조회 (모달용)
|
||||
// ✅ 리팩토링: 집계 테이블 대신 daily_work_reports에서 직접 조회 (중복 문제 완전 해결)
|
||||
static async getDailyWorkerStatus(date) {
|
||||
const db = await getDb();
|
||||
|
||||
|
||||
try {
|
||||
// daily_work_reports에서 직접 집계하여 조회 (중복 없음 보장)
|
||||
const [rows] = await db.query(`
|
||||
SELECT
|
||||
dwr.worker_id,
|
||||
w.worker_id,
|
||||
w.worker_name,
|
||||
w.job_type,
|
||||
YEAR(?) as year,
|
||||
@@ -58,7 +58,7 @@ class MonthlyStatusModel {
|
||||
COALESCE(SUM(dwr.work_hours), 0) as total_work_hours,
|
||||
COALESCE(SUM(CASE WHEN dwr.project_id != 13 THEN dwr.work_hours ELSE 0 END), 0) as actual_work_hours,
|
||||
COALESCE(SUM(CASE WHEN dwr.project_id = 13 THEN dwr.work_hours ELSE 0 END), 0) as vacation_hours,
|
||||
COUNT(*) as total_work_count,
|
||||
COUNT(dwr.id) as total_work_count,
|
||||
COUNT(CASE WHEN dwr.project_id != 13 AND dwr.work_status_id != 2 THEN 1 END) as regular_work_count,
|
||||
COUNT(CASE WHEN dwr.work_status_id = 2 THEN 1 END) as error_work_count,
|
||||
CASE
|
||||
@@ -76,24 +76,24 @@ class MonthlyStatusModel {
|
||||
ELSE 0
|
||||
END as has_issues,
|
||||
MAX(dwr.created_at) as last_updated
|
||||
FROM daily_work_reports dwr
|
||||
JOIN workers w ON dwr.worker_id = w.worker_id
|
||||
WHERE dwr.report_date = ?
|
||||
GROUP BY dwr.worker_id, w.worker_name, w.job_type
|
||||
FROM workers w
|
||||
LEFT JOIN daily_work_reports dwr ON w.worker_id = dwr.worker_id AND dwr.report_date = ?
|
||||
WHERE w.status = 'active'
|
||||
GROUP BY w.worker_id, w.worker_name, w.job_type
|
||||
ORDER BY w.worker_name ASC
|
||||
`, [date, date, date, date]);
|
||||
|
||||
|
||||
return rows;
|
||||
} catch (error) {
|
||||
console.error('일별 작업자 상태 조회 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 월별 집계 데이터 강제 재계산 (관리용)
|
||||
static async recalculateMonth(year, month) {
|
||||
const db = await getDb();
|
||||
|
||||
|
||||
try {
|
||||
// 해당 월의 모든 날짜와 작업자 조합을 찾아서 재계산
|
||||
const [workDates] = await db.execute(`
|
||||
@@ -101,27 +101,27 @@ class MonthlyStatusModel {
|
||||
FROM daily_work_reports
|
||||
WHERE YEAR(report_date) = ? AND MONTH(report_date) = ?
|
||||
`, [year, month]);
|
||||
|
||||
|
||||
let updatedCount = 0;
|
||||
|
||||
|
||||
for (const { report_date, worker_id } of workDates) {
|
||||
await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [report_date, worker_id]);
|
||||
updatedCount++;
|
||||
}
|
||||
|
||||
|
||||
console.log(`✅ ${year}년 ${month}월 집계 재계산 완료: ${updatedCount}건`);
|
||||
return { success: true, updatedCount };
|
||||
|
||||
|
||||
} catch (error) {
|
||||
console.error('월별 집계 재계산 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 특정 날짜 집계 강제 업데이트
|
||||
static async updateDateSummary(date, workerId = null) {
|
||||
const db = await getDb();
|
||||
|
||||
|
||||
try {
|
||||
if (workerId) {
|
||||
// 특정 작업자만 업데이트
|
||||
@@ -133,23 +133,23 @@ class MonthlyStatusModel {
|
||||
FROM daily_work_reports
|
||||
WHERE report_date = ?
|
||||
`, [date]);
|
||||
|
||||
|
||||
for (const { worker_id } of workers) {
|
||||
await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [date, worker_id]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return { success: true };
|
||||
} catch (error) {
|
||||
console.error('날짜별 집계 업데이트 오류:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 집계 테이블 상태 확인
|
||||
static async getStatusInfo() {
|
||||
const db = await getDb();
|
||||
|
||||
|
||||
try {
|
||||
const [summaryCount] = await db.execute(`
|
||||
SELECT
|
||||
@@ -159,7 +159,7 @@ class MonthlyStatusModel {
|
||||
MAX(last_updated) as last_update
|
||||
FROM monthly_summary
|
||||
`);
|
||||
|
||||
|
||||
const [workerStatusCount] = await db.execute(`
|
||||
SELECT
|
||||
COUNT(*) as total_records,
|
||||
@@ -168,7 +168,7 @@ class MonthlyStatusModel {
|
||||
MAX(last_updated) as last_update
|
||||
FROM monthly_worker_status
|
||||
`);
|
||||
|
||||
|
||||
return {
|
||||
summary: summaryCount[0],
|
||||
workerStatus: workerStatusCount[0]
|
||||
|
||||
@@ -2,16 +2,16 @@ const { getDb } = require('../dbPool');
|
||||
|
||||
// 사용자 조회
|
||||
const findByUsername = async (username) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
'SELECT user_id, username, password, name, email, role, access_level, worker_id, is_active, last_login_at, password_changed_at, failed_login_attempts, locked_until, created_at, updated_at FROM users WHERE username = ?', [username]
|
||||
);
|
||||
return rows[0];
|
||||
} catch (err) {
|
||||
console.error('DB 오류 - 사용자 조회 실패:', err);
|
||||
throw err;
|
||||
}
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
'SELECT user_id, username, password, name, email, role, access_level, worker_id, is_active, last_login_at, password_changed_at, failed_login_attempts, locked_until, created_at, updated_at FROM users WHERE username = ?', [username]
|
||||
);
|
||||
return rows[0];
|
||||
} catch (err) {
|
||||
console.error('DB 오류 - 사용자 조회 실패:', err);
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -21,7 +21,7 @@ const findByUsername = async (username) => {
|
||||
const incrementFailedLoginAttempts = async (userId) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
await db.execute(
|
||||
await db.query(
|
||||
'UPDATE users SET failed_login_attempts = failed_login_attempts + 1 WHERE user_id = ?',
|
||||
[userId]
|
||||
);
|
||||
@@ -38,7 +38,7 @@ const incrementFailedLoginAttempts = async (userId) => {
|
||||
const lockUserAccount = async (userId) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
await db.execute(
|
||||
await db.query(
|
||||
'UPDATE users SET locked_until = DATE_ADD(NOW(), INTERVAL 15 MINUTE) WHERE user_id = ?',
|
||||
[userId]
|
||||
);
|
||||
@@ -55,7 +55,7 @@ const lockUserAccount = async (userId) => {
|
||||
const resetLoginAttempts = async (userId) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
await db.execute(
|
||||
await db.query(
|
||||
'UPDATE users SET last_login_at = NOW(), failed_login_attempts = 0, locked_until = NULL WHERE user_id = ?',
|
||||
[userId]
|
||||
);
|
||||
@@ -68,8 +68,8 @@ const resetLoginAttempts = async (userId) => {
|
||||
|
||||
// 명확한 내보내기
|
||||
module.exports = {
|
||||
findByUsername,
|
||||
incrementFailedLoginAttempts,
|
||||
lockUserAccount,
|
||||
resetLoginAttempts
|
||||
findByUsername,
|
||||
incrementFailedLoginAttempts,
|
||||
lockUserAccount,
|
||||
resetLoginAttempts
|
||||
};
|
||||
Reference in New Issue
Block a user