package listing import ( "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) } type publicZoneCountCache struct { Counts map[string]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元)