const { getDb } = require('../dbPool'); // ==================== 출입 신청 관리 ==================== const createVisitRequest = async (requestData) => { 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] ); return result.insertId; }; const getAllVisitRequests = async (filters = {}) => { 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); return rows; }; const getVisitRequestById = async (requestId) => { 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] ); return rows[0]; }; const updateVisitRequest = async (requestId, requestData) => { 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] ); return result; }; const deleteVisitRequest = async (requestId) => { const db = await getDb(); const [result] = await db.query( `DELETE FROM workplace_visit_requests WHERE request_id = ?`, [requestId] ); return result; }; const approveVisitRequest = async (requestId, approvedBy) => { 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] ); return result; }; const rejectVisitRequest = async (requestId, rejectionData) => { 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] ); return result; }; const updateVisitRequestStatus = async (requestId, status) => { const db = await getDb(); const [result] = await db.query( `UPDATE workplace_visit_requests SET status = ?, updated_at = NOW() WHERE request_id = ?`, [status, requestId] ); return result; }; // ==================== 방문 목적 관리 ==================== const getAllVisitPurposes = async () => { 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` ); return rows; }; const getActiveVisitPurposes = async () => { 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` ); return rows; }; const createVisitPurpose = async (purposeData) => { 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] ); return result.insertId; }; const updateVisitPurpose = async (purposeId, purposeData) => { 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] ); return result; }; const deleteVisitPurpose = async (purposeId) => { const db = await getDb(); const [result] = await db.query( `DELETE FROM visit_purpose_types WHERE purpose_id = ?`, [purposeId] ); return result; }; // ==================== 안전교육 기록 관리 ==================== const createTrainingRecord = async (trainingData) => { 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] ); return result.insertId; }; const getTrainingRecordByRequestId = async (requestId) => { 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] ); return rows[0]; }; const updateTrainingRecord = async (trainingId, trainingData) => { 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] ); return result; }; const completeTraining = async (trainingId, signatureData) => { 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] ); return result; }; const getTrainingRecords = async (filters = {}) => { 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); return rows; }; module.exports = { createVisitRequest, getAllVisitRequests, getVisitRequestById, updateVisitRequest, deleteVisitRequest, approveVisitRequest, rejectVisitRequest, updateVisitRequestStatus, getAllVisitPurposes, getActiveVisitPurposes, createVisitPurpose, updateVisitPurpose, deleteVisitPurpose, createTrainingRecord, getTrainingRecordByRequestId, updateTrainingRecord, completeTraining, getTrainingRecords };