// equipment-management.js // 설비 관리 페이지 JavaScript let equipments = []; let allEquipments = []; // 필터링 전 전체 데이터 let workplaces = []; let equipmentTypes = []; let currentEquipment = null; // 페이지 로드 시 초기화 document.addEventListener('DOMContentLoaded', async () => { await waitForAxiosConfig(); await loadInitialData(); }); // axios 설정 대기 함수 function waitForAxiosConfig() { return new Promise((resolve) => { const check = setInterval(() => { if (axios.defaults.baseURL) { clearInterval(check); resolve(); } }, 50); setTimeout(() => { clearInterval(check); if (!axios.defaults.baseURL) { console.error('Axios 설정 시간 초과'); } resolve(); }, 5000); }); } // 초기 데이터 로드 async function loadInitialData() { try { await Promise.all([ loadEquipments(), loadWorkplaces(), loadEquipmentTypes() ]); } catch (error) { console.error('초기 데이터 로드 실패:', error); alert('데이터를 불러오는데 실패했습니다.'); } } // 설비 목록 로드 async function loadEquipments() { try { const response = await axios.get('/equipments'); if (response.data.success) { allEquipments = response.data.data; equipments = [...allEquipments]; renderStats(); renderEquipmentList(); } } catch (error) { console.error('설비 목록 로드 실패:', error); throw error; } } // 작업장 목록 로드 async function loadWorkplaces() { try { const response = await axios.get('/workplaces'); if (response.data.success) { workplaces = response.data.data; populateWorkplaceFilters(); } } catch (error) { console.error('작업장 목록 로드 실패:', error); } } // 설비 유형 목록 로드 async function loadEquipmentTypes() { try { const response = await axios.get('/equipments/types'); if (response.data.success) { equipmentTypes = response.data.data; populateTypeFilter(); } } catch (error) { console.error('설비 유형 로드 실패:', error); } } // 통계 렌더링 function renderStats() { const container = document.getElementById('statsSection'); if (!container) return; const totalCount = allEquipments.length; const activeCount = allEquipments.filter(e => e.status === 'active').length; const maintenanceCount = allEquipments.filter(e => e.status === 'maintenance').length; const inactiveCount = allEquipments.filter(e => e.status === 'inactive').length; const totalValue = allEquipments.reduce((sum, e) => sum + (Number(e.purchase_price) || 0), 0); const avgValue = totalCount > 0 ? totalValue / totalCount : 0; container.innerHTML = `
전체 설비
${totalCount}대
총 자산가치 ${formatPriceShort(totalValue)}
활성
${activeCount}대
${totalCount > 0 ? Math.round(activeCount / totalCount * 100) : 0}%
정비중
${maintenanceCount}대
${totalCount > 0 ? Math.round(maintenanceCount / totalCount * 100) : 0}%
비활성
${inactiveCount}대
${totalCount > 0 ? Math.round(inactiveCount / totalCount * 100) : 0}%
평균 구입가
${formatPriceShort(avgValue)}
설비당 평균
`; } // 작업장 필터 채우기 function populateWorkplaceFilters() { const filterWorkplace = document.getElementById('filterWorkplace'); const modalWorkplace = document.getElementById('workplaceId'); const workplaceOptions = workplaces.map(w => { const safeId = parseInt(w.workplace_id) || 0; const categoryName = escapeHtml(w.category_name || ''); const workplaceName = escapeHtml(w.workplace_name || ''); const label = categoryName ? categoryName + ' - ' + workplaceName : workplaceName; return ``; }).join(''); if (filterWorkplace) filterWorkplace.innerHTML = '' + workplaceOptions; if (modalWorkplace) modalWorkplace.innerHTML = '' + workplaceOptions; } // 설비 유형 필터 채우기 function populateTypeFilter() { const filterType = document.getElementById('filterType'); if (!filterType) return; const typeOptions = equipmentTypes.map(type => { const safeType = escapeHtml(type || ''); return ``; }).join(''); filterType.innerHTML = '' + typeOptions; } // 설비 목록 렌더링 function renderEquipmentList() { const container = document.getElementById('equipmentList'); if (equipments.length === 0) { container.innerHTML = `

등록된 설비가 없습니다.

`; return; } const tableHTML = `
검색 결과 ${equipments.length}건
${equipments.map(eq => { const safeId = parseInt(eq.equipment_id) || 0; const safeCode = escapeHtml(eq.equipment_code || '-'); const safeName = escapeHtml(eq.equipment_name || '-'); const safeModel = escapeHtml(eq.model_name || '-'); const safeSpec = escapeHtml(eq.specifications || '-'); const safeManufacturer = escapeHtml(eq.manufacturer || '-'); const safeSupplier = escapeHtml(eq.supplier || '-'); const validStatuses = ['active', 'maintenance', 'inactive']; const safeStatus = validStatuses.includes(eq.status) ? eq.status : 'inactive'; return ` `; }).join('')}
관리번호 설비명 모델명 규격 제조사 구입처 구입가격 구입일자 상태 관리
${safeCode} ${safeName} ${safeModel} ${safeSpec} ${safeManufacturer} ${safeSupplier} ${eq.purchase_price ? formatPrice(eq.purchase_price) : '-'} ${eq.installation_date ? formatDate(eq.installation_date) : '-'} ${getStatusText(eq.status)}
`; container.innerHTML = tableHTML; } // 상태 텍스트 변환 function getStatusText(status) { const statusMap = { 'active': '활성', 'maintenance': '정비중', 'inactive': '비활성' }; return statusMap[status] || status || '-'; } // 가격 포맷팅 (전체) function formatPrice(price) { if (!price) return '-'; return Number(price).toLocaleString('ko-KR') + '원'; } // 가격 포맷팅 (축약) function formatPriceShort(price) { if (!price) return '0원'; const num = Number(price); if (num >= 100000000) { return (num / 100000000).toFixed(1).replace(/\.0$/, '') + '억원'; } else if (num >= 10000) { return (num / 10000).toFixed(0) + '만원'; } return num.toLocaleString('ko-KR') + '원'; } // 날짜 포맷팅 function formatDate(dateStr) { if (!dateStr) return '-'; const date = new Date(dateStr); return date.toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit' }); } // 필터링 function filterEquipments() { const workplaceFilter = document.getElementById('filterWorkplace').value; const typeFilter = document.getElementById('filterType').value; const statusFilter = document.getElementById('filterStatus').value; const searchTerm = document.getElementById('searchInput').value.toLowerCase(); equipments = allEquipments.filter(e => { if (workplaceFilter && e.workplace_id != workplaceFilter) return false; if (typeFilter && e.equipment_type !== typeFilter) return false; if (statusFilter && e.status !== statusFilter) return false; if (searchTerm) { const searchFields = [ e.equipment_name, e.equipment_code, e.manufacturer, e.supplier, e.model_name ].map(f => (f || '').toLowerCase()); if (!searchFields.some(f => f.includes(searchTerm))) return false; } return true; }); renderEquipmentList(); } // 설비 추가 모달 열기 async function openEquipmentModal(equipmentId = null) { currentEquipment = equipmentId; const modal = document.getElementById('equipmentModal'); const modalTitle = document.getElementById('modalTitle'); const form = document.getElementById('equipmentForm'); form.reset(); document.getElementById('equipmentId').value = ''; if (equipmentId) { modalTitle.textContent = '설비 수정'; loadEquipmentData(equipmentId); } else { modalTitle.textContent = '설비 추가'; // 새 설비일 경우 다음 관리번호 자동 생성 await loadNextEquipmentCode(); } modal.style.display = 'flex'; } // 다음 관리번호 로드 async function loadNextEquipmentCode() { try { console.log('📋 다음 관리번호 조회 중...'); const response = await axios.get('/equipments/next-code'); console.log('📋 다음 관리번호 응답:', response.data); if (response.data.success) { document.getElementById('equipmentCode').value = response.data.data.next_code; console.log('✅ 다음 관리번호 설정:', response.data.data.next_code); } } catch (error) { console.error('❌ 다음 관리번호 조회 실패:', error); console.error('❌ 에러 상세:', error.response?.data || error.message); // 오류 시 기본값으로 빈 값 유지 (사용자가 직접 입력) } } // 설비 데이터 로드 (수정용) async function loadEquipmentData(equipmentId) { try { const response = await axios.get(`/equipments/${equipmentId}`); if (response.data.success) { const eq = response.data.data; document.getElementById('equipmentId').value = eq.equipment_id; document.getElementById('equipmentCode').value = eq.equipment_code || ''; document.getElementById('equipmentName').value = eq.equipment_name || ''; document.getElementById('equipmentType').value = eq.equipment_type || ''; document.getElementById('workplaceId').value = eq.workplace_id || ''; document.getElementById('manufacturer').value = eq.manufacturer || ''; document.getElementById('supplier').value = eq.supplier || ''; document.getElementById('purchasePrice').value = eq.purchase_price || ''; document.getElementById('modelName').value = eq.model_name || ''; document.getElementById('serialNumber').value = eq.serial_number || ''; document.getElementById('installationDate').value = eq.installation_date ? eq.installation_date.split('T')[0] : ''; document.getElementById('equipmentStatus').value = eq.status || 'active'; document.getElementById('specifications').value = eq.specifications || ''; document.getElementById('notes').value = eq.notes || ''; } } catch (error) { console.error('설비 데이터 로드 실패:', error); alert('설비 정보를 불러오는데 실패했습니다.'); } } // 설비 모달 닫기 function closeEquipmentModal() { document.getElementById('equipmentModal').style.display = 'none'; currentEquipment = null; } // 설비 저장 async function saveEquipment() { const equipmentId = document.getElementById('equipmentId').value; const equipmentData = { equipment_code: document.getElementById('equipmentCode').value.trim(), equipment_name: document.getElementById('equipmentName').value.trim(), equipment_type: document.getElementById('equipmentType').value.trim() || null, workplace_id: document.getElementById('workplaceId').value || null, manufacturer: document.getElementById('manufacturer').value.trim() || null, supplier: document.getElementById('supplier').value.trim() || null, purchase_price: document.getElementById('purchasePrice').value || null, model_name: document.getElementById('modelName').value.trim() || null, serial_number: document.getElementById('serialNumber').value.trim() || null, installation_date: document.getElementById('installationDate').value || null, status: document.getElementById('equipmentStatus').value, specifications: document.getElementById('specifications').value.trim() || null, notes: document.getElementById('notes').value.trim() || null }; if (!equipmentData.equipment_code) { alert('관리번호를 입력해주세요.'); return; } if (!equipmentData.equipment_name) { alert('설비명을 입력해주세요.'); return; } try { let response; if (equipmentId) { response = await axios.put(`/equipments/${equipmentId}`, equipmentData); } else { response = await axios.post('/equipments', equipmentData); } if (response.data.success) { alert(equipmentId ? '설비가 수정되었습니다.' : '설비가 추가되었습니다.'); closeEquipmentModal(); await loadEquipments(); await loadEquipmentTypes(); } } catch (error) { console.error('설비 저장 실패:', error); if (error.response?.data?.message) { alert(error.response.data.message); } else { alert('설비 저장 중 오류가 발생했습니다.'); } } } // 설비 수정 function editEquipment(equipmentId) { openEquipmentModal(equipmentId); } // 설비 삭제 async function deleteEquipment(equipmentId) { const equipment = allEquipments.find(e => e.equipment_id === equipmentId); if (!equipment) return; if (!confirm(`'${equipment.equipment_name}' 설비를 삭제하시겠습니까?`)) { return; } try { const response = await axios.delete(`/equipments/${equipmentId}`); if (response.data.success) { alert('설비가 삭제되었습니다.'); await loadEquipments(); } } catch (error) { console.error('설비 삭제 실패:', error); alert('설비 삭제 중 오류가 발생했습니다.'); } } // ESC 키로 모달 닫기 document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { closeEquipmentModal(); } }); // 모달 외부 클릭 시 닫기 document.getElementById('equipmentModal')?.addEventListener('click', (e) => { if (e.target.id === 'equipmentModal') { closeEquipmentModal(); } });