Browse Source

对接拼团数据1

master
wangfukang 1 week ago
parent
commit
22db0e9b6f
  1. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java
  2. 22
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallRefundRecordController.java
  3. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java
  4. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallRefundRecordMapper.java
  5. 14
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallRefundRecord.java
  6. 25
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallRefundRecordPageQuery.java
  7. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java
  8. 6
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallRefundRecordService.java
  9. 153
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java
  10. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderGroupServiceImpl.java
  11. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
  12. 228
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java
  13. 4
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WechatPayUtil.java
  14. 19
      hiver-modules/hiver-mall/src/main/resources/mapper/MallRefundRecordMapper.xml

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallDeliveryOrderController.java

@ -105,8 +105,8 @@ public class MallDeliveryOrderController {
@PostMapping("/countOrderByStatus") @PostMapping("/countOrderByStatus")
@ApiOperation(value = "查询当前配送员指派单和已接单数量") @ApiOperation(value = "查询当前配送员指派单和已接单数量")
public Result<List<Map<Integer, Integer>>> countOrderByStatus(@RequestParam String workerId) { public Result<List<Map<String, Object>>> countOrderByStatus(@RequestParam String workerId) {
return new ResultUtil<List<Map<Integer, Integer>>>().setData(mallDeliveryOrderService.countOrdersByStatus(workerId)); return new ResultUtil<List<Map<String, Object>>>().setData(mallDeliveryOrderService.countOrdersByStatus(workerId));
} }
@PostMapping("/pagebyworker") @PostMapping("/pagebyworker")

22
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallRefundRecordController.java

@ -3,7 +3,9 @@ package cc.hiver.mall.controller;
import cc.hiver.core.common.utils.ResultUtil; import cc.hiver.core.common.utils.ResultUtil;
import cc.hiver.core.common.vo.Result; import cc.hiver.core.common.vo.Result;
import cc.hiver.mall.entity.MallRefundRecord; import cc.hiver.mall.entity.MallRefundRecord;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery;
import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.service.mybatis.MallRefundRecordService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -50,4 +52,24 @@ public class MallRefundRecordController {
} }
} }
@PostMapping("/page")
@ApiOperation(value = "分页查询退款售后列表")
public Result<IPage<MallRefundRecord>> page(@RequestBody MallRefundRecordPageQuery q) {
return new ResultUtil<IPage<MallRefundRecord>>().setData(mallRefundRecordService.selectPageVO(q));
}
/**
* 商家配送员处理退款/售后
*/
@PostMapping("/allowOrReject")
@ApiOperation(value = "处理退款/售后")
public Result allowOrReject(@RequestBody MallRefundRecord mallRefundRecord) {
try {
mallRefundRecordService.updateStatus(mallRefundRecord);
return ResultUtil.success("处理成功");
} catch (Exception e) {
log.error("处理失败: {}", e.getMessage(), e);
return ResultUtil.error(e.getMessage());
}
}
} }

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallDeliveryOrderMapper.java

@ -33,6 +33,6 @@ public interface MallDeliveryOrderMapper extends BaseMapper<MallDeliveryOrder> {
List<Map<Integer, Integer>> countOrdersByType(@Param("regionId") String regionId); List<Map<Integer, Integer>> countOrdersByType(@Param("regionId") String regionId);
List<Map<Integer, Integer>> countOrdersByStatus(@Param("workerId") String workerId); List<Map<String, Object>> countOrdersByStatus(@Param("workerId") String workerId);
} }

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallRefundRecordMapper.java

@ -1,7 +1,10 @@
package cc.hiver.mall.dao.mapper; package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.MallRefundRecord; import cc.hiver.mall.entity.MallRefundRecord;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
/** /**
@ -9,4 +12,5 @@ import org.springframework.stereotype.Repository;
*/ */
@Repository @Repository
public interface MallRefundRecordMapper extends BaseMapper<MallRefundRecord> { public interface MallRefundRecordMapper extends BaseMapper<MallRefundRecord> {
IPage<MallRefundRecord> selectPageVO(IPage<?> page, @Param("q") MallRefundRecordPageQuery q);
} }

14
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallRefundRecord.java

@ -21,7 +21,7 @@ import java.util.List;
@Entity @Entity
@Table(name = "mall_refund_record") @Table(name = "mall_refund_record")
@TableName("mall_refund_record") @TableName("mall_refund_record")
@ApiModel(value = "退款记录表") @ApiModel(value = "退款或售后记录表")
public class MallRefundRecord implements Serializable { public class MallRefundRecord implements Serializable {
@Id @Id
@TableId @TableId
@ -38,7 +38,7 @@ public class MallRefundRecord implements Serializable {
private String reason; private String reason;
@ApiModelProperty(value = "退款图片") @ApiModelProperty(value = "退款图片")
private String pictures; private String pictures;
@ApiModelProperty(value = "退款状态 0:退款处理中 1:退款成功 2:商家拒绝退款 退款失败 3售后中 4已售后 5 拒绝售后 6 商家拒绝售后 7 配送员拒绝售后") @ApiModelProperty(value = "退款状态 0:退款处理中 1:同意退款 2:(商家或者配送员)拒绝退款 退款失败 3售后中 4同意售后 5 (商家或者配送员)拒绝售后")
private Integer status; private Integer status;
@ApiModelProperty(value = "退款类型 1 退商品 2退配送费 3 全额退款") @ApiModelProperty(value = "退款类型 1 退商品 2退配送费 3 全额退款")
private Integer refundType; private Integer refundType;
@ -53,6 +53,16 @@ public class MallRefundRecord implements Serializable {
@TableField(exist = false) @TableField(exist = false)
private List<MallReturnOrderGoods> items; private List<MallReturnOrderGoods> items;
@ApiModelProperty("售后订单详情")
@Transient
@TableField(exist = false)
private MallOrder mallOrder;
@ApiModelProperty("订单是否配送")
@Transient
@TableField(exist = false)
private Integer deliveryType;
@ApiModelProperty("店铺id") @ApiModelProperty("店铺id")
@Transient @Transient
@TableField(exist = false) @TableField(exist = false)

25
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallRefundRecordPageQuery.java

@ -0,0 +1,25 @@
package cc.hiver.mall.pojo.query;
import cc.hiver.core.base.HiverBasePageQuery;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 退款售后分页查询对象
*/
@ApiModel("退款售后分页查询对象")
@Data
public class MallRefundRecordPageQuery extends HiverBasePageQuery {
@ApiModelProperty("退款或售后状态 0:退款处理中 1:退款成功 2:(商家或者配送员)拒绝退款 退款失败 3售后中 4已售后成功 5 (商家或者配送员)拒绝售后")
private Integer status;
@ApiModelProperty(value = "关联的商家或者配送员ID 如果 refundType = 3 && refundTypeStatus == 3 MallRefundRecord存两条记录")
private String linkId;
@ApiModelProperty("多种状态查")
private List<Integer> statusList;
}

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallDeliveryOrderService.java

@ -56,5 +56,5 @@ public interface MallDeliveryOrderService extends IService<MallDeliveryOrder> {
List<Map<Integer, Integer>> countOrdersByType(String regionId); List<Map<Integer, Integer>> countOrdersByType(String regionId);
List<Map<Integer, Integer>> countOrdersByStatus(String workerId); List<Map<String, Object>> countOrdersByStatus(String workerId);
} }

6
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallRefundRecordService.java

@ -1,6 +1,8 @@
package cc.hiver.mall.service.mybatis; package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.MallRefundRecord; import cc.hiver.mall.entity.MallRefundRecord;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List; import java.util.List;
@ -12,5 +14,9 @@ public interface MallRefundRecordService extends IService<MallRefundRecord> {
void create(MallRefundRecord mallRefundRecord); void create(MallRefundRecord mallRefundRecord);
void updateStatus(MallRefundRecord mallRefundRecord);
List<MallRefundRecord> selectByLinkId(MallRefundRecord mallRefundRecord); List<MallRefundRecord> selectByLinkId(MallRefundRecord mallRefundRecord);
IPage<MallRefundRecord> selectPageVO(MallRefundRecordPageQuery q);
} }

153
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java

@ -3,13 +3,12 @@ package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.mall.dao.mapper.MallDeliveryOrderMapper; import cc.hiver.mall.dao.mapper.MallDeliveryOrderMapper;
import cc.hiver.mall.dao.mapper.MallOrderGoodsMapper; import cc.hiver.mall.dao.mapper.MallOrderGoodsMapper;
import cc.hiver.mall.dao.mapper.MallOrderGroupMapper; import cc.hiver.mall.dao.mapper.MallOrderGroupMapper;
import cc.hiver.mall.entity.MallDeliveryOrder; import cc.hiver.mall.entity.*;
import cc.hiver.mall.entity.MallOrder;
import cc.hiver.mall.entity.MallOrderGoods;
import cc.hiver.mall.entity.MallOrderGroup;
import cc.hiver.mall.pojo.query.MallDeliveryOrderPageQuery; import cc.hiver.mall.pojo.query.MallDeliveryOrderPageQuery;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery;
import cc.hiver.mall.service.mybatis.MallDeliveryOrderService; import cc.hiver.mall.service.mybatis.MallDeliveryOrderService;
import cc.hiver.mall.service.mybatis.MallOrderService; import cc.hiver.mall.service.mybatis.MallOrderService;
import cc.hiver.mall.service.mybatis.MallRefundRecordService;
import cc.hiver.mall.utils.MerchantOrderSeqUtil; import cc.hiver.mall.utils.MerchantOrderSeqUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@ -23,10 +22,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Map;
/** /**
* 配送订单 Service 实现 * 配送订单 Service 实现
@ -48,6 +44,8 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
private static final int ORDER_STATUS_DELIVERING = 4; // 配送中 private static final int ORDER_STATUS_DELIVERING = 4; // 配送中
private static final int ORDER_STATUS_DONE = 5; // 已完成 private static final int ORDER_STATUS_DONE = 5; // 已完成
private static final int ORDER_STATUS_RETURN = 7; // 已完成 private static final int ORDER_STATUS_RETURN = 7; // 已完成
private static final int PAGE_SIZE = 100;
private static final int PAGE_SIZE_TWENTY = 20;
@Autowired @Autowired
@Lazy @Lazy
@ -59,12 +57,16 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
@Autowired @Autowired
private MallOrderGoodsMapper mallOrderGoodsMapper; private MallOrderGoodsMapper mallOrderGoodsMapper;
@Autowired
private MallRefundRecordService mallRefundRecordService;
@Autowired @Autowired
private MerchantOrderSeqUtil merchantOrderSeqUtil; private MerchantOrderSeqUtil merchantOrderSeqUtil;
@Override @Override
public IPage<MallDeliveryOrder> pageDelivery(MallDeliveryOrderPageQuery q) { public IPage<MallDeliveryOrder> pageDelivery(MallDeliveryOrderPageQuery q) {
if (Boolean.TRUE.equals(q.getHallOnly())) { if (Boolean.TRUE.equals(q.getHallOnly())) {
q.setPageSize(20); q.setPageSize(PAGE_SIZE_TWENTY);
} }
IPage<MallDeliveryOrder> page = new Page<>(q.getPageNum(), q.getPageSize()); IPage<MallDeliveryOrder> page = new Page<>(q.getPageNum(), q.getPageSize());
page = this.baseMapper.selectPageVO(page, q); page = this.baseMapper.selectPageVO(page, q);
@ -75,26 +77,8 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
page.setCurrent(actualPage); page.setCurrent(actualPage);
page = this.baseMapper.selectPageVO(page, q); page = this.baseMapper.selectPageVO(page, q);
} }
// 批量查询订单商品明细,避免 N+1 问题 // 批量查询订单商品明细,避免 N+1 问题,处理面对面拼团子订单
List<MallDeliveryOrder> records = page.getRecords(); assembleOrderGoodsForDeliveries(page.getRecords());
if (records != null && !records.isEmpty()) {
// 1. 收集所有订单ID
List<String> orderIds = records.stream()
.map(MallDeliveryOrder::getOrderId)
.collect(java.util.stream.Collectors.toList());
// 2. 一次 IN 查询所有商品明细
List<MallOrderGoods> allGoods = mallOrderGoodsMapper.selectByOrderIds(orderIds);
// 3. 按 orderId 分组
java.util.Map<String, List<MallOrderGoods>> goodsMap = allGoods.stream()
.collect(java.util.stream.Collectors.groupingBy(MallOrderGoods::getOrderId));
// 4. 组装到每个 VO
for (MallDeliveryOrder vo : records) {
vo.setGoodsList(goodsMap.getOrDefault(vo.getOrderId(), java.util.Collections.emptyList()));
}
}
return page; return page;
} }
@ -103,26 +87,8 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
public IPage<MallDeliveryOrder> pageDeliveryByStatus(MallDeliveryOrderPageQuery q) { public IPage<MallDeliveryOrder> pageDeliveryByStatus(MallDeliveryOrderPageQuery q) {
IPage<MallDeliveryOrder> page = new Page<>(q.getPageNum(), q.getPageSize()); IPage<MallDeliveryOrder> page = new Page<>(q.getPageNum(), q.getPageSize());
page = this.baseMapper.selectPageVOByStatus(page,q); page = this.baseMapper.selectPageVOByStatus(page,q);
// 批量查询订单商品明细,避免 N+1 问题 // 批量查询订单商品明细,避免 N+1 问题,处理面对面拼团子订单
List<MallDeliveryOrder> records = page.getRecords(); assembleOrderGoodsForDeliveries(page.getRecords());
if (records != null && !records.isEmpty()) {
// 1. 收集所有订单ID
List<String> orderIds = records.stream()
.map(MallDeliveryOrder::getOrderId)
.collect(java.util.stream.Collectors.toList());
// 2. 一次 IN 查询所有商品明细
List<MallOrderGoods> allGoods = mallOrderGoodsMapper.selectByOrderIds(orderIds);
// 3. 按 orderId 分组
java.util.Map<String, List<MallOrderGoods>> goodsMap = allGoods.stream()
.collect(java.util.stream.Collectors.groupingBy(MallOrderGoods::getOrderId));
// 4. 组装到每个
for (MallDeliveryOrder vo : records) {
vo.setGoodsList(goodsMap.getOrDefault(vo.getOrderId(), java.util.Collections.emptyList()));
}
}
return page; return page;
} }
@ -305,6 +271,74 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
return delivery; return delivery;
} }
private void assembleOrderGoodsForDeliveries(List<MallDeliveryOrder> records) {
if (records == null || records.isEmpty()) {
return;
}
// 1. 收集所有基本的订单ID,使用 Set 防止重复查询
java.util.Set<String> allOrderIdsToQuery = new java.util.HashSet<>();
for (MallDeliveryOrder record : records) {
if (StringUtils.isNotBlank(record.getOrderId())) {
allOrderIdsToQuery.add(record.getOrderId());
}
}
// 2. 收集所有包含 groupId 的记录(针对面对面拼团情况)
List<String> groupIds = records.stream()
.map(MallDeliveryOrder::getGroupId)
.filter(StringUtils::isNotBlank)
.distinct()
.collect(java.util.stream.Collectors.toList());
java.util.Map<String, MallOrderGroup> groupMap = new java.util.HashMap<>();
if (!groupIds.isEmpty()) {
List<MallOrderGroup> groups = mallOrderGroupMapper.selectBatchIds(groupIds);
if (groups != null) {
for (MallOrderGroup group : groups) {
groupMap.put(group.getId(), group);
// 仅当是面对面拼团时,统一获取该团下的所有商品明细
if (group.getIsFace() != null && group.getIsFace() == 1 && StringUtils.isNotBlank(group.getGroupOrderIds())) {
allOrderIdsToQuery.addAll(Arrays.asList(group.getGroupOrderIds().split(",")));
}
}
}
}
if (allOrderIdsToQuery.isEmpty()) {
return;
}
// 3. 一次 IN 查询所有商品明细
List<MallOrderGoods> allGoods = mallOrderGoodsMapper.selectByOrderIds(new java.util.ArrayList<>(allOrderIdsToQuery));
// 4. 按 orderId 分组
java.util.Map<String, List<MallOrderGoods>> goodsMap = allGoods.stream()
.collect(java.util.stream.Collectors.groupingBy(MallOrderGoods::getOrderId));
// 5. 将商品明细组装到每个配送单 (MallDeliveryOrder)
for (MallDeliveryOrder vo : records) {
java.util.Set<String> targetOrderIds = new java.util.HashSet<>();
if (StringUtils.isNotBlank(vo.getOrderId())) {
targetOrderIds.add(vo.getOrderId());
}
if (StringUtils.isNotBlank(vo.getGroupId()) && groupMap.containsKey(vo.getGroupId())) {
MallOrderGroup group = groupMap.get(vo.getGroupId());
if (group.getIsFace() != null && group.getIsFace() == 1 && StringUtils.isNotBlank(group.getGroupOrderIds())) {
targetOrderIds.addAll(Arrays.asList(group.getGroupOrderIds().split(",")));
}
}
List<MallOrderGoods> voGoodsList = new java.util.ArrayList<>();
for (String oid : targetOrderIds) {
if (StringUtils.isNotBlank(oid)) {
voGoodsList.addAll(goodsMap.getOrDefault(oid, java.util.Collections.emptyList()));
}
}
vo.setGoodsList(voGoodsList);
}
}
@Override @Override
public long countWaitGrabOrders(int deliveryType) { public long countWaitGrabOrders(int deliveryType) {
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MallDeliveryOrder> query = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>(); com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<MallDeliveryOrder> query = new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<>();
@ -320,7 +354,24 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
} }
@Override @Override
public List<Map<Integer, Integer>> countOrdersByStatus(String workerId) { public List<Map<String, Object>> countOrdersByStatus(String workerId) {
return this.baseMapper.countOrdersByStatus(workerId); List<Map<String, Object>> returnList = this.baseMapper.countOrdersByStatus(workerId);
MallRefundRecordPageQuery q = new MallRefundRecordPageQuery();
q.setPageSize(PAGE_SIZE);
IPage<MallRefundRecord> page = new Page<>(q.getPageNum(), q.getPageSize());
q.setLinkId(workerId);
List<Integer> statusList = new ArrayList<>();
//查待售后待退款数
statusList.add(STATUS_WAIT_ACCEPT);
statusList.add(STATUS_DONE);
q.setStatusList(statusList);
IPage<MallRefundRecord> result = mallRefundRecordService.selectPageVO(q);
if(result != null){
Map<String, Object> newRecord = new HashMap<>();
newRecord.put("status", STATUS_DONE); // 状态
newRecord.put("orderCount", result.getRecords().size());
returnList.add(newRecord);
}
return returnList;
} }
} }

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderGroupServiceImpl.java

@ -234,7 +234,7 @@ public class MallOrderGroupServiceImpl extends ServiceImpl<MallOrderGroupMapper,
refund.setStatus(0); refund.setStatus(0);
refund.setCreateTime(new Date()); refund.setCreateTime(new Date());
mallRefundRecordMapper.insert(refund); mallRefundRecordMapper.insert(refund);
wechatPayUtil.refund(order.getId(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue()); wechatPayUtil.refund(order.getId(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue(),order.getTotalAmount().multiply(new BigDecimal(100)).longValue());
List<MallOrderGoods> goodsList = mallOrderGoodsMapper.selectByOrderId(order.getId()); List<MallOrderGoods> goodsList = mallOrderGoodsMapper.selectByOrderId(order.getId());
if (goodsList == null || goodsList.isEmpty()) return; if (goodsList == null || goodsList.isEmpty()) return;
List<MallReturnOrderGoods> returnList = goodsList.stream() List<MallReturnOrderGoods> returnList = goodsList.stream()

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java

@ -1282,7 +1282,7 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
record.setRefundType(3); record.setRefundType(3);
record.setRefundTypeStatus(4); record.setRefundTypeStatus(4);
mallRefundRecordMapper.insert(record); mallRefundRecordMapper.insert(record);
wechatPayUtil.refund(order.getId(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue()); wechatPayUtil.refund(order.getId(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue());
List<MallOrderGoods> goodsList = mallOrderGoodsMapper.selectByOrderId(order.getId()); List<MallOrderGoods> goodsList = mallOrderGoodsMapper.selectByOrderId(order.getId());
if (goodsList == null || goodsList.isEmpty()) return; if (goodsList == null || goodsList.isEmpty()) return;
List<MallReturnOrderGoods> returnList = goodsList.stream() List<MallReturnOrderGoods> returnList = goodsList.stream()

228
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java

@ -1,18 +1,27 @@
package cc.hiver.mall.serviceimpl.mybatis; package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.core.common.utils.SnowFlakeUtil; import cc.hiver.core.common.utils.SnowFlakeUtil;
import cc.hiver.mall.dao.mapper.MallDeliveryOrderMapper;
import cc.hiver.mall.dao.mapper.MallOrderMapper;
import cc.hiver.mall.dao.mapper.MallRefundRecordMapper; import cc.hiver.mall.dao.mapper.MallRefundRecordMapper;
import cc.hiver.mall.dao.mapper.MallReturnOrderGoodsMapper; import cc.hiver.mall.dao.mapper.MallReturnOrderGoodsMapper;
import cc.hiver.mall.entity.MallDeliveryOrder;
import cc.hiver.mall.entity.MallOrder; import cc.hiver.mall.entity.MallOrder;
import cc.hiver.mall.entity.MallRefundRecord; import cc.hiver.mall.entity.MallRefundRecord;
import cc.hiver.mall.entity.MallReturnOrderGoods; import cc.hiver.mall.entity.MallReturnOrderGoods;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery;
import cc.hiver.mall.service.mybatis.MallOrderService; import cc.hiver.mall.service.mybatis.MallOrderService;
import cc.hiver.mall.service.mybatis.MallRefundRecordService; import cc.hiver.mall.service.mybatis.MallRefundRecordService;
import cc.hiver.mall.utils.WechatPayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -23,6 +32,21 @@ import java.util.List;
public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMapper, MallRefundRecord> public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMapper, MallRefundRecord>
implements MallRefundRecordService { implements MallRefundRecordService {
// 订单状态常量数据库存储为 "01",用数字10代替
private static final int STATUS_WAIT_SHOP = 1;
private static final int STATUS_WAIT_PICKUP = 3;
private static final int STATUS_DELIVERING = 4;
private static final int STATUS_END = 5;
private static final int STATUS_REFUNDED = 8;
private static final int STATUS_LAST_REFUNDED = 12;
// 配送方式常量// 外卖
private static final int DELIVERY_TYPE_SELF = 2;// 外
private static final int DELIVERY_TYPE_PEISONG = 1;
private static final int PAGESIZE = 10;
private static final int PAGENUM = 1;
@Autowired @Autowired
private MallRefundRecordMapper mallRefundRecordMapper; private MallRefundRecordMapper mallRefundRecordMapper;
@ -32,6 +56,18 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
@Autowired @Autowired
private MallOrderService mallOrderService; private MallOrderService mallOrderService;
@Autowired
private MallOrderMapper mallOrderMapper;
@Autowired
private WechatPayUtil wechatPayUtil;
@Autowired
private MallDeliveryOrderMapper mallDeliveryOrderMapper;
@Autowired
private MallRefundRecordService mallRefundRecordService;
@Override @Override
public void create(MallRefundRecord mallRefundRecord) { public void create(MallRefundRecord mallRefundRecord) {
//更新订单为 待售后 //更新订单为 待售后
@ -79,6 +115,161 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
} }
} }
@Override
public void updateStatus(MallRefundRecord mallRefundRecord) {
LambdaUpdateWrapper<MallRefundRecord> uw = new LambdaUpdateWrapper<>();
uw.eq(MallRefundRecord::getId, mallRefundRecord.getId())
.set(MallRefundRecord::getSuccessTime, new Date())
.set(MallRefundRecord::getStatus, mallRefundRecord.getStatus());
this.update(null, uw);
Boolean isTuiKuan = true;
if(mallRefundRecord.getStatus() > 3){
//处理售后
isTuiKuan = false;
}
//更新订单status、 配送单isReturn
if(mallRefundRecord.getRefundTypeStatus() != null && mallRefundRecord.getRefundTypeStatus() == 3){
//商家和配送员都有原因,需要判断另外角色处理了没再判断是否更新订单的状态
IPage<MallRefundRecord> page = new Page<>(PAGENUM, PAGESIZE);
MallRefundRecordPageQuery q = new MallRefundRecordPageQuery();
q.setOrder(mallRefundRecord.getOrderId());
IPage<MallRefundRecord> result = this.baseMapper.selectPageVO(page, q);
boolean hasEnd = result.getRecords().stream()
.anyMatch(item -> item.getStatus() == 3 || item.getStatus() == 0);
boolean hasReject = result.getRecords().stream()
.anyMatch(item -> item.getStatus() == 2 || item.getStatus() == 5);
if(isTuiKuan){
//都处理了
if(!hasEnd){
//都同意退款
if(!hasReject){
//同意退款
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED);
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){
//更新配送单
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();
duw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId())
.set(MallDeliveryOrder::getStatus, 4);
mallDeliveryOrderMapper.update(null, duw);
}
BigDecimal totalRefund = result.getRecords().stream()
.map(item -> item.getRefundAmount()) // 提取 BigDecimal 金额
.reduce(BigDecimal.ZERO, BigDecimal::add);
wechatPayUtil.refund(mallRefundRecord.getOrderId(), totalRefund.multiply(new BigDecimal(100)).longValue(), totalRefund.multiply(new BigDecimal(100)).longValue());
}else{
//拒绝退款
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
//如果是自取订单,则恢复待消费状态
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_SELF){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP);
}else{
MallDeliveryOrder delivery = findDeliveryByOrderId(mallRefundRecord.getOrderId());
if(delivery == null){
//去查团长的配送单
}
if(delivery.getStatus() == STATUS_WAIT_SHOP){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP);
}else if(delivery.getStatus() == DELIVERY_TYPE_SELF){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_DELIVERING);
}
//更新配送单isReturn
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();
duw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId())
.set(MallDeliveryOrder::getIsReturn, 0);
mallDeliveryOrderMapper.update(null, duw);
}
}
}
}else{
//售后
if(mallRefundRecord.getStatus() == 4){
//同意售后
MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
wechatPayUtil.refund(mallRefundRecord.getOrderId(),order.getTotalAmount().multiply(new BigDecimal(100)).longValue(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue());
}
//都处理了
if(!hasEnd){
//更新订单状态已售后
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_LAST_REFUNDED);
}
}
}else{
if(isTuiKuan){
//拒绝退款
if(mallRefundRecord.getStatus() == 2){
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
//如果是自取订单,则恢复待消费状态
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_SELF){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP);
}else{
MallDeliveryOrder delivery = findDeliveryByOrderId(mallRefundRecord.getOrderId());
if(delivery == null){
//去查团长的配送单
}
if(delivery.getStatus() == STATUS_WAIT_SHOP){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_WAIT_PICKUP);
}else if(delivery.getStatus() == DELIVERY_TYPE_SELF){
updateOrderStatusAndReturn(mallRefundRecord.getOrderId(), STATUS_DELIVERING);
}
//更新配送单isReturn
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();
duw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId())
.set(MallDeliveryOrder::getIsReturn, 0);
mallDeliveryOrderMapper.update(null, duw);
}
}else{
//同意退款
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED);
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){
//更新配送单
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();
duw.eq(MallDeliveryOrder::getOrderId, mallRefundRecord.getOrderId())
.set(MallDeliveryOrder::getStatus, 4);
mallDeliveryOrderMapper.update(null, duw);
}
wechatPayUtil.refund(mallRefundRecord.getOrderId(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue());
}
}else{
//售后
if(mallRefundRecord.getStatus() == 4){
//同意售后
MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_LAST_REFUNDED);
wechatPayUtil.refund(mallRefundRecord.getOrderId(), order.getTotalAmount().multiply(new BigDecimal(100)).longValue(), mallRefundRecord.getRefundAmount().multiply(new BigDecimal(100)).longValue());
}else{
//订单还是变成已完成状态
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_END);
}
}
}
}
/**
* 更新订单状态
*/
private void updateOrderStatus(String orderId, int status) {
LambdaUpdateWrapper<MallOrder> uw = new LambdaUpdateWrapper<>();
uw.eq(MallOrder::getId, orderId).set(MallOrder::getStatus, status);
mallOrderMapper.update(null, uw);
}
private void updateOrderStatusAndReturn(String orderId, int status) {
LambdaUpdateWrapper<MallOrder> uw = new LambdaUpdateWrapper<>();
uw.eq(MallOrder::getId, orderId).set(MallOrder::getStatus, status);
mallOrderMapper.update(null, uw);
}
/**
* 根据订单ID查找配送单
*/
private MallDeliveryOrder findDeliveryByOrderId(String orderId) {
LambdaQueryWrapper<MallDeliveryOrder> dq = new LambdaQueryWrapper<>();
dq.eq(MallDeliveryOrder::getOrderId, orderId).last("LIMIT 1");
return mallDeliveryOrderMapper.selectOne(dq);
}
@Override @Override
public List<MallRefundRecord> selectByLinkId(MallRefundRecord mallRefundRecord) { public List<MallRefundRecord> selectByLinkId(MallRefundRecord mallRefundRecord) {
LambdaUpdateWrapper<MallRefundRecord> uw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallRefundRecord> uw = new LambdaUpdateWrapper<>();
@ -86,4 +277,41 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
List<MallRefundRecord> mallRefundRecords = this.list(uw); List<MallRefundRecord> mallRefundRecords = this.list(uw);
return mallRefundRecords; return mallRefundRecords;
} }
@Override
public IPage<MallRefundRecord> selectPageVO(MallRefundRecordPageQuery q) {
IPage<MallRefundRecord> page = new Page<>(q.getPageNum(), q.getPageSize());
IPage<MallRefundRecord> result = this.baseMapper.selectPageVO(page, q);
// 批量查询售后商品明细,避免 N+1 问题
List<MallRefundRecord> records = result.getRecords();
if (records != null && !records.isEmpty()) {
// 1. 收集所有订单ID
List<String> orderIds = records.stream()
.map(MallRefundRecord::getOrderId)
.collect(java.util.stream.Collectors.toList());
// 2. 一次 IN 查询所有商品明细
LambdaQueryWrapper<MallReturnOrderGoods> qw = new LambdaQueryWrapper<>();
qw.in(MallReturnOrderGoods::getOrderId, orderIds);
List<MallReturnOrderGoods> allGoods = mallReturnOrderGoodsMapper.selectList(qw);
// 3. 按 orderId 分组
java.util.Map<String, List<MallReturnOrderGoods>> goodsMap = allGoods.stream()
.collect(java.util.stream.Collectors.groupingBy(MallReturnOrderGoods::getOrderId));
// 4. 批量查询订单商品明细,避免 N+1 问题
LambdaQueryWrapper<MallOrder> qwOrder = new LambdaQueryWrapper<>();
qwOrder.in(MallOrder::getId, orderIds);
List<MallOrder> allOrders = mallOrderMapper.selectList(qwOrder);
java.util.Map<String, List<MallOrder>> orderMap = allOrders.stream()
.collect(java.util.stream.Collectors.groupingBy(MallOrder::getId));
// 4. 组装到每个 VO
for (MallRefundRecord vo : records) {
vo.setItems(goodsMap.getOrDefault(vo.getOrderId(), java.util.Collections.emptyList()));
vo.setMallOrder(orderMap.getOrDefault(vo.getOrderId(), new java.util.ArrayList<>()).get(0));
}
}
return result;
}
} }

4
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/utils/WechatPayUtil.java

@ -27,7 +27,7 @@ public class WechatPayUtil {
private final OkHttpClient httpClient = new OkHttpClient(); private final OkHttpClient httpClient = new OkHttpClient();
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
public Boolean refund(String orderId,long totalFee) { public Boolean refund(String orderId,long totalFee,long refundFee) {
try { try {
// 2. 构建退款请求参数 // 2. 构建退款请求参数
// 原支付交易号(与下单时一致,带 ORDER_ 前缀) // 原支付交易号(与下单时一致,带 ORDER_ 前缀)
@ -44,7 +44,7 @@ public class WechatPayUtil {
reqBody.put("reason", reason); reqBody.put("reason", reason);
Map<String, Object> amountMap = new HashMap<>(); Map<String, Object> amountMap = new HashMap<>();
amountMap.put("refund", totalFee); amountMap.put("refund", refundFee);
amountMap.put("total", totalFee); amountMap.put("total", totalFee);
amountMap.put("currency", "CNY"); amountMap.put("currency", "CNY");
reqBody.put("amount", amountMap); reqBody.put("amount", amountMap);

19
hiver-modules/hiver-mall/src/main/resources/mapper/MallRefundRecordMapper.xml

@ -18,4 +18,23 @@
<result column="link_id" property="linkId"/> <result column="link_id" property="linkId"/>
</resultMap> </resultMap>
<select id="selectPageVO" resultMap="refundMap">
select * from mall_refund_record
<where>
<if test="q.linkId != null and q.linkId != ''">
AND link_id = #{q.linkId}
</if>
<if test="q.status != null">
AND status = #{q.status}
</if>
<if test='q.statusList !=null '>
and status in
<foreach item="item" index="index" collection="q.statusList" open="(" close=")" separator=",">
#{item}
</foreach>
</if>
</where>
ORDER BY create_time ASC
</select>
</mapper> </mapper>

Loading…
Cancel
Save