feat(pickup): 店铺管理支持历史店铺可视化手动映射与一键批量清洗
- 数据库升级:新增 pickup_shop_mappings 映射别名表,并在 admin_pickups 增加 raw_shop_name 永久保留原始店铺录入值 - 后端映射能力:提供历史店铺聚合统计、单条/批量映射至目标标准店铺、映射规则撤销与提号单还原接口;新建提号时若录入已映射别名自动归一化 - 前端管理升级:PickupShopDialog 升级为双 Tab 结构,Tab 2「历史店铺映射与清洗」支持总览统计卡片、状态筛选、单条/批量映射清洗、一键设为标准店铺及撤销还原 - 验证方式:执行并通过全套代码门禁(scripts/check.sh:SQL约束、go vet/build/test、MySQL测试库覆盖率、vue大小、eslint、prettier、vue-tsc及vite构建)
This commit is contained in:
@@ -62,6 +62,7 @@ type PickupDTO struct {
|
||||
Platform string `json:"platform"`
|
||||
ThirdPartyOrderNo string `json:"third_party_order_no"`
|
||||
ShopName string `json:"shop_name"`
|
||||
RawShopName string `json:"raw_shop_name"`
|
||||
AccountSource string `json:"account_source"`
|
||||
SourceChannel string `json:"source_channel"`
|
||||
SettlementMode string `json:"settlement_mode"`
|
||||
@@ -195,6 +196,39 @@ type PickupShopQuery struct {
|
||||
Status string
|
||||
}
|
||||
|
||||
type PickupShopHistoricalItemDTO struct {
|
||||
SourceName string `json:"source_name"`
|
||||
Count int64 `json:"count"`
|
||||
MappingStatus string `json:"mapping_status"` // standard, mapped, unmapped
|
||||
TargetShopID uint64 `json:"target_shop_id,omitempty"`
|
||||
TargetShopName string `json:"target_shop_name,omitempty"`
|
||||
Remark string `json:"remark,omitempty"`
|
||||
}
|
||||
|
||||
type PickupShopHistoricalStatsDTO struct {
|
||||
Items []PickupShopHistoricalItemDTO `json:"items"`
|
||||
TotalPickups int64 `json:"total_pickups"`
|
||||
TotalShops int `json:"total_shops"`
|
||||
StandardCount int `json:"standard_count"`
|
||||
MappedCount int `json:"mapped_count"`
|
||||
UnmappedCount int `json:"unmapped_count"`
|
||||
}
|
||||
|
||||
type MapHistoricalShopsRequest struct {
|
||||
FromShopNames []string `json:"from_shop_names" binding:"required,min=1"`
|
||||
TargetShopName string `json:"target_shop_name" binding:"required,max=100"`
|
||||
CreateTargetMissing bool `json:"create_target_missing"`
|
||||
TargetPlatform string `json:"target_platform" binding:"max=32"`
|
||||
Remark string `json:"remark" binding:"max=255"`
|
||||
}
|
||||
|
||||
type MapHistoricalShopsResultDTO struct {
|
||||
UpdatedPickupsCount int64 `json:"updated_pickups_count"`
|
||||
TargetShopName string `json:"target_shop_name"`
|
||||
TargetShopID uint64 `json:"target_shop_id"`
|
||||
CreatedStandardShop bool `json:"created_standard_shop"`
|
||||
}
|
||||
|
||||
type SellerPickupQuery struct {
|
||||
Page int
|
||||
PageSize int
|
||||
|
||||
@@ -383,6 +383,55 @@ func (h *Handler) DeleteShop(c *gin.Context) {
|
||||
response.OK(c, gin.H{"deleted": true})
|
||||
}
|
||||
|
||||
// GetHistoricalShopStats 获取历史店铺聚合统计及映射情况(管理员)
|
||||
func (h *Handler) GetHistoricalShopStats(c *gin.Context) {
|
||||
stats, err := h.service.GetHistoricalShopStats(c.Request.Context())
|
||||
if err != nil {
|
||||
writePickupError(c, err)
|
||||
return
|
||||
}
|
||||
response.OK(c, stats)
|
||||
}
|
||||
|
||||
// MapHistoricalShops 批量映射历史店铺并清洗提号单(管理员)
|
||||
func (h *Handler) MapHistoricalShops(c *gin.Context) {
|
||||
adminID, ok := currentAdminID(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "缺少管理员上下文")
|
||||
return
|
||||
}
|
||||
var req MapHistoricalShopsRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.BadRequest(c, "映射参数格式不正确")
|
||||
return
|
||||
}
|
||||
res, err := h.service.MapHistoricalShops(c.Request.Context(), req, adminID, auditMeta(c))
|
||||
if err != nil {
|
||||
writePickupError(c, err)
|
||||
return
|
||||
}
|
||||
response.OK(c, res)
|
||||
}
|
||||
|
||||
// DeleteShopMapping 删除历史店铺映射规则并还原提号单(管理员)
|
||||
func (h *Handler) DeleteShopMapping(c *gin.Context) {
|
||||
adminID, ok := currentAdminID(c)
|
||||
if !ok {
|
||||
response.Unauthorized(c, "缺少管理员上下文")
|
||||
return
|
||||
}
|
||||
sourceName := c.Query("source_name")
|
||||
if sourceName == "" {
|
||||
response.BadRequest(c, "缺少 source_name 参数")
|
||||
return
|
||||
}
|
||||
if err := h.service.DeleteShopMapping(c.Request.Context(), sourceName, adminID, auditMeta(c)); err != nil {
|
||||
writePickupError(c, err)
|
||||
return
|
||||
}
|
||||
response.OK(c, gin.H{"deleted": true})
|
||||
}
|
||||
|
||||
func auditMeta(c *gin.Context) auditlog.Meta {
|
||||
return auditlog.Meta{
|
||||
IP: c.ClientIP(),
|
||||
|
||||
@@ -81,6 +81,15 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shopName := strings.TrimSpace(req.ShopName)
|
||||
rawShopName := shopName
|
||||
if shopName != "" {
|
||||
var mapping model.PickupShopMapping
|
||||
if err := tx.Where("source_name = ?", shopName).First(&mapping).Error; err == nil && mapping.TargetShopName != "" {
|
||||
shopName = mapping.TargetShopName
|
||||
}
|
||||
}
|
||||
|
||||
pickup := model.AdminPickup{
|
||||
PickupNo: pickupNo,
|
||||
ListingID: listing.ID,
|
||||
@@ -90,7 +99,8 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
|
||||
Operator: strings.TrimSpace(req.Operator),
|
||||
Platform: strings.TrimSpace(req.Platform),
|
||||
ThirdPartyOrderNo: strings.TrimSpace(req.ThirdPartyOrderNo),
|
||||
ShopName: strings.TrimSpace(req.ShopName),
|
||||
ShopName: shopName,
|
||||
RawShopName: rawShopName,
|
||||
AccountSource: accountSource,
|
||||
SourceChannel: sourceChannel,
|
||||
SettlementMode: pickupSettlementMode(listing.SettlementMode, accountSource),
|
||||
@@ -1086,6 +1096,274 @@ func (r *Repository) DeleteShop(ctx context.Context, id uint64, adminID uint64,
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHistoricalShopStats 聚合统计 admin_pickups 中的全部历史店铺,并对照标准库与映射规则
|
||||
func (r *Repository) GetHistoricalShopStats(ctx context.Context) (*PickupShopHistoricalStatsDTO, error) {
|
||||
if r == nil || r.db == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
|
||||
type rawCountRow struct {
|
||||
SourceName string `gorm:"column:source_name"`
|
||||
Cnt int64 `gorm:"column:cnt"`
|
||||
}
|
||||
var rows []rawCountRow
|
||||
err := r.db.WithContext(ctx).Model(&model.AdminPickup{}).
|
||||
Select("CASE WHEN raw_shop_name <> '' THEN raw_shop_name ELSE shop_name END AS source_name, COUNT(*) AS cnt").
|
||||
Group("source_name").
|
||||
Order("cnt DESC, source_name ASC").
|
||||
Scan(&rows).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var standardShops []model.PickupShop
|
||||
if err := r.db.WithContext(ctx).Model(&model.PickupShop{}).Find(&standardShops).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
standardMap := make(map[string]model.PickupShop)
|
||||
for _, s := range standardShops {
|
||||
standardMap[s.Name] = s
|
||||
}
|
||||
|
||||
var mappings []model.PickupShopMapping
|
||||
if err := r.db.WithContext(ctx).Model(&model.PickupShopMapping{}).Find(&mappings).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mappingMap := make(map[string]model.PickupShopMapping)
|
||||
for _, m := range mappings {
|
||||
mappingMap[m.SourceName] = m
|
||||
}
|
||||
|
||||
var totalPickups int64
|
||||
standardCount := 0
|
||||
mappedCount := 0
|
||||
unmappedCount := 0
|
||||
|
||||
seenSource := make(map[string]bool)
|
||||
items := make([]PickupShopHistoricalItemDTO, 0, len(rows)+len(mappings))
|
||||
|
||||
for _, row := range rows {
|
||||
seenSource[row.SourceName] = true
|
||||
totalPickups += row.Cnt
|
||||
|
||||
item := PickupShopHistoricalItemDTO{
|
||||
SourceName: row.SourceName,
|
||||
Count: row.Cnt,
|
||||
}
|
||||
|
||||
if mapping, ok := mappingMap[row.SourceName]; ok {
|
||||
item.MappingStatus = "mapped"
|
||||
item.TargetShopID = mapping.TargetShopID
|
||||
item.TargetShopName = mapping.TargetShopName
|
||||
item.Remark = mapping.Remark
|
||||
mappedCount++
|
||||
} else if std, ok := standardMap[row.SourceName]; ok && row.SourceName != "" {
|
||||
item.MappingStatus = "standard"
|
||||
item.TargetShopID = std.ID
|
||||
item.TargetShopName = std.Name
|
||||
standardCount++
|
||||
} else {
|
||||
item.MappingStatus = "unmapped"
|
||||
unmappedCount++
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
for _, m := range mappings {
|
||||
if !seenSource[m.SourceName] {
|
||||
mappedCount++
|
||||
items = append(items, PickupShopHistoricalItemDTO{
|
||||
SourceName: m.SourceName,
|
||||
Count: m.MappedCount,
|
||||
MappingStatus: "mapped",
|
||||
TargetShopID: m.TargetShopID,
|
||||
TargetShopName: m.TargetShopName,
|
||||
Remark: m.Remark,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &PickupShopHistoricalStatsDTO{
|
||||
Items: items,
|
||||
TotalPickups: totalPickups,
|
||||
TotalShops: len(items),
|
||||
StandardCount: standardCount,
|
||||
MappedCount: mappedCount,
|
||||
UnmappedCount: unmappedCount,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// MapHistoricalShops 批量将历史店铺名称映射至目标标准店铺,并同步清洗历史提号单中的店铺名
|
||||
func (r *Repository) MapHistoricalShops(ctx context.Context, req MapHistoricalShopsRequest, adminID uint64, meta auditlog.Meta) (*MapHistoricalShopsResultDTO, error) {
|
||||
if r == nil || r.db == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
|
||||
targetName := strings.TrimSpace(req.TargetShopName)
|
||||
if targetName == "" {
|
||||
return nil, ErrInvalidAmount
|
||||
}
|
||||
|
||||
fromNames := make([]string, 0, len(req.FromShopNames))
|
||||
seen := make(map[string]bool)
|
||||
for _, name := range req.FromShopNames {
|
||||
if seen[name] {
|
||||
continue
|
||||
}
|
||||
seen[name] = true
|
||||
fromNames = append(fromNames, name)
|
||||
}
|
||||
if len(fromNames) == 0 {
|
||||
return nil, ErrInvalidAmount
|
||||
}
|
||||
|
||||
var result MapHistoricalShopsResultDTO
|
||||
result.TargetShopName = targetName
|
||||
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var targetShop model.PickupShop
|
||||
findErr := tx.Where("name = ?", targetName).First(&targetShop).Error
|
||||
if errors.Is(findErr, gorm.ErrRecordNotFound) {
|
||||
if !req.CreateTargetMissing {
|
||||
return ErrPickupShopNotFound
|
||||
}
|
||||
now := time.Now()
|
||||
targetShop = model.PickupShop{
|
||||
Name: targetName,
|
||||
Platform: strings.TrimSpace(req.TargetPlatform),
|
||||
Status: PickupShopStatusActive,
|
||||
SortOrder: 0,
|
||||
Remark: "历史映射自动创建",
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&targetShop).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
result.CreatedStandardShop = true
|
||||
} else if findErr != nil {
|
||||
return findErr
|
||||
}
|
||||
result.TargetShopID = targetShop.ID
|
||||
|
||||
// 将未初始化 raw_shop_name 的记录填入旧 shop_name
|
||||
if err := tx.Exec(`UPDATE admin_pickups
|
||||
SET raw_shop_name = shop_name
|
||||
WHERE (raw_shop_name = '' OR raw_shop_name IS NULL)
|
||||
AND (shop_name IN ? OR (shop_name = '' AND '' IN ?))`, fromNames, fromNames).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 批量更新 admin_pickups 的 shop_name
|
||||
res := tx.Model(&model.AdminPickup{}).
|
||||
Where("raw_shop_name IN ?", fromNames).
|
||||
Update("shop_name", targetName)
|
||||
if res.Error != nil {
|
||||
return res.Error
|
||||
}
|
||||
result.UpdatedPickupsCount = res.RowsAffected
|
||||
|
||||
now := time.Now()
|
||||
for _, fromName := range fromNames {
|
||||
if fromName == targetName {
|
||||
continue
|
||||
}
|
||||
var mappedCount int64
|
||||
tx.Model(&model.AdminPickup{}).Where("raw_shop_name = ?", fromName).Count(&mappedCount)
|
||||
|
||||
var existing model.PickupShopMapping
|
||||
if err := tx.Where("source_name = ?", fromName).First(&existing).Error; errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
newMapping := model.PickupShopMapping{
|
||||
SourceName: fromName,
|
||||
TargetShopID: targetShop.ID,
|
||||
TargetShopName: targetName,
|
||||
MappedCount: mappedCount,
|
||||
Remark: strings.TrimSpace(req.Remark),
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
if err := tx.Create(&newMapping).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err == nil {
|
||||
existing.TargetShopID = targetShop.ID
|
||||
existing.TargetShopName = targetName
|
||||
existing.MappedCount = mappedCount
|
||||
if req.Remark != "" {
|
||||
existing.Remark = strings.TrimSpace(req.Remark)
|
||||
}
|
||||
existing.UpdatedAt = now
|
||||
if err := tx.Save(&existing).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
bid := targetShop.ID
|
||||
_ = auditlog.Append(tx, auditlog.Entry{
|
||||
ActorType: "admin",
|
||||
ActorID: adminID,
|
||||
Action: "pickup_shop_map_historical",
|
||||
BizType: "pickup_shop",
|
||||
BizID: &bid,
|
||||
Meta: meta,
|
||||
Detail: map[string]any{
|
||||
"target_shop_id": targetShop.ID,
|
||||
"target_shop_name": targetName,
|
||||
"from_shop_names": fromNames,
|
||||
"updated_count": result.UpdatedPickupsCount,
|
||||
},
|
||||
})
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &result, nil
|
||||
}
|
||||
|
||||
// DeleteShopMapping 删除指定历史店铺的映射规则,并还原历史提号单中的原始店铺名
|
||||
func (r *Repository) DeleteShopMapping(ctx context.Context, sourceName string, adminID uint64, meta auditlog.Meta) error {
|
||||
if r == nil || r.db == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
var mapping model.PickupShopMapping
|
||||
if err := tx.Where("source_name = ?", sourceName).First(&mapping).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if err := tx.Model(&model.AdminPickup{}).
|
||||
Where("raw_shop_name = ?", sourceName).
|
||||
Update("shop_name", sourceName).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tx.Delete(&mapping).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
bid := mapping.ID
|
||||
_ = auditlog.Append(tx, auditlog.Entry{
|
||||
ActorType: "admin",
|
||||
ActorID: adminID,
|
||||
Action: "pickup_shop_unmap_historical",
|
||||
BizType: "pickup_shop",
|
||||
BizID: &bid,
|
||||
Meta: meta,
|
||||
Detail: map[string]any{
|
||||
"source_name": sourceName,
|
||||
"target_shop_name": mapping.TargetShopName,
|
||||
},
|
||||
})
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Repository) ListForSeller(ctx context.Context, ownerID uint64, query SellerPickupQuery) (*PaginatedResult, error) {
|
||||
if r == nil || r.db == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
@@ -1228,6 +1506,7 @@ func (row pickupRow) toDTO() PickupDTO {
|
||||
Platform: row.Platform,
|
||||
ThirdPartyOrderNo: row.ThirdPartyOrderNo,
|
||||
ShopName: row.ShopName,
|
||||
RawShopName: row.RawShopName,
|
||||
AccountSource: row.AccountSource,
|
||||
SourceChannel: row.SourceChannel,
|
||||
SettlementMode: row.SettlementMode,
|
||||
|
||||
@@ -918,3 +918,104 @@ func TestRepositoryPickupShopCRUDAndOptions(t *testing.T) {
|
||||
t.Fatalf("active shops after delete length = %d, want 0", len(shopsAfterDelete))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepositoryHistoricalShopStatsAndMapping(t *testing.T) {
|
||||
repo, db := newPickupTestRepo(t)
|
||||
|
||||
// 1. 创建标准店铺
|
||||
stdShop1, err := repo.CreateShop(t.Context(), CreatePickupShopRequest{
|
||||
Name: "王大锤游戏",
|
||||
Platform: "淘宝",
|
||||
Status: "active",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("CreateShop() error = %v", err)
|
||||
}
|
||||
|
||||
// 2. 插入测试提号记录
|
||||
listing1 := seedAvailableListing(t, db, "LST-MAP-01", "映射测试商品1", false)
|
||||
_, err = repo.Create(t.Context(), CreateRequest{
|
||||
ListingID: listing1.ID,
|
||||
ShopName: "王大锤游戏",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("Create() error = %v", err)
|
||||
}
|
||||
|
||||
listing2 := seedAvailableListing(t, db, "LST-MAP-02", "映射测试商品2", false)
|
||||
_, err = repo.Create(t.Context(), CreateRequest{
|
||||
ListingID: listing2.ID,
|
||||
ShopName: "王大锤游戏专营",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("Create() error = %v", err)
|
||||
}
|
||||
|
||||
listing3 := seedAvailableListing(t, db, "LST-MAP-03", "映射测试商品3", false)
|
||||
_, err = repo.Create(t.Context(), CreateRequest{
|
||||
ListingID: listing3.ID,
|
||||
ShopName: "淘宝王大锤商行",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("Create() error = %v", err)
|
||||
}
|
||||
|
||||
// 3. 获取历史聚合统计
|
||||
stats, err := repo.GetHistoricalShopStats(t.Context())
|
||||
if err != nil {
|
||||
t.Fatalf("GetHistoricalShopStats() error = %v", err)
|
||||
}
|
||||
if stats.TotalShops < 3 {
|
||||
t.Fatalf("stats.TotalShops = %d, want >= 3", stats.TotalShops)
|
||||
}
|
||||
if stats.StandardCount < 1 {
|
||||
t.Fatalf("stats.StandardCount = %d, want >= 1", stats.StandardCount)
|
||||
}
|
||||
|
||||
// 4. 批量映射
|
||||
mapRes, err := repo.MapHistoricalShops(t.Context(), MapHistoricalShopsRequest{
|
||||
FromShopNames: []string{"王大锤游戏专营", "淘宝王大锤商行"},
|
||||
TargetShopName: "王大锤游戏",
|
||||
Remark: "测试批量映射",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("MapHistoricalShops() error = %v", err)
|
||||
}
|
||||
if mapRes.UpdatedPickupsCount != 2 {
|
||||
t.Fatalf("UpdatedPickupsCount = %d, want 2", mapRes.UpdatedPickupsCount)
|
||||
}
|
||||
if mapRes.TargetShopID != stdShop1.ID {
|
||||
t.Fatalf("TargetShopID = %d, want %d", mapRes.TargetShopID, stdShop1.ID)
|
||||
}
|
||||
|
||||
// 5. 再次统计
|
||||
statsAfter, err := repo.GetHistoricalShopStats(t.Context())
|
||||
if err != nil {
|
||||
t.Fatalf("GetHistoricalShopStats() error = %v", err)
|
||||
}
|
||||
if statsAfter.MappedCount < 2 {
|
||||
t.Fatalf("statsAfter.MappedCount = %d, want >= 2", statsAfter.MappedCount)
|
||||
}
|
||||
|
||||
// 6. 验证新建提号自动归一化
|
||||
listing4 := seedAvailableListing(t, db, "LST-MAP-04", "映射测试商品4", false)
|
||||
createdWithAlias, err := repo.Create(t.Context(), CreateRequest{
|
||||
ListingID: listing4.ID,
|
||||
ShopName: "王大锤游戏专营",
|
||||
}, 1, auditlog.Meta{})
|
||||
if err != nil {
|
||||
t.Fatalf("Create() with alias error = %v", err)
|
||||
}
|
||||
if createdWithAlias.ShopName != "王大锤游戏" {
|
||||
t.Fatalf("createdWithAlias.ShopName = %q, want 王大锤游戏", createdWithAlias.ShopName)
|
||||
}
|
||||
if createdWithAlias.RawShopName != "王大锤游戏专营" {
|
||||
t.Fatalf("createdWithAlias.RawShopName = %q, want 王大锤游戏专营", createdWithAlias.RawShopName)
|
||||
}
|
||||
|
||||
// 7. 取消映射
|
||||
if err := repo.DeleteShopMapping(t.Context(), "王大锤游戏专营", 1, auditlog.Meta{}); err != nil {
|
||||
t.Fatalf("DeleteShopMapping() error = %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -176,3 +176,25 @@ func (s *Service) DeleteShop(ctx context.Context, id uint64, adminID uint64, met
|
||||
}
|
||||
return s.repo.DeleteShop(ctx, id, adminID, meta)
|
||||
}
|
||||
|
||||
func (s *Service) GetHistoricalShopStats(ctx context.Context) (*PickupShopHistoricalStatsDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.GetHistoricalShopStats(ctx)
|
||||
}
|
||||
|
||||
func (s *Service) MapHistoricalShops(ctx context.Context, req MapHistoricalShopsRequest, adminID uint64, meta auditlog.Meta) (*MapHistoricalShopsResultDTO, error) {
|
||||
if s.repo == nil {
|
||||
return nil, ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.MapHistoricalShops(ctx, req, adminID, meta)
|
||||
}
|
||||
|
||||
func (s *Service) DeleteShopMapping(ctx context.Context, sourceName string, adminID uint64, meta auditlog.Meta) error {
|
||||
if s.repo == nil {
|
||||
return ErrDependencyUnavailable
|
||||
}
|
||||
return s.repo.DeleteShopMapping(ctx, sourceName, adminID, meta)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user