kdrug-inventory-system/templates/index.html
시골약사 8f2823e6df refactor: 주성분코드 기반 데이터베이스 리팩토링 완료
DB 구조 개선:
- 454개 주성분코드 기반 herb_masters 테이블 생성
- 53,769개 제품 데이터를 herb_products 테이블에 임포트
- 128개 업체 정보를 product_companies 테이블에 추가
- 기존 herb_items에 ingredient_code 매핑 (100% 완료)

UI/API 개선:
- 급여 약재 보유 현황 표시 (28/454 = 6.2%)
- 재고 현황에 프로그레스 바 추가
- 주성분코드 기준 통계 API 추가

문서화:
- 데이터베이스 리팩토링 제안서 작성
- 리팩토링 결과 보고서 작성
- 백업 정보 문서화

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-15 10:34:32 +00:00

660 lines
33 KiB
HTML

<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>한약 재고관리 시스템</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.1/font/bootstrap-icons.css" rel="stylesheet">
<style>
body {
font-family: 'Noto Sans KR', sans-serif;
background-color: #f8f9fa;
}
.navbar-brand {
font-weight: bold;
color: #2c3e50 !important;
}
.sidebar {
min-height: calc(100vh - 56px);
background-color: #fff;
box-shadow: 2px 0 5px rgba(0,0,0,0.05);
}
.sidebar .nav-link {
color: #495057;
padding: 12px 20px;
border-left: 3px solid transparent;
transition: all 0.3s;
}
.sidebar .nav-link:hover {
background-color: #f8f9fa;
border-left-color: #007bff;
}
.sidebar .nav-link.active {
background-color: #e7f1ff;
border-left-color: #007bff;
color: #007bff;
font-weight: 500;
}
.content-area {
padding: 20px;
}
.stat-card {
background: white;
border-radius: 10px;
padding: 20px;
box-shadow: 0 2px 4px rgba(0,0,0,0.08);
margin-bottom: 20px;
}
.stat-card h5 {
color: #6c757d;
font-size: 14px;
margin-bottom: 10px;
}
.stat-card .value {
font-size: 24px;
font-weight: bold;
color: #2c3e50;
}
.main-content {
display: none;
}
.main-content.active {
display: block;
}
</style>
</head>
<body>
<!-- Navigation Bar -->
<nav class="navbar navbar-expand-lg navbar-light bg-white shadow-sm">
<div class="container-fluid">
<a class="navbar-brand" href="#">
<i class="bi bi-heart-pulse-fill text-primary"></i> 한약 재고관리 시스템
</a>
<div class="navbar-nav ms-auto">
<span class="navbar-text me-3">
<i class="bi bi-person-circle"></i> 관리자
</span>
<button class="btn btn-outline-secondary btn-sm">
<i class="bi bi-box-arrow-right"></i> 로그아웃
</button>
</div>
</div>
</nav>
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<div class="col-md-2 sidebar p-0">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#" data-page="dashboard">
<i class="bi bi-speedometer2"></i> 대시보드
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="patients">
<i class="bi bi-people"></i> 환자 관리
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="purchase">
<i class="bi bi-file-earmark-arrow-up"></i> 입고 관리
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="formulas">
<i class="bi bi-journal-medical"></i> 처방 관리
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="compound">
<i class="bi bi-prescription2"></i> 조제 관리
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="inventory">
<i class="bi bi-box-seam"></i> 재고 현황
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#" data-page="herbs">
<i class="bi bi-flower1"></i> 약재 관리
</a>
</li>
</ul>
</div>
<!-- Main Content Area -->
<div class="col-md-10 content-area">
<!-- Dashboard Page -->
<div id="dashboard" class="main-content active">
<h3 class="mb-4">대시보드</h3>
<div class="row">
<div class="col-md-3">
<div class="stat-card">
<h5><i class="bi bi-people-fill"></i> 총 환자수</h5>
<div class="value" id="totalPatients">0</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card">
<h5><i class="bi bi-box-seam-fill"></i> 재고 품목</h5>
<div class="value" id="totalHerbs">0</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card">
<h5><i class="bi bi-calendar-check"></i> 오늘 조제</h5>
<div class="value" id="todayCompounds">0</div>
</div>
</div>
<div class="col-md-3">
<div class="stat-card">
<h5><i class="bi bi-cash-stack"></i> 재고 자산</h5>
<div class="value" id="inventoryValue">0</div>
</div>
</div>
</div>
<div class="row mt-4">
<div class="col-md-12">
<div class="card">
<div class="card-header">
<h5 class="mb-0">최근 조제 내역</h5>
</div>
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>조제일</th>
<th>환자명</th>
<th>처방명</th>
<th>제수</th>
<th>파우치</th>
<th>상태</th>
</tr>
</thead>
<tbody id="recentCompounds">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Patients Page -->
<div id="patients" class="main-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>환자 관리</h3>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#patientModal">
<i class="bi bi-person-plus"></i> 새 환자 등록
</button>
</div>
<div class="card">
<div class="card-body">
<div class="mb-3">
<input type="text" class="form-control" id="patientSearch" placeholder="환자명 또는 전화번호로 검색...">
</div>
<table class="table table-hover">
<thead>
<tr>
<th>환자명</th>
<th>전화번호</th>
<th>성별</th>
<th>생년월일</th>
<th>메모</th>
<th>작업</th>
</tr>
</thead>
<tbody id="patientsList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Purchase Page -->
<div id="purchase" class="main-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>입고 관리</h3>
</div>
<!-- 입고장 목록 -->
<div class="card mb-4">
<div class="card-header">
<h5 class="mb-0">입고장 목록</h5>
</div>
<div class="card-body">
<div class="row mb-3">
<div class="col-md-3">
<label class="form-label">시작일</label>
<input type="date" class="form-control" id="purchaseStartDate">
</div>
<div class="col-md-3">
<label class="form-label">종료일</label>
<input type="date" class="form-control" id="purchaseEndDate">
</div>
<div class="col-md-3">
<label class="form-label">공급업체</label>
<select class="form-control" id="purchaseSupplier">
<option value="">전체</option>
</select>
</div>
<div class="col-md-3">
<label class="form-label">&nbsp;</label>
<button class="btn btn-primary w-100" id="searchPurchaseBtn">
<i class="bi bi-search"></i> 조회
</button>
</div>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>입고일</th>
<th>공급업체</th>
<th>품목 수</th>
<th>총 금액</th>
<th>총 수량</th>
<th>파일명</th>
<th>작업</th>
</tr>
</thead>
<tbody id="purchaseReceiptsList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
<!-- Excel 업로드 -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="mb-0">새 입고 등록 (Excel 업로드)</h5>
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" data-bs-target="#supplierModal">
<i class="bi bi-plus"></i> 도매상 등록
</button>
</div>
<div class="card-body">
<form id="purchaseUploadForm" enctype="multipart/form-data">
<div class="row">
<div class="col-md-6">
<label for="uploadSupplier" class="form-label">도매상 선택 *</label>
<select class="form-control" id="uploadSupplier" required>
<option value="">도매상을 선택하세요</option>
</select>
</div>
<div class="col-md-6">
<label for="purchaseFile" class="form-label">Excel 파일 선택 *</label>
<input type="file" class="form-control" id="purchaseFile" accept=".xlsx,.xls" required>
</div>
</div>
<div class="form-text mt-2">
<i class="bi bi-info-circle"></i> Excel 형식: 한의사랑, 한의정보 (자동 감지)<br>
<i class="bi bi-info-circle"></i> Excel 내 업체명은 제조사(제약사)로 저장됩니다
</div>
<button type="submit" class="btn btn-primary mt-3">
<i class="bi bi-upload"></i> 업로드 및 처리
</button>
</form>
<div id="uploadResult" class="mt-3"></div>
</div>
</div>
</div>
<!-- Formulas Page -->
<div id="formulas" class="main-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>처방 관리</h3>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#formulaModal">
<i class="bi bi-plus-circle"></i> 새 처방 등록
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>처방코드</th>
<th>처방명</th>
<th>기본 첩수</th>
<th>기본 파우치</th>
<th>구성 약재</th>
<th>작업</th>
</tr>
</thead>
<tbody id="formulasList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Compound Page -->
<div id="compound" class="main-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>조제 관리</h3>
<button class="btn btn-primary" id="newCompoundBtn">
<i class="bi bi-plus-circle"></i> 새 조제
</button>
</div>
<div class="card" id="compoundForm" style="display: none;">
<div class="card-body">
<h5>조제 입력</h5>
<form id="compoundEntryForm">
<div class="row">
<div class="col-md-6">
<label class="form-label">환자 선택</label>
<select class="form-control" id="compoundPatient" required>
<option value="">환자를 선택하세요</option>
</select>
</div>
<div class="col-md-6">
<label class="form-label">처방 선택</label>
<select class="form-control" id="compoundFormula" required>
<option value="">처방을 선택하세요</option>
</select>
</div>
</div>
<div class="row mt-3">
<div class="col-md-4">
<label class="form-label">제수</label>
<input type="number" class="form-control" id="jeCount" value="1" min="0.5" step="0.5" required>
</div>
<div class="col-md-4">
<label class="form-label">총 첩수</label>
<input type="number" class="form-control" id="cheopTotal" readonly>
</div>
<div class="col-md-4">
<label class="form-label">총 파우치수</label>
<input type="number" class="form-control" id="pouchTotal" required>
</div>
</div>
<div class="mt-3">
<h6>약재 구성 (가감 가능)</h6>
<table class="table table-sm">
<thead>
<tr>
<th>약재명</th>
<th>1첩당 용량(g)</th>
<th>총 용량(g)</th>
<th>원산지 선택</th>
<th>재고</th>
<th>작업</th>
</tr>
</thead>
<tbody id="compoundIngredients">
<!-- Dynamic content -->
</tbody>
</table>
<button type="button" class="btn btn-sm btn-outline-primary" id="addIngredientBtn">
<i class="bi bi-plus"></i> 약재 추가
</button>
</div>
<div class="mt-3">
<button type="submit" class="btn btn-success">
<i class="bi bi-check-circle"></i> 조제 실행
</button>
<button type="button" class="btn btn-secondary ms-2" id="cancelCompoundBtn">
취소
</button>
</div>
</form>
</div>
</div>
<div class="card mt-4">
<div class="card-header">
<h5 class="mb-0">조제 내역</h5>
</div>
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>조제일</th>
<th>환자명</th>
<th>처방명</th>
<th>제수</th>
<th>파우치</th>
<th>원가</th>
<th>상태</th>
</tr>
</thead>
<tbody id="compoundsList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Inventory Page -->
<div id="inventory" class="main-content">
<h3 class="mb-4">재고 현황</h3>
<div class="card">
<div class="card-body">
<div class="mb-3">
<input type="text" class="form-control" id="inventorySearch" placeholder="약재명으로 검색...">
</div>
<table class="table table-hover">
<thead>
<tr>
<th>보험코드</th>
<th>약재명</th>
<th>현재 재고(g)</th>
<th>로트 수</th>
<th>평균 단가</th>
<th>재고 금액</th>
</tr>
</thead>
<tbody id="inventoryList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
<!-- Herbs Page -->
<div id="herbs" class="main-content">
<div class="d-flex justify-content-between align-items-center mb-4">
<h3>약재 관리</h3>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#herbModal">
<i class="bi bi-plus-circle"></i> 새 약재 등록
</button>
</div>
<div class="card">
<div class="card-body">
<table class="table table-hover">
<thead>
<tr>
<th>보험코드</th>
<th>약재명</th>
<th>규격</th>
<th>현재 재고</th>
<th>작업</th>
</tr>
</thead>
<tbody id="herbsList">
<!-- Dynamic content -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Patient Modal -->
<div class="modal fade" id="patientModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">환자 등록</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="patientForm">
<div class="mb-3">
<label class="form-label">환자명 *</label>
<input type="text" class="form-control" id="patientName" required>
</div>
<div class="mb-3">
<label class="form-label">전화번호 *</label>
<input type="tel" class="form-control" id="patientPhone" required>
</div>
<div class="mb-3">
<label class="form-label">주민번호</label>
<input type="text" class="form-control" id="patientJumin" placeholder="000000-0000000">
</div>
<div class="mb-3">
<label class="form-label">성별</label>
<select class="form-control" id="patientGender">
<option value="">선택</option>
<option value="M">남성</option>
<option value="F">여성</option>
</select>
</div>
<div class="mb-3">
<label class="form-label">생년월일</label>
<input type="date" class="form-control" id="patientBirth">
</div>
<div class="mb-3">
<label class="form-label">주소</label>
<input type="text" class="form-control" id="patientAddress">
</div>
<div class="mb-3">
<label class="form-label">메모</label>
<textarea class="form-control" id="patientNotes" rows="2"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" id="savePatientBtn">저장</button>
</div>
</div>
</div>
</div>
<!-- Formula Modal -->
<div class="modal fade" id="formulaModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">처방 등록</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="formulaForm">
<div class="row">
<div class="col-md-6">
<label class="form-label">처방코드</label>
<input type="text" class="form-control" id="formulaCode">
</div>
<div class="col-md-6">
<label class="form-label">처방명 *</label>
<input type="text" class="form-control" id="formulaName" required>
</div>
</div>
<div class="row mt-3">
<div class="col-md-4">
<label class="form-label">처방 유형</label>
<select class="form-control" id="formulaType">
<option value="CUSTOM">약속처방</option>
<option value="INSURANCE">보험처방</option>
</select>
</div>
<div class="col-md-4">
<label class="form-label">기본 첩수</label>
<input type="number" class="form-control" id="baseCheop" value="20">
</div>
<div class="col-md-4">
<label class="form-label">기본 파우치수</label>
<input type="number" class="form-control" id="basePouches" value="30">
</div>
</div>
<div class="mt-3">
<label class="form-label">설명</label>
<textarea class="form-control" id="formulaDescription" rows="2"></textarea>
</div>
<div class="mt-3">
<h6>구성 약재</h6>
<table class="table table-sm">
<thead>
<tr>
<th>약재명</th>
<th>1첩당 용량(g)</th>
<th>비고</th>
<th>삭제</th>
</tr>
</thead>
<tbody id="formulaIngredients">
<!-- Dynamic content -->
</tbody>
</table>
<button type="button" class="btn btn-sm btn-outline-primary" id="addFormulaIngredientBtn">
<i class="bi bi-plus"></i> 약재 추가
</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" id="saveFormulaBtn">저장</button>
</div>
</div>
</div>
</div>
<!-- Supplier Modal -->
<div class="modal fade" id="supplierModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">도매상 등록</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="supplierForm">
<div class="mb-3">
<label class="form-label">도매상명 *</label>
<input type="text" class="form-control" id="supplierName" required>
</div>
<div class="mb-3">
<label class="form-label">사업자번호</label>
<input type="text" class="form-control" id="supplierBusinessNo" placeholder="000-00-00000">
</div>
<div class="mb-3">
<label class="form-label">담당자</label>
<input type="text" class="form-control" id="supplierContactPerson">
</div>
<div class="mb-3">
<label class="form-label">전화번호</label>
<input type="tel" class="form-control" id="supplierPhone">
</div>
<div class="mb-3">
<label class="form-label">주소</label>
<input type="text" class="form-control" id="supplierAddress">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" id="saveSupplierBtn">저장</button>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="/static/app.js?v=20260215"></script>
</body>
</html>