Browse Source

update: 把4月3日修改订单预览、提交的分支内容,通过重新覆盖代码,重新提交。

Ben 1 year ago
parent
commit
e78f392548
20 changed files with 765 additions and 187 deletions
  1. 0 4
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/convert/comment/ProductCommentConvert.java
  2. 0 8
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/comment/ProductCommentDO.java
  3. 0 8
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spu/ProductSpuDO.java
  4. 4 14
      feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/comment/ProductCommentServiceImpl.java
  5. 9 7
      feifan-module-mall/feifan-module-sale-api/src/main/java/cn/newfeifan/mall/module/sale/enums/ErrorCodeConstants.java
  6. 95 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/ShopController.java
  7. 3 5
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopPageReqVO.java
  8. 5 12
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopRespVO.java
  9. 3 14
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopSaveReqVO.java
  10. 5 8
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/dataobject/shop/ShopDO.java
  11. 9 2
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/mysql/shop/ShopMapper.java
  12. 55 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/shop/ShopService.java
  13. 75 0
      feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/shop/ShopServiceImpl.java
  14. 1 1
      feifan-module-mall/feifan-module-sale-biz/src/main/resources/mapper/shop/ShopMapper.xml
  15. 146 0
      feifan-module-mall/feifan-module-sale-biz/src/test/java/cn/newfeifan/mall/module/sale/service/shop/ShopServiceImplTest.java
  16. 2 8
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java
  17. 0 8
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/aftersale/AfterSaleDO.java
  18. 0 17
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/aftersale/AfterSaleServiceImpl.java
  19. 351 68
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java
  20. 2 3
      feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java

+ 0 - 4
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/convert/comment/ProductCommentConvert.java

@@ -36,10 +36,6 @@ public interface ProductCommentConvert {
         if (sku != null) {
             comment.setSkuPicUrl(sku.getPicUrl()).setSkuProperties(sku.getProperties());
         }
-
-        //加上评论的默认可见
-        comment.setVisible(Boolean.TRUE);
-
         return comment;
     }
 

+ 0 - 8
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/comment/ProductCommentDO.java

@@ -155,13 +155,5 @@ public class ProductCommentDO extends BaseDO {
      * 商家回复时间
      */
     private LocalDateTime replyTime;
-    /**
-     * 店铺id
-     */
-    private Long shopId;
-    /**
-     * 商户id
-     */
-    private Long merchantId;
 
 }

+ 0 - 8
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/dal/dataobject/spu/ProductSpuDO.java

@@ -168,12 +168,4 @@ public class ProductSpuDO extends BaseDO {
      * 浏览量
      */
     private Integer browseCount;
-    /**
-     * 店铺id
-     */
-    private Long shopId;
-    /**
-     * 商户id
-     */
-    private Long merchantId;
 }

+ 4 - 14
feifan-module-mall/feifan-module-product-biz/src/main/java/cn/newfeifan/mall/module/product/service/comment/ProductCommentServiceImpl.java

@@ -4,7 +4,10 @@ import cn.newfeifan.mall.framework.common.pojo.PageResult;
 import cn.newfeifan.mall.module.member.api.user.MemberUserApi;
 import cn.newfeifan.mall.module.member.api.user.dto.MemberUserRespDTO;
 import cn.newfeifan.mall.module.product.api.comment.dto.ProductCommentCreateReqDTO;
-import cn.newfeifan.mall.module.product.controller.admin.comment.vo.*;
+import cn.newfeifan.mall.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
+import cn.newfeifan.mall.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.newfeifan.mall.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO;
+import cn.newfeifan.mall.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.newfeifan.mall.module.product.controller.app.comment.vo.AppCommentPageReqVO;
 import cn.newfeifan.mall.module.product.convert.comment.ProductCommentConvert;
 import cn.newfeifan.mall.module.product.dal.dataobject.comment.ProductCommentDO;
@@ -54,11 +57,6 @@ public class ProductCommentServiceImpl implements ProductCommentService {
 
         // 创建评论
         ProductCommentDO comment = ProductCommentConvert.INSTANCE.convert(createReqVO, spu, sku);
-
-        ShopBO shop = getShop(sku.getSpuId());
-        comment.setShopId(shop.getShopId());
-        comment.setMerchantId(shop.getMerchantId());
-
         productCommentMapper.insert(comment);
     }
 
@@ -108,14 +106,6 @@ public class ProductCommentServiceImpl implements ProductCommentService {
         return spu;
     }
 
-    private ShopBO getShop(Long spuId){
-        ProductSpuDO spu = productSpuService.getSpu(spuId);
-        if (null == spu) {
-            throw exception(SPU_NOT_EXISTS);
-        }
-        return new ShopBO(spu.getShopId(),spu.getMerchantId());
-    }
-
     @Override
     public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) {
         // 校验评论是否存在

+ 9 - 7
feifan-module-mall/feifan-module-sale-api/src/main/java/cn/newfeifan/mall/module/sale/enums/ErrorCodeConstants.java

@@ -3,14 +3,16 @@ package cn.newfeifan.mall.module.sale.enums;
 import cn.newfeifan.mall.framework.common.exception.ErrorCode;
 
 /**
- * System 错误码枚举类
- *
- * system 系统,使用 1-002-000-000 段
+ * Sale 错误码枚举类 add by Ben 20240315
+ * <p>
+ * Sale 系统,使用 1-101-000-000 段
+ * 第二段是模块编号,用101这么大,是不想与原来的编码重复
+ * 第三段是表编号,如:商户表、店铺表
+ * 第四段是表内的错误编号
  */
 public interface ErrorCodeConstants {
-    // ========== 店铺商户信息 1-002-029-000 ==========
-    ErrorCode SHOP_STATUS_NOT_EXISTS = new ErrorCode(1_002_029_000 , "店铺状态不存在");
-    ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1_002_029_001, "商户不存在");
-    ErrorCode SHOP_NOT_EXISTS = new ErrorCode(1_002_029_002, "店铺不存在不存在");
+
+    //店铺表相关错误,表编号是1
+    ErrorCode SHOP_NOT_EXISTS = new ErrorCode(1_101_001_001, "店铺不存在");
 
 }

+ 95 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/ShopController.java

@@ -0,0 +1,95 @@
+package cn.newfeifan.mall.module.sale.controller.admin.shop;
+
+import org.springframework.web.bind.annotation.*;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import javax.validation.constraints.*;
+import javax.validation.*;
+import javax.servlet.http.*;
+import java.util.*;
+import java.io.IOException;
+
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.CommonResult;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+import static cn.newfeifan.mall.framework.common.pojo.CommonResult.success;
+
+import cn.newfeifan.mall.framework.excel.core.util.ExcelUtils;
+
+import cn.newfeifan.mall.framework.operatelog.core.annotations.OperateLog;
+import static cn.newfeifan.mall.framework.operatelog.core.enums.OperateTypeEnum.*;
+
+import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
+import cn.newfeifan.mall.module.sale.service.shop.ShopService;
+
+@Tag(name = "管理后台 - 店铺")
+@RestController
+@RequestMapping("/sale/shop")
+@Validated
+public class ShopController {
+
+    @Resource
+    private ShopService shopService;
+
+    @PostMapping("/create")
+    @Operation(summary = "创建店铺")
+    @PreAuthorize("@ss.hasPermission('sale:shop:create')")
+    public CommonResult<Long> createShop(@Valid @RequestBody ShopSaveReqVO createReqVO) {
+        return success(shopService.createShop(createReqVO));
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新店铺")
+    @PreAuthorize("@ss.hasPermission('sale:shop:update')")
+    public CommonResult<Boolean> updateShop(@Valid @RequestBody ShopSaveReqVO updateReqVO) {
+        shopService.updateShop(updateReqVO);
+        return success(true);
+    }
+
+    @DeleteMapping("/delete")
+    @Operation(summary = "删除店铺")
+    @Parameter(name = "id", description = "编号", required = true)
+    @PreAuthorize("@ss.hasPermission('sale:shop:delete')")
+    public CommonResult<Boolean> deleteShop(@RequestParam("id") Long id) {
+        shopService.deleteShop(id);
+        return success(true);
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "获得店铺")
+    @Parameter(name = "id", description = "编号", required = true, example = "1024")
+    @PreAuthorize("@ss.hasPermission('sale:shop:query')")
+    public CommonResult<ShopRespVO> getShop(@RequestParam("id") Long id) {
+        ShopDO shop = shopService.getShop(id);
+        return success(BeanUtils.toBean(shop, ShopRespVO.class));
+    }
+
+    @GetMapping("/page")
+    @Operation(summary = "获得店铺分页")
+    @PreAuthorize("@ss.hasPermission('sale:shop:query')")
+    public CommonResult<PageResult<ShopRespVO>> getShopPage(@Valid ShopPageReqVO pageReqVO) {
+        PageResult<ShopDO> pageResult = shopService.getShopPage(pageReqVO);
+        return success(BeanUtils.toBean(pageResult, ShopRespVO.class));
+    }
+
+    @GetMapping("/export-excel")
+    @Operation(summary = "导出店铺 Excel")
+    @PreAuthorize("@ss.hasPermission('sale:shop:export')")
+    @OperateLog(type = EXPORT)
+    public void exportShopExcel(@Valid ShopPageReqVO pageReqVO,
+              HttpServletResponse response) throws IOException {
+        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
+        List<ShopDO> list = shopService.getShopPage(pageReqVO).getList();
+        // 导出 Excel
+        ExcelUtils.write(response, "店铺.xls", "数据", ShopRespVO.class,
+                        BeanUtils.toBean(list, ShopRespVO.class));
+    }
+
+}

+ 3 - 5
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopPageReqVO.java

@@ -1,12 +1,10 @@
 package cn.newfeifan.mall.module.sale.controller.admin.shop.vo;
 
-import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import lombok.*;
+import java.util.*;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
 import org.springframework.format.annotation.DateTimeFormat;
-
 import java.time.LocalDateTime;
 
 import static cn.newfeifan.mall.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;

+ 5 - 12
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopRespVO.java

@@ -1,11 +1,12 @@
 package cn.newfeifan.mall.module.sale.controller.admin.shop.vo;
 
-import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
-import com.alibaba.excel.annotation.ExcelProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
+import lombok.*;
+import java.util.*;
+import java.util.*;
+import org.springframework.format.annotation.DateTimeFormat;
 import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
 
 @Schema(description = "管理后台 - 店铺 Response VO")
 @Data
@@ -36,12 +37,4 @@ public class ShopRespVO {
     @ExcelProperty("logo地址")
     private String logoUrl;
 
-    @Schema(description = "域名", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
-    @ExcelProperty("域名")
-    private String website;
-
-    @Schema(description = "最后更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
-    @ExcelProperty("最后更新时间")
-    private LocalDateTime updateTime;
-
 }

+ 3 - 14
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/controller/admin/shop/vo/ShopSaveReqVO.java

@@ -1,19 +1,12 @@
 package cn.newfeifan.mall.module.sale.controller.admin.shop.vo;
 
 import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-import javax.validation.constraints.NotEmpty;
-import javax.validation.constraints.NotNull;
+import lombok.*;
+import java.util.*;
+import javax.validation.constraints.*;
 
 @Schema(description = "管理后台 - 店铺新增/修改 Request VO")
 @Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
 public class ShopSaveReqVO {
 
     @Schema(description = "店铺id", requiredMode = Schema.RequiredMode.REQUIRED, example = "15084")
@@ -34,8 +27,4 @@ public class ShopSaveReqVO {
     @Schema(description = "logo地址", example = "https://www.zhongxing.cn")
     private String logoUrl;
 
-    @Schema(description = "域名", example = "https://www.zhongxing.cn")
-    private String website;
-
-
 }

+ 5 - 8
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/dataobject/shop/ShopDO.java

@@ -1,10 +1,11 @@
 package cn.newfeifan.mall.module.sale.dal.dataobject.shop;
 
-import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
-import com.baomidou.mybatisplus.annotation.KeySequence;
-import com.baomidou.mybatisplus.annotation.TableId;
-import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.*;
+import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalDateTime;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.newfeifan.mall.framework.mybatis.core.dataobject.BaseDO;
 
 /**
  * 店铺 DO
@@ -49,9 +50,5 @@ public class ShopDO extends BaseDO {
      * logo地址
      */
     private String logoUrl;
-    /**
-     * 域名
-     */
-    private String website;
 
 }

+ 9 - 2
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/dal/mysql/shop/ShopMapper.java

@@ -1,20 +1,27 @@
 package cn.newfeifan.mall.module.sale.dal.mysql.shop;
 
+import java.util.*;
+
 import cn.newfeifan.mall.framework.common.pojo.PageResult;
-import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
 import cn.newfeifan.mall.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.ShopPageReqVO;
+import cn.newfeifan.mall.framework.mybatis.core.mapper.BaseMapperX;
 import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
 import org.apache.ibatis.annotations.Mapper;
+import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.*;
 
 /**
  * 店铺 Mapper
  *
  * @author 非繁人
+ * add by Ben 20240315
  */
 @Mapper
 public interface ShopMapper extends BaseMapperX<ShopDO> {
 
+    default List<ShopDO> selectListById(Collection<Long> shopIds) {
+        return selectList(ShopDO::getId, shopIds);
+    }
+
     default PageResult<ShopDO> selectPage(ShopPageReqVO reqVO) {
         return selectPage(reqVO, new LambdaQueryWrapperX<ShopDO>()
                 .likeIfPresent(ShopDO::getName, reqVO.getName())

+ 55 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/shop/ShopService.java

@@ -0,0 +1,55 @@
+package cn.newfeifan.mall.module.sale.service.shop;
+
+import java.util.*;
+import javax.validation.*;
+import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+
+/**
+ * 店铺 Service 接口
+ *
+ * @author 非繁人
+ */
+public interface ShopService {
+
+    /**
+     * 创建店铺
+     *
+     * @param createReqVO 创建信息
+     * @return 编号
+     */
+    Long createShop(@Valid ShopSaveReqVO createReqVO);
+
+    /**
+     * 更新店铺
+     *
+     * @param updateReqVO 更新信息
+     */
+    void updateShop(@Valid ShopSaveReqVO updateReqVO);
+
+    /**
+     * 删除店铺
+     *
+     * @param id 编号
+     */
+    void deleteShop(Long id);
+
+    /**
+     * 获得店铺
+     *
+     * @param id 编号
+     * @return 店铺
+     */
+    ShopDO getShop(Long id);
+
+    /**
+     * 获得店铺分页
+     *
+     * @param pageReqVO 分页查询
+     * @return 店铺分页
+     */
+    PageResult<ShopDO> getShopPage(ShopPageReqVO pageReqVO);
+
+}

+ 75 - 0
feifan-module-mall/feifan-module-sale-biz/src/main/java/cn/newfeifan/mall/module/sale/service/shop/ShopServiceImpl.java

@@ -0,0 +1,75 @@
+package cn.newfeifan.mall.module.sale.service.shop;
+
+import cn.newfeifan.mall.module.sale.enums.ErrorCodeConstants;
+import org.springframework.stereotype.Service;
+import javax.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+import cn.newfeifan.mall.framework.common.pojo.PageParam;
+import cn.newfeifan.mall.framework.common.util.object.BeanUtils;
+
+import cn.newfeifan.mall.module.sale.dal.mysql.shop.ShopMapper;
+
+import static cn.newfeifan.mall.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.newfeifan.mall.module.sale.enums.ErrorCodeConstants.*;
+
+/**
+ * 店铺 Service 实现类
+ *
+ * @author 非繁人
+ */
+@Service
+@Validated
+public class ShopServiceImpl implements ShopService {
+
+    @Resource
+    private ShopMapper shopMapper;
+
+    @Override
+    public Long createShop(ShopSaveReqVO createReqVO) {
+        // 插入
+        ShopDO shop = BeanUtils.toBean(createReqVO, ShopDO.class);
+        shopMapper.insert(shop);
+        // 返回
+        return shop.getId();
+    }
+
+    @Override
+    public void updateShop(ShopSaveReqVO updateReqVO) {
+        // 校验存在
+        validateShopExists(updateReqVO.getId());
+        // 更新
+        ShopDO updateObj = BeanUtils.toBean(updateReqVO, ShopDO.class);
+        shopMapper.updateById(updateObj);
+    }
+
+    @Override
+    public void deleteShop(Long id) {
+        // 校验存在
+        validateShopExists(id);
+        // 删除
+        shopMapper.deleteById(id);
+    }
+
+    private void validateShopExists(Long id) {
+        if (shopMapper.selectById(id) == null) {
+            throw exception(ErrorCodeConstants.SHOP_NOT_EXISTS);
+        }
+    }
+
+    @Override
+    public ShopDO getShop(Long id) {
+        return shopMapper.selectById(id);
+    }
+
+    @Override
+    public PageResult<ShopDO> getShopPage(ShopPageReqVO pageReqVO) {
+        return shopMapper.selectPage(pageReqVO);
+    }
+
+}

+ 1 - 1
feifan-module-mall/feifan-module-sale-biz/src/main/resources/mapper/shop/ShopMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="cn.newfeifan.mall.sale.dal.mysql.shop.ShopMapper">
+<mapper namespace="cn.newfeifan.mall.module.sale.dal.mysql.shop.ShopMapper">
 
     <!--
         一般情况下,尽可能使用 Mapper 进行 CRUD 增删改查即可。

+ 146 - 0
feifan-module-mall/feifan-module-sale-biz/src/test/java/cn/newfeifan/mall/module/sale/service/shop/ShopServiceImplTest.java

@@ -0,0 +1,146 @@
+package cn.newfeifan.mall.module.sale.service.shop;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
+
+import javax.annotation.Resource;
+
+import cn.newfeifan.mall.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.newfeifan.mall.module.sale.controller.admin.shop.vo.*;
+import cn.newfeifan.mall.module.sale.dal.dataobject.shop.ShopDO;
+import cn.newfeifan.mall.module.sale.dal.mysql.shop.ShopMapper;
+import cn.newfeifan.mall.framework.common.pojo.PageResult;
+
+import javax.annotation.Resource;
+import org.springframework.context.annotation.Import;
+import java.util.*;
+import java.time.LocalDateTime;
+
+import static cn.hutool.core.util.RandomUtil.*;
+import static cn.newfeifan.mall.module.sale.enums.ErrorCodeConstants.*;
+import static cn.newfeifan.mall.framework.test.core.util.AssertUtils.*;
+import static cn.newfeifan.mall.framework.test.core.util.RandomUtils.*;
+import static cn.newfeifan.mall.framework.common.util.date.LocalDateTimeUtils.*;
+import static cn.newfeifan.mall.framework.common.util.object.ObjectUtils.*;
+import static cn.newfeifan.mall.framework.common.util.date.DateUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * {@link ShopServiceImpl} 的单元测试类
+ *
+ * @author 非繁人
+ */
+@Import(ShopServiceImpl.class)
+public class ShopServiceImplTest extends BaseDbUnitTest {
+
+    @Resource
+    private ShopServiceImpl shopService;
+
+    @Resource
+    private ShopMapper shopMapper;
+
+    @Test
+    public void testCreateShop_success() {
+        // 准备参数
+        ShopSaveReqVO createReqVO = randomPojo(ShopSaveReqVO.class).setId(null);
+
+        // 调用
+        Long shopId = shopService.createShop(createReqVO);
+        // 断言
+        assertNotNull(shopId);
+        // 校验记录的属性是否正确
+        ShopDO shop = shopMapper.selectById(shopId);
+        assertPojoEquals(createReqVO, shop, "id");
+    }
+
+    @Test
+    public void testUpdateShop_success() {
+        // mock 数据
+        ShopDO dbShop = randomPojo(ShopDO.class);
+        shopMapper.insert(dbShop);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        ShopSaveReqVO updateReqVO = randomPojo(ShopSaveReqVO.class, o -> {
+            o.setId(dbShop.getId()); // 设置更新的 ID
+        });
+
+        // 调用
+        shopService.updateShop(updateReqVO);
+        // 校验是否更新正确
+        ShopDO shop = shopMapper.selectById(updateReqVO.getId()); // 获取最新的
+        assertPojoEquals(updateReqVO, shop);
+    }
+
+    @Test
+    public void testUpdateShop_notExists() {
+        // 准备参数
+        ShopSaveReqVO updateReqVO = randomPojo(ShopSaveReqVO.class);
+
+        // 调用, 并断言异常
+        assertServiceException(() -> shopService.updateShop(updateReqVO), SHOP_NOT_EXISTS);
+    }
+
+    @Test
+    public void testDeleteShop_success() {
+        // mock 数据
+        ShopDO dbShop = randomPojo(ShopDO.class);
+        shopMapper.insert(dbShop);// @Sql: 先插入出一条存在的数据
+        // 准备参数
+        Long id = dbShop.getId();
+
+        // 调用
+        shopService.deleteShop(id);
+       // 校验数据不存在了
+       assertNull(shopMapper.selectById(id));
+    }
+
+    @Test
+    public void testDeleteShop_notExists() {
+        // 准备参数
+        Long id = randomLongId();
+
+        // 调用, 并断言异常
+        assertServiceException(() -> shopService.deleteShop(id), SHOP_NOT_EXISTS);
+    }
+
+    @Test
+    @Disabled  // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解
+    public void testGetShopPage() {
+       // mock 数据
+       ShopDO dbShop = randomPojo(ShopDO.class, o -> { // 等会查询到
+           o.setName(null);
+           o.setStatus(null);
+           o.setMerchantId(null);
+           o.setCreateTime(null);
+           o.setLogoUrl(null);
+       });
+       shopMapper.insert(dbShop);
+       // 测试 name 不匹配
+       shopMapper.insert(cloneIgnoreId(dbShop, o -> o.setName(null)));
+       // 测试 status 不匹配
+       shopMapper.insert(cloneIgnoreId(dbShop, o -> o.setStatus(null)));
+       // 测试 merchantId 不匹配
+       shopMapper.insert(cloneIgnoreId(dbShop, o -> o.setMerchantId(null)));
+       // 测试 createTime 不匹配
+       shopMapper.insert(cloneIgnoreId(dbShop, o -> o.setCreateTime(null)));
+       // 测试 logoUrl 不匹配
+       shopMapper.insert(cloneIgnoreId(dbShop, o -> o.setLogoUrl(null)));
+       // 准备参数
+       ShopPageReqVO reqVO = new ShopPageReqVO();
+       reqVO.setName(null);
+       reqVO.setStatus(null);
+       reqVO.setMerchantId(null);
+       reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28));
+       reqVO.setLogoUrl(null);
+
+       // 调用
+       PageResult<ShopDO> pageResult = shopService.getShopPage(reqVO);
+       // 断言
+       assertEquals(1, pageResult.getTotal());
+       assertEquals(1, pageResult.getList().size());
+       assertPojoEquals(dbShop, pageResult.getList().get(0));
+    }
+
+}

+ 2 - 8
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/controller/app/aftersale/vo/AppAfterSaleCreateReqVO.java

@@ -19,8 +19,8 @@ public class AppAfterSaleCreateReqVO {
 
     @Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "售后方式不能为空")
-    private Integer way;    @InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
-
+    @InEnum(value = AfterSaleWayEnum.class, message = "售后方式必须是 {value}")
+    private Integer way;
 
     @Schema(description = "退款金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
     @NotNull(message = "退款金额不能为空")
@@ -37,10 +37,4 @@ public class AppAfterSaleCreateReqVO {
     @Schema(description = "补充凭证图片", example = "https://www.zhongxing.cn/1.png, https://www.zhongxing.cn/2.png")
     private List<String> applyPicUrls;
 
-    @Schema(description = "店铺id")
-    private Long shopId;
-
-    @Schema(description = "商户id")
-    private Long merchantId;
-
 }

+ 0 - 8
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/dal/dataobject/aftersale/AfterSaleDO.java

@@ -197,13 +197,5 @@ public class AfterSaleDO extends BaseDO {
      * 注意,只有拒绝收货才会填写
      */
     private String receiveReason;
-    /**
-     * 店铺id
-     */
-    private Long shopId;
-    /**
-     * 商户id
-     */
-    private Long merchantId;
 
 }

+ 0 - 17
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/aftersale/AfterSaleServiceImpl.java

@@ -8,7 +8,6 @@ import cn.newfeifan.mall.framework.common.pojo.PageResult;
 import cn.newfeifan.mall.framework.common.util.object.ObjectUtils;
 import cn.newfeifan.mall.module.pay.api.refund.PayRefundApi;
 import cn.newfeifan.mall.module.pay.api.refund.dto.PayRefundCreateReqDTO;
-import cn.newfeifan.mall.module.product.controller.admin.comment.vo.ShopBO;
 import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSaleDisagreeReqVO;
 import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSalePageReqVO;
 import cn.newfeifan.mall.module.trade.controller.admin.aftersale.vo.AfterSaleRefuseReqVO;
@@ -161,12 +160,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
         afterSale.setOrderNo(order.getNo()); // 记录 orderNo 订单流水,方便后续检索
         afterSale.setType(TradeOrderStatusEnum.isCompleted(order.getStatus())
                 ? AfterSaleTypeEnum.AFTER_SALE.getType() : AfterSaleTypeEnum.IN_SALE.getType());
-
-        //插入店铺信息及商户信息
-        ShopBO shop = getShop(afterSale.getOrderId());
-        afterSale.setShopId(shop.getShopId());
-        afterSale.setMerchantId(shop.getMerchantId());
-
         tradeAfterSaleMapper.insert(afterSale);
 
         // 更新交易订单项的售后状态
@@ -180,16 +173,6 @@ public class AfterSaleServiceImpl implements AfterSaleService {
         return afterSale;
     }
 
-    /**
-     * 获取商户、店铺信息
-     * @param orderId 订单编号
-     * @return 商铺信息
-     */
-    private ShopBO getShop(Long orderId){
-        TradeOrderDO order = tradeOrderQueryService.getOrder(orderId);
-        return new ShopBO(order.getShopId(),order.getMerchantId());
-    }
-
     @Override
     @Transactional(rollbackFor = Exception.class)
     @AfterSaleLog(operateType = AfterSaleOperateTypeEnum.ADMIN_AGREE_APPLY)

+ 351 - 68
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/order/TradeOrderUpdateServiceImpl.java

@@ -13,6 +13,8 @@ import cn.newfeifan.mall.framework.common.util.json.JsonUtils;
 import cn.newfeifan.mall.framework.common.util.number.MoneyUtils;
 import cn.newfeifan.mall.module.member.api.address.MemberAddressApi;
 import cn.newfeifan.mall.module.member.api.address.dto.MemberAddressRespDTO;
+import cn.newfeifan.mall.module.member.dal.dataobject.user.MemberUserDO;
+import cn.newfeifan.mall.module.member.dal.mysql.user.MemberUserMapper;
 import cn.newfeifan.mall.module.pay.api.order.PayOrderApi;
 import cn.newfeifan.mall.module.pay.api.order.dto.PayOrderCreateReqDTO;
 import cn.newfeifan.mall.module.pay.api.order.dto.PayOrderRespDTO;
@@ -49,14 +51,14 @@ import cn.newfeifan.mall.module.trade.service.delivery.DeliveryExpressService;
 import cn.newfeifan.mall.module.trade.service.message.TradeMessageService;
 import cn.newfeifan.mall.module.trade.service.message.bo.TradeOrderMessageWhenDeliveryOrderReqBO;
 import cn.newfeifan.mall.module.trade.service.order.handler.TradeOrderHandler;
+import cn.newfeifan.mall.module.trade.service.order.handler.TradeProductSkuOrderHandler;
 import cn.newfeifan.mall.module.trade.service.price.TradePriceService;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateReqBO;
 import cn.newfeifan.mall.module.trade.service.price.bo.TradePriceCalculateRespBO;
 import cn.newfeifan.mall.module.trade.service.price.calculator.TradePriceCalculatorHelper;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import lombok.extern.slf4j.Slf4j;
-import org.ehcache.shadow.org.terracotta.offheapstore.HashingMap;
 import org.jetbrains.annotations.NotNull;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -81,12 +83,18 @@ import static cn.newfeifan.mall.module.trade.enums.ErrorCodeConstants.*;
 @Slf4j
 public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
 
+    @Resource
+    private MemberUserMapper memberUserMapper;//add by ben 20240314
+
     @Resource
     private ProductSkuMapper productSkuMapper;//add by ben 20240314
 
     @Resource
     private ShopMapper shopMapper;//add by ben 20240314
 
+    @Resource
+    private TradeProductSkuOrderHandler tradeProductSkuOrderHandler;//add by ben 20240405
+
     @Resource
     private TradeOrderMapper tradeOrderMapper;
     @Resource
@@ -126,52 +134,116 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             settlementReqVO.setAddressId(address.getId());
         }
 
-        // 2. 计算价格
-        TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, settlementReqVO);
-
-        // 3. 拼接返回
-        AppTradeOrderSettlementRespVO respVO = TradeOrderConvert.INSTANCE.convert(calculateRespBO, address);
-
         // add by Ben 20240314
         // 4. 查询每个sku对应的店铺ID,并传回页面
         List<AppTradeOrderSettlementReqVO.Item> productSkuList = settlementReqVO.getItems();
-        List<Long> productSkuIdList = new ArrayList<>();
-        for (AppTradeOrderSettlementReqVO.Item skuItem : productSkuList) {
+        List<Long> productSkuIdList = new ArrayList<Long>();
+        Map<Long,AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<Long,AppTradeOrderSettlementReqVO.Item>();
+        for(AppTradeOrderSettlementReqVO.Item skuItem : productSkuList){
             productSkuIdList.add(skuItem.getSkuId());
+            itemMap.put(skuItem.getSkuId(),skuItem);
         }
         // 查询每个skuid对应的sku对象
         List<ProductSkuDO> productSkuDOList = productSkuMapper.selectListBySKuId(productSkuIdList);
 
         //key为店铺ID,value为skuid的List
-        Map<Long, List<Long>> shopSkuIds = new HashMap<Long, List<Long>>();
-        for (ProductSkuDO sku : productSkuDOList) {//把sku根据店聚合放到map中
+        Map<Long,List<Long>> shopSkuIds = new HashMap<Long, List<Long>>();
+        //key为店铺ID,value为item的Map
+        Map<Long,List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<Long,List<AppTradeOrderSettlementReqVO.Item>>();
+
+        for(ProductSkuDO sku:productSkuDOList){//把sku根据店聚合放到map中
             Long skuId = sku.getId();
             Long shopId = sku.getShopId();
-            if (shopId != null) {
-                List<Long> shopSkuList = shopSkuIds.get(shopId);
-                if (shopSkuList == null) {
-                    shopSkuList = new ArrayList<Long>();
-                    shopSkuIds.put(shopId, shopSkuList);
-                }
-                shopSkuList.add(skuId);//把sku根据店聚合放到map中
+
+            List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);
+            if(itemList==null){
+                itemList=new ArrayList<AppTradeOrderSettlementReqVO.Item>();
+                shopSkuItemMap.put(shopId,itemList);
+            }
+//            AppTradeOrderSettlementReqVO.Item item = new AppTradeOrderSettlementReqVO.Item();
+            itemList.add(itemMap.get(skuId));
+
+            List<Long> shopSkuList = shopSkuIds.get(shopId);
+            if(shopSkuList==null) {
+                shopSkuList = new ArrayList<Long>();
+                shopSkuIds.put(shopId,shopSkuList);
             }
+            shopSkuList.add(skuId);//把sku根据店聚合放到map中
         }
-        respVO.setShopSkuIds(shopSkuIds);//把sku根据店聚合放到map中
+
 
         //把店铺id和店铺名称查出来放到map中
         List<Long> shopIds = new ArrayList<Long>();
         for (Long shopid : shopSkuIds.keySet()) {
             shopIds.add(shopid);
         }
-        List<ShopDO> shopDOList = shopMapper.selectList(new LambdaQueryWrapper<ShopDO>().eq(ShopDO::getId,shopIds));
-        Map<Long, String> shopNameMap = new HashMap<Long, String>();//key为店铺id,value为店铺名
+        List<ShopDO> shopDOList = shopMapper.selectListById(shopIds);
+        Map<Long,String> shopNameMap = new HashMap<Long,String>();//key为店铺id,value为店铺名
         for (ShopDO shopDO : shopDOList) {
-            shopNameMap.put(shopDO.getId(), shopDO.getName());
+            shopNameMap.put(shopDO.getId(),shopDO.getName());
         }
+
+        // 2. 计算价格
+        /**
+         * add by Ben 20240402
+         * 原来下面的代码中是取settlementReqVO.getItems()的所有项计算的,其中Items含不同店铺的商品,现在要把不同店铺的商品分开计算
+         *
+         */
+        //保存每个店铺返回页面的 订单信息汇总
+        Map<Long,AppTradeOrderSettlementRespVO> shopRespVOMap = new HashMap<Long,AppTradeOrderSettlementRespVO>();
+        //所有店铺支付总价
+        Integer allShopPayPrice = 0;
+        //所有店商品不算运费的商品总价
+        Integer allShopItemPrice = 0;
+        //所有店运费总价
+        Integer allShopDeliveryPrice = 0;
+
+        //循环计算各个店铺的价格
+        for(Long shopId:shopSkuItemMap.keySet()){
+            List<AppTradeOrderSettlementReqVO.Item> items = shopSkuItemMap.get(shopId);
+            AppTradeOrderSettlementReqVO shopSettlementReqVO = new AppTradeOrderSettlementReqVO();
+            BeanUtils.copyProperties(settlementReqVO, shopSettlementReqVO);
+            shopSettlementReqVO.setItems(items);//设置每个店铺的商品。
+            shopSettlementReqVO.setShopId(shopId);
+
+            //计算价格
+            TradePriceCalculateRespBO shopCalculateRespBO = calculatePrice(userId, shopSettlementReqVO);
+            // 3. 拼接返回
+            AppTradeOrderSettlementRespVO respVO = TradeOrderConvert.INSTANCE.convert(shopCalculateRespBO, address);
+            shopRespVOMap.put(shopId,respVO);
+
+            //所有店铺支付总价
+            allShopPayPrice += shopCalculateRespBO.getPrice().getPayPrice();
+            //所有店商品不算运费的商品总价
+            allShopItemPrice += shopCalculateRespBO.getPrice().getTotalPrice();
+            //所有店运费总价
+            allShopDeliveryPrice += shopCalculateRespBO.getPrice().getDeliveryPrice();
+        }
+
+        //********这句是要被注释掉的
+        TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, settlementReqVO);
+
+//        TradePriceCalculateRespBO calculateRespBO = new TradePriceCalculateRespBO();
+        calculateRespBO.setPrice(new TradePriceCalculateRespBO.Price());
+        calculateRespBO.getPrice().setPayPrice(allShopPayPrice);
+        calculateRespBO.getPrice().setTotalPrice(allShopItemPrice);
+        calculateRespBO.getPrice().setDeliveryPrice(allShopDeliveryPrice);
+
+        //2.5 加载用户有的积分
+        MemberUserDO memberUserDO = memberUserMapper.selectById(userId);
+        Long memberPoints = memberUserDO.getCurrentMemberPoints();//用户当前积分
+
+        // 3. 拼接返回
+        AppTradeOrderSettlementRespVO respVO = TradeOrderConvert.INSTANCE.convert(calculateRespBO, address);
+
+        // add by Ben
+        respVO.setShopRespVOMap(shopRespVOMap);//保存每个店铺返回页面的 订单信息汇总
+        respVO.setShopSkuIds(shopSkuIds);//把sku根据店聚合放到map中
         respVO.setShopNameMap(shopNameMap);
+        respVO.setCurrentMemberPoints(memberPoints);//用户当前积分
 
-        System.out.println("shopSkuIds@@@@@@@@" + shopSkuIds);
-        System.out.println("shopNameMap@@@@@@@@" + shopNameMap);
+//        System.out.println("shopSkuIds@@@@@@@@"+shopSkuIds);
+//        System.out.println("shopNameMap@@@@@@@@"+shopNameMap);
 
         return respVO;
     }
@@ -206,30 +278,215 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
         TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList);
         calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的
                 "商品({}) 未设置为选中", item.getSkuId()));
+
+        calculateReqBO.setShopId(settlementReqVO.getShopId());
+        return tradePriceService.calculatePrice(calculateReqBO);
+    }
+
+
+
+    /**
+     * add by Ben
+     * 计算订单含积分的各项商品价格
+     *
+     * @param userId          用户编号
+     * @param settlementReqVO 结算信息
+     * @return 订单价格
+     */
+    private TradePriceCalculateRespBO calculatePriceWithPoints(Long userId, AppTradeOrderSettlementReqVO settlementReqVO) {
+        // 1. 如果来自购物车,则获得购物车的商品
+        List<CartDO> cartList = cartService.getCartList(userId,
+                convertSet(settlementReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId));
+
+        // 2. 计算价格
+        TradePriceCalculateReqBO calculateReqBO = TradeOrderConvert.INSTANCE.convert(userId, settlementReqVO, cartList);
+        calculateReqBO.getItems().forEach(item -> Assert.isTrue(item.getSelected(), // 防御性编程,保证都是选中的
+                "商品({}) 未设置为选中", item.getSkuId()));
+
+        calculateReqBO.setShopId(settlementReqVO.getShopId());
         return tradePriceService.calculatePrice(calculateReqBO);
     }
 
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_CREATE)
     public TradeOrderDO createOrder(Long userId, AppTradeOrderCreateReqVO createReqVO) {
-        // 1.1 价格计算
-        TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, createReqVO);
-        // 1.2 构建订单
-        TradeOrderDO order = buildTradeOrder(userId, createReqVO, calculateRespBO);
-        List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO);
-
-        // 2. 订单创建前的逻辑
-        tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));
-
-        // 3. 保存订单
-        tradeOrderMapper.insert(order);
-        orderItems.forEach(orderItem -> orderItem.setOrderId(order.getId()));
-        tradeOrderItemMapper.insertBatch(orderItems);
-
-        // 4. 订单创建后的逻辑
-        afterCreateTradeOrder(order, orderItems, createReqVO);
-        return order;
+
+        // add by Ben 20240314
+        // 4. 查询每个sku对应的店铺ID,并传回页面
+        List<AppTradeOrderSettlementReqVO.Item> productSkuList = createReqVO.getItems();
+        // 把所有商品的id都取出来,为查询所有商品的店铺做准备
+        List<Long> productSkuIdList = new ArrayList<Long>();
+        Map<Long,AppTradeOrderSettlementReqVO.Item> itemMap = new HashMap<Long,AppTradeOrderSettlementReqVO.Item>();
+        for(AppTradeOrderSettlementReqVO.Item skuItem : productSkuList){
+            productSkuIdList.add(skuItem.getSkuId());
+            itemMap.put(skuItem.getSkuId(),skuItem);
+        }
+        // 查询每个skuid对应的sku对象
+        List<ProductSkuDO> productSkuDOList = productSkuMapper.selectListBySKuId(productSkuIdList);
+
+        Map<Long,Long> shopMerchantMap = new HashMap<Long,Long>();//key是店铺ID,value是商户ID
+        for(ProductSkuDO productSkuDO:productSkuDOList){
+            shopMerchantMap.put(productSkuDO.getShopId(),productSkuDO.getMerchantId());
+        }
+
+        //key为店铺ID,value为skuid的List
+        Map<Long,List<Long>> shopSkuIds = new HashMap<Long, List<Long>>();
+        //key为店铺ID,value为item的Map
+        Map<Long,List<AppTradeOrderSettlementReqVO.Item>> shopSkuItemMap = new HashMap<Long,List<AppTradeOrderSettlementReqVO.Item>>();
+
+
+
+        for(ProductSkuDO sku:productSkuDOList){//把sku根据店聚合放到map中
+            Long skuId = sku.getId();
+            Long shopId = sku.getShopId();
+
+            List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);
+            if(itemList==null){
+                itemList=new ArrayList<AppTradeOrderSettlementReqVO.Item>();
+                shopSkuItemMap.put(shopId,itemList);
+            }
+//            AppTradeOrderSettlementReqVO.Item item = new AppTradeOrderSettlementReqVO.Item();
+            itemList.add(itemMap.get(skuId));
+
+            List<Long> shopSkuList = shopSkuIds.get(shopId);
+            if(shopSkuList==null) {
+                shopSkuList = new ArrayList<Long>();
+                shopSkuIds.put(shopId,shopSkuList);
+            }
+            shopSkuList.add(skuId);//把sku根据店聚合放到map中
+        }
+
+
+        //add by Ben
+        //为键值对,键为店铺ID,值为备注文本
+        Map<Long,String> shopRemarks = createReqVO.getShopRemarks();
+        if(shopRemarks==null){
+            shopRemarks = new HashMap<Long,String>();
+        }
+
+        //消费者在页面录入的,要使用的积分
+        Integer payPoints = createReqVO.getPayPoints();
+        if(payPoints == null){
+            payPoints = 0;
+        }
+
+
+        payPoints = 3;//为了测试方便,临时写死
+
+        //计算订单含积分的各项商品价格
+        TradePriceCalculateRespBO tradePriceCalculateRespBO = calculatePriceWithPoints(userId, createReqVO);
+        //计算分摊的积分金额
+        List<Integer> dividePoints = TradePriceCalculatorHelper.dividePrice(tradePriceCalculateRespBO.getItems(), payPoints);
+        //键为skuId,value为单个商品项信息
+        Map<Long, TradePriceCalculateRespBO.OrderItem> itemPayPointsMap = new HashMap<Long, TradePriceCalculateRespBO.OrderItem>();
+
+        //订单项数组
+        List<TradePriceCalculateRespBO.OrderItem> priceOrderItems = tradePriceCalculateRespBO.getItems();
+        for (int i = 0; i < priceOrderItems.size(); i++) {
+            TradePriceCalculateRespBO.OrderItem orderItem = priceOrderItems.get(i);
+            Integer itemPoint = dividePoints.get(i);//每项商品使用的积分
+            orderItem.setPayPoints(itemPoint);
+            itemPayPointsMap.put(orderItem.getSkuId(),orderItem);
+        }
+
+        Integer allShopPayRMB = 0;//所有店铺订单实际支付的金额
+
+        List<Map<String,Object>> orderMapList = new ArrayList<Map<String,Object>>();
+
+        //循环调用原来的计算订单价格方法,计算价格
+        //循环一次生成一间店的订单
+        for(Long shopId:shopSkuItemMap.keySet()){
+
+            AppTradeOrderCreateReqVO shopCreateReqVO = new AppTradeOrderCreateReqVO();
+
+            BeanUtils.copyProperties(createReqVO, shopCreateReqVO);
+            List<AppTradeOrderSettlementReqVO.Item> itemList = shopSkuItemMap.get(shopId);//店铺的商品列表
+            shopCreateReqVO.setItems(itemList);//设置为只有一个店铺的商品列表
+
+            //设置本店的订单备注
+            String remark = shopRemarks.get(shopId);
+            shopCreateReqVO.setRemark(remark);
+
+            // 1.1 价格计算
+            TradePriceCalculateRespBO calculateRespBO = calculatePrice(userId, shopCreateReqVO);
+            // 1.2 构建订单
+            TradeOrderDO order = buildTradeOrder(userId, shopCreateReqVO, calculateRespBO);
+            List<TradeOrderItemDO> orderItems = buildTradeOrderItems(order, calculateRespBO);
+
+            // 2. 订单创建前的逻辑
+            //修改sku库存
+            tradeProductSkuOrderHandler.beforeOrderCreate(order, orderItems);
+            //下面的要注释掉:下面是旧的“订单创建前的逻辑”,因为里面的修改积分、营销与我们的业务不符,所以注释掉,只保留处理sku库存的代码
+//            tradeOrderHandlers.forEach(handler -> handler.beforeOrderCreate(order, orderItems));
+
+            // 3. 保存一间店铺的订单
+            Integer shopPayPoints = 0;//一间店铺订单总支付积分
+            Integer shopPayPrice = 0;//一间店铺订单总支付价格
+
+            for(TradeOrderItemDO orderItem:orderItems){//一间店铺订单的所有商品项
+//                orderItem.setOrderId(order.getId());
+
+                //3.5 add by Ben
+                //计算抵扣积分后的价格
+                Long skuId = orderItem.getSkuId();
+                TradePriceCalculateRespBO.OrderItem orderItemTmp = itemPayPointsMap.get(skuId);
+                orderItem.setPayPoints(orderItemTmp.getPayPoints()); //本商品使用积分
+                Integer payRmb = orderItem.getPrice()*orderItem.getCount()-orderItemTmp.getPayPoints();//本商品实付人民币
+                orderItem.setPayRmb(payRmb);//本商品实付人民币
+                orderItem.setPayPrice(payRmb);//本商品实付人民币
+
+                shopPayPoints += orderItemTmp.getPayPoints();//一间店铺订单总支付积分
+                shopPayPrice += payRmb;//一间店铺订单总支付价格
+            }
+
+            shopPayPrice+=order.getDeliveryPrice();//店铺支付总金额,加上运费
+
+            allShopPayRMB +=shopPayPrice;
+
+            Long merchantId = shopMerchantMap.get(shopId);//商户ID
+
+            order.setMerchantId(merchantId);
+            order.setShopId(shopId);
+            order.setPayPrice(shopPayPrice);
+            order.setPayRmb(shopPayPrice);
+            order.setPayPoints(shopPayPoints);
+
+            tradeOrderMapper.insert(order);
+
+            orderItems.forEach(orderItem -> orderItem.setOrderId(order.getId()));
+            tradeOrderItemMapper.insertBatch(orderItems);
+
+            // 4. 订单创建后的逻辑
+            afterCreateTradeOrder(order, orderItems, shopCreateReqVO);
+
+//            Map<>
+            Map<String,Object> orderMap = new HashMap<String,Object>();
+            orderMap.put("order",order);
+            orderMap.put("orderItems",orderItems);
+            orderMapList.add(orderMap);//把订单保存起来,为支付订单做准备
+        }
+
+        TradeOrderDO virtualOrder = new TradeOrderDO();//为了生成支付订单,创建的虚拟订单,本订单不会保存到数据库
+        TradeOrderDO firstOrder = (TradeOrderDO)(orderMapList.get(0).get("order"));
+        List<TradeOrderItemDO> firstOrderItems = (List<TradeOrderItemDO>)(orderMapList.get(0).get("orderItems"));
+
+        BeanUtils.copyProperties(firstOrder, virtualOrder);
+        virtualOrder.setPayPrice(allShopPayRMB);
+        virtualOrder.setPayRmb(allShopPayRMB);
+        virtualOrder.setId(0l);//为了让payOrder中的tradeOrderId为0;
+
+        // 3. 生成预支付:生成支付订单记录
+        Long payOrderId = createPayOrder(virtualOrder, firstOrderItems);
+
+        for(Map<String,Object> m:orderMapList){
+            TradeOrderDO order = (TradeOrderDO)(m.get("order"));
+            // 更新到交易单上
+            tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId));
+        }
+
+        return virtualOrder;
     }
 
     private TradeOrderDO buildTradeOrder(Long userId, AppTradeOrderCreateReqVO createReqVO,
@@ -275,7 +532,9 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     private void afterCreateTradeOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems,
                                        AppTradeOrderCreateReqVO createReqVO) {
         // 1. 执行订单创建后置处理器
-        tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems));
+
+        //下面的代码是原来的营销代码,用不上,先注释掉
+//        tradeOrderHandlers.forEach(handler -> handler.afterOrderCreate(order, orderItems));
 
         // 2. 删除购物车商品
         Set<Long> cartIds = convertSet(createReqVO.getItems(), AppTradeOrderSettlementReqVO.Item::getCartId);
@@ -283,50 +542,74 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
             cartService.deleteCart(order.getUserId(), cartIds);
         }
 
-        // 3. 生成预支付
-        createPayOrder(order, orderItems);
+        // 3. 生成预支付(去除)
+//        createPayOrder(order, orderItems);
 
         // 4. 插入订单日志
         TradeOrderLogUtils.setOrderInfo(order.getId(), null, order.getStatus());
 
-        // TODO @LeeYan9: 是可以思考下, 订单的营销优惠记录, 应该记录在哪里, 微信讨论起来!
+        // TODO 是可以思考下, 订单的营销优惠记录, 应该记录在哪里
     }
 
-    private void createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
+
+
+    private Long createPayOrder(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
         // 创建支付单,用于后续的支付
         PayOrderCreateReqDTO payOrderCreateReqDTO = TradeOrderConvert.INSTANCE.convert(
                 order, orderItems, tradeOrderProperties);
+
+        payOrderCreateReqDTO.setPrice(order.getPayRmb());//同步订单价格
+
         Long payOrderId = payOrderApi.createOrder(payOrderCreateReqDTO);
 
+        // update By Ben  因为订单与支付订单表的关系已经变成多对一了,所以把下面为订单表设置支付订单ID要移到外面做。
         // 更新到交易单上
-        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId));
+//        tradeOrderMapper.updateById(new TradeOrderDO().setId(order.getId()).setPayOrderId(payOrderId));
+
         order.setPayOrderId(payOrderId);
+
+        return payOrderId;//返回支付订单ID
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MEMBER_PAY)
-    public void updateOrderPaid(Long id, Long payOrderId) {
-        // 1. 校验并获得交易订单(可支付)
-        KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(id, payOrderId);
-        TradeOrderDO order = orderResult.getKey();
-        PayOrderRespDTO payOrder = orderResult.getValue();
-
-        // 2. 更新 TradeOrderDO 状态为已支付,等待发货
-        int updateCount = tradeOrderMapper.updateByIdAndStatus(id, order.getStatus(),
-                new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true)
-                        .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
-        if (updateCount == 0) {
-            throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
-        }
+    //下面的参数中的id1为交易订单TradeOrder表的id,已经没用了,因为一个支付订单对应多个订单。
+    //只有支付订单id参数payOrderId是有用的。
+    public void updateOrderPaid(Long id1, Long payOrderId) {
 
-        // 3. 执行 TradeOrderHandler 的后置处理
-        List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(id);
-        tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));
+        //add by Ben 根据支付订单id,查询所有 支付订单 对应的 订单
+        List<TradeOrderDO> TradeOrderDOList = tradeOrderMapper.selectList("no", payOrderId);
+
+        for(TradeOrderDO tradeOrderDO:TradeOrderDOList) {
+
+            Long tradeOrderId = tradeOrderDO.getId();
 
-        // 4. 记录订单日志
-        TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
-        TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
+            // 1. 校验并获得交易订单(可支付)
+            KeyValue<TradeOrderDO, PayOrderRespDTO> orderResult = validateOrderPayable(tradeOrderId, payOrderId);
+
+            TradeOrderDO order = orderResult.getKey();
+            PayOrderRespDTO payOrder = orderResult.getValue();
+
+            // 2. 更新 TradeOrderDO 状态为已支付,等待发货
+            int updateCount = tradeOrderMapper.updateByIdAndStatus(tradeOrderId, order.getStatus(),
+                    new TradeOrderDO().setStatus(TradeOrderStatusEnum.UNDELIVERED.getStatus()).setPayStatus(true)
+                            .setPayTime(LocalDateTime.now()).setPayChannelCode(payOrder.getChannelCode()));
+            if (updateCount == 0) {
+                throw exception(ORDER_UPDATE_PAID_STATUS_NOT_UNPAID);
+            }
+
+            // 3. 执行 TradeOrderHandler 的后置处理
+            List<TradeOrderItemDO> orderItems = tradeOrderItemMapper.selectListByOrderId(tradeOrderId);
+
+            //注释 by Ben ,下面是系统原来的营销部分,和我们业务对不上,注释掉
+//            tradeOrderHandlers.forEach(handler -> handler.afterPayOrder(order, orderItems));
+
+            // 4. 记录订单日志
+            TradeOrderLogUtils.setOrderInfo(order.getId(), order.getStatus(), TradeOrderStatusEnum.UNDELIVERED.getStatus());
+            TradeOrderLogUtils.setUserInfo(order.getUserId(), UserTypeEnum.MEMBER.getValue());
+
+        }
     }
 
     /**
@@ -881,7 +1164,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService {
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void cancelPaidOrder(Long userId, Long orderId) {
-        // TODO 芋艿:这里实现要优化下;
+        // TODO 非繁人:这里实现要优化下;
         TradeOrderDO order = tradeOrderMapper.selectOrderByIdAndUserId(orderId, userId);
         if (order == null) {
             throw exception(ORDER_NOT_FOUND);

+ 2 - 3
feifan-module-mall/feifan-module-trade-biz/src/main/java/cn/newfeifan/mall/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java

@@ -49,8 +49,7 @@ public class TradeMemberLevelPriceCalculator implements TradePriceCalculator {
         // 2. 计算每个 SKU 的优惠金额
         result.getItems().forEach(orderItem -> {
             // 2.1 计算优惠金额
-//            Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
-            Integer vipPrice = 0;
+            Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
             if (vipPrice <= 0) {
                 return;
             }
@@ -74,7 +73,7 @@ public class TradeMemberLevelPriceCalculator implements TradePriceCalculator {
     /**
      * 计算会员 VIP 优惠价格
      *
-     * @param price           原价
+     * @param price 原价
      * @param discountPercent 折扣
      * @return 优惠价格
      */