Files
hfb_sys/backend/internal/modules/listing/repository.go
T

96 lines
2.8 KiB
Go

package listing
import (
"context"
"errors"
"sync"
"time"
"gorm.io/gorm"
"hfb_sys/backend/internal/model"
)
// ListingChatCreator 发布群创建接口(由 chat 模块实现,避免直接依赖)
type ListingChatCreator interface {
EnsureListingConversation(tx *gorm.DB, listing model.RentalListing, supportAdminID uint64) (conversationID uint64, err error)
}
// ListingShelfSyncer 商品上架后的分站货架铺货接口(由 distribution 模块实现,避免模块反向依赖)。
//
// 所有站点与主站共用同一批已审核商品,因此商品审核通过后必须自动出现在各分站货架,
// 不能依赖站长手动「一键同步主站商品」。
type ListingShelfSyncer interface {
EnsureListingShelvedTx(tx *gorm.DB, listingID, accountID uint64) error
}
type Repository struct {
db *gorm.DB
publicZoneCountsMu sync.Mutex
publicZoneCounts publicZoneCountCache
chatCreator ListingChatCreator
shelfSyncer ListingShelfSyncer
}
func NewRepository(db *gorm.DB, chatCreator ListingChatCreator) *Repository {
return &Repository{
db: db,
chatCreator: chatCreator,
}
}
// SetShelfSyncer 注入货架铺货实现;未注入(如未接入分销模块的环境)时自动铺货为 no-op。
func (r *Repository) SetShelfSyncer(syncer ListingShelfSyncer) {
if r == nil {
return
}
r.shelfSyncer = syncer
}
// syncPublishedShelf 只在商品真正对外可售(published + approved)时铺货到各分站货架。
// 草稿、待审核、已下架商品不需要铺货:分站前台本身就要求 published + approved 才展示。
func (r *Repository) syncPublishedShelf(tx *gorm.DB, listing *model.RentalListing) error {
if r == nil || r.shelfSyncer == nil || listing == nil {
return nil
}
if listing.Status != "published" || listing.ReviewStatus != "approved" {
return nil
}
return r.shelfSyncer.EnsureListingShelvedTx(tx, listing.ID, listing.AccountID)
}
func (r *Repository) IsQualityOwner(ctx context.Context, userID uint64) (bool, error) {
if r == nil || r.db == nil {
return false, ErrDependencyUnavailable
}
var status string
err := r.db.WithContext(ctx).Model(&model.User{}).
Where("id = ?", userID).
Pluck("quality_owner_status", &status).Error
if err != nil {
return false, err
}
return status == "active", nil
}
type publicZoneCountCache struct {
Counts map[string]int64
NonPremiumTotal int64
ExpiresAt time.Time
}
const publicZoneCountCacheTTL = 5 * time.Second
func initialPublishState(reviewRequired bool) (string, string, *time.Time) {
if reviewRequired {
return "draft", "pending", nil
}
now := time.Now()
return "published", "approved", &now
}
func IsNotFound(err error) bool {
return errors.Is(err, gorm.ErrRecordNotFound)
}
// roundMoney 使用统一的角精度(0.1元)