package service import ( "errors" "gorm.io/gorm" "github.com/sundynix/pets-be/internal/ai" "github.com/sundynix/pets-be/internal/config" "github.com/sundynix/pets-be/internal/model" "github.com/sundynix/pets-be/internal/storage" ) // ErrNotFound 资源不存在(handler 据此返回 40400) var ErrNotFound = errors.New("not found") // ErrPayNotReady 支付未接入。会员开通必须走真实支付,未接入前一律拒绝, // 避免「点一下白拿会员」。 var ErrPayNotReady = errors.New("支付功能即将开放,敬请期待") // ErrForbidden 越权操作(如删除别人的内容) var ErrForbidden = errors.New("无权操作") // ErrInvalidParam 参数不合法(handler 据此返回 40000) var ErrInvalidParam = errors.New("参数不合法") // ErrContentRejected 内容安全判定为违规,直接拒绝发送(不入库) var ErrContentRejected = errors.New("内容包含违规信息,无法发布") // Service 业务逻辑聚合,方法按领域分散在各文件 type Service struct { db *gorm.DB storage *storage.Storage cfg *config.Config ai *ai.Engine } func New(db *gorm.DB, st *storage.Storage, cfg *config.Config, engine *ai.Engine) *Service { return &Service{db: db, storage: st, cfg: cfg, ai: engine} } // ownedPet 校验宠物归属当前用户并返回 func (s *Service) ownedPet(userID, petID string) (*model.Pet, error) { var pet model.Pet err := s.db.Where("id = ? AND user_id = ?", petID, userID).First(&pet).Error if errors.Is(err, gorm.ErrRecordNotFound) { return nil, ErrNotFound } if err != nil { return nil, err } // Age 是计算字段(gorm:"-")。在这里填而不是在每个调用点填 —— // ownedPet 是所有「取一只宠物」的路径的收口,漏一个就会返回空年龄 pet.Age = AgeLabel(pet.Birthday) return &pet, nil }