diff --git a/constants/min_purchase_box.go b/constants/min_purchase_box.go new file mode 100644 index 00000000..9b26d20c --- /dev/null +++ b/constants/min_purchase_box.go @@ -0,0 +1,6 @@ +package constants + +type Purchase int64 + +// 最低购买箱数 +const MIN_PURCHASE_QUANTITY Purchase = 3 diff --git a/model/gmodel/fs_shopping_cart_gen.go b/model/gmodel/fs_shopping_cart_gen.go index 0cdf795f..2997ec11 100644 --- a/model/gmodel/fs_shopping_cart_gen.go +++ b/model/gmodel/fs_shopping_cart_gen.go @@ -12,22 +12,15 @@ type FsShoppingCart struct { ProductId *int64 `gorm:"default:0;" json:"product_id"` // 产品id TemplateId *int64 `gorm:"default:0;" json:"template_id"` // 模板id ModelId *int64 `gorm:"default:0;" json:"model_id"` // 模型id - PriceId *int64 `gorm:"default:0;" json:"price_id"` // 价格id SizeId *int64 `gorm:"default:0;" json:"size_id"` // 尺寸id - MaterialId *int64 `gorm:"default:0;" json:"material_id"` // 材质id FittingId *int64 `gorm:"default:0;" json:"fitting_id"` // 配件id PurchaseQuantity *int64 `gorm:"default:0;" json:"purchase_quantity"` // 购买数量 - UnitPrice *int64 `gorm:"default:0;" json:"unit_price"` // 当时加入购物车的单价,不作为支付计算,支付计算需要实时价格(厘)换算美元除以1000 - TotalPrice *int64 `gorm:"default:0;" json:"total_price"` // 当时加入购物车单价x数量的总价,不作为支付计算,支付计算需要实时价格 - Logo *string `gorm:"default:'';" json:"logo"` // - CombineImage *string `gorm:"default:'';" json:"combine_image"` // - RenderImage *string `gorm:"default:'';" json:"render_image"` // Snapshot *string `gorm:"default:'';" json:"snapshot"` // IsHighlyCustomized *int64 `gorm:"default:0;" json:"is_highly_customized"` // 是否高度定制 0非 1是(针对客人高度定制只能后台增加如购物车) Status *int64 `gorm:"default:0;" json:"status"` // 0未下单 1已下单 IsEffective *int64 `gorm:"default:1;" json:"is_effective"` // 是否有效 0非 1是(针对对购物车下单,此前数据表更失效) - IsDeleted *int64 `gorm:"default:0;" json:"is_deleted"` // 0正常 1删除 Ctime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"ctime"` // + Utime *time.Time `gorm:"default:'0000-00-00 00:00:00';" json:"utime"` // } type FsShoppingCartModel struct { db *gorm.DB diff --git a/model/gmodel/fs_shopping_cart_logic.go b/model/gmodel/fs_shopping_cart_logic.go index e68225aa..684078ce 100644 --- a/model/gmodel/fs_shopping_cart_logic.go +++ b/model/gmodel/fs_shopping_cart_logic.go @@ -1,2 +1,48 @@ package gmodel -// TODO: 使用model的属性做你想做的 \ No newline at end of file + +import "context" + +// 获取用户购物车数量 +func (s *FsShoppingCartModel) CountUserCart(ctx context.Context, userId int64) (total int64, err error) { + err = s.db.WithContext(ctx).Where("user_id = ?", userId).Limit(1).Count(&total).Error + return total, err +} + +// 获取单个 +func (s *FsShoppingCartModel) FindOne(ctx context.Context, id int64, fields ...string) (resp *FsShoppingCart, err error) { + db := s.db.WithContext(ctx).Where("id = ?", id) + if len(fields) > 0 { + db = db.Select(fields[0]) + } + err = db.Take(&resp).Error + return resp, err +} + +// 获取多个 +func (s *FsShoppingCartModel) GetAllByIds(ctx context.Context, ids []int64, sort string, fields ...string) (resp []FsShoppingCart, err error) { + if len(ids) == 0 { + return + } + db := s.db.WithContext(ctx).Where("id in (?)", ids) + if len(fields) > 0 { + db = db.Select(fields[0]) + } + if sort != "" { + db = db.Order(sort) + } + err = db.Find(&resp).Error + return resp, err +} + +// 获取用户所有的购物车 +func (s *FsShoppingCartModel) GetUserAllCarts(ctx context.Context, userId int64, sort string, fields ...string) (resp []FsShoppingCart, err error) { + db := s.db.WithContext(ctx).Where("user_id = ?", userId) + if len(fields) > 0 { + db = db.Select(fields[0]) + } + if sort != "" { + db = db.Order(sort) + } + err = db.Find(&resp).Error + return resp, err +} diff --git a/server/shopping-cart/internal/logic/addtocartlogic.go b/server/shopping-cart/internal/logic/addtocartlogic.go index 858ad0d6..f6cca17b 100644 --- a/server/shopping-cart/internal/logic/addtocartlogic.go +++ b/server/shopping-cart/internal/logic/addtocartlogic.go @@ -1,12 +1,16 @@ package logic import ( + "context" "errors" + "fmt" + "fusenapi/constants" + "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/basic" + "fusenapi/utils/shopping_cart" "gorm.io/gorm" - - "context" + "math" "fusenapi/server/shopping-cart/internal/svc" "fusenapi/server/shopping-cart/internal/types" @@ -40,8 +44,17 @@ func (l *AddToCartLogic) AddToCart(req *types.AddToCartReq, userinfo *auth.UserI if err := l.AddToCartParamVerify(req); err != nil { return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, err.Error()) } - //获取产品信息 - productInfo, err := l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId) + //查询该用户购物车数量 + cartCount, err := l.svcCtx.AllModels.FsShoppingCart.CountUserCart(l.ctx, userinfo.UserId) + if err != nil { + logx.Error(err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get the count of your shopping cart") + } + if cartCount >= 100 { + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "sorry,the count of your carts can`t greater than 100") + } + //获取产品是否存在 + _, err = l.svcCtx.AllModels.FsProduct.FindOne(l.ctx, req.ProductId, "id") if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists") @@ -49,23 +62,66 @@ func (l *AddToCartLogic) AddToCart(req *types.AddToCartReq, userinfo *auth.UserI logx.Error("获取产品信息错误:", err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info") } - //获取模板信息 - templateInfo, err := l.svcCtx.AllModels.FsProductTemplateV2.FindOne(l.ctx, req.TemplateId) + var ( + templateJson string //模板表的记录中的json设计信息 + templateTag string //模板表的模板标签 + fittingJson string //配件的json设计信息 + ) + //有模板 + if req.TemplateId > 0 { + templateInfo, err := l.svcCtx.AllModels.FsProductTemplateV2.FindOne(l.ctx, req.TemplateId) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the template is not exists") + } + logx.Error("获取模板信息错误:", err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template info") + } + if *templateInfo.IsDel == 1 { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template is deleted") + } + if *templateInfo.Status != 1 { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template`s status is unNormal") + } + if templateInfo.TemplateInfo == nil || *templateInfo.TemplateInfo == "" { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template`s design info is empty") + } + templateJson = *templateInfo.TemplateInfo + templateTag = *templateInfo.TemplateTag + } + //有配件 + if req.FittingId > 0 { + fittingInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, req.FittingId) + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the fitting is not exists") + } + logx.Error("获取配件信息错误:", err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting info") + } + if *fittingInfo.Status != 1 { + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the fitting`s status is unNormal") + } + if fittingInfo.ModelInfo == nil || *fittingInfo.ModelInfo == "" { + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "the fitting`s design info is empty") + } + fittingJson = *fittingInfo.ModelInfo + } + //获取尺寸信息 + sizeInfo, err := l.svcCtx.AllModels.FsProductSize.FindOne(l.ctx, req.SizeId) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { - return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the template is not exists") + return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the size is not exists") } - logx.Error("获取模板信息错误:", err) - return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template info") + logx.Error("获取尺寸信息错误:", err) + return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get size info") } - if *templateInfo.IsDel == 1 { - return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template is deleted") - } - if *templateInfo.Status != 1 { - return resp.SetStatusWithMessage(basic.CodeServiceErr, "the template`s status is unNormal") + //状态 + if *sizeInfo.Status != 1 { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "size info status is not normal") } //获取模型信息 - modelInfo, err := l.svcCtx.AllModels.FsProductModel3d.FindOne(l.ctx, *templateInfo.ModelId) + modelInfo, err := l.svcCtx.AllModels.FsProductModel3d.GetOneBySizeIdTag(l.ctx, sizeInfo.Id, constants.TAG_MODEL) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the template`s model is not exists") @@ -73,39 +129,56 @@ func (l *AddToCartLogic) AddToCart(req *types.AddToCartReq, userinfo *auth.UserI logx.Error("获取模型信息错误:", err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get template`s model info") } - //模型里面的size_id是否跟传入的size_id匹配 - if req.SizeId != *modelInfo.SizeId { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "param size_id is not match model`s size_id") + if *modelInfo.Status != 1 { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model` status is unNormal") } - //获取尺寸信息 - sizeInfo, err := l.svcCtx.AllModels.FsProductSize.FindOne(l.ctx, req.SizeId) - if err != nil { - if errors.Is(err, gorm.ErrRecordNotFound) { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "the size is not exists") - } - logx.Error("获取尺寸信息错误:", err) - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "failed to get size info") + //如果模型是配件则返回 + if *modelInfo.Tag != 1 { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model your post is not a model but fitting") } - //状态 - if *sizeInfo.Status != 1 { - return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "size info status is not normal") + if modelInfo.ModelInfo == nil || *modelInfo.ModelInfo == "" { + return resp.SetStatusWithMessage(basic.CodeServiceErr, "the model`s design info is empty") } + //快照数据 + snapshot := shopping_cart.CartSnapshot{ + Logo: req.Logo, + CombineImage: req.CombineImage, + RenderImage: req.RenderImage, + TemplateInfo: shopping_cart.TemplateInfo{ + TemplateJson: templateJson, + TemplateTag: templateTag, + }, + ModelInfo: shopping_cart.ModelInfo{ + ModelJson: *modelInfo.ModelInfo, + }, + FittingInfo: shopping_cart.FittingInfo{ + FittingJson: fittingJson, + }, + SizeInfo: shopping_cart.SizeInfo{ + Title: *sizeInfo.Title, + }, + UserDiyInformation: shopping_cart.UserDiyInformation{ + Phone: req.DiyInfo.Phone, + Address: req.DiyInfo.Address, + Website: req.DiyInfo.Website, + Qrcode: req.DiyInfo.Qrcode, + Slogan: req.DiyInfo.Slogan, + }, + } + //根据 return resp.SetStatus(basic.CodeOK) } // 参数校验 func (l *AddToCartLogic) AddToCartParamVerify(req *types.AddToCartReq) error { if req.ProductId <= 0 { - return errors.New("invalid param:product_id") + return errors.New("product_id is required") } if req.SizeId <= 0 { - return errors.New("invalid param:size_id") - } - if req.TemplateId <= 0 { - return errors.New("invalid param:template_id") + return errors.New("product size is required") } if req.PurchaseQuantity <= 0 { - return errors.New("invalid param:purchase_quantity") + return errors.New("purchase quantity can not less than 0 or equal 0") } return nil } diff --git a/server/shopping-cart/internal/types/types.go b/server/shopping-cart/internal/types/types.go index 4dbebdbb..5d474939 100644 --- a/server/shopping-cart/internal/types/types.go +++ b/server/shopping-cart/internal/types/types.go @@ -6,14 +6,23 @@ import ( ) type AddToCartReq struct { - ProductId int64 `json:"product_id"` //产品id - TemplateId int64 `json:"template_id"` //模板id - SizeId int64 `json:"size_id"` //尺寸id - FittingId int64 `json:"fitting_id"` //配件id - PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量 - Logo string `json:"logo"` //logo地址 - CombineImage string `json:"combine_image"` //合图地址 - RenderImage string `json:"render_image"` //渲染结果图 + ProductId int64 `json:"product_id"` //产品id + TemplateId int64 `json:"template_id,optional"` //模板id(不可定制的不传) + SizeId int64 `json:"size_id"` //尺寸id + FittingId int64 `json:"fitting_id,optional"` //配件id(没有可以不传) + PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量 + Logo string `json:"logo,optional"` //logo地址(没有可以不传) + CombineImage string `json:"combine_image,optional"` //合图地址 (没有可以不传) + RenderImage string `json:"render_image,optional"` //渲染结果图 (没有可以不传) + DiyInfo DiyInfo `json:"diy_info,optional"` //用户diy数据(可选) +} + +type DiyInfo struct { + Phone string `json:"phone,optional"` //电话(可选) + Address string `json:"address,optional"` //地址 (可选) + Website string `json:"website,optional"` //网站 (可选) + Qrcode string `json:"qrcode,optional"` //二维码 (可选) + Slogan string `json:"slogan,optional"` //slogan (可选) } type DeleteCartReq struct { diff --git a/server_api/shopping-cart.api b/server_api/shopping-cart.api index 9731e835..5d50db8f 100644 --- a/server_api/shopping-cart.api +++ b/server_api/shopping-cart.api @@ -25,14 +25,22 @@ service shopping-cart { //加入购物车 type AddToCartReq { - ProductId int64 `json:"product_id"` //产品id - TemplateId int64 `json:"template_id"` //模板id - SizeId int64 `json:"size_id"` //尺寸id - FittingId int64 `json:"fitting_id"` //配件id - PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量 - Logo string `json:"logo"` //logo地址 - CombineImage string `json:"combine_image"` //合图地址 - RenderImage string `json:"render_image"` //渲染结果图 + ProductId int64 `json:"product_id"` //产品id + TemplateId int64 `json:"template_id,optional"` //模板id(不可定制的不传) + SizeId int64 `json:"size_id"` //尺寸id + FittingId int64 `json:"fitting_id,optional"` //配件id(没有可以不传) + PurchaseQuantity int64 `json:"purchase_quantity"` //购买数量 + Logo string `json:"logo,optional"` //logo地址(没有可以不传) + CombineImage string `json:"combine_image,optional"` //合图地址 (没有可以不传) + RenderImage string `json:"render_image,optional"` //渲染结果图 (没有可以不传) + DiyInfo DiyInfo `json:"diy_info,optional"` //用户diy数据(可选) +} +type DiyInfo { + Phone string `json:"phone,optional"` //电话(可选) + Address string `json:"address,optional"` //地址 (可选) + Website string `json:"website,optional"` //网站 (可选) + Qrcode string `json:"qrcode,optional"` //二维码 (可选) + Slogan string `json:"slogan,optional"` //slogan (可选) } //删除购物车 type DeleteCartReq { diff --git a/utils/shopping_cart/shopping_cart_snapshot.go b/utils/shopping_cart/shopping_cart_snapshot.go new file mode 100644 index 00000000..66d23aa4 --- /dev/null +++ b/utils/shopping_cart/shopping_cart_snapshot.go @@ -0,0 +1,33 @@ +package shopping_cart + +// 购物车快照数据结构 +type CartSnapshot struct { + Logo string `json:"logo"` //logo地址 + CombineImage string `json:"combine_image"` //刀版图地址 + RenderImage string `json:"render_image"` //渲染结果图 + TemplateInfo TemplateInfo `json:"template_info"` //模板数据 + ModelInfo ModelInfo `json:"model_info"` //模型的数据 + FittingInfo FittingInfo `json:"fitting_info"` //配件信息 + SizeInfo SizeInfo `json:"size_info"` //尺寸基本信息 + UserDiyInformation UserDiyInformation `json:"user_diy_information"` //用户diy数据 +} +type ModelInfo struct { + ModelJson string `json:"model_json"` //模型json数据 +} +type FittingInfo struct { + FittingJson string `json:"fitting_json"` +} +type TemplateInfo struct { + TemplateJson string `json:"template_json"` //模板json数据 + TemplateTag string `json:"template_tag"` //模板标签 +} +type SizeInfo struct { + Title string `json:"title"` +} +type UserDiyInformation struct { + Phone string `json:"phone"` + Address string `json:"address"` + Website string `json:"website"` + Qrcode string `json:"qrcode"` + Slogan string `json:"slogan"` +}