package logic import ( "errors" "fmt" "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/basic" "fusenapi/utils/format" "fusenapi/utils/step_price" "sort" "strings" "gorm.io/gorm" "context" "fusenapi/server/product/internal/svc" "fusenapi/server/product/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type GetPriceByPidLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewGetPriceByPidLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetPriceByPidLogic { return &GetPriceByPidLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } // 新的阶梯价格(到时候替换) /*func (l *GetPriceByPidLogic) GetPriceByPid(req *types.GetPriceByPidReq, userinfo *auth.UserInfo) (resp *basic.Response) { req.Pid = strings.Trim(req.Pid, " ") if req.Pid == "" { return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:pid is empty") } //获取产品信息(只是获取id) productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Pid, "id") if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists") } logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info") } //查询产品价格 modelPriceList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByProductIdTag(l.ctx, productInfo.Id, constants.TAG_MODEL, "id,part_id,step_price,packed_unit") if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get model price list") } fittingIds := make([]int64, 0, len(modelPriceList)) for _, v := range modelPriceList { if *v.PartId > 0 { fittingIds = append(fittingIds, *v.PartId) } } //查询配件价格列表 fittingPriceList, err := l.svcCtx.AllModels.FsProductModel3d.GetAllByIdsTag(l.ctx, fittingIds, constants.TAG_PARTS, "id,price,packed_unit") if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get fitting price list") } mapFitting := make(map[int64]gmodel.FsProductModel3d) for _, v := range fittingPriceList { mapFitting[v.Id] = v } //遍历处理模型价格 mapRsp := make(map[string]interface{}) for _, modelPriceInfo := range modelPriceList { var stepPrice gmodel.StepPriceJsonStruct if err = json.Unmarshal(*modelPriceInfo.StepPrice, &stepPrice); err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeJsonErr, "failed to parse step price json") } if len(stepPrice.PriceRange) == 0 { return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("step price is not set:%d", modelPriceInfo.Id)) } //最小单价 minPrice := stepPrice.PriceRange[len(stepPrice.PriceRange)-1].Price //最大单价 maxPrice := stepPrice.PriceRange[0].Price //购买数步进基数 stepPurchaseQuantity := *modelPriceInfo.PackedUnit if *modelPriceInfo.PartId > 0 { fittingPriceInfo, ok := mapFitting[*modelPriceInfo.PartId] if !ok { return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("fitting price is not exists:%d", *modelPriceInfo.PartId)) } //最小价格要加配件 minPrice += *fittingPriceInfo.Price //如果配件装箱基数比主体大,则基数以配件为主 if *fittingPriceInfo.PackedUnit > stepPurchaseQuantity { stepPurchaseQuantity = *fittingPriceInfo.PackedUnit } } mapRsp[fmt.Sprintf("_%d", *modelPriceInfo.SizeId)] = map[string]interface{}{ "step_purchase_quantity": stepPurchaseQuantity, "min_price": minPrice, "max_price": maxPrice, "step_range": stepPrice.PriceRange, "min_buy_units_num": stepPrice.MinBuyUnitsNum, } } return resp.SetStatusWithMessage(basic.CodeOK, "success", mapRsp) } */ func (l *GetPriceByPidLogic) GetPriceByPid(req *types.GetPriceByPidReq, userinfo *auth.UserInfo) (resp *basic.Response) { req.Pid = strings.Trim(req.Pid, " ") if req.Pid == "" { return resp.SetStatusWithMessage(basic.CodeRequestParamsErr, "err param:pid is empty") } //获取产品信息(只是获取id) productInfo, err := l.svcCtx.AllModels.FsProduct.FindOneBySn(l.ctx, req.Pid, "id") if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the product is not exists") } logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product info") } //查询产品价格 priceList, err := l.svcCtx.AllModels.FsProductPrice.GetPriceListByProductIds(l.ctx, []int64{productInfo.Id}) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get price list") } if len(priceList) == 0 { return resp.SetStatusWithMessage(basic.CodeOK, "success:price list is empty") } //处理价格信息 mapRsp := make(map[string]*types.GetPriceByPidRsp) for _, priceInfo := range priceList { stepNumSlice, err := format.StrSlicToIntSlice(strings.Split(*priceInfo.StepNum, ",")) if err != nil { return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("failed to parse step num,price_id=%d", priceInfo.Id)) } stepPriceSlice, err := format.StrSlicToIntSlice(strings.Split(*priceInfo.StepPrice, ",")) if err != nil { return resp.SetStatusWithMessage(basic.CodeServiceErr, fmt.Sprintf("failed to parse step price,id = %d", priceInfo.Id)) } if len(stepPriceSlice) == 0 || len(stepNumSlice) == 0 { return resp.SetStatusWithMessage(basic.CodeServiceErr, "number of step num or step price is zero") } lenStepNum := len(stepNumSlice) itemList := make([]types.PriceItem, 0, 10) tmpMinBuyNum := *priceInfo.MinBuyNum for tmpMinBuyNum < (int64(stepNumSlice[lenStepNum-1]) + 5) { itemList = append(itemList, types.PriceItem{ Num: tmpMinBuyNum, TotalNum: tmpMinBuyNum * (*priceInfo.EachBoxNum), Price: step_price.GetCentStepPrice(int(tmpMinBuyNum), stepNumSlice, stepPriceSlice), }) tmpMinBuyNum++ } //组装阶梯数量范围价格 stepRange := l.dealWithStepRange(stepNumSlice, stepPriceSlice, priceInfo) //排序(必须放在其他逻辑之后) sort.Ints(stepPriceSlice) minPrice := float64(stepPriceSlice[0]) / 100 maxPrice := float64(stepPriceSlice[len(stepPriceSlice)-1]) / 100 mapKey := l.getSizePriceMapKey(*priceInfo.SizeId) mapRsp[mapKey] = &types.GetPriceByPidRsp{ Items: itemList, MinPrice: minPrice, MaxPrice: maxPrice, StepRange: stepRange, } } return resp.SetStatusWithMessage(basic.CodeOK, "success", mapRsp) } // 组装阶梯价格范围 func (l *GetPriceByPidLogic) dealWithStepRange(stepNumSlice, stepPriceSlice []int, priceInfo gmodel.FsProductPrice) []types.StepRange { //要求写死不影响前端展示 return []types.StepRange{ { Begin: 1000, End: 2999, Price: 0.23, }, { Begin: 3000, End: 4999, Price: 0.2, }, { Begin: 5000, End: -1, Price: 0.1, }, } //下面是正常的 lenStepNum := len(stepNumSlice) lenStepPrice := len(stepPriceSlice) stepListRsp := make([]types.StepRange, 0, lenStepNum) //只有一个阶梯价格 if lenStepPrice == 1 { stepListRsp = append(stepListRsp, types.StepRange{ Begin: *priceInfo.MinBuyNum * (*priceInfo.EachBoxNum), End: -1, Price: float64(stepPriceSlice[0]) / 100, }) return stepListRsp } begin := int64(0) end := int64(0) for numKey, stepNum := range stepNumSlice { //先取最后一个 tmpPrice := float64(stepPriceSlice[lenStepPrice-1]) / 100 //如果同下标下面有价格 if numKey < lenStepPrice { tmpPrice = float64(stepPriceSlice[numKey]) / 100 } begin = int64(stepNum) * (*priceInfo.EachBoxNum) //不是最后一个 if numKey < lenStepNum-1 { nextBegin := int64(stepNumSlice[numKey+1]) * (*priceInfo.EachBoxNum) end = nextBegin - 1 } else { end = -1 } stepListRsp = append(stepListRsp, types.StepRange{ Begin: begin, End: end, Price: tmpPrice, }) } return stepListRsp } // 获取mapKey func (l *GetPriceByPidLogic) getSizePriceMapKey(sizeId int64) string { return fmt.Sprintf("_%d", sizeId) }