feat: 단위바코드 갯수 뱃지 + QR 바코드 우선순위 수정

화면 표시:
- 대표바코드 옆 빨간 뱃지로 단위바코드 갯수 표시 (카톡 스타일)
- APC 없어도 단위바코드 있으면 POS 판매 가능함을 표시

QR 인쇄 우선순위:
1. 대표바코드 (있으면)
2. 단위바코드 첫 번째 (대표 없으면)
3. drug_code (fallback)

쿼리 추가:
- UNIT_FIRST: 단위바코드 첫 번째 (조건 없이)
- UNIT_CNT: 단위바코드 갯수
This commit is contained in:
thug0bin
2026-03-04 16:29:23 +09:00
parent 1c2bfd473b
commit 77c667e1f6
2 changed files with 75 additions and 10 deletions

View File

@@ -3335,7 +3335,7 @@ def api_products():
# 제품 검색 쿼리 - 사용약품만 옵션에 따라 JOIN 방식 변경
if in_stock_only:
# 최적화된 쿼리: 재고 있는 제품만 (IM_total INNER JOIN)
# 대표바코드만 표시 (없으면 빈값), APC는 02로 시작하는 것만
# 대표바코드만 표시, 단위바코드 첫번째/갯수, APC(02%)
products_query = text(f"""
SELECT TOP {limit}
G.DrugCode as drug_code,
@@ -3348,7 +3348,9 @@ def api_products():
G.POS_BOON as pos_boon,
IT.IM_QT_sale_debit as stock,
ISNULL(POS.CD_NM_sale, '') as location,
APC.CD_CD_BARCODE as apc_code
APC.CD_CD_BARCODE as apc_code,
UNIT_FIRST.CD_CD_BARCODE as unit_barcode,
ISNULL(UNIT_CNT.cnt, 0) as unit_barcode_count
FROM CD_GOODS G
INNER JOIN IM_total IT ON G.DrugCode = IT.DrugCode AND IT.IM_QT_sale_debit > 0
LEFT JOIN CD_item_position POS ON G.DrugCode = POS.DrugCode
@@ -3357,6 +3359,16 @@ def api_products():
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE LIKE '02%'
) APC
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 != ''
) UNIT_FIRST
OUTER APPLY (
SELECT COUNT(*) as cnt
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
) UNIT_CNT
WHERE 1=1
{animal_condition}
{search_condition}
@@ -3378,7 +3390,9 @@ def api_products():
G.POS_BOON as pos_boon,
ISNULL(IT.IM_QT_sale_debit, 0) as stock,
ISNULL(POS.CD_NM_sale, '') as location,
APC.CD_CD_BARCODE as apc_code
APC.CD_CD_BARCODE as apc_code,
UNIT_FIRST.CD_CD_BARCODE as unit_barcode,
ISNULL(UNIT_CNT.cnt, 0) as unit_barcode_count
FROM CD_GOODS G
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
LEFT JOIN CD_item_position POS ON G.DrugCode = POS.DrugCode
@@ -3387,6 +3401,16 @@ def api_products():
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE LIKE '02%'
) APC
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 != ''
) UNIT_FIRST
OUTER APPLY (
SELECT COUNT(*) as cnt
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
) UNIT_CNT
WHERE G.POS_BOON = '010103'
{search_condition}
ORDER BY G.GoodsName
@@ -3408,7 +3432,9 @@ def api_products():
G.POS_BOON as pos_boon,
ISNULL(IT.IM_QT_sale_debit, 0) as stock,
ISNULL(POS.CD_NM_sale, '') as location,
APC.CD_CD_BARCODE as apc_code
APC.CD_CD_BARCODE as apc_code,
UNIT_FIRST.CD_CD_BARCODE as unit_barcode,
ISNULL(UNIT_CNT.cnt, 0) as unit_barcode_count
FROM CD_GOODS G
LEFT JOIN IM_total IT ON G.DrugCode = IT.DrugCode
LEFT JOIN CD_item_position POS ON G.DrugCode = POS.DrugCode
@@ -3422,6 +3448,16 @@ def api_products():
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE LIKE '02%'
) APC
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 != ''
) UNIT_FIRST
OUTER APPLY (
SELECT COUNT(*) as cnt
FROM CD_ITEM_UNIT_MEMBER
WHERE DRUGCODE = G.DrugCode AND CD_CD_BARCODE IS NOT NULL AND CD_CD_BARCODE != ''
) UNIT_CNT
WHERE 1=1
{search_condition}
ORDER BY G.GoodsName
@@ -3456,8 +3492,12 @@ def api_products():
# APC 코드: 쿼리에서 02%로 조회한 것만 사용 (바코드 대체 X)
apc_code = getattr(row, 'apc_code', None) or ''
# PostgreSQL 조회용 APC (분류/도매재고): apc 또는 apc_code 사용
pg_apc = apc or apc_code
# 단위바코드 (첫 번째, 갯수)
unit_barcode = getattr(row, 'unit_barcode', None) or ''
unit_barcode_count = getattr(row, 'unit_barcode_count', 0) or 0
# PostgreSQL 조회용 APC (분류/도매재고): apc 또는 apc_code 또는 unit_barcode
pg_apc = apc or apc_code or unit_barcode
items.append({
'drug_code': row.drug_code or '',
@@ -3471,6 +3511,8 @@ def api_products():
'stock': int(row.stock) if row.stock else 0,
'location': row.location or '', # 위치
'apc': apc_code, # UI용 APC 코드 (02로 시작하는 것만)
'unit_barcode': unit_barcode, # 단위바코드 첫 번째 (QR용)
'unit_barcode_count': int(unit_barcode_count), # 단위바코드 갯수 (뱃지용)
'_pg_apc': pg_apc, # PostgreSQL 조회용 (내부용)
'category': None, # PostgreSQL에서 lazy fetch
'wholesaler_stock': None,