Files
affiliate_dash/backend/internal/service/provider_test.go
T
yml2213andCursor 6c41834274 fix(delivery): 乐玩不可用时回退 DLC,避免提交 UID 绑定失败
legacy 双渠道配置升为 priority;显式 lewan 且具备 DLC 时允许回退,缓解 LEWAN_* 未注入导致的 bind 失败。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-15 11:51:32 +08:00

143 lines
5.6 KiB
Go
Raw 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.
package service
import (
"testing"
"affiliate_dash/internal/model"
)
func TestParseProductRoutingConfig(t *testing.T) {
// Case 1: 存量老商品未配置,根据 SKU 默认走 DLC
cfg1 := ParseProductRoutingConfig("", "suit_pink_sheep")
if cfg1.RoutingMode != RoutingModeDLC {
t.Fatalf("expected RoutingModeDLC, got %s", cfg1.RoutingMode)
}
if cfg1.DLCGoodID != "682ef3c5a8f40c4234c59f4d" {
t.Fatalf("expected builtin goodID 682ef3c5a8f40c4234c59f4d, got %s", cfg1.DLCGoodID)
}
// Case 2: 仅配置乐玩
cfg2JSON := `{"routing_mode":"lewan","lewan_product_id":"uuid-001","delivery_type":"LINK_BINDING"}`
cfg2 := ParseProductRoutingConfig(cfg2JSON, "any_sku")
if cfg2.RoutingMode != RoutingModeLewan {
t.Fatalf("expected RoutingModeLewan, got %s", cfg2.RoutingMode)
}
if cfg2.LewanProductID != "uuid-001" {
t.Fatalf("expected lewan_product_id uuid-001, got %s", cfg2.LewanProductID)
}
// Case 3: 双平台优先级 (乐玩优先)
cfg3JSON := `{"routing_mode":"priority","priority":["lewan","dlc"],"dlc_good_id":"dlc-123","lewan_product_id":"uuid-123"}`
cfg3 := ParseProductRoutingConfig(cfg3JSON, "any_sku")
if cfg3.RoutingMode != RoutingModePriority {
t.Fatalf("expected RoutingModePriority, got %s", cfg3.RoutingMode)
}
if len(cfg3.Priority) != 2 || cfg3.Priority[0] != ProviderLewan || cfg3.Priority[1] != ProviderDLC {
t.Fatalf("expected priority [lewan, dlc], got %+v", cfg3.Priority)
}
if cfg3.DLCGoodID != "dlc-123" || cfg3.LewanProductID != "uuid-123" {
t.Fatalf("mismatched IDs: dlc=%s lewan=%s", cfg3.DLCGoodID, cfg3.LewanProductID)
}
// Case 4: 兼容历史 legacy 单 provider 字段(无内置 DLC 时仍为 lewan-only)
cfg4JSON := `{"provider":"lewan","lewan_product_id":"uuid-999"}`
cfg4 := ParseProductRoutingConfig(cfg4JSON, "any_sku")
if cfg4.RoutingMode != RoutingModeLewan || cfg4.LewanProductID != "uuid-999" {
t.Fatalf("legacy lewan format failed: %+v", cfg4)
}
// Case 5: legacy 仅有 lewan_product_id,但 SKU 有内置 DLC → 应升为 priority
cfg5JSON := `{"lewan_product_id":"b1fff090-e389-4c6c-9c51-32751582239d"}`
cfg5 := ParseProductRoutingConfig(cfg5JSON, "suit_romantic_destiny")
if cfg5.RoutingMode != RoutingModePriority {
t.Fatalf("expected priority for dual-capable legacy config, got %s", cfg5.RoutingMode)
}
if cfg5.DLCGoodID != "682ef39ca8f40c4234c59f38" {
t.Fatalf("expected builtin DLC good id, got %s", cfg5.DLCGoodID)
}
}
func TestFulfillmentRouterResolution(t *testing.T) {
dlc := NewDLCProvider("https://bff.example", "dlc", nil)
lewan := NewLewanProvider(nil)
router := NewFulfillmentRouter(dlc, lewan)
// Case 1: 存量 DLC 商品
orderDLC := &model.FulfillmentOrder{
ProductSKU: "suit_alan_walker",
}
providers, _ := router.ResolveProviders(orderDLC)
if len(providers) != 1 || providers[0].Name() != ProviderDLC {
t.Fatalf("expected DLC provider for suit_alan_walker, got %d providers", len(providers))
}
// Case 2: 仅乐玩商品
orderLewan := &model.FulfillmentOrder{
ProductSKU: "custom_lewan_item",
MerchantProduct: &model.MerchantProduct{
FulfillmentConfig: `{"routing_mode":"lewan","lewan_product_id":"uuid-001"}`,
},
}
providers, _ = router.ResolveProviders(orderLewan)
if len(providers) != 1 || providers[0].Name() != ProviderLewan {
t.Fatalf("expected Lewan provider, got %d providers", len(providers))
}
// Case 2b: 显式 lewan 但 SKU 有内置 DLC → 应附带 DLC 回退
orderLewanWithDLC := &model.FulfillmentOrder{
ProductSKU: "suit_romantic_destiny",
MerchantProduct: &model.MerchantProduct{
FulfillmentConfig: `{"routing_mode":"lewan","lewan_product_id":"b1fff090-e389-4c6c-9c51-32751582239d","dlc_good_id":""}`,
},
}
providers, _ = router.ResolveProviders(orderLewanWithDLC)
if len(providers) != 2 || providers[0].Name() != ProviderLewan || providers[1].Name() != ProviderDLC {
t.Fatalf("expected [lewan, dlc] fallback, got %v", providerNames(providers))
}
// Case 3: 优先级路由 [lewan, dlc]
orderPriority := &model.FulfillmentOrder{
ProductSKU: "shared_item",
MerchantProduct: &model.MerchantProduct{
FulfillmentConfig: `{"routing_mode":"priority","priority":["lewan","dlc"],"lewan_product_id":"uuid-001","dlc_good_id":"dlc-001"}`,
},
}
providers, _ = router.ResolveProviders(orderPriority)
if len(providers) != 2 || providers[0].Name() != ProviderLewan || providers[1].Name() != ProviderDLC {
t.Fatalf("expected [lewan, dlc], got %v", providers)
}
// Case 4: 订单已锁定渠道(已在 result_data 中写明 provider=dlc)
orderLocked := &model.FulfillmentOrder{
ProductSKU: "shared_item",
MerchantProduct: &model.MerchantProduct{
FulfillmentConfig: `{"routing_mode":"priority","priority":["lewan","dlc"],"lewan_product_id":"uuid-001","dlc_good_id":"dlc-001"}`,
},
ResultData: `{"provider":"dlc"}`,
}
providers, _ = router.ResolveProviders(orderLocked)
if len(providers) != 1 || providers[0].Name() != ProviderDLC {
t.Fatalf("expected locked DLC provider, got %+v", providers)
}
// Case 5: 优先级 [dlc, lewan]
orderDLCFirst := &model.FulfillmentOrder{
ProductSKU: "shared_item",
MerchantProduct: &model.MerchantProduct{
FulfillmentConfig: `{"routing_mode":"priority","priority":["dlc","lewan"],"lewan_product_id":"uuid-001","dlc_good_id":"dlc-001"}`,
},
}
providers, _ = router.ResolveProviders(orderDLCFirst)
if len(providers) != 2 || providers[0].Name() != ProviderDLC || providers[1].Name() != ProviderLewan {
t.Fatalf("expected [dlc, lewan], got %v", providerNames(providers))
}
}
func providerNames(providers []FulfillmentProvider) []string {
names := make([]string, 0, len(providers))
for _, p := range providers {
names = append(names, p.Name())
}
return names
}