feat: 동물약만 체크 시 검색어 없이 전체 조회 가능

- 동물약은 39건뿐이라 전체 조회해도 빠름
- 동물약만 체크 + 검색어 없음 → 전체 동물약 리스트
- 쿼리 조건 동적 생성 (animal_condition, search_condition)
This commit is contained in:
thug0bin 2026-03-04 14:02:47 +09:00
parent a0cbb984e5
commit 2859dc43cc
2 changed files with 86 additions and 57 deletions

View File

@ -3313,15 +3313,26 @@ def api_products():
animal_only = request.args.get('animal_only', '0') == '1' animal_only = request.args.get('animal_only', '0') == '1'
in_stock_only = request.args.get('in_stock_only', '0') == '1' in_stock_only = request.args.get('in_stock_only', '0') == '1'
if not search or len(search) < 2: # 동물약만 체크시 검색어 없어도 전체 조회 가능
if not animal_only and (not search or len(search) < 2):
return jsonify({'success': False, 'error': '검색어는 2글자 이상 입력하세요'}) return jsonify({'success': False, 'error': '검색어는 2글자 이상 입력하세요'})
try: try:
drug_session = db_manager.get_session('PM_DRUG') drug_session = db_manager.get_session('PM_DRUG')
# WHERE 조건 생성 (동물약 전체 조회 시 검색 조건 없음)
search_condition = ""
if search:
search_condition = """
AND (G.GoodsName LIKE :search_like
OR G.DrugCode LIKE :search_like
OR G.BARCODE LIKE :search_like)
"""
# 동물약만 필터 (쿼리에서 직접 처리)
animal_condition = "AND G.POS_BOON = '010103'" if animal_only else ""
# 제품 검색 쿼리 - 사용약품만 옵션에 따라 JOIN 방식 변경 # 제품 검색 쿼리 - 사용약품만 옵션에 따라 JOIN 방식 변경
# in_stock_only: INNER JOIN으로 재고 있는 제품만 (빠름)
# 그렇지 않으면: LEFT JOIN으로 모든 제품 (느림)
if in_stock_only: if in_stock_only:
# 최적화된 쿼리: 재고 있는 제품만 (IM_total INNER JOIN) # 최적화된 쿼리: 재고 있는 제품만 (IM_total INNER JOIN)
products_query = text(f""" products_query = text(f"""
@ -3337,62 +3348,76 @@ def api_products():
IT.IM_QT_sale_debit as stock IT.IM_QT_sale_debit as stock
FROM CD_GOODS G FROM CD_GOODS G
INNER JOIN IM_total IT ON G.DrugCode = IT.DrugCode AND IT.IM_QT_sale_debit > 0 INNER JOIN IM_total IT ON G.DrugCode = IT.DrugCode AND IT.IM_QT_sale_debit > 0
WHERE WHERE 1=1
G.GoodsName LIKE :search_like {animal_condition}
OR G.DrugCode LIKE :search_like {search_condition}
OR G.BARCODE LIKE :search_like
ORDER BY G.GoodsName ORDER BY G.GoodsName
""") """)
else: else:
# 전체 쿼리 (OUTER APPLY 포함, 느림) # 전체 쿼리 (OUTER APPLY 포함, 느림)
products_query = text(f""" # 동물약만 조회 시 OUTER APPLY 생략 가능
SELECT TOP {limit} if animal_only:
G.DrugCode as drug_code, products_query = text(f"""
G.GoodsName as product_name, SELECT TOP {limit}
COALESCE(NULLIF(G.BARCODE, ''), U.CD_CD_BARCODE, '') as barcode, G.DrugCode as drug_code,
G.Saleprice as sale_price, G.GoodsName as product_name,
G.Price as cost_price, COALESCE(NULLIF(G.BARCODE, ''), '') as barcode,
CASE G.Saleprice as sale_price,
WHEN G.SplName IS NOT NULL AND G.SplName != '' THEN G.SplName G.Price as cost_price,
WHEN SET_CHK.is_set = 1 THEN N'세트상품' ISNULL(G.SplName, '') as supplier,
ELSE '' 0 as is_set,
END as supplier, G.POS_BOON as pos_boon,
CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set, ISNULL(IT.IM_QT_sale_debit, 0) as stock
G.POS_BOON as pos_boon, FROM CD_GOODS G
ISNULL(IT.IM_QT_sale_debit, 0) as stock LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
FROM CD_GOODS G WHERE G.POS_BOON = '010103'
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode {search_condition}
OUTER APPLY ( ORDER BY G.GoodsName
SELECT TOP 1 CD_CD_BARCODE """)
FROM CD_ITEM_UNIT_MEMBER else:
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != '' products_query = text(f"""
) U SELECT TOP {limit}
OUTER APPLY ( G.DrugCode as drug_code,
SELECT TOP 1 1 as is_set G.GoodsName as product_name,
FROM CD_item_set COALESCE(NULLIF(G.BARCODE, ''), U.CD_CD_BARCODE, '') as barcode,
WHERE SetCode = G.DrugCode AND DrugCode = 'SET0000' G.Saleprice as sale_price,
) SET_CHK G.Price as cost_price,
WHERE CASE
G.GoodsName LIKE :search_like WHEN G.SplName IS NOT NULL AND G.SplName != '' THEN G.SplName
OR G.DrugCode LIKE :search_like WHEN SET_CHK.is_set = 1 THEN N'세트상품'
OR G.BARCODE LIKE :search_like ELSE ''
OR U.CD_CD_BARCODE LIKE :search_like END as supplier,
ORDER BY G.GoodsName CASE WHEN SET_CHK.is_set = 1 THEN 1 ELSE 0 END as is_set,
""") G.POS_BOON as pos_boon,
ISNULL(IT.IM_QT_sale_debit, 0) as stock
FROM CD_GOODS G
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
OUTER APPLY (
SELECT TOP 1 CD_CD_BARCODE
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
) U
OUTER APPLY (
SELECT TOP 1 1 as is_set
FROM CD_item_set
WHERE SetCode = G.DrugCode AND DrugCode = 'SET0000'
) SET_CHK
WHERE 1=1
{search_condition}
ORDER BY G.GoodsName
""")
search_like = f'%{search}%' # 파라미터 설정 (검색어가 있을 때만)
rows = drug_session.execute(products_query, { params = {}
'search_like': search_like if search:
}).fetchall() params['search_like'] = f'%{search}%'
rows = drug_session.execute(products_query, params).fetchall()
items = [] items = []
for row in rows: for row in rows:
is_animal = row.pos_boon == '010103' is_animal = row.pos_boon == '010103'
# 동물약만 필터링
if animal_only and not is_animal:
continue
# APC 조회 (동물약인 경우) # APC 조회 (동물약인 경우)
apc = None apc = None
if is_animal: if is_animal:

View File

@ -695,19 +695,23 @@
function searchProducts() { function searchProducts() {
const search = document.getElementById('searchInput').value.trim(); const search = document.getElementById('searchInput').value.trim();
if (!search) { const animalOnly = document.getElementById('animalOnly').checked;
alert('검색어를 입력하세요');
return; // 동물약만 체크시 검색어 없어도 전체 조회 가능
} if (!animalOnly) {
if (search.length < 2) { if (!search) {
alert('2글자 이상 입력하세요'); alert('검색어를 입력하세요');
return; return;
}
if (search.length < 2) {
alert('2글자 이상 입력하세요');
return;
}
} }
const tbody = document.getElementById('productsTableBody'); const tbody = document.getElementById('productsTableBody');
tbody.innerHTML = '<tr><td colspan="6" class="empty-state"><p>검색 중...</p></td></tr>'; tbody.innerHTML = '<tr><td colspan="6" class="empty-state"><p>검색 중...</p></td></tr>';
const animalOnly = document.getElementById('animalOnly').checked;
const inStockOnly = document.getElementById('inStockOnly').checked; const inStockOnly = document.getElementById('inStockOnly').checked;
let url = `/api/products?search=${encodeURIComponent(search)}`; let url = `/api/products?search=${encodeURIComponent(search)}`;
if (animalOnly) url += '&animal_only=1'; if (animalOnly) url += '&animal_only=1';