| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | package logic | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							|  |  |  |  | 	"errors" | 
					
						
							|  |  |  |  | 	"fusenapi/model/gmodel" | 
					
						
							|  |  |  |  | 	"fusenapi/utils/auth" | 
					
						
							|  |  |  |  | 	"fusenapi/utils/basic" | 
					
						
							|  |  |  |  | 	"fusenapi/utils/format" | 
					
						
							|  |  |  |  | 	"gorm.io/gorm" | 
					
						
							|  |  |  |  | 	"sort" | 
					
						
							|  |  |  |  | 	"strings" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"context" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"fusenapi/server/product/internal/svc" | 
					
						
							|  |  |  |  | 	"fusenapi/server/product/internal/types" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	"github.com/zeromicro/go-zero/core/logx" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 17:47:28 +08:00
										 |  |  |  | type HomePageRecommendProductListLogic struct { | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	logx.Logger | 
					
						
							|  |  |  |  | 	ctx    context.Context | 
					
						
							|  |  |  |  | 	svcCtx *svc.ServiceContext | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 17:47:28 +08:00
										 |  |  |  | func NewHomePageRecommendProductListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *HomePageRecommendProductListLogic { | 
					
						
							|  |  |  |  | 	return &HomePageRecommendProductListLogic{ | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 		Logger: logx.WithContext(ctx), | 
					
						
							|  |  |  |  | 		ctx:    ctx, | 
					
						
							|  |  |  |  | 		svcCtx: svcCtx, | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-20 17:47:28 +08:00
										 |  |  |  | func (l *HomePageRecommendProductListLogic) HomePageRecommendProductList(req *types.HomePageRecommendProductListReq, userinfo *auth.UserInfo) (resp *basic.Response) { | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	//查询用户信息(不用判断存在) | 
					
						
							| 
									
										
										
										
											2023-08-14 11:49:02 +08:00
										 |  |  |  | 	_, err := l.svcCtx.AllModels.FsUser.FindUserById(l.ctx, userinfo.UserId) | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get user info err") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2023-08-14 11:35:23 +08:00
										 |  |  |  | 		merchantInfo                *gmodel.FsMerchantCategory | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 		recommendProductList        []gmodel.FsProduct                       //产品列表(select 字段需要看查询的地方) | 
					
						
							|  |  |  |  | 		productOptionalPartList     []gmodel.GetGroupPartListByProductIdsRsp //产品配件列表 | 
					
						
							| 
									
										
										
										
											2023-08-14 11:53:16 +08:00
										 |  |  |  | 		mapProductHaveOptionFitting = make(map[int64]struct{})               //是否有配件map | 
					
						
							|  |  |  |  | 		productPriceList            []gmodel.GetPriceListByProductIdsRsp     //产品价格列表(select 字段需要看查询的地方) | 
					
						
							|  |  |  |  | 		mapProductMinPrice          = make(map[int64]int64)                  //产品最小价格map | 
					
						
							|  |  |  |  | 		productTemplatesV2          []gmodel.FsProductTemplateV2             //产品模板列表(select 字段需要看查询的地方) | 
					
						
							|  |  |  |  | 		productSizeCountList        []gmodel.CountProductSizeByStatusRsp     //产品尺寸数量列表(select 字段需要看查询的地方) | 
					
						
							|  |  |  |  | 		mapProductSizeCount         = make(map[int64]int64)                  //产品尺寸数量map | 
					
						
							|  |  |  |  | 		mapProductTemplate          = make(map[int64]struct{})               //产品模板map | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2023-08-14 11:35:23 +08:00
										 |  |  |  | 	//选了商家类型 | 
					
						
							|  |  |  |  | 	if req.MerchantType > 0 { | 
					
						
							|  |  |  |  | 		merchantInfo, err = l.svcCtx.AllModels.FsMerchantCategory.FindOne(l.ctx, req.MerchantType) | 
					
						
							| 
									
										
										
										
											2023-08-28 14:56:01 +08:00
										 |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			if errors.Is(err, gorm.ErrRecordNotFound) { | 
					
						
							| 
									
										
										
										
											2023-08-28 15:40:56 +08:00
										 |  |  |  | 				return resp.SetStatusWithMessage(basic.CodeOK, "the merchant category is not exists", []interface{}{}) | 
					
						
							| 
									
										
										
										
											2023-08-28 14:56:01 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 			logx.Error(err) | 
					
						
							|  |  |  |  | 			return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get merchant category") | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-08-14 11:35:23 +08:00
										 |  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2023-08-28 14:56:01 +08:00
										 |  |  |  | 		//获取默认的那个 | 
					
						
							|  |  |  |  | 		merchantInfo, err = l.svcCtx.AllModels.FsMerchantCategory.FindDefualtOne(l.ctx) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			if errors.Is(err, gorm.ErrRecordNotFound) { | 
					
						
							| 
									
										
										
										
											2023-08-28 15:40:56 +08:00
										 |  |  |  | 				return resp.SetStatusWithMessage(basic.CodeOK, "the default merchant category is not exists", []interface{}{}) | 
					
						
							| 
									
										
										
										
											2023-08-28 14:56:01 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 			logx.Error(err) | 
					
						
							|  |  |  |  | 			return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get default merchant category") | 
					
						
							| 
									
										
										
										
											2023-08-14 11:35:23 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if *merchantInfo.RecommendProduct == "" { | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeOK, "success", []interface{}{}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	recommendProductIds, err := format.StrSlicToInt64Slice(strings.Split(*merchantInfo.RecommendProduct, ",")) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse recommend product") | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	//获取列表推荐产品 | 
					
						
							| 
									
										
										
										
											2023-08-14 11:35:23 +08:00
										 |  |  |  | 	recommendProductList, err = l.svcCtx.AllModels.FsProduct.GetProductListByIds(l.ctx, recommendProductIds, "sort-desc") | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product list") | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	if len(recommendProductList) == 0 { | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeOK, "success", []interface{}{}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	productIds := make([]int64, 0, len(recommendProductList)) | 
					
						
							|  |  |  |  | 	for _, product := range recommendProductList { | 
					
						
							|  |  |  |  | 		productIds = append(productIds, product.Id) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//获取商品可选配件 | 
					
						
							|  |  |  |  | 	productOptionalPartList, err = l.svcCtx.AllModels.FsProductModel3d.GetGroupPartListByProductIds(l.ctx, productIds) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product part list") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//存储有配件的map | 
					
						
							|  |  |  |  | 	for _, partList := range productOptionalPartList { | 
					
						
							|  |  |  |  | 		partList.PartList = strings.Trim(partList.PartList, " ") | 
					
						
							|  |  |  |  | 		partList.PartList = strings.Trim(partList.PartList, ",") | 
					
						
							|  |  |  |  | 		if partList.PartList == "" { | 
					
						
							|  |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		mapProductHaveOptionFitting[partList.ProductId] = struct{}{} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//获取产品价格列表 | 
					
						
							|  |  |  |  | 	productPriceList, err = l.svcCtx.AllModels.FsProductPrice.GetSimplePriceListByProductIds(l.ctx, productIds) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product min price list") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//存储产品最小价格 | 
					
						
							|  |  |  |  | 	for _, v := range productPriceList { | 
					
						
							|  |  |  |  | 		priceStrSlic := strings.Split(v.Price, ",") | 
					
						
							|  |  |  |  | 		priceSlice, err := format.StrSlicToIntSlice(priceStrSlic) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			logx.Error(err) | 
					
						
							|  |  |  |  | 			return resp.SetStatusWithMessage(basic.CodeServiceErr, err.Error()) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if len(priceSlice) == 0 { | 
					
						
							|  |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		sort.Ints(priceSlice) | 
					
						
							|  |  |  |  | 		if min, ok := mapProductMinPrice[v.ProductId]; ok { | 
					
						
							|  |  |  |  | 			if min > int64(priceSlice[0]) { | 
					
						
							|  |  |  |  | 				mapProductMinPrice[v.ProductId] = int64(priceSlice[0]) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} else { | 
					
						
							|  |  |  |  | 			mapProductMinPrice[v.ProductId] = int64(priceSlice[0]) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//获取模板(只是获取产品product_id) | 
					
						
							| 
									
										
										
										
											2023-08-17 18:19:15 +08:00
										 |  |  |  | 	productTemplatesV2, err = l.svcCtx.AllModels.FsProductTemplateV2.FindAllByProductIds(l.ctx, productIds, "", "product_id") | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get product template_v2 err") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for _, v := range productTemplatesV2 { | 
					
						
							|  |  |  |  | 		mapProductTemplate[*v.ProductId] = struct{}{} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	//获取产品尺寸数量 | 
					
						
							|  |  |  |  | 	productSizeCountList, err = l.svcCtx.AllModels.FsProductSize.GetGroupProductSizeByStatus(l.ctx, productIds, 1) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "get product size count err") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	for _, v := range productSizeCountList { | 
					
						
							|  |  |  |  | 		mapProductSizeCount[v.ProductId] = v.Num | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-08-14 12:30:14 +08:00
										 |  |  |  | 	//获取产品标签相关属性 | 
					
						
							|  |  |  |  | 	productTagPropList, err := l.svcCtx.AllModels.FsProductTagProp.GetTagPropByProductIdsWithProductTag(l.ctx, productIds) | 
					
						
							|  |  |  |  | 	if err != nil { | 
					
						
							|  |  |  |  | 		logx.Error(err) | 
					
						
							|  |  |  |  | 		return resp.SetStatusWithMessage(basic.CodeDbSqlErr, "failed to get product tag property") | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	mapTagProp := make(map[int64][]types.CoverDefaultItem) | 
					
						
							|  |  |  |  | 	for _, v := range productTagPropList { | 
					
						
							|  |  |  |  | 		mapTagProp[*v.ProductId] = append(mapTagProp[*v.ProductId], types.CoverDefaultItem{ | 
					
						
							| 
									
										
										
										
											2023-08-17 11:14:47 +08:00
										 |  |  |  | 			Tag:   v.TemplateTag, | 
					
						
							| 
									
										
										
										
											2023-08-14 12:30:14 +08:00
										 |  |  |  | 			Cover: *v.Cover, | 
					
						
							|  |  |  |  | 		}) | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	//组装返回 | 
					
						
							| 
									
										
										
										
											2023-07-20 17:47:28 +08:00
										 |  |  |  | 	listRsp := make([]types.HomePageRecommendProductListRsp, 0, len(recommendProductList)) | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 	for _, productInfo := range recommendProductList { | 
					
						
							|  |  |  |  | 		minPrice, ok := mapProductMinPrice[productInfo.Id] | 
					
						
							|  |  |  |  | 		_, tmpOk := mapProductTemplate[productInfo.Id] | 
					
						
							|  |  |  |  | 		//无最小价格则不显示 || 没有模板也不显示 | 
					
						
							|  |  |  |  | 		if !ok || !tmpOk { | 
					
						
							|  |  |  |  | 			continue | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		sizeNum := int64(0) | 
					
						
							|  |  |  |  | 		if mapSizeNum, ok := mapProductSizeCount[productInfo.Id]; ok { | 
					
						
							|  |  |  |  | 			sizeNum = mapSizeNum | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		//有无可选配件 | 
					
						
							|  |  |  |  | 		haveOptionalFitting := false | 
					
						
							|  |  |  |  | 		if _, ok = mapProductHaveOptionFitting[productInfo.Id]; ok { | 
					
						
							|  |  |  |  | 			haveOptionalFitting = true | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-07-20 17:47:28 +08:00
										 |  |  |  | 		item := types.HomePageRecommendProductListRsp{ | 
					
						
							| 
									
										
										
										
											2023-07-24 18:08:19 +08:00
										 |  |  |  | 			Id:                  productInfo.Id, | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 			Sn:                  *productInfo.Sn, | 
					
						
							|  |  |  |  | 			Title:               *productInfo.Title, | 
					
						
							| 
									
										
										
										
											2023-08-14 11:46:29 +08:00
										 |  |  |  | 			Cover:               *productInfo.Cover, | 
					
						
							| 
									
										
										
										
											2023-08-14 12:31:49 +08:00
										 |  |  |  | 			CoverDefault:        []types.CoverDefaultItem{}, | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 			SizeNum:             uint32(sizeNum), | 
					
						
							| 
									
										
										
										
											2023-07-24 10:30:08 +08:00
										 |  |  |  | 			MinPrice:            minPrice, | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 			HaveOptionalFitting: haveOptionalFitting, | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-08-14 12:30:14 +08:00
										 |  |  |  | 		if _, ok = mapTagProp[productInfo.Id]; ok { | 
					
						
							|  |  |  |  | 			item.CoverDefault = mapTagProp[productInfo.Id] | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 		//千人千面处理 | 
					
						
							| 
									
										
										
										
											2023-08-14 11:46:29 +08:00
										 |  |  |  | 		/*r := image.ThousandFaceImageFormatReq{ | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 			Size:           int(req.Size), | 
					
						
							|  |  |  |  | 			IsThousandFace: 0, | 
					
						
							|  |  |  |  | 			Cover:          *productInfo.Cover, | 
					
						
							|  |  |  |  | 			CoverImg:       *productInfo.CoverImg, | 
					
						
							|  |  |  |  | 			CoverDefault:   *productInfo.CoverImg, | 
					
						
							|  |  |  |  | 			ProductId:      productInfo.Id, | 
					
						
							|  |  |  |  | 			UserId:         user.Id, | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if user.Id != 0 { | 
					
						
							|  |  |  |  | 			r.IsThousandFace = int(*user.IsThousandFace) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		image.ThousandFaceImageFormat(&r) | 
					
						
							|  |  |  |  | 		item.Cover = r.Cover | 
					
						
							| 
									
										
										
										
											2023-08-14 11:46:29 +08:00
										 |  |  |  | 		item.CoverDefault = r.CoverDefault*/ | 
					
						
							| 
									
										
										
										
											2023-07-20 17:35:13 +08:00
										 |  |  |  | 		//加入分类产品切片 | 
					
						
							|  |  |  |  | 		listRsp = append(listRsp, item) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	return resp.SetStatusWithMessage(basic.CodeOK, "success", listRsp) | 
					
						
							|  |  |  |  | } |