From 8a18b530bd434bdbd117a09331de0c936e7d1651 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B2=AD=EC=B6=98=EC=95=BD=EA=B5=AD?= Date: Wed, 18 Mar 2026 23:45:32 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20product=5Fid=20=EC=B6=A9=EB=8F=8C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0=20(=EC=9E=84=EC=9D=98=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=205=EC=A2=85=20=E2=86=92=20MASTER-017~021)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- check_json.py | 16 ++++++++++ data/master/apoquel.json | 45 ++++++++++++++++---------- data/master/bravecto.json | 58 ++++++++++++++++++++++++---------- data/master/gabapentin.json | 15 ++++----- data/master/metronidazole.json | 23 +++++++------- data/master/simparica.json | 58 ++++++++++++++++++++++++---------- fix_ids.py | 29 +++++++++++++++++ test_v2_all.py | 50 +++++++++++++++++++++++++++++ 8 files changed, 224 insertions(+), 70 deletions(-) create mode 100644 check_json.py create mode 100644 fix_ids.py create mode 100644 test_v2_all.py diff --git a/check_json.py b/check_json.py new file mode 100644 index 0000000..c21ca3b --- /dev/null +++ b/check_json.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +import json +import os + +master_dir = r'C:\Users\청춘약국\source\animal-medication-api\data\master' + +for filename in sorted(os.listdir(master_dir)): + if filename.endswith('.json'): + filepath = os.path.join(master_dir, filename) + try: + with open(filepath, 'r', encoding='utf-8') as f: + data = json.load(f) + pid = data.get('product_id', 'NO_ID') + print(f'OK: {filename} ({pid})') + except Exception as e: + print(f'ERROR: {filename} - {e}') diff --git a/data/master/apoquel.json b/data/master/apoquel.json index f649c7b..f09346d 100644 --- a/data/master/apoquel.json +++ b/data/master/apoquel.json @@ -1,37 +1,52 @@ { - "product_id": "MASTER-011", + "product_id": "MASTER-017", "apc_code": "0519-APOQUEL", "name": "아포퀠", "english_name": "Apoquel (Oclacitinib)", "manufacturer": "조에티스 (Zoetis)", "category": "immunomodulator", "category_display": "아토피/알러지 치료제", - "target_animal": ["개"], + "target_animal": [ + "개" + ], "administration": "경구 (정제)", - "indication": "개 아토피성 피부염, 알러지성 가려움증 완화", - "mechanism": { "drug_class": "JAK 억제제 (Janus Kinase Inhibitor)", "action": "JAK1/JAK3 억제 → 가려움/염증 사이토카인 차단", "onset": "4시간 내 가려움 감소 시작" }, - "dosage": { "standard": "0.4~0.6mg/kg 1일 2회", "maintenance": "0.4~0.6mg/kg 1일 1회", "note": "처음 14일간 1일 2회 → 이후 1일 1회 유지" }, - "dosage_table": [ - {"weight": "4.5~6kg", "tablets": "3.6mg 1정"}, - {"weight": "6.1~9kg", "tablets": "5.4mg 1정"}, - {"weight": "9.1~13.5kg", "tablets": "3.6mg + 5.4mg"}, - {"weight": "13.6~20kg", "tablets": "16mg 1정"}, - {"weight": "20.1~27kg", "tablets": "16mg + 5.4mg"}, - {"weight": "27.1~40kg", "tablets": "16mg 2정"} + { + "weight": "4.5~6kg", + "tablets": "3.6mg 1정" + }, + { + "weight": "6.1~9kg", + "tablets": "5.4mg 1정" + }, + { + "weight": "9.1~13.5kg", + "tablets": "3.6mg + 5.4mg" + }, + { + "weight": "13.6~20kg", + "tablets": "16mg 1정" + }, + { + "weight": "20.1~27kg", + "tablets": "16mg + 5.4mg" + }, + { + "weight": "27.1~40kg", + "tablets": "16mg 2정" + } ], - "warnings": [ "⚠️ 12개월 미만 강아지 금지", "⚠️ 중증 감염 시 사용 주의", @@ -39,12 +54,10 @@ "⚠️ 면역 억제 → 종양 발생 모니터링", "⚠️ 번식용 개 안전성 미확립" ], - "contraindications": [ "12개월 미만", "중증 감염", "면역결핍" ], - "storage": "실온 보관" -} +} \ No newline at end of file diff --git a/data/master/bravecto.json b/data/master/bravecto.json index 240c435..76afe81 100644 --- a/data/master/bravecto.json +++ b/data/master/bravecto.json @@ -1,49 +1,73 @@ { - "product_id": "MASTER-012", + "product_id": "MASTER-018", "apc_code": "0519-BRAVECTO", "name": "브라벡토", "english_name": "Bravecto (Fluralaner)", "manufacturer": "MSD동물약품", "category": "antiparasitic", "category_display": "장기 지속 구충제", - "target_animal": ["개", "고양이"], + "target_animal": [ + "개", + "고양이" + ], "administration": "경구 (츄어블) / 스팟온", - "indication": "벼룩·진드기 12주 지속 구제", - "coverage_summary": { - "covered": ["벼룩", "진드기", "모낭충", "개선충"], - "not_covered": ["심장사상충", "내부기생충"], + "covered": [ + "벼룩", + "진드기", + "모낭충", + "개선충" + ], + "not_covered": [ + "심장사상충", + "내부기생충" + ], "gap_solution": "심장사상충: 셀라리드/하트가드 / 내부기생충: 안텔민" }, - "dosing": { "interval": "12주(3개월) 1회", "interval_reason": "Fluralaner 반감기 12~15일, 12주간 유효 혈중 농도 유지", "minimum_age": "8주(개) / 11주(고양이)", "minimum_weight": "2kg 이상" }, - "weight_products": [ - {"size": "XS", "weight_range": "2~4.5kg", "dose": "112.5mg"}, - {"size": "S", "weight_range": "4.5~10kg", "dose": "250mg"}, - {"size": "M", "weight_range": "10~20kg", "dose": "500mg"}, - {"size": "L", "weight_range": "20~40kg", "dose": "1000mg"}, - {"size": "XL", "weight_range": "40~56kg", "dose": "1400mg"} + { + "size": "XS", + "weight_range": "2~4.5kg", + "dose": "112.5mg" + }, + { + "size": "S", + "weight_range": "4.5~10kg", + "dose": "250mg" + }, + { + "size": "M", + "weight_range": "10~20kg", + "dose": "500mg" + }, + { + "size": "L", + "weight_range": "20~40kg", + "dose": "1000mg" + }, + { + "size": "XL", + "weight_range": "40~56kg", + "dose": "1400mg" + } ], - "warnings": [ "⚠️ 경련/간질 이력 주의 (이소자졸린 계열)", "⚠️ 8주/2kg 미만 금지", "⚠️ 심장사상충 별도 예방 필수", "⚠️ MDR1 유전자 변이 품종 주의" ], - "clinical_notes": [ "3개월 1회 투여 → 보호자 편의성 높음", "넥스가드 대비: 심장사상충 미커버, 주기 길음", "음식과 함께 투여 시 흡수율 증가" ], - "storage": "실온 보관" -} +} \ No newline at end of file diff --git a/data/master/gabapentin.json b/data/master/gabapentin.json index cb9075b..6ef1517 100644 --- a/data/master/gabapentin.json +++ b/data/master/gabapentin.json @@ -1,41 +1,38 @@ { - "product_id": "MASTER-015", + "product_id": "MASTER-020", "apc_code": "0519-GABAPENTIN", "name": "가바펜틴", "english_name": "Gabapentin", "manufacturer": "일반의약품", "category": "analgesic", "category_display": "신경병증성 진통제", - "target_animal": ["개", "고양이"], + "target_animal": [ + "개", + "고양이" + ], "administration": "경구 (캡슐/정제)", - "indication": "신경병증성 통증, 만성 통증, 수술 전 진정, 불안 완화", - "mechanism": { "drug_class": "GABA 유사체", "action": "칼슘 채널 α2δ 서브유닛 결합 → 신경 흥분 억제", "feature": "진통 + 항경련 + 진정 작용" }, - "dosage": { "dog_pain": "5~10mg/kg 1일 2~3회", "cat_pain": "5~10mg/kg 1일 1~2회", "cat_anxiety": "50~100mg/cat 내원 2~3시간 전", "note": "용량은 효과에 따라 점진적 증량" }, - "warnings": [ "⚠️ 신장 기능 저하 시 감량 필요", "⚠️ 급격한 중단 금지 (점진적 감량)", "⚠️ 졸음/운동실조 발생 가능", "⚠️ 액상 제제 중 자일리톨 함유 주의 (개)" ], - "clinical_notes": [ "NSAIDs와 병용 시 시너지 (multimodal analgesia)", "고양이 내원 스트레스 감소에 효과적", "만성 관절염 장기 통증 관리에 유용" ], - "storage": "실온 보관" -} +} \ No newline at end of file diff --git a/data/master/metronidazole.json b/data/master/metronidazole.json index 757335f..7c98432 100644 --- a/data/master/metronidazole.json +++ b/data/master/metronidazole.json @@ -1,43 +1,44 @@ { - "product_id": "MASTER-016", + "product_id": "MASTER-021", "apc_code": "0519-METRONIDAZOLE", "name": "메트로니다졸", "english_name": "Metronidazole", "manufacturer": "일반의약품", "category": "antibiotic", "category_display": "항생제/항원충제", - "target_animal": ["개", "고양이"], + "target_animal": [ + "개", + "고양이" + ], "administration": "경구 (정제)", - "indication": "지아르디아, 클로스트리디움, 염증성 장질환, 혐기성 감염", - "mechanism": { "drug_class": "니트로이미다졸계", "action": "DNA 합성 억제 → 혐기성균/원충 사멸", "spectrum": "혐기성균, 지아르디아, 트리코모나스" }, - "dosage": { "standard": "10~25mg/kg 1일 2회", "giardia": "25mg/kg 1일 2회, 5~7일", "ibd": "10~15mg/kg 1일 2회", "duration": "5~14일 (적응증에 따라)" }, - "warnings": [ "⚠️ 장기 투여 시 신경독성 주의 (운동실조, 경련)", "⚠️ 임신 중 금기 (기형 유발 가능성)", "⚠️ 쓴맛 → 고양이 투약 어려움 (캡슐 권장)", "⚠️ 음식과 함께 투여 (위장 자극 감소)" ], - - "side_effects": ["식욕부진", "구토", "설사", "신경독성(고용량/장기)"], - + "side_effects": [ + "식욕부진", + "구토", + "설사", + "신경독성(고용량/장기)" + ], "clinical_notes": [ "지아르디아: 펜벤다졸과 병용 시 효과 증가", "IBD: 면역조절 효과로 장기 사용 가능", "투약 어려운 고양이: 트랜스더말 제제 고려" ], - "storage": "차광 보관" -} +} \ No newline at end of file diff --git a/data/master/simparica.json b/data/master/simparica.json index 59c1f6d..8987a02 100644 --- a/data/master/simparica.json +++ b/data/master/simparica.json @@ -1,48 +1,72 @@ { - "product_id": "MASTER-013", + "product_id": "MASTER-019", "apc_code": "0519-SIMPARICA", "name": "심파리카 트리오", "english_name": "Simparica Trio (Sarolaner+Moxidectin+Pyrantel)", "manufacturer": "조에티스 (Zoetis)", "category": "antiparasitic", "category_display": "올인원 구충제", - "target_animal": ["개"], + "target_animal": [ + "개" + ], "administration": "경구 (츄어블)", - "indication": "벼룩·진드기 + 심장사상충 예방 + 회충/구충 구제", - "coverage_summary": { - "covered": ["벼룩", "진드기", "심장사상충", "회충", "구충"], - "not_covered": ["편충", "조충"], + "covered": [ + "벼룩", + "진드기", + "심장사상충", + "회충", + "구충" + ], + "not_covered": [ + "편충", + "조충" + ], "gap_solution": "편충: 넥스가드 스펙트라 / 조충: 안텔민 추가" }, - "dosing": { "interval": "매월 1회", "interval_reason": "심장사상충 예방 주기 + 벼룩 라이프사이클", "minimum_age": "8주 이상", "minimum_weight": "1.25kg 이상" }, - "weight_products": [ - {"size": "XS", "weight_range": "1.25~2.5kg", "dose": "3/0.06/12.5mg"}, - {"size": "S", "weight_range": "2.6~5kg", "dose": "6/0.12/25mg"}, - {"size": "M", "weight_range": "5.1~10kg", "dose": "12/0.25/50mg"}, - {"size": "L", "weight_range": "10.1~20kg", "dose": "24/0.5/100mg"}, - {"size": "XL", "weight_range": "20.1~40kg", "dose": "48/1/200mg"} + { + "size": "XS", + "weight_range": "1.25~2.5kg", + "dose": "3/0.06/12.5mg" + }, + { + "size": "S", + "weight_range": "2.6~5kg", + "dose": "6/0.12/25mg" + }, + { + "size": "M", + "weight_range": "5.1~10kg", + "dose": "12/0.25/50mg" + }, + { + "size": "L", + "weight_range": "10.1~20kg", + "dose": "24/0.5/100mg" + }, + { + "size": "XL", + "weight_range": "20.1~40kg", + "dose": "48/1/200mg" + } ], - "warnings": [ "⚠️ 경련/간질 이력 주의 (이소자졸린 계열)", "⚠️ 8주/1.25kg 미만 금지", "⚠️ 투약 전 심장사상충 검사 필수", "⚠️ MDR1 유전자 변이 품종 주의" ], - "comparison": { "vs_nexgard_spectra": "편충 미커버, 최소 체중 더 낮음 (1.25kg)", "vs_bravecto": "심장사상충 커버, 월 1회 투여" }, - "storage": "실온 보관" -} +} \ No newline at end of file diff --git a/fix_ids.py b/fix_ids.py new file mode 100644 index 0000000..223777a --- /dev/null +++ b/fix_ids.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +import json +import os + +master_dir = r'C:\Users\청춘약국\source\animal-medication-api\data\master' + +# 충돌 ID 수정 매핑 +id_map = { + 'apoquel.json': 'MASTER-017', + 'bravecto.json': 'MASTER-018', + 'simparica.json': 'MASTER-019', + 'gabapentin.json': 'MASTER-020', + 'metronidazole.json': 'MASTER-021' +} + +for filename, new_id in id_map.items(): + filepath = os.path.join(master_dir, filename) + with open(filepath, 'r', encoding='utf-8') as f: + data = json.load(f) + + old_id = data['product_id'] + data['product_id'] = new_id + + with open(filepath, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + + print(f'{filename}: {old_id} -> {new_id}') + +print('Done') diff --git a/test_v2_all.py b/test_v2_all.py new file mode 100644 index 0000000..6fda657 --- /dev/null +++ b/test_v2_all.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +""" +v2 API 테스트 - 전체 약품 +""" + +import os +import sys +sys.path.insert(0, os.path.dirname(__file__)) + +from animal_med import AnimalMedRendererV2 + + +def main(): + renderer = AnimalMedRendererV2() + + # 전체 마스터 약품 + drugs = renderer.list_drugs() + print(f"총 {len(drugs)}개 약품 → {(len(drugs) + 3) // 4} 페이지") + + # 전체 ID 수집 + all_ids = [d['product_id'] for d in drugs] + + # 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, f'v2_all_{len(drugs)}drugs.pdf') + + result = renderer.render_to_pdf( + product_ids=all_ids, + output_path=pdf_path, + patient_name="김보호자", + pet_name="뽀삐", + pet_species="푸들", + pet_age="3세" + ) + + if result['success']: + import fitz + doc = fitz.open(pdf_path) + size = os.path.getsize(pdf_path) + print(f"✅ PDF 생성: {len(doc)} 페이지, {size/1024:.1f}KB") + print(f"📄 {pdf_path}") + doc.close() + else: + print(f"❌ 실패: {result.get('error')}") + + +if __name__ == "__main__": + main()