feat(distribution): 完善分销站与主站业务数据及权益风控隔离,修复历史商品归属

This commit is contained in:
yml2213
2026-09-08 15:25:46 +08:00
parent 0fcb6a513f
commit fd4e490ed3
16 changed files with 221 additions and 35 deletions
@@ -103,7 +103,8 @@ func (h *Handler) ListMine(c *gin.Context) {
response.Unauthorized(c, "缺少用户上下文")
return
}
items, err := h.service.ListMine(c.Request.Context(), ownerID)
siteCode := strings.TrimSpace(c.GetHeader("X-Distribution-Site-Code"))
items, err := h.service.ListMine(c.Request.Context(), ownerID, siteCode)
if err != nil {
writeListingError(c, err)
return
+11 -5
View File
@@ -170,12 +170,18 @@ func (r *Repository) FindAdmin(ctx context.Context, listingID uint64) (*ListingD
return r.findDTO(ctx, "l.id = ?", listingID)
}
func (r *Repository) ListMine(ctx context.Context, ownerID uint64) ([]ListingDTO, error) {
func (r *Repository) ListMine(ctx context.Context, ownerID uint64, siteCode ...string) ([]ListingDTO, error) {
var rows []listingRow
err := r.baseQuery(ctx).
Where("l.owner_id = ?", ownerID).
Order("l.id DESC").
Scan(&rows).Error
base := r.baseQuery(ctx).Where("l.owner_id = ?", ownerID)
if len(siteCode) > 0 {
code := strings.TrimSpace(siteCode[0])
if code != "" {
base = base.Joins("INNER JOIN distribution_sites AS my_ds ON my_ds.id = l.distribution_site_id AND my_ds.site_code = ?", code)
} else {
base = base.Where("l.distribution_site_id IS NULL OR l.distribution_site_id = 0")
}
}
err := base.Order("l.id DESC").Scan(&rows).Error
if err != nil {
return nil, err
}
@@ -11,11 +11,11 @@ func (s *Service) ListPublic(ctx context.Context, query PublicListQuery) (*Publi
return s.repo.ListPublic(ctx, query)
}
func (s *Service) ListMine(ctx context.Context, ownerID uint64) ([]ListingDTO, error) {
func (s *Service) ListMine(ctx context.Context, ownerID uint64, siteCode ...string) ([]ListingDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
return s.repo.ListMine(ctx, ownerID)
return s.repo.ListMine(ctx, ownerID, siteCode...)
}
func (s *Service) FindPublic(ctx context.Context, id uint64) (*ListingDTO, error) {
@@ -888,3 +888,63 @@ func TestCreateListingWithDistributionSiteCode(t *testing.T) {
}
}
func TestListMineSiteIsolation(t *testing.T) {
db := database.NewTestDB()
if err := database.MigrateListingLifecycleTestSchema(db); err != nil {
t.Fatalf("migrate err: %v", err)
}
repo := NewRepository(db, nil)
user := model.User{Phone: "18800000002", Nickname: "多站卖家", RealnameStatus: "verified", Status: "active"}
db.Create(&user)
site := model.DistributionSite{
SiteCode: "dist_x",
SiteName: "分销X",
Domain: "x.com",
Status: "active",
DisplayAccountEnabled: true,
}
db.Create(&site)
req1 := CreateRequest{Title: "主站商品", ServerRegion: "QQ", LoginPlatform: "PC", PriceCent: 1000}
l1, err := repo.Create(context.Background(), user.ID, req1, false, 0)
if err != nil {
t.Fatalf("Create main failed: %v", err)
}
req2 := CreateRequest{Title: "分销商品", ServerRegion: "QQ", LoginPlatform: "PC", PriceCent: 2000}
l2, err := repo.Create(context.Background(), user.ID, req2, false, 0, "dist_x")
if err != nil {
t.Fatalf("Create dist failed: %v", err)
}
// 1. 分销站查询只返回分销站商品
distItems, err := repo.ListMine(context.Background(), user.ID, "dist_x")
if err != nil {
t.Fatalf("ListMine dist_x err: %v", err)
}
if len(distItems) != 1 || distItems[0].ID != l2.ID {
t.Fatalf("expected only dist listing %d, got %v", l2.ID, distItems)
}
// 2. 主站查询只返回主站商品
mainItems, err := repo.ListMine(context.Background(), user.ID, "")
if err != nil {
t.Fatalf("ListMine main err: %v", err)
}
if len(mainItems) != 1 || mainItems[0].ID != l1.ID {
t.Fatalf("expected only main listing %d, got %v", l1.ID, mainItems)
}
// 3. 不传站点时兼容返回全部
allItems, err := repo.ListMine(context.Background(), user.ID)
if err != nil {
t.Fatalf("ListMine all err: %v", err)
}
if len(allItems) != 2 {
t.Fatalf("expected 2 listings, got %d", len(allItems))
}
}