"""PAAI ESC/POS 프린터 모듈""" import json from datetime import datetime from escpos.printer import Network from PIL import Image, ImageDraw, ImageFont # 프린터 설정 PRINTER_IP = "192.168.0.174" PRINTER_PORT = 9100 THERMAL_WIDTH = 576 def print_paai_result(pre_serial: str, patient_name: str, analysis: dict, kims_summary: dict) -> dict: """PAAI 분석 결과 인쇄""" try: # 이미지 생성 img = create_receipt_image(pre_serial, patient_name, analysis, kims_summary) # 프린터 연결 및 출력 p = Network(PRINTER_IP, port=PRINTER_PORT, timeout=15) p.image(img) p.text('\n\n\n') p.cut() return {'success': True, 'message': '인쇄 완료'} except Exception as e: return {'success': False, 'error': str(e)} def create_receipt_image(pre_serial: str, patient_name: str, analysis: dict, kims_summary: dict) -> Image: """영수증 이미지 생성""" # 폰트 try: font_title = ImageFont.truetype('malgun.ttf', 28) font_section = ImageFont.truetype('malgunbd.ttf', 20) font_normal = ImageFont.truetype('malgun.ttf', 18) font_small = ImageFont.truetype('malgun.ttf', 15) except: font_title = ImageFont.load_default() font_section = font_title font_normal = font_title font_small = font_title width = THERMAL_WIDTH padding = 20 y = padding # 이미지 생성 img = Image.new('RGB', (width, 1000), 'white') draw = ImageDraw.Draw(img) # 헤더 draw.text((width//2, y), 'PAAI 복약안내', font=font_title, fill='black', anchor='mt') y += 40 draw.line([(padding, y), (width-padding, y)], fill='black', width=1) y += 15 # 환자 정보 draw.text((padding, y), f'환자: {patient_name}', font=font_normal, fill='black') y += 25 draw.text((padding, y), f'처방번호: {pre_serial}', font=font_small, fill='black') y += 20 now_str = datetime.now().strftime("%Y-%m-%d %H:%M") draw.text((padding, y), f'출력: {now_str}', font=font_small, fill='black') y += 25 draw.line([(padding, y), (width-padding, y)], fill='black', width=1) y += 15 # 상호작용 interaction_count = kims_summary.get('interaction_count', 0) has_severe = kims_summary.get('has_severe', False) if has_severe: draw.text((padding, y), '[주의] 중증 상호작용 있음!', font=font_section, fill='black') elif interaction_count > 0: draw.text((padding, y), f'약물 상호작용: {interaction_count}건', font=font_normal, fill='black') else: draw.text((padding, y), '상호작용 없음', font=font_normal, fill='black') y += 30 # 처방 해석 insight = analysis.get('prescription_insight', '') if insight: draw.text((padding, y), '[처방 해석]', font=font_section, fill='black') y += 28 for line in wrap_text(insight, 40)[:3]: draw.text((padding, y), line, font=font_small, fill='black') y += 20 y += 10 # 주의사항 cautions = analysis.get('cautions', []) if cautions: draw.text((padding, y), '[복용 주의사항]', font=font_section, fill='black') y += 28 for i, c in enumerate(cautions[:3], 1): for line in wrap_text(f'{i}. {c}', 40)[:2]: draw.text((padding, y), line, font=font_small, fill='black') y += 20 y += 10 # 상담 포인트 counseling = analysis.get('counseling_points', []) if counseling: draw.text((padding, y), '[상담 포인트]', font=font_section, fill='black') y += 28 for i, c in enumerate(counseling[:2], 1): for line in wrap_text(f'{i}. {c}', 40)[:2]: draw.text((padding, y), line, font=font_small, fill='black') y += 20 y += 10 # 푸터 y += 10 draw.line([(padding, y), (width-padding, y)], fill='black', width=1) y += 15 draw.text((width//2, y), '양구청춘약국 PAAI', font=font_small, fill='black', anchor='mt') return img.crop((0, 0, width, y + 30)) def wrap_text(text: str, max_chars: int = 40) -> list: """텍스트 줄바꿈""" lines = [] words = text.split() current = "" for word in words: if len(current) + len(word) + 1 <= max_chars: current = current + " " + word if current else word else: if current: lines.append(current) current = word if current: lines.append(current) return lines if lines else [text[:max_chars]] if __name__ == '__main__': # CLI 테스트 import sys if len(sys.argv) > 1: pre_serial = sys.argv[1] else: pre_serial = '20260305000075' # 테스트 데이터 analysis = { 'prescription_insight': '테스트 처방입니다.', 'cautions': ['주의사항 1', '주의사항 2'], 'counseling_points': ['상담 포인트 1'] } kims_summary = {'interaction_count': 0, 'has_severe': False} result = print_paai_result(pre_serial, '테스트환자', analysis, kims_summary) print(result)