feat:支付使用优惠券

This commit is contained in:
dzc committed 2026-05-26 10:49:20 +08:00
1 parent c9f39910f9
commit 667bdac868
19 files changed
+255 -26

No files matched your search

@@ -19,4 +19,7 @@ public class HardAppCreateOrderScancode {
@NotNull(message = "自定义金额不能为空")
private Integer customPrice;
@Schema(description = "优惠券id")
private Long actCouponRecordId;
}
@@ -48,4 +48,7 @@ public class HardAppCreateOrderDto {
// 预约id
private Long apptId;
// 优惠券id
private Long actCouponRecordId;
}
@@ -235,6 +235,7 @@ public class HardOrderController {
.hardType(HardTypeEnum.MERCHANT_QR_CODE)
.orderType(HardOrderTypeEnum.BELOW)
.payType(HardPayTypeEnum.WALLET_QR_CODE_SCAN)
.actCouponRecordId(body.getActCouponRecordId())
.build();
return R.ok(hardwareOrderService.appCreateOrderScancode(dto));
}
@@ -97,6 +97,7 @@ import com.bsd.pjcloud.wallet.api.vo.WalletSettingVo;
import com.bsd.pjcloud.wallet.api.vo.WalletXfjDiscounts;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActComItemVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo;
import com.bsd.pjcloud.wallet.api.vo.mch.MchPickUpVo;
import com.bsd.pjcloud.wallet.api.vo.mch.MchRuleJoinDtoVo;
import jakarta.validation.Valid;
@@ -158,6 +159,7 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
private final RemoteShopSkuService remoteShopSkuService;
private final RemoteComActService remoteComActService;
private final RemoteActCancelService remoteActCancelService;
private final RemoteActCouponCancelService remoteActCouponCancelService;
private final RemoteMallProductService remoteMallProductService;
private final HardManagerMapper hardManagerMapper;
@@ -752,6 +754,15 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
Integer balance = wallet.getBalance();
int totalPrice = dto.getCustomPrice();
// 用户是否使用优惠券
if (ObjectUtil.isNotEmpty(dto.getActCouponRecordId())) {
ActCouponRecordVo actCouponRecord = remoteActCouponCancelService.remoteGetDetail(dto.getActCouponRecordId(), totalPrice).getData();
if (ObjectUtil.isEmpty(actCouponRecord)) {
throw new RuntimeException("优惠券不存在");
}
}
String subject = "未知商品x?";
if (balance < totalPrice) {
throw new RuntimeException("钱包余额不足");
@@ -781,9 +792,10 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
getSelf().fastReduceBalance(orderObj);
// 是否需要创建二维码
getSelf().generateCode(orderObj);
// 扣减库存
// getSelf().fastenerInventory(orderObj, YesNoEnum.YES);
// 核销优惠券
if (ObjectUtil.isNotEmpty(dto.getActCouponRecordId())) {
}
// 云音箱播报
CompletableFuture.runAsync(() -> yyxService.send(orderObj.getMerchantId(), orderObj.getPayPrice(), userDetail.getSysUser().getPhone()));
return orderObj.getId();
@@ -18,4 +18,14 @@ public class ActCouponRecordDto extends ActCouponRecordEntity {
private LocalDateTime[] createTimeList;
/**
* 适用范围 (1:全场通用 2:指定商户 3:指定分类 4:指定商品)
*/
private String useScopeType;
/**
* 适用范围ID集合 (商户ID/分类ID/商品ID, 逗号分隔)
*/
private String scopeId;
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.wallet.api.dto.act;
import lombok.Data;
@Data
public class ActCouponRecordRemoteCancelDto {
/**
* 优惠券id
*/
private Long actCouponRecordId;
/**
* 订单id
*/
private Long orderId;
/**
* 优惠券抵消的金额
*/
private Integer useAmountPrice;
}
@@ -0,0 +1,27 @@
package com.bsd.pjcloud.wallet.api.feign;
import com.bsd.pjcloud.common.core.constant.ServiceNameConstants;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.feign.annotation.NoToken;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordRemoteCancelDto;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(contextId = "remoteActCouponCancelService", value = ServiceNameConstants.WALLET_SERVICE)
public interface RemoteActCouponCancelService {
@NoToken
@GetMapping("/act-coupon-record/remote/get-detail")
R<ActCouponRecordVo> remoteGetDetail(@RequestParam Long actCouponRecordId, @RequestParam Integer totalPrice);
@NoToken
@PostMapping("/act-coupon-record/remote/cancel")
R<Boolean> remoteCancel(@RequestBody ActCouponRecordRemoteCancelDto dto);
}
@@ -27,4 +27,8 @@ public class ActCouponRecordVo extends ActCouponRecordEntity implements BaseUser
*/
private String actUniquecode;
/**
* 优惠券抵消的金额
*/
private Integer useAmountPrice;
}
@@ -1,4 +1,5 @@
com.bsd.pjcloud.wallet.api.feign.RemoteActCancelService
com.bsd.pjcloud.wallet.api.feign.RemoteActCouponCancelService
com.bsd.pjcloud.wallet.api.feign.RemoteWalletService
com.bsd.pjcloud.wallet.api.feign.RemoteMchPickUpService
com.bsd.pjcloud.wallet.api.feign.RemoteMchRuleJoinService
@@ -37,6 +37,8 @@ public class ActCancelItemController {
private final ActCancelItemService actCancelItemService;
/* ************************************* start 远程调用 start ************************************* */
@Inner()
@Operation(summary = "查询优惠券详情", description = "查询优惠券详情")
@GetMapping("/get-detail")
@@ -1,13 +1,16 @@
package com.bsd.pjcloud.wallet.controller.act;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.wallet.api.constant.act.ActCancelStatusEnum;
@@ -15,6 +18,7 @@ import com.bsd.pjcloud.wallet.api.constant.act.ActCouponRecordStatusEnum;
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponReceiveDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordRemoteCancelDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCouponRecordEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCancelItemVo;
import com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo;
@@ -44,8 +48,37 @@ public class ActCouponRecordController {
private final ActCouponRecordService actCouponRecordService;
/* ************************************* start 远程调用 start ************************************* */
@Inner()
@Operation(summary = "远程查询优惠券详情", description = "远程查询优惠券详情")
@GetMapping("/remote/get-detail")
R<ActCouponRecordVo> remoteGetDetail(@RequestParam Long actCouponRecordId, @RequestParam Integer totalPrice) {
return R.ok(actCouponRecordService.remoteGetDetail(actCouponRecordId, totalPrice));
}
@Inner()
@Operation(summary = "远程核销优惠券", description = "远程核销优惠券")
@PostMapping("/remote/cancel")
R<Boolean> remoteCancel(@RequestBody ActCouponRecordRemoteCancelDto dto) {
return R.ok(actCouponRecordService.remoteCancel(dto));
}
/* ************************************* end 远程调用 end ************************************* */
/* ************************************* start app start ************************************* */
@Operation(summary = "查询用户拥有的店铺优惠券", description = "查询用户拥有的店铺优惠券")
@PostMapping("/app/mch-list")
public R<List<ActCouponRecordVo>> appMchList(@RequestBody ActCouponRecordDto dto) {
if (ObjectUtil.isEmpty(dto.getScopeId())) {
throw new RuntimeException("商户id不能为空");
}
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
return R.ok(actCouponRecordService.mchList(dto));
}
@Operation(summary = "领取优惠券", description = "领取优惠券")
@PostMapping("/app/receive")
@Idempotent(expireTime = 2, key = "'/act/receive/app/receive/' + #dto.getReceiveUserId()", info = "正在领取中,请勿重复操作")
@@ -42,7 +42,7 @@ public interface WalletManageMapper extends PjcloudBaseMapper<WalletManageEntity
)
.le(ObjectUtil.isNotEmpty(dto.getLeBalance()), WalletManageEntity::getBalance, dto.getLeBalance())
.orderByDesc(WalletManageEntity::getUserId)
.orderByDesc(WalletManageEntity::getWalletTypeId)
.orderByAsc(WalletManageEntity::getWalletTypeId)
.orderByDesc(WalletManageEntity::getCreateTime);
if (ObjectUtil.isNotEmpty(dto.getIsInclude())) {
if (dto.getIsInclude()) {
@@ -15,5 +15,7 @@ public interface ActCouponRecordMapper extends PjcloudBaseMapper<ActCouponRecord
Page<ActCouponRecordVo> pageList(Page page, @Param("dto") ActCouponRecordDto dto);
List<ActCouponRecordVo> findList(@Param("dto") ActCouponRecordDto dto);
Long userTotal(@Param("userId") Long userId, @Param("statusCodeList") List<String> statusCodeList);
}
@@ -5,9 +5,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.wallet.api.constant.act.ActUserReceiveEnum;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponReceiveDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCouponEntity;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordRemoteCancelDto;
import com.bsd.pjcloud.wallet.api.entity.act.ActCouponRecordEntity;
import com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo;
import jakarta.validation.Valid;
import java.util.List;
@@ -23,6 +24,21 @@ public interface ActCouponRecordService extends IService<ActCouponRecordEntity>
*/
ActCouponRecordEntity getDetail(Long actItemId, Long userId);
/**
* 查询用户拥有的店铺优惠券
*/
List<ActCouponRecordVo> mchList(@Valid ActCouponRecordDto dto);
/**
* 远程核销优惠券
*/
Boolean remoteCancel(ActCouponRecordRemoteCancelDto dto);
/**
* 远程查询优惠券详情
*/
ActCouponRecordVo remoteGetDetail(Long actCouponRecordId, Integer totalPrice);
/**
* 领取优惠券
*/
@@ -49,4 +65,9 @@ public interface ActCouponRecordService extends IService<ActCouponRecordEntity>
* 用户参加活动的数量统计
*/
Long userTotal(Long userId);
/**
* 计算优惠券优惠后的价格
*/
int computerUseAmountPrice(ActCouponRecordEntity detail, Integer totalPrice);
}
@@ -1,5 +1,6 @@
package com.bsd.pjcloud.wallet.service.impl.act;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
@@ -20,10 +21,13 @@ import com.bsd.pjcloud.wallet.api.constant.WalletBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletCodeBizEnum;
import com.bsd.pjcloud.wallet.api.constant.WalletTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActCouponRecordStatusEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActCouponTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActCouponUseScopeTypeEnum;
import com.bsd.pjcloud.wallet.api.constant.act.ActUserReceiveEnum;
import com.bsd.pjcloud.wallet.api.dto.WalletTransactionDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponReceiveDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordDto;
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordRemoteCancelDto;
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
import com.bsd.pjcloud.wallet.api.entity.WalletTypeEntity;
@@ -42,6 +46,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
@@ -83,6 +88,17 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
return pageList;
}
/**
* 查询用户拥有的店铺优惠券
*/
@Override
public List<ActCouponRecordVo> mchList(ActCouponRecordDto dto) {
dto.setStatus(ActCouponRecordStatusEnum.UNUSED.getCode());
dto.setUseScopeType(ActCouponUseScopeTypeEnum.SPECIFIED_MERCHANT.getCode());
dto.setIsFindNoExpire(true);
return baseMapper.findList(dto);
}
/**
* 查询详情
*/
@@ -130,10 +146,74 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
return record.getId();
}
/**
* 远程核销优惠券
*/
@Override
public Boolean remoteCancel(ActCouponRecordRemoteCancelDto dto) {
// 查询用户领取的优惠券
ActCouponRecordEntity detail = baseMapper.selectById(dto.getActCouponRecordId());
if (ObjectUtil.isEmpty(detail)) {
log.error("|{}|远程核销优惠券,优惠券不存在", TAG);
return false;
}
cancel(detail, dto.getOrderId(), dto.getUseAmountPrice());
return true;
}
/**
* 远程查询优惠券详情
*/
@Override
public ActCouponRecordVo remoteGetDetail(Long actCouponRecordId, Integer totalPrice) {
// 查询用户领取的优惠券
ActCouponRecordEntity detail = baseMapper.selectById(actCouponRecordId);
if (ObjectUtil.isEmpty(detail)) {
log.error("|{}|远程查询优惠券详情,优惠券不存在", TAG);
return null;
}
ActCouponRecordVo result = BeanUtil.toBean(detail, ActCouponRecordVo.class);
// 计算优惠券优惠后的价格
if (ObjectUtil.isNotEmpty(totalPrice)) {
int useAmountPrice = computerUseAmountPrice(detail, totalPrice);
result.setUseAmountPrice(useAmountPrice);
}
return result;
}
/**
* 计算优惠券优惠后的价格
*/
@Override
public int computerUseAmountPrice(ActCouponRecordEntity detail, Integer totalPrice) {
// 满减券
if (ObjectUtil.equals(detail.getCouponType(), ActCouponTypeEnum.MANJIAN_QUAN.getCode())) {
// 不足门槛,不优惠
if (totalPrice < detail.getMinPoint() && detail.getMinPoint() > 0) {
return 0;
}
return detail.getUseAmount();
}
// 折扣券
else if (ObjectUtil.equals(detail.getCouponType(), ActCouponTypeEnum.ZHEKOU_QUAN.getCode())) {
if (totalPrice < detail.getMinPoint() && detail.getMinPoint() > 0) {
return 0;
}
return BigDecimal.valueOf(totalPrice).multiply(BigDecimal.valueOf(detail.getFaceValue())).divide(BigDecimal.valueOf(100)).intValue();
}
// 立减券
else if (ObjectUtil.equals(detail.getCouponType(), ActCouponTypeEnum.LIJIAN_QUAN.getCode())) {
return detail.getUseAmount();
} else {
return 0;
}
}
/**
* 核销优惠券
*/
@Override
@Transactional
public void cancel(ActCouponRecordEntity dto, Long orderId, Integer useAmountPrice) {
// 1. 获取当前用户
UserInfo userInfo = remoteUserService.getInnerByUserId(dto.getUserId()).getData();
@@ -3,7 +3,6 @@ package com.bsd.pjcloud.wallet.service.impl.recharge;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
@@ -14,7 +13,6 @@ import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.dto.UserInfo;
@@ -4,26 +4,26 @@
<mapper namespace="com.bsd.pjcloud.wallet.mapper.act.ActCouponRecordMapper">
<sql id="selectA">
select a.id,
a.coupon_id,
a.user_id,
a.user_name,
a.coupon_code,
a.status,
a.coupon_name,
a.coupon_type,
a.face_value,
a.min_point,
a.start_time,
a.end_time,
a.use_time,
a.order_id,
a.use_amount,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
a.coupon_id,
a.user_id,
a.user_name,
a.coupon_code,
a.status,
a.coupon_name,
a.coupon_type,
a.face_value,
a.min_point,
a.start_time,
a.end_time,
a.use_time,
a.order_id,
a.use_amount,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
</sql>
<sql id="whereA">
@@ -60,6 +60,15 @@
order by a.create_time desc , a.id desc
</select>
<select id="findList" resultType="com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo">
<include refid="selectA"/>
from act_coupon_record a
<where>
<include refid="whereA"/>
</where>
order by a.create_time desc , a.id desc
</select>
<select id="userTotal" resultType="java.lang.Long">
select count(0)
from act_coupon_record a