const { getDb } = require('../dbPool'); // ==================== 출입 신청 관리 ==================== /** * 출입 신청 생성 */ const createVisitRequest = async (requestData, callback) => { try { const db = await getDb(); const { requester_id, visitor_company, visitor_count = 1, category_id, workplace_id, visit_date, visit_time, purpose_id, notes = null } = requestData; const [result] = await db.query( `INSERT INTO workplace_visit_requests (requester_id, visitor_company, visitor_count, category_id, workplace_id, visit_date, visit_time, purpose_id, notes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [requester_id, visitor_company, visitor_count, category_id, workplace_id, visit_date, visit_time, purpose_id, notes] ); callback(null, result.insertId); } catch (err) { callback(err); } }; /** * 출입 신청 목록 조회 (필터 옵션 포함) */ const getAllVisitRequests = async (filters = {}, callback) => { try { const db = await getDb(); let query = ` SELECT vr.request_id, vr.requester_id, vr.visitor_company, vr.visitor_count, vr.category_id, vr.workplace_id, vr.visit_date, vr.visit_time, vr.purpose_id, vr.notes, vr.status, vr.approved_by, vr.approved_at, vr.rejection_reason, vr.created_at, vr.updated_at, u.username as requester_name, u.name as requester_full_name, wc.category_name, w.workplace_name, vpt.purpose_name, approver.username as approver_name FROM workplace_visit_requests vr INNER JOIN users u ON vr.requester_id = u.user_id INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id LEFT JOIN users approver ON vr.approved_by = approver.user_id WHERE 1=1 `; const params = []; // 필터 적용 if (filters.status) { query += ` AND vr.status = ?`; params.push(filters.status); } if (filters.visit_date) { query += ` AND vr.visit_date = ?`; params.push(filters.visit_date); } if (filters.start_date && filters.end_date) { query += ` AND vr.visit_date BETWEEN ? AND ?`; params.push(filters.start_date, filters.end_date); } if (filters.requester_id) { query += ` AND vr.requester_id = ?`; params.push(filters.requester_id); } if (filters.category_id) { query += ` AND vr.category_id = ?`; params.push(filters.category_id); } query += ` ORDER BY vr.visit_date DESC, vr.visit_time DESC, vr.created_at DESC`; const [rows] = await db.query(query, params); callback(null, rows); } catch (err) { callback(err); } }; /** * 출입 신청 상세 조회 */ const getVisitRequestById = async (requestId, callback) => { try { const db = await getDb(); const [rows] = await db.query( `SELECT vr.request_id, vr.requester_id, vr.visitor_company, vr.visitor_count, vr.category_id, vr.workplace_id, vr.visit_date, vr.visit_time, vr.purpose_id, vr.notes, vr.status, vr.approved_by, vr.approved_at, vr.rejection_reason, vr.created_at, vr.updated_at, u.username as requester_name, u.name as requester_full_name, wc.category_name, w.workplace_name, vpt.purpose_name, approver.username as approver_name FROM workplace_visit_requests vr INNER JOIN users u ON vr.requester_id = u.user_id INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id LEFT JOIN users approver ON vr.approved_by = approver.user_id WHERE vr.request_id = ?`, [requestId] ); callback(null, rows[0]); } catch (err) { callback(err); } }; /** * 출입 신청 수정 */ const updateVisitRequest = async (requestId, requestData, callback) => { try { const db = await getDb(); const { visitor_company, visitor_count, category_id, workplace_id, visit_date, visit_time, purpose_id, notes } = requestData; const [result] = await db.query( `UPDATE workplace_visit_requests SET visitor_company = ?, visitor_count = ?, category_id = ?, workplace_id = ?, visit_date = ?, visit_time = ?, purpose_id = ?, notes = ?, updated_at = NOW() WHERE request_id = ?`, [visitor_company, visitor_count, category_id, workplace_id, visit_date, visit_time, purpose_id, notes, requestId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 출입 신청 삭제 */ const deleteVisitRequest = async (requestId, callback) => { try { const db = await getDb(); const [result] = await db.query( `DELETE FROM workplace_visit_requests WHERE request_id = ?`, [requestId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 출입 신청 승인 */ const approveVisitRequest = async (requestId, approvedBy, callback) => { try { const db = await getDb(); const [result] = await db.query( `UPDATE workplace_visit_requests SET status = 'approved', approved_by = ?, approved_at = NOW(), updated_at = NOW() WHERE request_id = ?`, [approvedBy, requestId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 출입 신청 반려 */ const rejectVisitRequest = async (requestId, rejectionData, callback) => { try { const db = await getDb(); const { approved_by, rejection_reason } = rejectionData; const [result] = await db.query( `UPDATE workplace_visit_requests SET status = 'rejected', approved_by = ?, approved_at = NOW(), rejection_reason = ?, updated_at = NOW() WHERE request_id = ?`, [approved_by, rejection_reason, requestId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 출입 신청 상태 변경 */ const updateVisitRequestStatus = async (requestId, status, callback) => { try { const db = await getDb(); const [result] = await db.query( `UPDATE workplace_visit_requests SET status = ?, updated_at = NOW() WHERE request_id = ?`, [status, requestId] ); callback(null, result); } catch (err) { callback(err); } }; // ==================== 방문 목적 관리 ==================== /** * 모든 방문 목적 조회 */ const getAllVisitPurposes = async (callback) => { try { const db = await getDb(); const [rows] = await db.query( `SELECT purpose_id, purpose_name, display_order, is_active, created_at FROM visit_purpose_types ORDER BY display_order ASC, purpose_id ASC` ); callback(null, rows); } catch (err) { callback(err); } }; /** * 활성 방문 목적만 조회 */ const getActiveVisitPurposes = async (callback) => { try { const db = await getDb(); const [rows] = await db.query( `SELECT purpose_id, purpose_name, display_order, is_active, created_at FROM visit_purpose_types WHERE is_active = TRUE ORDER BY display_order ASC, purpose_id ASC` ); callback(null, rows); } catch (err) { callback(err); } }; /** * 방문 목적 추가 */ const createVisitPurpose = async (purposeData, callback) => { try { const db = await getDb(); const { purpose_name, display_order = 0, is_active = true } = purposeData; const [result] = await db.query( `INSERT INTO visit_purpose_types (purpose_name, display_order, is_active) VALUES (?, ?, ?)`, [purpose_name, display_order, is_active] ); callback(null, result.insertId); } catch (err) { callback(err); } }; /** * 방문 목적 수정 */ const updateVisitPurpose = async (purposeId, purposeData, callback) => { try { const db = await getDb(); const { purpose_name, display_order, is_active } = purposeData; const [result] = await db.query( `UPDATE visit_purpose_types SET purpose_name = ?, display_order = ?, is_active = ? WHERE purpose_id = ?`, [purpose_name, display_order, is_active, purposeId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 방문 목적 삭제 */ const deleteVisitPurpose = async (purposeId, callback) => { try { const db = await getDb(); const [result] = await db.query( `DELETE FROM visit_purpose_types WHERE purpose_id = ?`, [purposeId] ); callback(null, result); } catch (err) { callback(err); } }; // ==================== 안전교육 기록 관리 ==================== /** * 안전교육 기록 생성 */ const createTrainingRecord = async (trainingData, callback) => { try { const db = await getDb(); const { request_id, trainer_id, training_date, training_start_time, training_end_time = null, training_topics = null } = trainingData; const [result] = await db.query( `INSERT INTO safety_training_records (request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics) VALUES (?, ?, ?, ?, ?, ?)`, [request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics] ); callback(null, result.insertId); } catch (err) { callback(err); } }; /** * 특정 출입 신청의 안전교육 기록 조회 */ const getTrainingRecordByRequestId = async (requestId, callback) => { try { const db = await getDb(); const [rows] = await db.query( `SELECT str.training_id, str.request_id, str.trainer_id, str.training_date, str.training_start_time, str.training_end_time, str.training_topics, str.signature_data, str.completed_at, str.created_at, str.updated_at, u.username as trainer_name, u.name as trainer_full_name FROM safety_training_records str INNER JOIN users u ON str.trainer_id = u.user_id WHERE str.request_id = ?`, [requestId] ); callback(null, rows[0]); } catch (err) { callback(err); } }; /** * 안전교육 기록 수정 */ const updateTrainingRecord = async (trainingId, trainingData, callback) => { try { const db = await getDb(); const { training_date, training_start_time, training_end_time, training_topics } = trainingData; const [result] = await db.query( `UPDATE safety_training_records SET training_date = ?, training_start_time = ?, training_end_time = ?, training_topics = ?, updated_at = NOW() WHERE training_id = ?`, [training_date, training_start_time, training_end_time, training_topics, trainingId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 안전교육 완료 (서명 포함) */ const completeTraining = async (trainingId, signatureData, callback) => { try { const db = await getDb(); const [result] = await db.query( `UPDATE safety_training_records SET signature_data = ?, completed_at = NOW(), updated_at = NOW() WHERE training_id = ?`, [signatureData, trainingId] ); callback(null, result); } catch (err) { callback(err); } }; /** * 안전교육 목록 조회 (날짜별 필터) */ const getTrainingRecords = async (filters = {}, callback) => { try { const db = await getDb(); let query = ` SELECT str.training_id, str.request_id, str.trainer_id, str.training_date, str.training_start_time, str.training_end_time, str.training_topics, str.completed_at, str.created_at, str.updated_at, u.username as trainer_name, u.name as trainer_full_name, vr.visitor_company, vr.visitor_count, vr.visit_date FROM safety_training_records str INNER JOIN users u ON str.trainer_id = u.user_id INNER JOIN workplace_visit_requests vr ON str.request_id = vr.request_id WHERE 1=1 `; const params = []; if (filters.training_date) { query += ` AND str.training_date = ?`; params.push(filters.training_date); } if (filters.start_date && filters.end_date) { query += ` AND str.training_date BETWEEN ? AND ?`; params.push(filters.start_date, filters.end_date); } if (filters.trainer_id) { query += ` AND str.trainer_id = ?`; params.push(filters.trainer_id); } query += ` ORDER BY str.training_date DESC, str.training_start_time DESC`; const [rows] = await db.query(query, params); callback(null, rows); } catch (err) { callback(err); } }; module.exports = { // 출입 신청 createVisitRequest, getAllVisitRequests, getVisitRequestById, updateVisitRequest, deleteVisitRequest, approveVisitRequest, rejectVisitRequest, updateVisitRequestStatus, // 방문 목적 getAllVisitPurposes, getActiveVisitPurposes, createVisitPurpose, updateVisitPurpose, deleteVisitPurpose, // 안전교육 createTrainingRecord, getTrainingRecordByRequestId, updateTrainingRecord, completeTraining, getTrainingRecords };