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:
Hyungi Ahn
2026-02-05 06:33:10 +09:00
parent 7c38c555f5
commit 36f110c90a
97 changed files with 2523 additions and 24267 deletions

View File

@@ -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
};
};

View File

@@ -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
};
};

View File

@@ -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 = {

View File

@@ -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
};
};

View File

@@ -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
};
};

View File

@@ -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
};
};