增加线下提号店铺管理
This commit is contained in:
@@ -37,6 +37,7 @@ type PickupDTO struct {
|
||||
OwnerPhone string `json:"owner_phone"`
|
||||
AdminID uint64 `json:"admin_id"`
|
||||
Platform string `json:"platform"`
|
||||
ShopName string `json:"shop_name"`
|
||||
ListingPriceCent int64 `json:"listing_price_cent"`
|
||||
OwnerPriceCent int64 `json:"owner_price_cent"`
|
||||
WebsiteProfitCent int64 `json:"website_profit_cent"`
|
||||
@@ -56,6 +57,7 @@ type PickupDTO struct {
|
||||
type CreateRequest struct {
|
||||
ListingID uint64 `json:"listing_id" binding:"required"`
|
||||
Platform string `json:"platform"`
|
||||
ShopName string `json:"shop_name" binding:"max=100"`
|
||||
ProfitAmountCent int64 `json:"profit_amount_cent"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
@@ -80,6 +82,7 @@ type AdminPickupQuery struct {
|
||||
PageSize int
|
||||
Keyword string
|
||||
Status string
|
||||
ShopName string
|
||||
}
|
||||
|
||||
type SellerPickupQuery struct {
|
||||
|
||||
@@ -122,6 +122,16 @@ func (h *Handler) List(c *gin.Context) {
|
||||
response.OK(c, result)
|
||||
}
|
||||
|
||||
// ShopOptions 返回后台提号已使用的店铺名称。
|
||||
func (h *Handler) ShopOptions(c *gin.Context) {
|
||||
items, err := h.service.ListShopNames(c.Request.Context(), c.Query("platform"))
|
||||
if err != nil {
|
||||
writePickupError(c, err)
|
||||
return
|
||||
}
|
||||
response.OK(c, items)
|
||||
}
|
||||
|
||||
// Detail 提号订单详情(管理员)
|
||||
func (h *Handler) Detail(c *gin.Context) {
|
||||
id, ok := parseID(c)
|
||||
|
||||
@@ -58,6 +58,7 @@ func parseAdminQuery(c *gin.Context) AdminPickupQuery {
|
||||
PageSize: pageSize,
|
||||
Keyword: c.Query("keyword"),
|
||||
Status: c.Query("status"),
|
||||
ShopName: c.Query("shop_name"),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
|
||||
OwnerID: listing.OwnerID,
|
||||
AdminID: adminID,
|
||||
Platform: strings.TrimSpace(req.Platform),
|
||||
ShopName: strings.TrimSpace(req.ShopName),
|
||||
ListingPriceCent: priceSnapshot.ListingPriceCent,
|
||||
OwnerPriceCent: priceSnapshot.OwnerPriceCent,
|
||||
WebsiteProfitCent: priceSnapshot.WebsiteProfitCent,
|
||||
@@ -145,6 +146,7 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
|
||||
"pickup_no": pickupNo,
|
||||
"listing_id": listing.ID,
|
||||
"platform": pickup.Platform,
|
||||
"shop_name": pickup.ShopName,
|
||||
"profit_cent": pickup.ProfitAmountCent,
|
||||
},
|
||||
}); err != nil {
|
||||
@@ -417,6 +419,9 @@ func (r *Repository) ListAdmin(ctx context.Context, query AdminPickupQuery) (*Pa
|
||||
if status := strings.TrimSpace(query.Status); status != "" {
|
||||
db = db.Where("p.status = ?", status)
|
||||
}
|
||||
if shopName := strings.TrimSpace(query.ShopName); shopName != "" {
|
||||
db = db.Where("p.shop_name = ?", shopName)
|
||||
}
|
||||
if kw := strings.TrimSpace(query.Keyword); kw != "" {
|
||||
like := "%" + kw + "%"
|
||||
db = db.Where("p.pickup_no LIKE ? OR l.listing_no LIKE ? OR a.title LIKE ?", like, like, like)
|
||||
@@ -424,6 +429,23 @@ func (r *Repository) ListAdmin(ctx context.Context, query AdminPickupQuery) (*Pa
|
||||
return r.paginatePickups(db, query.Page, query.PageSize, false)
|
||||
}
|
||||
|
||||
// ListShopNames 返回历史提号中已使用的店铺名称,供后台选择和筛选。
|
||||
func (r *Repository) ListShopNames(ctx context.Context, platform string) ([]string, error) {
|
||||
if r == nil || r.db == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
db := r.db.WithContext(ctx).Model(&model.AdminPickup{}).
|
||||
Where("shop_name <> ''")
|
||||
if value := strings.TrimSpace(platform); value != "" {
|
||||
db = db.Where("platform = ?", value)
|
||||
}
|
||||
names := make([]string, 0)
|
||||
if err := db.Distinct("shop_name").Order("shop_name ASC").Limit(200).Pluck("shop_name", &names).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return names, nil
|
||||
}
|
||||
|
||||
func (r *Repository) ListForSeller(ctx context.Context, ownerID uint64, query SellerPickupQuery) (*PaginatedResult, error) {
|
||||
if r == nil || r.db == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
@@ -453,6 +475,7 @@ func (r *Repository) paginatePickups(db *gorm.DB, page, pageSize int, sellerView
|
||||
item.WebsiteProfitCent = 0
|
||||
item.ProfitAmountCent = 0
|
||||
item.BuyerRatio = 0
|
||||
item.ShopName = ""
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
@@ -521,6 +544,7 @@ func (row pickupRow) toDTO() PickupDTO {
|
||||
OwnerPhone: row.OwnerPhone,
|
||||
AdminID: row.AdminID,
|
||||
Platform: row.Platform,
|
||||
ShopName: row.ShopName,
|
||||
ListingPriceCent: row.ListingPriceCent,
|
||||
OwnerPriceCent: row.OwnerPriceCent,
|
||||
WebsiteProfitCent: row.WebsiteProfitCent,
|
||||
|
||||
@@ -125,6 +125,62 @@ func TestRepositoryUpdateProfitRejectsCompleted(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoryListAdminFiltersShopName(t *testing.T) {
|
||||
repo, db := newPickupTestRepo(t)
|
||||
first := seedPickup(t, db, StatusPickingUp)
|
||||
if err := db.Model(&first).Updates(map[string]any{
|
||||
"platform": "淘宝",
|
||||
"shop_name": "大锤一店",
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("设置第一条提号店铺失败: %v", err)
|
||||
}
|
||||
second := first
|
||||
second.ID = 0
|
||||
second.PickupNo = "PK-PROFIT-002"
|
||||
second.ShopName = "大锤二店"
|
||||
if err := db.Create(&second).Error; err != nil {
|
||||
t.Fatalf("创建第二条提号记录失败: %v", err)
|
||||
}
|
||||
|
||||
result, err := repo.ListAdmin(t.Context(), AdminPickupQuery{ShopName: " 大锤一店 "})
|
||||
if err != nil {
|
||||
t.Fatalf("ListAdmin() error = %v", err)
|
||||
}
|
||||
if result.Total != 1 || len(result.Items) != 1 {
|
||||
t.Fatalf("店铺筛选结果 = total %d, items %d, want 1", result.Total, len(result.Items))
|
||||
}
|
||||
if result.Items[0].ShopName != "大锤一店" {
|
||||
t.Fatalf("店铺名称 = %q, want 大锤一店", result.Items[0].ShopName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoryListShopNamesReturnsDistinctPlatformOptions(t *testing.T) {
|
||||
repo, db := newPickupTestRepo(t)
|
||||
first := seedPickup(t, db, StatusPickingUp)
|
||||
if err := db.Model(&first).Updates(map[string]any{
|
||||
"platform": "淘宝",
|
||||
"shop_name": "大锤一店",
|
||||
}).Error; err != nil {
|
||||
t.Fatalf("设置第一条提号店铺失败: %v", err)
|
||||
}
|
||||
for index, row := range []model.AdminPickup{
|
||||
{PickupNo: "PK-SHOP-002", ListingID: first.ListingID, AccountID: first.AccountID, OwnerID: first.OwnerID, AdminID: 1, Platform: "淘宝", ShopName: "大锤一店", Status: StatusPickingUp},
|
||||
{PickupNo: "PK-SHOP-003", ListingID: first.ListingID, AccountID: first.AccountID, OwnerID: first.OwnerID, AdminID: 1, Platform: "拼多多", ShopName: "大锤二店", Status: StatusPickingUp},
|
||||
} {
|
||||
if err := db.Create(&row).Error; err != nil {
|
||||
t.Fatalf("创建第 %d 条店铺选项失败: %v", index+2, err)
|
||||
}
|
||||
}
|
||||
|
||||
names, err := repo.ListShopNames(t.Context(), "淘宝")
|
||||
if err != nil {
|
||||
t.Fatalf("ListShopNames() error = %v", err)
|
||||
}
|
||||
if len(names) != 1 || names[0] != "大锤一店" {
|
||||
t.Fatalf("淘宝店铺选项 = %v, want [大锤一店]", names)
|
||||
}
|
||||
}
|
||||
|
||||
func assertInt64(t *testing.T, name string, got, want int64) {
|
||||
t.Helper()
|
||||
if got != want {
|
||||
|
||||
@@ -77,6 +77,13 @@ func (s *Service) ListAdmin(ctx context.Context, query AdminPickupQuery) (*Pagin
|
||||
return s.repo.ListAdmin(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) ListShopNames(ctx context.Context, platform string) ([]string, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.ListShopNames(ctx, platform)
|
||||
}
|
||||
|
||||
func (s *Service) ListForSeller(ctx context.Context, ownerID uint64, query SellerPickupQuery) (*PaginatedResult, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
|
||||
Reference in New Issue
Block a user