fix(growth): normalize nested marketplace packs
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
Some checks failed
CD Pipeline / deploy (push) Has been cancelled
This commit is contained in:
@@ -3443,6 +3443,7 @@ def test_marketplace_search_terms_prefer_readable_brand_core_spec():
|
||||
|
||||
def test_marketplace_sheet_count_is_structured_for_search_and_identity():
|
||||
from services.marketplace_product_matcher import (
|
||||
build_unit_price_comparison,
|
||||
build_search_terms,
|
||||
parse_product_identity,
|
||||
score_marketplace_match,
|
||||
@@ -3450,15 +3451,21 @@ def test_marketplace_sheet_count_is_structured_for_search_and_identity():
|
||||
|
||||
pchome_name = "GATSBY 潔面濕紙巾超值包42張入"
|
||||
same_pack = "【GATSBY】潔面濕紙巾超值包42張入(2款任選)"
|
||||
multi_pack = "【GATSBY】潔面濕紙巾超值包42張入*4包(4款任選)"
|
||||
different_pack = "【GATSBY】潔面濕紙巾15張入(3款任選)"
|
||||
|
||||
identity = parse_product_identity(pchome_name)
|
||||
multi_pack_identity = parse_product_identity(multi_pack)
|
||||
terms = build_search_terms(pchome_name, max_terms=5)
|
||||
exact = score_marketplace_match(same_pack, pchome_name)
|
||||
normalized = score_marketplace_match(multi_pack, pchome_name)
|
||||
unit_price = build_unit_price_comparison(multi_pack, pchome_name, 495, 199)
|
||||
rejected = score_marketplace_match(different_pack, pchome_name)
|
||||
|
||||
assert (42, "張") in identity.counts
|
||||
assert identity.total_piece_count == 42
|
||||
assert (4, "包") in multi_pack_identity.counts
|
||||
assert multi_pack_identity.total_piece_count == 168
|
||||
assert terms[0] == "gatsby 潔面濕紙巾 42張"
|
||||
assert not any(term in {"gatsby 張入", "張入"} for term in terms)
|
||||
assert exact.hard_veto is False
|
||||
@@ -3467,6 +3474,16 @@ def test_marketplace_sheet_count_is_structured_for_search_and_identity():
|
||||
assert exact.alert_tier == "price_alert_exact"
|
||||
assert exact.spec_score == 1.0
|
||||
assert "spec_name_alignment" in exact.reasons
|
||||
assert normalized.hard_veto is True
|
||||
assert normalized.comparison_mode == "unit_comparable"
|
||||
assert normalized.match_type == "same_product_different_pack"
|
||||
assert normalized.price_basis == "unit_price"
|
||||
assert "count_conflict" in normalized.reasons
|
||||
assert "pack_quantity_difference" in normalized.reasons
|
||||
assert unit_price["comparable"] is True
|
||||
assert unit_price["unit_label"] == "張"
|
||||
assert unit_price["momo_total_quantity"] == 168
|
||||
assert unit_price["competitor_total_quantity"] == 42
|
||||
assert rejected.hard_veto is True
|
||||
assert "count_conflict" in rejected.reasons
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@ def test_independent_verifier_promotes_exact_and_unit_candidates_but_rejects_con
|
||||
assert result["blocked_candidates"][0]["reasons"]
|
||||
|
||||
|
||||
def test_independent_verifier_promotes_exact_sheet_pack_and_blocks_wrong_count():
|
||||
def test_independent_verifier_prefers_exact_sheet_pack_over_unit_candidate():
|
||||
from services.pchome_growth_same_item_reconciliation import (
|
||||
verify_same_item_candidates,
|
||||
)
|
||||
@@ -160,14 +160,63 @@ def test_independent_verifier_promotes_exact_sheet_pack_and_blocks_wrong_count()
|
||||
assert result["selected_candidate_count"] == 1
|
||||
assert result["verified_candidates"][0]["product_id"] == "M-GATSBY-42"
|
||||
assert result["verified_candidates"][0]["auto_compare_type"] == "total_price"
|
||||
rejected = next(
|
||||
item
|
||||
for item in result["blocked_candidates"]
|
||||
if item["source_product_id"] == "M-GATSBY-15"
|
||||
assert result["verified_candidate_count"] == 2
|
||||
assert result["blocked_candidate_count"] == 0
|
||||
|
||||
unit_result = verify_same_item_candidates(
|
||||
[target],
|
||||
[candidates[1]],
|
||||
identity={
|
||||
"trace_id": "trace-gatsby-unit",
|
||||
"run_id": "run-gatsby-unit",
|
||||
"work_item_id": "GROWTH-P0-001-B",
|
||||
},
|
||||
)
|
||||
assert rejected["hard_veto"] is True
|
||||
assert rejected["search_term"] == "gatsby 潔面濕紙巾 42張"
|
||||
assert "count_conflict" in rejected["reasons"]
|
||||
assert unit_result["selected_candidate_count"] == 1
|
||||
unit_candidate = unit_result["verified_candidates"][0]
|
||||
assert unit_candidate["auto_compare_type"] == "unit_price"
|
||||
assert unit_candidate["target_price_basis"] == "unit_price"
|
||||
assert unit_candidate["target_unit_price_comparison"]["comparable"] is True
|
||||
assert unit_candidate["target_unit_price_comparison"]["unit_label"] == "張"
|
||||
|
||||
|
||||
def test_independent_verifier_never_treats_outer_sheet_pack_as_exact_total_price():
|
||||
from services.pchome_growth_same_item_reconciliation import (
|
||||
verify_same_item_candidates,
|
||||
)
|
||||
|
||||
target = _target(
|
||||
"P-GATSBY-42",
|
||||
"GATSBY 潔面濕紙巾超值包42張入",
|
||||
199,
|
||||
1,
|
||||
)
|
||||
result = verify_same_item_candidates(
|
||||
[target],
|
||||
[{
|
||||
"product_id": "M-GATSBY-42-X4",
|
||||
"name": "【GATSBY】潔面濕紙巾超值包42張入*4包(4款任選)",
|
||||
"price": 495,
|
||||
"target_pchome_product_id": "P-GATSBY-42",
|
||||
"target_search_term": "gatsby 潔面濕紙巾 42張",
|
||||
"auto_compare_type": "total_price",
|
||||
}],
|
||||
identity={
|
||||
"trace_id": "trace-gatsby-outer-pack",
|
||||
"run_id": "run-gatsby-outer-pack",
|
||||
"work_item_id": "GROWTH-P0-001-B",
|
||||
},
|
||||
)
|
||||
|
||||
assert result["selected_candidate_count"] == 1
|
||||
candidate = result["verified_candidates"][0]
|
||||
assert candidate["auto_compare_type"] == "unit_price"
|
||||
assert candidate["same_item_reconciliation"]["candidate_claim_drift"] is True
|
||||
assert candidate["target_match_type"] == "same_product_different_pack"
|
||||
assert candidate["target_price_basis"] == "unit_price"
|
||||
assert candidate["target_unit_price_comparison"]["unit_label"] == "張"
|
||||
assert candidate["target_unit_price_comparison"]["momo_total_quantity"] == 168
|
||||
assert candidate["target_unit_price_comparison"]["competitor_total_quantity"] == 42
|
||||
|
||||
|
||||
def test_coverage_post_verifier_requires_exact_source_readback_and_reports_revenue_delta():
|
||||
|
||||
Reference in New Issue
Block a user