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'])
|
@app.route('/api/admin/product-images/crawl-today', methods=['POST'])
|
||||||
def api_crawl_today():
|
def api_crawl_today():
|
||||||
"""오늘 판매 제품 크롤링"""
|
"""특정 날짜 판매 제품 크롤링 (date 파라미터 없으면 오늘)"""
|
||||||
try:
|
try:
|
||||||
from utils.yakkok_crawler import crawl_today_sales
|
from utils.yakkok_crawler import crawl_sales_by_date
|
||||||
result = crawl_today_sales(headless=True)
|
data = request.get_json() or {}
|
||||||
return jsonify({'success': True, 'result': result})
|
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:
|
except Exception as e:
|
||||||
logging.error(f"크롤링 오류: {e}")
|
logging.error(f"크롤링 오류: {e}")
|
||||||
return jsonify({'success': False, 'error': str(e)}), 500
|
return jsonify({'success': False, 'error': str(e)}), 500
|
||||||
|
|||||||
@ -325,8 +325,9 @@
|
|||||||
<header>
|
<header>
|
||||||
<h1>🖼️ 제품 이미지 관리</h1>
|
<h1>🖼️ 제품 이미지 관리</h1>
|
||||||
<div class="actions">
|
<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>
|
||||||
<button class="btn btn-secondary" onclick="openManualCrawl()">
|
<button class="btn btn-secondary" onclick="openManualCrawl()">
|
||||||
➕ 수동 크롤링
|
➕ 수동 크롤링
|
||||||
@ -453,6 +454,10 @@
|
|||||||
|
|
||||||
// 초기 로드
|
// 초기 로드
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
// 오늘 날짜로 기본값 설정
|
||||||
|
const today = new Date().toISOString().split('T')[0];
|
||||||
|
document.getElementById('crawlDate').value = today;
|
||||||
|
|
||||||
loadStats();
|
loadStats();
|
||||||
loadImages();
|
loadImages();
|
||||||
});
|
});
|
||||||
@ -542,14 +547,25 @@
|
|||||||
debounceTimer = setTimeout(loadImages, 300);
|
debounceTimer = setTimeout(loadImages, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function crawlToday() {
|
async function crawlByDate() {
|
||||||
if (!confirm('오늘 판매된 제품 이미지를 크롤링합니다. 진행할까요?')) return;
|
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 {
|
try {
|
||||||
const res = await fetch('/api/admin/product-images/crawl-today', {
|
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();
|
const data = await res.json();
|
||||||
|
|
||||||
|
|||||||
@ -272,8 +272,12 @@ def crawl_products(products, headless=True):
|
|||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
def get_today_sales_products():
|
def get_sales_products(date_str=None):
|
||||||
"""오늘 판매된 제품 목록 조회 (MSSQL)"""
|
"""특정 날짜 판매 제품 목록 조회 (MSSQL)
|
||||||
|
|
||||||
|
Args:
|
||||||
|
date_str: 날짜 문자열 (YYYYMMDD 또는 YYYY-MM-DD), None이면 오늘
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
# 상위 폴더의 db 모듈 import
|
# 상위 폴더의 db 모듈 import
|
||||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
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')
|
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("""
|
query = text("""
|
||||||
SELECT DISTINCT
|
SELECT DISTINCT
|
||||||
COALESCE(NULLIF(G.Barcode, ''),
|
COALESCE(NULLIF(G.Barcode, ''),
|
||||||
@ -294,11 +303,11 @@ def get_today_sales_products():
|
|||||||
ISNULL(G.GoodsName, '알수없음') AS product_name
|
ISNULL(G.GoodsName, '알수없음') AS product_name
|
||||||
FROM SALE_SUB S
|
FROM SALE_SUB S
|
||||||
LEFT JOIN PM_DRUG.dbo.CD_GOODS G ON S.DrugCode = G.DrugCode
|
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
|
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 = []
|
products = []
|
||||||
for row in result:
|
for row in result:
|
||||||
@ -306,7 +315,7 @@ def get_today_sales_products():
|
|||||||
if barcode: # 바코드 있는 것만
|
if barcode: # 바코드 있는 것만
|
||||||
products.append((barcode, row[1], row[2]))
|
products.append((barcode, row[1], row[2]))
|
||||||
|
|
||||||
logger.info(f"[MSSQL] 오늘 판매 품목: {len(products)}개")
|
logger.info(f"[MSSQL] {target_date} 판매 품목: {len(products)}개")
|
||||||
return products
|
return products
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -314,15 +323,29 @@ def get_today_sales_products():
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
def crawl_today_sales(headless=True):
|
def get_today_sales_products():
|
||||||
"""오늘 판매된 제품 이미지 크롤링"""
|
"""오늘 판매된 제품 목록 조회 (하위호환)"""
|
||||||
products = 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:
|
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)
|
return crawl_products(products, headless=headless)
|
||||||
|
|
||||||
|
|
||||||
|
def crawl_today_sales(headless=True):
|
||||||
|
"""오늘 판매된 제품 이미지 크롤링 (하위호환)"""
|
||||||
|
return crawl_sales_by_date(None, headless=headless)
|
||||||
|
|
||||||
|
|
||||||
# CLI 실행
|
# CLI 실행
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import argparse
|
import argparse
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user