Replaced `SELECT *` statements across multiple data models with explicit column lists to improve query performance, reduce data transfer, and increase code clarity. This is part of the Phase 2 refactoring plan. - Refactored queries in the following models: - projectModel - toolsModel - attendanceModel - dailyIssueReportModel - issueTypeModel - workReportModel - userModel - dailyWorkReportModel fix(api): Add missing volume mounts to docker-compose Modified docker-compose.yml to mount the `config`, `middlewares`, `utils`, and `services` directories into the API container. This fixes a `MODULE_NOT_FOUND` error that caused the container to crash on startup. feat(db): Add migration for missing project columns Created a new database migration to add `is_active`, `project_status`, and `completed_date` columns to the `projects` table, resolving an inconsistency between the model code and the schema. docs: Add deployment notes Added a new markdown file to document the testing (macOS, Docker Desktop) and production (Synology NAS, Container Manager) environments.
154 lines
4.3 KiB
JavaScript
154 lines
4.3 KiB
JavaScript
const { getDb } = require('../dbPool');
|
|
|
|
/**
|
|
* 1. 여러 개의 이슈 보고서를 트랜잭션으로 생성합니다.
|
|
* @param {Array<object>} reports - 생성할 보고서 데이터 배열
|
|
* @returns {Promise<Array<number>>} - 삽입된 ID 배열
|
|
*/
|
|
const createMany = async (reports) => {
|
|
const db = await getDb();
|
|
const conn = await db.getConnection();
|
|
try {
|
|
await conn.beginTransaction();
|
|
|
|
const insertedIds = [];
|
|
const sql = `
|
|
INSERT INTO DailyIssueReports
|
|
(date, worker_id, project_id, start_time, end_time, issue_type_id)
|
|
VALUES (?, ?, ?, ?, ?, ?)
|
|
`;
|
|
|
|
for (const report of reports) {
|
|
const { date, worker_id, project_id, start_time, end_time, issue_type_id } = report;
|
|
const [result] = await conn.query(sql, [date, worker_id, project_id, start_time, end_time, issue_type_id]);
|
|
insertedIds.push(result.insertId);
|
|
}
|
|
|
|
await conn.commit();
|
|
return insertedIds;
|
|
} catch (err) {
|
|
await conn.rollback();
|
|
console.error('[Model] 여러 이슈 보고서 생성 중 오류:', err);
|
|
throw new Error('데이터베이스에 이슈 보고서를 생성하는 중 오류가 발생했습니다.');
|
|
} finally {
|
|
conn.release();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 2. 특정 날짜의 전체 이슈 목록 조회 (Promise 기반)
|
|
*/
|
|
const getAllByDate = async (date) => {
|
|
try {
|
|
const db = await getDb();
|
|
const [rows] = await db.query(
|
|
`SELECT
|
|
d.id, d.date, w.worker_name, p.project_name, d.start_time, d.end_time,
|
|
t.category, t.subcategory, d.description
|
|
FROM DailyIssueReports d
|
|
LEFT JOIN workers w ON d.worker_id = w.worker_id
|
|
LEFT JOIN projects p ON d.project_id = p.project_id
|
|
LEFT JOIN IssueTypes t ON d.issue_type_id = t.issue_type_id
|
|
WHERE d.date = ?
|
|
ORDER BY d.start_time ASC`,
|
|
[date]
|
|
);
|
|
return rows;
|
|
} catch (err) {
|
|
console.error(`[Model] ${date} 이슈 목록 조회 오류:`, err);
|
|
throw new Error('데이터베이스에서 이슈 목록을 조회하는 중 오류가 발생했습니다.');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 3. 단일 조회 (선택사항: 컨트롤러에서 사용 중)
|
|
*/
|
|
const getById = async (id, callback) => {
|
|
try {
|
|
const db = await getDb();
|
|
const [rows] = await db.query(`SELECT id, date, worker_id, project_id, issue_type_id, description, created_at, start_time, end_time FROM DailyIssueReports WHERE id = ?`, [id]);
|
|
callback(null, rows[0]);
|
|
} catch (err) {
|
|
callback(err);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 4. 수정
|
|
*/
|
|
const update = async (id, data, callback) => {
|
|
try {
|
|
const db = await getDb();
|
|
|
|
const fields = [];
|
|
const values = [];
|
|
|
|
for (const key in data) {
|
|
fields.push(`${key} = ?`);
|
|
values.push(data[key]);
|
|
}
|
|
|
|
values.push(id); // 마지막에 id
|
|
|
|
const [result] = await db.query(
|
|
`UPDATE DailyIssueReports SET ${fields.join(', ')} WHERE id = ?`,
|
|
values
|
|
);
|
|
|
|
callback(null, result.affectedRows);
|
|
} catch (err) {
|
|
callback(err);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* 5. 삭제 (Promise 기반)
|
|
*/
|
|
const remove = async (id) => {
|
|
try {
|
|
const db = await getDb();
|
|
const [result] = await db.query(`DELETE FROM DailyIssueReports WHERE id = ?`, [id]);
|
|
return result.affectedRows;
|
|
} catch (err) {
|
|
console.error(`[Model] 이슈(id: ${id}) 삭제 오류:`, err);
|
|
throw new Error('데이터베이스에서 이슈를 삭제하는 중 오류가 발생했습니다.');
|
|
}
|
|
};
|
|
|
|
// V1 함수들은 점진적으로 제거 예정
|
|
const create = async (report, callback) => {
|
|
try {
|
|
const db = await getDb();
|
|
const {
|
|
date,
|
|
worker_id,
|
|
project_id,
|
|
start_time,
|
|
end_time,
|
|
issue_type_id,
|
|
description = null // 선택값 처리
|
|
} = report;
|
|
|
|
const [result] = await db.query(
|
|
`INSERT INTO DailyIssueReports
|
|
(date, worker_id, project_id, start_time, end_time, issue_type_id, description)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
[date, worker_id, project_id, start_time, end_time, issue_type_id, description]
|
|
);
|
|
|
|
callback(null, result.insertId);
|
|
} catch (err) {
|
|
callback(err);
|
|
}
|
|
};
|
|
|
|
|
|
module.exports = {
|
|
createMany, // 신규
|
|
getAllByDate,
|
|
remove,
|
|
// 레거시 호환성을 위해 V1 함수들 임시 유지
|
|
create: (report, callback) => createMany([report]).then(ids => callback(null, ids[0])).catch(err => callback(err)),
|
|
getById,
|
|
update,
|
|
}; |