fix: pick best targeted momo offer per pchome item
All checks were successful
CD Pipeline / deploy (push) Successful in 1m4s
All checks were successful
CD Pipeline / deploy (push) Successful in 1m4s
This commit is contained in:
@@ -712,6 +712,31 @@ def _targeted_candidate_needs_review(candidate: dict[str, Any]) -> bool:
|
||||
return bool(reasons & review_reason_markers)
|
||||
|
||||
|
||||
def _targeted_candidate_sync_rank(candidate: dict[str, Any]) -> tuple[float, float, float, float]:
|
||||
"""同一個 PChome 商品有多個候選時,挑最適合營運判斷的一筆。"""
|
||||
auto_type = _targeted_candidate_auto_type(candidate)
|
||||
type_rank = 3.0 if auto_type == "total_price" else 2.0 if auto_type == "unit_price" else 0.0
|
||||
try:
|
||||
match_score = float(candidate.get("target_match_score") or 0.0)
|
||||
except (TypeError, ValueError):
|
||||
match_score = 0.0
|
||||
|
||||
unit_price_comparison = (
|
||||
candidate.get("target_unit_price_comparison")
|
||||
if isinstance(candidate.get("target_unit_price_comparison"), dict)
|
||||
else {}
|
||||
)
|
||||
momo_total = _to_float(unit_price_comparison.get("momo_total_quantity"))
|
||||
pchome_total = _to_float(unit_price_comparison.get("competitor_total_quantity"))
|
||||
quantity_delta = 999999.0
|
||||
same_quantity = 0.0
|
||||
if momo_total > 0 and pchome_total > 0:
|
||||
quantity_delta = abs(momo_total - pchome_total)
|
||||
same_quantity = 1.0 if quantity_delta <= 0.0001 else 0.0
|
||||
|
||||
return (type_rank, same_quantity, -quantity_delta, match_score)
|
||||
|
||||
|
||||
def _targeted_candidate_to_external_offer(
|
||||
candidate: dict[str, Any],
|
||||
*,
|
||||
@@ -839,7 +864,7 @@ def sync_targeted_momo_candidates_to_external_offers(
|
||||
|
||||
_ensure_external_market_source_seeds(conn)
|
||||
base_observed_at = datetime.now()
|
||||
offers: list[dict[str, Any]] = []
|
||||
ranked_offers: list[tuple[dict[str, Any], tuple[float, float, float, float]]] = []
|
||||
skipped_reasons: dict[str, int] = {}
|
||||
for index, candidate in enumerate(candidates):
|
||||
offer, reason = _targeted_candidate_to_external_offer(
|
||||
@@ -847,9 +872,16 @@ def sync_targeted_momo_candidates_to_external_offers(
|
||||
observed_at=base_observed_at + timedelta(microseconds=index),
|
||||
)
|
||||
if offer:
|
||||
offers.append(offer)
|
||||
ranked_offers.append((offer, _targeted_candidate_sync_rank(candidate)))
|
||||
else:
|
||||
skipped_reasons[reason] = skipped_reasons.get(reason, 0) + 1
|
||||
selected_by_pchome: dict[str, tuple[dict[str, Any], tuple[float, float, float, float]]] = {}
|
||||
for offer, rank in ranked_offers:
|
||||
key = str(offer.get("pchome_product_id") or offer.get("source_offer_key") or "").strip()
|
||||
existing = selected_by_pchome.get(key)
|
||||
if existing is None or rank > existing[1]:
|
||||
selected_by_pchome[key] = (offer, rank)
|
||||
offers = [offer for offer, _ in selected_by_pchome.values()]
|
||||
|
||||
if not dry_run:
|
||||
for offer in offers:
|
||||
|
||||
Reference in New Issue
Block a user