// 한약 재고관리 시스템 - Frontend JavaScript $(document).ready(function() { // 페이지 네비게이션 $('.sidebar .nav-link').on('click', function(e) { e.preventDefault(); const page = $(this).data('page'); // Active 상태 변경 $('.sidebar .nav-link').removeClass('active'); $(this).addClass('active'); // 페이지 전환 $('.main-content').removeClass('active'); $(`#${page}`).addClass('active'); // 페이지별 데이터 로드 loadPageData(page); }); // 초기 데이터 로드 loadPageData('dashboard'); // 페이지별 데이터 로드 함수 function loadPageData(page) { switch(page) { case 'dashboard': loadDashboard(); break; case 'patients': loadPatients(); break; case 'purchase': loadPurchaseReceipts(); loadSuppliersForSelect(); break; case 'formulas': loadFormulas(); break; case 'compound': loadCompounds(); loadPatientsForSelect(); loadFormulasForSelect(); break; case 'inventory': loadInventory(); break; case 'herbs': loadHerbs(); break; } } // 대시보드 데이터 로드 function loadDashboard() { // 환자 수 $.get('/api/patients', function(response) { if (response.success) { $('#totalPatients').text(response.data.length); } }); // 재고 현황 $.get('/api/inventory/summary', function(response) { if (response.success) { $('#totalHerbs').text(response.data.length); $('#inventoryValue').text(formatCurrency(response.summary.total_value)); } }); // 오늘 조제 수 $.get('/api/compounds', function(response) { if (response.success) { const today = new Date().toISOString().split('T')[0]; const todayCompounds = response.data.filter(c => c.compound_date === today); $('#todayCompounds').text(todayCompounds.length); } }); } // 환자 목록 로드 function loadPatients() { $.get('/api/patients', function(response) { if (response.success) { const tbody = $('#patientsList'); tbody.empty(); response.data.forEach(patient => { tbody.append(` ${patient.name} ${patient.phone} ${patient.gender === 'M' ? '남' : patient.gender === 'F' ? '여' : '-'} ${patient.birth_date || '-'} ${patient.notes || '-'} `); }); } }); } // 환자 등록 $('#savePatientBtn').on('click', function() { const patientData = { name: $('#patientName').val(), phone: $('#patientPhone').val(), jumin_no: $('#patientJumin').val(), gender: $('#patientGender').val(), birth_date: $('#patientBirth').val(), address: $('#patientAddress').val(), notes: $('#patientNotes').val() }; $.ajax({ url: '/api/patients', method: 'POST', contentType: 'application/json', data: JSON.stringify(patientData), success: function(response) { if (response.success) { alert('환자가 등록되었습니다.'); $('#patientModal').modal('hide'); $('#patientForm')[0].reset(); loadPatients(); } }, error: function(xhr) { alert('오류: ' + xhr.responseJSON.error); } }); }); // 처방 목록 로드 function loadFormulas() { $.get('/api/formulas', function(response) { if (response.success) { const tbody = $('#formulasList'); tbody.empty(); response.data.forEach(formula => { tbody.append(` ${formula.formula_code || '-'} ${formula.formula_name} ${formula.base_cheop}첩 ${formula.base_pouches}파우치 `); }); // 구성 약재 보기 $('.view-ingredients').on('click', function() { const formulaId = $(this).data('id'); $.get(`/api/formulas/${formulaId}/ingredients`, function(response) { if (response.success) { let ingredientsList = response.data.map(ing => `${ing.herb_name}: ${ing.grams_per_cheop}g` ).join(', '); alert('구성 약재:\n' + ingredientsList); } }); }); } }); } // 처방 구성 약재 추가 (모달) let formulaIngredientCount = 0; $('#addFormulaIngredientBtn').on('click', function() { formulaIngredientCount++; $('#formulaIngredients').append(` `); // 약재 목록 로드 const selectElement = $(`#formulaIngredients tr[data-row="${formulaIngredientCount}"] .herb-select`); loadHerbsForSelect(selectElement); // 삭제 버튼 이벤트 $(`#formulaIngredients tr[data-row="${formulaIngredientCount}"] .remove-ingredient`).on('click', function() { $(this).closest('tr').remove(); }); }); // 처방 저장 $('#saveFormulaBtn').on('click', function() { const ingredients = []; $('#formulaIngredients tr').each(function() { const herbId = $(this).find('.herb-select').val(); const grams = $(this).find('.grams-input').val(); if (herbId && grams) { ingredients.push({ herb_item_id: parseInt(herbId), grams_per_cheop: parseFloat(grams), notes: $(this).find('.notes-input').val() }); } }); const formulaData = { formula_code: $('#formulaCode').val(), formula_name: $('#formulaName').val(), formula_type: $('#formulaType').val(), base_cheop: parseInt($('#baseCheop').val()), base_pouches: parseInt($('#basePouches').val()), description: $('#formulaDescription').val(), ingredients: ingredients }; $.ajax({ url: '/api/formulas', method: 'POST', contentType: 'application/json', data: JSON.stringify(formulaData), success: function(response) { if (response.success) { alert('처방이 등록되었습니다.'); $('#formulaModal').modal('hide'); $('#formulaForm')[0].reset(); $('#formulaIngredients').empty(); loadFormulas(); } }, error: function(xhr) { alert('오류: ' + xhr.responseJSON.error); } }); }); // 조제 관리 $('#newCompoundBtn').on('click', function() { $('#compoundForm').show(); $('#compoundEntryForm')[0].reset(); $('#compoundIngredients').empty(); }); $('#cancelCompoundBtn').on('click', function() { $('#compoundForm').hide(); }); // 제수 변경 시 첩수 자동 계산 $('#jeCount').on('input', function() { const jeCount = parseFloat($(this).val()) || 0; const cheopTotal = jeCount * 20; const pouchTotal = jeCount * 30; $('#cheopTotal').val(cheopTotal); $('#pouchTotal').val(pouchTotal); // 약재별 총 용량 재계산 updateIngredientTotals(); }); // 처방 선택 시 구성 약재 로드 $('#compoundFormula').on('change', function() { const formulaId = $(this).val(); if (!formulaId) { $('#compoundIngredients').empty(); return; } // 직접조제인 경우 if (formulaId === 'custom') { $('#compoundIngredients').empty(); // 빈 행 하나 추가 addEmptyIngredientRow(); return; } // 등록된 처방인 경우 $.get(`/api/formulas/${formulaId}/ingredients`, function(response) { if (response.success) { $('#compoundIngredients').empty(); response.data.forEach(ing => { const cheopTotal = parseFloat($('#cheopTotal').val()) || 0; const totalGrams = ing.grams_per_cheop * cheopTotal; $('#compoundIngredients').append(` ${ing.herb_name} ${totalGrams.toFixed(1)} 확인중... `); // 각 약재별로 원산지별 재고 확인 loadOriginOptions(ing.herb_item_id, totalGrams); }); // 재고 확인 checkStockForCompound(); // 용량 변경 이벤트 $('.grams-per-cheop').on('input', updateIngredientTotals); // 삭제 버튼 이벤트 $('.remove-compound-ingredient').on('click', function() { $(this).closest('tr').remove(); }); } }); }); // 약재별 총 용량 업데이트 function updateIngredientTotals() { const cheopTotal = parseFloat($('#cheopTotal').val()) || 0; $('#compoundIngredients tr').each(function() { const gramsPerCheop = parseFloat($(this).find('.grams-per-cheop').val()) || 0; const totalGrams = gramsPerCheop * cheopTotal; $(this).find('.total-grams').text(totalGrams.toFixed(1)); }); checkStockForCompound(); } // 재고 확인 function checkStockForCompound() { $('#compoundIngredients tr').each(function() { const herbId = $(this).data('herb-id'); const totalGrams = parseFloat($(this).find('.total-grams').text()) || 0; const $stockStatus = $(this).find('.stock-status'); // TODO: API 호출로 실제 재고 확인 $stockStatus.text('재고 확인 필요'); }); } // 조제 약재 추가 // 빈 약재 행 추가 함수 function addEmptyIngredientRow() { const newRow = $(` 0.0 - `); $('#compoundIngredients').append(newRow); // 약재 목록 로드 loadHerbsForSelect(newRow.find('.herb-select-compound')); // 약재 선택 시 원산지 옵션 로드 newRow.find('.herb-select-compound').on('change', function() { const herbId = $(this).val(); if (herbId) { const row = $(this).closest('tr'); row.attr('data-herb-id', herbId); const cheopTotal = parseFloat($('#cheopTotal').val()) || 0; const gramsPerCheop = parseFloat(row.find('.grams-per-cheop').val()) || 0; const totalGrams = gramsPerCheop * cheopTotal; loadOriginOptions(herbId, totalGrams); } }); // 이벤트 바인딩 newRow.find('.grams-per-cheop').on('input', function() { updateIngredientTotals(); // 원산지 옵션 다시 로드 const herbId = $(this).closest('tr').attr('data-herb-id'); if (herbId) { const cheopTotal = parseFloat($('#cheopTotal').val()) || 0; const gramsPerCheop = parseFloat($(this).val()) || 0; const totalGrams = gramsPerCheop * cheopTotal; loadOriginOptions(herbId, totalGrams); } }); newRow.find('.remove-compound-ingredient').on('click', function() { $(this).closest('tr').remove(); updateIngredientTotals(); }); } $('#addIngredientBtn').on('click', function() { addEmptyIngredientRow(); }); // 기존 약재 추가 버튼 (기존 코드 삭제) /* $('#addIngredientBtn').on('click', function() { const newRow = $(` 0.0 - `); $('#compoundIngredients').append(newRow); // 약재 목록 로드 loadHerbsForSelect(newRow.find('.herb-select-compound')); // 이벤트 바인딩 newRow.find('.grams-per-cheop').on('input', updateIngredientTotals); newRow.find('.remove-compound-ingredient').on('click', function() { $(this).closest('tr').remove(); }); newRow.find('.herb-select-compound').on('change', function() { const herbId = $(this).val(); $(this).closest('tr').attr('data-herb-id', herbId); updateIngredientTotals(); }); }); */ // 조제 실행 $('#compoundEntryForm').on('submit', function(e) { e.preventDefault(); const ingredients = []; $('#compoundIngredients tr').each(function() { const herbId = $(this).data('herb-id'); const gramsPerCheop = parseFloat($(this).find('.grams-per-cheop').val()); const totalGrams = parseFloat($(this).find('.total-grams').text()); const originCountry = $(this).find('.origin-select').val(); if (herbId && gramsPerCheop) { ingredients.push({ herb_item_id: parseInt(herbId), grams_per_cheop: gramsPerCheop, total_grams: totalGrams, origin_country: originCountry || null // 원산지 선택 정보 추가 }); } }); const compoundData = { patient_id: $('#compoundPatient').val() ? parseInt($('#compoundPatient').val()) : null, formula_id: $('#compoundFormula').val() ? parseInt($('#compoundFormula').val()) : null, je_count: parseFloat($('#jeCount').val()), cheop_total: parseFloat($('#cheopTotal').val()), pouch_total: parseFloat($('#pouchTotal').val()), ingredients: ingredients }; $.ajax({ url: '/api/compounds', method: 'POST', contentType: 'application/json', data: JSON.stringify(compoundData), success: function(response) { if (response.success) { alert(`조제가 완료되었습니다.\n원가: ${formatCurrency(response.total_cost)}`); $('#compoundForm').hide(); loadCompounds(); } }, error: function(xhr) { alert('오류: ' + xhr.responseJSON.error); } }); }); // 조제 내역 로드 function loadCompounds() { $.get('/api/compounds', function(response) { const tbody = $('#compoundsList'); tbody.empty(); if (response.success && response.data.length > 0) { // 통계 업데이트 const today = new Date().toISOString().split('T')[0]; const currentMonth = new Date().toISOString().slice(0, 7); let todayCount = 0; let monthCount = 0; response.data.forEach((compound, index) => { // 통계 계산 if (compound.compound_date === today) todayCount++; if (compound.compound_date && compound.compound_date.startsWith(currentMonth)) monthCount++; // 상태 뱃지 let statusBadge = ''; switch(compound.status) { case 'PREPARED': statusBadge = '조제완료'; break; case 'DISPENSED': statusBadge = '출고완료'; break; case 'CANCELLED': statusBadge = '취소'; break; default: statusBadge = '대기'; } const row = $(` ${response.data.length - index} ${compound.compound_date || ''}
${compound.created_at ? compound.created_at.split(' ')[1] : ''} ${compound.patient_name || '직접조제'} ${compound.patient_phone || '-'} ${compound.formula_name || '직접조제'} ${compound.je_count || 0} ${compound.cheop_total || 0} ${compound.pouch_total || 0} ${formatCurrency(compound.cost_total || 0)} ${formatCurrency(compound.sell_price_total || 0)} ${statusBadge} ${compound.prescription_no || '-'} `); tbody.append(row); }); // 통계 업데이트 $('#todayCompoundCount').text(todayCount); $('#monthCompoundCount').text(monthCount); // 상세보기 버튼 이벤트 $('.view-compound-detail').on('click', function() { const compoundId = $(this).data('id'); viewCompoundDetail(compoundId); }); } else { tbody.html('조제 내역이 없습니다.'); $('#todayCompoundCount').text(0); $('#monthCompoundCount').text(0); } }).fail(function() { $('#compoundsList').html('데이터를 불러오는데 실패했습니다.'); }); } // 조제 상세보기 function viewCompoundDetail(compoundId) { $.get(`/api/compounds/${compoundId}`, function(response) { if (response.success && response.data) { const data = response.data; // 환자 정보 $('#detailPatientName').text(data.patient_name || '직접조제'); $('#detailPatientPhone').text(data.patient_phone || '-'); $('#detailCompoundDate').text(data.compound_date || '-'); // 처방 정보 $('#detailFormulaName').text(data.formula_name || '직접조제'); $('#detailPrescriptionNo').text(data.prescription_no || '-'); $('#detailQuantities').text(`${data.je_count}제 / ${data.cheop_total}첩 / ${data.pouch_total}파우치`); // 처방 구성 약재 const ingredientsBody = $('#detailIngredients'); ingredientsBody.empty(); if (data.ingredients && data.ingredients.length > 0) { data.ingredients.forEach(ing => { ingredientsBody.append(` ${ing.herb_name} ${ing.insurance_code || '-'} ${ing.grams_per_cheop}g ${ing.total_grams}g ${ing.notes || '-'} `); }); } // 재고 소비 내역 const consumptionsBody = $('#detailConsumptions'); consumptionsBody.empty(); if (data.consumptions && data.consumptions.length > 0) { data.consumptions.forEach(con => { consumptionsBody.append(` ${con.herb_name} ${con.origin_country || '-'} ${con.supplier_name || '-'} ${con.quantity_used}g ${formatCurrency(con.unit_cost_per_g)}/g ${formatCurrency(con.cost_amount)} `); }); } // 총 원가 $('#detailTotalCost').text(formatCurrency(data.cost_total || 0)); // 비고 $('#detailNotes').text(data.notes || ''); // 모달 표시 $('#compoundDetailModal').modal('show'); } }).fail(function() { alert('조제 상세 정보를 불러오는데 실패했습니다.'); }); } // 재고 현황 로드 function loadInventory() { $.get('/api/inventory/summary', function(response) { if (response.success) { const tbody = $('#inventoryList'); tbody.empty(); let totalValue = 0; let herbsInStock = 0; // 주성분코드 기준 보유 현황 표시 if (response.summary) { const summary = response.summary; const coverageHtml = `
📊 급여 약재 보유 현황
전체 급여 약재: ${summary.total_ingredient_codes || 454}개 주성분
보유 약재: ${summary.owned_ingredient_codes || 0}개 주성분
보유율: ${summary.coverage_rate || 0}%
${summary.owned_ingredient_codes || 0} / ${summary.total_ingredient_codes || 454}
※ 건강보험 급여 한약재 ${summary.total_ingredient_codes || 454}개 주성분 중 ${summary.owned_ingredient_codes || 0}개 보유
`; // 재고 테이블 위에 통계 표시 if ($('#inventoryCoverage').length === 0) { $('#inventoryList').parent().before(`
${coverageHtml}
`); } else { $('#inventoryCoverage').html(coverageHtml); } } response.data.forEach(item => { // 원산지가 여러 개인 경우 표시 const originBadge = item.origin_count > 1 ? `${item.origin_count}개 원산지` : ''; // 효능 태그 표시 let efficacyTags = ''; if (item.efficacy_tags && item.efficacy_tags.length > 0) { efficacyTags = item.efficacy_tags.map(tag => `${tag}` ).join(''); } // 가격 범위 표시 (원산지가 여러 개이고 가격차가 있는 경우) let priceDisplay = item.avg_price ? formatCurrency(item.avg_price) : '-'; if (item.origin_count > 1 && item.min_price && item.max_price && item.min_price !== item.max_price) { priceDisplay = `${formatCurrency(item.min_price)} ~ ${formatCurrency(item.max_price)}`; } // 통계 업데이트 totalValue += item.total_value || 0; if (item.total_quantity > 0) herbsInStock++; tbody.append(` ${item.insurance_code || '-'} ${item.herb_name}${originBadge}${efficacyTags} ${item.total_quantity.toFixed(1)} ${item.lot_count} ${priceDisplay} ${formatCurrency(item.total_value)} `); }); // 통계 업데이트 $('#totalInventoryValue').text(formatCurrency(totalValue)); $('#totalHerbsInStock').text(`${herbsInStock}종`); // 클릭 이벤트 바인딩 $('.view-inventory-detail').on('click', function(e) { e.stopPropagation(); const herbId = $(this).data('herb-id'); showInventoryDetail(herbId); }); // 입출고 내역 버튼 이벤트 $('.view-stock-ledger').on('click', function(e) { e.stopPropagation(); const herbId = $(this).data('herb-id'); const herbName = $(this).data('herb-name'); viewStockLedger(herbId, herbName); }); } }); } // 재고 상세 모달 표시 function showInventoryDetail(herbId) { $.get(`/api/inventory/detail/${herbId}`, function(response) { if (response.success) { const data = response.data; // 원산지별 재고 정보 HTML 생성 let originsHtml = ''; data.origins.forEach(origin => { originsHtml += `
${origin.origin_country} ${origin.total_quantity.toFixed(1)}g
평균 단가:
${formatCurrency(origin.avg_price)}/g
재고 가치:
${formatCurrency(origin.total_value)}
`; origin.lots.forEach(lot => { originsHtml += ` `; }); originsHtml += `
로트ID 수량 단가 입고일 도매상
#${lot.lot_id} ${lot.quantity_onhand.toFixed(1)}g ${formatCurrency(lot.unit_price_per_g)} ${lot.received_date} ${lot.supplier_name || '-'}
`; }); // 모달 생성 및 표시 const modalHtml = ` `; // 기존 모달 제거 $('#inventoryDetailModal').remove(); $('body').append(modalHtml); // 모달 표시 const modal = new bootstrap.Modal(document.getElementById('inventoryDetailModal')); modal.show(); } }); } // 약재 목록 로드 function loadHerbs() { $.get('/api/herbs', function(response) { if (response.success) { const tbody = $('#herbsList'); tbody.empty(); response.data.forEach(herb => { tbody.append(` ${herb.insurance_code || '-'} ${herb.herb_name} ${herb.specification || '-'} ${herb.current_stock ? herb.current_stock.toFixed(1) + 'g' : '0g'} `); }); } }); } // 입고장 목록 로드 function loadPurchaseReceipts() { const startDate = $('#purchaseStartDate').val(); const endDate = $('#purchaseEndDate').val(); const supplierId = $('#purchaseSupplier').val(); let url = '/api/purchase-receipts?'; if (startDate) url += `start_date=${startDate}&`; if (endDate) url += `end_date=${endDate}&`; if (supplierId) url += `supplier_id=${supplierId}`; $.get(url, function(response) { if (response.success) { const tbody = $('#purchaseReceiptsList'); tbody.empty(); if (response.data.length === 0) { tbody.append('입고장이 없습니다.'); return; } response.data.forEach(receipt => { tbody.append(` ${receipt.receipt_date} ${receipt.supplier_name} ${receipt.line_count}개 ${receipt.total_amount ? formatCurrency(receipt.total_amount) : '-'} ${receipt.total_quantity ? receipt.total_quantity.toLocaleString() + 'g' : '-'} ${receipt.source_file || '-'} `); }); // 이벤트 바인딩 $('.view-receipt').on('click', function() { const receiptId = $(this).data('id'); viewReceiptDetail(receiptId); }); $('.delete-receipt').on('click', function() { const receiptId = $(this).data('id'); if (confirm('정말 이 입고장을 삭제하시겠습니까? 사용되지 않은 재고만 삭제 가능합니다.')) { deleteReceipt(receiptId); } }); } }); } // 입고장 상세 보기 function viewReceiptDetail(receiptId) { $.get(`/api/purchase-receipts/${receiptId}`, function(response) { if (response.success) { const data = response.data; let linesHtml = ''; data.lines.forEach(line => { linesHtml += ` ${line.herb_name} ${line.insurance_code || '-'} ${line.origin_country || '-'} ${line.quantity_g}g ${formatCurrency(line.unit_price_per_g)} ${formatCurrency(line.line_total)} ${line.current_stock}g `; }); const modalHtml = ` `; // 기존 모달 제거 $('#receiptDetailModal').remove(); $('body').append(modalHtml); $('#receiptDetailModal').modal('show'); } }); } // 입고장 삭제 function deleteReceipt(receiptId) { $.ajax({ url: `/api/purchase-receipts/${receiptId}`, method: 'DELETE', success: function(response) { if (response.success) { alert(response.message); loadPurchaseReceipts(); } }, error: function(xhr) { alert('오류: ' + xhr.responseJSON.error); } }); } // 입고장 조회 버튼 $('#searchPurchaseBtn').on('click', function() { loadPurchaseReceipts(); }); // 도매상 목록 로드 (셀렉트 박스용) function loadSuppliersForSelect() { $.get('/api/suppliers', function(response) { if (response.success) { const select = $('#uploadSupplier'); select.empty().append(''); response.data.forEach(supplier => { select.append(``); }); // 필터용 셀렉트 박스도 업데이트 const filterSelect = $('#purchaseSupplier'); filterSelect.empty().append(''); response.data.forEach(supplier => { filterSelect.append(``); }); } }); } // 도매상 등록 $('#saveSupplierBtn').on('click', function() { const supplierData = { name: $('#supplierName').val(), business_no: $('#supplierBusinessNo').val(), contact_person: $('#supplierContactPerson').val(), phone: $('#supplierPhone').val(), address: $('#supplierAddress').val() }; if (!supplierData.name) { alert('도매상명은 필수입니다.'); return; } $.ajax({ url: '/api/suppliers', method: 'POST', contentType: 'application/json', data: JSON.stringify(supplierData), success: function(response) { if (response.success) { alert('도매상이 등록되었습니다.'); $('#supplierModal').modal('hide'); $('#supplierForm')[0].reset(); loadSuppliersForSelect(); } }, error: function(xhr) { alert('오류: ' + xhr.responseJSON.error); } }); }); // 입고장 업로드 $('#purchaseUploadForm').on('submit', function(e) { e.preventDefault(); const supplierId = $('#uploadSupplier').val(); if (!supplierId) { alert('도매상을 선택해주세요.'); return; } const formData = new FormData(); const fileInput = $('#purchaseFile')[0]; if (fileInput.files.length === 0) { alert('파일을 선택해주세요.'); return; } formData.append('file', fileInput.files[0]); formData.append('supplier_id', supplierId); $('#uploadResult').html('
업로드 중...
'); $.ajax({ url: '/api/upload/purchase', method: 'POST', data: formData, processData: false, contentType: false, success: function(response) { if (response.success) { let summaryHtml = ''; if (response.summary) { summaryHtml = `
형식: ${response.summary.format}
처리: ${response.summary.processed_rows}개 라인
품목: ${response.summary.total_items}종
수량: ${response.summary.total_quantity}
금액: ${response.summary.total_amount}
`; } $('#uploadResult').html( `
${response.message} ${summaryHtml}
` ); $('#purchaseUploadForm')[0].reset(); // 입고장 목록 새로고침 loadPurchaseReceipts(); } }, error: function(xhr) { $('#uploadResult').html( `
오류: ${xhr.responseJSON.error}
` ); } }); }); // 검색 기능 $('#patientSearch').on('keyup', function() { const value = $(this).val().toLowerCase(); $('#patientsList tr').filter(function() { $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); }); }); $('#inventorySearch').on('keyup', function() { const value = $(this).val().toLowerCase(); $('#inventoryList tr').filter(function() { $(this).toggle($(this).text().toLowerCase().indexOf(value) > -1); }); }); // 헬퍼 함수들 function loadPatientsForSelect() { $.get('/api/patients', function(response) { if (response.success) { const select = $('#compoundPatient'); select.empty().append(''); response.data.forEach(patient => { select.append(``); }); } }); } function loadFormulasForSelect() { $.get('/api/formulas', function(response) { if (response.success) { const select = $('#compoundFormula'); select.empty().append(''); // 직접조제 옵션 추가 select.append(''); // 등록된 처방 추가 if (response.data.length > 0) { select.append(''); response.data.forEach(formula => { select.append(``); }); select.append(''); } } }); } function loadHerbsForSelect(selectElement) { $.get('/api/herbs', function(response) { if (response.success) { selectElement.empty().append(''); response.data.forEach(herb => { selectElement.append(``); }); } }); } // 원산지별 재고 옵션 로드 function loadOriginOptions(herbId, requiredQty) { $.get(`/api/herbs/${herbId}/available-lots`, function(response) { if (response.success) { const selectElement = $(`tr[data-herb-id="${herbId}"] .origin-select`); selectElement.empty(); const origins = response.data.origins; if (origins.length === 0) { selectElement.append(''); selectElement.prop('disabled', true); $(`tr[data-herb-id="${herbId}"] .stock-status`) .html('재고 없음'); } else { selectElement.append(''); origins.forEach(origin => { const stockStatus = origin.total_quantity >= requiredQty ? '' : ' (재고 부족)'; const priceInfo = `${formatCurrency(origin.min_price)}/g`; const option = ``; selectElement.append(option); }); selectElement.prop('disabled', false); // 재고 상태 업데이트 const totalAvailable = response.data.total_quantity; const statusElement = $(`tr[data-herb-id="${herbId}"] .stock-status`); if (totalAvailable >= requiredQty) { statusElement.html(`충분 (${totalAvailable.toFixed(1)}g)`); } else { statusElement.html(`부족 (${totalAvailable.toFixed(1)}g)`); } } } }); } // 재고 원장 보기 let currentLedgerData = []; // 원본 데이터 저장 function viewStockLedger(herbId, herbName) { const url = herbId ? `/api/stock-ledger?herb_id=${herbId}` : '/api/stock-ledger'; $.get(url, function(response) { if (response.success) { // 원본 데이터 저장 currentLedgerData = response.ledger; // 헤더 업데이트 if (herbName) { $('#stockLedgerModal .modal-title').html(` ${herbName} 입출고 원장`); } else { $('#stockLedgerModal .modal-title').html(` 전체 입출고 원장`); } // 필터 적용하여 표시 applyLedgerFilters(); // 약재 필터 옵션 업데이트 const herbFilter = $('#ledgerHerbFilter'); if (herbFilter.find('option').length <= 1) { response.summary.forEach(herb => { herbFilter.append(``); }); } $('#stockLedgerModal').modal('show'); } }).fail(function() { alert('입출고 내역을 불러오는데 실패했습니다.'); }); } // 필터 적용 함수 function applyLedgerFilters() { const typeFilter = $('#ledgerTypeFilter').val(); const tbody = $('#stockLedgerList'); tbody.empty(); // 필터링된 데이터 let filteredData = currentLedgerData; // 타입 필터 적용 if (typeFilter) { filteredData = currentLedgerData.filter(entry => entry.event_type === typeFilter); } // 데이터 표시 filteredData.forEach(entry => { let typeLabel = ''; let typeBadge = ''; switch(entry.event_type) { case 'PURCHASE': case 'RECEIPT': typeLabel = '입고'; typeBadge = 'badge bg-success'; break; case 'CONSUME': typeLabel = '출고'; typeBadge = 'badge bg-danger'; break; case 'ADJUST': typeLabel = '보정'; typeBadge = 'badge bg-warning'; break; default: typeLabel = entry.event_type; typeBadge = 'badge bg-secondary'; } const quantity = Math.abs(entry.quantity_delta); const sign = entry.quantity_delta > 0 ? '+' : '-'; const quantityDisplay = entry.quantity_delta > 0 ? `+${quantity.toFixed(1)}g` : `-${quantity.toFixed(1)}g`; const referenceInfo = entry.patient_name ? `${entry.patient_name}` : entry.supplier_name || '-'; tbody.append(` ${entry.event_time} ${typeLabel} ${entry.herb_name} ${quantityDisplay} ${entry.unit_cost_per_g ? formatCurrency(entry.unit_cost_per_g) + '/g' : '-'} ${entry.origin_country || '-'} ${referenceInfo} ${entry.reference_no || '-'} `); }); // 데이터가 없는 경우 if (filteredData.length === 0) { tbody.append(` 데이터가 없습니다. `); } } // 입출고 원장 모달 버튼 이벤트 $('#showStockLedgerBtn').on('click', function() { viewStockLedger(null, null); }); // 필터 변경 이벤트 $('#ledgerHerbFilter').on('change', function() { const herbId = $(this).val(); // 약재 필터 변경 시 데이터 재로드 if (herbId) { const herbName = $('#ledgerHerbFilter option:selected').text(); viewStockLedger(herbId, herbName); } else { viewStockLedger(null, null); } }); // 타입 필터 변경 이벤트 (현재 데이터에서 필터링만) $('#ledgerTypeFilter').on('change', function() { applyLedgerFilters(); }); function formatCurrency(amount) { if (amount === null || amount === undefined) return '0원'; return new Intl.NumberFormat('ko-KR', { style: 'currency', currency: 'KRW' }).format(amount); } // ==================== 주성분코드 기반 약재 관리 ==================== let allHerbMasters = []; // 전체 약재 데이터 저장 let currentFilter = 'all'; // 현재 필터 상태 // 약재 마스터 목록 로드 function loadHerbMasters() { $.get('/api/herbs/masters', function(response) { if (response.success) { allHerbMasters = response.data; // 통계 정보 표시 const summary = response.summary; $('#herbMasterSummary').html(`
📊 급여 약재 현황
전체: ${summary.total_herbs}개 주성분
재고 있음: ${summary.herbs_with_stock}개
재고 없음: ${summary.herbs_without_stock}개
보유율: ${summary.coverage_rate}%
${summary.herbs_with_stock} / ${summary.total_herbs}
`); // 목록 표시 displayHerbMasters(allHerbMasters); } }); } // 약재 목록 표시 function displayHerbMasters(herbs) { const tbody = $('#herbMastersList'); tbody.empty(); // 필터링 let filteredHerbs = herbs; if (currentFilter === 'stock') { filteredHerbs = herbs.filter(h => h.has_stock); } else if (currentFilter === 'no-stock') { filteredHerbs = herbs.filter(h => !h.has_stock); } // 검색 필터 const searchText = $('#herbSearch').val().toLowerCase(); if (searchText) { filteredHerbs = filteredHerbs.filter(h => h.herb_name.toLowerCase().includes(searchText) || h.ingredient_code.toLowerCase().includes(searchText) ); } // 효능 필터 const efficacyFilter = $('#efficacyFilter').val(); if (efficacyFilter) { filteredHerbs = filteredHerbs.filter(h => h.efficacy_tags && h.efficacy_tags.includes(efficacyFilter) ); } // 표시 filteredHerbs.forEach(herb => { // 효능 태그 표시 let efficacyTags = ''; if (herb.efficacy_tags && herb.efficacy_tags.length > 0) { efficacyTags = herb.efficacy_tags.map(tag => `${tag}` ).join(''); } // 상태 표시 const statusBadge = herb.has_stock ? '재고 있음' : '재고 없음'; // 재고량 표시 const stockDisplay = herb.stock_quantity > 0 ? `${herb.stock_quantity.toFixed(1)}g` : '-'; // 평균단가 표시 const priceDisplay = herb.avg_price > 0 ? formatCurrency(herb.avg_price) : '-'; tbody.append(` ${herb.ingredient_code} ${herb.herb_name} ${efficacyTags} ${stockDisplay} ${priceDisplay} ${herb.product_count || 0}개 ${statusBadge} `); }); if (filteredHerbs.length === 0) { tbody.append('표시할 약재가 없습니다.'); } } // 약재 상세 보기 function viewHerbDetail(ingredientCode) { // TODO: 약재 상세 모달 구현 console.log('View detail for:', ingredientCode); } // 필터 버튼 이벤트 $('#herbs .btn-group button[data-filter]').on('click', function() { $('#herbs .btn-group button').removeClass('active'); $(this).addClass('active'); currentFilter = $(this).data('filter'); displayHerbMasters(allHerbMasters); }); // 검색 이벤트 $('#herbSearch').on('keyup', function() { displayHerbMasters(allHerbMasters); }); // 효능 필터 이벤트 $('#efficacyFilter').on('change', function() { displayHerbMasters(allHerbMasters); }); // 약재 관리 페이지가 활성화되면 데이터 로드 $('.nav-link[data-page="herbs"]').on('click', function() { setTimeout(() => loadHerbMasters(), 100); }); });