feat: 제품 검색 페이지에 동물약 뱃지 표시
- /api/products API에 is_animal_drug 필드 추가
- POS_BOON='010103' 기준으로 동물약 판별
- 🐾 동물약 뱃지 표시 (초록색)
This commit is contained in:
parent
431909e50b
commit
197ded3806
@ -2672,7 +2672,8 @@ def api_products():
|
|||||||
WHEN SET_CHK.is_set = 1 THEN N'세트상품'
|
WHEN SET_CHK.is_set = 1 THEN N'세트상품'
|
||||||
ELSE ''
|
ELSE ''
|
||||||
END as supplier,
|
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
|
FROM CD_GOODS G
|
||||||
OUTER APPLY (
|
OUTER APPLY (
|
||||||
SELECT TOP 1 CD_CD_BARCODE
|
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,
|
'sale_price': float(row.sale_price) if row.sale_price else 0,
|
||||||
'cost_price': float(row.cost_price) if row.cost_price else 0,
|
'cost_price': float(row.cost_price) if row.cost_price else 0,
|
||||||
'supplier': row.supplier or '',
|
'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({
|
return jsonify({
|
||||||
|
|||||||
175
backend/scripts/tag_animal_drugs.py
Normal file
175
backend/scripts/tag_animal_drugs.py
Normal 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()
|
||||||
@ -469,7 +469,10 @@
|
|||||||
tbody.innerHTML = productsData.map((item, idx) => `
|
tbody.innerHTML = productsData.map((item, idx) => `
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<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>
|
<div class="product-supplier ${item.is_set ? 'set' : ''}">${escapeHtml(item.supplier) || ''}</div>
|
||||||
</td>
|
</td>
|
||||||
<td><span class="code code-drug">${item.drug_code}</span></td>
|
<td><span class="code code-drug">${item.drug_code}</span></td>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user