feat: 5개 마스터 JSON 추가 (총 9개) + 외용제 레이아웃
This commit is contained in:
@@ -129,13 +129,8 @@ class AnimalMedRendererV2:
|
||||
return { width: rect.width, height: rect.height };
|
||||
}''')
|
||||
|
||||
# A4에 맞는 scale 계산
|
||||
content_width_pt = rect['width'] * 0.75
|
||||
content_height_pt = rect['height'] * 0.75
|
||||
|
||||
scale_x = 595 / content_width_pt if content_width_pt > 0 else 1
|
||||
scale_y = 842 / content_height_pt if content_height_pt > 0 else 1
|
||||
scale = min(scale_x, scale_y, 1.0)
|
||||
# scale 고정 (자연스러운 페이지 분할)
|
||||
scale = 1.0
|
||||
|
||||
await page.pdf(
|
||||
path=output_path,
|
||||
|
||||
39
data/master/chlorhexidine_shampoo.json
Normal file
39
data/master/chlorhexidine_shampoo.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"product_id": "MASTER-009",
|
||||
"apc_code": "0519-CHLORHEX-SHAMPOO",
|
||||
"name": "클로르헥시딘 샴푸",
|
||||
"english_name": "Chlorhexidine Shampoo 2%",
|
||||
"manufacturer": "비르박",
|
||||
"category": "topical",
|
||||
"category_display": "피부외용제 (샴푸)",
|
||||
"target_animal": ["개", "고양이"],
|
||||
"administration": "외용 (샴푸)",
|
||||
|
||||
"indication": "세균성/진균성 피부염, 농피증, 피부 감염 예방",
|
||||
|
||||
"mechanism": {
|
||||
"drug_class": "비구아나이드계 소독제",
|
||||
"action": "세균 세포막 파괴 → 살균 작용",
|
||||
"spectrum": "그람양성균, 그람음성균, 효모균"
|
||||
},
|
||||
|
||||
"dosage": {
|
||||
"frequency": "주 2~3회",
|
||||
"contact_time": "5~10분간 방치 후 헹굼",
|
||||
"duration": "증상 호전 시까지 (보통 2~4주)"
|
||||
},
|
||||
|
||||
"warnings": [
|
||||
"⚠️ 눈, 귀, 점막 접촉 피할 것",
|
||||
"⚠️ 사용 후 완전히 헹굴 것",
|
||||
"⚠️ 깊은 상처에는 사용 금지"
|
||||
],
|
||||
|
||||
"clinical_notes": [
|
||||
"경구 항생제와 병용 시 효과 증가",
|
||||
"거품을 충분히 내어 피부에 접촉시키는 것이 중요",
|
||||
"피부 건조 시 보습제 병용 권장"
|
||||
],
|
||||
|
||||
"storage": "실온 보관, 직사광선 피할 것"
|
||||
}
|
||||
48
data/master/fronilspot.json
Normal file
48
data/master/fronilspot.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"product_id": "MASTER-006",
|
||||
"apc_code": "0519-FRONILSPOT",
|
||||
"name": "프로닐스팟",
|
||||
"english_name": "Fronil Spot (Fipronil)",
|
||||
"manufacturer": "한국동물약품",
|
||||
"category": "antiparasitic",
|
||||
"category_display": "외부구충제 (스팟온)",
|
||||
"target_animal": ["개", "고양이"],
|
||||
"administration": "경피 도포 (스팟온)",
|
||||
|
||||
"indication": "벼룩, 진드기 구제",
|
||||
|
||||
"coverage": {
|
||||
"external": {
|
||||
"fleas": {"covered": true, "note": "4~8시간 내 사멸"},
|
||||
"ticks": {"covered": true, "note": "접촉 사멸"}
|
||||
},
|
||||
"heartworm": {"covered": false},
|
||||
"intestinal": {
|
||||
"roundworm": {"covered": false},
|
||||
"hookworm": {"covered": false},
|
||||
"whipworm": {"covered": false},
|
||||
"tapeworm": {"covered": false}
|
||||
}
|
||||
},
|
||||
|
||||
"coverage_summary": {
|
||||
"covered": ["벼룩", "진드기"],
|
||||
"not_covered": ["심장사상충", "내부기생충"],
|
||||
"gap_solution": "심장사상충: 하트세이버 / 내부기생충: 안텔민 추가"
|
||||
},
|
||||
|
||||
"dosing": {
|
||||
"interval": "매월 1회",
|
||||
"interval_reason": "효능 지속 4주",
|
||||
"minimum_age": "8주 이상",
|
||||
"minimum_weight": "제한 없음"
|
||||
},
|
||||
|
||||
"warnings": [
|
||||
"⚠️ 도포 후 2일간 목욕/수영 금지",
|
||||
"⚠️ 토끼에게는 독성 (사용 금지)",
|
||||
"⚠️ 피부 상처 부위 도포 금지"
|
||||
],
|
||||
|
||||
"storage": "실온 보관, 직사광선 피할 것"
|
||||
}
|
||||
51
data/master/heartsaver.json
Normal file
51
data/master/heartsaver.json
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"product_id": "MASTER-005",
|
||||
"apc_code": "0519-HEARTSAVER",
|
||||
"name": "하트세이버 츄어블",
|
||||
"english_name": "Heartsaver (Ivermectin + Pyrantel)",
|
||||
"manufacturer": "중앙바이오텍",
|
||||
"category": "antiparasitic",
|
||||
"category_display": "심장사상충 예방",
|
||||
"target_animal": ["개"],
|
||||
"administration": "경구 (츄어블)",
|
||||
|
||||
"indication": "심장사상충 예방 + 회충/구충 구제",
|
||||
|
||||
"coverage": {
|
||||
"external": {
|
||||
"fleas": {"covered": false, "note": ""},
|
||||
"ticks": {"covered": false, "note": ""}
|
||||
},
|
||||
"heartworm": {
|
||||
"covered": true,
|
||||
"note": "L3/L4 유충 구제"
|
||||
},
|
||||
"intestinal": {
|
||||
"roundworm": {"covered": true, "note": "회충"},
|
||||
"hookworm": {"covered": true, "note": "구충"},
|
||||
"whipworm": {"covered": false, "note": ""},
|
||||
"tapeworm": {"covered": false, "note": ""}
|
||||
}
|
||||
},
|
||||
|
||||
"coverage_summary": {
|
||||
"covered": ["심장사상충", "회충", "구충"],
|
||||
"not_covered": ["벼룩", "진드기", "편충", "조충"],
|
||||
"gap_solution": "외부구충: 프로닐스팟 / 편충·조충: 안텔민 추가"
|
||||
},
|
||||
|
||||
"dosing": {
|
||||
"interval": "매월 1회",
|
||||
"interval_reason": "심장사상충 윈도우 30일",
|
||||
"minimum_age": "6주 이상",
|
||||
"minimum_weight": "제한 없음"
|
||||
},
|
||||
|
||||
"warnings": [
|
||||
"⚠️ 콜리 품종: MDR1 유전자 확인 필요",
|
||||
"⚠️ 투약 전 심장사상충 검사 필수",
|
||||
"⚠️ 감염견에 투약 시 쇼크 위험"
|
||||
],
|
||||
|
||||
"storage": "실온 보관"
|
||||
}
|
||||
39
data/master/oridermyl.json
Normal file
39
data/master/oridermyl.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"product_id": "MASTER-007",
|
||||
"apc_code": "0519-ORIDERMYL",
|
||||
"name": "오리더밀",
|
||||
"english_name": "Oridermyl (Nystatin+Neomycin+Triamcinolone)",
|
||||
"manufacturer": "TVM",
|
||||
"category": "otic",
|
||||
"category_display": "귀염증 치료제",
|
||||
"target_animal": ["개", "고양이"],
|
||||
"administration": "점이 (귀에 투약)",
|
||||
|
||||
"indication": "외이염, 귀진드기 감염, 세균성/진균성 귀감염",
|
||||
|
||||
"mechanism": {
|
||||
"nystatin": "항진균 (칸디다, 말라세지아)",
|
||||
"neomycin": "항균 (그람음성균)",
|
||||
"triamcinolone": "항염증 (가려움, 부종 완화)",
|
||||
"permethrin": "귀진드기 구제"
|
||||
},
|
||||
|
||||
"dosage": {
|
||||
"standard": "1일 1~2회",
|
||||
"amount": "귀당 5~10방울",
|
||||
"duration": "7~14일"
|
||||
},
|
||||
|
||||
"warnings": [
|
||||
"⚠️ 고막 천공 시 사용 금지",
|
||||
"⚠️ 투약 전 귀 세정 권장",
|
||||
"⚠️ 장기 사용 시 내성균 주의"
|
||||
],
|
||||
|
||||
"contraindications": [
|
||||
"고막 천공/손상",
|
||||
"아미노글리코사이드 과민증"
|
||||
],
|
||||
|
||||
"storage": "실온 보관"
|
||||
}
|
||||
38
data/master/terbiderm.json
Normal file
38
data/master/terbiderm.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"product_id": "MASTER-008",
|
||||
"apc_code": "0519-TERBIDERM",
|
||||
"name": "터비덤 스프레이",
|
||||
"english_name": "Terbiderm (Terbinafine)",
|
||||
"manufacturer": "동방동물약품",
|
||||
"category": "antifungal",
|
||||
"category_display": "항진균제 (피부)",
|
||||
"target_animal": ["개", "고양이"],
|
||||
"administration": "외용 (스프레이)",
|
||||
|
||||
"indication": "피부사상균증 (백선), 말라세지아 피부염",
|
||||
|
||||
"mechanism": {
|
||||
"drug_class": "알릴아민계 항진균제",
|
||||
"action": "스쿠알렌 에폭시다제 억제 → 진균 세포막 합성 차단"
|
||||
},
|
||||
|
||||
"dosage": {
|
||||
"frequency": "1일 1~2회",
|
||||
"duration": "2~4주 (완치 후 1주 추가)",
|
||||
"application": "병변 및 주변 2cm까지 도포"
|
||||
},
|
||||
|
||||
"warnings": [
|
||||
"⚠️ 눈, 점막 접촉 피할 것",
|
||||
"⚠️ 핥지 못하게 엘리자베스 칼라 권장",
|
||||
"⚠️ 경구 항진균제 병용 시 효과 증가"
|
||||
],
|
||||
|
||||
"clinical_notes": [
|
||||
"피부사상균 배양 검사 권장 (치료 전)",
|
||||
"환경 소독 병행 필수 (재감염 방지)",
|
||||
"장모종은 병변 주변 제모 권장"
|
||||
],
|
||||
|
||||
"storage": "실온 보관, 화기 주의"
|
||||
}
|
||||
@@ -544,6 +544,31 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% elif drug.category in ['otic', 'antifungal', 'topical'] %}
|
||||
<!-- 외용제 레이아웃 -->
|
||||
<div class="dosing-section">
|
||||
<div class="dosing-title">📋 적응증</div>
|
||||
<div class="dosing-main" style="font-size:7pt;">{{ drug.indication }}</div>
|
||||
</div>
|
||||
|
||||
<div class="dosage-table-section">
|
||||
<div class="coverage-title" style="font-size:7pt;">💊 용법</div>
|
||||
<div style="font-size:6pt; background:#E8F5E9; padding:1.5mm; border-radius:1mm;">
|
||||
{% if drug.dosage.frequency %}
|
||||
<div><b>빈도:</b> {{ drug.dosage.frequency }}</div>
|
||||
{% endif %}
|
||||
{% if drug.dosage.duration %}
|
||||
<div><b>기간:</b> {{ drug.dosage.duration }}</div>
|
||||
{% endif %}
|
||||
{% if drug.dosage.contact_time %}
|
||||
<div><b>접촉시간:</b> {{ drug.dosage.contact_time }}</div>
|
||||
{% endif %}
|
||||
{% if drug.dosage.amount %}
|
||||
<div><b>용량:</b> {{ drug.dosage.amount }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %}
|
||||
<!-- 기본 레이아웃 -->
|
||||
<div class="dosing-section">
|
||||
|
||||
69
test_v2_8drugs.py
Normal file
69
test_v2_8drugs.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
v2 API 테스트 - 8개 약품 (2페이지)
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.dirname(__file__))
|
||||
|
||||
from animal_med import AnimalMedRendererV2
|
||||
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("v2 API 테스트 - 8개 약품 (2페이지)")
|
||||
print("=" * 60)
|
||||
|
||||
renderer = AnimalMedRendererV2()
|
||||
|
||||
# 마스터 약품 목록
|
||||
print("\n[1] 마스터 약품 목록:")
|
||||
for drug in renderer.list_drugs():
|
||||
print(f" {drug['product_id']} - {drug['name']}")
|
||||
|
||||
# 8개 약품 사용 (2x2 x 2페이지)
|
||||
test_ids = [
|
||||
"MASTER-001", "MASTER-002", "MASTER-003", "MASTER-004",
|
||||
"MASTER-005", "MASTER-006", "MASTER-007", "MASTER-008"
|
||||
]
|
||||
|
||||
print(f"\n[2] PDF 렌더링 ({len(test_ids)}개 약품)")
|
||||
|
||||
# PDF 생성
|
||||
output_dir = os.path.join(os.path.dirname(__file__), 'output')
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
pdf_path = os.path.join(output_dir, 'v2_8drugs_2pages.pdf')
|
||||
|
||||
print(f"\n[3] PDF 생성 중...")
|
||||
|
||||
result = renderer.render_to_pdf(
|
||||
product_ids=test_ids,
|
||||
output_path=pdf_path,
|
||||
patient_name="박보호자",
|
||||
pet_name="콩이",
|
||||
pet_species="말티즈",
|
||||
pet_age="5세"
|
||||
)
|
||||
|
||||
if result['success']:
|
||||
print(f" ✅ 성공!")
|
||||
print(f" 📄 PDF: {result['pdf_path']}")
|
||||
print(f" 약품: {len(result['drugs'])}개")
|
||||
|
||||
size = os.path.getsize(pdf_path)
|
||||
print(f" 크기: {size / 1024:.1f} KB")
|
||||
|
||||
import fitz
|
||||
doc = fitz.open(pdf_path)
|
||||
print(f" 페이지 수: {len(doc)}")
|
||||
doc.close()
|
||||
else:
|
||||
print(f" ❌ 실패: {result.get('error')}")
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user