Browse Source

新增商品组合退款统计

大大的豆芽 22 hours ago
parent
commit
3962b89cef

+ 4 - 4
admin-ui/.env.development

@@ -5,10 +5,10 @@ VUE_APP_TITLE = 一七管理系统
 ENV = 'development'
 
 
-# VUE_APP_BASE_API_HOST = 'http://127.0.0.1:9801'
-# VUE_APP_BASE_API = 'http://127.0.0.1:9801'
-VUE_APP_BASE_API_HOST = 'http://139.224.65.227:8091/prod-api'
-VUE_APP_BASE_API = 'http://139.224.65.227:8091/prod-api'
+VUE_APP_BASE_API_HOST = 'http://127.0.0.1:9801'
+VUE_APP_BASE_API = 'http://127.0.0.1:9801'
+# VUE_APP_BASE_API_HOST = 'http://139.224.65.227:8091/prod-api'
+# VUE_APP_BASE_API = 'http://139.224.65.227:8091/prod-api'
 # VUE_APP_BASE_API_HOST = 'http://192.168.5.247:9801/'
 # VUE_APP_BASE_API = 'http://192.168.5.247:9801/'
 

+ 18 - 0
admin-ui/src/api/order/goods.js

@@ -131,3 +131,21 @@ export function getDeliveryPath(query) {
     params: query
   })
 }
+
+// 查询商品销售统计列表
+export function listStatistics(query) {
+  return request({
+    url: '/mapi/order/goods/statistics',
+    method: 'get',
+    params: query
+  })
+}
+
+// 导出商品销售统计列表
+export function exportStatistics(query) {
+  return request({
+    url: '/mapi/order/goods/statistics/export',
+    method: 'post',
+    params: query
+  })
+}

+ 25 - 1
yiqi-admin/src/main/java/com/yiqi/admin/controller/order/OrderGoodsController.java

@@ -355,5 +355,29 @@ public class OrderGoodsController extends BaseController {
     public R<OrderDeliveryPathVO> getDeliveryPath(@RequestParam("orderId") Long orderId) throws Exception {
         return R.ok(orderGoodsService.getDeliveryPath(orderId));
     }
-    //</editor-folder>
+
+    /**
+     * 查询商品销售统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('order:goods:statistics')")
+    @GetMapping("/statistics")
+    @ApiOperation(value = "查询商品销售统计列表")
+    public TableDataInfo statistics(GoodsStatisticsQueryDTO queryDTO) {
+        startPage();
+        List<GoodsStatisticsVO> list = orderGoodsService.getGoodsStatisticsList(queryDTO);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出商品销售统计列表
+     */
+    @PreAuthorize("@ss.hasPermi('order:goods:export')")
+    @Log(title = "商品销售统计", businessType = BusinessType.EXPORT)
+    @PostMapping("/statistics/export")
+    @ApiOperation(value = "导出商品销售统计列表")
+    public void exportStatistics(HttpServletResponse response, GoodsStatisticsQueryDTO queryDTO) {
+        List<GoodsStatisticsVO> list = orderGoodsService.getGoodsStatisticsList(queryDTO);
+        ExcelUtil<GoodsStatisticsVO> util = new ExcelUtil<GoodsStatisticsVO>(GoodsStatisticsVO.class);
+        util.exportExcel(response, list, "商品销售统计数据");
+    }
 }

+ 2 - 2
yiqi-common/src/main/java/com/yiqi/common/enums/GoodsType.java

@@ -3,8 +3,8 @@ package com.yiqi.common.enums;
 
 public enum GoodsType  implements CodeEnum{
 
-    MATERIAL("0", "材料商品"),
-    NORMAL("1", "普通商品"),
+    MATERIAL("1", "材料商品"),
+    NORMAL("0", "普通商品"),
     LIFE_SERVICE("2","生活服务"),
     CAR("3","汽车美容")
     ;

+ 7 - 7
yiqi-common/src/main/java/com/yiqi/order/domain/OrderGoods.java

@@ -98,13 +98,6 @@ public class OrderGoods extends BaseEntity {
     @ApiModelProperty("订单总价")
     private BigDecimal totalPrice;
 
-    /**
-     * 抵扣金额
-     */
-    @Excel(name = "抵扣金额")
-    @ApiModelProperty("抵扣金额")
-    private BigDecimal deductAmount;
-
     /**
      * 现金支付金额
      */
@@ -270,6 +263,13 @@ public class OrderGoods extends BaseEntity {
     @ApiModelProperty("下单渠道(APP=APP,WXAPP=小程序)")
     private String orderSource;
 
+    /**
+     * 抵扣金额
+     */
+    @Excel(name = "抵扣金额")
+    @ApiModelProperty("抵扣金额")
+    private BigDecimal deductAmount;
+
     @ApiModelProperty("优惠券抵扣金额")
     private BigDecimal couponDeductAmount;
 

+ 52 - 12
yiqi-common/src/main/java/com/yiqi/order/domain/OrderGoodsSku.java

@@ -1,6 +1,7 @@
 package com.yiqi.order.domain;
 
 import java.math.BigDecimal;
+
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -21,51 +22,90 @@ import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 @ApiModel("商品订单物料明细")
 @TableName("order_goods_sku")
 @Data
-public class OrderGoodsSku extends BaseEntity
-{
-    private static final long serialVersionUID=1L;
+public class OrderGoodsSku extends BaseEntity {
+    private static final long serialVersionUID = 1L;
 
-    /** 主键ID */
+    /**
+     * 主键ID
+     */
     @ApiModelProperty("主键ID")
     @TableId(type = IdType.AUTO)
     private Long id;
 
-    /** 订单ID */
+    /**
+     * 订单ID
+     */
     @Excel(name = "订单ID")
     @ApiModelProperty("订单ID")
     private Long orderId;
 
-    /** 订单编号 */
+    /**
+     * 退款ID
+     */
+    @Excel(name = "退款ID")
+    @ApiModelProperty("退款ID")
+    private Long refundId;
+
+    /**
+     * 订单编号
+     */
     @Excel(name = "订单编号")
     @ApiModelProperty("订单编号")
     private String orderNo;
 
-    /** 购买数量 */
+    /**
+     * 购买数量
+     */
     @Excel(name = "购买数量")
     @ApiModelProperty("购买数量")
     private Integer buyNum;
 
-    /** 单价 */
+    /**
+     * 单价
+     */
     @Excel(name = "单价")
     @ApiModelProperty("单价")
     private BigDecimal salePrice;
 
-    /** 规格内容 */
+
+    /**
+     * 折扣总价
+     */
+    @Excel(name = "折扣总价")
+    @ApiModelProperty("折扣总价")
+    private BigDecimal totalAmount;
+
+    /**
+     * 退款总价
+     */
+    @Excel(name = "退款总价")
+    @ApiModelProperty("退款总价")
+    private BigDecimal refundAmount;
+
+    /**
+     * 规格内容
+     */
     @Excel(name = "规格内容")
     @ApiModelProperty("规格内容")
     private String skuName;
 
-    /** 物料ID */
+    /**
+     * 物料ID
+     */
     @Excel(name = "物料ID")
     @ApiModelProperty("物料ID")
     private Long skuId;
 
-    /** 商品ID */
+    /**
+     * 商品ID
+     */
     @Excel(name = "商品ID")
     @ApiModelProperty("商品ID")
     private Long goodsId;
 
-    /** 商品名称 */
+    /**
+     * 商品名称
+     */
     @Excel(name = "商品名称")
     @ApiModelProperty("商品名称")
     private String goodsName;

+ 8 - 1
yiqi-common/src/main/java/com/yiqi/order/domain/dto/RechargeCardPayDTO.java

@@ -1,6 +1,8 @@
 package com.yiqi.order.domain.dto;
 
 import com.yiqi.common.annotation.Excel;
+import com.yiqi.common.enums.BuyGoodsType;
+import com.yiqi.common.enums.GoodsType;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
@@ -17,7 +19,9 @@ public class RechargeCardPayDTO {
     @ApiModelProperty("客户ID")
     private Long appUserId;
 
-    /** 来源类型 */
+    /**
+     * 来源类型
+     */
     @Excel(name = "来源类型")
     @ApiModelProperty("来源类型")
     private String sourceType;
@@ -55,5 +59,8 @@ public class RechargeCardPayDTO {
         this.orderNo = orderNo;
         this.payAmount = payAmount;
         this.buyGoodsType = buyGoodsType;
+        if (buyGoodsType.equals(GoodsType.NORMAL.getCode())) {
+            this.buyGoodsType = BuyGoodsType.COMMON_GOODS.getCode();
+        }
     }
 }

+ 16 - 6
yiqi-common/src/main/java/com/yiqi/order/service/IOrderGoodsService.java

@@ -55,16 +55,18 @@ public interface IOrderGoodsService extends IService<OrderGoods> {
     public List<GoodsOrderQueryVO> selectOrderGoodsList(GoodsOrderQueryDTO goodsOrderQueryDTO);
 
     /**
-     * 零售商品订单
+     * 创建零售商品订单
      *
-     * @param orderGoodsDTO 商品订单
-     * @return 结果
+     * @param orderGoodsDTO 零售商品订单
+     * @return 零售商品订单
      */
-    public OrderPayResultVO insertRetailOrderGoods(OrderGoodsDTO orderGoodsDTO, List<OrderGoodsSkuInfoVO> orderGoodsSkuInfoVOS);
-
-
     public OrderGoods cereateRetailOrderGoods(OrderGoodsDTO orderGoodsDTO, List<OrderGoodsSkuInfoVO> orderGoodsSkuInfoVOS);
 
+    /**
+     * 获取订单物料信息
+     * @param orderGoodsDTO
+     * @return
+     */
     List<OrderGoodsSkuInfoVO> getSkuInfoList(List<Long> skuIdList, String orderSource);
 
     /**
@@ -186,4 +188,12 @@ public interface IOrderGoodsService extends IService<OrderGoods> {
      */
     public OrderDeliveryPathVO getDeliveryPath(Long orderId) throws Exception;
 
+    /**
+     * 查询商品销售统计列表
+     *
+     * @param queryDTO 查询条件
+     * @return 商品销售统计列表
+     */
+    List<GoodsStatisticsVO> getGoodsStatisticsList(GoodsStatisticsQueryDTO queryDTO);
+
 }

+ 10 - 4
yiqi-core/src/main/java/com/yiqi/order/mapper/OrderGoodsMapper.java

@@ -1,11 +1,9 @@
 package com.yiqi.order.mapper;
 
 import java.util.List;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.yiqi.order.domain.dto.GoodsOrderQueryDTO;
-import com.yiqi.order.domain.dto.GoodsOrderRefundQueryDTO;
-import com.yiqi.order.domain.dto.OrderFinancialDayQueryDTO;
-import com.yiqi.order.domain.dto.OrderFinancialMonthQueryDTO;
+import com.yiqi.order.domain.dto.*;
 import com.yiqi.order.domain.dto.weapp.AppGoodsOrderInfoQueryDTO;
 import com.yiqi.order.domain.vo.*;
 import com.yiqi.order.domain.vo.weapp.AppGoodsOrderInfoQueryVO;
@@ -50,9 +48,17 @@ public interface OrderGoodsMapper extends BaseMapper<OrderGoods> {
 
     /**
      * APP分页获取订单商品列表
+     *
      * @param appGoodsOrderInfoQueryDTO
      * @return
      */
     public List<AppGoodsOrderInfoQueryVO> getGoodsOrderListByApp(AppGoodsOrderInfoQueryDTO appGoodsOrderInfoQueryDTO);
 
+    /**
+     * 获取商品订单统计列表
+     *
+     * @param queryDTO
+     * @return
+     */
+    List<GoodsStatisticsVO> getGoodsStatisticsList(GoodsStatisticsQueryDTO queryDTO);
 }

+ 40 - 19
yiqi-core/src/main/java/com/yiqi/order/service/impl/OrderGoodsServiceImpl.java

@@ -183,23 +183,9 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
         return baseMapper.selectOrderGoodsList(goodsOrderQueryDTO);
     }
 
-    /**
-     * 新增零售商品订单
-     *
-     * @param orderGoodsDTO 零售商品订单
-     * @return 结果
-     */
-    @Override
-    @Transactional(rollbackFor = RuntimeException.class)
-    public OrderPayResultVO insertRetailOrderGoods(OrderGoodsDTO orderGoodsDTO, List<OrderGoodsSkuInfoVO> orderGoodsSkuInfoVOS) {
-        // 保存零售商品订单
-        OrderGoods orderGoods = this.buildRetailOrderGoodsInfo(orderGoodsDTO, orderGoodsSkuInfoVOS);
-        // 处理支付流程
-        OrderPayResultVO orderPayResultVO = this.handlePay(orderGoods, orderGoodsDTO);
-        return orderPayResultVO;
-    }
 
     @Override
+    @Transactional(rollbackFor = RuntimeException.class)
     public OrderGoods cereateRetailOrderGoods(OrderGoodsDTO orderGoodsDTO, List<OrderGoodsSkuInfoVO> orderGoodsSkuInfoVOS) {
         // 保存零售商品订单
         OrderGoods orderGoods = this.buildRetailOrderGoodsInfo(orderGoodsDTO, orderGoodsSkuInfoVOS);
@@ -217,13 +203,11 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
         OrderGoods orderGoods = new OrderGoods();
         BeanUtils.copyProperties(orderGoodsDTO, orderGoods);
         orderGoods.buildCreateData();
-        orderGoods.setGoodsOrderType(GoodsOrderType.retail.getCode());
         orderGoods.setPayType(orderGoodsDTO.getPayType());
         orderGoods.setGoodsType(orderGoodsDTO.getGoodsType());
-        orderGoods.setDeductAmount(orderGoodsDTO.getDeductAmount() == null ? BigDecimal.ZERO : orderGoodsDTO.getDeductAmount());
         orderGoods.setCouponDeductAmount(orderGoodsDTO.getCouponDeductAmount() == null ? BigDecimal.ZERO : orderGoodsDTO.getCouponDeductAmount());
         orderGoods.setCashDeductAmount(orderGoodsDTO.getDeductAmount());
-        orderGoods.setPayAmount(orderGoodsDTO.getTotalPrice().subtract(orderGoods.getDeductAmount()));
+        orderGoods.setPayAmount(orderGoodsDTO.getTotalPrice().subtract(orderGoods.getCashDeductAmount()).subtract(orderGoods.getCouponDeductAmount()));
         orderGoods.setOrderStatus(OrderGoodsStatusType.NO_PAY.getCode());
         orderGoods.setRefundAmount(BigDecimal.ZERO);
         orderGoods.setDeliveryWay(this.getDeliveryWayByOrderSource(orderGoodsDTO.getOrderSource()));
@@ -242,8 +226,16 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
         }
         this.save(orderGoods);
 
+        // 计算商品原价总额
+        BigDecimal totalOriginalAmount = BigDecimal.ZERO;
+        for (OrderGoodsSkuInfoVO skuInfo : orderGoodsSkuInfoVOS) {
+            totalOriginalAmount = totalOriginalAmount.add(skuInfo.getSalePrice().multiply(new BigDecimal(skuInfo.getBuyNum())));
+        }
+        
         // 无法批量插入
-        for (OrderGoodsSkuInfoVO retailGoodsDTO : orderGoodsSkuInfoVOS) {
+        BigDecimal allocatedAmount = BigDecimal.ZERO;
+        for (int i = 0; i < orderGoodsSkuInfoVOS.size(); i++) {
+            OrderGoodsSkuInfoVO retailGoodsDTO = orderGoodsSkuInfoVOS.get(i);
             OrderGoodsSku orderGoodsSku = new OrderGoodsSku();
             orderGoodsSku.setOrderId(orderGoods.getId());
             orderGoodsSku.setOrderNo(orderGoods.getOrderNo());
@@ -251,12 +243,30 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
             orderGoodsSku.setGoodsImg(retailGoodsDTO.getGoodsImg());
             orderGoodsSku.setBuyNum(retailGoodsDTO.getBuyNum());
             orderGoodsSku.setSalePrice(retailGoodsDTO.getSalePrice());
+            orderGoodsSku.setRefundAmount(BigDecimal.ZERO);
             orderGoodsSku.setSkuName(retailGoodsDTO.getSkuName());
             orderGoodsSku.setSkuId(retailGoodsDTO.getSkuId());
             orderGoodsSku.setGoodsId(retailGoodsDTO.getGoodsId());
             orderGoodsSku.setCreateBy(orderGoods.getCreateBy());
             orderGoodsSku.setCreateTime(DateUtils.getNowDate());
             orderGoodsSku.setCreateById(orderGoods.getCreateById());
+            
+            // 计算该商品应分摊的支付金额
+            BigDecimal goodsOriginalAmount = retailGoodsDTO.getSalePrice().multiply(new BigDecimal(retailGoodsDTO.getBuyNum()));
+            BigDecimal goodsPayAmount;
+            
+            // 最后一个商品,使用剩余金额
+            if (i == orderGoodsSkuInfoVOS.size() - 1) {
+                goodsPayAmount = orderGoods.getPayAmount().subtract(allocatedAmount);
+            } else {
+                // 按照原价比例分配
+                goodsPayAmount = orderGoods.getPayAmount()
+                    .multiply(goodsOriginalAmount)
+                    .divide(totalOriginalAmount, 2, BigDecimal.ROUND_DOWN);
+                allocatedAmount = allocatedAmount.add(goodsPayAmount);
+            }
+            
+            orderGoodsSku.setTotalAmount(goodsPayAmount);
             orderGoodsSkuService.save(orderGoodsSku);
         }
         return orderGoods;
@@ -884,6 +894,12 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
         // 处理销量 - 扣商品销量
         List<OrderGoodsSku> list = orderGoodsSkuService.list(new QueryWrapper<OrderGoodsSku>().lambda().eq(OrderGoodsSku::getOrderId, orderGoods.getId()));
         if (CollUtil.isNotEmpty(list)) {
+            //更新商品退款金额
+            for (OrderGoodsSku orderGoodsSku : list) {
+                orderGoodsSku.setRefundAmount(orderGoodsSku.getTotalAmount());
+                orderGoodsSku.setRefundId(orderGoodsRefund.getId());
+                orderGoodsSkuService.updateById(orderGoodsSku);
+            }
             this.buildUpdateGoodsSales(list, Boolean.FALSE);
         }
         return null;
@@ -1262,4 +1278,9 @@ public class OrderGoodsServiceImpl extends ServiceImpl<OrderGoodsMapper, OrderGo
         return thirdDeliveryService.getDeliveryPath(OrderThirdDeliveryPathDTO.buildDeliveryPathByGoodsOrder(orderGoods, appUserInfo.getWxOpenId()));
     }
 
+    @Override
+    public List<GoodsStatisticsVO> getGoodsStatisticsList(GoodsStatisticsQueryDTO queryDTO) {
+        return baseMapper.getGoodsStatisticsList(queryDTO);
+    }
+
 }

+ 35 - 0
yiqi-core/src/main/resources/mapper/order/OrderGoodsMapper.xml

@@ -176,4 +176,39 @@
 
     </select>
 
+    <select id="getGoodsStatisticsList" resultType="com.yiqi.order.domain.vo.GoodsStatisticsVO">
+        SELECT 
+            a.goods_id as goodsId,
+            a.goods_name as goodsName,
+            a.goods_img as goodsImg,
+            SUM(a.buy_num) as saleCount,
+            SUM(a.buy_num * a.sale_price) as saleAmount,
+            SUM(CASE WHEN a.refund_amount > 0 THEN a.buy_num ELSE 0 END) as refundCount,
+            SUM(a.refund_amount) as refundAmount,
+            SUM(a.buy_num) - SUM(CASE WHEN a.refund_amount > 0 THEN a.buy_num ELSE 0 END) as actualSaleCount,
+            SUM(a.buy_num * a.sale_price) - SUM(a.refund_amount) as actualSaleAmount
+        FROM order_goods_sku a
+        LEFT JOIN order_goods b ON a.order_id = b.id
+        <where>
+            b.del_flag = '0'
+            <if test="startTime != null and startTime != ''">
+                AND b.pay_time >= concat(#{startTime}, ' 00:00:00')
+            </if>
+            <if test="endTime != null and endTime != ''">
+                AND b.pay_time &lt;= concat(#{endTime}, ' 23:59:59')
+            </if>
+            <if test="goodsType != null and goodsType != ''">
+                AND b.goods_type = #{goodsType}
+            </if>
+            <if test="orgId != null">
+                AND b.org_id = #{orgId}
+            </if>
+            <if test="goodsName != null and goodsName != ''">
+                AND a.goods_name LIKE CONCAT('%', #{goodsName}, '%')
+            </if>
+        </where>
+        GROUP BY a.goods_id
+        ORDER BY saleAmount DESC
+    </select>
+
 </mapper>