refactor: 일일 작업 보고서 CRUD API 구조 개선

- dailyWorkReportController의 조회, 수정, 삭제(CRUD) 로직을 Service와 Model로 분리
 - Promise 기반의 async/await 구조로 비동기 코드 개선
 - 새로운 DB 스키마 v2의 명명 규칙 적용
This commit is contained in:
2025-07-28 11:19:28 +09:00
parent 97e32a7057
commit d154514fa0
3 changed files with 363 additions and 174 deletions

View File

@@ -182,110 +182,29 @@ const removeMyEntry = (req, res) => {
};
/**
* 📊 작업보고서 조회 (권한별 전체 조회 지원 - 핵심 수정!)
* 📊 작업보고서 조회 (V2 - Service Layer 사용)
*/
const getDailyWorkReports = (req, res) => {
const { date, worker_id, created_by: requested_created_by, view_all, admin, all, no_filter, ignore_created_by } = req.query;
const current_user_id = req.user?.user_id || req.user?.id;
const user_access_level = req.user?.access_level;
const getDailyWorkReports = async (req, res) => {
try {
const userInfo = {
user_id: req.user?.user_id || req.user?.id,
role: req.user?.role || 'user' // 기본값을 'user'로 설정하여 안전하게 처리
};
if (!current_user_id) {
return res.status(401).json({
error: '사용자 인증 정보가 없습니다.'
});
}
if (!userInfo.user_id) {
return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' });
}
// 🎯 권한별 필터링 로직 개선
const isAdmin = user_access_level === 'system' || user_access_level === 'admin';
const hasViewAllFlag = view_all === 'true' || admin === 'true' || all === 'true' ||
no_filter === 'true' || ignore_created_by === 'true' ||
requested_created_by === 'all' || requested_created_by === '';
const canViewAll = isAdmin || hasViewAllFlag;
// 관리자가 아니고 전체 조회 플래그도 없으면 본인 작성분으로 제한
let final_created_by = null;
if (!canViewAll) {
final_created_by = requested_created_by || current_user_id;
} else if (requested_created_by && requested_created_by !== 'all' && requested_created_by !== '') {
final_created_by = requested_created_by;
}
const reports = await dailyWorkReportService.getDailyWorkReportsService(req.query, userInfo);
res.json(reports);
console.log('📊 작업보고서 조회 요청:', {
date,
worker_id,
requested_created_by,
current_user_id,
user_access_level,
isAdmin,
hasViewAllFlag,
canViewAll,
final_created_by
});
if (date && final_created_by) {
// 날짜 + 작성자별 조회
dailyWorkReportModel.getByDateAndCreator(date, final_created_by, (err, data) => {
if (err) {
console.error('작업보고서 조회 오류:', err);
return res.status(500).json({
error: '작업보고서 조회 중 오류가 발생했습니다.',
details: err.message
});
}
console.log(`📊 날짜+작성자별 조회 결과: ${data.length}`);
res.json(data);
});
} else if (date && worker_id) {
// 날짜 + 작업자별 조회
dailyWorkReportModel.getByDateAndWorker(date, worker_id, (err, data) => {
if (err) {
console.error('작업보고서 조회 오류:', err);
return res.status(500).json({
error: '작업보고서 조회 중 오류가 발생했습니다.',
details: err.message
});
}
// 🎯 권한별 필터링
let finalData = data;
if (!canViewAll) {
finalData = data.filter(report => report.created_by === current_user_id);
console.log(`📊 권한 필터링: 전체 ${data.length}개 → ${finalData.length}`);
} else {
console.log(`📊 관리자/전체 조회 권한: ${data.length}개 전체 반환`);
}
res.json(finalData);
});
} else if (date) {
// 날짜별 조회
dailyWorkReportModel.getByDate(date, (err, data) => {
if (err) {
console.error('작업보고서 조회 오류:', err);
return res.status(500).json({
error: '작업보고서 조회 중 오류가 발생했습니다.',
details: err.message
});
}
// 🎯 권한별 필터링
let finalData = data;
if (!canViewAll) {
finalData = data.filter(report => report.created_by === current_user_id);
console.log(`📊 권한 필터링: 전체 ${data.length}개 → ${finalData.length}`);
} else {
console.log(`📊 관리자/전체 조회 권한: ${data.length}개 전체 반환`);
}
res.json(finalData);
});
} else {
} catch (error) {
console.error('💥 작업보고서 조회 컨트롤러 오류:', error.message);
res.status(400).json({
error: '날짜(date) 파라미터가 필요합니다.',
example: 'date=2024-06-16',
optional: ['worker_id', 'created_by', 'view_all', 'admin', 'all']
success: false,
error: '작업보고서 조회에 실패했습니다.',
details: error.message
});
}
};
@@ -498,94 +417,75 @@ const getMonthlySummary = (req, res) => {
};
/**
* ✏️ 작업보고서 수정
* ✏️ 작업보고서 수정 (V2 - Service Layer 사용)
*/
const updateWorkReport = (req, res) => {
const { id } = req.params;
const updateData = req.body;
const updated_by = req.user?.user_id || req.user?.id;
const updateWorkReport = async (req, res) => {
try {
const { id: reportId } = req.params;
const updateData = req.body;
const userInfo = {
user_id: req.user?.user_id || req.user?.id,
role: req.user?.role || 'user'
};
if (!updated_by) {
return res.status(401).json({
error: '사용자 인증 정보가 없습니다.'
if (!userInfo.user_id) {
return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' });
}
const result = await dailyWorkReportService.updateWorkReportService(reportId, updateData, userInfo);
res.json({
success: true,
timestamp: new Date().toISOString(),
...result
});
} catch (error) {
console.error(`💥 작업보고서 수정 컨트롤러 오류 (id: ${req.params.id}):`, error.message);
const statusCode = error.statusCode || 400;
res.status(statusCode).json({
success: false,
error: '작업보고서 수정에 실패했습니다.',
details: error.message
});
}
updateData.updated_by = updated_by;
console.log(`✏️ 작업보고서 수정 요청: id=${id}, 수정자=${updated_by}`);
dailyWorkReportModel.updateById(id, updateData, (err, affectedRows) => {
if (err) {
console.error('작업보고서 수정 오류:', err);
return res.status(500).json({
error: '작업보고서 수정 중 오류가 발생했습니다.',
details: err.message
});
}
if (affectedRows === 0) {
return res.status(404).json({
error: '수정할 작업보고서를 찾을 수 없습니다.',
id: id
});
}
console.log(`✅ 작업보고서 수정 완료: id=${id}`);
res.json({
message: '작업보고서가 성공적으로 수정되었습니다.',
id: id,
affected_rows: affectedRows,
updated_by,
timestamp: new Date().toISOString()
});
});
};
/**
* 🗑️ 특정 작업보고서 삭제
* 🗑️ 특정 작업보고서 삭제 (V2 - Service Layer 사용)
*/
const removeDailyWorkReport = (req, res) => {
const { id } = req.params;
const deleted_by = req.user?.user_id || req.user?.id;
const removeDailyWorkReport = async (req, res) => {
try {
const { id: reportId } = req.params;
const userInfo = {
user_id: req.user?.user_id || req.user?.id,
};
if (!deleted_by) {
return res.status(401).json({
error: '사용자 인증 정보가 없습니다.'
if (!userInfo.user_id) {
return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' });
}
const result = await dailyWorkReportService.removeDailyWorkReportService(reportId, userInfo);
res.json({
success: true,
timestamp: new Date().toISOString(),
...result
});
} catch (error) {
console.error(`💥 작업보고서 삭제 컨트롤러 오류 (id: ${req.params.id}):`, error.message);
const statusCode = error.statusCode || 400;
res.status(statusCode).json({
success: false,
error: '작업보고서 삭제에 실패했습니다.',
details: error.message
});
}
console.log(`🗑️ 작업보고서 삭제 요청: id=${id}, 삭제자=${deleted_by}`);
dailyWorkReportModel.removeById(id, deleted_by, (err, affectedRows) => {
if (err) {
console.error('작업보고서 삭제 오류:', err);
return res.status(500).json({
error: '작업보고서 삭제 중 오류가 발생했습니다.',
details: err.message
});
}
if (affectedRows === 0) {
return res.status(404).json({
error: '삭제할 작업보고서를 찾을 수 없습니다.',
id: id
});
}
console.log(`✅ 작업보고서 삭제 완료: id=${id}`);
res.json({
message: '작업보고서가 성공적으로 삭제되었습니다.',
id: id,
affected_rows: affectedRows,
deleted_by,
timestamp: new Date().toISOString()
});
});
};
/**
* 🗑 작업자의 특정 날짜 전체 삭제
* <EFBFBD><EFBFBD> 작업자의 특정 날짜 전체 삭제
*/
const removeDailyWorkReportByDateAndWorker = (req, res) => {
const { date, worker_id } = req.params;