feat: PMR 효능효과(add_info) 추가
- CD_MC.PRINT_TYPE JOIN으로 효능 조회 - 약품 테이블에 효능 표시 - 라벨 미리보기에 효능 포함
This commit is contained in:
parent
c21aa956da
commit
fc2db78816
@ -176,7 +176,7 @@ def get_prescription_detail(prescription_id):
|
|||||||
conn.close()
|
conn.close()
|
||||||
return jsonify({'success': False, 'error': '처방전을 찾을 수 없습니다'}), 404
|
return jsonify({'success': False, 'error': '처방전을 찾을 수 없습니다'}), 404
|
||||||
|
|
||||||
# 처방 약품 목록 (PS_sub_pharm + PM_DRUG.CD_GOODS JOIN)
|
# 처방 약품 목록 (PS_sub_pharm + CD_GOODS + CD_MC JOIN)
|
||||||
medications = []
|
medications = []
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT
|
SELECT
|
||||||
@ -187,17 +187,24 @@ def get_prescription_detail(prescription_id):
|
|||||||
s.PS_Type,
|
s.PS_Type,
|
||||||
s.INV_QUAN,
|
s.INV_QUAN,
|
||||||
g.GoodsName,
|
g.GoodsName,
|
||||||
g.SUNG_CODE
|
g.SUNG_CODE,
|
||||||
|
m.PRINT_TYPE,
|
||||||
|
m.SIM_EFFECT
|
||||||
FROM PS_sub_pharm s
|
FROM PS_sub_pharm s
|
||||||
LEFT JOIN PM_DRUG.dbo.CD_GOODS g ON s.DrugCode = g.DrugCode
|
LEFT JOIN PM_DRUG.dbo.CD_GOODS g ON s.DrugCode = g.DrugCode
|
||||||
|
LEFT JOIN PM_DRUG.dbo.CD_MC m ON s.DrugCode = m.DRUGCODE
|
||||||
WHERE s.PreSerial = ?
|
WHERE s.PreSerial = ?
|
||||||
ORDER BY s.SUB_SERIAL
|
ORDER BY s.SUB_SERIAL
|
||||||
""", (prescription_id,))
|
""", (prescription_id,))
|
||||||
|
|
||||||
for row in cursor.fetchall():
|
for row in cursor.fetchall():
|
||||||
|
# 효능: PRINT_TYPE > SIM_EFFECT > 없음
|
||||||
|
add_info = row.PRINT_TYPE or row.SIM_EFFECT or ''
|
||||||
|
|
||||||
medications.append({
|
medications.append({
|
||||||
'medication_code': row.DrugCode or '',
|
'medication_code': row.DrugCode or '',
|
||||||
'med_name': row.GoodsName or row.DrugCode or '',
|
'med_name': row.GoodsName or row.DrugCode or '',
|
||||||
|
'add_info': add_info,
|
||||||
'dosage': float(row.QUAN) if row.QUAN else 0,
|
'dosage': float(row.QUAN) if row.QUAN else 0,
|
||||||
'frequency': row.QUAN_TIME or 0,
|
'frequency': row.QUAN_TIME or 0,
|
||||||
'duration': row.Days or 0,
|
'duration': row.Days or 0,
|
||||||
@ -346,6 +353,7 @@ def preview_label():
|
|||||||
|
|
||||||
patient_name = data.get('patient_name', '')
|
patient_name = data.get('patient_name', '')
|
||||||
med_name = data.get('med_name', '')
|
med_name = data.get('med_name', '')
|
||||||
|
add_info = data.get('add_info', '')
|
||||||
dosage = float(data.get('dosage', 0))
|
dosage = float(data.get('dosage', 0))
|
||||||
frequency = int(data.get('frequency', 0))
|
frequency = int(data.get('frequency', 0))
|
||||||
duration = int(data.get('duration', 0))
|
duration = int(data.get('duration', 0))
|
||||||
@ -355,6 +363,7 @@ def preview_label():
|
|||||||
image = create_label_image(
|
image = create_label_image(
|
||||||
patient_name=patient_name,
|
patient_name=patient_name,
|
||||||
med_name=med_name,
|
med_name=med_name,
|
||||||
|
add_info=add_info,
|
||||||
dosage=dosage,
|
dosage=dosage,
|
||||||
frequency=frequency,
|
frequency=frequency,
|
||||||
duration=duration,
|
duration=duration,
|
||||||
@ -377,7 +386,7 @@ def preview_label():
|
|||||||
return jsonify({'success': False, 'error': str(e)}), 500
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
|
|
||||||
|
|
||||||
def create_label_image(patient_name, med_name, dosage, frequency, duration, unit='정'):
|
def create_label_image(patient_name, med_name, add_info='', dosage=0, frequency=0, duration=0, unit='정'):
|
||||||
"""
|
"""
|
||||||
라벨 이미지 생성 (29mm 용지 기준)
|
라벨 이미지 생성 (29mm 용지 기준)
|
||||||
"""
|
"""
|
||||||
@ -442,19 +451,17 @@ def create_label_image(patient_name, med_name, dosage, frequency, duration, unit
|
|||||||
# 괄호 앞에서 분리
|
# 괄호 앞에서 분리
|
||||||
if '(' in med_name:
|
if '(' in med_name:
|
||||||
main_name = med_name.split('(')[0].strip()
|
main_name = med_name.split('(')[0].strip()
|
||||||
sub_info = '(' + med_name.split('(', 1)[1] if '(' in med_name else ''
|
|
||||||
else:
|
else:
|
||||||
main_name = med_name
|
main_name = med_name
|
||||||
sub_info = ''
|
|
||||||
|
|
||||||
# 약품명 줄바꿈
|
# 약품명 줄바꿈
|
||||||
name_lines = wrap_text(main_name, drug_font, label_width - 30)
|
name_lines = wrap_text(main_name, drug_font, label_width - 30)
|
||||||
for line in name_lines:
|
for line in name_lines:
|
||||||
y = draw_centered(line, y, drug_font)
|
y = draw_centered(line, y, drug_font)
|
||||||
|
|
||||||
# 부가정보
|
# 효능효과 (add_info)
|
||||||
if sub_info:
|
if add_info:
|
||||||
y = draw_centered(sub_info, y, small_font, fill="gray")
|
y = draw_centered(f"({add_info})", y, small_font, fill="gray")
|
||||||
|
|
||||||
y += 5
|
y += 5
|
||||||
|
|
||||||
|
|||||||
@ -316,6 +316,14 @@
|
|||||||
<script>
|
<script>
|
||||||
let currentPrescriptionId = null;
|
let currentPrescriptionId = null;
|
||||||
|
|
||||||
|
// HTML 이스케이프
|
||||||
|
function escapeHtml(text) {
|
||||||
|
if (!text) return '';
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.textContent = text;
|
||||||
|
return div.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
// 초기화
|
// 초기화
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const today = new Date().toISOString().split('T')[0];
|
const today = new Date().toISOString().split('T')[0];
|
||||||
@ -429,11 +437,12 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
${data.medications.map(m => `
|
${data.medications.map(m => `
|
||||||
<tr>
|
<tr data-add-info="${escapeHtml(m.add_info || '')}">
|
||||||
<td><input type="checkbox" class="med-check" data-code="${m.medication_code}" ${m.is_auto_print ? 'checked' : ''}></td>
|
<td><input type="checkbox" class="med-check" data-code="${m.medication_code}" ${m.is_auto_print ? 'checked' : ''}></td>
|
||||||
<td>
|
<td>
|
||||||
<div class="med-name">${m.med_name || m.medication_code}</div>
|
<div class="med-name">${m.med_name || m.medication_code}</div>
|
||||||
<div class="med-code">${m.medication_code}</div>
|
<div class="med-code">${m.medication_code}</div>
|
||||||
|
${m.add_info ? `<div style="font-size:0.75rem;color:#6b7280;">${escapeHtml(m.add_info)}</div>` : ''}
|
||||||
</td>
|
</td>
|
||||||
<td>${m.formulation ? `<span class="med-form">${m.formulation}</span>` : '-'}</td>
|
<td>${m.formulation ? `<span class="med-form">${m.formulation}</span>` : '-'}</td>
|
||||||
<td><span class="med-dosage">${m.dosage || '-'}</span></td>
|
<td><span class="med-dosage">${m.dosage || '-'}</span></td>
|
||||||
@ -481,8 +490,8 @@
|
|||||||
|
|
||||||
// 라벨 미리보기
|
// 라벨 미리보기
|
||||||
async function previewLabels() {
|
async function previewLabels() {
|
||||||
const rows = document.querySelectorAll('.med-check:checked');
|
const checkboxes = document.querySelectorAll('.med-check:checked');
|
||||||
if (rows.length === 0) {
|
if (checkboxes.length === 0) {
|
||||||
alert('미리보기할 약품을 선택하세요');
|
alert('미리보기할 약품을 선택하세요');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -496,12 +505,24 @@
|
|||||||
|
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
||||||
for (const checkbox of rows) {
|
for (const checkbox of checkboxes) {
|
||||||
const tr = checkbox.closest('tr');
|
const tr = checkbox.closest('tr');
|
||||||
const medName = tr.querySelector('.med-name')?.textContent || '';
|
const cells = tr.querySelectorAll('td');
|
||||||
const dosage = parseFloat(tr.cells[3]?.querySelector('.med-dosage')?.textContent) || 0;
|
|
||||||
const frequency = parseInt(tr.cells[4]?.textContent) || 0;
|
// 약품명: 두 번째 셀의 .med-name
|
||||||
const duration = parseInt(tr.cells[5]?.textContent) || 0;
|
const medName = tr.querySelector('.med-name')?.textContent?.trim() || '';
|
||||||
|
const addInfo = tr.dataset.addInfo || '';
|
||||||
|
// 용량: 네 번째 셀 (index 3)
|
||||||
|
const dosageText = cells[3]?.textContent?.replace(/[^0-9.]/g, '') || '0';
|
||||||
|
const dosage = parseFloat(dosageText) || 0;
|
||||||
|
// 횟수: 다섯 번째 셀 (index 4)
|
||||||
|
const freqText = cells[4]?.textContent?.replace(/[^0-9]/g, '') || '0';
|
||||||
|
const frequency = parseInt(freqText) || 0;
|
||||||
|
// 일수: 여섯 번째 셀 (index 5)
|
||||||
|
const durText = cells[5]?.textContent?.replace(/[^0-9]/g, '') || '0';
|
||||||
|
const duration = parseInt(durText) || 0;
|
||||||
|
|
||||||
|
console.log('Preview data:', { patientName, medName, addInfo, dosage, frequency, duration });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/pmr/api/label/preview', {
|
const res = await fetch('/pmr/api/label/preview', {
|
||||||
@ -510,6 +531,7 @@
|
|||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
patient_name: patientName,
|
patient_name: patientName,
|
||||||
med_name: medName,
|
med_name: medName,
|
||||||
|
add_info: addInfo,
|
||||||
dosage: dosage,
|
dosage: dosage,
|
||||||
frequency: frequency,
|
frequency: frequency,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
@ -517,12 +539,15 @@
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
console.log('Preview response:', data.success, data.error);
|
||||||
|
|
||||||
if (data.success) {
|
if (data.success && data.image) {
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.src = data.image;
|
img.src = data.image;
|
||||||
img.style.cssText = 'max-width:100%;border:1px solid #ddd;border-radius:8px;';
|
img.style.cssText = 'max-width:100%;border:1px solid #ddd;border-radius:8px;';
|
||||||
container.appendChild(img);
|
container.appendChild(img);
|
||||||
|
} else {
|
||||||
|
console.error('Preview failed:', data.error);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Preview error:', err);
|
console.error('Preview error:', err);
|
||||||
@ -530,7 +555,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (container.children.length === 0) {
|
if (container.children.length === 0) {
|
||||||
container.innerHTML = '<p style="color:#999;">미리보기 생성 실패</p>';
|
container.innerHTML = '<p style="color:#999;">미리보기 생성 실패 - 콘솔(F12) 확인</p>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user