fix: 보안 취약점 수정 및 XSS 방지 적용
## 백엔드 보안 수정 - 하드코딩된 비밀번호 및 JWT 시크릿 폴백 제거 - SQL Injection 방지를 위한 화이트리스트 검증 추가 - 인증 미적용 API 라우트에 requireAuth 미들웨어 적용 - CSRF 보호 미들웨어 구현 (csrf.js) - 파일 업로드 보안 유틸리티 추가 (fileUploadSecurity.js) - 비밀번호 정책 검증 유틸리티 추가 (passwordValidator.js) ## 프론트엔드 XSS 방지 - api-base.js에 전역 escapeHtml() 함수 추가 - 17개 주요 JS 파일에 escapeHtml 적용: - tbm.js, daily-patrol.js, daily-work-report.js - task-management.js, workplace-status.js - equipment-detail.js, equipment-management.js - issue-detail.js, issue-report.js - vacation-common.js, worker-management.js - safety-report-list.js, nonconformity-list.js - project-management.js, workplace-management.js ## 정리 - 백업 폴더 및 빈 파일 삭제 - SECURITY_GUIDE.md 문서 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,53 +1,37 @@
|
||||
const { getDb } = require('../dbPool');
|
||||
|
||||
// CREATE
|
||||
const create = async (type, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO IssueTypes (category, subcategory) VALUES (?, ?)`,
|
||||
[type.category, type.subcategory]
|
||||
);
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const create = async (type) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO IssueTypes (category, subcategory) VALUES (?, ?)`,
|
||||
[type.category, type.subcategory]
|
||||
);
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
// READ ALL
|
||||
const getAll = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`SELECT issue_type_id, category, subcategory FROM IssueTypes ORDER BY category, subcategory`);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAll = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`SELECT issue_type_id, category, subcategory FROM IssueTypes ORDER BY category, subcategory`);
|
||||
return rows;
|
||||
};
|
||||
|
||||
// UPDATE
|
||||
const update = async (id, type, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`UPDATE IssueTypes SET category = ?, subcategory = ? WHERE id = ?`,
|
||||
[type.category, type.subcategory, id]
|
||||
);
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const update = async (id, type) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`UPDATE IssueTypes SET category = ?, subcategory = ? WHERE id = ?`,
|
||||
[type.category, type.subcategory, id]
|
||||
);
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
// DELETE
|
||||
const remove = async (id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(`DELETE FROM IssueTypes WHERE id = ?`, [id]);
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const remove = async (id) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(`DELETE FROM IssueTypes WHERE id = ?`, [id]);
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@@ -55,4 +39,4 @@ module.exports = {
|
||||
getAll,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,113 +1,89 @@
|
||||
const { getDb } = require('../dbPool');
|
||||
|
||||
const create = async (project, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const {
|
||||
job_no, project_name,
|
||||
contract_date, due_date,
|
||||
delivery_method, site, pm,
|
||||
is_active = true,
|
||||
project_status = 'active',
|
||||
completed_date = null
|
||||
} = project;
|
||||
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO projects
|
||||
(job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date]
|
||||
);
|
||||
const create = async (project) => {
|
||||
const db = await getDb();
|
||||
const {
|
||||
job_no, project_name,
|
||||
contract_date, due_date,
|
||||
delivery_method, site, pm,
|
||||
is_active = true,
|
||||
project_status = 'active',
|
||||
completed_date = null
|
||||
} = project;
|
||||
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO projects
|
||||
(job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date]
|
||||
);
|
||||
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
const getAll = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects ORDER BY project_id DESC`
|
||||
);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAll = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects ORDER BY project_id DESC`
|
||||
);
|
||||
return rows;
|
||||
};
|
||||
|
||||
// 활성 프로젝트만 조회 (작업보고서용)
|
||||
const getActiveProjects = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects
|
||||
WHERE is_active = TRUE
|
||||
ORDER BY project_name ASC`
|
||||
);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getActiveProjects = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects
|
||||
WHERE is_active = TRUE
|
||||
ORDER BY project_name ASC`
|
||||
);
|
||||
return rows;
|
||||
};
|
||||
|
||||
const getById = async (project_id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects WHERE project_id = ?`,
|
||||
[project_id]
|
||||
);
|
||||
callback(null, rows[0]);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getById = async (project_id) => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects WHERE project_id = ?`,
|
||||
[project_id]
|
||||
);
|
||||
return rows[0];
|
||||
};
|
||||
|
||||
const update = async (project, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const {
|
||||
project_id, job_no, project_name,
|
||||
contract_date, due_date,
|
||||
delivery_method, site, pm,
|
||||
is_active, project_status, completed_date
|
||||
} = project;
|
||||
const update = async (project) => {
|
||||
const db = await getDb();
|
||||
const {
|
||||
project_id, job_no, project_name,
|
||||
contract_date, due_date,
|
||||
delivery_method, site, pm,
|
||||
is_active, project_status, completed_date
|
||||
} = project;
|
||||
|
||||
const [result] = await db.query(
|
||||
`UPDATE projects
|
||||
SET job_no = ?,
|
||||
project_name = ?,
|
||||
contract_date = ?,
|
||||
due_date = ?,
|
||||
delivery_method= ?,
|
||||
site = ?,
|
||||
pm = ?,
|
||||
is_active = ?,
|
||||
project_status = ?,
|
||||
completed_date = ?
|
||||
WHERE project_id = ?`,
|
||||
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, project_id]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`UPDATE projects
|
||||
SET job_no = ?,
|
||||
project_name = ?,
|
||||
contract_date = ?,
|
||||
due_date = ?,
|
||||
delivery_method= ?,
|
||||
site = ?,
|
||||
pm = ?,
|
||||
is_active = ?,
|
||||
project_status = ?,
|
||||
completed_date = ?
|
||||
WHERE project_id = ?`,
|
||||
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, project_id]
|
||||
);
|
||||
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(new Error(err.message || String(err)));
|
||||
}
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
const remove = async (project_id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`DELETE FROM projects WHERE project_id = ?`,
|
||||
[project_id]
|
||||
);
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const remove = async (project_id) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`DELETE FROM projects WHERE project_id = ?`,
|
||||
[project_id]
|
||||
);
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
@@ -117,4 +93,4 @@ module.exports = {
|
||||
getById,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,151 +12,123 @@ const { getDb } = require('../dbPool');
|
||||
/**
|
||||
* 작업 생성
|
||||
*/
|
||||
const createTask = async (taskData, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const { work_type_id, task_name, description } = taskData;
|
||||
const createTask = async (taskData) => {
|
||||
const db = await getDb();
|
||||
const { work_type_id, task_name, description } = taskData;
|
||||
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO tasks (work_type_id, task_name, description, is_active)
|
||||
VALUES (?, ?, ?, 1)`,
|
||||
[work_type_id || null, task_name, description || null]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO tasks (work_type_id, task_name, description, is_active)
|
||||
VALUES (?, ?, ?, 1)`,
|
||||
[work_type_id || null, task_name, description || null]
|
||||
);
|
||||
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
/**
|
||||
* 전체 작업 목록 조회 (공정 정보 포함)
|
||||
*/
|
||||
const getAllTasks = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
ORDER BY wt.category ASC, t.task_id DESC`
|
||||
);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAllTasks = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
ORDER BY wt.category ASC, t.task_id DESC`
|
||||
);
|
||||
return rows;
|
||||
};
|
||||
|
||||
/**
|
||||
* 활성 작업만 조회
|
||||
*/
|
||||
const getActiveTasks = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.is_active = 1
|
||||
ORDER BY wt.category ASC, t.task_name ASC`
|
||||
);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getActiveTasks = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.is_active = 1
|
||||
ORDER BY wt.category ASC, t.task_name ASC`
|
||||
);
|
||||
return rows;
|
||||
};
|
||||
|
||||
/**
|
||||
* 공정별 작업 목록 조회
|
||||
*/
|
||||
const getTasksByWorkType = async (workTypeId, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.work_type_id = ?
|
||||
ORDER BY t.task_id DESC`,
|
||||
[workTypeId]
|
||||
);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getTasksByWorkType = async (workTypeId) => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.work_type_id = ?
|
||||
ORDER BY t.task_id DESC`,
|
||||
[workTypeId]
|
||||
);
|
||||
return rows;
|
||||
};
|
||||
|
||||
/**
|
||||
* 단일 작업 조회
|
||||
*/
|
||||
const getTaskById = async (taskId, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.task_id = ?`,
|
||||
[taskId]
|
||||
);
|
||||
callback(null, rows[0] || null);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getTaskById = async (taskId) => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(
|
||||
`SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active,
|
||||
t.created_at, t.updated_at,
|
||||
wt.name as work_type_name, wt.category
|
||||
FROM tasks t
|
||||
LEFT JOIN work_types wt ON t.work_type_id = wt.id
|
||||
WHERE t.task_id = ?`,
|
||||
[taskId]
|
||||
);
|
||||
return rows[0] || null;
|
||||
};
|
||||
|
||||
/**
|
||||
* 작업 수정
|
||||
*/
|
||||
const updateTask = async (taskId, taskData, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const { work_type_id, task_name, description, is_active } = taskData;
|
||||
const updateTask = async (taskId, taskData) => {
|
||||
const db = await getDb();
|
||||
const { work_type_id, task_name, description, is_active } = taskData;
|
||||
|
||||
const [result] = await db.query(
|
||||
`UPDATE tasks
|
||||
SET work_type_id = ?,
|
||||
task_name = ?,
|
||||
description = ?,
|
||||
is_active = ?,
|
||||
updated_at = NOW()
|
||||
WHERE task_id = ?`,
|
||||
[
|
||||
work_type_id || null,
|
||||
task_name,
|
||||
description || null,
|
||||
is_active !== undefined ? is_active : 1,
|
||||
taskId
|
||||
]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`UPDATE tasks
|
||||
SET work_type_id = ?,
|
||||
task_name = ?,
|
||||
description = ?,
|
||||
is_active = ?,
|
||||
updated_at = NOW()
|
||||
WHERE task_id = ?`,
|
||||
[
|
||||
work_type_id || null,
|
||||
task_name,
|
||||
description || null,
|
||||
is_active !== undefined ? is_active : 1,
|
||||
taskId
|
||||
]
|
||||
);
|
||||
|
||||
callback(null, result);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 작업 삭제
|
||||
*/
|
||||
const deleteTask = async (taskId, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`DELETE FROM tasks WHERE task_id = ?`,
|
||||
[taskId]
|
||||
);
|
||||
callback(null, result);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const deleteTask = async (taskId) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query(
|
||||
`DELETE FROM tasks WHERE task_id = ?`,
|
||||
[taskId]
|
||||
);
|
||||
return result;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1,89 +1,68 @@
|
||||
const { getDb } = require('../dbPool');
|
||||
|
||||
// 1. 전체 도구 조회
|
||||
const getAll = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools');
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAll = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools');
|
||||
return rows;
|
||||
};
|
||||
|
||||
// 2. 단일 도구 조회
|
||||
const getById = async (id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools WHERE id = ?', [id]);
|
||||
callback(null, rows[0]);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getById = async (id) => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools WHERE id = ?', [id]);
|
||||
return rows[0];
|
||||
};
|
||||
|
||||
// 3. 도구 생성
|
||||
const create = async (tool, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool;
|
||||
const create = async (tool) => {
|
||||
const db = await getDb();
|
||||
const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool;
|
||||
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO Tools
|
||||
(name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO Tools
|
||||
(name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note]
|
||||
);
|
||||
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
// 4. 도구 수정
|
||||
const update = async (id, tool, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool;
|
||||
const update = async (id, tool) => {
|
||||
const db = await getDb();
|
||||
const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool;
|
||||
|
||||
const [result] = await db.query(
|
||||
`UPDATE Tools
|
||||
SET name = ?,
|
||||
location = ?,
|
||||
stock = ?,
|
||||
status = ?,
|
||||
factory_id = ?,
|
||||
map_x = ?,
|
||||
map_y = ?,
|
||||
map_zone = ?,
|
||||
map_note = ?
|
||||
WHERE id = ?`,
|
||||
[name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note, id]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`UPDATE Tools
|
||||
SET name = ?,
|
||||
location = ?,
|
||||
stock = ?,
|
||||
status = ?,
|
||||
factory_id = ?,
|
||||
map_x = ?,
|
||||
map_y = ?,
|
||||
map_zone = ?,
|
||||
map_note = ?
|
||||
WHERE id = ?`,
|
||||
[name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note, id]
|
||||
);
|
||||
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(new Error(err.message || String(err)));
|
||||
}
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
// 5. 도구 삭제
|
||||
const remove = async (id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query('DELETE FROM Tools WHERE id = ?', [id]);
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const remove = async (id) => {
|
||||
const db = await getDb();
|
||||
const [result] = await db.query('DELETE FROM Tools WHERE id = ?', [id]);
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
// ✅ export 정리
|
||||
module.exports = {
|
||||
getAll,
|
||||
getById,
|
||||
create,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,45 +1,36 @@
|
||||
const { getDb } = require('../dbPool');
|
||||
|
||||
// 1. 문서 업로드
|
||||
const create = async (doc, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const sql = `
|
||||
INSERT INTO uploaded_documents
|
||||
(title, tags, description, original_name, stored_name, file_path, file_type, file_size, submitted_by)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
const values = [
|
||||
doc.title,
|
||||
doc.tags,
|
||||
doc.description,
|
||||
doc.original_name,
|
||||
doc.stored_name,
|
||||
doc.file_path,
|
||||
doc.file_type,
|
||||
doc.file_size,
|
||||
doc.submitted_by
|
||||
];
|
||||
const [result] = await db.query(sql, values);
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
callback(new Error(err.message || String(err)));
|
||||
}
|
||||
const create = async (doc) => {
|
||||
const db = await getDb();
|
||||
const sql = `
|
||||
INSERT INTO uploaded_documents
|
||||
(title, tags, description, original_name, stored_name, file_path, file_type, file_size, submitted_by)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`;
|
||||
const values = [
|
||||
doc.title,
|
||||
doc.tags,
|
||||
doc.description,
|
||||
doc.original_name,
|
||||
doc.stored_name,
|
||||
doc.file_path,
|
||||
doc.file_type,
|
||||
doc.file_size,
|
||||
doc.submitted_by
|
||||
];
|
||||
const [result] = await db.query(sql, values);
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
// 2. 전체 문서 목록 조회
|
||||
const getAll = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`SELECT * FROM uploaded_documents ORDER BY created_at DESC`);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAll = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`SELECT * FROM uploaded_documents ORDER BY created_at DESC`);
|
||||
return rows;
|
||||
};
|
||||
|
||||
// ✅ 내보내기
|
||||
module.exports = {
|
||||
create,
|
||||
getAll
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,152 +10,133 @@ const formatDate = (dateStr) => {
|
||||
};
|
||||
|
||||
// 1. 작업자 생성
|
||||
const create = async (worker, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const {
|
||||
worker_name,
|
||||
job_type = null,
|
||||
join_date = null,
|
||||
salary = null,
|
||||
annual_leave = null,
|
||||
status = 'active',
|
||||
employment_status = 'employed',
|
||||
department_id = null
|
||||
} = worker;
|
||||
const create = async (worker) => {
|
||||
const db = await getDb();
|
||||
const {
|
||||
worker_name,
|
||||
job_type = null,
|
||||
join_date = null,
|
||||
salary = null,
|
||||
annual_leave = null,
|
||||
status = 'active',
|
||||
employment_status = 'employed',
|
||||
department_id = null
|
||||
} = worker;
|
||||
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO workers
|
||||
(worker_name, job_type, join_date, salary, annual_leave, status, employment_status, department_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[worker_name, job_type, formatDate(join_date), salary, annual_leave, status, employment_status, department_id]
|
||||
);
|
||||
const [result] = await db.query(
|
||||
`INSERT INTO workers
|
||||
(worker_name, job_type, join_date, salary, annual_leave, status, employment_status, department_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
||||
[worker_name, job_type, formatDate(join_date), salary, annual_leave, status, employment_status, department_id]
|
||||
);
|
||||
|
||||
callback(null, result.insertId);
|
||||
} catch (err) {
|
||||
console.error('❌ create 함수 에러:', err);
|
||||
callback(err);
|
||||
}
|
||||
return result.insertId;
|
||||
};
|
||||
|
||||
// 2. 전체 조회
|
||||
const getAll = async (callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`
|
||||
SELECT
|
||||
w.*,
|
||||
CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active,
|
||||
u.user_id,
|
||||
d.department_name
|
||||
FROM workers w
|
||||
LEFT JOIN users u ON w.worker_id = u.worker_id
|
||||
LEFT JOIN departments d ON w.department_id = d.department_id
|
||||
ORDER BY w.worker_id DESC
|
||||
`);
|
||||
callback(null, rows);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getAll = async () => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`
|
||||
SELECT
|
||||
w.*,
|
||||
CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active,
|
||||
u.user_id,
|
||||
d.department_name
|
||||
FROM workers w
|
||||
LEFT JOIN users u ON w.worker_id = u.worker_id
|
||||
LEFT JOIN departments d ON w.department_id = d.department_id
|
||||
ORDER BY w.worker_id DESC
|
||||
`);
|
||||
return rows;
|
||||
};
|
||||
|
||||
// 3. 단일 조회
|
||||
const getById = async (worker_id, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`
|
||||
SELECT
|
||||
w.*,
|
||||
CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active,
|
||||
u.user_id,
|
||||
d.department_name
|
||||
FROM workers w
|
||||
LEFT JOIN users u ON w.worker_id = u.worker_id
|
||||
LEFT JOIN departments d ON w.department_id = d.department_id
|
||||
WHERE w.worker_id = ?
|
||||
`, [worker_id]);
|
||||
callback(null, rows[0]);
|
||||
} catch (err) {
|
||||
callback(err);
|
||||
}
|
||||
const getById = async (worker_id) => {
|
||||
const db = await getDb();
|
||||
const [rows] = await db.query(`
|
||||
SELECT
|
||||
w.*,
|
||||
CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active,
|
||||
u.user_id,
|
||||
d.department_name
|
||||
FROM workers w
|
||||
LEFT JOIN users u ON w.worker_id = u.worker_id
|
||||
LEFT JOIN departments d ON w.department_id = d.department_id
|
||||
WHERE w.worker_id = ?
|
||||
`, [worker_id]);
|
||||
return rows[0];
|
||||
};
|
||||
|
||||
// 4. 작업자 수정
|
||||
const update = async (worker, callback) => {
|
||||
try {
|
||||
const db = await getDb();
|
||||
const {
|
||||
worker_id,
|
||||
worker_name,
|
||||
job_type,
|
||||
status,
|
||||
join_date,
|
||||
salary,
|
||||
annual_leave,
|
||||
employment_status,
|
||||
department_id
|
||||
} = worker;
|
||||
const update = async (worker) => {
|
||||
const db = await getDb();
|
||||
const {
|
||||
worker_id,
|
||||
worker_name,
|
||||
job_type,
|
||||
status,
|
||||
join_date,
|
||||
salary,
|
||||
annual_leave,
|
||||
employment_status,
|
||||
department_id
|
||||
} = worker;
|
||||
|
||||
// 업데이트할 필드만 동적으로 구성
|
||||
const updates = [];
|
||||
const values = [];
|
||||
// 업데이트할 필드만 동적으로 구성
|
||||
const updates = [];
|
||||
const values = [];
|
||||
|
||||
if (worker_name !== undefined) {
|
||||
updates.push('worker_name = ?');
|
||||
values.push(worker_name);
|
||||
}
|
||||
if (job_type !== undefined) {
|
||||
updates.push('job_type = ?');
|
||||
values.push(job_type);
|
||||
}
|
||||
if (status !== undefined) {
|
||||
updates.push('status = ?');
|
||||
values.push(status);
|
||||
}
|
||||
if (join_date !== undefined) {
|
||||
updates.push('join_date = ?');
|
||||
values.push(formatDate(join_date));
|
||||
}
|
||||
if (salary !== undefined) {
|
||||
updates.push('salary = ?');
|
||||
values.push(salary);
|
||||
}
|
||||
if (annual_leave !== undefined) {
|
||||
updates.push('annual_leave = ?');
|
||||
values.push(annual_leave);
|
||||
}
|
||||
if (employment_status !== undefined) {
|
||||
updates.push('employment_status = ?');
|
||||
values.push(employment_status);
|
||||
}
|
||||
if (department_id !== undefined) {
|
||||
updates.push('department_id = ?');
|
||||
values.push(department_id);
|
||||
}
|
||||
|
||||
if (updates.length === 0) {
|
||||
callback(new Error('업데이트할 필드가 없습니다'));
|
||||
return;
|
||||
}
|
||||
|
||||
values.push(worker_id); // WHERE 조건용
|
||||
|
||||
const query = `UPDATE workers SET ${updates.join(', ')} WHERE worker_id = ?`;
|
||||
|
||||
console.log('🔍 실행할 SQL:', query);
|
||||
console.log('🔍 SQL 파라미터:', values);
|
||||
|
||||
const [result] = await db.query(query, values);
|
||||
|
||||
callback(null, result.affectedRows);
|
||||
} catch (err) {
|
||||
console.error('❌ update 함수 에러:', err);
|
||||
callback(new Error(err.message || String(err)));
|
||||
if (worker_name !== undefined) {
|
||||
updates.push('worker_name = ?');
|
||||
values.push(worker_name);
|
||||
}
|
||||
if (job_type !== undefined) {
|
||||
updates.push('job_type = ?');
|
||||
values.push(job_type);
|
||||
}
|
||||
if (status !== undefined) {
|
||||
updates.push('status = ?');
|
||||
values.push(status);
|
||||
}
|
||||
if (join_date !== undefined) {
|
||||
updates.push('join_date = ?');
|
||||
values.push(formatDate(join_date));
|
||||
}
|
||||
if (salary !== undefined) {
|
||||
updates.push('salary = ?');
|
||||
values.push(salary);
|
||||
}
|
||||
if (annual_leave !== undefined) {
|
||||
updates.push('annual_leave = ?');
|
||||
values.push(annual_leave);
|
||||
}
|
||||
if (employment_status !== undefined) {
|
||||
updates.push('employment_status = ?');
|
||||
values.push(employment_status);
|
||||
}
|
||||
if (department_id !== undefined) {
|
||||
updates.push('department_id = ?');
|
||||
values.push(department_id);
|
||||
}
|
||||
|
||||
if (updates.length === 0) {
|
||||
throw new Error('업데이트할 필드가 없습니다');
|
||||
}
|
||||
|
||||
values.push(worker_id); // WHERE 조건용
|
||||
|
||||
const query = `UPDATE workers SET ${updates.join(', ')} WHERE worker_id = ?`;
|
||||
|
||||
console.log('🔍 실행할 SQL:', query);
|
||||
console.log('🔍 SQL 파라미터:', values);
|
||||
|
||||
const [result] = await db.query(query, values);
|
||||
|
||||
return result.affectedRows;
|
||||
};
|
||||
|
||||
// 5. 삭제 (외래키 제약조건 처리)
|
||||
const remove = async (worker_id, callback) => {
|
||||
const remove = async (worker_id) => {
|
||||
const db = await getDb();
|
||||
const conn = await db.getConnection();
|
||||
|
||||
@@ -196,22 +177,21 @@ const remove = async (worker_id, callback) => {
|
||||
console.log(`✅ 작업자 삭제 완료: ${result.affectedRows}건`);
|
||||
|
||||
await conn.commit();
|
||||
callback(null, result.affectedRows);
|
||||
return result.affectedRows;
|
||||
|
||||
} catch (err) {
|
||||
await conn.rollback();
|
||||
console.error(`❌ 작업자 삭제 오류 (worker_id: ${worker_id}):`, err);
|
||||
callback(new Error(`작업자 삭제 중 오류가 발생했습니다: ${err.message}`));
|
||||
throw new Error(`작업자 삭제 중 오류가 발생했습니다: ${err.message}`);
|
||||
} finally {
|
||||
conn.release();
|
||||
}
|
||||
};
|
||||
|
||||
// ✅ 모듈 내보내기 (정상 구조)
|
||||
module.exports = {
|
||||
create,
|
||||
getAll,
|
||||
getById,
|
||||
update,
|
||||
remove
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user