feat(order): 지오영/수인 선택적 주문 + 장바구니 보존 기능

- internal_code DB 저장 → 프론트에서 선택한 제품 그대로 주문
- 기존 장바구니 백업/복구로 사용자 장바구니 보존
- 수인약품 submit_order() 수정 (체크박스 제외 방식)
- 테스트 파일 정리 및 문서 추가
This commit is contained in:
thug0bin
2026-03-06 23:26:44 +09:00
parent f48e657e12
commit a672c7a2a0
79 changed files with 4851 additions and 2672 deletions

View File

@@ -0,0 +1,136 @@
# -*- coding: utf-8 -*-
"""
지오영 "전체삭제" 버튼 분석 - Playwright로 실제 버튼 클릭 시 API 확인
"""
import asyncio
import os
from dotenv import load_dotenv
load_dotenv(r'c:\Users\청춘약국\source\pharmacy-wholesale-api\.env')
async def analyze_delete_all():
from playwright.async_api import async_playwright
username = os.getenv('GEOYOUNG_USER_ID')
password = os.getenv('GEOYOUNG_PASSWORD')
if not username or not password:
print("❌ GEOYOUNG_USER_ID, GEOYOUNG_PASSWORD 환경변수 필요")
return
print("=" * 60)
print("지오영 '전체삭제' 버튼 분석")
print("=" * 60)
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False) # 보이게
page = await browser.new_page()
# 네트워크 요청 감시
requests_log = []
def log_request(request):
if 'Cart' in request.url or 'cart' in request.url or 'del' in request.url.lower():
requests_log.append({
'method': request.method,
'url': request.url,
'post_data': request.post_data
})
print(f"🔗 {request.method} {request.url}")
if request.post_data:
print(f" POST data: {request.post_data}")
page.on('request', log_request)
# 1. 로그인
print("\n1⃣ 로그인 중...")
await page.goto("https://gwn.geoweb.kr/Member/Login")
await page.fill('input[type="text"]', username)
await page.fill('input[type="password"]', password)
await page.click('button[type="submit"], input[type="submit"], .btn-login')
await page.wait_for_load_state('networkidle', timeout=15000)
print("✅ 로그인 완료")
# 2. 주문 페이지로 이동 (장바구니 표시됨)
print("\n2⃣ 주문 페이지로 이동...")
await page.goto("https://gwn.geoweb.kr/Home/Order")
await page.wait_for_load_state('networkidle', timeout=15000)
# 3. 장바구니 확인
print("\n3⃣ 장바구니 확인...")
await asyncio.sleep(2)
# 스크린샷
await page.screenshot(path='geo_cart_before.png')
print("📸 스크린샷 저장: geo_cart_before.png")
# 4. "전체삭제" 버튼 찾기
print("\n4'전체삭제' 버튼 찾기...")
# 가능한 선택자들
selectors = [
'button:has-text("전체삭제")',
'a:has-text("전체삭제")',
'.btn-del-all',
'#btnDelAll',
'[onclick*="delAll"]',
'button:has-text("전체 삭제")',
'button:has-text("삭제")',
]
delete_btn = None
for sel in selectors:
try:
btn = page.locator(sel).first
if await btn.count() > 0:
print(f" ✅ 버튼 발견: {sel}")
# 버튼의 HTML 확인
btn_html = await btn.evaluate('el => el.outerHTML')
print(f" HTML: {btn_html[:200]}...")
delete_btn = btn
break
except:
pass
if not delete_btn:
print(" ❌ 전체삭제 버튼을 찾지 못함")
# 페이지 HTML에서 삭제 관련 요소 검색
html = await page.content()
if '전체삭제' in html or 'delAll' in html:
print(" ⚠️ 페이지에 관련 텍스트는 있음. 수동 확인 필요")
await browser.close()
return
# 5. 버튼 클릭 (네트워크 요청 감시)
print("\n5'전체삭제' 버튼 클릭...")
requests_log.clear()
try:
await delete_btn.click()
await asyncio.sleep(2)
# confirm 다이얼로그 처리
page.on('dialog', lambda dialog: asyncio.create_task(dialog.accept()))
await page.wait_for_load_state('networkidle', timeout=5000)
except Exception as e:
print(f" ⚠️ 클릭 중 오류: {e}")
# 6. 캡처된 요청 출력
print("\n6⃣ 캡처된 API 요청:")
for req in requests_log:
print(f" 📤 {req['method']} {req['url']}")
if req['post_data']:
print(f" Body: {req['post_data']}")
# 스크린샷
await page.screenshot(path='geo_cart_after.png')
print("\n📸 스크린샷 저장: geo_cart_after.png")
print("\n잠시 대기 (확인용)...")
await asyncio.sleep(5)
await browser.close()
print("\n✅ 완료")
if __name__ == "__main__":
asyncio.run(analyze_delete_all())