feat: 제품 검색 페이지에 동물약 뱃지 표시

- /api/products API에 is_animal_drug 필드 추가
- POS_BOON='010103' 기준으로 동물약 판별
- 🐾 동물약 뱃지 표시 (초록색)
This commit is contained in:
thug0bin 2026-02-27 17:56:34 +09:00
parent 431909e50b
commit 197ded3806
3 changed files with 183 additions and 3 deletions

View File

@ -2672,7 +2672,8 @@ def api_products():
WHEN SET_CHK.is_set = 1 THEN N'세트상품'
ELSE ''
END as supplier,
CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set
CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set,
G.POS_BOON as pos_boon
FROM CD_GOODS G
OUTER APPLY (
SELECT TOP 1 CD_CD_BARCODE
@ -2706,7 +2707,8 @@ def api_products():
'sale_price': float(row.sale_price) if row.sale_price else 0,
'cost_price': float(row.cost_price) if row.cost_price else 0,
'supplier': row.supplier or '',
'is_set': bool(row.is_set)
'is_set': bool(row.is_set),
'is_animal_drug': row.pos_boon == '010103'
})
return jsonify({

View File

@ -0,0 +1,175 @@
"""
동물약 태깅 MSSQL 동기화
1. 키워드로 CD_GOODS에서 동물약 검색
2. SQLite drug_tags.db에 태깅
3. MSSQL CD_GOODS.POS_BOON = '010103' 업데이트
"""
import sqlite3
from pathlib import Path
import sys
sys.path.insert(0, str(Path(__file__).parent.parent))
from db.dbsetup import db_manager
from sqlalchemy import text
# SQLite DB 경로
DB_PATH = Path(__file__).parent.parent / 'db' / 'drug_tags.db'
# 동물약 키워드
ANIMAL_KEYWORDS = [
'동물', '반려', '애견', '강아지', '고양이', '반려견',
'넥스가드', '브라벡토', '심파리카', '크레델리오', '컴포티스',
'하트세이버', '하트가드', '다이로하트', '하트웜', '하트캅',
'안텔민', '파라캅', '제스타제',
'캐치원', '셀라이트', '가드닐', '리펠로', '심피드독',
'세레니아', '아포퀄', '갈리프란트', '클라펫',
'펫팜', '동물약품', '애니팜'
]
# 제외 키워드 (사람용 약)
EXCLUDE_KEYWORDS = [
'헤리펫사', '토피라펫', '메타트레이스', '페리돈', '세파라캅'
]
def init_sqlite_db():
"""SQLite DB 초기화"""
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS drug_tags (
id INTEGER PRIMARY KEY AUTOINCREMENT,
drug_code TEXT NOT NULL,
drug_name TEXT,
barcode TEXT,
tag_type TEXT NOT NULL,
tag_value TEXT,
note TEXT,
source TEXT DEFAULT 'keyword',
confidence REAL DEFAULT 0.8,
is_active BOOLEAN DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(drug_code, tag_type)
)
''')
conn.commit()
conn.close()
print(f"✅ SQLite DB 준비: {DB_PATH}")
def search_animal_drugs():
"""MSSQL에서 동물약 키워드 검색"""
print("🔍 CD_GOODS에서 동물약 검색 중...")
session = db_manager.get_session('PM_DRUG')
# 키워드 조건 생성
conditions = ' OR '.join([f"GoodsName LIKE '%{kw}%'" for kw in ANIMAL_KEYWORDS])
query = text(f"""
SELECT DrugCode, GoodsName, BARCODE, POS_BOON
FROM CD_GOODS
WHERE ({conditions})
AND GoodsSelCode = 'B'
""")
result = session.execute(query)
drugs = result.fetchall()
print(f"✅ 발견: {len(drugs)}")
return drugs
def tag_to_sqlite(drugs):
"""SQLite에 동물약 태깅"""
print("\n📝 SQLite 태깅 중...")
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
added = 0
skipped = 0
excluded = 0
for drug in drugs:
drug_code = drug[0]
drug_name = drug[1] or ''
barcode = drug[2]
# 제외 키워드 체크
if any(ex in drug_name for ex in EXCLUDE_KEYWORDS):
excluded += 1
print(f" ⛔ 제외: {drug_code} - {drug_name}")
continue
try:
cursor.execute('''
INSERT INTO drug_tags (drug_code, drug_name, barcode, tag_type, tag_value, note)
VALUES (?, ?, ?, 'animal_drug', 'all', '키워드 자동 태깅')
''', (drug_code, drug_name, barcode))
added += 1
print(f"{drug_code}: {drug_name}")
except sqlite3.IntegrityError:
skipped += 1
conn.commit()
conn.close()
print(f"\n📊 태깅 결과: 추가 {added}개, 중복 {skipped}개, 제외 {excluded}")
return added
def sync_to_mssql():
"""SQLite 태그를 MSSQL POS_BOON에 동기화"""
print("\n🔄 MSSQL 동기화 중...")
# SQLite에서 동물약 목록 가져오기
conn = sqlite3.connect(DB_PATH)
cursor = conn.cursor()
cursor.execute('''
SELECT drug_code, drug_name FROM drug_tags
WHERE tag_type = 'animal_drug' AND is_active = 1
''')
animal_drugs = cursor.fetchall()
conn.close()
print(f" 동물약 {len(animal_drugs)}개 → POS_BOON='010103' 업데이트")
# MSSQL 업데이트
session = db_manager.get_session('PM_DRUG')
updated = 0
for drug_code, drug_name in animal_drugs:
try:
result = session.execute(text('''
UPDATE CD_GOODS SET POS_BOON = '010103' WHERE DrugCode = :dc
'''), {'dc': drug_code})
session.commit()
if result.rowcount > 0:
updated += 1
print(f"{drug_code}: {drug_name}")
except Exception as e:
print(f"{drug_code}: {e}")
print(f"\n🎉 완료! MSSQL 업데이트: {updated}")
def main():
print("=" * 50)
print("🐾 동물약 태깅 시스템")
print("=" * 50)
# 1. SQLite 초기화
init_sqlite_db()
# 2. 동물약 검색
drugs = search_animal_drugs()
# 3. SQLite 태깅
tag_to_sqlite(drugs)
# 4. MSSQL 동기화
sync_to_mssql()
print("\n" + "=" * 50)
print("✅ 모든 작업 완료!")
print("=" * 50)
if __name__ == '__main__':
main()

View File

@ -469,7 +469,10 @@
tbody.innerHTML = productsData.map((item, idx) => `
<tr>
<td>
<div class="product-name">${escapeHtml(item.product_name)}</div>
<div class="product-name">
${item.is_animal_drug ? '<span style="display:inline-block;background:#10b981;color:#fff;font-size:11px;padding:2px 6px;border-radius:4px;margin-right:6px;">🐾 동물약</span>' : ''}
${escapeHtml(item.product_name)}
</div>
<div class="product-supplier ${item.is_set ? 'set' : ''}">${escapeHtml(item.supplier) || ''}</div>
</td>
<td><span class="code code-drug">${item.drug_code}</span></td>