feat: persist targeted momo review candidates
Some checks failed
CD Pipeline / deploy (push) Failing after 35s

This commit is contained in:
OoO
2026-06-19 02:43:34 +08:00
parent bed4488a72
commit 4b0a331d98
8 changed files with 291 additions and 3 deletions

View File

@@ -361,6 +361,74 @@ def test_sync_targeted_momo_candidates_skips_total_price_identity_review(monkeyp
assert count == 0
def test_sync_targeted_momo_review_candidates_writes_needs_review_offer(monkeypatch):
from services import external_market_offer_service as service
stale_marks = []
monkeypatch.setattr(service, "mark_pchome_growth_cache_stale", lambda: stale_marks.append(True))
engine = create_engine("sqlite:///:memory:")
_seed_external_offer_sync_tables(engine)
payload = service.sync_targeted_momo_review_candidates_to_external_offers(engine, [
{
"product_id": "14917079",
"name": "【cle de peau 肌膚之鑰】光采柔焦蜜粉 24g (國際航空版)",
"price": 2618,
"target_pchome_product_id": "PCH-CDP",
"target_pchome_name": "cle de peau 光采柔焦蜜粉 24g #1",
"target_pchome_price": 2790,
"target_match_score": 1.0,
"auto_compare_type": "manual_review",
"target_price_basis": "none",
"target_alert_tier": "identity_review",
"target_match_type": "exact",
"target_match_reasons": ["variant_selection_review", "strong_exact_spec_match"],
"target_comparison_mode": "exact_identity",
"target_gap_pct": -6.16,
},
{
"product_id": "LOW-SCORE",
"name": "低分候選",
"price": 100,
"target_pchome_product_id": "PCH-LOW",
"target_match_score": 0.4,
"target_alert_tier": "identity_review",
},
])
assert payload["success"] is True
assert payload["status"] == "synced"
assert payload["candidate_count"] == 2
assert payload["written_count"] == 1
assert payload["skipped_reasons"] == {"人工確認候選分數過低": 1}
with engine.connect() as conn:
row = conn.execute(text("""
SELECT source_product_id, price, pchome_product_id, match_status,
quality_score, data_quality_status, ingestion_method,
raw_payload_json
FROM external_offers
""")).mappings().one()
readiness = service.build_external_source_readiness(engine)
raw_payload = __import__("json").loads(row["raw_payload_json"])
assert row["source_product_id"] == "14917079"
assert row["price"] == 2618
assert row["pchome_product_id"] == "PCH-CDP"
assert row["match_status"] == "needs_review"
assert row["quality_score"] == 100
assert row["data_quality_status"] == "needs_review"
assert row["ingestion_method"] == "targeted_momo_review"
assert raw_payload["review_state"] == "needs_review"
assert raw_payload["price_basis"] == "none"
assert raw_payload["alert_tier"] == "identity_review"
assert "needs_review" in raw_payload["tags"]
assert readiness["review_offer_count"] == 1
assert stale_marks == [True]
def test_sync_targeted_momo_candidates_keeps_best_unit_quantity_match(monkeypatch):
from services import external_market_offer_service as service

View File

@@ -307,12 +307,21 @@ def test_pchome_growth_momo_backfill_service_targets_unmapped_high_sales_items()
"unit_price_count": 1,
}
def fake_sync_review(engine, candidates):
captured["review_sync_candidates"] = candidates
return {
"success": True,
"status": "synced",
"written_count": len(candidates),
}
payload = run_pchome_growth_momo_backfill(
FakeEngine(),
limit=2,
build_payload_func=fake_build_payload,
search_func=fake_search,
sync_func=fake_sync,
sync_review_func=fake_sync_review,
)
assert payload["success"] is True
@@ -321,10 +330,12 @@ def test_pchome_growth_momo_backfill_service_targets_unmapped_high_sales_items()
assert payload["data"]["auto_compare_count"] == 2
assert payload["data"]["review_count"] == 1
assert payload["data"]["external_offer_sync"]["written_count"] == 2
assert payload["data"]["review_candidate_sync"]["written_count"] == 1
assert payload["data"]["after_stats"]["mapping_rate"] == 66.7
assert [item["product_id"] for item in captured["targets"]] == ["PCH-NEEDS-1", "PCH-NEEDS-2"]
assert [item["price"] for item in captured["targets"]] == [920, 760]
assert [item["product_id"] for item in captured["sync_candidates"]] == ["MOMO-AUTO", "MOMO-UNIT"]
assert [item["product_id"] for item in captured["review_sync_candidates"]] == ["MOMO-REVIEW"]
assert captured["search_limit"] == 2