feat: persist targeted momo review candidates
Some checks failed
CD Pipeline / deploy (push) Failing after 35s
Some checks failed
CD Pipeline / deploy (push) Failing after 35s
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user