Files
TK-FB-Project/api.hyungi.net/models/workerModel.js
Hyungi Ahn 90d3e32992 feat: 일일순회점검 시스템 구축 및 관리 기능 개선
- 일일순회점검 시스템 신규 구현
  - DB 테이블: patrol_checklist_items, daily_patrol_sessions, patrol_check_records, workplace_items, item_types
  - API: /api/patrol/* 엔드포인트
  - 프론트엔드: 지도 기반 작업장 점검 UI

- 설비 관리 기능 개선
  - 구매 관련 필드 추가 (구매일, 가격, 공급업체 등)
  - 설비 코드 자동 생성 (TKP-XXX 형식)

- 작업장 관리 개선
  - 레이아웃 이미지 업로드 기능
  - 마커 위치 저장 기능

- 부서 관리 기능 추가
- 사이드바 네비게이션 카테고리 재구성
- 이미지 401 오류 수정 (정적 파일 경로 처리)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 11:41:41 +09:00

217 lines
6.4 KiB
JavaScript

const { getDb } = require('../dbPool');
// 날짜 형식 변환 헬퍼 함수 (ISO 8601 -> MySQL DATE)
const formatDate = (dateStr) => {
if (!dateStr) return null;
if (typeof dateStr === 'string' && dateStr.includes('T')) {
return dateStr.split('T')[0]; // ISO 8601 -> YYYY-MM-DD
}
return 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 [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);
}
};
// 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);
}
};
// 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);
}
};
// 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 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)));
}
};
// 5. 삭제 (외래키 제약조건 처리)
const remove = async (worker_id, callback) => {
const db = await getDb();
const conn = await db.getConnection();
try {
await conn.beginTransaction();
console.log(`🗑️ 작업자 삭제 시작: worker_id=${worker_id}`);
// 안전한 삭제: 각 테이블을 개별적으로 처리하고 오류가 발생해도 계속 진행
const tables = [
{ name: 'users', query: 'UPDATE users SET worker_id = NULL WHERE worker_id = ?', action: '업데이트' },
{ name: 'Users', query: 'UPDATE Users SET worker_id = NULL WHERE worker_id = ?', action: '업데이트' },
{ name: 'daily_issue_reports', query: 'DELETE FROM daily_issue_reports WHERE worker_id = ?', action: '삭제' },
{ name: 'DailyIssueReports', query: 'DELETE FROM DailyIssueReports WHERE worker_id = ?', action: '삭제' },
{ name: 'work_reports', query: 'DELETE FROM work_reports WHERE worker_id = ?', action: '삭제' },
{ name: 'WorkReports', query: 'DELETE FROM WorkReports WHERE worker_id = ?', action: '삭제' },
{ name: 'daily_work_reports', query: 'DELETE FROM daily_work_reports WHERE worker_id = ?', action: '삭제' },
{ name: 'monthly_worker_status', query: 'DELETE FROM monthly_worker_status WHERE worker_id = ?', action: '삭제' },
{ name: 'worker_groups', query: 'DELETE FROM worker_groups WHERE worker_id = ?', action: '삭제' }
];
for (const table of tables) {
try {
const [result] = await conn.query(table.query, [worker_id]);
if (result.affectedRows > 0) {
console.log(`${table.name} 테이블 ${table.action}: ${result.affectedRows}`);
}
} catch (tableError) {
console.log(`⚠️ ${table.name} 테이블 ${table.action} 실패 (무시): ${tableError.message}`);
}
}
// 마지막으로 작업자 삭제
const [result] = await conn.query(
`DELETE FROM workers WHERE worker_id = ?`,
[worker_id]
);
console.log(`✅ 작업자 삭제 완료: ${result.affectedRows}`);
await conn.commit();
callback(null, result.affectedRows);
} catch (err) {
await conn.rollback();
console.error(`❌ 작업자 삭제 오류 (worker_id: ${worker_id}):`, err);
callback(new Error(`작업자 삭제 중 오류가 발생했습니다: ${err.message}`));
} finally {
conn.release();
}
};
// ✅ 모듈 내보내기 (정상 구조)
module.exports = {
create,
getAll,
getById,
update,
remove
};