refactor: 일일 작업 보고서 CRUD API 구조 개선
- dailyWorkReportController의 조회, 수정, 삭제(CRUD) 로직을 Service와 Model로 분리 - Promise 기반의 async/await 구조로 비동기 코드 개선 - 새로운 DB 스키마 v2의 명명 규칙 적용
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -845,6 +845,163 @@ const createReportEntries = async ({ report_date, worker_id, entries }) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* [V2] 공통 SELECT 쿼리 (새로운 스키마 기준)
|
||||
*/
|
||||
const getSelectQueryV2 = () => `
|
||||
SELECT
|
||||
dwr.report_id,
|
||||
dwr.report_date,
|
||||
dwr.worker_id,
|
||||
dwr.project_id,
|
||||
dwr.task_id,
|
||||
dwr.work_hours,
|
||||
dwr.is_error,
|
||||
dwr.error_type_code_id,
|
||||
dwr.created_by_user_id,
|
||||
w.worker_name,
|
||||
p.project_name,
|
||||
t.task_name,
|
||||
c.code_name as error_type_name,
|
||||
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 projects p ON dwr.project_id = p.project_id
|
||||
LEFT JOIN tasks t ON dwr.task_id = t.task_id
|
||||
LEFT JOIN users u ON dwr.created_by_user_id = u.user_id
|
||||
LEFT JOIN codes c ON dwr.error_type_code_id = c.code_id AND c.code_type_id = 'ERROR_TYPE'
|
||||
`;
|
||||
|
||||
/**
|
||||
* [V2] 옵션 기반으로 작업 보고서를 조회합니다. (Promise 기반)
|
||||
* @param {object} options - 조회 조건 (date, worker_id, created_by_user_id 등)
|
||||
* @returns {Promise<Array>} 조회된 작업 보고서 배열
|
||||
*/
|
||||
const getReportsWithOptions = async (options) => {
|
||||
const db = await getDb();
|
||||
let whereConditions = [];
|
||||
let queryParams = [];
|
||||
|
||||
if (options.date) {
|
||||
whereConditions.push('dwr.report_date = ?');
|
||||
queryParams.push(options.date);
|
||||
}
|
||||
if (options.worker_id) {
|
||||
whereConditions.push('dwr.worker_id = ?');
|
||||
queryParams.push(options.worker_id);
|
||||
}
|
||||
if (options.created_by_user_id) {
|
||||
whereConditions.push('dwr.created_by_user_id = ?');
|
||||
queryParams.push(options.created_by_user_id);
|
||||
}
|
||||
// 필요에 따라 다른 조건 추가 가능 (project_id 등)
|
||||
|
||||
if (whereConditions.length === 0) {
|
||||
throw new Error('조회 조건이 하나 이상 필요합니다.');
|
||||
}
|
||||
|
||||
const whereClause = whereConditions.join(' AND ');
|
||||
const sql = `${getSelectQueryV2()} WHERE ${whereClause} ORDER BY w.worker_name ASC, p.project_name ASC`;
|
||||
|
||||
try {
|
||||
const [rows] = await db.query(sql, queryParams);
|
||||
return rows;
|
||||
} catch (err) {
|
||||
console.error('[Model] 작업 보고서 조회 오류:', err);
|
||||
throw new Error('데이터베이스에서 작업 보고서를 조회하는 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* [V2] ID를 기준으로 특정 작업 보고서 항목을 수정합니다. (Promise 기반)
|
||||
* @param {string} reportId - 수정할 보고서의 ID
|
||||
* @param {object} updateData - 수정할 필드와 값
|
||||
* @returns {Promise<number>} 영향을 받은 행의 수
|
||||
*/
|
||||
const updateReportById = async (reportId, updateData) => {
|
||||
const db = await getDb();
|
||||
|
||||
// 허용된 필드 목록 (보안 및 안정성)
|
||||
const allowedFields = ['project_id', 'task_id', 'work_hours', 'is_error', 'error_type_code_id'];
|
||||
const setClauses = [];
|
||||
const queryParams = [];
|
||||
|
||||
for (const field of allowedFields) {
|
||||
if (updateData[field] !== undefined) {
|
||||
setClauses.push(`${field} = ?`);
|
||||
queryParams.push(updateData[field]);
|
||||
}
|
||||
}
|
||||
|
||||
// updated_by_user_id는 항상 업데이트
|
||||
if (updateData.updated_by_user_id) {
|
||||
setClauses.push('updated_by_user_id = ?');
|
||||
queryParams.push(updateData.updated_by_user_id);
|
||||
}
|
||||
|
||||
if (setClauses.length === 0) {
|
||||
throw new Error('수정할 데이터가 없습니다.');
|
||||
}
|
||||
|
||||
queryParams.push(reportId);
|
||||
|
||||
const sql = `UPDATE daily_work_reports SET ${setClauses.join(', ')} WHERE report_id = ?`;
|
||||
|
||||
try {
|
||||
const [result] = await db.query(sql, queryParams);
|
||||
return result.affectedRows;
|
||||
} catch (err) {
|
||||
console.error(`[Model] 작업 보고서 수정 오류 (id: ${reportId}):`, err);
|
||||
throw new Error('데이터베이스에서 작업 보고서를 수정하는 중 오류가 발생했습니다.');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* [V2] ID를 기준으로 특정 작업 보고서를 삭제합니다. (Promise 기반)
|
||||
* @param {string} reportId - 삭제할 보고서 ID
|
||||
* @param {number} deletedByUserId - 삭제를 수행하는 사용자 ID
|
||||
* @returns {Promise<number>} 영향을 받은 행의 수
|
||||
*/
|
||||
const removeReportById = async (reportId, deletedByUserId) => {
|
||||
const db = await getDb();
|
||||
const conn = await db.getConnection();
|
||||
|
||||
try {
|
||||
await conn.beginTransaction();
|
||||
|
||||
// 감사 로그를 위해 삭제 전 정보 조회
|
||||
const [reportInfo] = await conn.query('SELECT * FROM daily_work_reports WHERE report_id = ?', [reportId]);
|
||||
|
||||
// 실제 삭제 작업
|
||||
const [result] = await conn.query('DELETE FROM daily_work_reports WHERE report_id = ?', [reportId]);
|
||||
|
||||
// 감사 로그 추가 (삭제된 항목이 있고, 삭제자가 명시된 경우)
|
||||
if (reportInfo.length > 0 && deletedByUserId) {
|
||||
try {
|
||||
await conn.query(
|
||||
`INSERT INTO work_report_audit_log (action, report_id, old_values, changed_by, change_reason) VALUES (?, ?, ?, ?, ?)`,
|
||||
['DELETE', reportId, JSON.stringify(reportInfo[0]), deletedByUserId, 'Manual deletion by user']
|
||||
);
|
||||
} catch (auditErr) {
|
||||
console.warn('감사 로그 추가 실패:', auditErr.message);
|
||||
// 감사 로그 실패가 전체 트랜잭션을 롤백시키지는 않음
|
||||
}
|
||||
}
|
||||
|
||||
await conn.commit();
|
||||
return result.affectedRows;
|
||||
|
||||
} catch (err) {
|
||||
await conn.rollback();
|
||||
console.error(`[Model] 작업 보고서 삭제 오류 (id: ${reportId}):`, err);
|
||||
throw new Error('데이터베이스에서 작업 보고서를 삭제하는 중 오류가 발생했습니다.');
|
||||
} finally {
|
||||
conn.release();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 모든 함수 내보내기 (기존 기능 + 누적 기능)
|
||||
module.exports = {
|
||||
// 📋 마스터 데이터
|
||||
@@ -880,5 +1037,8 @@ module.exports = {
|
||||
getStatistics,
|
||||
|
||||
// 새로 추가된 V2 함수
|
||||
createReportEntries
|
||||
createReportEntries,
|
||||
getReportsWithOptions,
|
||||
updateReportById,
|
||||
removeReportById
|
||||
};
|
||||
@@ -79,6 +79,135 @@ const createDailyWorkReportService = async (reportData) => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 사용자 권한과 요청 파라미터에 따라 일일 작업 보고서를 조회하는 비즈니스 로직을 처리합니다.
|
||||
* @param {object} queryParams - 컨트롤러에서 전달된 쿼리 파라미터
|
||||
* @param {object} userInfo - 요청을 보낸 사용자의 정보 (id, role 등)
|
||||
* @returns {Promise<Array>} 조회된 작업 보고서 배열
|
||||
*/
|
||||
const getDailyWorkReportsService = async (queryParams, userInfo) => {
|
||||
const { date, worker_id, created_by: requested_created_by, view_all } = queryParams;
|
||||
const { user_id: current_user_id, role } = userInfo;
|
||||
|
||||
if (!date) {
|
||||
throw new Error('조회를 위해 날짜(date)는 필수입니다.');
|
||||
}
|
||||
|
||||
// 관리자 여부 확인
|
||||
const isAdmin = role === 'system' || role === 'admin';
|
||||
const canViewAll = isAdmin || view_all === 'true';
|
||||
|
||||
// 모델에 전달할 조회 옵션 객체 생성
|
||||
const options = { date };
|
||||
|
||||
if (worker_id) {
|
||||
options.worker_id = parseInt(worker_id);
|
||||
}
|
||||
|
||||
// 최종적으로 필터링할 작성자 ID 결정
|
||||
if (!canViewAll) {
|
||||
// 관리자가 아니면 자신의 데이터만 보거나, 명시적으로 요청된 자신의 ID만 허용
|
||||
options.created_by_user_id = requested_created_by ? Math.min(requested_created_by, current_user_id) : current_user_id;
|
||||
} else if (requested_created_by) {
|
||||
// 관리자는 다른 사람의 데이터도 조회 가능
|
||||
options.created_by_user_id = parseInt(requested_created_by);
|
||||
}
|
||||
// created_by_user_id가 명시되지 않으면 모든 작성자의 데이터를 조회
|
||||
|
||||
console.log('📊 [Service] 작업보고서 조회 요청:', { ...options, requester: current_user_id, isAdmin });
|
||||
|
||||
try {
|
||||
// 모델 함수 호출
|
||||
const reports = await dailyWorkReportModel.getReportsWithOptions(options);
|
||||
console.log(`✅ [Service] 작업보고서 ${reports.length}개 조회 성공`);
|
||||
return reports;
|
||||
} catch (error) {
|
||||
console.error('[Service] 작업보고서 조회 중 오류 발생:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 특정 작업 보고서 항목을 수정하는 비즈니스 로직을 처리합니다.
|
||||
* @param {string} reportId - 수정할 보고서의 ID
|
||||
* @param {object} updateData - 수정할 데이터
|
||||
* @param {object} userInfo - 요청을 보낸 사용자의 정보
|
||||
* @returns {Promise<object>} 수정 결과
|
||||
*/
|
||||
const updateWorkReportService = async (reportId, updateData, userInfo) => {
|
||||
const { user_id: updated_by } = userInfo;
|
||||
|
||||
if (!reportId || !updateData || Object.keys(updateData).length === 0) {
|
||||
throw new Error('수정을 위해 보고서 ID와 수정할 데이터가 필요합니다.');
|
||||
}
|
||||
|
||||
const modelUpdateData = { ...updateData, updated_by_user_id: updated_by };
|
||||
|
||||
console.log(`✏️ [Service] 작업보고서 수정 요청: id=${reportId}`);
|
||||
|
||||
try {
|
||||
const affectedRows = await dailyWorkReportModel.updateReportById(reportId, modelUpdateData);
|
||||
|
||||
if (affectedRows === 0) {
|
||||
// 에러를 발생시켜 컨트롤러에서 404 처리를 할 수 있도록 함
|
||||
const notFoundError = new Error('수정할 작업보고서를 찾을 수 없습니다.');
|
||||
notFoundError.statusCode = 404;
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
console.log(`✅ [Service] 작업보고서 수정 성공: id=${reportId}`);
|
||||
return {
|
||||
message: '작업보고서가 성공적으로 수정되었습니다.',
|
||||
report_id: reportId,
|
||||
affected_rows: affectedRows
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[Service] 작업보고서 수정 중 오류 발생 (id: ${reportId}):`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 특정 작업 보고서 항목을 삭제하는 비즈니스 로직을 처리합니다.
|
||||
* @param {string} reportId - 삭제할 보고서의 ID
|
||||
* @param {object} userInfo - 요청을 보낸 사용자의 정보
|
||||
* @returns {Promise<object>} 삭제 결과
|
||||
*/
|
||||
const removeDailyWorkReportService = async (reportId, userInfo) => {
|
||||
const { user_id: deleted_by } = userInfo;
|
||||
|
||||
if (!reportId) {
|
||||
throw new Error('삭제를 위해 보고서 ID가 필요합니다.');
|
||||
}
|
||||
|
||||
console.log(`🗑️ [Service] 작업보고서 삭제 요청: id=${reportId}`);
|
||||
|
||||
try {
|
||||
// 모델 함수는 삭제 전 권한 검사를 위해 deleted_by 정보를 받을 수 있습니다 (현재 모델에서는 미사용).
|
||||
const affectedRows = await dailyWorkReportModel.removeReportById(reportId, deleted_by);
|
||||
|
||||
if (affectedRows === 0) {
|
||||
const notFoundError = new Error('삭제할 작업보고서를 찾을 수 없습니다.');
|
||||
notFoundError.statusCode = 404;
|
||||
throw notFoundError;
|
||||
}
|
||||
|
||||
console.log(`✅ [Service] 작업보고서 삭제 성공: id=${reportId}`);
|
||||
return {
|
||||
message: '작업보고서가 성공적으로 삭제되었습니다.',
|
||||
report_id: reportId,
|
||||
affected_rows: affectedRows
|
||||
};
|
||||
} catch (error) {
|
||||
console.error(`[Service] 작업보고서 삭제 중 오류 발생 (id: ${reportId}):`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
createDailyWorkReportService,
|
||||
getDailyWorkReportsService,
|
||||
updateWorkReportService,
|
||||
removeDailyWorkReportService,
|
||||
};
|
||||
Reference in New Issue
Block a user