加速競品風險查詢
All checks were successful
CD Pipeline / deploy (push) Successful in 1m3s

This commit is contained in:
OoO
2026-05-19 22:55:26 +08:00
parent d88d9b7326
commit 3e66a71c8c
2 changed files with 28 additions and 23 deletions

View File

@@ -329,19 +329,7 @@ def _fetch_top_competitor_risks_uncached(engine, limit: int = 10) -> list[dict]:
limit = max(1, min(int(limit or 10), 50))
sql = text(f"""
WITH latest_momo AS (
SELECT
p.id AS product_id,
p.i_code AS sku,
p.name,
p.category,
pr.price AS momo_price,
ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY pr.timestamp DESC, pr.id DESC) AS rn
FROM products p
JOIN price_records pr ON pr.product_id = p.id
WHERE p.status = 'ACTIVE'
),
valid_competitor AS (
WITH valid_competitor AS (
SELECT DISTINCT ON (cp.sku)
cp.sku,
cp.price AS pchome_price,
@@ -359,21 +347,29 @@ def _fetch_top_competitor_risks_uncached(engine, limit: int = 10) -> list[dict]:
ORDER BY cp.sku, cp.crawled_at DESC NULLS LAST
)
SELECT
lm.sku,
lm.name,
lm.category,
lm.momo_price,
p.i_code AS sku,
p.name,
p.category,
latest_price.momo_price,
vc.pchome_price,
vc.competitor_product_id,
vc.competitor_product_name,
vc.match_score,
vc.crawled_at,
(lm.momo_price - vc.pchome_price) AS gap_amount,
((lm.momo_price - vc.pchome_price) / vc.pchome_price * 100) AS gap_pct
FROM latest_momo lm
JOIN valid_competitor vc ON vc.sku = lm.sku
WHERE lm.rn = 1
AND lm.momo_price > vc.pchome_price * 1.05
(latest_price.momo_price - vc.pchome_price) AS gap_amount,
((latest_price.momo_price - vc.pchome_price) / vc.pchome_price * 100) AS gap_pct
FROM valid_competitor vc
JOIN products p
ON p.i_code = vc.sku
AND p.status = 'ACTIVE'
JOIN LATERAL (
SELECT pr.price AS momo_price
FROM price_records pr
WHERE pr.product_id = p.id
ORDER BY pr.timestamp DESC, pr.id DESC
LIMIT 1
) latest_price ON TRUE
WHERE latest_price.momo_price > vc.pchome_price * 1.05
ORDER BY gap_pct DESC NULLS LAST, gap_amount DESC NULLS LAST
LIMIT :limit
""")

View File

@@ -58,3 +58,12 @@ def test_competitor_ppt_prompt_uses_neutral_ewooc_viewpoint():
assert "待補身份/價格" in source
assert "我方 = PChome" not in source
assert "請以 PChome 視角" not in source
def test_top_competitor_risks_reads_latest_momo_price_after_valid_competitor_filter():
source = (ROOT / "services" / "competitor_intel_repository.py").read_text(encoding="utf-8")
assert "FROM valid_competitor vc" in source
assert "JOIN LATERAL" in source
assert "WHERE pr.product_id = p.id" in source
assert "ROW_NUMBER() OVER (PARTITION BY p.id" not in source.split("def _fetch_top_competitor_risks_uncached", 1)[1].split("def fetch_competitor_comparison_results", 1)[0]