Commit 90ea36b3 authored by Vũ Hoàng Anh's avatar Vũ Hoàng Anh

feat(api): add dedicated n8n product endpoint with description, update promo tool

parent 37c109a3
...@@ -33,21 +33,30 @@ async def canifa_get_promotions(check_date: str = None) -> str: ...@@ -33,21 +33,30 @@ async def canifa_get_promotions(check_date: str = None) -> str:
target_date = check_date target_date = check_date
if not target_date: if not target_date:
target_date = datetime.now().strftime("%Y-%m-%d") target_date = datetime.now().strftime("%Y-%m-%d")
logger.info(f"🎁 [Promotion Search] Checking for date: {target_date}") logger.info(f"🎁 [Promotion Search] Checking for date: {target_date}")
try: try:
sql = f""" sql = f"""
SELECT SELECT
name, name,
description, description,
description_full, description_full,
from_date, from_date,
to_date to_date,
applied_channel
FROM shared_source.chatbot_rsa_salerule_with_text_embedding FROM shared_source.chatbot_rsa_salerule_with_text_embedding
WHERE '{target_date}' >= DATE(from_date) WHERE '{target_date}' >= DATE(from_date)
AND '{target_date}' <= DATE(to_date) AND '{target_date}' <= DATE(to_date)
ORDER BY to_date ASC ORDER BY
CASE applied_channel
WHEN 'only_online' THEN 0
WHEN 'both' THEN 1
WHEN 'unknown' THEN 2
WHEN 'only_offline' THEN 3
ELSE 4
END,
to_date ASC
LIMIT 20 LIMIT 20
""" """
...@@ -57,6 +66,14 @@ async def canifa_get_promotions(check_date: str = None) -> str: ...@@ -57,6 +66,14 @@ async def canifa_get_promotions(check_date: str = None) -> str:
if not results: if not results:
return f"Hiện tại (ngày {target_date}) không có chương trình khuyến mãi nào đang diễn ra trên hệ thống." return f"Hiện tại (ngày {target_date}) không có chương trình khuyến mãi nào đang diễn ra trên hệ thống."
# Map channel values to Vietnamese labels
channel_labels = {
"only_online": "Online (Web/App)",
"both": "Online + Cửa hàng",
"only_offline": "Chỉ tại cửa hàng",
"unknown": "Chưa phân loại kênh",
}
lines = [f"Tìm thấy {len(results)} chương trình khuyến mãi đang diễn ra (ngày {target_date}):\n"] lines = [f"Tìm thấy {len(results)} chương trình khuyến mãi đang diễn ra (ngày {target_date}):\n"]
for i, res in enumerate(results, 1): for i, res in enumerate(results, 1):
name = res.get("name", "CTKM") name = res.get("name", "CTKM")
...@@ -64,19 +81,25 @@ async def canifa_get_promotions(check_date: str = None) -> str: ...@@ -64,19 +81,25 @@ async def canifa_get_promotions(check_date: str = None) -> str:
desc_full = res.get("description_full", "") desc_full = res.get("description_full", "")
f_date = res.get("from_date", "") f_date = res.get("from_date", "")
t_date = res.get("to_date", "") t_date = res.get("to_date", "")
channel = res.get("applied_channel", "unknown")
channel_label = channel_labels.get(channel, channel)
# Use description_full if available and longer, else description # Use description_full if available and longer, else description
content = desc_full if desc_full and len(str(desc_full)) > len(str(desc)) else desc content = desc_full if desc_full and len(str(desc_full)) > len(str(desc)) else desc
lines.append( lines.append(
f"[CTKM {i}]\n" f"[CTKM {i}]\n"
f"Tên: {name}\n" f"Tên: {name}\n"
f"Kênh áp dụng: {channel_label}\n"
f"Nội dung: {content}\n" f"Nội dung: {content}\n"
f"Thời gian: {f_date} đến {t_date}\n" f"Thời gian: {f_date} đến {t_date}\n"
) )
lines.append( lines.append(
"LƯU Ý: Trình bày NỘI DUNG ưu đãi chi tiết cho khách. " "LƯU Ý QUAN TRỌNG VỀ KÊNH ÁP DỤNG:\n"
"- Mặc định: ƯU TIÊN trình bày các CTKM 'Online (Web/App)' và 'Online + Cửa hàng' TRƯỚC.\n"
"- Chỉ trình bày CTKM 'Chỉ tại cửa hàng' khi khách hỏi CỤ THỂ về ưu đãi tại cửa hàng/offline.\n"
"- Trình bày NỘI DUNG ưu đãi chi tiết cho khách. "
"Nếu nội dung chỉ ghi địa điểm áp dụng mà KHÔNG ghi cụ thể giảm bao nhiêu %, " "Nếu nội dung chỉ ghi địa điểm áp dụng mà KHÔNG ghi cụ thể giảm bao nhiêu %, "
"hãy trình bày tên chương trình + thời gian + nội dung có sẵn, " "hãy trình bày tên chương trình + thời gian + nội dung có sẵn, "
"rồi hướng dẫn khách liên hệ hotline 1800 6061 hoặc vào canifa.com để xem chi tiết ưu đãi." "rồi hướng dẫn khách liên hệ hotline 1800 6061 hoặc vào canifa.com để xem chi tiết ưu đãi."
......
import logging
from fastapi import APIRouter, HTTPException
logger = logging.getLogger(__name__)
router = APIRouter()
@router.get("/api/agent/n8n/products", summary="N8N Specific: Get Sample Products")
async def n8n_get_sample_products(limit: int = 10):
"""
API DÀNH RIÊNG CHO N8N để lấy danh sách sản phẩm thực tế làm data cho AI sinh câu hỏi.
- Code hoàn toàn tách biệt khỏi hệ thống cũ (không đụng vào logic SearchItem/Embedding)
- Trả về danh sách ngẫu nhiên từ StarRocks
"""
try:
from common.starrocks_connection import get_db_connection
db = get_db_connection()
# Lấy random các sản phẩm có hiển thị trên web, có giá
query = f"""
SELECT
magento_ref_code,
product_name,
description_text,
original_price,
sale_price,
master_color,
gender_by_product,
product_web_url,
product_image_url_thumbnail
FROM shared_source.magento_product_dimension_with_text_embedding
WHERE sale_price > 0 AND quantity_sold > 0
ORDER BY rand()
LIMIT {limit}
"""
products = await db.execute_query_async(query)
return {
"status": "success",
"total": len(products),
"products": products
}
except Exception as e:
logger.error(f"❌ Error in N8N Dedicated Product Fetch API: {e!s}", exc_info=True)
raise HTTPException(status_code=500, detail=f"N8N API Error: {e!s}")
...@@ -15,6 +15,7 @@ from api.mock_api_route import router as mock_router ...@@ -15,6 +15,7 @@ from api.mock_api_route import router as mock_router
from api.prompt_route import router as prompt_router from api.prompt_route import router as prompt_router
from api.stock_route import router as stock_router from api.stock_route import router as stock_router
from api.tool_prompt_route import router as tool_prompt_router from api.tool_prompt_route import router as tool_prompt_router
from api.n8n_api_route import router as n8n_router
from common.cache import redis_cache from common.cache import redis_cache
from common.middleware import middleware_manager from common.middleware import middleware_manager
from config import PORT from config import PORT
...@@ -94,6 +95,7 @@ app.include_router(prompt_router) ...@@ -94,6 +95,7 @@ app.include_router(prompt_router)
app.include_router(tool_prompt_router) # Register new router app.include_router(tool_prompt_router) # Register new router
app.include_router(mock_router) app.include_router(mock_router)
app.include_router(stock_router) app.include_router(stock_router)
app.include_router(n8n_router)
if __name__ == "__main__": if __name__ == "__main__":
......
import requests
import json
import time
def test_api(limit):
url = f'http://localhost:5000/api/agent/n8n/products?limit={limit}'
print(f'\n--- Testing API with limit={limit} ---')
print(f'URL: {url}')
start_time = time.time()
try:
response = requests.get(url, timeout=10)
elapsed = time.time() - start_time
print(f'Status Code : {response.status_code}')
print(f'Time Taken : {elapsed:.3f} seconds')
if response.status_code == 200:
data = response.json()
print(f'Status Field: {data.get("status")}')
print(f'Total Field : {data.get("total")}')
products = data.get("products", [])
print(f'Products returned: {len(products)}')
if len(products) > 0:
print('\nSample Product (first item):')
print(json.dumps(products[0], indent=2, ensure_ascii=False))
else:
print('WARNING: No products returned. Is the database empty or filter too strict?')
else:
print('ERROR Response:')
try:
print(json.dumps(response.json(), indent=2, ensure_ascii=False))
except:
print(response.text)
except Exception as e:
print(f'Request failed: {e}')
if __name__ == '__main__':
test_api(3)
test_api(10)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment