Browse Source

对接拼团数据1

master
wangfukang 2 days ago
parent
commit
3d255eff24
  1. 2
      hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java
  2. 22
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallCouponController.java
  3. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java
  4. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java
  5. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallCouponMapper.java
  6. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallUserCouponMapper.java
  7. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallCoupon.java
  8. 2
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallDeliveryOrder.java
  9. 65
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallCouponQuery.java
  10. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java
  11. 3
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/MallOrderVO.java
  12. 5
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java
  13. 21
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallDeliveryOrderServiceImpl.java
  14. 7
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderGroupServiceImpl.java
  15. 105
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallOrderServiceImpl.java
  16. 8
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallRefundRecordServiceImpl.java
  17. 37
      hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java
  18. 68
      hiver-modules/hiver-mall/src/main/resources/mapper/MallCouponMapper.xml
  19. 14
      hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml

2
hiver-modules/hiver-base/src/main/java/cc/hiver/base/controller/manage/AuthController.java

@ -128,7 +128,7 @@ public class AuthController {
@SystemLog(description = "账号登录", type = LogType.LOGIN) @SystemLog(description = "账号登录", type = LogType.LOGIN)
@ApiOperation("账号/手机/邮箱登录") @ApiOperation("账号/手机/邮箱登录")
@Transactional @Transactional
public Result login(@RequestParam String username,@RequestParam String clientId, public Result login(@RequestParam String username,@RequestParam(required = false) String clientId,
@RequestParam String password, @RequestParam String password,
@RequestParam(required = false) String type, @RequestParam(required = false) String type,
@RequestParam(required = false) Boolean saveLogin) { @RequestParam(required = false) Boolean saveLogin) {

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

@ -4,8 +4,10 @@ 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.MallCoupon; import cc.hiver.mall.entity.MallCoupon;
import cc.hiver.mall.entity.MallUserCoupon; import cc.hiver.mall.entity.MallUserCoupon;
import cc.hiver.mall.pojo.query.MallCouponQuery;
import cc.hiver.mall.service.mybatis.MallCouponService; import cc.hiver.mall.service.mybatis.MallCouponService;
import cc.hiver.mall.service.mybatis.MallUserCouponService; import cc.hiver.mall.service.mybatis.MallUserCouponService;
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 org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -32,6 +34,13 @@ public class MallCouponController {
return ResultUtil.success("发行成功"); return ResultUtil.success("发行成功");
} }
@PostMapping("/update")
@ApiOperation(value = "修改优惠券")
public Result<Object> update(@RequestBody MallCoupon coupon) {
mallCouponService.saveOrUpdate(coupon);
return ResultUtil.success("修改成功");
}
@PostMapping("/receive") @PostMapping("/receive")
@ApiOperation(value = "用户领取优惠券") @ApiOperation(value = "用户领取优惠券")
public Result<Object> receiveCoupon(@RequestParam String userId, @RequestParam String couponId) { public Result<Object> receiveCoupon(@RequestParam String userId, @RequestParam String couponId) {
@ -39,6 +48,13 @@ public class MallCouponController {
return ResultUtil.success("领取成功"); return ResultUtil.success("领取成功");
} }
@PostMapping("/send")
@ApiOperation(value = "平台发放优惠券")
public Result<Object> send(@RequestParam String userPhones, @RequestParam Integer type,@RequestParam String couponId) {
mallUserCouponService.send(userPhones, type,couponId);
return ResultUtil.success("发放成功");
}
@GetMapping("/available") @GetMapping("/available")
@ApiOperation(value = "获取可用优惠券列表(下单时调用)") @ApiOperation(value = "获取可用优惠券列表(下单时调用)")
public Result<List<MallUserCoupon>> getAvailableCoupons( public Result<List<MallUserCoupon>> getAvailableCoupons(
@ -49,4 +65,10 @@ public class MallCouponController {
@RequestParam(required = true) String regionId) { @RequestParam(required = true) String regionId) {
return new ResultUtil<List<MallUserCoupon>>().setData(mallUserCouponService.getAvailableCoupons(userId, applyScene, amount, merchantId, regionId)); return new ResultUtil<List<MallUserCoupon>>().setData(mallUserCouponService.getAvailableCoupons(userId, applyScene, amount, merchantId, regionId));
} }
@PostMapping("/list")
@ApiOperation(value = "获取优惠券列表")
public Result<IPage<MallCoupon>> list(MallCouponQuery query) {
return new ResultUtil<IPage<MallCoupon>>().setData(mallUserCouponService.selectPageVO(query));
}
} }

5
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/MallOrderController.java

@ -33,6 +33,7 @@ public class MallOrderController {
@Autowired @Autowired
private MallOrderGroupService mallOrderGroupService; private MallOrderGroupService mallOrderGroupService;
/** /**
* 下单普通购买 / 发起拼团 / 参团 * 下单普通购买 / 发起拼团 / 参团
*/ */
@ -187,10 +188,10 @@ public class MallOrderController {
} }
/** /**
* 用户确认完成 * 自取订单完成
*/ */
@PostMapping("/complete") @PostMapping("/complete")
@ApiOperation(value = "用户确认完成", notes = "外卖送达或自取后,用户手动点击确认完成") @ApiOperation(value = "自取订单完成")
public Result completeOrder(@RequestParam String orderId) { public Result completeOrder(@RequestParam String orderId) {
try { try {
mallOrderService.completeOrder(orderId); mallOrderService.completeOrder(orderId);

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/controller/ShopController.java

@ -164,6 +164,9 @@ public class ShopController {
shop.setRegion(""); shop.setRegion("");
shop.setRegionId(null); shop.setRegionId(null);
} }
if(shop.getSaleCount() == null){
shop.setSaleCount(0);
}
shopService.update(shop); shopService.update(shop);

5
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/dao/mapper/MallCouponMapper.java

@ -1,9 +1,14 @@
package cc.hiver.mall.dao.mapper; package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.MallCoupon; import cc.hiver.mall.entity.MallCoupon;
import cc.hiver.mall.pojo.query.MallCouponQuery;
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.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@Repository
public interface MallCouponMapper extends BaseMapper<MallCoupon> { public interface MallCouponMapper extends BaseMapper<MallCoupon> {
int deductStock(@Param("id") String id); int deductStock(@Param("id") String id);
IPage<MallCoupon> selectPageVO(IPage<?> page, @Param("q") MallCouponQuery q);
} }

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

@ -2,6 +2,8 @@ package cc.hiver.mall.dao.mapper;
import cc.hiver.mall.entity.MallUserCoupon; import cc.hiver.mall.entity.MallUserCoupon;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;
@Repository
public interface MallUserCouponMapper extends BaseMapper<MallUserCoupon> { public interface MallUserCouponMapper extends BaseMapper<MallUserCoupon> {
} }

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallCoupon.java

@ -23,7 +23,7 @@ public class MallCoupon extends HiverBaseEntity {
@ApiModelProperty(value = "发放方:1-平台,2-商家") @ApiModelProperty(value = "发放方:1-平台,2-商家")
private Integer issuerType; private Integer issuerType;
@ApiModelProperty(value = "发放方ID") @ApiModelProperty(value = "发放方ID 0平台 其他为店铺id")
private String issuerId; private String issuerId;
@ApiModelProperty(value = "适用场景:0-通用,1-外卖/买饭,2-快递/跑腿,3-二手物品交易") @ApiModelProperty(value = "适用场景:0-通用,1-外卖/买饭,2-快递/跑腿,3-二手物品交易")

2
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/entity/MallDeliveryOrder.java

@ -33,6 +33,8 @@ public class MallDeliveryOrder implements Serializable {
private String groupId; private String groupId;
@ApiModelProperty(value = "配送员ID") @ApiModelProperty(value = "配送员ID")
private String workerId; private String workerId;
@ApiModelProperty(value = "转单对象id")
private String newWorker;
@ApiModelProperty(value = "配送员电话") @ApiModelProperty(value = "配送员电话")
private String workerPhone; private String workerPhone;
@ApiModelProperty(value = "配送员名称") @ApiModelProperty(value = "配送员名称")

65
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallCouponQuery.java

@ -0,0 +1,65 @@
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.math.BigDecimal;
import java.util.Date;
/**
* 优惠券分页查询对象
*/
@ApiModel("优惠券分页查询对象")
@Data
public class MallCouponQuery extends HiverBasePageQuery {
@ApiModelProperty(value = "优惠券名称")
private String name;
@ApiModelProperty(value = "发放方:1-平台,2-商家")
private Integer issuerType;
@ApiModelProperty(value = "发放方ID 0平台 其他为店铺id")
private String issuerId;
@ApiModelProperty(value = "适用场景:0-通用,1-外卖/买饭,2-快递/跑腿,3-二手物品交易")
private Integer applyScene;
@ApiModelProperty(value = "优惠券类型:1-满减券,2-无门槛直减券")
private Integer type;
@ApiModelProperty(value = "使用门槛金额")
private BigDecimal minAmount;
@ApiModelProperty(value = "抵扣面额")
private BigDecimal discountAmount;
@ApiModelProperty(value = "发行总数")
private Integer totalCount;
@ApiModelProperty(value = "剩余领取数量")
private Integer remainCount;
@ApiModelProperty(value = "每人最多限领张数")
private Integer limitPerUser;
@ApiModelProperty(value = "有效期类型:1-绝对时间段有效,2-领取后相对天数有效")
private Integer validType;
@ApiModelProperty(value = "有效期开始时间")
private Date validStartTime;
@ApiModelProperty(value = "有效期结束时间")
private Date validEndTime;
@ApiModelProperty(value = "自领取之日起有效天数")
private Integer validDays;
@ApiModelProperty(value = "状态:0-已下架/停发,1-发放中")
private Integer status;
@ApiModelProperty(value = "学校id")
private String regionId;
}

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/query/MallDeliveryOrderPageQuery.java

@ -15,6 +15,9 @@ public class MallDeliveryOrderPageQuery extends HiverBasePageQuery {
@ApiModelProperty("配送员ID") @ApiModelProperty("配送员ID")
private String workerId; private String workerId;
@ApiModelProperty("转单对象id")
private String newWorker;
@ApiModelProperty("店铺ID") @ApiModelProperty("店铺ID")
private String shopId; private String shopId;

3
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/pojo/vo/MallOrderVO.java

@ -25,6 +25,9 @@ public class MallOrderVO extends MallOrder {
@ApiModelProperty("配送信息(外卖订单时返回)") @ApiModelProperty("配送信息(外卖订单时返回)")
private MallDeliveryOrder deliveryInfo; private MallDeliveryOrder deliveryInfo;
@ApiModelProperty("优惠券")
private List<MallUserCoupon> userCoupon;
@ApiModelProperty("收货地址详情(冗余展示用)") @ApiModelProperty("收货地址详情(冗余展示用)")
private String addressDetail; private String addressDetail;

5
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/service/mybatis/MallUserCouponService.java

@ -1,6 +1,9 @@
package cc.hiver.mall.service.mybatis; package cc.hiver.mall.service.mybatis;
import cc.hiver.mall.entity.MallCoupon;
import cc.hiver.mall.entity.MallUserCoupon; import cc.hiver.mall.entity.MallUserCoupon;
import cc.hiver.mall.pojo.query.MallCouponQuery;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import java.math.BigDecimal; import java.math.BigDecimal;
@ -12,4 +15,6 @@ public interface MallUserCouponService extends IService<MallUserCoupon> {
boolean lockCoupon(String userCouponId, String orderId); boolean lockCoupon(String userCouponId, String orderId);
boolean useCoupon(String orderId); boolean useCoupon(String orderId);
boolean refundCoupon(String orderId); boolean refundCoupon(String orderId);
IPage<MallCoupon> selectPageVO(MallCouponQuery q);
void send(String userPhones,Integer type,String couponId);
} }

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

@ -22,6 +22,9 @@ 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.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*; import java.util.*;
/** /**
@ -113,11 +116,19 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
} }
// 更新配送单 // 更新配送单
Date createTime = new Timestamp(System.currentTimeMillis());
// 1. 获取当前时间 (LocalDateTime)
LocalDateTime now = LocalDateTime.now();
// 2. 加40分钟
LocalDateTime futureTime = now.plusMinutes(40);
// 3. 如果需要转回 java.util.Date (为了兼容旧代码)
Date mustFinishTime = Date.from(futureTime.atZone(ZoneId.systemDefault()).toInstant());
LambdaUpdateWrapper<MallDeliveryOrder> uw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallDeliveryOrder> uw = new LambdaUpdateWrapper<>();
uw.eq(MallDeliveryOrder::getId, deliveryId) uw.eq(MallDeliveryOrder::getId, deliveryId)
.set(MallDeliveryOrder::getStatus, STATUS_WAIT_PICKUP) .set(MallDeliveryOrder::getStatus, STATUS_WAIT_PICKUP)
.set(MallDeliveryOrder::getWorkerId, workerId).set(MallDeliveryOrder::getWorkerName, workerName).set(MallDeliveryOrder::getWorkerPhone, workerPhone) .set(MallDeliveryOrder::getWorkerId, workerId).set(MallDeliveryOrder::getWorkerName, workerName).set(MallDeliveryOrder::getWorkerPhone, workerPhone)
.set(MallDeliveryOrder::getAcceptTime, new Date()); .set(MallDeliveryOrder::getAcceptTime, new Date())
.set(MallDeliveryOrder::getMustFinishTime, mustFinishTime);
MallOrder order = mallOrderService.getById(delivery.getOrderId()); MallOrder order = mallOrderService.getById(delivery.getOrderId());
String numberCode = ""; String numberCode = "";
@ -239,6 +250,12 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
LambdaUpdateWrapper<MallOrder> oqw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallOrder> oqw = new LambdaUpdateWrapper<>();
oqw.in(MallOrder::getId, orderIdList).set(MallOrder::getStatus,ORDER_STATUS_DONE); oqw.in(MallOrder::getId, orderIdList).set(MallOrder::getStatus,ORDER_STATUS_DONE);
mallOrderService.update(oqw); mallOrderService.update(oqw);
//更新优惠券已使用
LambdaUpdateWrapper<MallUserCoupon> oqwCoupon = new LambdaUpdateWrapper<>();
oqwCoupon.in(MallUserCoupon::getOrderId, orderIdList).set(MallUserCoupon::getStatus,2);
mallUserCouponService.update(oqwCoupon);
}else{ }else{
// 同步订单状态 -> 已完成 // 同步订单状态 -> 已完成
if (StringUtils.isNotBlank(delivery.getOrderId())) { if (StringUtils.isNotBlank(delivery.getOrderId())) {
@ -246,6 +263,8 @@ public class MallDeliveryOrderServiceImpl extends ServiceImpl<MallDeliveryOrderM
oUw.eq(MallOrder::getId, delivery.getOrderId()) oUw.eq(MallOrder::getId, delivery.getOrderId())
.set(MallOrder::getStatus, ORDER_STATUS_DONE); .set(MallOrder::getStatus, ORDER_STATUS_DONE);
mallOrderService.update(oUw); mallOrderService.update(oUw);
//优惠券变成已使用
mallUserCouponService.useCoupon(delivery.getOrderId());
} }
} }
} }

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

@ -6,6 +6,7 @@ import cc.hiver.mall.dao.mapper.*;
import cc.hiver.mall.entity.*; import cc.hiver.mall.entity.*;
import cc.hiver.mall.service.mybatis.MallOrderGroupService; import cc.hiver.mall.service.mybatis.MallOrderGroupService;
import cc.hiver.mall.service.mybatis.MallOrderService; import cc.hiver.mall.service.mybatis.MallOrderService;
import cc.hiver.mall.service.mybatis.MallUserCouponService;
import cc.hiver.mall.utils.MerchantOrderSeqUtil; import cc.hiver.mall.utils.MerchantOrderSeqUtil;
import cc.hiver.mall.utils.WechatPayUtil; import cc.hiver.mall.utils.WechatPayUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -50,6 +51,9 @@ public class MallOrderGroupServiceImpl extends ServiceImpl<MallOrderGroupMapper,
@Lazy @Lazy
private MallOrderService mallOrderService; private MallOrderService mallOrderService;
@Autowired
private MallUserCouponService mallUserCouponService;
@Autowired @Autowired
private MerchantOrderSeqUtil merchantOrderSeqUtil; private MerchantOrderSeqUtil merchantOrderSeqUtil;
@ -225,6 +229,9 @@ public class MallOrderGroupServiceImpl extends ServiceImpl<MallOrderGroupMapper,
mallDeliveryOrderMapper.update(null, duw); mallDeliveryOrderMapper.update(null, duw);
} }
//回退优惠券
mallUserCouponService.refundCoupon(order.getId());
// 生成退款记录 // 生成退款记录
MallRefundRecord refund = new MallRefundRecord(); MallRefundRecord refund = new MallRefundRecord();
refund.setOrderId(order.getId()); refund.setOrderId(order.getId());

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

@ -1,9 +1,11 @@
package cc.hiver.mall.serviceimpl.mybatis; package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.core.common.redis.RedisTemplateHelper;
import cc.hiver.core.common.utils.SnowFlakeUtil; import cc.hiver.core.common.utils.SnowFlakeUtil;
import cc.hiver.mall.dao.mapper.*; import cc.hiver.mall.dao.mapper.*;
import cc.hiver.mall.entity.*; import cc.hiver.mall.entity.*;
import cc.hiver.mall.pojo.dto.CreateOrderDTO; import cc.hiver.mall.pojo.dto.CreateOrderDTO;
import cc.hiver.mall.pojo.dto.ShopCacheDTO;
import cc.hiver.mall.pojo.query.MallOrderPageQuery; import cc.hiver.mall.pojo.query.MallOrderPageQuery;
import cc.hiver.mall.pojo.vo.MallOrderVO; import cc.hiver.mall.pojo.vo.MallOrderVO;
import cc.hiver.mall.service.mybatis.MallOrderGroupService; import cc.hiver.mall.service.mybatis.MallOrderGroupService;
@ -15,6 +17,7 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
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;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@ -79,6 +82,9 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
@Autowired @Autowired
private MallDeliveryOrderMapper mallDeliveryOrderMapper; private MallDeliveryOrderMapper mallDeliveryOrderMapper;
@Autowired
private MallUserCouponMapper mallUserCouponMapper;
@Autowired @Autowired
private MallRefundRecordMapper mallRefundRecordMapper; private MallRefundRecordMapper mallRefundRecordMapper;
@ -106,6 +112,9 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
@Autowired @Autowired
private cc.hiver.mall.service.mybatis.MallUserCouponService mallUserCouponService; private cc.hiver.mall.service.mybatis.MallUserCouponService mallUserCouponService;
@Autowired
private RedisTemplateHelper redisTemplateHelper;
// ================================================================ // ================================================================
// 核心下单逻辑 // 核心下单逻辑
// ================================================================ // ================================================================
@ -127,12 +136,25 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
BigDecimal goodsAmount = BigDecimal.ZERO; BigDecimal goodsAmount = BigDecimal.ZERO;
List<MallOrderGoods> goodsSnapshots = new ArrayList<>(); List<MallOrderGoods> goodsSnapshots = new ArrayList<>();
for (CreateOrderDTO.OrderItemDTO item : dto.getItems()) { // 一次性查出所有商品,避免循环查询
Product product = productMapper.selectById(item.getProductId()); List<String> productIds = dto.getItems().stream()
if (product == null) { .map(CreateOrderDTO.OrderItemDTO::getProductId)
throw new RuntimeException("商品不存在: " + item.getProductId()); .collect(Collectors.toList());
List<Product> productList = productMapper.selectBatchIds(productIds);
Map<String, Product> productMap = productList.stream()
.collect(Collectors.toMap(Product::getId, p -> p));
// 校验是否所有商品都存在
for (String pid : productIds) {
if (!productMap.containsKey(pid)) {
throw new RuntimeException("商品不存在: " + pid);
}
} }
// 扣减库存(更新 attributeListPrice 中的 specNum) Integer shopSaleCount = 0;
for (CreateOrderDTO.OrderItemDTO item : dto.getItems()) {
Product product = productMap.get(item.getProductId());
shopSaleCount += item.getQuantity();
// 扣减库存(更新 attributeListPrice 中的 specNum)以及销量
deductStock(product, item.getQuantity()); deductStock(product, item.getQuantity());
// 累计商品金额 // 累计商品金额
@ -149,6 +171,17 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
snapshot.setQuantity(item.getQuantity()); snapshot.setQuantity(item.getQuantity());
goodsSnapshots.add(snapshot); goodsSnapshots.add(snapshot);
} }
//更新店铺销量
if(shopSaleCount != 0){
shopMapper.update(null,new UpdateWrapper<Shop>().eq("id",dto.getShopId()).set("sale_count",shopSaleCount));
}
// 增量更新Redis缓存(店铺销量 + 商品销量),避免走refreshShopCache全量查询
try {
updateSaleCacheIncremental(dto.getShopId(), dto.getRegionId(), dto.getItems(), productMap, shopSaleCount);
} catch (Exception e) {
log.warn("增量更新Redis销量缓存失败,不影响下单: {}", e.getMessage());
}
BigDecimal packageFee = dto.getPackageFee() != null ? dto.getPackageFee() : BigDecimal.ZERO; BigDecimal packageFee = dto.getPackageFee() != null ? dto.getPackageFee() : BigDecimal.ZERO;
@ -860,6 +893,8 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
if (order.getStatus() != STATUS_WAIT_PICKUP && order.getStatus() != STATUS_DELIVERING) { if (order.getStatus() != STATUS_WAIT_PICKUP && order.getStatus() != STATUS_DELIVERING) {
throw new RuntimeException("当前状态不可完成"); throw new RuntimeException("当前状态不可完成");
} }
//优惠券变成已使用
mallUserCouponService.useCoupon(orderId);
updateOrderStatus(orderId, STATUS_DONE); updateOrderStatus(orderId, STATUS_DONE);
} }
@ -931,6 +966,12 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
MallOrderGroup group = mallOrderGroupMapper.selectOne(gq2); MallOrderGroup group = mallOrderGroupMapper.selectOne(gq2);
vo.setGroupInfo(group); vo.setGroupInfo(group);
} }
//优惠券
LambdaQueryWrapper<MallUserCoupon> uq = new LambdaQueryWrapper<>();
uq.eq(MallUserCoupon::getOrderId, orderId);
vo.setUserCoupon(mallUserCouponMapper.selectList(uq));
// 售后、退款信息 // 售后、退款信息
LambdaQueryWrapper<MallRefundRecord> rq = new LambdaQueryWrapper<>(); LambdaQueryWrapper<MallRefundRecord> rq = new LambdaQueryWrapper<>();
rq.eq(MallRefundRecord::getOrderId, orderId); rq.eq(MallRefundRecord::getOrderId, orderId);
@ -967,10 +1008,10 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
int current = spec.getInt("specNum"); int current = spec.getInt("specNum");
if (current < quantity) throw new RuntimeException("商品库存不足: " + product.getProductName()); if (current < quantity) throw new RuntimeException("商品库存不足: " + product.getProductName());
spec.set("specNum", current - quantity); spec.set("specNum", current - quantity);
//同时更新销量
LambdaUpdateWrapper<Product> uw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<Product> uw = new LambdaUpdateWrapper<>();
uw.eq(Product::getId, product.getId()) uw.eq(Product::getId, product.getId())
.set(Product::getAttributeListPrice, arr.toString()); .set(Product::getAttributeListPrice, arr.toString()).set(Product::getTailWarn, product.getTailWarn() + quantity);
productMapper.update(null, uw); productMapper.update(null, uw);
} catch (RuntimeException e) { } catch (RuntimeException e) {
throw e; throw e;
@ -979,6 +1020,56 @@ public class MallOrderServiceImpl extends ServiceImpl<MallOrderMapper, MallOrder
} }
} }
/**
* 增量更新Redis缓存中的销量字段避免走refreshShopCache全量重查
* 1. SHOP_CACHE:{regionId} hash field shopId ShopCacheDTO.shop.saleCount 累加
* 2. SHOP_PRODUCTS:{shopId} JSON数组 对应商品的 tailWarn 累加
*/
private void updateSaleCacheIncremental(String shopId, String regionId,
List<CreateOrderDTO.OrderItemDTO> items,
Map<String, Product> productMap,
int shopSaleCount) {
// 1. 更新店铺缓存中的 saleCount
if (StringUtils.isNotBlank(regionId) && shopSaleCount > 0) {
String shopCacheKey = "SHOP_CACHE:" + regionId;
String shopJson = (String) redisTemplateHelper.hGet(shopCacheKey, shopId);
if (StringUtils.isNotBlank(shopJson)) {
ShopCacheDTO cacheDTO = JSONUtil.toBean(shopJson, ShopCacheDTO.class);
if (cacheDTO.getShop() != null) {
Integer oldSaleCount = cacheDTO.getShop().getSaleCount();
cacheDTO.getShop().setSaleCount((oldSaleCount != null ? oldSaleCount : 0) + shopSaleCount);
redisTemplateHelper.hPut(shopCacheKey, shopId, JSONUtil.toJsonStr(cacheDTO));
}
}
}
// 2. 更新商品缓存中的 tailWarn(销量)
String productsKey = "SHOP_PRODUCTS:" + shopId;
String productsJson = redisTemplateHelper.get(productsKey);
if (StringUtils.isNotBlank(productsJson)) {
// 构建本次每个商品的销量增量 map: productId -> quantity
Map<String, Integer> quantityMap = new HashMap<>();
for (CreateOrderDTO.OrderItemDTO item : items) {
quantityMap.merge(item.getProductId(), item.getQuantity(), Integer::sum);
}
JSONArray productArr = JSONUtil.parseArray(productsJson);
boolean changed = false;
for (int i = 0; i < productArr.size(); i++) {
JSONObject productObj = productArr.getJSONObject(i);
String pid = productObj.getStr("id");
if (pid != null && quantityMap.containsKey(pid)) {
int oldTailWarn = productObj.getInt("tailWarn", 0);
productObj.set("tailWarn", oldTailWarn + quantityMap.get(pid));
changed = true;
}
}
if (changed) {
redisTemplateHelper.set(productsKey, productArr.toString());
}
}
}
/** /**
* 构建基础订单对象 * 构建基础订单对象
*/ */

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

@ -12,6 +12,7 @@ import cc.hiver.mall.entity.MallReturnOrderGoods;
import cc.hiver.mall.pojo.query.MallRefundRecordPageQuery; 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.service.mybatis.MallUserCouponService;
import cc.hiver.mall.utils.WechatPayUtil; import cc.hiver.mall.utils.WechatPayUtil;
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;
@ -62,6 +63,9 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
@Autowired @Autowired
private WechatPayUtil wechatPayUtil; private WechatPayUtil wechatPayUtil;
@Autowired
private MallUserCouponService mallUserCouponService;
@Autowired @Autowired
private MallDeliveryOrderMapper mallDeliveryOrderMapper; private MallDeliveryOrderMapper mallDeliveryOrderMapper;
@ -146,6 +150,8 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
//同意退款 //同意退款
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId()); //MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED); updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED);
//回退优惠券
mallUserCouponService.refundCoupon(mallRefundRecord.getOrderId());
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){ if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){
//更新配送单 //更新配送单
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();
@ -246,6 +252,8 @@ public class MallRefundRecordServiceImpl extends ServiceImpl<MallRefundRecordMap
//同意退款 //同意退款
//MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId()); //MallOrder order = mallOrderService.getById(mallRefundRecord.getOrderId());
updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED); updateOrderStatus(mallRefundRecord.getOrderId(), STATUS_REFUNDED);
//回退优惠券
mallUserCouponService.refundCoupon(mallRefundRecord.getOrderId());
if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){ if(mallRefundRecord.getDeliveryType() == DELIVERY_TYPE_PEISONG){
//更新配送单 //更新配送单
LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>(); LambdaUpdateWrapper<MallDeliveryOrder> duw = new LambdaUpdateWrapper<>();

37
hiver-modules/hiver-mall/src/main/java/cc/hiver/mall/serviceimpl/mybatis/MallUserCouponServiceImpl.java

@ -1,19 +1,26 @@
package cc.hiver.mall.serviceimpl.mybatis; package cc.hiver.mall.serviceimpl.mybatis;
import cc.hiver.core.common.exception.HiverException; import cc.hiver.core.common.exception.HiverException;
import cc.hiver.core.common.utils.StringUtils;
import cc.hiver.core.entity.User;
import cc.hiver.core.service.UserService;
import cc.hiver.mall.dao.mapper.MallCouponMapper; import cc.hiver.mall.dao.mapper.MallCouponMapper;
import cc.hiver.mall.dao.mapper.MallUserCouponMapper; import cc.hiver.mall.dao.mapper.MallUserCouponMapper;
import cc.hiver.mall.entity.MallCoupon; import cc.hiver.mall.entity.MallCoupon;
import cc.hiver.mall.entity.MallUserCoupon; import cc.hiver.mall.entity.MallUserCoupon;
import cc.hiver.mall.pojo.query.MallCouponQuery;
import cc.hiver.mall.service.mybatis.MallUserCouponService; import cc.hiver.mall.service.mybatis.MallUserCouponService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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 org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -23,6 +30,9 @@ public class MallUserCouponServiceImpl extends ServiceImpl<MallUserCouponMapper,
@Autowired @Autowired
private MallCouponMapper mallCouponMapper; private MallCouponMapper mallCouponMapper;
@Autowired
private UserService userService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void receiveCoupon(String userId, String couponId) { public void receiveCoupon(String userId, String couponId) {
@ -118,4 +128,31 @@ public class MallUserCouponServiceImpl extends ServiceImpl<MallUserCouponMapper,
.set("use_time", null); .set("use_time", null);
return this.update(uw); return this.update(uw);
} }
@Override
public IPage<MallCoupon> selectPageVO(MallCouponQuery q) {
IPage<MallCoupon> page = new Page<>(q.getPageNum(), q.getPageSize());
IPage<MallCoupon> result = mallCouponMapper.selectPageVO(page, q);
return result;
}
@Override
public void send(String userPhones, Integer type,String couponId) {
//精准发放
if(type == 1){
if(!StringUtils.isEmpty(userPhones)){
List<String> phones = Arrays.asList(userPhones.split(","));
phones.forEach(phone -> {
this.receiveCoupon(userService.findByMobile(phone).getId(), couponId);
});
}
}else{
//全部发放
List<User> users = userService.getAll();
users.forEach(user -> {
this.receiveCoupon(user.getId(), couponId);
});
}
}
} }

68
hiver-modules/hiver-mall/src/main/resources/mapper/MallCouponMapper.xml

@ -2,10 +2,78 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cc.hiver.mall.dao.mapper.MallCouponMapper"> <mapper namespace="cc.hiver.mall.dao.mapper.MallCouponMapper">
<resultMap id="couponMap" type="cc.hiver.mall.entity.MallCoupon">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="issuer_type" property="issuerType"/>
<result column="issuer_id" property="issuerId"/>
<result column="apply_scene" property="applyScene"/>
<result column="type" property="type"/>
<result column="min_amount" property="minAmount"/>
<result column="discount_amount" property="discountAmount"/>
<result column="total_count" property="totalCount"/>
<result column="remain_count" property="remainCount"/>
<result column="limit_per_user" property="limitPerUser"/>
<result column="valid_type" property="validType"/>
<result column="valid_start_time" property="validStartTime"/>
<result column="valid_end_time" property="validEndTime"/>
<result column="valid_days" property="validDays"/>
<result column="status" property="status"/>
<result column="region_id" property="regionId"/>
</resultMap>
<sql id="selectCouponColumns">
id,
name,
issuer_type,
issuer_id,
apply_scene,
type,
min_amount,
discount_amount,
total_count,
remain_count,
limit_per_user,
valid_type,
valid_start_time,
valid_end_time,
valid_days,
status,
region_id
</sql>
<update id="deductStock"> <update id="deductStock">
UPDATE t_mall_coupon UPDATE t_mall_coupon
SET remain_count = remain_count - 1 SET remain_count = remain_count - 1
WHERE id = #{id} AND remain_count > 0 AND del_flag = 0 WHERE id = #{id} AND remain_count > 0 AND del_flag = 0
</update> </update>
<!-- 分页查询-->
<select id="selectPageVO" resultMap="couponMap">
SELECT
<include refid="selectCouponColumns"/>
FROM
t_mall_coupon
<where>
<!-- 示例:动态查询条件 -->
<if test="q.name != null and q.name != ''">
AND name LIKE CONCAT('%', #{q.name}, '%')
</if>
<if test="q.status != null">
AND status = #{q.status}
</if>
<if test="q.type != null">
AND type = #{q.type}
</if>
<if test="q.issuerType != null">
AND issuer_type = #{q.issuerType}
</if>
<if test="q.applyScene != null">
AND apply_scene = #{applyScene}
</if>
<if test="q.regionId != null and q.regionId != ''">
AND region_id = #{q.regionId}
</if>
</where>
ORDER BY id DESC
</select>
</mapper> </mapper>

14
hiver-modules/hiver-mall/src/main/resources/mapper/MallDeliveryOrderMapper.xml

@ -38,6 +38,7 @@
<result column="worker_name" property="workerName"/> <result column="worker_name" property="workerName"/>
<result column="arrive_time" property="arriveTime"/> <result column="arrive_time" property="arriveTime"/>
<result column="arrive_time" property="arriveTime"/> <result column="arrive_time" property="arriveTime"/>
<result column="new_worker" property="newWorker"/>
</resultMap> </resultMap>
<!-- 分页查询配送单,支持多条件过滤(抢单大厅:hallOnly=true时只查workerId为空的) --> <!-- 分页查询配送单,支持多条件过滤(抢单大厅:hallOnly=true时只查workerId为空的) -->
@ -49,7 +50,7 @@
d.receiver_name, d.receiver_phone, d.receiver_address, d.receiver_name, d.receiver_phone, d.receiver_address,
d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code, d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code,
d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures, d.is_big, d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures, d.is_big,
d.is_return,d.worker_name, d.arrive_time d.is_return,d.worker_name, d.arrive_time,d.new_worker
FROM mall_delivery_order d FROM mall_delivery_order d
<where> <where>
<if test="q.regionId != null and q.regionId != ''"> <if test="q.regionId != null and q.regionId != ''">
@ -58,6 +59,9 @@
<if test="q.workerId != null and q.workerId != ''"> <if test="q.workerId != null and q.workerId != ''">
AND d.worker_id = #{q.workerId} AND d.worker_id = #{q.workerId}
</if> </if>
<if test="q.newWorker != null and q.newWorker != ''">
AND d.new_worker = #{q.newWorker}
</if>
<if test="q.shopId != null and q.shopId != ''"> <if test="q.shopId != null and q.shopId != ''">
AND d.shop_id = #{q.shopId} AND d.shop_id = #{q.shopId}
</if> </if>
@ -114,7 +118,8 @@
d.status, d.create_time, d.accept_time, d.get_time, d.must_finish_time, d.finish_time, d.status, d.create_time, d.accept_time, d.get_time, d.must_finish_time, d.finish_time,
d.receiver_name, d.receiver_phone, d.receiver_address, d.receiver_name, d.receiver_phone, d.receiver_address,
d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code, d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code,
d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures, d.is_big,d.is_return,d.worker_name,d.arrive_time d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures,
d.is_big,d.is_return,d.worker_name,d.arrive_time,d.new_worker
FROM mall_delivery_order d FROM mall_delivery_order d
<where> <where>
d.status not in (-1,4,0) d.status not in (-1,4,0)
@ -124,6 +129,9 @@
<if test="q.workerId != null and q.workerId != ''"> <if test="q.workerId != null and q.workerId != ''">
AND d.worker_id = #{q.workerId} AND d.worker_id = #{q.workerId}
</if> </if>
<if test="q.newWorker != null and q.newWorker != ''">
AND d.new_worker = #{q.newWorker}
</if>
<if test="q.shopId != null and q.shopId != ''"> <if test="q.shopId != null and q.shopId != ''">
AND d.shop_id = #{q.shopId} AND d.shop_id = #{q.shopId}
</if> </if>
@ -160,7 +168,7 @@
d.status, d.create_time, d.accept_time, d.get_time, d.must_finish_time, d.finish_time, d.status, d.create_time, d.accept_time, d.get_time, d.must_finish_time, d.finish_time,
d.receiver_name, d.receiver_phone, d.receiver_address, d.receiver_name, d.receiver_phone, d.receiver_address,
d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code, d.shop_name, d.shop_phone, d.shop_address, d.delivery_type, d.number_code,
d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures, d.is_big,d.is_return,d.worker_name,d.arrive_time d.region_id,d.remark, d.all_count, d.phone_number, d.get_codes, d.get_pictures, d.is_big,d.is_return,d.worker_name,d.arrive_time,d.new_worker
FROM mall_delivery_order d FROM mall_delivery_order d
where d.group_id = (select id from mall_order_group where 1 = 1 where d.group_id = (select id from mall_order_group where 1 = 1
<if test='orderId != null and orderId.trim() neq ""'> <if test='orderId != null and orderId.trim() neq ""'>

Loading…
Cancel
Save