Browse Source

【功能完善】商城: APP 积分商城活动完善 app-api 接口

puhui999 10 months ago
parent
commit
dd82f13c03

+ 9 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java

@@ -290,6 +290,15 @@ public class CollectionUtils {
         return valueFunc.apply(t);
     }
 
+    public static <T, V extends Comparable<? super V>> T getMinPropertyObj(List<T> from, Function<T, V> valueFunc) {
+        if (CollUtil.isEmpty(from)) {
+            return null;
+        }
+        assert from.size() > 0; // 断言,避免告警
+        return from.stream().min(Comparator.comparing(valueFunc)).get();
+    }
+
+
     public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
                                                                      BinaryOperator<V> accumulator) {
         return getSumValue(from, valueFunc, accumulator, null);

+ 5 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java

@@ -28,8 +28,7 @@ import java.util.List;
 import java.util.Map;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
 
 @Tag(name = "管理后台 - 积分商城活动")
 @RestController
@@ -108,7 +107,10 @@ public class PointActivityController {
                 convertSet(pageResult.getList(), PointActivityDO::getSpuId));
         PageResult<PointActivityRespVO> result = BeanUtils.toBean(pageResult, PointActivityRespVO.class);
         result.getList().forEach(activity -> {
-            activity.setProducts(BeanUtils.toBean(productsMap.get(activity.getId()), PointProductRespVO.class));
+            // 设置 product 信息
+            PointProductDO minProduct = getMinPropertyObj(productsMap.get(activity.getId()), PointProductDO::getPoint);
+            assert minProduct != null;
+            activity.setPoint(minProduct.getPoint()).setPrice(minProduct.getPrice());
             MapUtils.findAndThen(spuMap, activity.getSpuId(),
                     spu -> activity.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
 

+ 0 - 3
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java

@@ -63,9 +63,6 @@ public class PointActivityRespVO {
 
     //======================= 显示所需兑换积分最少的 sku 信息 =======================
 
-    @Schema(description = "可兑换数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3926")
-    private Integer maxCount;
-
     @Schema(description = "兑换积分", requiredMode = Schema.RequiredMode.REQUIRED)
     private Integer point;
 

+ 114 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java

@@ -0,0 +1,114 @@
+package cn.iocoder.yudao.module.promotion.controller.app.point;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity.PointActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.point.vo.AppPointActivityDetailRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.point.vo.AppPointActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.point.vo.AppPointActivityRespVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.point.PointActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.point.PointProductDO;
+import cn.iocoder.yudao.module.promotion.service.point.PointActivityService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
+
+@Tag(name = "用户 App - 积分商城活动")
+@RestController
+@RequestMapping("/promotion/point-activity")
+@Validated
+public class AppPointActivityController {
+
+    @Resource
+    private PointActivityService pointActivityService;
+
+    @Resource
+    private ProductSpuApi productSpuApi;
+
+    @GetMapping("/page")
+    @Operation(summary = "获得积分商城活动分页")
+    public CommonResult<PageResult<AppPointActivityRespVO>> getPointActivityPage(AppPointActivityPageReqVO pageReqVO) {
+        // 1. 查询满足当前阶段的活动
+        PageResult<PointActivityDO> pageResult = pointActivityService.getPointActivityPage(
+                BeanUtils.toBean(pageReqVO, PointActivityPageReqVO.class));
+        if (CollUtil.isEmpty(pageResult.getList())) {
+            return success(PageResult.empty(pageResult.getTotal()));
+        }
+
+        // 2. 拼接数据
+        List<AppPointActivityRespVO> resultList = buildAppPointActivityRespVOList(pageResult.getList());
+        return success(new PageResult<>(resultList, pageResult.getTotal()));
+    }
+
+    @GetMapping("/get-detail")
+    @Operation(summary = "获得积分商城活动明细")
+    @Parameter(name = "id", description = "活动编号", required = true, example = "1024")
+    public CommonResult<AppPointActivityDetailRespVO> getPointActivity(@RequestParam("id") Long id) {
+        // 1. 获取活动
+        PointActivityDO activity = pointActivityService.getPointActivity(id);
+        if (activity == null
+                || ObjUtil.equal(activity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            return success(null);
+        }
+
+        // 2. 拼接数据
+        List<PointProductDO> products = pointActivityService.getPointProductListByActivityIds(Collections.singletonList(id));
+        AppPointActivityDetailRespVO respVO = BeanUtils.toBean(activity, AppPointActivityDetailRespVO.class);
+        respVO.setProducts(BeanUtils.toBean(products, AppPointActivityDetailRespVO.Product.class));
+        return success(respVO);
+    }
+
+    @GetMapping("/list-by-ids")
+    @Operation(summary = "获得拼团活动列表,基于活动编号数组")
+    @Parameter(name = "ids", description = "活动编号数组", required = true, example = "[1024, 1025]")
+    public CommonResult<List<AppPointActivityRespVO>> getCombinationActivityListByIds(@RequestParam("ids") List<Long> ids) {
+        // 1. 获得开启的活动列表
+        List<PointActivityDO> activityList = pointActivityService.getPointActivityListByIds(ids);
+        activityList.removeIf(activity -> CommonStatusEnum.isDisable(activity.getStatus()));
+        if (CollUtil.isEmpty(activityList)) {
+            return success(Collections.emptyList());
+        }
+        // 2. 拼接返回
+        List<AppPointActivityRespVO> result = buildAppPointActivityRespVOList(activityList);
+        return success(result);
+    }
+
+    private List<AppPointActivityRespVO> buildAppPointActivityRespVOList(List<PointActivityDO> activityList) {
+        List<PointProductDO> products = pointActivityService.getPointProductListByActivityIds(
+                convertSet(activityList, PointActivityDO::getId));
+        Map<Long, List<PointProductDO>> productsMap = convertMultiMap(products, PointProductDO::getActivityId);
+        Map<Long, ProductSpuRespDTO> spuMap = productSpuApi.getSpusMap(
+                convertSet(activityList, PointActivityDO::getSpuId));
+        List<AppPointActivityRespVO> result = BeanUtils.toBean(activityList, AppPointActivityRespVO.class);
+        result.forEach(activity -> {
+            // 设置 product 信息
+            PointProductDO minProduct = getMinPropertyObj(productsMap.get(activity.getId()), PointProductDO::getPoint);
+            assert minProduct != null;
+            activity.setPoint(minProduct.getPoint()).setPrice(minProduct.getPrice());
+            findAndThen(spuMap, activity.getSpuId(),
+                    spu -> activity.setSpuName(spu.getName()).setPicUrl(spu.getPicUrl()).setMarketPrice(spu.getMarketPrice()));
+        });
+        return result;
+    }
+
+}

+ 57 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityDetailRespVO.java

@@ -0,0 +1,57 @@
+package cn.iocoder.yudao.module.promotion.controller.app.point.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "用户 App - 积分商城活动的详细 Response VO")
+@Data
+public class AppPointActivityDetailRespVO {
+
+    @Schema(description = "积分商城活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11373")
+    private Long id;
+
+    @Schema(description = "积分商城活动商品", requiredMode = Schema.RequiredMode.REQUIRED, example = "19509")
+    private Long spuId;
+
+    @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer status;
+
+    @Schema(description = "积分商城活动库存(剩余库存积分兑换时扣减)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer stock;
+
+    @Schema(description = "积分商城活动总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    private Integer totalStock;
+
+    @Schema(description = "备注", example = "你说的对")
+    private String remark;
+
+    @Schema(description = "商品信息数组", requiredMode = Schema.RequiredMode.REQUIRED)
+    private List<Product> products;
+
+    @Schema(description = "商品信息")
+    @Data
+    public static class Product {
+
+        @Schema(description = "积分商城商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31718")
+        private Long id;
+
+        @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2736")
+        private Long skuId;
+
+        @Schema(description = "可兑换数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "3926")
+        private Integer count;
+
+        @Schema(description = "兑换积分", requiredMode = Schema.RequiredMode.REQUIRED)
+        private Integer point;
+
+        @Schema(description = "兑换金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "15860")
+        private Integer price;
+
+        @Schema(description = "积分商城商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
+        private Integer stock;
+
+    }
+
+}

+ 16 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityPageReqVO.java

@@ -0,0 +1,16 @@
+package cn.iocoder.yudao.module.promotion.controller.app.point.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+@Schema(description = "用户 App - 积分商城活动分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class AppPointActivityPageReqVO extends PageParam {
+
+
+}

+ 65 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java

@@ -0,0 +1,65 @@
+package cn.iocoder.yudao.module.promotion.controller.app.point.vo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "用户 App - 积分商城活动 Response VO")
+@Data
+public class AppPointActivityRespVO {
+
+    @Schema(description = "积分商城活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11373")
+    @ExcelProperty("积分商城活动编号")
+    private Long id;
+
+    @Schema(description = "积分商城活动商品", requiredMode = Schema.RequiredMode.REQUIRED, example = "19509")
+    @ExcelProperty("积分商城活动商品")
+    private Long spuId;
+
+    @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @ExcelProperty("活动状态")
+    private Integer status;
+
+    @Schema(description = "积分商城活动库存(剩余库存积分兑换时扣减)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @ExcelProperty("积分商城活动库存(剩余库存积分兑换时扣减)")
+    private Integer stock;
+
+    @Schema(description = "积分商城活动总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @ExcelProperty("积分商城活动总库存")
+    private Integer totalStock;
+
+    @Schema(description = "备注", example = "你说的对")
+    @ExcelProperty("备注")
+    private String remark;
+
+    @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("排序")
+    private Integer sort;
+
+    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+    @ExcelProperty("创建时间")
+    private LocalDateTime createTime;
+
+    // ========== 商品字段 ==========
+
+    @Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 name 读取
+            example = "618大促")
+    private String spuName;
+    @Schema(description = "商品主图", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 picUrl 读取
+            example = "https://www.iocoder.cn/xx.png")
+    private String picUrl;
+    @Schema(description = "商品市场价,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, // 从 SPU 的 marketPrice 读取
+            example = "50")
+    private Integer marketPrice;
+
+    //======================= 显示所需兑换积分最少的 sku 信息 =======================
+
+    @Schema(description = "兑换积分", requiredMode = Schema.RequiredMode.REQUIRED)
+    private Integer point;
+
+    @Schema(description = "兑换金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "15860")
+    private Integer price;
+
+}

+ 8 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityService.java

@@ -62,6 +62,14 @@ public interface PointActivityService {
      */
     PageResult<PointActivityDO> getPointActivityPage(PointActivityPageReqVO pageReqVO);
 
+    /**
+     * 获得积分商城活动列表
+     *
+     * @param ids 活动编号
+     * @return 积分商城活动列表
+     */
+    List<PointActivityDO> getPointActivityListByIds(Collection<Long> ids);
+
     /**
      * 获得活动商品
      *

+ 5 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java

@@ -234,6 +234,11 @@ public class PointActivityServiceImpl implements PointActivityService {
         return pointActivityMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public List<PointActivityDO> getPointActivityListByIds(Collection<Long> ids) {
+        return pointActivityMapper.selectBatchIds(ids);
+    }
+
     @Override
     public List<PointProductDO> getPointProductListByActivityIds(Collection<Long> activityIds) {
         return pointProductMapper.selectListByActivityId(activityIds);