From 45672a125fac99ee06365e66512fc1446f6e11bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=8B=9C=EA=B3=A8=EC=95=BD=EC=82=AC?= Date: Sun, 15 Feb 2026 12:45:21 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=ED=99=98=EC=9E=90=20=EC=B2=98=EB=B0=A9?= =?UTF-8?q?=20=EB=82=B4=EC=97=AD=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 환자 목록에 처방 횟수 표시 (배지) - 환자별 처방 내역 조회 버튼 추가 - 환자 처방 내역 모달 추가 (통계 + 상세 내역) - 총 처방 횟수, 최근 방문일, 총 제수, 총 처방비 - 전체 처방 내역 테이블 (조제일, 처방명, 상태 등) - 각 처방의 상세 보기 기능 연동 - 환자 개별 조회 API 엔드포인트 추가 (GET /api/patients/) - 환자 편집 버튼 UI 추가 (기능 준비) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app.py | 19 +++++ static/app.js | 168 +++++++++++++++++++++++++++++++++++++++---- templates/index.html | 94 +++++++++++++++++++++++- 3 files changed, 265 insertions(+), 16 deletions(-) diff --git a/app.py b/app.py index c1539bd..8913d71 100644 --- a/app.py +++ b/app.py @@ -83,6 +83,25 @@ def get_patients(): except Exception as e: return jsonify({'success': False, 'error': str(e)}), 500 +@app.route('/api/patients/', methods=['GET']) +def get_patient(patient_id): + """환자 개별 조회""" + try: + with get_db() as conn: + cursor = conn.cursor() + cursor.execute(""" + SELECT patient_id, name, phone, jumin_no, gender, birth_date, address, notes + FROM patients + WHERE patient_id = ? AND is_active = 1 + """, (patient_id,)) + patient_row = cursor.fetchone() + if patient_row: + return jsonify({'success': True, 'data': dict(patient_row)}) + else: + return jsonify({'success': False, 'error': '환자를 찾을 수 없습니다'}), 404 + except Exception as e: + return jsonify({'success': False, 'error': str(e)}), 500 + @app.route('/api/patients', methods=['POST']) def create_patient(): """새 환자 등록""" diff --git a/static/app.js b/static/app.js index 154d8cf..7860195 100644 --- a/static/app.js +++ b/static/app.js @@ -122,21 +122,52 @@ $(document).ready(function() { const tbody = $('#patientsList'); tbody.empty(); - response.data.forEach(patient => { - tbody.append(` - - ${patient.name} - ${patient.phone} - ${patient.gender === 'M' ? '남' : patient.gender === 'F' ? '여' : '-'} - ${patient.birth_date || '-'} - ${patient.notes || '-'} - - - - - `); + // 각 환자의 처방 횟수를 가져오기 위해 처방 데이터도 로드 + $.get('/api/compounds', function(compoundsResponse) { + const compounds = compoundsResponse.success ? compoundsResponse.data : []; + + // 환자별 처방 횟수 계산 + const compoundCounts = {}; + compounds.forEach(compound => { + if (compound.patient_id) { + compoundCounts[compound.patient_id] = (compoundCounts[compound.patient_id] || 0) + 1; + } + }); + + response.data.forEach(patient => { + const compoundCount = compoundCounts[patient.patient_id] || 0; + + tbody.append(` + + ${patient.name} + ${patient.phone} + ${patient.gender === 'M' ? '남' : patient.gender === 'F' ? '여' : '-'} + ${patient.birth_date || '-'} + + ${compoundCount}회 + + ${patient.notes || '-'} + + + + + + `); + }); + + // 처방내역 버튼 이벤트 + $('.view-patient-compounds').on('click', function() { + const patientId = $(this).data('id'); + const patientName = $(this).data('name'); + viewPatientCompounds(patientId, patientName); + }); }); } }); @@ -173,6 +204,113 @@ $(document).ready(function() { }); }); + // 환자 처방 내역 조회 + function viewPatientCompounds(patientId, patientName) { + // 환자 정보 가져오기 + $.get(`/api/patients/${patientId}`, function(patientResponse) { + if (patientResponse.success) { + const patient = patientResponse.data; + + // 환자 기본 정보 표시 + $('#patientCompoundsName').text(patient.name); + $('#patientInfoName').text(patient.name); + $('#patientInfoPhone').text(patient.phone || '-'); + $('#patientInfoGender').text(patient.gender === 'M' ? '남성' : patient.gender === 'F' ? '여성' : '-'); + $('#patientInfoBirth').text(patient.birth_date || '-'); + + // 환자의 처방 내역 가져오기 + $.get(`/api/patients/${patientId}/compounds`, function(compoundsResponse) { + if (compoundsResponse.success) { + const compounds = compoundsResponse.data; + + // 통계 계산 + const totalCompounds = compounds.length; + let totalJe = 0; + let totalAmount = 0; + let lastVisit = '-'; + + if (compounds.length > 0) { + compounds.forEach(c => { + totalJe += c.je_count || 0; + totalAmount += c.sell_price_total || 0; + }); + lastVisit = compounds[0].compound_date || '-'; + } + + // 통계 표시 + $('#patientTotalCompounds').text(totalCompounds + '회'); + $('#patientLastVisit').text(lastVisit); + $('#patientTotalJe').text(totalJe + '제'); + $('#patientTotalAmount').text(formatCurrency(totalAmount)); + + // 처방 내역 테이블 표시 + const tbody = $('#patientCompoundsList'); + tbody.empty(); + + if (compounds.length === 0) { + tbody.append(` + + 처방 내역이 없습니다. + + `); + } else { + compounds.forEach(compound => { + // 상태 뱃지 + let statusBadge = ''; + switch(compound.status) { + case 'PREPARED': + statusBadge = '조제완료'; + break; + case 'DISPENSED': + statusBadge = '출고완료'; + break; + case 'CANCELLED': + statusBadge = '취소'; + break; + default: + statusBadge = '대기'; + } + + tbody.append(` + + ${compound.compound_date || '-'} + ${compound.formula_name || '직접조제'} + ${compound.je_count || 0} + ${compound.cheop_total || 0} + ${compound.pouch_total || 0} + ${formatCurrency(compound.cost_total || 0)} + ${formatCurrency(compound.sell_price_total || 0)} + ${statusBadge} + ${compound.prescription_no || '-'} + + + + + `); + }); + + // 상세보기 버튼 이벤트 + $('.view-compound-detail').on('click', function() { + const compoundId = $(this).data('id'); + viewCompoundDetail(compoundId); + }); + } + + // 모달 표시 + $('#patientCompoundsModal').modal('show'); + } + }).fail(function() { + alert('처방 내역을 불러오는데 실패했습니다.'); + }); + } + }).fail(function() { + alert('환자 정보를 불러오는데 실패했습니다.'); + }); + } + // 처방 목록 로드 function loadFormulas() { $.get('/api/formulas', function(response) { diff --git a/templates/index.html b/templates/index.html index 092b2cb..18c03fd 100644 --- a/templates/index.html +++ b/templates/index.html @@ -205,8 +205,9 @@ 전화번호 성별 생년월일 + 처방 횟수 메모 - 작업 + 작업 @@ -1024,6 +1025,97 @@ + + +