package product import ( "context" "encoding/json" "strings" "bindbox-game/internal/pkg/logger" "bindbox-game/internal/repository/mysql" "bindbox-game/internal/repository/mysql/dao" "bindbox-game/internal/repository/mysql/model" ) type Service interface { CreateCategory(ctx context.Context, in CreateCategoryInput) (*model.ProductCategories, error) ModifyCategory(ctx context.Context, id int64, in ModifyCategoryInput) error DeleteCategory(ctx context.Context, id int64) error ListCategories(ctx context.Context, in ListCategoriesInput) (items []*model.ProductCategories, total int64, err error) CreateProduct(ctx context.Context, in CreateProductInput) (*model.Products, error) ModifyProduct(ctx context.Context, id int64, in ModifyProductInput) error DeleteProduct(ctx context.Context, id int64) error ListProducts(ctx context.Context, in ListProductsInput) (items []*model.Products, total int64, err error) } type service struct { logger logger.CustomLogger readDB *dao.Query writeDB *dao.Query } func New(l logger.CustomLogger, db mysql.Repo) Service { return &service{logger: l, readDB: dao.Use(db.GetDbR()), writeDB: dao.Use(db.GetDbW())} } type CreateCategoryInput struct { Name string ParentID int64 Status int32 } type ModifyCategoryInput struct { Name *string ParentID *int64 Status *int32 } type ListCategoriesInput struct { Name string Status *int32 Page int PageSize int } func (s *service) CreateCategory(ctx context.Context, in CreateCategoryInput) (*model.ProductCategories, error) { m := &model.ProductCategories{Name: in.Name, ParentID: in.ParentID, Status: in.Status} if err := s.writeDB.ProductCategories.WithContext(ctx).Create(m); err != nil { return nil, err } return m, nil } func (s *service) ModifyCategory(ctx context.Context, id int64, in ModifyCategoryInput) error { updater := s.writeDB.ProductCategories.WithContext(ctx).Where(s.writeDB.ProductCategories.ID.Eq(id)) set := map[string]any{} if in.Name != nil { set["name"] = *in.Name } if in.ParentID != nil { set["parent_id"] = *in.ParentID } if in.Status != nil { set["status"] = *in.Status } if len(set) == 0 { return nil } _, err := updater.Updates(set) return err } func (s *service) DeleteCategory(ctx context.Context, id int64) error { _, err := s.writeDB.ProductCategories.WithContext(ctx).Where(s.writeDB.ProductCategories.ID.Eq(id)).Delete() return err } func (s *service) ListCategories(ctx context.Context, in ListCategoriesInput) (items []*model.ProductCategories, total int64, err error) { if in.Page <= 0 { in.Page = 1 } if in.PageSize <= 0 { in.PageSize = 20 } q := s.readDB.ProductCategories.WithContext(ctx).ReadDB() if in.Name != "" { q = q.Where(s.readDB.ProductCategories.Name.Like("%" + in.Name + "%")) } if in.Status != nil { q = q.Where(s.readDB.ProductCategories.Status.Eq(*in.Status)) } total, err = q.Count() if err != nil { return } items, err = q.Order(s.readDB.ProductCategories.ID.Desc()).Limit(in.PageSize).Offset((in.Page - 1) * in.PageSize).Find() return } type CreateProductInput struct { Name string CategoryID int64 ImagesJSON string Price int64 Stock int64 Status int32 } type ModifyProductInput struct { Name *string CategoryID *int64 ImagesJSON *string Price *int64 Stock *int64 Status *int32 } type ListProductsInput struct { Name string CategoryID *int64 Status *int32 Page int PageSize int } func (s *service) CreateProduct(ctx context.Context, in CreateProductInput) (*model.Products, error) { m := &model.Products{Name: in.Name, CategoryID: in.CategoryID, ImagesJSON: normalizeJSON(in.ImagesJSON), Price: in.Price, Stock: in.Stock, Status: in.Status} if err := s.writeDB.Products.WithContext(ctx).Create(m); err != nil { return nil, err } return m, nil } func (s *service) ModifyProduct(ctx context.Context, id int64, in ModifyProductInput) error { updater := s.writeDB.Products.WithContext(ctx).Where(s.writeDB.Products.ID.Eq(id)) set := map[string]any{} if in.Name != nil { set["name"] = *in.Name } if in.CategoryID != nil { set["category_id"] = *in.CategoryID } if in.ImagesJSON != nil { set["images_json"] = normalizeJSON(*in.ImagesJSON) } if in.Price != nil { set["price"] = *in.Price } if in.Stock != nil { set["stock"] = *in.Stock } if in.Status != nil { set["status"] = *in.Status } if len(set) == 0 { return nil } _, err := updater.Updates(set) return err } func (s *service) DeleteProduct(ctx context.Context, id int64) error { _, err := s.writeDB.Products.WithContext(ctx).Where(s.writeDB.Products.ID.Eq(id)).Delete() return err } func (s *service) ListProducts(ctx context.Context, in ListProductsInput) (items []*model.Products, total int64, err error) { if in.Page <= 0 { in.Page = 1 } if in.PageSize <= 0 { in.PageSize = 20 } q := s.readDB.Products.WithContext(ctx).ReadDB() if in.Name != "" { q = q.Where(s.readDB.Products.Name.Like("%" + in.Name + "%")) } if in.CategoryID != nil { q = q.Where(s.readDB.Products.CategoryID.Eq(*in.CategoryID)) } if in.Status != nil { q = q.Where(s.readDB.Products.Status.Eq(*in.Status)) } total, err = q.Count() if err != nil { return } items, err = q.Order(s.readDB.Products.ID.Desc()).Limit(in.PageSize).Offset((in.Page - 1) * in.PageSize).Find() return } func normalizeJSON(s string) string { if strings.TrimSpace(s) == "" { return "[]" } var v any if json.Unmarshal([]byte(s), &v) != nil { return "[]" } return s }