feat: 실시간 커스텀 처방(가감방) 감지 시스템 구현
- 프론트엔드: 조제 시 실시간 커스텀 처방 감지 - 처방 선택 시 원래 구성 약재 저장 - 약재 추가/삭제/변경 시 즉시 감지 - 가감방 뱃지 및 변경 내용 표시 - 백엔드: 커스텀 처방 자동 감지 및 저장 - compounds 테이블에 커스텀 관련 필드 추가 - 조제 시 원 처방과 비교하여 변경사항 자동 감지 - 커스텀 처방 정보 저장 (추가/제거/변경된 약재) - 환자 조제 내역에 커스텀 처방 표시 - 가감방 뱃지 표시 - 변경 내용 상세 표시 - DB 마이그레이션 스크립트 추가 - is_custom, custom_summary, custom_type 필드 추가 - compound_ingredients에 modification_type, original_grams 필드 추가 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
103
static/app.js
103
static/app.js
@@ -1,5 +1,8 @@
|
||||
// 한약 재고관리 시스템 - Frontend JavaScript
|
||||
|
||||
// 원래 처방 구성 저장용 전역 변수
|
||||
let originalFormulaIngredients = {};
|
||||
|
||||
$(document).ready(function() {
|
||||
// 페이지 네비게이션
|
||||
$('.sidebar .nav-link').on('click', function(e) {
|
||||
@@ -273,13 +276,22 @@ $(document).ready(function() {
|
||||
|
||||
const detailRowId = `compound-detail-${compound.compound_id}`;
|
||||
|
||||
// 처방명 표시 (가감방 여부 포함)
|
||||
let formulaDisplay = compound.formula_name || '직접조제';
|
||||
if (compound.is_custom && compound.formula_name) {
|
||||
formulaDisplay = `${compound.formula_name} <span class="badge bg-warning ms-1">가감</span>`;
|
||||
}
|
||||
|
||||
tbody.append(`
|
||||
<tr class="compound-row" style="cursor: pointer;" data-compound-id="${compound.compound_id}">
|
||||
<td>
|
||||
<i class="bi bi-chevron-right toggle-icon"></i>
|
||||
</td>
|
||||
<td>${compound.compound_date || '-'}</td>
|
||||
<td>${compound.formula_name || '직접조제'}</td>
|
||||
<td>
|
||||
${formulaDisplay}
|
||||
${compound.custom_summary ? `<br><small class="text-muted">${compound.custom_summary}</small>` : ''}
|
||||
</td>
|
||||
<td>${compound.je_count || 0}</td>
|
||||
<td>${compound.cheop_total || 0}</td>
|
||||
<td>${compound.pouch_total || 0}</td>
|
||||
@@ -573,6 +585,11 @@ $(document).ready(function() {
|
||||
// 처방 선택 시 구성 약재 로드
|
||||
$('#compoundFormula').on('change', function() {
|
||||
const formulaId = $(this).val();
|
||||
|
||||
// 원래 처방 구성 초기화
|
||||
originalFormulaIngredients = {};
|
||||
$('#customPrescriptionBadge').remove(); // 커스텀 뱃지 제거
|
||||
|
||||
if (!formulaId) {
|
||||
$('#compoundIngredients').empty();
|
||||
return;
|
||||
@@ -591,6 +608,14 @@ $(document).ready(function() {
|
||||
if (response.success) {
|
||||
$('#compoundIngredients').empty();
|
||||
|
||||
// 원래 처방 구성 저장
|
||||
response.data.forEach(ing => {
|
||||
originalFormulaIngredients[ing.ingredient_code] = {
|
||||
herb_name: ing.herb_name,
|
||||
grams_per_cheop: ing.grams_per_cheop
|
||||
};
|
||||
});
|
||||
|
||||
response.data.forEach(ing => {
|
||||
const cheopTotal = parseFloat($('#cheopTotal').val()) || 0;
|
||||
const totalGrams = ing.grams_per_cheop * cheopTotal;
|
||||
@@ -688,6 +713,7 @@ $(document).ready(function() {
|
||||
// 삭제 버튼 이벤트
|
||||
$('.remove-compound-ingredient').on('click', function() {
|
||||
$(this).closest('tr').remove();
|
||||
updateIngredientTotals(); // 총용량 재계산 및 커스텀 감지
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -704,6 +730,80 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
checkStockForCompound();
|
||||
// 커스텀 처방 감지 호출
|
||||
checkCustomPrescription();
|
||||
}
|
||||
|
||||
// 커스텀 처방 감지 함수
|
||||
function checkCustomPrescription() {
|
||||
const formulaId = $('#compoundFormula').val();
|
||||
|
||||
// 처방이 선택되지 않았거나 직접조제인 경우 리턴
|
||||
if (!formulaId || formulaId === 'custom' || Object.keys(originalFormulaIngredients).length === 0) {
|
||||
$('#customPrescriptionBadge').remove();
|
||||
return;
|
||||
}
|
||||
|
||||
// 현재 약재 구성 수집
|
||||
const currentIngredients = {};
|
||||
$('#compoundIngredients tr').each(function() {
|
||||
const ingredientCode = $(this).attr('data-ingredient-code');
|
||||
const gramsPerCheop = parseFloat($(this).find('.grams-per-cheop').val());
|
||||
|
||||
if (ingredientCode && gramsPerCheop > 0) {
|
||||
currentIngredients[ingredientCode] = gramsPerCheop;
|
||||
}
|
||||
});
|
||||
|
||||
// 변경사항 감지
|
||||
const customDetails = [];
|
||||
let isCustom = false;
|
||||
|
||||
// 추가된 약재 확인
|
||||
for (const code in currentIngredients) {
|
||||
if (!originalFormulaIngredients[code]) {
|
||||
const herbName = $(`tr[data-ingredient-code="${code}"] .herb-select-compound option:selected`).data('herb-name') || code;
|
||||
customDetails.push(`${herbName} ${currentIngredients[code]}g 추가`);
|
||||
isCustom = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 삭제된 약재 확인
|
||||
for (const code in originalFormulaIngredients) {
|
||||
if (!currentIngredients[code]) {
|
||||
customDetails.push(`${originalFormulaIngredients[code].herb_name} 제거`);
|
||||
isCustom = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 용량 변경된 약재 확인
|
||||
for (const code in currentIngredients) {
|
||||
if (originalFormulaIngredients[code]) {
|
||||
const originalGrams = originalFormulaIngredients[code].grams_per_cheop;
|
||||
const currentGrams = currentIngredients[code];
|
||||
|
||||
if (Math.abs(originalGrams - currentGrams) > 0.01) {
|
||||
const herbName = originalFormulaIngredients[code].herb_name;
|
||||
customDetails.push(`${herbName} ${originalGrams}g→${currentGrams}g`);
|
||||
isCustom = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 커스텀 뱃지 표시/숨기기
|
||||
$('#customPrescriptionBadge').remove();
|
||||
|
||||
if (isCustom) {
|
||||
const badgeHtml = `
|
||||
<div id="customPrescriptionBadge" class="alert alert-warning mt-2">
|
||||
<span class="badge bg-warning">가감방</span>
|
||||
<small class="ms-2">${customDetails.join(' | ')}</small>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 처방 선택 영역 아래에 추가
|
||||
$('#compoundFormula').closest('.col-md-6').append(badgeHtml);
|
||||
}
|
||||
}
|
||||
|
||||
// 재고 확인
|
||||
@@ -861,6 +961,7 @@ $(document).ready(function() {
|
||||
newRow.find('.grams-per-cheop').on('input', updateIngredientTotals);
|
||||
newRow.find('.remove-compound-ingredient').on('click', function() {
|
||||
$(this).closest('tr').remove();
|
||||
updateIngredientTotals(); // 총용량 재계산 및 커스텀 감지
|
||||
});
|
||||
newRow.find('.herb-select-compound').on('change', function() {
|
||||
const herbId = $(this).val();
|
||||
|
||||
Reference in New Issue
Block a user