feat: 제품 이미지 크롤링에 날짜 선택 기능 추가 - 달력으로 날짜 선택 가능 - 해당 날짜 판매 제품 크롤링
This commit is contained in:
parent
51216c582f
commit
30d95c8579
@ -5767,11 +5767,13 @@ def api_product_image_detail(barcode):
|
||||
|
||||
@app.route('/api/admin/product-images/crawl-today', methods=['POST'])
|
||||
def api_crawl_today():
|
||||
"""오늘 판매 제품 크롤링"""
|
||||
"""특정 날짜 판매 제품 크롤링 (date 파라미터 없으면 오늘)"""
|
||||
try:
|
||||
from utils.yakkok_crawler import crawl_today_sales
|
||||
result = crawl_today_sales(headless=True)
|
||||
return jsonify({'success': True, 'result': result})
|
||||
from utils.yakkok_crawler import crawl_sales_by_date
|
||||
data = request.get_json() or {}
|
||||
date_str = data.get('date') # YYYY-MM-DD 형식
|
||||
result = crawl_sales_by_date(date_str, headless=True)
|
||||
return jsonify({'success': True, 'result': result, 'date': date_str or 'today'})
|
||||
except Exception as e:
|
||||
logging.error(f"크롤링 오류: {e}")
|
||||
return jsonify({'success': False, 'error': str(e)}), 500
|
||||
|
||||
@ -325,8 +325,9 @@
|
||||
<header>
|
||||
<h1>🖼️ 제품 이미지 관리</h1>
|
||||
<div class="actions">
|
||||
<button class="btn btn-primary" onclick="crawlToday()">
|
||||
🔄 오늘 판매 제품 크롤링
|
||||
<input type="date" id="crawlDate" class="filter-select" style="padding: 8px 12px;">
|
||||
<button class="btn btn-primary" onclick="crawlByDate()">
|
||||
🔄 해당일 판매 제품 크롤링
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="openManualCrawl()">
|
||||
➕ 수동 크롤링
|
||||
@ -453,6 +454,10 @@
|
||||
|
||||
// 초기 로드
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// 오늘 날짜로 기본값 설정
|
||||
const today = new Date().toISOString().split('T')[0];
|
||||
document.getElementById('crawlDate').value = today;
|
||||
|
||||
loadStats();
|
||||
loadImages();
|
||||
});
|
||||
@ -542,14 +547,25 @@
|
||||
debounceTimer = setTimeout(loadImages, 300);
|
||||
}
|
||||
|
||||
async function crawlToday() {
|
||||
if (!confirm('오늘 판매된 제품 이미지를 크롤링합니다. 진행할까요?')) return;
|
||||
async function crawlByDate() {
|
||||
const dateInput = document.getElementById('crawlDate').value;
|
||||
if (!dateInput) {
|
||||
showToast('날짜를 선택하세요', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
showToast('크롤링 시작... 잠시 기다려주세요', 'info');
|
||||
const dateStr = dateInput.replace(/-/g, '');
|
||||
const displayDate = `${dateStr.slice(4,6)}/${dateStr.slice(6,8)}`;
|
||||
|
||||
if (!confirm(`${displayDate} 판매 제품 이미지를 크롤링합니다. 진행할까요?`)) return;
|
||||
|
||||
showToast(`${displayDate} 크롤링 시작... 잠시 기다려주세요`, 'info');
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/admin/product-images/crawl-today', {
|
||||
method: 'POST'
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ date: dateInput })
|
||||
});
|
||||
const data = await res.json();
|
||||
|
||||
|
||||
@ -272,8 +272,12 @@ def crawl_products(products, headless=True):
|
||||
return results
|
||||
|
||||
|
||||
def get_today_sales_products():
|
||||
"""오늘 판매된 제품 목록 조회 (MSSQL)"""
|
||||
def get_sales_products(date_str=None):
|
||||
"""특정 날짜 판매 제품 목록 조회 (MSSQL)
|
||||
|
||||
Args:
|
||||
date_str: 날짜 문자열 (YYYYMMDD 또는 YYYY-MM-DD), None이면 오늘
|
||||
"""
|
||||
try:
|
||||
# 상위 폴더의 db 모듈 import
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||
@ -282,9 +286,14 @@ def get_today_sales_products():
|
||||
|
||||
session = db_manager.get_session('PM_PRES')
|
||||
|
||||
today = datetime.now().strftime('%Y%m%d')
|
||||
# 날짜 처리
|
||||
if date_str:
|
||||
# YYYY-MM-DD -> YYYYMMDD 변환
|
||||
target_date = date_str.replace('-', '')
|
||||
else:
|
||||
target_date = datetime.now().strftime('%Y%m%d')
|
||||
|
||||
# 오늘 판매된 품목 조회 (중복 제거)
|
||||
# 해당 날짜 판매된 품목 조회 (중복 제거)
|
||||
query = text("""
|
||||
SELECT DISTINCT
|
||||
COALESCE(NULLIF(G.Barcode, ''),
|
||||
@ -294,11 +303,11 @@ def get_today_sales_products():
|
||||
ISNULL(G.GoodsName, '알수없음') AS product_name
|
||||
FROM SALE_SUB S
|
||||
LEFT JOIN PM_DRUG.dbo.CD_GOODS G ON S.DrugCode = G.DrugCode
|
||||
WHERE S.SL_NO_order LIKE :today_pattern
|
||||
WHERE S.SL_NO_order LIKE :date_pattern
|
||||
AND S.DrugCode IS NOT NULL
|
||||
""")
|
||||
|
||||
result = session.execute(query, {'today_pattern': f'{today}%'}).fetchall()
|
||||
result = session.execute(query, {'date_pattern': f'{target_date}%'}).fetchall()
|
||||
|
||||
products = []
|
||||
for row in result:
|
||||
@ -306,7 +315,7 @@ def get_today_sales_products():
|
||||
if barcode: # 바코드 있는 것만
|
||||
products.append((barcode, row[1], row[2]))
|
||||
|
||||
logger.info(f"[MSSQL] 오늘 판매 품목: {len(products)}개")
|
||||
logger.info(f"[MSSQL] {target_date} 판매 품목: {len(products)}개")
|
||||
return products
|
||||
|
||||
except Exception as e:
|
||||
@ -314,15 +323,29 @@ def get_today_sales_products():
|
||||
return []
|
||||
|
||||
|
||||
def crawl_today_sales(headless=True):
|
||||
"""오늘 판매된 제품 이미지 크롤링"""
|
||||
products = get_today_sales_products()
|
||||
def get_today_sales_products():
|
||||
"""오늘 판매된 제품 목록 조회 (하위호환)"""
|
||||
return get_sales_products(None)
|
||||
|
||||
|
||||
def crawl_sales_by_date(date_str=None, headless=True):
|
||||
"""특정 날짜 판매 제품 이미지 크롤링
|
||||
|
||||
Args:
|
||||
date_str: 날짜 문자열 (YYYYMMDD 또는 YYYY-MM-DD), None이면 오늘
|
||||
"""
|
||||
products = get_sales_products(date_str)
|
||||
if not products:
|
||||
return {'total': 0, 'success': 0, 'failed': 0, 'skipped': 0, 'message': '오늘 판매 내역 없음'}
|
||||
return {'total': 0, 'success': 0, 'failed': 0, 'skipped': 0, 'message': '해당일 판매 내역 없음'}
|
||||
|
||||
return crawl_products(products, headless=headless)
|
||||
|
||||
|
||||
def crawl_today_sales(headless=True):
|
||||
"""오늘 판매된 제품 이미지 크롤링 (하위호환)"""
|
||||
return crawl_sales_by_date(None, headless=headless)
|
||||
|
||||
|
||||
# CLI 실행
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
|
||||
Loading…
Reference in New Issue
Block a user