package logic import ( "context" "errors" "fmt" "fusenapi/constants" "fusenapi/model" "fusenapi/utils/basic" "fusenapi/utils/format" "strings" "fusenapi/server/product/internal/svc" "fusenapi/server/product/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type GetSizeByProductLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewGetSizeByProductLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetSizeByProductLogic { return &GetSizeByProductLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 获取分类下的产品以及尺寸 func (l *GetSizeByProductLogic) GetSizeByProduct() (resp *types.Response) { //获取所有网站目录 tagsModel := model.NewFsTagsModel(l.svcCtx.MysqlConn) tagsList, err := tagsModel.GetAllByLevel(l.ctx, constants.TYPE_WEBSITE) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get website tags") } if len(tagsList) == 0 { return resp.SetStatusWithMessage(basic.CodeOK, "tag list is null") } tagIds := make([]string, 0, len(tagsList)) for _, v := range tagsList { tagIds = append(tagIds, fmt.Sprintf("%d", v.Id)) } //获取这些类型的产品 productModel := model.NewFsProductModel(l.svcCtx.MysqlConn) productList, err := productModel.GetProductListByConditions(l.ctx, tagIds, "sort-desc") if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get tag product list") } productIds := make([]string, 0, len(productList)) for _, v := range productList { productIds = append(productIds, fmt.Sprintf("%d", v.Id)) } productSizeModel := model.NewFsProductSizeModel(l.svcCtx.MysqlConn) productSizeList, err := productSizeModel.GetAllByProductIds(l.ctx, productIds, "sort-desc") if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product size list") } sizeIds := make([]string, 0, len(productSizeList)) for _, v := range productSizeList { sizeIds = append(sizeIds, fmt.Sprintf("%d", v.Id)) } //获取价格列表 productPriceModel := model.NewFsProductPriceModel(l.svcCtx.MysqlConn) productPriceList, err := productPriceModel.GetPriceListBySizeIds(l.ctx, sizeIds) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product proce list") } mapProductPrice := make(map[int64]model.FsProductPrice) for _, v := range productPriceList { mapProductPrice[v.SizeId] = v } //组装返回 list := make([]types.GetSizeByProductRsp, 0, len(tagsList)) for _, tag := range tagsList { //获取第一层子类 firstChildrenList, err := l.GetFirstChildrenList(tag, productList, productSizeList, mapProductPrice) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get first level children list") } data := types.GetSizeByProductRsp{ Id: tag.Id, Name: tag.Title, Children: firstChildrenList, } list = append(list, data) } return resp.SetStatusWithMessage(basic.CodeOK, "success", list) } // 第一层子层 func (l *GetSizeByProductLogic) GetFirstChildrenList(tag model.FsTags, productList []model.FsProduct, productSizeList []model.FsProductSize, mapProductPrice map[int64]model.FsProductPrice) (childrenList []types.Children, err error) { childrenList = make([]types.Children, 0, len(productList)) for _, product := range productList { if product.Type != tag.Id { continue } childrenObjList, err := l.GetSecondChildrenList(tag, product, productSizeList, mapProductPrice) if err != nil { return nil, err } //获取第二层子类 data := types.Children{ Id: product.Id, Name: product.Title, Cycle: int(product.DeliveryDays + product.ProduceDays), ChildrenList: childrenObjList, } childrenList = append(childrenList, data) } return } // 第2层子层 func (l *GetSizeByProductLogic) GetSecondChildrenList(tag model.FsTags, product model.FsProduct, productSizeList []model.FsProductSize, mapProductPrice map[int64]model.FsProductPrice) (childrenObjList []types.ChildrenObj, err error) { childrenObjList = make([]types.ChildrenObj, 0, len(productSizeList)) for _, productSize := range productSizeList { if product.Id != productSize.ProductId { continue } priceList := make([]types.PriceObj, 0, len(productSizeList)) price, ok := mapProductPrice[productSize.Id] //无对应尺寸价格 if !ok { childrenObjList = append(childrenObjList, types.ChildrenObj{ Id: productSize.Id, Name: productSize.Capacity, PriceList: []types.PriceObj{ {Num: 1, Price: 0}, {Num: 1, Price: 0}, {Num: 1, Price: 0}, }, }) continue } price.StepNum = strings.Trim(price.StepNum, " ") price.StepPrice = strings.Trim(price.StepPrice, " ") if price.StepNum == "" || price.StepPrice == "" { continue } //阶梯数量切片 stepNum, err := format.StrSlicToIntSlice(strings.Split(price.StepNum, ",")) if err != nil { return nil, err } //阶梯价格切片 stepPrice, err := format.StrSlicToIntSlice(strings.Split(price.StepPrice, ",")) if err != nil { return nil, err } if len(stepNum) == 0 || len(stepPrice) == 0 { return nil, errors.New(fmt.Sprintf("stepNum count or stepPrice count is empty: product size id :%d ,product price id :%d", productSize.Id, price.Id)) } index := 0 // 最小购买数量小于 最大阶梯数量+5 for int(price.MinBuyNum) < (stepNum[len(stepNum)-1]+5) && index < 3 { priceList = append(priceList, types.PriceObj{ Num: int(price.MinBuyNum * price.EachBoxNum), Price: l.GetPrice(int(price.MinBuyNum), stepNum, stepPrice), }) price.MinBuyNum++ index++ } data := types.ChildrenObj{ Id: productSize.Id, Name: productSize.Capacity, PriceList: priceList, } childrenObjList = append(childrenObjList, data) } return } func (l *GetSizeByProductLogic) GetPrice(minBuyNum int, stepNum []int, stepPrice []int) float64 { if minBuyNum > stepNum[len(stepNum)-1] { return float64(stepPrice[len(stepPrice)-1]) / float64(100) } for k, v := range stepNum { if minBuyNum <= v { if k <= (len(stepPrice) - 1) { return float64(stepPrice[k]) / float64(100) } return float64(stepPrice[len(stepPrice)-1]) / float64(100) } } return float64(stepPrice[len(stepPrice)-1]) / float64(100) }