Files
ewoooc/tests/test_marketplace_product_matcher.py
OoO 9d84cbfd43
All checks were successful
CD Pipeline / deploy (push) Successful in 1m8s
feat: deepen pchome momo backfill guardrails
2026-06-19 00:41:20 +08:00

3677 lines
154 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from sqlalchemy import create_engine, text
def test_marketplace_matcher_accepts_same_product_identity():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"理膚寶水 B5 修復霜 40ml",
"理膚寶水 全面修復霜 B5 40ml",
momo_price=699,
competitor_price=679,
)
assert diagnostics.score >= 0.9
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "spec_match" in diagnostics.tags
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "match_type_exact" in diagnostics.tags
def test_marketplace_matcher_normalizes_drw_u_alias_for_exact_identity():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【DR.WU 達爾膚】玻尿酸保濕精華乳50ML",
"DR.WU 玻尿酸保濕精華乳50ML",
momo_price=1200,
competitor_price=1180,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "brand_match" in diagnostics.tags
def test_marketplace_matcher_rejects_brand_conflict_even_when_volume_matches():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【蘭蔻】官方直營 玫瑰霜60ml+玫瑰精露150ml",
"LOREAL Paris 巴黎萊雅 金致臻顏花蜜奢養膠原輕盈乳霜_60ml",
momo_price=18765,
competitor_price=1249,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "brand_conflict" in diagnostics.reasons
def test_marketplace_matcher_rejects_volume_conflict_for_same_brand():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【CLARINS 克蘭詩】黃金亮眼萃20mlX2囤貨組",
"【CLARINS克蘭詩】黃金雙萃精華 75ml",
momo_price=4500,
competitor_price=3549,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "volume_conflict" in diagnostics.reasons
def test_marketplace_matcher_handles_bundle_piece_count():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Relove】馬甲纖纖飲-莓果風味X3盒 共72包",
"【3入超值組】Relove 馬甲纖纖飲 24包/7克",
momo_price=4590,
competitor_price=4590,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_accepts_strong_model_line_without_specs():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Stadler Form】Sophie 無線香氛水氧機 水氧機 香氛機",
"【瑞士Stadler Form】無線香氛水氧機 露營燈造型 Sophie",
momo_price=3780,
competitor_price=3980,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "strong_product_line_match" in diagnostics.reasons
def test_marketplace_matcher_rejects_bundle_to_single_even_when_brand_matches():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NARS】小白餅閨蜜分享組(裸光蜜粉餅/定妝蜜粉)",
"【NARS】裸光蜜粉餅(小白餅) 10g",
momo_price=3300,
competitor_price=1099,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "bundle_offer_conflict" in diagnostics.reasons
assert diagnostics.comparison_mode == "not_comparable"
def test_marketplace_matcher_marks_bundle_single_as_unit_comparable_not_exact():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"理膚寶水 B5 全面修復霜 40ml x2 超值組",
"理膚寶水 全面修復霜 B5 40ml",
momo_price=1199,
competitor_price=679,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "unit_comparable"
assert diagnostics.match_type == "same_product_different_pack"
assert diagnostics.price_basis == "unit_price"
assert diagnostics.alert_tier == "unit_price_review"
assert "unit_comparable" in diagnostics.reasons
assert "comparison_unit_comparable" in diagnostics.tags
def test_marketplace_matcher_suppresses_same_line_variant_price_alert():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Dashing Diva】時尚潮流美甲片 月影柔霧",
"Dashing Diva 時尚潮流美甲片 銀絲柔彩 30片",
momo_price=399,
competitor_price=399,
)
assert diagnostics.match_type == "no_match"
assert diagnostics.price_basis == "none"
assert diagnostics.alert_tier == "suppress"
assert "variant_descriptor_conflict" in diagnostics.reasons
def test_unit_price_comparison_builds_normalized_evidence():
from services.marketplace_product_matcher import build_unit_price_comparison
comparison = build_unit_price_comparison(
"理膚寶水 B5 全面修復霜 40ml x2 超值組",
"理膚寶水 全面修復霜 B5 40ml",
momo_price=1199,
competitor_price=679,
)
assert comparison["comparable"] is True
assert comparison["unit_label"] == "ml"
assert comparison["momo_total_quantity"] == 80
assert comparison["competitor_total_quantity"] == 40
assert comparison["momo_unit_price"] == 14.9875
assert comparison["competitor_unit_price"] == 16.975
assert comparison["unit_gap_pct"] < 0
def test_marketplace_matcher_routes_same_base_different_piece_pack_to_unit_comparable():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【日本Beauty Foot】去角質足膜25mlx2枚入 5入組(一般尺寸、大尺寸可選)",
"【日本Beauty Foot 】煥膚足膜(25ml*2枚入)四入組",
momo_price=1290,
competitor_price=989,
)
assert diagnostics.comparison_mode == "unit_comparable"
assert diagnostics.match_type == "same_product_different_pack"
assert diagnostics.price_basis == "unit_price"
assert "pack_quantity_difference" in diagnostics.reasons
assert "unit_comparable" in diagnostics.reasons
def test_marketplace_matcher_does_not_unit_compare_multi_component_set():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【蘭蔻】官方直營 玫瑰霜60ml+玫瑰精露150ml",
"【蘭蔻】絕對完美玫瑰霜 60ml",
momo_price=18765,
competitor_price=5349,
)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "unit_comparable" not in diagnostics.reasons
comparison = score_marketplace_match(
"【蘭蔻】官方直營 玫瑰霜60ml+玫瑰精露150ml",
"【蘭蔻】絕對完美玫瑰霜 60ml",
momo_price=18765,
competitor_price=5349,
)
assert comparison.comparison_mode == "not_comparable"
def test_marketplace_matcher_does_not_promote_wide_price_refill_candidate():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【蘭蔻】官方直營 絕對完美永生玫瑰逆齡乳霜60ml補充瓶",
"LANCOME蘭蔻 絕對完美永生玫瑰逆齡乳霜 60ml",
momo_price=11205,
competitor_price=5349,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "refill_pack_conflict" in diagnostics.reasons
assert "strong_product_line_match" not in diagnostics.reasons
def test_marketplace_matcher_rejects_partial_overlap_in_multi_spec_set():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【蘭蔻】玫瑰霜60ml+玫瑰精露150ml",
"【蘭蔻】玫瑰霜60ml+玫瑰精露20ml",
momo_price=18765,
competitor_price=7999,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "volume_conflict" in diagnostics.reasons
assert diagnostics.comparison_mode == "not_comparable"
def test_marketplace_matcher_rejects_dosage_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"品牌 葉黃素 10mg 60錠",
"品牌 葉黃素 20mg 60錠",
momo_price=990,
competitor_price=890,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "dosage_conflict" in diagnostics.reasons
def test_marketplace_matcher_rejects_product_type_conflict_even_when_line_matches():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"理膚寶水 MelaB3 淡斑精華 30ml",
"理膚寶水 MelaB3 淡斑化妝水 30ml",
momo_price=1280,
competitor_price=1180,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "type_conflict" in diagnostics.reasons
assert diagnostics.comparison_mode == "not_comparable"
def test_marketplace_matcher_rejects_foundation_stick_vs_foundation_liquid():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【蘭蔻】零粉感超持久粉底棒9.5g",
"【LANCOME 蘭蔻】零粉感超持久粉底 30ml",
momo_price=1620,
competitor_price=1580,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "type_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_nivea_deodorant_spray_identity():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NIVEA 妮維雅】男士 止汗爽身噴霧 無印乾爽-清新海洋",
"NIVEA 妮維雅 男士止汗爽身噴霧 無印乾爽-清新海洋150ml",
momo_price=159,
competitor_price=169,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_promotes_nivea_deodorant_lotion_noise_variants():
from services.marketplace_product_matcher import build_search_terms, score_marketplace_match
momo_name = "【NIVEA 妮維雅】德國妮維雅 止汗爽身乳液50ml(無印止汗滾珠)"
diagnostics = score_marketplace_match(
momo_name,
"NIVEA 妮維雅 止汗爽身乳液 50ml",
momo_price=149,
competitor_price=169,
)
terms = build_search_terms(momo_name, max_terms=5)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert terms[0] == "妮維雅 止汗爽身乳液 50ml"
assert "德國妮維雅" not in " ".join(terms[:3])
assert "無印止汗滾珠" not in " ".join(terms[:3])
def test_marketplace_matcher_promotes_packaging_variant_for_same_nars_powder():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NARS】官方直營 裸光蜜粉餅(璀璨奢金限定版/星沙金小白餅)",
"【NARS】裸光蜜粉餅(小白餅) 10g",
momo_price=1050,
competitor_price=1050,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_packaging_variant" in diagnostics.reasons
def test_marketplace_matcher_promotes_private_wash_same_identity():
from services.marketplace_product_matcher import score_marketplace_match
summer = score_marketplace_match(
"【Summers Eve 舒摩兒】浴潔露237ml 單入任選(私密清潔 經典防護王)",
"eve舒摩兒 賦活美學浴潔露-全肌防護 237ml",
momo_price=441,
competitor_price=441,
)
femfresh = score_marketplace_match(
"【femfresh 芳芯】弱酸性植萃複方溫和潤澤護理私密肌潔膚露250ml/瓶(pH值平衡護潔露淨味沐浴乳香氛凝膠)",
"【femfresh芳芯 官方直營】私密潔膚露250ml (任選)",
momo_price=399,
competitor_price=399,
)
for diagnostics in (summer, femfresh):
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_rejects_private_spray_vs_private_gel():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【isLeaf】韓國isLeaf男性私密醒肌抑菌噴霧60ml-夏夜微醺(SGS 24小時抑菌)",
"韓國 isLeaf 男性私密激淨凝露 湛藍海洋 60ml",
momo_price=299,
competitor_price=299,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "type_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_marketing_variant_same_maybelline_lip_tint():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【MAYBELLINE 媚比琳】超持久水光鎖吻唇釉(絲絨甜點新色/鎖吻棒/水光持色)",
"MAYBELLINE 媚比琳 超持久水光鎖吻唇釉 4.2ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_marketing_variant" in diagnostics.reasons
def test_marketplace_matcher_promotes_besthot_aroma_machine_marketing_variant():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【BESTHOT】天然陶瓷精油香薰機-贈精油一瓶(水氧機 加濕器 精油機 香薰機 擴香機 小夜燈)",
"Besthot 天然陶瓷超聲波大噴霧精油香薰機-贈送薰衣草精油 水氧機 加濕器 精油機",
momo_price=899,
competitor_price=899,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_promotes_precise_cosmetics_and_skincare_lines():
from services.marketplace_product_matcher import score_marketplace_match
samples = [
(
"【NARS】官方直營 裸光幻閃亮采餅",
"NARS 裸光幻閃亮采餅 2g #Heavenly",
),
(
"【PONY EFFECT】絕對持久定妝噴霧 100ml(持久定妝/控油特霧)",
"【PONY EFFECT】絕對持久定妝噴霧(控油特霧版)",
),
(
"【植村秀】官方直營 自動武士刀眉筆(Shu uemura/眉筆)",
"《Shu Uemura 植村秀》自動武士刀眉筆 0.3g",
),
(
"【SHISEIDO 資生堂國際櫃】超進化光感輕潤遮瑕棒(遮瑕/修容/打亮/新品)",
"【資生堂國際櫃】超進化光感輕潤遮瑕棒2.7g",
),
(
"【LANCOME 蘭蔻】唯我玫瑰裸光潤唇膏(多款任選 國際航空版 送禮)",
"LANCOME 唯我玫瑰裸光潤唇膏 3g",
),
(
"【Les nez 香鼻子】晨曦冷香儀贈複方擴香精油 30ml(無水擴香 智能霧化)",
"les nez 晨曦冷香儀(無水擴香、智能霧化)",
),
(
"【Mustela 慕之恬廊】舒恬良 修護霜 40ml(Vit.B5 嬰兒界萬用霜 醫師好辣推薦)",
"Mustela 慕之恬廊舒恬良修護霜40ml",
),
]
for left, right in samples:
diagnostics = score_marketplace_match(left, right, momo_price=399, competitor_price=399)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_suppresses_price_penalty_for_exact_identity_toner():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Estee Lauder 雅詩蘭黛】微分子肌底原生露/櫻花版200ml任選(新上市/化妝水/水精華/無酒精)",
"ESTEE LAUDER 雅詩蘭黛 微分子肌底原生露 200ml",
momo_price=4750,
competitor_price=999,
)
assert diagnostics.score >= 0.76
assert "price_penalty_suppressed_exact_identity" in diagnostics.reasons
def test_marketplace_matcher_promotes_exact_line_near_threshold_without_global_threshold_change():
from services.marketplace_product_matcher import score_marketplace_match
za = score_marketplace_match(
"【Za】官方直營 細芯睛彩雙頭眉筆(色號任選)",
"Za 細芯睛彩雙頭眉筆0.1g",
momo_price=158,
competitor_price=158,
)
assert za.score >= 0.76
assert "shared_identity_anchor_exact_line" in za.reasons
def test_marketplace_matcher_promotes_shared_variant_descriptor_alignment_for_shu():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Shu uemura 植村秀】武士刀眉筆(平輸航空版/多色任選/橡棕.暗灰. 灰棕)",
"《Shu Uemura 植村秀》武士刀眉筆(H9) 4g -#橡棕06",
momo_price=699,
competitor_price=699,
)
assert diagnostics.score >= 0.76
assert "shared_variant_descriptor_alignment" in diagnostics.reasons
def test_marketplace_matcher_ignores_generic_variant_noise_for_peripera_brow_pencil():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【peripera官方直營】雙頭旋轉極細眉筆_多色任選(1.5mm極細筆頭)",
"PERIPERA 雙頭旋轉極細眉筆 09灰褐棕 0.05g",
momo_price=180,
competitor_price=180,
)
assert "variant_descriptor_conflict" not in diagnostics.reasons
assert diagnostics.score < 0.76
def test_marketplace_matcher_promotes_brandless_exact_identity_when_anchor_is_strong():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【小米有品】小浪智能感應自動噴香機(三種噴香模式 霧化噴香 芳香除臭)",
"小浪智能感應自動噴香機 三種噴香模式 霧化噴香 芳香除臭 芳香劑 去異味",
momo_price=539,
competitor_price=539,
)
assert diagnostics.score >= 0.76
assert (
"brandless_exact_identity" in diagnostics.reasons
or "shared_identity_anchor_variant_safe" in diagnostics.reasons
)
def test_marketplace_matcher_promotes_ludeya_line_with_platform_name_drift():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【LUDEYA】蜂王玫瑰外泌微臻霜超值兩入組(瑰泌霜60mlx2)",
"LUDEYA 蜂王玫瑰微泌新生霜 60ml x2",
momo_price=2000,
competitor_price=2000,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor" in diagnostics.reasons or "shared_identity_anchor_no_spec" in diagnostics.reasons
def test_marketplace_matcher_promotes_focused_exact_pack_rows_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【3W CLINIC】膠原蛋白粉底液50mlX2入(膠原 保濕 清透 服貼 長效持久)",
"【韓國 3W CLINIC】膠原蛋白粉底液50mlx2入",
"focused_exact_identity_3w_clinic_collagen_foundation_50ml_2pack",
),
(
"【花美水】Moisture保濕修護精華凝膠-原黃金(1.7g x 3支/盒)",
"【花美水】Moisture 保濕修護 精華凝膠(原黃金)(1.7g*3支入)/盒",
"focused_exact_identity_hanamisui_moisture_original_gel_1_7g_3pack",
),
(
"【花美水】Inclear 櫻克麗兒一次性私密淨化凝膠(1.7g x 3支/盒)",
"【花美水】Inclear櫻克麗兒私密淨化凝膠(1.7g*3支)/盒",
"focused_exact_identity_hanamisui_inclear_private_gel_1_7g_3pack",
),
(
"【花美水】Relax薰衣草潤滑凝膠(1.7g x 3支/盒)",
"【花美水】Relax - 薰衣草潤滑凝膠(1.7g*3支入)/盒",
"focused_exact_identity_hanamisui_relax_lavender_gel_1_7g_3pack",
),
(
"【St.Clare 聖克萊爾】私密呼呼溫和潔淨慕斯150mlx2入",
"St.Clare聖克萊爾 私密呼呼溫和潔淨慕斯150mlx2入",
"focused_exact_identity_st_clare_private_mousse_150ml_2pack",
),
(
"【St.Clare 聖克萊爾】私密呼呼溫和潔淨慕斯150ml+私密呼呼舒緩護理噴霧50ml",
"St.Clare聖克萊爾 私密呼呼溫和潔淨慕斯150ml+私密呼呼舒緩護理噴霧50ml",
"focused_exact_identity_st_clare_private_mousse_spray_set",
),
(
"【BIOPEUTIC 葆療美】PLUS+ 果酸煥膚水凝乳20%(150ml)",
"Biopeutic葆療美 PLUS+ 果酸煥膚水凝乳20% 150ml",
"focused_exact_identity_biopeutic_plus_aha_lotion_20_150ml",
),
(
"【台塑生醫】嬰兒沐浴洗髮超值3件組 嬰兒沐浴精*2+嬰幼童洗髮精*1",
"台塑生醫 嬰兒沐浴洗髮超值3件組(嬰兒沐浴精*2+嬰幼童洗髮精*1)",
"focused_exact_identity_taisu_baby_bath_shampoo_3pc",
),
(
"【Elizabeth Arden 伊麗莎白雅頓】八小時潤澤護唇膏SPF15(3.7gX3-專櫃公司貨)",
"ARDEN 雅頓 八小時潤澤護唇膏SPF15(3.7g)X3-百貨公司貨",
"focused_exact_identity_arden_eight_hour_lip_spf15_3_7g_3pack",
),
(
"【理膚寶水】全面修復潤唇膏7.5ml(多重修復)",
"理膚寶水 全面修復潤唇膏 7.5ml",
"focused_exact_identity_laroche_posay_repair_lip_balm_7_5ml",
),
(
"【FLORTTE花洛莉亞】水果沙拉系列彩色防水眼線液筆0.5ml(色號任選)",
"【FLORTTE花洛莉亞】水果沙拉系列彩色防水眼線液筆0.5ml(色號任選)",
"focused_exact_identity_flortte_fruit_salad_eyeliner_0_5ml_catalog",
),
(
"【Neutrogena露得清】護手霜-深層滋潤配方56g(無香/有香)",
"露得清 護手霜56g(任選_無香/有香)",
"focused_exact_identity_neutrogena_hand_cream_56g_scent_catalog",
),
(
"【Kanebo 佳麗寶】ALLIE 持采亮化UV防曬水凝乳 60g* (多款任選)",
"【Kanebo 佳麗寶】ALLIE 持采亮化UV防曬水凝乳 60g(3款任選)",
"focused_exact_identity_kanebo_allie_bright_uv_milk_60g_catalog",
),
(
"【O.P.I】馬拉加葡萄酒 類光繚指甲油-ISLL87(小銀蓋/如膠似漆2.0系列指彩/美甲彩繪/官方直營)",
"OPI 官方直營.馬拉加葡萄酒類光繚-ISLL87如膠似漆2.0系列指彩",
"focused_exact_identity_opi_gel_polish_exact_model",
),
(
"【The Ordinary】5%咖啡因 + EGCG兒茶眼部配方",
"The Ordinary 5%咖啡因 + EGCG兒茶眼部配方 (30ml)",
"focused_exact_identity_the_ordinary_caffeine_egcg_30ml",
),
(
"【澳洲Natures Care】綿羊油(6 入組 125ml/瓶)",
"【澳洲Natures Care】綿羊油(6 入組 125m/瓶)",
"focused_exact_identity_natures_care_sheep_oil_exact_pack",
),
(
"【TOMOON】德國奔月-超省力防飛濺頂級指甲剪/指甲刀(豪華套裝組-L號)",
"TOMOON 德國奔月-超省力防飛濺頂級指甲剪/指甲刀 (豪華套裝組-L號)",
"focused_exact_identity_tomoon_nail_clipper_luxury_size",
),
(
"【HH草本新淨界】私密植萃抗菌潔淨露+私密衣物抗菌手洗精(200ml+200ml)",
"HH私密植萃抗菌潔淨露(200ML)+私密衣物抗菌手洗精(200ML)【裡外兼顧組】",
"focused_exact_identity_hh_private_cleanser_laundry_wash_set",
),
(
"【SEBAMED 施巴】衛生護潔露200mlx2入(總代理)",
"SEBAMED pH3.8女性私密護潔露200mlx2入",
"focused_exact_identity_sebamed_ph38_private_wash_200ml_2pack",
),
(
"【YES 德悅氏】德國進口 鋒利窄弧型剪刀(9cm)",
"【YES 德悅氏】德國製造 鋒利窄弧型剪刀(9cm)",
"focused_exact_identity_yes_curved_scissors_9cm",
),
(
"【SK-II】青春露 330ml*二入組(專櫃公司貨/限量加大版)",
"【SK-II】青春露 330ml 兩入組",
"focused_exact_identity_sk_ii_essence_330ml_2pack",
),
(
"【AMIINO 安美諾 】美白修護霜30ml(母親節禮物)",
"AMIINO安美諾美白修護霜 30ml",
"focused_exact_identity_amiino_whitening_repair_cream_30ml",
),
(
"【YES 德悅氏】德國進口 腳指甲剪刀(10.5cm)",
"【YES 德悅氏】德國製造 腳指甲剪刀(10.5cm)",
"focused_exact_identity_yes_foot_nail_scissors_10_5cm",
),
(
"【YES 德悅氏】德國進口 極細指甲緣硬皮剪刀(9cm)",
"【YES 德悅氏】德國製造 極細指甲緣硬皮剪刀(9cm)",
"focused_exact_identity_yes_cuticle_scissors_9cm",
),
(
"【YES 德悅氏】德國進口 指甲剪附除垢銼刀-亮面(8cm)",
"【YES 德悅氏】德國製造 指甲剪附除垢銼刀-亮面(8cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【YES 德悅氏】德國進口 指甲剪附除垢銼刀-霧面(8cm)",
"【YES 德悅氏】德國製造 指甲剪附除垢銼刀-霧面(8cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【YES 德悅氏】德國進口 腳皮銼腳板(23.5cm)",
"【YES 德悅氏】德國製造 腳皮銼腳板(23.5cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【YES 德悅氏】德國進口 藍寶石銼刀-可收納(9cm)",
"【YES 德悅氏】德國製造 藍寶石銼刀-可收納(9cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【YES 德悅氏】德國進口 指甲剪-不掉屑(6cm)",
"【YES 德悅氏】德國製造 指甲剪-不掉屑(6cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【YES 德悅氏】德國進口 三面指甲拋光棒(17.5cm)",
"【YES 德悅氏】德國製造 指甲拋光棒-三面(17.5cm)",
"focused_exact_identity_yes_nail_tool_exact_model_size",
),
(
"【The Ordinary】Caffeine Solution 咖啡因 + EGCG兒茶眼部配方30ml",
"The Ordinary 5%咖啡因 + EGCG兒茶眼部配方 (30ml)",
"focused_exact_identity_the_ordinary_caffeine_egcg_30ml",
),
(
"【KUSSEN 葵森】寶寶益菌屁屁膏 50ml 3入(易敏肌 屁屁霜 紅屁屁 尿布膏 尿布區照護)",
"【KUSSEN 葵森】寶寶益菌屁屁膏 50ml 3入",
"focused_exact_identity_kussen_baby_butt_cream_50ml_3pack",
),
(
"【Bone 蹦克】擴香禮盒三入組 原木麋鹿+搖搖貓頭鷹+薰衣草精油(交換禮物 香氛 擴香木 )",
"Bone / 擴香禮盒三入組 - 原木麋鹿+搖搖貓頭鷹+薰衣草精油",
"focused_exact_identity_bone_diffuser_gift_3pack",
),
(
"【1990選物】現代簡約半圓罩融燭燈 香氛蠟燭暖燈-白色款( 送禮) 生日禮物 香氛蠟燭燈)",
"【1990選物】現代簡約半圓罩融燭燈 香氛蠟燭暖燈-白色款",
"focused_exact_identity_selection1990_half_dome_wax_lamp_white",
),
(
"【1990選物】歐式可彎融燭燈 香氛蠟燭暖燈-白色款( 送禮) 生日禮物 香氛蠟燭燈)",
"【1990選物】歐式可彎融燭燈 香氛蠟燭暖燈-白色款",
"focused_exact_identity_selection1990_bendable_wax_lamp_white",
),
(
"【CANMAKE】淚袋專用盤(淚袋眼影盤)",
"台隆手創館 CANMAKE淚袋專用盤(淚袋眼影盤)",
"focused_exact_identity_canmake_tear_bag_palette",
),
(
"【Lab52 齒妍堂】小頭軟毛嬰幼兒牙刷2入/組(幼兒專用/牙齒清潔/柔軟刷毛/汪汪隊牙刷/呵護幼兒牙齦)",
"Lab52齒妍堂 汪汪隊立大功小頭軟毛嬰幼兒牙刷(2入/組)",
"focused_exact_identity_lab52_paw_patrol_baby_toothbrush_2pack",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name, momo_price=1000, competitor_price=900)
assert diagnostics.score >= 0.76, (momo_name, diagnostics)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert expected_reason in diagnostics.reasons
assert "focused_exact_total_price_safe" in diagnostics.reasons
def test_marketplace_matcher_blocks_focused_total_price_for_commercial_condition_gap():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"即期品【Kanebo 佳麗寶】ALLIE 持采亮化UV防曬水凝乳 60g* (多款任選)",
"【Kanebo 佳麗寶】ALLIE 持采亮化UV防曬水凝乳 60g(3款任選)",
momo_price=499,
competitor_price=499,
)
assert "commercial_condition_gap" in diagnostics.reasons
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "focused_exact_total_price_safe" not in diagnostics.reasons
def test_marketplace_matcher_blocks_opi_gel_polish_cross_model_autopromotion():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【O.P.I】馬拉加葡萄酒 類光繚指甲油-ISLL87(小銀蓋/如膠似漆2.0系列指彩)",
"OPI 官方直營.極地白雪類光繚-ISLL00如膠似漆2.0系列指彩",
momo_price=578,
competitor_price=578,
)
assert diagnostics.price_basis != "total_price"
assert "focused_exact_identity_opi_gel_polish_exact_model" not in diagnostics.reasons
assert "focused_exact_total_price_safe" not in diagnostics.reasons
def test_marketplace_matcher_blocks_nail_polish_cross_model_codes():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【ANNY 時尚指甲油】party is started 15ml_A10.074.60",
"ANNY時尚指甲油 opalescent (A10.500)15ml",
momo_price=390,
competitor_price=390,
)
assert diagnostics.hard_veto is True
assert "nail_polish_model_code_conflict" in diagnostics.reasons
assert diagnostics.price_basis != "total_price"
def test_marketplace_matcher_blocks_tomoon_cross_size_autopromotion():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【TOMOON】德國奔月-超省力防飛濺頂級指甲剪/指甲刀(豪華套裝組-L號)",
"TOMOON 德國奔月-超省力防飛濺頂級指甲剪/指甲刀 (豪華套裝組-S號)",
momo_price=599,
competitor_price=599,
)
assert diagnostics.price_basis != "total_price"
assert "focused_exact_identity_tomoon_nail_clipper_luxury_size" not in diagnostics.reasons
assert "focused_exact_total_price_safe" not in diagnostics.reasons
def test_marketplace_matcher_promotes_recipe_box_marketing_line_drift():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Recipe Box】Recipe Box多效提亮防曬霜(兒童化妝品/無毒防曬霜/天然彩妝/防曬/提亮)",
"Recipe Box 韓兔 多效提亮防曬霜",
momo_price=299,
competitor_price=299,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor_recipe_box_line" in diagnostics.reasons
def test_marketplace_matcher_promotes_st_deodorizer_with_brand_alias_and_line_anchor():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【日本雞仔牌ST】室內消臭力智能光感應3段定時無線自動除臭芳香噴霧機(內贈芳香劑39ml 衛浴精油擴香瓶棒組)",
"日本ST雞仔牌-室內消臭力智能光感應3段定時無線自動除臭芳香噴霧機1入(含芳香劑39ml)",
momo_price=699,
competitor_price=699,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor_exact_line" in diagnostics.reasons or "shared_identity_anchor_packaging_variant" in diagnostics.reasons
def test_marketplace_matcher_promotes_nivea_dry_lotion_with_long_shared_anchor():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NIVEA 妮維雅】男士無印乾爽止汗爽身乳液(無印止汗滾珠/德國妮維雅)",
"【NIVEA 妮維雅】止汗爽身乳液 無印乾爽50ml",
momo_price=129,
competitor_price=129,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor_nivea_dry_lotion" in diagnostics.reasons
def test_marketplace_matcher_promotes_curel_body_lotion_with_brand_alias():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Curel 珂潤】潤浸保濕清爽身體乳液 220ml",
"珂潤 Curel 潤浸保濕清爽身體乳液220ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_karadium_pearl_shadow_stick_anchor():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【KARADIUM】閃亮珍珠眼影棒 1.4g",
"karadium 閃亮珍珠眼影棒 1.4g",
momo_price=259,
competitor_price=259,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_karadium_pearl_shadow_stick_without_spec_text():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Karadium】閃亮珍珠眼影棒(滑順柔軟 顯色持久 一筆多用眼影筆)",
"KARADIUM閃亮珍珠眼影棒",
momo_price=500,
competitor_price=500,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_karadium_eye_stick" in diagnostics.reasons
def test_marketplace_matcher_promotes_lactacyd_private_wash_multi_option_title():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Lactacyd 立朵舒】柔軟滋潤/亮肌柔滑/加倍修護/全日清爽/生理呵護/滋潤緊緻 私密潔浴露250ml/瓶(多款任選)原廠公司貨_樂齡生醫",
"Lactacyd 立朵舒 私密潔浴露 多款任選(250ml/入)X1入",
momo_price=299,
competitor_price=299,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_lactacyd_wash" in diagnostics.reasons
def test_marketplace_matcher_promotes_relove_private_cleanser_campaign_title():
from services.marketplace_product_matcher import score_marketplace_match, build_search_terms
source = "【Relove】胺基酸私密潔淨凝露120ml-限量聯名款(小虎/啾啾妹/煎妮花/PLAY BOY私密處清潔 涼感潔淨)"
diagnostics = score_marketplace_match(
source,
"RELOVE金盞花萃取低敏私密潔淨凝露 120ml",
momo_price=629,
competitor_price=629,
)
terms = build_search_terms(source, max_terms=4)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_relove_cleanser" in diagnostics.reasons
assert "play" not in terms[0].lower()
assert "boy" not in terms[0].lower()
def test_marketplace_matcher_rejects_serum_milk_vs_serum_cream():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【自白肌】官方直營 極潤玻尿酸精華乳200ml",
"自白肌 極潤玻尿酸精華霜50g",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is False
assert "variant_descriptor_conflict" in diagnostics.reasons
def test_marketplace_matcher_bridges_maquillage_shiseido_counter_alias():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【資生堂東京櫃】MAQuillAGE 心機星魅蜜光圈潤唇膏N",
"【MAQuillAGE 心機彩妝】心機星魅蜜光圈潤唇膏N",
momo_price=850,
competitor_price=850,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_conflict" not in diagnostics.reasons
def test_marketplace_matcher_promotes_kate_bare_lip_line_with_series_copy():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"即期品【KATE 凱婷】柔霧裸唇膏-東京夜喫茶系列(裸色系霧面唇膏/4色任選)",
"【KATE 凱婷】柔霧裸唇膏 (2.3g)",
momo_price=320,
competitor_price=320,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_kate_bare_lip" in diagnostics.reasons
def test_marketplace_matcher_promotes_next_recoverable_exact_identity_cohorts():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【OBgE】【官方公司貨】控油清爽防曬棒 18g (清爽 輕薄 控油 防曬棒 補擦不卡粉 戶外通勤 油肌友善 李多慧)",
"OBgE/控油清爽防曬棒18g",
"shared_identity_anchor",
),
(
"【Play&Joy 官方直營】ARTMIS 蔓越莓私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)",
"ARTMIS 蔓越莓私密清潔慕斯 250ml",
"shared_identity_anchor",
),
(
"【Play&Joy 官方直營】ARTMIS 金縷梅私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)",
"ARTMIS 金縷梅私密清潔慕斯 250ml",
"shared_identity_anchor",
),
(
"美國 Seche Vite 快乾亮油",
"美國Seche Vite指甲快乾亮油14ml",
"shared_identity_anchor_seche_vite_top_coat",
),
(
"【TAICEND 泰陞】寶貝液體保護膜 屁屁噴(100ml/1入組)",
"TAICEND泰陞 寶貝液體護膜100ml 屁屁噴 屁屁膏",
"strong_exact_spec_match",
),
(
"【femfresh 芳芯】私密潔膚露 250ml 長效清新 純淨植萃 舒緩敏感肌膚 私密處清潔 私密處護理|繁華中西藥局|",
"【femfresh芳芯 官方直營】私密潔膚露250ml (任選)",
"shared_identity_anchor_femfresh_wash",
),
(
"【VIGILL 婦潔】男性私密沐浴露220ml(男性私密清潔 一瓶洗全身)",
"【VIGILL 婦潔】日常潔淨 私密沐浴露220ml",
"shared_identity_anchor_vigill_private_wash",
),
(
"【Solone】光采奪目眼部飾底乳(眼部打底 眼影打底)",
"Solone 光采奪目眼部飾底乳 2.8g",
"shared_identity_anchor_packaging_variant",
),
(
"【小米有品】HYDSTO 車載香薰(全車淨化/持久清香/車用香水/香薰)",
"小米有品 HYDSTO 車載香薰",
"shared_identity_anchor_packaging_variant",
),
(
"【小米】電動刮鬍刀 S101(米家電動刮鬍刀 小米刮鬍刀 電動刮鬍刀 米家刮鬍刀)",
"【小米 Xiaomi】 小米電動刮鬍刀 S101",
"shared_model_token_xiaomi_s101_shaver",
),
(
"【PRAMY 柏瑞美】磁吸控油定妝噴霧 100ML(柔焦霧面)",
"【柏瑞美PRAMY】 磁吸控油定粧噴霧 柔焦霧面",
"shared_identity_anchor",
),
(
"【PRAMY 柏瑞美】磁吸控油定妝噴霧 100ML(水光亮面)",
"【柏瑞美PRAMY】 磁吸控油定粧噴霧 水光亮面",
"shared_identity_anchor",
),
(
"【im meme】韓國 Multi Stick Dual 雙頭修容打亮棒 3.3g (修容 打亮 修容棒 打亮筆 修容筆)",
"【IM MEME】我愛小臉修容打亮棒 3.3g",
"shared_identity_anchor",
),
(
"【檜山坊】檜木精油滾珠瓶5ml 兩入(療癒 放鬆 穩定心神)",
"【檜山坊】台灣原生檜木精油5ml滾珠瓶兩入組",
"shared_identity_anchor_hinoki_roller_oil",
),
(
"【ARM&HAMMER 鐵鎚】小蘇打配方體香膏(71g)",
"Arm & Hammer 小蘇打體香膏 2.5oz /71g 長效防護 植物萃取 溫合無鋁",
"strong_exact_spec_match",
),
(
"【Brush Baby】WildOnes 充電式兒童聲波電動牙刷 0-10Y(多款可選)",
"Brush Baby WildOnes 充電式兒童電動牙刷(0-10Y)-多款可選",
"shared_model_token_brush_baby_wildones",
),
(
"【PALMERS 帕瑪氏】新撫紋按摩乳250ml(新配方效果全新升級)",
"Palmer s 可可脂撫紋按摩乳液 250ml",
"strong_exact_spec_match",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76, (momo_name, diagnostics)
assert diagnostics.hard_veto is False
if expected_reason == "shared_identity_anchor":
assert any(reason.startswith("shared_identity_anchor") for reason in diagnostics.reasons)
else:
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_rejects_fragrance_formula_and_finish_variant_mismatch():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【MUJI 無印良品】芬香蠟燭.茉莉花香味/85g",
"芬香蠟燭.梔子花香味/85g【MUJI 無印良品】",
"variant_option_conflict",
),
(
"【Play&Joy 官方直營】ARTMIS 蔓越莓私密清潔慕斯 250ml",
"ARTMIS 金縷梅私密清潔慕斯 250ml",
"variant_option_conflict",
),
(
"【PRAMY 柏瑞美】磁吸控油定妝噴霧 100ML(柔焦霧面)",
"【柏瑞美PRAMY】 磁吸控油定粧噴霧 水光亮面",
"variant_option_conflict",
),
(
"【Relove】8%菸鹼醯胺私密淨白清潔凝露120ml(私密清潔 私密美白 涼感潔淨 PH3.8弱酸呵護)",
"RELOVE胺基酸私密清潔凝露120ml",
"variant_option_conflict",
),
(
"【CeraVe 適樂膚】極抗痕抗老全配組★極抗痕A醇緊緻修護精華+極抗痕多肽緊緻修護霜+極抗痕C10煥亮修護精華",
"【CeraVe適樂膚】極抗痕A醇緊緻修護精華 30ml+極抗痕多肽緊緻修護霜 48g",
"multi_component_count_conflict",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert diagnostics.score < 0.76
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_ignores_sunscreen_and_model_plus_markers_for_bundle_count():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【O.P.I】受損型硬甲油記得卸組-亮麗增強基礎護甲油15mL+專業去光水110mL-NTT80+AL414(禮物/官方直營)",
"OPI 護甲油記得卸組亮麗增強基礎護甲油15mL+去光水110mL",
),
(
"【Neutrogena 露得清】新品上市★水感透亮防曬乳SPF50+ PA++++(40mlx2入組)",
"露得清水感透亮防曬乳SPF50+ 40ml *2入",
),
(
"【AGE20】輕透光潤色素顏霜(SPF50+/PA++++/台灣總代理)",
"AGE20S 輕透光潤色素顏霜SPF50+/PA++++",
),
(
"【Estee Lauder 雅詩蘭黛】粉持久完美鎖妝氣墊粉餅(SPF45/PA+++/一盒一蕊/IU同款)",
"【ESTEE LAUDER雅詩蘭黛】粉持久完美鎖妝氣墊粉餅SPF45/PA+++",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name, momo_price=1000, competitor_price=900)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert "multi_component_count_conflict" not in diagnostics.reasons
def test_marketplace_matcher_ignores_quantity_plus_markers_inside_component_specs():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【HH草本新淨界】私密植萃抗菌潔淨露+私密衣物抗菌手洗精(200ml+200ml)",
"HH私密植萃抗菌潔淨露(200ML)+私密衣物抗菌手洗精(200ML)【裡外兼顧組】",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "focused_exact_identity_hh_private_cleanser_laundry_wash_set" in diagnostics.reasons
assert "multi_component_count_conflict" not in diagnostics.reasons
def test_marketplace_matcher_keeps_named_scent_catalog_in_identity_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【HH草本新淨界】女性私密衣物抗菌手洗精200ml(私密衣物手洗 衣物手洗精)",
"HH女性私密衣物抗菌手洗精 200ml (白麝香&清新花園&寶貝粉香)",
momo_price=399,
competitor_price=356,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_catalog_variant_recoveries_in_identity_review():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【Johnsons 嬌生】嬰兒潤膚乳500ml_嬰兒乳液(牛奶/純淨/甜夢/溫和/棉柔_任選)",
"嬌生嬰兒甜夢潤膚乳500ml",
),
(
"【im meme】我愛超磁妝定妝噴霧60ml(涼感/一般)",
"【IM MEME】我愛超磁妝定妝噴霧-涼感控油",
),
(
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 經典款/光澤款/霧面款/夏日款",
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
),
(
"【KATE 凱婷】怪獸級持色唇膏-經典款(獨家技術持久不沾 高保濕)",
"【KATE 凱婷】怪獸級持色唇膏 (3g)",
),
(
"【植村秀】官方直營 自動武士刀眉筆筆蕊(Shu uemura/筆蕊 8色任選)",
"《Shu Uemura 植村秀》自動武士刀眉筆 -筆蕊 0.3g",
),
(
"【The Forest 癒森林】焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油(居家香氛/香水精油/香氛擴香花/擴香禮物)",
"焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油",
),
(
"【O.P.I】類光繚指甲油 12色任選1瓶(小銀蓋/如膠似漆白日夢遊系列指彩/官方直營)",
"OPI 如膠似漆白日夢遊系列 類光繚指甲油12色任選",
),
(
"【O.P.I】類光繚指甲油 12色任選1瓶(小銀蓋/如膠似漆驕傲果凍系列指彩/官方直營)",
"OPI 如膠似漆驕傲果凍系列 類光繚指甲油11色任選",
),
(
"即期品【Summers Eve 舒摩兒】全肌防護浴潔露2入(私密清潔 經典防護王)無外盒裸瓶包裝",
"eve舒摩兒 賦活美學浴潔露-全肌防護 2入組",
),
(
"【rom&nd】果汁唇釉 2.0(the juicy 果汁唇釉 romand)",
"rom&nd 果汁唇釉2.0_3.5g_多款可選",
),
(
"【Solone】持久眼線筆(眼線膠 超防暈推薦)",
"Solone 持久眼線筆 1.5g",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_aligns_cushion_one_box_two_refills_with_spec_times_two():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【CLIO 珂莉奧 官方直營】羽緻無限緞光氣墊粉餅 SPF50+ PA+++(任選 一盒兩蕊)",
"珂莉奧 羽緻無限緞光氣墊粉餅 SPF50+, PA+++15g*2",
momo_price=885,
competitor_price=808,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "cushion_refill_pack_alignment" in diagnostics.reasons
assert "multi_component_conflict" not in diagnostics.reasons
def test_marketplace_matcher_keeps_cushion_four_refills_vs_spec_times_two_vetoed():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"即期品【CLIO 珂莉奧 官方直營】玫瑰精萃亮采氣墊粉餅SPF 50+ PA++++(2入組-任選 共2盒4蕊)",
"CLIO珂莉奧 粉鑽亮采氣墊粉餅 SPF50 PA (15gX2)",
momo_price=999,
competitor_price=1150,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "multi_component_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_multi_variant_catalog_listings():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【日本Johns Blend】香氛擴香罐85g(車用/任選/白麝香/黑麝香/茉莉/櫻花/繡球花/魔髮奇緣/青檸羅勒)",
"日本Johns Blend 車用香氛擴香罐85g(多款可選)",
),
(
"【日本Johns Blend】香氛擴香罐85g 任選3入((車用/任選/白麝香/黑麝香/茉莉/櫻花/繡球花/魔髮奇緣))",
"日本Johns Blend 車用香氛擴香罐85g 3入組",
),
(
"【COCODOR】香氛蠟燭170g(多款任選/官方直營)",
"COCODOR Premium Jar Candle 香氛精油蠟燭170g(多種香味任選)",
),
(
"【COCODOR】香氛蠟燭95g(多款任選/官方直營)",
"COCODOR Premium Jar Candle 香氛精油蠟燭95g(多種香味任選)",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert (
"catalog_variant_listing_alignment" in diagnostics.reasons
or "strong_exact_spec_match" in diagnostics.reasons
)
def test_marketplace_matcher_requires_non_brand_product_line_evidence():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【CEZANNE】柔潤腮紅",
"Cezanne",
)
assert diagnostics.score < 0.76
assert "strong_product_line_match" not in diagnostics.reasons
def test_marketplace_matcher_promotes_baan_lip_catalog_with_same_options():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Baan 貝恩】嬰兒修護唇膏(草莓/原味) 4.5g/個 (新東海藥局)",
"【貝恩】嬰兒修護唇膏(原味/草莓)",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "variant_selection_review" not in diagnostics.reasons
assert "focused_exact_identity_baan_baby_lip_original_strawberry_catalog" in diagnostics.reasons
assert "catalog_variant_listing_alignment_baan_lip" in diagnostics.reasons
def test_marketplace_matcher_promotes_exact_variant_safe_review_bypass_lines():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【LUSH 嵐舒】櫻之花身體噴霧 200ml(香氛噴霧/茉莉花/檸檬/含羞草/苦橙花/花香)",
"英國原裝LUSH 櫻之花身體噴霧200ml Sakura Body Spray",
"focused_exact_identity_lush_sakura_body_spray",
),
(
"【Play&Joy 官方直營】ARTMIS 金縷梅私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)",
"ARTMIS 金縷梅私密清潔慕斯 250ml",
"focused_exact_identity_artmis_witch_hazel_private_mousse_250ml",
),
(
"【Play&Joy 官方直營】ARTMIS 蔓越莓私密清潔慕斯 250ml(私密清潔 胺基酸配方 綿密泡沫 粉嫩如春 私密保養)",
"ARTMIS 蔓越莓私密清潔慕斯 250ml",
"focused_exact_identity_artmis_cranberry_private_mousse_250ml",
),
(
"【SO NATURAL】FIXX全天候超完美定妝噴霧 120ml(定妝 保濕 控油 定妝噴霧)",
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
"focused_exact_identity_so_natural_fixx_setting_spray_120ml_plain",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "variant_selection_review" not in diagnostics.reasons
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_promotes_safe_multi_component_exact_sets_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【Aveeno 艾惟諾】燕麥高效舒緩護手霜100gx3",
"艾惟諾 燕麥高效舒緩護手霜100gx3",
),
(
"【花美水】Aging逆齡緊緻精華凝膠-原白金(1.7g x 3支/盒)",
"【花美水】Aging 逆齡緊緻 精華凝膠(原白金)(1.7g*3支入)/盒",
),
(
"【O.P.I】受損型硬甲油記得卸組-亮麗增強基礎護甲油15mL+專業去光水110mL-NTT80+AL414(禮物/官方直營)",
"OPI 護甲油記得卸組亮麗增強基礎護甲油15mL+去光水110mL",
),
(
"【Bioneo 德國百妮】微煥膚藻晶去角質凝膠 150mlX2入(去角質 杏仁酸 積雪草)",
"【Bioneo 德國百妮】微煥膚藻晶去角質凝膠 150mlX2入(去角質 杏仁酸 積雪草)",
),
(
"【Cetaphil 舒特膚】官方直營 舒新雪潤安撫水150ml*2入",
"舒特膚 舒新雪潤安撫水 150mlx2入",
),
(
"【Avene 雅漾】舒護活泉水 300ml*4入組 -平行輸入(法文版)",
"Avene 雅漾官方直營舒護活泉水-300mlx4入組",
),
(
"【Schick 舒適牌】超捍輕便刀(2+1入)",
"【Schick 舒適牌】超捍輕便刀2+1入",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "safe_multi_component_exact_total_price" in diagnostics.reasons
def test_marketplace_matcher_uses_pchome_nick_for_paulas_choice_body_lotion_pack():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Paulas Choice 寶拉珍選】2%水楊酸身體乳210ml二入",
"【寶拉珍選】水楊酸身體乳雙入組 (2%水楊酸身體乳 210ml x2)",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "paulas_choice_body_lotion_210ml_2pack_alignment" in diagnostics.reasons
def test_marketplace_matcher_keeps_expiry_or_variant_pack_in_manual_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Paulas Choice 寶拉珍選】2%水楊酸精華液118ml二入組(金蓋限定版)",
"【寶拉珍選】水楊酸精華液雙入組 【寶拉珍選】2%水楊酸精華液 118ml雙入組 效期至2026/12",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "commercial_condition_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
assert "safe_multi_component_exact_total_price" not in diagnostics.reasons
def test_marketplace_matcher_promotes_nivea_creme_100ml_type_alignment():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NIVEA 妮維雅】妮維雅霜100ml 隨身版(小藍罐 身體乳霜 臉部身體適用)",
"NIVEA 妮維雅 妮維雅霜100ml 隨身版(小藍罐/身體乳霜/臉部身體適用)",
)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "nivea_creme_100ml_type_alignment" in diagnostics.reasons
assert "focused_exact_identity_nivea_creme_100ml" in diagnostics.reasons
def test_marketplace_matcher_promotes_recent_stale_recovery_single_spec_lines():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【LAURA MERCIER 蘿拉蜜思】煥顏透明蜜粉29g超殺組(冠軍蜜粉/定妝散粉)",
"【Laura Mercier 蘿拉蜜思】煥顏透明蜜粉 29g 專櫃公司貨 Translucent Loose Setting Powder",
),
(
"【TS6 護一生】沁涼潔淨慕斯100g(私密清潔)",
"TS6護一生 沁涼潔淨慕斯100g",
),
(
"【Schick 舒適牌】舒綺仕女 除毛刀片 刀片3入(敏感肌)",
"【Schick 舒適牌】舒綺仕女除毛刀片(敏感肌用)3入",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
def test_marketplace_matcher_keeps_single_sided_rose_powder_in_identity_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【LAURA MERCIER 蘿拉蜜思】煥顏透明蜜粉 Rose 29g (國際航空版)",
"【Laura Mercier 蘿拉蜜思】煥顏透明蜜粉 29g",
)
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_baby_shampoo_bath_gap_in_identity_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【IBL 依必朗】依必朗 Angel Baby 嬰兒 沐浴精 洗髮精 600ml",
"依必朗Angel Baby嬰兒洗髮精600ml",
)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "comparable"
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
def test_marketplace_matcher_promotes_focused_lip_care_exact_lines_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【DHC】純欖護唇膏1.5g",
"【DHC】純欖護唇膏 1.5g",
"focused_exact_identity_dhc_olive_lip_1_5g",
),
(
"【FRUDIA】確認過嘴唇 蜂蜜藍莓保濕潤澤護唇膏10g(冠軍護唇膏/還可當晚安唇膜)",
"FRUDIA確認過嘴唇蜂蜜藍莓保濕潤澤護唇膏10g",
"focused_exact_identity_frudia_honey_blueberry_lip_10g",
),
(
"【SEBAMED 施巴】嬰兒護唇膏4.8gx2(總代理)",
"施巴5.5 sebamed 嬰兒護唇膏 4.8g*2入/袋",
"focused_exact_identity_sebamed_baby_lip_4_8g_2pack",
),
(
"【理膚寶水】滋養修護潤唇膏 4.7ml(滋養軟化唇部)",
"理膚寶水 滋養修護潤唇膏 4.7ml",
"focused_exact_identity_laroche_posay_lip_balm_4_7ml",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "variant_selection_review" not in diagnostics.reasons
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_promotes_focused_manual_gate_exact_lines_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【Play&Joy】POWERMAN男性私密養護液30ml",
"POWERMAN 男性私密養護液 30ml",
"focused_exact_identity_playjoy_powerman_male_care_30ml",
),
(
"【PHYSIOGEL潔美淨】層脂質AI冰鎮精華露200ml(2入)",
"PHYSIOGEL 潔美淨AI冰鎮精華露 200ml 2入",
None,
),
(
"【TS6護一生】緊彈水嫩凝膠40g",
"TS6 護一生緊彈水嫩凝膠 40g",
"focused_exact_identity_ts6_private_elastic_gel_40g",
),
(
"【日本Beauty Foot】去角質足膜 25mlx2枚入(三入組)",
"【日本Beauty Foot 】煥膚足膜(25ml*2枚入)三入組",
"focused_exact_identity_beauty_foot_mask_exact_pack",
),
(
"【日本Beauty Foot】去角質足膜-大尺寸 30mlx2枚入(二入組)",
"【日本Beauty Foot 】煥膚足膜大尺寸(30ml*2枚入)二入組",
"focused_exact_identity_beauty_foot_mask_exact_pack",
),
(
"【KAMERIA】凱蜜菈 足足稱奇積雪草去皮嫩足膜(17ml*2枚入)",
"Kameria 足足稱奇 積雪草去皮嫩足膜 17MLX2枚入",
"focused_exact_identity_kameria_centella_foot_mask_17ml_2pc",
),
(
"【TS6 護一生】蜜愛潤滑液(100gx3入)",
"TS6護一生 蜜愛潤滑液(100g)X3入",
"focused_exact_identity_ts6_lubricant_100g_3pack",
),
(
"【TS6 護一生】蜜桃煥白凝膠-私密美白保養(45gx3入)",
"TS6護一生 蜜桃煥白凝膠 45gX3",
"focused_exact_identity_ts6_peach_bright_gel_45g_3pack",
),
(
"【TS6 護一生】極淨白私密潔膚露250g+蜜桃煥白凝膠45g(私密清潔 私密美白保養)",
"TS6護一生 極淨白私密潔膚露250g+蜜桃煥白凝膠45g",
"focused_exact_identity_ts6_white_wash_peach_gel_kit",
),
(
"【Vaseline 凡士林】官方直營 經典嬰兒高純修護凝膠368gx3入",
"Vaseline 凡士林經典嬰兒高純修護凝膠368g x3入",
"focused_exact_identity_vaseline_baby_jelly_368g_3pack",
),
(
"【DERMA 丹麥德瑪】寶寶有機水嫩洗髮沐浴露150ml",
"丹麥DERMA 有機寶寶洗髮沐浴露150ml",
None,
),
(
"【DERMA 丹麥德瑪】寶寶有機水嫩洗髮沐浴露500ml",
"丹麥DERMA 有機寶寶洗髮沐浴露500ml",
None,
),
(
"【CLARINS 克蘭詩】黃金亮眼萃20ml",
"克蘭詩 黃金亮眼萃 20ml",
"focused_exact_identity_clarins_double_serum_eye_20ml",
),
(
"【Cetaphil 舒特膚】長效潤膚乳237ml",
"舒特膚 長效潤膚乳 237ml",
"focused_exact_identity_cetaphil_long_lotion_237ml",
),
(
"【Cetaphil 舒特膚】長效潤膚乳473ml",
"舒特膚 長效潤膚乳 473ml",
"focused_exact_identity_cetaphil_long_lotion_473ml",
),
(
"【Cetaphil 舒特膚】官方直營 長效潤膚霜 250g(臉部身體乳霜/敏感肌/保濕/B3/B5/乾燥粗糙)",
"【Cetaphil 舒特膚】長效潤膚霜250g",
"focused_exact_identity_cetaphil_long_moisturizing_cream_250g",
),
(
"【Cetaphil 舒特膚】官方直營 AD益膚康修護舒敏乳霜 227g(臉部身體乳霜/益膚保濕)",
"Cetaphil舒特膚 AD益膚康修護舒敏乳霜227g",
"focused_exact_identity_cetaphil_ad_repair_cream_227g",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "variant_selection_review" not in diagnostics.reasons
assert "type_conflict" not in diagnostics.reasons
if expected_reason:
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_keeps_ts6_scented_laundry_variant_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【TS6 護一生】私舒衣物手洗精(300gx3入)",
"TS6護一生 私舒衣物手洗精(絲絨玫瑰)300gX3",
)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "focused_exact_total_price_safe" not in diagnostics.reasons
def test_marketplace_matcher_keeps_ambiguous_ts6_white_mousse_packaging_out_of_total_price():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【TS6護一生】淨白植感慕斯180g 3入",
"TS6 護一生私密淨白慕斯 180g x3",
)
assert diagnostics.price_basis != "total_price"
assert diagnostics.alert_tier != "price_alert_exact"
def test_marketplace_matcher_promotes_safe_low_score_identity_review_samples():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【TS6 護一生】超美白香氛誘霜120g 私密保養(私密美白)",
"TS6 護一生超美 白香氛誘霜(120ml)",
"focused_exact_identity_ts6_private_white_fragrance_cream_120",
),
(
"【W 修護保養】蝸牛特潤修護面膜6片 醫美術後保養 修護 保濕 皮秒(保濕優 修護強 隱形面膜 雷射術後必備)",
"【W修護保養】蝸牛特潤修護面膜 28ml 6片裝",
"focused_exact_identity_w_repair_snail_mask_6pcs_review",
),
(
"【Derma 丹麥德瑪】大地有機植萃撫紋護膚油-2入組(天然成分 適合孕哺期間使用)",
"Derma 大地 Eco 植萃護膚油2入組",
"focused_exact_identity_derma_eco_skin_oil_2pack_review",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert diagnostics.match_type in {"comparable", "exact"}
assert expected_reason in diagnostics.reasons
assert "variant_selection_review" not in diagnostics.reasons
def test_marketplace_matcher_keeps_one_sided_candle_catalog_selection_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【COCODOR】大豆蠟燭130g x2入(小/多款任選/官方直營)",
"COCODOR 大豆蠟燭130gx2",
)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "candle_catalog_selection_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_same_candle_catalog_alignment_as_total_price():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"Pavaruni 香氛蠟燭450g 20種香味",
"Pavaruni 20種香味香氛蠟燭 450g",
)
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "candle_catalog_selection_gap" not in diagnostics.reasons
assert "variant_selection_review" not in diagnostics.reasons
assert "focused_exact_identity_pavaruni_20_scent_candle" in diagnostics.reasons
def test_marketplace_matcher_blocks_different_carrier_oil_core_ingredients():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【NEW DIRECTIONS】甜杏仁油1000ml+按壓頭1入組(澳洲原裝進口-新方向按摩油保濕油基礎油)",
"【NEW DIRECTIONS】酪梨油1000ml+按壓頭1入組(澳洲原裝進口-新方向按摩油保濕油基礎油)",
),
(
"【NEW DIRECTIONS】甜杏仁油1000ml+按壓頭1入組(澳洲原裝進口-新方向按摩油保濕油基礎油)",
"【NEW DIRECTIONS】杏桃核仁油1000ml+按壓頭1入組(澳洲原裝進口-杏核仁油按摩油保濕油基礎油)",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "core_ingredient_line_conflict" in diagnostics.reasons
def test_marketplace_matcher_sends_fragrance_and_foot_mask_catalog_gaps_to_review():
from services.marketplace_product_matcher import score_marketplace_match
cocodor = score_marketplace_match(
"【COCODOR】經典擴香瓶200mlx4入(多款任選/官方直營/韓國香氛)",
"COCODOR 經典擴香瓶200mlx4",
)
kameria = score_marketplace_match(
"【KAMERIA】凱蜜菈 足足稱奇足膜17ml*2枚入(任選三款)",
"Kameria足足稱奇涼感去皮嫩足膜 17ml*2枚入",
)
for diagnostics in (cocodor, kameria):
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_sends_bath_additive_box_variants_to_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【日本Hakugen白元】濁湯溫泉之旅炭酸泡澡入浴劑45gx16錠/馨香-橘盒(含4種湯色發泡沐浴劑草本溫泉粉泡澡錠)",
"日本Hakugen白元-濁湯溫泉之旅炭酸泡澡入浴劑-懷舊45gx16錠/綠盒",
)
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "bath_additive_variant_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_rejects_clarins_body_oil_line_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【CLARINS 克蘭詩】輕盈美體護理油100ml",
"CLARINS 克蘭詩身體調和護理油100ml",
)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "clarins_body_oil_line_conflict" in diagnostics.reasons
def test_marketplace_matcher_rejects_named_component_quantity_reversal():
from services.marketplace_product_matcher import score_marketplace_match
baby_kit = score_marketplace_match(
"【台塑生醫】嬰兒沐浴洗髮超值3件組(嬰兒沐浴精500g*1+嬰幼童洗髮精500g*2)",
"台塑生醫FORTE 嬰幼童洗髮精500g*1+嬰兒沐浴精500g*2",
)
private_mousse = score_marketplace_match(
"【isLeaf】韓國男性私密激淨慕絲200ml二入組(魅惑麋香+湛藍海洋)",
"韓國isLeaf 男性私密激淨慕絲200ml 湛藍海洋x2+魅惑麋香x2",
)
for diagnostics in (baby_kit, private_mousse):
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "named_component_quantity_conflict" in diagnostics.reasons
def test_marketplace_matcher_sends_hooome_one_sided_design_gap_to_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【HOOOME】經典大理石 香氛蠟燭暖燈-黑色",
"HOOOME 經典款香氛蠟燭暖燈 黑色",
)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "hooome_wax_lamp_design_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_kiehls_no1_lip_balm_as_product_line_not_color_number():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【契爾氏】官方直營 1號護唇膏15ml(Kiehls)",
"KIEHLS 一號護唇膏 (原味) 15ml",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "variant_option_conflict" not in diagnostics.reasons
def test_marketplace_matcher_promotes_pshine_beauty_foot_file_identity_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【P.SHINE BEAUTY FOOT】日本製雙面足部去角質硬皮磨砂棒 足搓棒(日本進口)",
"P.SHINE BEAUTY FOOT 雙面足部去硬皮磨砂棒(日本製)",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "shared_model_token_pshine_beauty_foot_file" in diagnostics.reasons
def test_marketplace_matcher_rejects_multi_color_catalog_against_single_color_candidate():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【LOriginal London 洛瑞歐】官方直營 皇家小羊皮車用香氛禮盒 琥珀橙/干邑棕/賽車綠 生日禮物送",
"英國LOriginal精品小羊皮車用香氛禮盒-干邑棕(平行輸入)",
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "variant_option_conflict" in diagnostics.reasons
def test_marketplace_matcher_rejects_starter_set_against_single_lotion():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【理膚寶水】安心抗敏入門組★多容安舒緩濕潤乳液_A(安心乳液/敏感肌保濕)",
"理膚寶水 多容安舒緩濕潤乳液 40ml",
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "bundle_offer_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_focused_low_score_exact_identity_lines():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【Biodance】深層保濕面膜/膠原蛋白深層全效面膜 4片入(補水面膜 韓國 保濕 小分子玻尿酸)",
"【Biodance】實感深層全效面膜 4片(多重保濕鎮靜/膠原蛋白)",
"focused_exact_identity_biodance_deep_mask",
),
(
"【SAB 初淨肌】私密防護舒緩噴霧30mlX1入(私密舒緩/私密保養/日本愛宕柿淨味/洋甘菊/保濕/私密肌專用)",
"初淨肌 SAB 私密防護舒緩噴霧 30ml*1入",
"focused_exact_identity_sab_private_spray",
),
(
"【LUSH 嵐舒】櫻之花身體噴霧 200ml(香氛噴霧/茉莉花/檸檬/含羞草/苦橙花/花香)",
"英國原裝LUSH 櫻之花身體噴霧200ml Sakura Body Spray",
"focused_exact_identity_lush_sakura_body_spray",
),
(
"【Kanebo 佳麗寶】COFFRET DOR 光透立體眼線筆蕊/眼線液蕊(多色任選)",
"【Kanebo 佳麗寶】COFFRET DOR光透立體眼線筆(蕊)0.11g",
"focused_exact_identity_kanebo_coffret_eyeliner",
),
(
"【Play&Joy 官方直營】ARTMIS 葳兒柔私密賦活凝膠35ml(私密精華 體感升級 靈芝外泌體 費洛蒙香氛 親密互動)",
"ARTMIS葳兒柔賦活凝膠35ml",
"focused_exact_identity_artmis_virile_gel",
),
(
"【Nailmatic】兒童水漾亮彩指甲油 - 小精靈(兒童專用指甲油)",
"nailmatic 兒童指甲油(Casper小精靈)",
"focused_exact_identity_nailmatic_casper_polish",
),
(
"【小浪】智能感應自動噴香機+補充液3入組(三種噴香模式 霧化噴香 芳香除臭)",
"小浪智能感應自動噴香機+補充液3入組",
"focused_exact_identity_xiaolang_spray_machine_refill_set",
),
(
"【YUNMI】J10濕度數顯智能加濕器 雙噴頭納米霧化水氧機 香氛機 噴霧器 空氣清淨機 增濕器",
"YUNMI J10濕度數顯智能加濕器",
"focused_exact_identity_yunmi_j10_humidifier",
),
(
"【AQUIESSE】美國大豆蠟香氛蠟燭 5oz/141g(多款任選.清新茶香木質果香)",
"【AQUIESSE】香氛蠟燭 5oz 多款任選",
"focused_exact_identity_aquiesse_5oz_candle_catalog",
),
(
"【REJURAN 麗珠蘭】官方直營|麗駐蘭修復舒緩面膜5P(補水 保濕)|台灣總代理 動物性 PDRN",
"REJURAN 麗駐蘭修復舒緩面膜5P",
"focused_exact_identity_rejuran_repair_mask_5p",
),
(
"【SHISEIDO 資生堂國際櫃】新艷陽•夏 水離子熱防禦UV隔離露 SPF50(防曬/防曬乳/清爽/不黏膩)",
"《SHISEIDO 資生堂》新艷陽夏水離子熱防禦隔離露 50ml",
"focused_exact_identity_shiseido_blue_sunscreen",
),
(
"【Baan 貝恩】嬰兒修護唇膏4.5g",
"【貝恩】嬰兒修護唇膏(原味/草莓)",
"focused_exact_identity_baan_baby_lip_base_catalog",
),
(
"【植村秀】官方直營 3D極細防水眼線膠筆(Shu uemura)",
"《Shu Uemura 植村秀》3D極細防水眼線膠筆 0.08g-#深棕",
"focused_exact_identity_shu_3d_eyeliner",
),
(
"【YSL】官方直營 恆久完美透膚煙染腮紅(任選1款/新品上市)",
"【YSL聖羅蘭】恆久完美透膚煙染腮紅 6g ( #12/ #57/ #93)",
"focused_exact_identity_ysl_blush_catalog",
),
(
"【HH草本新淨界】私密植萃美白緊緻凝露30ml(私密美白 保濕緊緻 私密緊實)",
"HH 私密植萃美白緊緻凝露(30ml)",
"focused_exact_identity_hh_private_gel",
),
(
"【Lab52 齒妍堂】學習刷牙漱口水170g/瓶(食品級配方/牙菌斑顯示劑/口腔清潔居家檢測)",
"Lab52齒妍堂 汪汪隊立大功學習刷牙漱口水170g",
"focused_exact_identity_lab52_mouthwash",
),
(
"【benefit 貝玲妃】經典染唇液(唇頰兩用/持久不脫妝)",
"【Benefit】經典菲菲染唇液6ml(唇頰兩用/持久不脫妝)多色",
"focused_exact_identity_benefit_lip_tint",
),
(
"【草本24】Herb24 晨霧純精油擴香儀II_霧黑無須用水紅桔 純質精油)(歐盟EMC證書 主機享半年保固)",
"【草本24。Herb24】晨霧純精油擴香儀II_黑色任選價值780元純質精油10ml",
"focused_exact_identity_herb24_mist_diffuser_black",
),
(
"【Pavaruni】美國天然植物精油40香味10ml(香薰 擴香 萃取 薰香機 水氧機 薰衣草 檀香 玫瑰 雪松 白茶 茉莉)",
"【美國Pavaruni】天然植物香氛精油40種香味10ml 多款任選",
"focused_exact_identity_pavaruni_40_scent_oil",
),
(
"【Pavaruni】美國香氛蠟燭20種香味450g(禮盒大豆蠟植物天然精油花香木質果香生日聖誕交換女友女生情人禮物)",
"【美國Pavaruni】香氛蠟燭20種香味450g 卡啡那系列 多款任選",
"focused_exact_identity_pavaruni_20_scent_candle",
),
(
"【日本Laundrin朗德林】TOKYO汽車空調出風口專用夾式消臭芳香劑1入/袋(車用清新擴香劑香氛淨化馨香約30天)",
"日本Laundrin朗德林-TOKYO車用夾式消臭芳香劑1入/袋",
"focused_exact_identity_laundrin_tokyo_car_freshener",
),
(
"【好物良品】北歐簡樸融蠟燈桌面氣氛夜燈|附燈泡(氛圍燈 室內芳香 交換禮物 桌上檯燈 香氛蠟燭 擴香)",
"【好物良品】北歐簡樸融蠟燈桌面氣氛夜燈(2款任選附燈泡)",
"focused_exact_identity_goodgoods_nordic_wax_lamp",
),
(
"【Derma 丹麥德瑪】大地有機植萃撫紋護膚油 150ml(有機植物油複合配方 滋潤不黏膩)",
"Derma 大地 Eco 有機植萃護膚油 150ml",
"focused_exact_identity_derma_eco_skin_oil",
),
(
"【悠斯晶】日本No.1維他命乳霜★經典乳霜30g(攜帶型 6入組)",
"【Yuskin悠斯晶】A乳霜 攜帶型 6盒組(30g/盒)",
"focused_exact_identity_yuskin_classic_cream_30g_6pack",
),
(
"【Herbacin 德國小甘菊】小甘菊1號護手霜20ml",
"小甘菊經典護手霜20ml",
"focused_exact_identity_herbacin_classic_hand_cream_20ml_brandless",
),
(
"【Johnsons 嬌生】嬰兒潤膚乳500ml_嬰兒乳液(牛奶/純淨/甜夢/溫和/棉柔_任選)",
"嬌生嬰兒甜夢潤膚乳500ml",
"focused_exact_identity_johnsons_baby_lotion_variant_catalog",
),
(
"【Johnsons 嬌生】嬰兒潤膚乳500mlx3(牛奶/純淨/甜夢/溫和/棉柔任選_嬰兒乳液)",
"嬌生嬰兒 純淨潤膚乳500mlx3",
"focused_exact_identity_johnsons_baby_lotion_variant_catalog",
),
(
"【im meme】我愛超磁妝定妝噴霧60ml(涼感/一般)",
"【IM MEME】我愛超磁妝定妝噴霧-涼感控油",
"focused_exact_identity_im_meme_fixx_cool_setting_spray",
),
(
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 經典款/光澤款/霧面款/夏日款",
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
"focused_exact_identity_so_natural_fixx_setting_spray_catalog",
),
(
"【KATE 凱婷】怪獸級持色唇膏-經典款(獨家技術持久不沾 高保濕)",
"【KATE 凱婷】怪獸級持色唇膏 (3g)",
"focused_exact_identity_kate_monster_lipstick_catalog",
),
(
"【植村秀】官方直營 自動武士刀眉筆筆蕊(Shu uemura/筆蕊 8色任選)",
"《Shu Uemura 植村秀》自動武士刀眉筆 -筆蕊 0.3g",
"focused_exact_identity_shu_auto_hard_formula_refill_catalog",
),
(
"【The Forest 癒森林】焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油(居家香氛/香水精油/香氛擴香花/擴香禮物)",
"焦糖楓葉香氛擴香花禮盒 含30ml品牌香氛油",
"focused_exact_identity_the_forest_maple_diffuser_flower_brandless",
),
(
"【O.P.I】類光繚指甲油 12色任選1瓶(小銀蓋/如膠似漆白日夢遊系列指彩/官方直營)",
"OPI 如膠似漆白日夢遊系列 類光繚指甲油12色任選",
"focused_exact_identity_opi_gel_polish_series_catalog",
),
(
"【O.P.I】類光繚指甲油 12色任選1瓶(小銀蓋/如膠似漆驕傲果凍系列指彩/官方直營)",
"OPI 如膠似漆驕傲果凍系列 類光繚指甲油11色任選",
"focused_exact_identity_opi_gel_polish_series_catalog",
),
(
"即期品【Summers Eve 舒摩兒】全肌防護浴潔露2入(私密清潔 經典防護王)無外盒裸瓶包裝",
"eve舒摩兒 賦活美學浴潔露-全肌防護 2入組",
"focused_exact_identity_summer_eve_full_skin_wash_2pack",
),
(
"【rom&nd】果汁唇釉 2.0(the juicy 果汁唇釉 romand)",
"rom&nd 果汁唇釉2.0_3.5g_多款可選",
"focused_exact_identity_romand_juicy_lip_tint_2_catalog",
),
(
"【Solone】持久眼線筆(眼線膠 超防暈推薦)",
"Solone 持久眼線筆 1.5g",
"focused_exact_identity_solone_longlasting_eyeliner",
),
(
"【GATSBY】爆水擦澡濕巾24張入(涼感乾洗澡)",
"GATSBY 爆水擦澡濕巾24張入(240g)",
"focused_exact_identity_gatsby_body_wipes_24",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76, (momo_name, diagnostics)
assert diagnostics.hard_veto is False
assert expected_reason in diagnostics.reasons
if expected_reason in {
"focused_exact_identity_sab_private_spray",
"focused_exact_identity_herb24_mist_diffuser_black",
"focused_exact_identity_pavaruni_40_scent_oil",
"focused_exact_identity_pavaruni_20_scent_candle",
"focused_exact_identity_derma_eco_skin_oil",
}:
assert "focused_exact_total_price_safe" in diagnostics.reasons
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
def test_marketplace_matcher_promotes_precise_brandless_herbacin_hand_cream_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【Herbacin 德國小甘菊】小甘菊柔皙護手霜20ml",
"小甘菊柔皙護手霜 20ml",
),
(
"【Herbacin 德國小甘菊】小甘菊野生玫瑰護手霜20ml 條狀",
"小甘菊野生玫瑰護手霜20ml",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "focused_exact_total_price_safe" in diagnostics.reasons
assert "focused_exact_identity_herbacin_classic_hand_cream_20ml_brandless" in diagnostics.reasons
def test_marketplace_matcher_keeps_herbacin_cross_variant_out_of_total_price():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Herbacin 德國小甘菊】小甘菊柔皙護手霜20ml",
"小甘菊野生玫瑰護手霜20ml",
)
assert diagnostics.price_basis != "total_price"
assert diagnostics.alert_tier != "price_alert_exact"
assert "focused_exact_total_price_safe" not in diagnostics.reasons
def test_marketplace_matcher_keeps_high_variant_low_score_lines_outside_focused_promotion():
from services.marketplace_product_matcher import score_marketplace_match
lush = score_marketplace_match(
"【LUSH 嵐舒】Sticky Dates 椰棗布丁身體噴霧 200ml(香氛噴霧/安息香/檀木/甜蜜香氣)",
"英國原裝LUSH 睡公主身體噴霧200ml Sleepy Body Spray",
)
lactacyd = score_marketplace_match(
"【Lactacyd 立朵舒】清新舒涼 私密潔浴露250ml(天然薄荷涼感 私密清潔 私密保養 乾癢修護)",
"Lactacyd 立朵舒私密潔浴露-生理呵護250ml",
)
lunasol = score_marketplace_match(
"即期品【Kanebo 佳麗寶】LUNASOL 晶巧霓光/明艷頰彩(多色任選)",
"【Kanebo 佳麗寶】LUNASOL 晶巧霓光眼彩寵愛組",
)
muji_swab = score_marketplace_match(
"【MUJI 無印良品】細軸棉棒/200支",
"【MUJI 無印良品】棉棒(黑色)/200支",
)
kate_limited = score_marketplace_match(
"【KATE 凱婷】絕美綻放睫毛膏(NANA限量聯名款)",
"【KATE 凱婷】絕美綻放睫毛膏 7.1g",
)
schick_bundle_gap = score_marketplace_match(
"【Schick 舒適牌】舒芙仕女除毛刀把刀片組 (1刀把2刀片+刀片3入)",
"【Schick舒適牌】舒綺 仕女除毛刀 敏感肌用 1刀把+2刀片 送卡娜赫拉束口袋",
)
lancome_line_gap = score_marketplace_match(
"【LANCOME 蘭蔻】官方直營 超極光活粹晶露150ml(LANCOME/四重酸極光水/化妝水/精華水)",
"LANCOME 蘭蔻 超極限肌因精華露150ml 專櫃公司貨",
)
mac_finish_gap = score_marketplace_match(
"【M.A.C】MACximal極自我柔霧唇膏3.5g(子彈唇膏 #柔霧大巨彈_全新質地_新色登場)",
"M.A.C MACximal 極自我緞光唇膏 3.5g 多款可選",
)
ysl_powder_variant_guard = score_marketplace_match(
"【YSL】官方直營 恆久完美持久柔霧蜜粉餅(任選1款/皮革蜜粉)",
"YSL 恆久完美持久柔霧蜜粉餅(7.5g) [百貨公司專櫃貨]",
)
opi_series_gap = score_marketplace_match(
"【O.P.I】類光繚指甲油 12色任選1瓶(小銀蓋/如膠似漆白日夢遊系列指彩/官方直營)",
"OPI 如膠似漆驕傲果凍系列 類光繚指甲油11色任選",
)
romand_line_gap = score_marketplace_match(
"【rom&nd】水感唇釉",
"rom&nd 果汁唇釉5.5g_多款可選",
)
peripera_variant_gap = score_marketplace_match(
"【peripera官方直營】雙頭旋轉極細眉筆_多色任選(1.5mm極細筆頭)",
"PERIPERA 雙頭旋轉極細眉筆 09灰褐棕 0.05g",
)
summer_eve_variant_gap = score_marketplace_match(
"即期品【Summers Eve 舒摩兒】全肌防護浴潔露2入(私密清潔 經典防護王)無外盒裸瓶包裝",
"eve舒摩兒 生理呵護浴潔露 2入組",
)
solone_type_gap = score_marketplace_match(
"【Solone】持久眼線筆(眼線膠 超防暈推薦)",
"Solone 斜角眉筆 0.35g",
)
erbe_tool_gap = score_marketplace_match(
"ERBE 德國不鏽鋼指甲清垢棒",
"ERBE 德國雙頭指甲緣刨刀",
)
mirae_count_gap = score_marketplace_match(
"【MIRAE 未來美】EX8分鐘極速面膜 5片(補水/淨白/舒緩/修護)",
"未來美EX8分鐘極速補水/淨白/舒緩/修護面膜x8",
)
gonesh_scent_gap = score_marketplace_match(
"【GONESH】室內汽車用香氛固體凝膠78g(持久芳香)",
"【日本GONESH】室內汽車用香氛固體凝膠空氣芳香劑(No.4號 藤蔓果園78g/罐 長效8週持久芳香型)",
)
sunscreen_line_gap = score_marketplace_match(
"【我的心機】溫和寶貝兒童防曬乳35ml(SPF50+ PA+++)",
"我的心機 海洋友善保濕高效防曬乳35ml(SPF50+PA++++)",
)
for diagnostics in (
lush,
lactacyd,
lunasol,
muji_swab,
kate_limited,
schick_bundle_gap,
lancome_line_gap,
mac_finish_gap,
ysl_powder_variant_guard,
opi_series_gap,
romand_line_gap,
peripera_variant_gap,
summer_eve_variant_gap,
solone_type_gap,
erbe_tool_gap,
mirae_count_gap,
gonesh_scent_gap,
sunscreen_line_gap,
):
assert diagnostics.score < 0.76
assert not any(reason.startswith("focused_exact_identity_") for reason in diagnostics.reasons)
assert sunscreen_line_gap.hard_veto is True
assert "variant_descriptor_conflict" in sunscreen_line_gap.reasons
assert lactacyd.hard_veto is True
assert "lactacyd_variant_conflict" in lactacyd.reasons
assert lunasol.hard_veto is True
assert "makeup_usage_conflict" in lunasol.reasons
assert muji_swab.hard_veto is True
assert "cotton_swab_variant_conflict" in muji_swab.reasons
assert mirae_count_gap.hard_veto is True
assert "count_conflict" in mirae_count_gap.reasons
assert gonesh_scent_gap.hard_veto is True
assert "aroma_scent_variant_conflict" in gonesh_scent_gap.reasons
assert lancome_line_gap.hard_veto is True
assert "lancome_line_conflict" in lancome_line_gap.reasons
assert peripera_variant_gap.hard_veto is False
assert "variant_selection_review" in peripera_variant_gap.reasons
assert mac_finish_gap.hard_veto is True
assert "makeup_finish_conflict" in mac_finish_gap.reasons
assert schick_bundle_gap.hard_veto is True
assert "schick_razor_line_conflict" in schick_bundle_gap.reasons
assert erbe_tool_gap.hard_veto is True
assert "nail_tool_function_conflict" in erbe_tool_gap.reasons
def test_marketplace_matcher_rejects_saugella_private_wash_variant_gap():
from services.marketplace_product_matcher import score_marketplace_match
for momo_name in (
"【SAUGELLA 賽吉兒】菁萃潔浴凝露日用250ml二入組",
"【SAUGELLA 賽吉兒】菁萃潔浴凝露加強250ml二入組",
"【SAUGELLA 賽吉兒】菁萃潔浴凝露潤澤二入組",
):
diagnostics = score_marketplace_match(
momo_name,
"SAUGELLA賽吉兒 pH3.5菁萃婦潔凝露【黃金女郎型】250ml(2入特惠)",
momo_price=1080,
competitor_price=990,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "saugella_variant_conflict" in diagnostics.reasons
production_preview = score_marketplace_match(
"【SAUGELLA 賽吉兒】菁萃潔浴凝露潤澤二入組",
"《2入特惠》SAUGELLA賽吉兒 菁萃潔浴凝露【日用型】500ml",
)
assert production_preview.hard_veto is True
assert "saugella_variant_conflict" in production_preview.reasons
def test_marketplace_matcher_keeps_mac_powder_single_shade_as_review():
from services.competitor_price_feeder import _classify_low_score_attempt
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【M.A.C】超持妝輕透濾鏡蜜粉(國際航空版)",
"【M.A.C】超持妝輕透濾鏡蜜粉6.5g #絕絕紫",
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is False
assert "variant_selection_review" in diagnostics.reasons
assert _classify_low_score_attempt(diagnostics.score, diagnostics) == "true_low_confidence"
def test_marketplace_matcher_rejects_dr_hsieh_labsmart_vs_repair_serum_line_gap():
from services.marketplace_product_matcher import score_marketplace_match
for momo_name in (
"【Dr.Hsieh 達特醫】官方直營★LabSmart Hi-Tech精華50ml-無盒(神經醯胺/A醇/維生素B3)",
"【Dr.Hsieh 達特醫】官方直營★LabSmart Classic精華50ml-無盒(神經醯胺/A醇/維生素B3/維生素C醣甘)",
):
diagnostics = score_marketplace_match(
momo_name,
"Dr.Hsieh達特醫 神經醯胺多重修復保濕精華液50ml",
momo_price=550,
competitor_price=960,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "dr_hsieh_labsmart_line_conflict" in diagnostics.reasons
same_line = score_marketplace_match(
"Dr.Hsieh達特醫 神經醯胺多重修復保濕精華液50ml",
"Dr.Hsieh 達特醫 神經醯胺多重修復保濕精華液 50ml",
)
assert "dr_hsieh_labsmart_line_conflict" not in same_line.reasons
def test_marketplace_matcher_rejects_kanebo_milano_powder_vs_perfume_type_gap():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Kanebo 佳麗寶】Milano Collection 2024絕色蜜粉餅GR 30g",
"Kanebo Milano Collection 2026 絕色香水30mL",
momo_price=3500,
competitor_price=2900,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "kanebo_milano_type_conflict" in diagnostics.reasons
same_powder = score_marketplace_match(
"【Kanebo 佳麗寶】Milano Collection 2024絕色蜜粉餅GR 30g",
"Kanebo Milano Collection 2024 絕色蜜粉餅 GR 30g",
)
assert "kanebo_milano_type_conflict" not in same_powder.reasons
def test_marketplace_matcher_rejects_hoi_candle_product_line_gap():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【hoi! 好好生活】日京山風香氛天然蠟燭150g",
"hoi!LAB 實驗室香氛天然大豆香氛蠟燭經典篇 150g",
momo_price=780,
competitor_price=699,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "hoi_candle_line_conflict" in diagnostics.reasons
same_line = score_marketplace_match(
"【hoi! 好好生活】日京山風香氛天然蠟燭150g",
"hoi! 日京山風 香氛天然蠟燭 150g",
)
assert "hoi_candle_line_conflict" not in same_line.reasons
def test_marketplace_matcher_rejects_refill_core_vs_case_only_pack():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【KATE 凱婷】3D造型眉彩餅補充芯(眉彩刷、眉餅盒分開販售)",
"【KATE 凱婷】眉彩餅盒一入款(搭配3D造型眉彩餅補充芯)",
momo_price=280,
competitor_price=280,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "accessory_case_conflict" in diagnostics.reasons or "refill_pack_conflict" in diagnostics.reasons
def test_marketplace_matcher_suppresses_wide_price_penalty_for_exact_lip_product():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【REJURAN 麗珠蘭】官方直營|REJURAN 麗駐蘭唇膏 3.7g|台灣總代理 動物性 PDRN",
"REJURAN 麗駐蘭唇膏 3.7g",
momo_price=169,
competitor_price=380,
)
assert diagnostics.score >= 0.76
assert "price_penalty_suppressed_wide_exact_identity" in diagnostics.reasons
def test_marketplace_matcher_promotes_mac_brand_alias_and_exact_compact_name():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【M.A.C】口袋雙色修容打亮盤 7g(國際航空版)",
"【MAC】口袋雙色修容打亮盤 7g",
momo_price=1200,
competitor_price=1200,
)
assert diagnostics.score >= 0.76
def test_marketplace_matcher_promotes_yuskin_bundle_when_only_bundle_wording_differs():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【悠斯晶】經典乳霜120g(4入組)",
"【Yuskin悠斯晶】經典乳霜 4盒組(120g/盒)",
momo_price=1200,
competitor_price=1200,
)
assert diagnostics.score >= 0.76
assert "variant_descriptor_conflict" not in diagnostics.reasons
def test_marketplace_matcher_promotes_ahc_line_with_keyword_reordering():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【AHC】瞬效B5微導玻尿酸保濕精華液30ml_3入(右旋B5/玻尿酸/保濕霸主/高效修護/敏感肌/醫美後適用)",
"【AHC】瞬效保濕B5微導 玻尿酸精華 30ML 3入組",
momo_price=1200,
competitor_price=1200,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor_reordered_line" in diagnostics.reasons
def test_marketplace_matcher_promotes_bundle_equivalent_when_count_matches():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【悠斯晶】經典乳霜120g(4入組)",
"【Yuskin悠斯晶】經典乳霜 4盒組(120g/盒)",
momo_price=1200,
competitor_price=1200,
)
assert diagnostics.score >= 0.76
assert "shared_identity_anchor_bundle_equivalent" in diagnostics.reasons
def test_marketplace_matcher_rejects_same_count_different_unit_family():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"品牌 保濕面膜10片",
"品牌 保濕面膜10盒",
momo_price=399,
competitor_price=1990,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "count_conflict" in diagnostics.reasons
def test_marketplace_matcher_marks_generic_bundle_words_as_unit_comparable():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【NARS】裸光蜜粉餅 雙件組 10g",
"【NARS】裸光蜜粉餅 10g",
momo_price=1999,
competitor_price=1099,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert "bundle_offer_conflict" in diagnostics.reasons
assert diagnostics.comparison_mode == "unit_comparable"
def test_marketplace_matcher_ignores_non_brand_bracket_copy():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【保濕組】理膚寶水 B5 修復霜 40ml",
"理膚寶水 B5 修復霜 40ml",
momo_price=699,
competitor_price=679,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_conflict" not in diagnostics.reasons
def test_marketplace_matcher_uses_brand_alias_and_chinese_line_signal():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【CLARINS 克蘭詩】黃金雙激萃50ml",
"克蘭詩 黃金雙萃精華 50ml",
momo_price=4500,
competitor_price=3549,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
assert "spec_match" in diagnostics.tags
def test_marketplace_matcher_matches_cetaphil_alias():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"舒特膚 AD 乳液 200ml",
"Cetaphil AD 乳液 200ml",
momo_price=980,
competitor_price=899,
)
assert diagnostics.score >= 0.9
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
def test_marketplace_matcher_treats_piece_unit_synonyms_as_same_pack():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"品牌 葉黃素 10mg 60粒",
"品牌 葉黃素 10毫克 60錠",
momo_price=990,
competitor_price=890,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "count_conflict" not in diagnostics.reasons
def test_marketplace_matcher_normalizes_buy_get_pack_evidence():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"NARS 裸光蜜粉餅 買1送1 10g",
"NARS 裸光蜜粉餅 10g x2",
momo_price=1999,
competitor_price=1099,
)
assert diagnostics.comparison_mode == "unit_comparable"
assert "unit_comparable" in diagnostics.reasons
assert "count_conflict" not in diagnostics.reasons
def test_marketplace_matcher_accepts_strong_multi_component_line_without_full_specs():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Gennies 奇妮】COSVITAL乳頭霜50ml+滋潤彈力霜100ml+修復彈力霜100ml(金燦極緻法國頂級孕期產後保養組)",
"Gennies奇妮 COSVITAL 金燦極緻法國頂級保養(乳頭霜+滋潤彈力霜+修復彈力霜)(801062+801081+801082)",
momo_price=6980,
competitor_price=6980,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.comparison_mode == "exact_identity"
assert "strong_component_line_match" in diagnostics.reasons
def test_marketplace_matcher_accepts_known_brand_alias_and_option_copy():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【OBgE】韓國 OBgE 男士自然遮瑕粉底棒13g",
"OBgE/自然遮瑕粉底棒13g - 多款可選",
momo_price=765,
competitor_price=1099,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.comparison_mode == "exact_identity"
def test_marketplace_matcher_accepts_same_pack_with_chinese_count_wording():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【SEBAMED】潔膚露1000ml共2入(大容量 平行輸入)",
"Sebamed施巴 潔膚露1000ml 兩入組",
momo_price=799,
competitor_price=899,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "brand_match" in diagnostics.tags
def test_marketplace_matcher_rejects_razor_series_and_blade_count_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Gillette 吉列】SkinGuard 紳適系列刮鬍刀頭(4刀頭)",
"【Gillette 吉列 】Fusion鋒隱系列刮鬍刀頭(8刀頭)",
momo_price=499,
competitor_price=906,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "count_conflict" in diagnostics.reasons
assert "model_line_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_safe_exact_spec_near_threshold():
from services.marketplace_product_matcher import score_marketplace_match
opi = score_marketplace_match(
"【O.P.I】Top Coat 持久閃耀保色護甲油15mL-IST31(類光繚指甲油專用亮油/小銀蓋/如膠似漆/美甲/官方直營)",
"OPI 官方直營持久閃耀保色護甲油15mL-IST31如膠似漆閃耀系列",
momo_price=578,
competitor_price=680,
)
mustela = score_marketplace_match(
"【Mustela 慕之恬廊】慕之幼 免用水潔淨液 300ml(外出清潔 卸除髒汙 卸除防曬 卸防曬)",
"Mustela慕之恬廊 慕之幼免用水潔淨液300ml",
momo_price=275,
competitor_price=398,
)
romand = score_marketplace_match(
"【rom&nd】韓國 Rom&nd 果汁唇釉 5.5g(韓國彩妝 唇釉 唇彩 果汁 水光感)",
"rom&nd 果汁唇釉5.5g_多款可選",
momo_price=211,
competitor_price=319,
)
muji_hand_cream = score_marketplace_match(
"【MUJI 無印良品】精油芬香護手霜 50g",
"MUJI 無印良品 精油芬香護手霜/薰衣草&迷迭香/50g",
)
muji_brandless_hand_cream = score_marketplace_match(
"【MUJI 無印良品】精油芬香護手霜/50g(薰衣草&迷迭香/葡萄柚&柳橙/檜木&佛手柑)",
"精油芬香護手霜/薰衣草&迷迭香/50g",
)
mustela_lotion_2pack = score_marketplace_match(
"【Mustela 慕之恬廊】慕之幼 爽身潤膚乳500mlX2",
"Mustela慕之恬廊 慕之幼爽身潤膚乳500mlX2",
)
mustela_lotion_2pack_production_title = score_marketplace_match(
"【Mustela 慕之恬廊】慕之幼 加量版爽身潤膚乳 500mlX2入(寶寶 嬰兒乳液 公司貨 台灣獨家總代理)",
"【慕之恬廊】慕之幼爽身潤膚乳(500毫升X2入)",
momo_price=1390,
competitor_price=1210,
)
herbacin_hand_cream = score_marketplace_match(
"【Herbacin 德國小甘菊】小甘菊1號護手霜20ml",
"Herbacin 小甘菊經典護手霜20ml",
)
for diagnostics in (
opi,
mustela,
romand,
muji_hand_cream,
mustela_lotion_2pack,
mustela_lotion_2pack_production_title,
herbacin_hand_cream,
):
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "strong_exact_spec_match" in diagnostics.reasons
assert any(
reason.startswith("shared_identity_anchor")
for reason in mustela_lotion_2pack_production_title.reasons
)
assert muji_brandless_hand_cream.score >= 0.76
assert muji_brandless_hand_cream.hard_veto is False
assert "focused_exact_identity_muji_aroma_hand_cream_brandless" in muji_brandless_hand_cream.reasons
assert "variant_selection_review" in muji_brandless_hand_cream.reasons
def test_marketplace_matcher_does_not_promote_different_option_without_spec():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【DASHING DIVA】MAGICPRESS時尚潮流美甲片_極光之藍",
"Dashing Diva/F 時尚潮流美甲片-月光銀影 MDF5F010AG",
momo_price=331,
competitor_price=420,
)
assert diagnostics.score < 0.76
assert "strong_exact_spec_match" not in diagnostics.reasons
assert "variant_descriptor_conflict" in diagnostics.reasons
def test_marketplace_matcher_keeps_named_option_vs_catalog_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【DASHING DIVA】MAGICPRESS時尚潮流美甲片_極光之藍",
"DASHING DIVA MAGIC PRESS 時尚潮流美甲片 多款任選",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_kate_catalog_vs_single_variant_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【KATE 凱婷】怪獸級持色唇膏 水光款/經典款/微發色款(獨家技術持久不沾 高保濕)",
"【KATE 凱婷】怪獸級持色唇膏(水光) 1.6g",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_so_natural_variant_catalog_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 經典款/光澤款/霧面款/夏日款",
"【SO NATURAL】FIXX 全天候超完美定妝噴霧 120ml",
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
assert "focused_exact_identity_so_natural_fixx_setting_spray_catalog" in diagnostics.reasons
assert "focused_exact_identity_so_natural_fixx_setting_spray_120ml_plain" not in diagnostics.reasons
def test_marketplace_matcher_promotes_variant_safe_exact_option():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【DASHING DIVA】MAGICPRESS時尚潮流美甲片_極光之藍",
"Dashing Diva/F 時尚潮流美甲片-極光之藍 MDF5F001AG",
momo_price=331,
competitor_price=420,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_variant_safe" in diagnostics.reasons
def test_marketplace_matcher_allows_catalog_piece_count_for_exact_dashing_diva_variant():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【DASHING DIVA】MAGICPRESS 時尚潮流美甲片-銀河綠波(貓眼 漸層)",
"Dashing Diva/F 時尚潮流美甲片-銀河綠波 30片/盒 MDF5F012AG",
momo_price=399,
competitor_price=420,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "count_conflict" not in diagnostics.reasons
def test_marketplace_matcher_rejects_explicit_shade_option_mismatch():
from services.marketplace_product_matcher import score_marketplace_match
lipstick = score_marketplace_match(
"【Maybelline 媚比琳】超持久水光鎖吻唇釉#62 4.2ml",
"MAYBELLINE 媚比琳 超持久水光鎖吻唇釉 #120 4.2ml",
momo_price=399,
competitor_price=399,
)
primer = score_marketplace_match(
"【植村秀】水凝光透妝前防護乳 紫色 30ml",
"植村秀 水凝光透妝前防護乳 粉色 30ml",
momo_price=1200,
competitor_price=1100,
)
for diagnostics in (lipstick, primer):
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert diagnostics.score < 0.76
assert "variant_option_conflict" in diagnostics.reasons
def test_marketplace_matcher_accepts_same_explicit_shade_option():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Maybelline 媚比琳】超持久水光鎖吻唇釉#62 4.2ml",
"MAYBELLINE 媚比琳 超持久水光鎖吻唇釉 #62 4.2ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.hard_veto is False
assert diagnostics.comparison_mode == "exact_identity"
assert diagnostics.score >= 0.76
assert "variant_option_conflict" not in diagnostics.reasons
def test_marketplace_matcher_promotes_shared_identity_anchor_near_threshold():
from services.marketplace_product_matcher import score_marketplace_match
obge = score_marketplace_match(
"【OBgE】自然遮瑕素顏霜 50g",
"OBgE/自然遮瑕素顏霜50g",
momo_price=699,
competitor_price=699,
)
unicat = score_marketplace_match(
"【UNICAT 變臉貓】超持久細滑眼線筆1.5ml",
"【UNICAT】超持久細滑眼線筆 1.5ml 新品搶先優惠",
momo_price=399,
competitor_price=399,
)
for diagnostics in (obge, unicat):
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_contained_identity_anchor_with_same_spec():
from services.marketplace_product_matcher import score_marketplace_match
sebamed = score_marketplace_match(
"【Sebamed】女性私密處護潔露200ml",
"Sebamed私密護潔露(pH6.8)黃金女郎型200ml",
momo_price=399,
competitor_price=399,
)
lab52 = score_marketplace_match(
"【Lab52 齒妍堂】兒童口腔清潔棒30入/盒",
"Lab52齒妍堂 兒童口腔清潔棒30入",
momo_price=299,
competitor_price=299,
)
for diagnostics in (sebamed, lab52):
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor" in lab52.reasons or "shared_identity_anchor" in sebamed.reasons
def test_marketplace_matcher_promotes_same_spec_name_alignment_near_threshold():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Sebamed】女性私密處護潔露200ml(國際航空版)",
"Sebamed私密護潔露(pH6.8)黃金女郎型200ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "spec_name_alignment" in diagnostics.reasons or "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_shared_anchor_without_spec_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Les nez 香鼻子】水晶香氛能量寶盒禮盒組(運財、智慧、愛情、守護、和諧、療癒、悟性 聖誕禮物)",
"【Les nez 香鼻子】水晶香氛能量寶盒禮盒組",
momo_price=2480,
competitor_price=2480,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_no_spec" in diagnostics.reasons
def test_marketplace_matcher_promotes_recipe_box_near_threshold_with_variant_safe_anchor():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Recipebox】Recipe Box兒童防曬氣墊粉餅(兒童化妝品/無毒防曬粉餅/天然彩妝)",
"Recipe Box 韓兔 兒童防曬氣墊粉餅",
momo_price=699,
competitor_price=699,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_variant_safe" in diagnostics.reasons
def test_marketplace_matcher_promotes_romand_palette_exact_line():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【rom&nd】勝過眼皮十色眼影盤",
"rom&nd X ZO&FRIENDS 勝過眼皮十色眼影盤 8g/7g",
momo_price=499,
competitor_price=499,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor_variant_safe" in diagnostics.reasons
def test_marketplace_matcher_promotes_lactacyd_private_wash_exact_line():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Lactacyd 立朵舒】私密潔浴露250ml - 滋潤緊緻/加倍修護(私密清潔 產後私密保養 更年期乾癢修護)",
"Lactacyd 立朵舒私密潔浴露-滋潤緊緻250ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_identity_anchor" in diagnostics.reasons
def test_marketplace_matcher_promotes_safe_aroma_lamps_to_total_price():
from services.marketplace_product_matcher import score_marketplace_match
hooome = score_marketplace_match(
"【HOOOME】白色 經典款香氛蠟燭暖燈 薰香燈 蠟燭燈 香氛燈 燭燈 融蠟燈(可調光+附兩顆燈泡+精美禮盒包裝 /",
"【HOOOME】白色 經典款香氛蠟燭暖燈 蠟燭燈 香氛燈 融燭燈 融蠟燈 (可調光+附兩顆燈泡+禮盒包裝)",
momo_price=1290,
competitor_price=1290,
)
gdesign = score_marketplace_match(
"【Gdesign】全新升級 Aroma Lava 解憂放鬆緩緩燈2.0|熔岩燈、精油擴香 2 in 1(熔岩燈/精油/氛圍燈)",
"全新升級 Aroma Lava 解憂放鬆緩緩燈2.0|熔岩燈、精油擴香 2 in 1(熔岩燈/精油/氛圍燈)",
momo_price=1980,
competitor_price=1980,
)
for diagnostics in (hooome, gdesign):
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.match_type == "exact"
assert diagnostics.price_basis == "total_price"
assert diagnostics.alert_tier == "price_alert_exact"
assert "focused_exact_identity_hooome_classic_white_wax_lamp_bulbs_giftbox" in hooome.reasons
def test_marketplace_matcher_blocks_aroma_lamp_style_selection_from_recoverable():
from services.marketplace_product_matcher import score_marketplace_match
named_style_gap = score_marketplace_match(
"【Les nez 香鼻子】香氛融蠟燈 流金歲月(香氛/融蠟燈/交換禮物)",
"【Les nez 香鼻子】香氛融蠟燈 暮光琥珀(手工玻璃)",
)
single_sided_style_gap = score_marketplace_match(
"【Les nez 香鼻子】北歐香氛融蠟燈(香氛/融蠟燈)",
"【Les nez 香鼻子】北歐香氛水晶燈融蠟燈 流光玫瑰金",
)
for diagnostics in (named_style_gap, single_sided_style_gap):
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review" or diagnostics.score < 0.76
assert "aroma_lamp_style_selection_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_keeps_recipe_box_child_polish_catalog_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"韓國 recipebox 可撕式水性兒童指甲油(兒童水性指甲油 可撕式指甲油 韓兔指甲油)",
"【Recipe Box】韓國 recipebox 可撕式水性兒童指甲油",
momo_price=299,
competitor_price=299,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
assert "focused_exact_identity_recipe_box_peelable_child_polish_catalog" in diagnostics.reasons
def test_marketplace_matcher_keeps_aroma_and_nail_variant_gaps_blocked():
from services.marketplace_product_matcher import score_marketplace_match
pavaruni_cross_type = score_marketplace_match(
"【Pavaruni】美國香氛蠟燭20種香味500g(大豆蠟燭禮盒/天然植物精油/花香/木質香/果香)",
"【美國Pavaruni】天然植物香氛精油40種香味10ml 多款任選",
)
dashing_cross_style = score_marketplace_match(
"【DASHING DIVA】MAGICPRESS 時尚潮流美甲片-輕躍裸粉(貓眼 漸層)",
"Dashing Diva/F 時尚潮流美甲片-流光裸色 30片/盒 MDF5F015CG",
)
assert pavaruni_cross_type.hard_veto is True
assert pavaruni_cross_type.score < 0.76
assert dashing_cross_style.score < 0.76
assert "variant_descriptor_conflict" in dashing_cross_style.reasons
def test_marketplace_matcher_blocks_high_score_wax_lamp_and_device_variant_gaps():
from services.marketplace_product_matcher import score_marketplace_match
pray_size_gap = score_marketplace_match(
"【韓國PRAY】守夜人金屬香氛蠟燭暖燈-復古金(L/專櫃公司貨)",
"【韓國EPOCHSIA x Pray】守夜人金屬香氛蠟燭暖燈(S)-復古金",
)
nitori_model_gap = score_marketplace_match(
"【NITORI 宜得利家居】香氛噴霧器 5510(香氛)",
"【NITORI 宜得利家居】香氛噴霧器 YX168 WH",
)
nitori_short_model_gap = score_marketplace_match(
"【NITORI 宜得利家居】香氛噴霧器 5510(香氛)",
"【NITORI 宜得利家居】香氛噴霧器 J82 LBR",
)
assert pray_size_gap.hard_veto is True
assert pray_size_gap.comparison_mode == "not_comparable"
assert "size_letter_variant_conflict" in pray_size_gap.reasons
for diagnostics in (nitori_model_gap, nitori_short_model_gap):
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "nitori_diffuser_model_conflict" in diagnostics.reasons
def test_marketplace_matcher_sends_single_sided_makeup_shade_to_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【LA MER 海洋拉娜】奇蹟煥采氣墊粉霜 24g12g x 2專櫃公司貨",
"《LA MER 海洋拉娜》奇蹟煥采氣墊粉霜 24g12g x 2-11 Rosy Ivory",
)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_sends_single_sided_commercial_condition_to_review():
from services.marketplace_product_matcher import score_marketplace_match
expiry_item = score_marketplace_match(
"即期品【3W CLINIC】膠原蛋白粉底液50mlX2入(保存期限:2026/05)",
"【韓國 3W CLINIC】膠原蛋白粉底液50mlx2入",
)
box_damage_item = score_marketplace_match(
"【Sisley】全能乳液 125ml(新版 國際航空版)",
"sisley 全能乳液 125ml(新) (即期品/盒損品 / 效期至2026年11月)",
)
for diagnostics in (expiry_item, box_damage_item):
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "commercial_condition_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_blocks_spf_and_makeup_spray_line_conflicts():
from services.marketplace_product_matcher import score_marketplace_match
spf_gap = score_marketplace_match(
"【Jealousness 婕洛妮絲】抗UV防曬素顏霜30mlx2(SPF25★★★)",
"Jealousness婕洛妮絲 鳶尾花A醇防曬素顏霜SPF50+★★★30mlx2",
)
spray_line_gap = score_marketplace_match(
"【MAKE UP FOR EVER】超光肌控油定妝噴霧 100ml(黑特霧)",
"MAKE UP FOR EVER 超光肌活氧水-激活版100ml",
)
assert spf_gap.hard_veto is True
assert spf_gap.comparison_mode == "not_comparable"
assert "spf_value_conflict" in spf_gap.reasons
assert spray_line_gap.hard_veto is True
assert spray_line_gap.comparison_mode == "not_comparable"
assert "makeup_spray_line_conflict" in spray_line_gap.reasons
def test_marketplace_matcher_sends_catalog_specific_variant_gaps_to_review():
from services.marketplace_product_matcher import score_marketplace_match
lactacyd = score_marketplace_match(
"【Lactacyd 立朵舒】柔軟滋潤/亮肌柔滑/加倍修護/全日清爽/生理呵護/滋潤緊緻 私密潔浴露250ml/瓶(多款任選)原廠公司貨_樂齡生醫",
"Lactacyd 立朵舒私密潔浴露-亮肌柔滑250ml",
)
body_scrub = score_marketplace_match(
"【我的心機】保濕淨嫩身體去角質400g(三款任選)",
"我的心機 水梨花白麝香淨嫩身體去角質400g",
)
brow_shade = score_marketplace_match(
"【rom&nd】根纖染眉膏 9g推薦 染眉 眉毛 眼妝 染眉膏 romand",
"rom&nd X ZO&FRIENDS 根纖染眉膏 03 摩登米 9g",
)
for diagnostics in (lactacyd, body_scrub, brow_shade):
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_sends_legacy_gate_pass_risks_to_review():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【NARS】官方直營 妝點甜心遮瑕蜜(任選)",
"NARS 妝點甜心遮瑕蜜 1.4ml 多款可選",
"makeup_catalog_selection_gap",
),
(
"【LOREAL Paris 巴黎萊雅】玻尿酸瞬效保濕修護晶露2入組(啵啵精華水/液態紫熨斗/保濕)",
"(2入組)【LOREAL Paris 巴黎萊雅】玻尿酸瞬效保濕水光精華 30ml",
"loreal_serum_variant_gap",
),
(
"【SEBAMED 施巴】洗髮乳1000ml+安絲洗髮乳400ml(總代理)",
"施巴5.5 sebamed (溫和/油性抗屑)洗髮乳1000ml任選x1+安絲洗髮乳400ml",
"sebamed_shampoo_variant_catalog_gap",
),
(
"【Schick 舒適牌】舒綺美型刀 除毛刀(1刀把1刀片)",
"【Schick 舒適牌】舒綺2-in-1美型刀 ( 1刀把1刀片 )",
"schick_2in1_model_gap",
),
(
"【TAICEND 泰陞】寶貝液體保護膜(70ml)",
"【TAICEND泰陞】皮膚保護噴霧(70ml)",
"taicend_protection_form_gap",
),
]
for momo_name, competitor_name, expected_reason in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
assert expected_reason in diagnostics.reasons
def test_marketplace_matcher_blocks_scent_and_core_line_conflicts():
from services.marketplace_product_matcher import score_marketplace_match
rolling_oil_scent_gap = score_marketplace_match(
"【AUS LIFE 澳思萊】檸檬草滾珠精油 5.3ml",
"【AUS LIFE澳思萊】茶樹滾珠精油5.3ml",
)
candle_scent_gap = score_marketplace_match(
"【Time Leisure】聖誕節交換禮物香薰蠟燭擺飾禮盒",
"Time Leisure 聖誕節交換禮物香薰蠟燭擺飾禮盒 英國梨小蒼蘭",
)
ingredient_gap = score_marketplace_match(
"【NOW娜奧】純椰子油膏207ml-Now Foods",
"【NOW 娜奧】Now Foods 純乳木果油油膏 207ml",
)
powder_line_gap = score_marketplace_match(
"【港香蘭】漢本爽身粉100g/盒|誠意中西藥局",
"【港香蘭】艾魔菈 草本爽身粉(100g/罐)",
)
assert rolling_oil_scent_gap.hard_veto is True
assert "aroma_scent_variant_conflict" in rolling_oil_scent_gap.reasons
assert candle_scent_gap.hard_veto is True
assert "aroma_scent_variant_conflict" in candle_scent_gap.reasons
assert ingredient_gap.hard_veto is True
assert "core_ingredient_line_conflict" in ingredient_gap.reasons
assert powder_line_gap.hard_veto is True
assert "branded_powder_line_conflict" in powder_line_gap.reasons
def test_marketplace_matcher_sends_delimited_or_range_catalog_variants_to_review():
from services.marketplace_product_matcher import score_marketplace_match
powder_case = score_marketplace_match(
"【KATE 凱婷】零瑕肌密柔焦粉餅盒/極致零瑕光粉餅盒(單售粉盒)",
"凱婷 極致零瑕光粉餅盒",
)
shu_brow = score_marketplace_match(
"【Shu uemura 植村秀】武士刀眉筆(平輸航空版/多色任選/橡棕.暗灰. 灰棕)",
"《Shu Uemura 植村秀》武士刀眉筆(H9) 4g -#橡棕06",
)
peripera_range = score_marketplace_match(
"【peripera】韓國【PERIPERA 速描眼線膠筆 01~07】現貨 韓國境內版",
"PERIPERA 速描眼線膠筆07淺玫粉",
)
jo_malone = score_marketplace_match(
"【Jo Malone】車用擴香蕊芯1入 多款可選(國際航空版)",
"JO MALONE 車用擴香蕊心-鼠尾草與海鹽 1入",
)
for diagnostics in (powder_case, shu_brow, peripera_range, jo_malone):
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_blocks_cleanser_lotion_line_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Cetaphil 舒特膚】官方直營 三酸煥膚嫩亮修護乳473ml",
"Cetaphil 舒特膚 三酸煥膚嫩亮潔膚露 473ml",
)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "cleanser_lotion_line_conflict" in diagnostics.reasons
def test_marketplace_matcher_sends_single_sided_private_mousse_and_cream_variants_to_review():
from services.marketplace_product_matcher import score_marketplace_match
private_mousse = score_marketplace_match(
"【isLeaf】韓國女性私密防護慕絲250ml二款可選",
"韓國isLeaf 女性私密防護慕絲250ml 花妍巧語",
)
cream_variant = score_marketplace_match(
"【雪芙蘭】滋養霜60g(撫平粗糙 重現光滑)",
"【雪芙蘭】滋養霜《清爽型》60g",
)
for diagnostics in (private_mousse, cream_variant):
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_blocks_romand_lip_line_conflicts():
from services.marketplace_product_matcher import score_marketplace_match
zero_velvet = score_marketplace_match(
"【rom&nd】零絲絨 霧面唇釉 5.5g",
"rom&nd 果汁唇釉5.5g_多款可選",
)
glasting = score_marketplace_match(
"【rom&nd】果凍唇釉 5.5g",
"rom&nd 果汁唇釉5.5g_多款可選",
)
for diagnostics in (zero_velvet, glasting):
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "romand_lip_line_conflict" in diagnostics.reasons
def test_marketplace_matcher_sends_relove_brightening_cleanser_variant_to_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Relove】胺基酸私密潔淨精華凝露120ml",
"RELOVE傳明酸美白潔淨精華凝露120ml",
)
assert diagnostics.hard_veto is False
assert diagnostics.score >= 0.76
assert diagnostics.price_basis == "manual_review"
assert diagnostics.alert_tier == "identity_review"
assert "relove_private_cleanser_variant_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_matcher_blocks_selection1990_wax_lamp_design_conflict():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【1990選物】歐式可彎融燭燈 香氛蠟燭暖燈-黑色款",
"【1990選物】韓風原木底座融燭燈 香氛蠟燭暖燈-黑色款",
)
assert diagnostics.hard_veto is True
assert diagnostics.comparison_mode == "not_comparable"
assert "selection1990_wax_lamp_design_conflict" in diagnostics.reasons
def test_marketplace_matcher_promotes_eaoron_classic_tone_up_cream_exact_line():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Eaoron】澳洲 經典素顏霜 50ml#0000199#(面霜 素顏霜 懶人霜 打造素顏女神)",
"【澳洲 EAORON】第三代經典版白素顏霜 50ml",
momo_price=399,
competitor_price=399,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "strong_exact_spec_match" in diagnostics.reasons
def test_marketplace_matcher_promotes_shared_model_token_for_exact_model():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Panasonic 國際牌】男士身體除毛器 2025新款 ER-GK83 日版 日本直送",
"Panasonic 國際牌 男仕防水美體除毛器 國際版 (ER-GK83)",
momo_price=2490,
competitor_price=2290,
)
assert diagnostics.score >= 0.76
assert diagnostics.hard_veto is False
assert "shared_model_token" in diagnostics.reasons
def test_marketplace_matcher_keeps_variant_warmer_low_score():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Les nez 香鼻子】香氛融蠟燈 閃耀琥珀(附燈泡 定時 調節亮度 聖誕節禮物)",
"【Les nez 香鼻子】香氛融蠟燈 雲石玫瑰琥珀 贈燈泡(定時 可調光 香氛蠟燭 香氛)",
momo_price=1980,
competitor_price=1980,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is False
def test_marketplace_matcher_keeps_generic_vs_specific_warmer_low_score():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【Les nez 香鼻子】北歐香氛融蠟燈(附燈泡 定時 調節亮度)",
"【Les nez 香鼻子】香氛融蠟燈 星夜款",
momo_price=1980,
competitor_price=1980,
)
assert diagnostics.score < 0.76
assert diagnostics.hard_veto is False
assert "variant_descriptor_conflict" in diagnostics.reasons
def test_marketplace_matcher_blocks_unknown_scent_variant_conflicts():
from services.marketplace_product_matcher import score_marketplace_match
cases = [
(
"【無印良品】精油芬香護手霜50g 雨後森林",
"無印良品 MUJI 精油芬香護手霜 50g 午後陽光",
),
(
"【COCODOR】經典擴香瓶200ml 雨後森林",
"cocodor 經典擴香瓶 200ml 午後陽光",
),
]
for momo_name, competitor_name in cases:
diagnostics = score_marketplace_match(momo_name, competitor_name, momo_price=399, competitor_price=390)
assert diagnostics.hard_veto is True
assert diagnostics.match_type == "no_match"
assert diagnostics.price_basis == "none"
assert diagnostics.alert_tier == "suppress"
assert "unknown_scent_variant_conflict" in diagnostics.reasons
def test_marketplace_matcher_blocks_nail_polish_cross_color_names_without_model_code():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【O.P.I】馬拉加葡萄酒 類光繚指甲油 15ml",
"OPI 極地白雪 類光繚指甲油 15ml",
momo_price=520,
competitor_price=500,
)
assert diagnostics.hard_veto is True
assert diagnostics.match_type == "no_match"
assert diagnostics.price_basis == "none"
assert diagnostics.alert_tier == "suppress"
assert "nail_polish_color_name_conflict" in diagnostics.reasons
def test_marketplace_matcher_keeps_wax_lamp_unknown_material_gap_in_review():
from services.marketplace_product_matcher import score_marketplace_match
diagnostics = score_marketplace_match(
"【HOOOME】香氛蠟燭暖燈 陶瓷白色款",
"HOOOME 香氛蠟燭暖燈 玻璃白色款",
momo_price=1280,
competitor_price=1180,
)
assert diagnostics.hard_veto is False
assert diagnostics.price_basis != "total_price"
assert diagnostics.alert_tier != "price_alert_exact"
assert "hooome_wax_lamp_design_gap" in diagnostics.reasons
assert "variant_selection_review" in diagnostics.reasons
def test_marketplace_search_terms_keep_unknown_variant_descriptor_first_for_sensitive_lines():
from services.marketplace_product_matcher import build_search_terms
opi_terms = build_search_terms("【O.P.I】馬拉加葡萄酒 類光繚指甲油 15ml", max_terms=5)
muji_terms = build_search_terms("【無印良品】精油芬香護手霜50g 雨後森林", max_terms=5)
cocodor_terms = build_search_terms("【COCODOR】經典擴香瓶200ml 雨後森林", max_terms=5)
assert "馬拉加葡萄酒" in opi_terms[0]
assert "雨後森林" in muji_terms[0]
assert "雨後森林" in cocodor_terms[0]
assert "雨後森林" in " ".join(muji_terms[:2])
def test_marketplace_search_terms_prefer_readable_brand_core_spec():
from services.marketplace_product_matcher import build_search_terms
terms = build_search_terms("【LA ROCHE-POSAY 理膚寶水】B5全面修復霜 40ml")
assert terms[0] == "理膚寶水 全面修復霜 b5 40ml"
assert not any(term.endswith(" l") for term in terms)
def test_marketplace_search_terms_prioritize_identity_phrase_over_ambiguous_copy():
from services.marketplace_product_matcher import build_search_terms
terms = build_search_terms("【TAICEND 泰陞】寶貝液體保護膜 屁屁噴 100ml", max_terms=5)
assert terms[0] == "泰陞 屁屁噴 100ml"
assert "保護膜" not in terms[0]
assert "屁屁噴" in " ".join(terms[:3])
def test_marketplace_search_terms_drop_option_and_marketing_noise():
from services.marketplace_product_matcher import build_search_terms
terms = build_search_terms("【YSL】情挑誘光嫩唇凍6ml(任選一款/新品上市)", max_terms=5)
assert terms[0] == "ysl 情挑誘光嫩唇凍 6ml"
assert not any("一款" in term or "上市" in term for term in terms)
def test_marketplace_search_terms_keep_professional_product_phrase():
from services.marketplace_product_matcher import build_search_terms
abysse_terms = build_search_terms("【Abysse】天然植萃身體按摩精油550ml", max_terms=5)
mustela_terms = build_search_terms(
"【Mustela 慕之恬廊】慕之幼 免用水潔淨液 300ml(外出清潔 卸除髒汙 卸除防曬 卸防曬)",
max_terms=5,
)
assert abysse_terms[0] == "abysse 身體按摩精油 550ml"
assert mustela_terms[0] == "慕之恬廊 免用水潔淨液 300ml"
assert not any("卸除防曬" in term or "外出清潔" in term for term in mustela_terms)
def test_marketplace_search_terms_keep_variant_descriptor_for_sensitive_lines():
from services.marketplace_product_matcher import build_search_terms
dashing_terms = build_search_terms("【DASHING DIVA】MAGICPRESS時尚潮流美甲片_極光之藍", max_terms=5)
romand_terms = build_search_terms("【rom&nd】勝過眼皮十色眼影盤", max_terms=5)
assert dashing_terms[0] == "dashing diva 時尚潮流美甲片 極光之藍"
assert romand_terms[0] == "romand 勝過眼皮十色眼影盤"
def test_marketplace_search_terms_prioritize_exact_dashing_diva_variant_name():
from services.marketplace_product_matcher import build_search_terms
moon_terms = build_search_terms(
"【DASHING DIVA】MAGICPRESS 時尚潮流美甲片-月影柔霧(貓眼 金色 漸層)",
max_terms=5,
)
silk_terms = build_search_terms(
"【DASHING DIVA】MAGICPRESS 時尚潮流美甲片-銀絲柔彩(紫色 漸層 貓眼)",
max_terms=5,
)
assert moon_terms[0] == "dashing diva 時尚潮流美甲片 月影柔霧"
assert silk_terms[0] == "dashing diva 時尚潮流美甲片 銀絲柔彩"
def test_marketplace_search_terms_prioritize_private_wash_identity_phrase():
from services.marketplace_product_matcher import build_search_terms
terms = build_search_terms(
"【Lactacyd 立朵舒】私密潔浴露250ml - 滋潤緊緻/加倍修護(私密清潔 產後私密保養 更年期乾癢修護)",
max_terms=5,
)
assert terms[0] == "立朵舒 私密潔浴露 250ml"
assert "滋潤緊緻" in terms[1]
def test_marketplace_search_terms_prioritize_precise_primer_identity_phrase():
from services.marketplace_product_matcher import build_search_terms
shu_terms = build_search_terms(
"【植村秀】官方直營 無極限保濕防曬妝前乳30ml(Shu uemura/防曬/保濕/校色",
max_terms=5,
)
meme_terms = build_search_terms(
"【im meme】我愛修膚/水凝光透/控油/好氣色妝前防護乳(SPF50+PA++++)",
max_terms=5,
)
eaoron_terms = build_search_terms(
"【Eaoron】澳洲 經典素顏霜 50ml#0000199#(面霜 素顏霜 懶人霜 打造素顏女神)",
max_terms=5,
)
assert shu_terms[0] == "植村秀 無極限保濕防曬妝前乳 30ml"
assert "校色" not in " ".join(shu_terms[:3])
assert any("水凝光透 妝前防護乳" in term for term in meme_terms[:4])
assert "好氣色" not in " ".join(meme_terms[:3])
assert eaoron_terms[0] == "eaoron 經典素顏霜 50ml"
assert "懶人霜" not in " ".join(eaoron_terms[:3])
def test_marketplace_search_terms_prefer_exact_identity_for_nail_foam_and_foot_mask():
from services.marketplace_product_matcher import build_search_terms
opi_terms = build_search_terms(
"【O.P.I】Top Coat 持久閃耀保色護甲油15mL-IST31(類光繚指甲油專用亮油/小銀蓋/如膠似漆/美甲/官方直營)",
max_terms=5,
)
arau_terms = build_search_terms(
"【arau baby】愛樂寶 溫和洗手慕斯300ml (溫和不乾澀;寶寶共和國)",
max_terms=5,
)
kameria_terms = build_search_terms(
"【KAMERIA】凱蜜菈 足足稱奇足膜17ml*2枚入(任選三款)",
max_terms=5,
)
assert opi_terms[0] == "opi 閃耀保色護甲油 15ml"
assert "小銀蓋" not in " ".join(opi_terms[:3])
assert arau_terms[0] == "愛樂寶 溫和洗手慕斯 300ml"
assert "溫和不乾澀" not in " ".join(arau_terms[:3])
assert kameria_terms[0] == "凱蜜菈 足足稱奇足膜 17ml 2包"
assert "枚入" not in " ".join(kameria_terms[:3])
def test_marketplace_search_terms_preserve_decimal_spec_and_shade_option():
from services.marketplace_product_matcher import build_search_terms
terms = build_search_terms(
"【Maybelline 媚比琳】超持久水光鎖吻唇釉#62 4.2ml",
max_terms=5,
)
assert terms[0] == "媚比琳 超持久水光鎖吻唇釉 62 4.2ml"
assert "4 2ml" not in " ".join(terms)
def test_marketplace_search_terms_prefer_specific_line_over_generic_usage_words():
from services.marketplace_product_matcher import build_search_terms
mask_terms = build_search_terms("【SK-II】官方直營 青春敷面膜10+6+6送12(保濕/面膜/超品日)", max_terms=5)
bottle_terms = build_search_terms(
"【LANCOME 蘭蔻】官方直營 經典款小黑瓶100ml雙入組(LANCOME/經典款/抗老)",
max_terms=5,
)
rose_terms = build_search_terms(
"【蘭蔻】官方直營 玫瑰霜60ml+玫瑰精露150ml(LANCOME/永生玫瑰霜/抗老/PDRN)",
max_terms=5,
)
assert mask_terms[0] == "sk ii 青春敷面膜"
assert bottle_terms[0] == "蘭蔻 小黑瓶 100ml"
assert rose_terms[0] == "蘭蔻 永生玫瑰霜 60ml"
assert "抗老" not in " ".join(bottle_terms[:3] + rose_terms[:3])
assert "pdrn" not in " ".join(term.lower() for term in rose_terms[:3])
def test_marketplace_search_terms_prioritize_exact_identity_for_low_score_frontier_brands():
from services.marketplace_product_matcher import build_search_terms
ludeya_terms = build_search_terms(
"【LUDEYA】蜂王玫瑰外泌微臻霜超值兩入組(60mlX2入)",
max_terms=5,
)
estee_terms = build_search_terms(
"【Estee Lauder 雅詩蘭黛】微分子肌底原生露200ml-櫻花輕盈版(國際航空版)",
max_terms=5,
)
za_palette_terms = build_search_terms(
"【Za】3D立體持色眉彩盤 3.4g(多色可選)",
max_terms=5,
)
za_pencil_terms = build_search_terms(
"【Za】細芯睛彩雙頭眉筆 0.1g(多色任選)",
max_terms=5,
)
peripera_terms = build_search_terms(
"【PERIPERA】雙頭旋轉極細眉筆 0.05g(09灰褐棕)",
max_terms=5,
)
za_classic_terms = build_search_terms(
"【Za】官方直營 經典旋轉眉筆(色號任選)",
max_terms=5,
)
kate_refill_terms = build_search_terms(
"【KATE 凱婷】3D造型眉彩餅補充芯(眉彩刷、眉餅盒分開販售)",
max_terms=5,
)
peripera_liner_terms = build_search_terms(
"【peripera官方直營】速描眼線膠筆_多色任選(極細筆芯 防水抗暈)",
max_terms=5,
)
recipe_box_sunscreen_terms = build_search_terms(
"【Recipe Box】Recipe Box多效提亮防曬霜(兒童化妝品/無毒防曬霜/天然彩妝/防曬/提亮)",
max_terms=5,
)
opi_terms = build_search_terms(
"【O.P.I】紅蘋果 類光繚指甲油-ISLN25(小銀蓋/如膠似漆2.0系列指彩/美甲彩繪/官方直營)",
max_terms=5,
)
assert ludeya_terms[0] == "ludeya 蜂王玫瑰瑰泌霜 60ml"
assert "兩入組" not in " ".join(ludeya_terms[:3])
assert estee_terms[0] == "雅詩蘭黛 微分子肌底原生露 200ml"
assert "櫻花輕盈版" not in " ".join(estee_terms[:3])
assert za_palette_terms[0] == "za 3d立體持色眉彩盤 3.4g"
assert za_pencil_terms[0] == "za 細芯睛彩雙頭眉筆 0.1g"
assert peripera_terms[0] == "peripera 雙頭旋轉極細眉筆 09 0.05g"
assert za_classic_terms[0] == "za 經典旋轉眉筆"
assert kate_refill_terms[0] == "凱婷 3d造型眉彩餅補充芯"
assert peripera_liner_terms[0] == "peripera 速描眼線膠筆"
assert recipe_box_sunscreen_terms[0] == "recipe box 多效提亮防曬霜"
assert opi_terms[0] == "opi 類光繚指甲油 isln25"
def test_batch_compare_top_uses_latest_momo_price_not_revenue(monkeypatch):
from services import pchome_crawler
engine = create_engine("sqlite:///:memory:")
with engine.begin() as conn:
conn.execute(text("CREATE TABLE products (id INTEGER PRIMARY KEY, name TEXT, i_code TEXT)"))
conn.execute(text("CREATE TABLE daily_sales (product_id INTEGER, revenue NUMERIC, date TEXT)"))
conn.execute(text("CREATE TABLE price_records (id INTEGER PRIMARY KEY, product_id INTEGER, price NUMERIC, timestamp TEXT)"))
conn.execute(text("INSERT INTO products VALUES (1, '理膚寶水 B5 修復霜 40ml', 'SKU001')"))
conn.execute(text("INSERT INTO daily_sales VALUES (1, 999999, '2026-05-19')"))
conn.execute(text("INSERT INTO price_records VALUES (1, 1, 699, '2026-05-19 10:00:00')"))
calls = []
def fake_compare_product(name, momo_price, momo_icode=""):
calls.append((name, momo_price, momo_icode))
return {"found": True, "momo_price": momo_price}
monkeypatch.setattr(pchome_crawler, "compare_product", fake_compare_product)
results = pchome_crawler.batch_compare_top(engine, top_n=1)
assert results == [{"found": True, "momo_price": 699.0}]
assert calls == [("理膚寶水 B5 修復霜 40ml", 699.0, "SKU001")]