pharmacy-pos-qr-system/docs/IMAGE_MAPPING_PLAN.md

239 lines
7.6 KiB
Markdown

# 🖼️ 동물약 이미지 매핑 계획
## 📋 목표
챗봇에서 동물약 추천 시 **제품 이미지**를 함께 표시
---
## 🗄️ 데이터 현황
### MSSQL (약국 POS - PM_DRUG.CD_GOODS)
| 컬럼 | 설명 | 현황 |
|------|------|------|
| `DrugCode` | 제품코드 | ✅ 전체 있음 (예: LB000003151) |
| `GoodsName` | 제품명 | ✅ 전체 있음 |
| `BARCODE` | 바코드 | ⚠️ **14/38개만 있음 (37%)** |
| `BaseCode` | 표준코드 | ❌ **0개** (사용 불가) |
### PostgreSQL (애니팜 - apc 테이블)
| 컬럼 | 설명 |
|------|------|
| `idx` | 고유 ID |
| `apc` | APC 코드 (고유) |
| `product_name` | 제품명 |
| `image_url1` ~ `image_url3` | 이미지 URL |
| `godoimage_url_f` | 고도몰 CDN - 앞 이미지 |
| `godoimage_url_b` | 고도몰 CDN - 뒤 이미지 |
| `godoimage_url_d` | 고도몰 CDN - 상세 이미지 |
**확인 필요**: `apc` 테이블에 바코드 컬럼이 있는지?
---
## 🔗 매핑 전략
### 옵션 1: 바코드 매핑 (37% 커버)
```
MSSQL.BARCODE ↔ PostgreSQL.barcode(?)
```
- 장점: 정확한 매칭
- 단점: 14/38개만 매핑 가능
### 옵션 2: 제품명 유사도 매핑 (Fuzzy Matching)
```python
from fuzzywuzzy import fuzz
# MSSQL: "다이로하트정M(12~22kg)"
# PostgreSQL: "다이로하트 정M 12~22kg" 등 유사 이름 매칭
score = fuzz.partial_ratio(mssql_name, pgsql_name)
if score > 80:
matched = True
```
- 장점: 100% 커버 가능
- 단점: 오매칭 위험
### 옵션 3: 매핑 테이블 생성 (권장) ✅
```sql
-- SQLite에 매핑 테이블 생성
CREATE TABLE drug_image_mapping (
id INTEGER PRIMARY KEY,
mssql_drug_code TEXT UNIQUE, -- MSSQL DrugCode
pgsql_apc TEXT, -- PostgreSQL apc 코드
image_url TEXT, -- 확정된 이미지 URL
verified BOOLEAN DEFAULT 0, -- 수동 검증 여부
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
```
**작업 흐름:**
1. 바코드 매칭 (자동) → 14개 즉시 매핑
2. 제품명 유사도로 후보 추천 → 관리자 확인
3. 수동 매핑 → 나머지 제품
---
## 📊 MSSQL 동물약 바코드 현황 (38개)
### ✅ 바코드 있음 (14개)
| 제품명 | DrugCode | 바코드 |
|--------|----------|--------|
| 가드L(20~40kg) | LB000003570 | 8801244508268 |
| 가드M(10~20kg) | LB000003569 | 8801244508237 |
| 가드S(2~10kg) | LB000003568 | 8801244508220 |
| 하트가드정L(10~20kg) | LB000003564 | 8801244508343 |
| 하트가드정M(5~10kg) | LB000003453 | 8801244508329 |
| 하트가드정S(2.5~5kg) | LB000003452 | 8801244508312 |
| 하트가드정SS(2.5kg이하) | LB000003451 | 8801244508305 |
| 심파리카L(10~25kg) | LB000003634 | 8801244508534 |
| 심파리카M(4~10kg) | LB000003635 | 8801244508435 |
| 안텔민 | S0000001 | 8809989000009 |
| 세레타정(10정) | LB000003146 | 8809720800455 |
| 파라칸L(5kg이상) | LB000003159 | 8809625390914 |
| 파라칸S(5kg이하) | LB000003160 | 8809625390655 |
| 하트칸츄어블(11kg이하) | LB000003696 | 8809625390563 |
### ❌ 바코드 없음 (24개)
| 제품명 | DrugCode |
|--------|----------|
| (동)클리어민50(100정) | LB000003504 |
| 넥스가드L(15~30kg) | LB000003531 |
| 넥스가드xs(2~3.5kg) | LB000003530 |
| 다이로하트정M(12~22kg) | LB000003151 |
| 다이로하트정S(5.6~11kg) | LB000003150 |
| 다이로하트정SS(5.6kg이하) | LB000003149 |
| 레보M(10~20kg) | LB000003161 |
| 레보S(2~10kg) | LB000003162 |
| 밀베마이신A정16mg(대동미어) | LB000003353 |
| 밀베마이신A정24mg(대동미어) | LB000003354 |
| 하트가드정XL(20~40kg) | LB000003545 |
| 안텔민사사(5kg이하) | LB000003158 |
| 안텔민킹(5kg이상) | LB000003157 |
| 캐치펫캅(2.5~7.5kg)/고양이 | LB000003167 |
| 캐치펫L(10~20kg)/개 | LB000003166 |
| 캐치펫M(5~10kg)/개 | LB000003165 |
| 캐치펫S(2.5~5kg)/개 | LB000003164 |
| 캐치펫SS(2.5kg이하/개,고양이가능) | LB000003163 |
| 하트플레이버블정L(23~45kg) | LB000003544 |
| 하트플레이버블정M(12~22kg) | LB000003152 |
| 하트플레이버블정mini(5.6kg이하) | LB000003154 |
| 하트플레이버블정S(5.6~11kg) | LB000003153 |
| 하트플라블러스정M(12~22kg) | LB000003155 |
| 하트플라블러스정S(11kg이하) | LB000003156 |
---
## 🛠️ 구현 단계
### Phase 1: PostgreSQL 조사
- [ ] apc 테이블에 바코드 컬럼 확인
- [ ] 이미지 URL 실제 데이터 샘플 확인
- [ ] 동물약 제품 필터링 방법 확인 (`for_pets = true`?)
### Phase 2: 매핑 테이블 생성
- [ ] SQLite에 `drug_image_mapping` 테이블 생성
- [ ] 바코드 있는 14개 자동 매핑 시도
- [ ] 관리자 페이지에 매핑 UI 추가
### Phase 3: 챗봇 연동
- [ ] AI 응답에서 제품 매칭 시 이미지 URL 포함
- [ ] 프론트엔드에 이미지 표시 (썸네일)
- [ ] 클릭 시 큰 이미지 또는 상세 페이지
---
## 📝 다음 작업
1. **PostgreSQL apc 테이블 샘플 조회**
```sql
SELECT product_name, image_url1, godoimage_url_f
FROM apc
WHERE for_pets = true
LIMIT 10;
```
2. **바코드 컬럼 존재 여부 확인**
```sql
SELECT column_name
FROM information_schema.columns
WHERE table_name = 'apc' AND column_name LIKE '%barcode%';
```
---
## 🗃️ MSSQL 테이블 구조 상세
### CD_GOODS vs CD_BARCODE 관계
```
CD_GOODS (제품 마스터) CD_BARCODE (바코드 마스터)
├── DrugCode (PK) ──────────► DRUGCODE (FK)
├── GoodsName ├── BARCODE (개별 바코드)
├── BARCODE (대표 바코드) ├── TITLECODE (대표 바코드)
├── BaseCode (❌ 비어있음) ├── BASECODE ✅ (100% 있음!)
├── SUNG_CODE ├── SUNG_CODE (성분코드)
└── Saleprice ├── DIK_CODE (의약품통합코드)
├── ETCNAME (제품명)
└── SPLNAME (제조사)
```
**핵심 포인트:**
- `CD_GOODS.BaseCode`는 비어있음 (사용 안 함)
- `CD_BARCODE.BASECODE`에 표준코드 100% 있음!
- 1개 제품(DrugCode)에 여러 바코드 가능 (낱개, 박스 등)
### CD_BARCODE 매핑 키 통계
| 컬럼 | 보유율 | 설명 | 외부 매핑 |
|------|--------|------|-----------|
| `BARCODE` | 100% | 개별 바코드 | ⭐ PostgreSQL 매핑 가능 |
| `BASECODE` | 100% | 표준코드 (식약처) | 인체용만 |
| `TITLECODE` | 100% | 대표 바코드 | |
| `DIK_CODE` | 68.2% | 의약품통합코드 | |
| `SUNG_CODE` | 44.5% | 성분코드 | |
### 동물약 특이사항
```
동물약 38개
├── CD_GOODS에 있음 ✅ (POS_BOON = '010103')
├── CD_BARCODE에 없음 ❌ (인체용 아님)
├── DrugCode가 "LB"로 시작 (로컬/자체 등록)
└── BASECODE 매핑 불가 → PostgreSQL(애니팜) 필요
```
---
## 🔗 PostgreSQL(애니팜) 매핑 전략
### 확인 필요 사항
PostgreSQL `apc` 테이블에서 확인할 컬럼:
```sql
-- 바코드 관련 컬럼 확인
SELECT column_name FROM information_schema.columns
WHERE table_name = 'apc'
AND column_name ILIKE '%barcode%';
-- 코드 관련 컬럼 확인
SELECT column_name FROM information_schema.columns
WHERE table_name = 'apc'
AND (column_name ILIKE '%code%' OR column_name ILIKE '%apc%');
```
### 예상 매핑 키
| MSSQL (CD_GOODS/BARCODE) | PostgreSQL (apc) | 매핑 방식 |
|--------------------------|------------------|-----------|
| `BARCODE` | `barcode`? | 직접 매핑 |
| `GoodsName` | `product_name` | 유사도 매칭 |
| `제조사` | `company_name` | 보조 키 |
---
*작성일: 2025-06-30*
*업데이트: 2025-06-30 - CD_BARCODE 구조 분석 추가*
*프로젝트: pharmacy-pos-qr-system*