Files
affiliate_dash/backend/internal/service/provider_test.go
T
yml2213andCursor 4c68103217 feat(routing): 渠道配置页把 Rock 作为独立履约策略展示
最新的 Rock 商品之前被算进第一平台,配置里也无法单独选择 Rock 库存池。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-05 21:15:20 +08:00

148 lines
5.9 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)
}
cfgRock := ParseProductRoutingConfig(`{"routing_mode":"rock","priority":["rock"],"delivery_type":"LINK_BINDING"}`, "rock_black_tshirt")
if cfgRock.RoutingMode != RoutingModeRock || len(cfgRock.Priority) != 1 || cfgRock.Priority[0] != ProviderRock {
t.Fatalf("expected rock-only routing, got %+v", cfgRock)
}
}
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
}