feat:支付选择优惠券
This commit is contained in:
1 parent
67320a4787
commit
b83657b1ea
15 files changed
+173
-32
No files matched your search
+12
@@ -219,6 +219,18 @@ public class HardOrderEntity extends Model<HardOrderEntity> {
|
||||
@Schema(description = "离线自动支付是否成功")
|
||||
private String offlinePaySuccess;
|
||||
|
||||
/**
|
||||
* 优惠券id
|
||||
*/
|
||||
@Schema(description = "优惠券id")
|
||||
private String couponRecordId;
|
||||
|
||||
/**
|
||||
* 优惠金额
|
||||
*/
|
||||
@Schema(description = "优惠金额")
|
||||
private Integer couponPrice;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
|
||||
+4
@@ -45,6 +45,7 @@ import com.bsd.pjcloud.hard.mapper.order.HardAfterSaleMapper;
|
||||
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
|
||||
import com.bsd.pjcloud.hard.service.*;
|
||||
import com.bsd.pjcloud.wallet.api.dto.recharge.WalletRechargeRefundDto;
|
||||
import com.bsd.pjcloud.wallet.api.feign.RemoteActCouponCancelService;
|
||||
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletRechargeService;
|
||||
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletSettingService;
|
||||
import com.bsd.pjcloud.wallet.api.vo.recharge.WalletRechargeVo;
|
||||
@@ -86,6 +87,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
private final RemoteDeptService deptService;
|
||||
private final RemoteWalletRechargeService walletRechargeService;
|
||||
private final RemoteWalletSettingService walletSettingService;
|
||||
private final RemoteActCouponCancelService actCouponCancelService;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -641,6 +643,8 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
|
||||
}
|
||||
// 执行退款
|
||||
getSelf().refund(saveObj.getId());
|
||||
// 退优惠券
|
||||
actCouponCancelService.remoteReturn(Long.valueOf(order.getCouponRecordId()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+24
-2
@@ -86,6 +86,7 @@ import com.bsd.pjcloud.wallet.api.constant.mch.WalletMchSupType;
|
||||
import com.bsd.pjcloud.wallet.api.dto.WalletBalanceTransactionDto;
|
||||
import com.bsd.pjcloud.wallet.api.dto.act.ActCancelItemDto;
|
||||
import com.bsd.pjcloud.wallet.api.dto.act.ActComCancelDto;
|
||||
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponRecordRemoteCancelDto;
|
||||
import com.bsd.pjcloud.wallet.api.entity.WalletCodeUseEntity;
|
||||
import com.bsd.pjcloud.wallet.api.entity.WalletManageEntity;
|
||||
import com.bsd.pjcloud.wallet.api.entity.WalletTransactionEntity;
|
||||
@@ -754,13 +755,20 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
if (ObjectUtil.isEmpty(wallet)) throw new RuntimeException("用户钱包不存在");
|
||||
Integer balance = wallet.getBalance();
|
||||
int totalPrice = dto.getCustomPrice();
|
||||
int payPrice = dto.getCustomPrice();
|
||||
|
||||
// 用户是否使用优惠券
|
||||
int useAmountPrice = 0;
|
||||
if (ObjectUtil.isNotEmpty(dto.getActCouponRecordId())) {
|
||||
ActCouponRecordVo actCouponRecord = remoteActCouponCancelService.remoteGetDetail(dto.getActCouponRecordId(), totalPrice).getData();
|
||||
if (ObjectUtil.isEmpty(actCouponRecord)) {
|
||||
throw new RuntimeException("优惠券不存在");
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(actCouponRecord.getUseAmountPrice()) && actCouponRecord.getUseAmountPrice() > 0) {
|
||||
payPrice -= actCouponRecord.getUseAmountPrice();
|
||||
if (payPrice < 0) payPrice = 0;
|
||||
useAmountPrice = actCouponRecord.getUseAmountPrice();
|
||||
}
|
||||
}
|
||||
|
||||
String subject = "未知商品x?";
|
||||
@@ -782,10 +790,14 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
.orderSourceTypeId(dto.getOrderSourceTypeId())
|
||||
.totalPrice(totalPrice)
|
||||
.extraPrice(0)
|
||||
.payPrice(totalPrice)
|
||||
.payPrice(payPrice)
|
||||
.isOfflineOrder(YesNoEnum.NO.getCode())
|
||||
.productDesc(subject)
|
||||
.build();
|
||||
if (ObjectUtil.isNotEmpty(dto.getActCouponRecordId())) {
|
||||
orderObj.setCouponRecordId(String.valueOf(dto.getActCouponRecordId()));
|
||||
orderObj.setCouponPrice(useAmountPrice);
|
||||
}
|
||||
orderObj.setWalletId(wallet.getId());
|
||||
baseMapper.insert(orderObj);
|
||||
// 钱包扣款
|
||||
@@ -794,7 +806,11 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
getSelf().generateCode(orderObj);
|
||||
// 核销优惠券
|
||||
if (ObjectUtil.isNotEmpty(dto.getActCouponRecordId())) {
|
||||
|
||||
ActCouponRecordRemoteCancelDto remoteCancelDto = new ActCouponRecordRemoteCancelDto();
|
||||
remoteCancelDto.setOrderId(orderObj.getId());
|
||||
remoteCancelDto.setActCouponRecordId(dto.getActCouponRecordId());
|
||||
remoteCancelDto.setUseAmountPrice(useAmountPrice);
|
||||
remoteActCouponCancelService.remoteCancel(remoteCancelDto);
|
||||
}
|
||||
// 云音箱播报
|
||||
CompletableFuture.runAsync(() -> yyxService.send(orderObj.getMerchantId(), orderObj.getPayPrice(), userDetail.getSysUser().getPhone()));
|
||||
@@ -1048,6 +1064,9 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
boolean isVerify = isVerify(hardPayType);
|
||||
if (isWalletPay) {
|
||||
int payPrice = order.getTotalPrice() + order.getExtraPrice();
|
||||
if (ObjectUtil.isNotEmpty(payPrice)) {
|
||||
payPrice -= order.getCouponPrice();
|
||||
}
|
||||
if (payPrice > 0) {
|
||||
WalletBalanceTransactionDto reduceBuild = new WalletBalanceTransactionDto();
|
||||
reduceBuild.setWalletId(order.getWalletId());
|
||||
@@ -1078,6 +1097,9 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
|
||||
}
|
||||
// 订单表订单状态
|
||||
Integer payPrice = isWalletPay ? order.getTotalPrice() + order.getExtraPrice() : 0;
|
||||
if (ObjectUtil.isNotEmpty(order.getCouponPrice())) {
|
||||
payPrice -= order.getCouponPrice();
|
||||
}
|
||||
HardOrderEntity update = HardOrderEntity.builder().id(order.getId()).payTime(LocalDateTime.now()).orderStatus(HardOrderStatusEnum.PAY.getType()).payPrice(payPrice).build();
|
||||
if (ObjectUtil.isNotEmpty(order.getOrderNo())) {
|
||||
update.setOrderNo(order.getOrderNo());
|
||||
|
||||
+2
@@ -228,6 +228,8 @@
|
||||
a.is_offline_order,
|
||||
a.product_desc,
|
||||
a.offline_pay_success,
|
||||
a.coupon_record_id,
|
||||
a.coupon_price,
|
||||
a.create_by,
|
||||
a.create_time,
|
||||
a.update_by,
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ public enum ActUserReceiveEnum {
|
||||
USER_LIMIT_REACHED("4", "已领取,核销码在我的礼券中"),
|
||||
USER_CANNOT_PARTICIPATE("5", "用户不能参加此活动"),
|
||||
OTHER_ERROR("6", "其他错误"),
|
||||
GET_DONE("7", "已领完"),
|
||||
USER_CAN_JOIN_ACT("99", "用户可以参加活动"),
|
||||
|
||||
// 特殊
|
||||
|
||||
+7
@@ -24,4 +24,11 @@ public interface RemoteActCouponCancelService {
|
||||
@PostMapping("/act-coupon-record/remote/cancel")
|
||||
R<Boolean> remoteCancel(@RequestBody ActCouponRecordRemoteCancelDto dto);
|
||||
|
||||
/**
|
||||
* 退回优惠券
|
||||
*/
|
||||
@NoToken
|
||||
@GetMapping("/act-coupon-record/remote/return")
|
||||
R<Boolean> remoteReturn(@RequestParam Long actCouponRecordId);
|
||||
|
||||
}
|
||||
+13
@@ -2,12 +2,14 @@ package com.bsd.pjcloud.wallet.controller.act;
|
||||
|
||||
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.data.datascope.DataScope;
|
||||
import com.bsd.pjcloud.common.log.annotation.SysLog;
|
||||
import com.bsd.pjcloud.wallet.api.constant.act.ActCouponTypeEnum;
|
||||
import com.bsd.pjcloud.wallet.api.dto.act.ActCouponDto;
|
||||
import com.bsd.pjcloud.wallet.api.entity.act.ActCouponEntity;
|
||||
import com.bsd.pjcloud.wallet.api.vo.act.ActCouponVo;
|
||||
@@ -65,6 +67,13 @@ public class ActCouponController {
|
||||
@PostMapping
|
||||
@PreAuthorize("@pms.hasPermission('wallet_actCoupon_add')")
|
||||
public R<Long> save(@RequestBody ActCouponEntity actCoupon) {
|
||||
if (ObjectUtil.isNotEmpty(actCoupon.getTotalCount())) {
|
||||
actCoupon.setSurplusCount(actCoupon.getTotalCount());
|
||||
}
|
||||
// 如果是立减券,则使用门槛设置为0
|
||||
if (ObjectUtil.equals(actCoupon.getType(), ActCouponTypeEnum.LIJIAN_QUAN.getCode())) {
|
||||
actCoupon.setMinPoint(0);
|
||||
}
|
||||
return R.ok(actCouponService.create(actCoupon));
|
||||
}
|
||||
|
||||
@@ -76,6 +85,10 @@ public class ActCouponController {
|
||||
@PutMapping
|
||||
@PreAuthorize("@pms.hasPermission('wallet_actCoupon_edit')")
|
||||
public R updateById(@RequestBody ActCouponEntity actCoupon) {
|
||||
// 如果是立减券,则使用门槛设置为0
|
||||
if (ObjectUtil.equals(actCoupon.getType(), ActCouponTypeEnum.LIJIAN_QUAN.getCode())) {
|
||||
actCoupon.setMinPoint(0);
|
||||
}
|
||||
actCouponService.modify(actCoupon);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
+7
@@ -64,6 +64,13 @@ public class ActCouponRecordController {
|
||||
return R.ok(actCouponRecordService.remoteCancel(dto));
|
||||
}
|
||||
|
||||
@Inner()
|
||||
@Operation(summary = "远程退回优惠券", description = "远程退回优惠券")
|
||||
@GetMapping("/remote/return")
|
||||
R<Boolean> remoteReturn(@RequestParam Long actCouponRecordId) {
|
||||
return R.ok(actCouponRecordService.remoteCancel(actCouponRecordId));
|
||||
}
|
||||
|
||||
/* ************************************* end 远程调用 end ************************************* */
|
||||
|
||||
/* ************************************* start app start ************************************* */
|
||||
|
||||
+8
@@ -13,4 +13,12 @@ public interface ActCouponMapper extends PjcloudBaseMapper<ActCouponEntity> {
|
||||
|
||||
Page<ActCouponVo> pageJoin(Page page, @Param("dto") ActCouponDto dto);
|
||||
|
||||
/**
|
||||
* 原子扣减库存(乐观锁)
|
||||
*
|
||||
* @param couponId 优惠券ID
|
||||
* @return 影响行数,如果返回0表示库存不足
|
||||
*/
|
||||
int deductStock(@Param("couponId") Long couponId);
|
||||
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ public interface ActCouponLifecycleService {
|
||||
*
|
||||
* @param record 优惠券记录实体
|
||||
*/
|
||||
void afterReceive(ActCouponRecordEntity record, SysUser sysUser);
|
||||
void afterReceive(ActCouponEntity coupon, ActCouponRecordEntity record, SysUser sysUser);
|
||||
|
||||
/**
|
||||
* 核销前的校验
|
||||
|
||||
+5
@@ -34,6 +34,11 @@ public interface ActCouponRecordService extends IService<ActCouponRecordEntity>
|
||||
*/
|
||||
Boolean remoteCancel(ActCouponRecordRemoteCancelDto dto);
|
||||
|
||||
/**
|
||||
* 远程退回优惠券
|
||||
*/
|
||||
Boolean remoteCancel(Long actCouponRecordId);
|
||||
|
||||
/**
|
||||
* 远程查询优惠券详情
|
||||
*/
|
||||
|
||||
+33
-3
@@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.bsd.pjcloud.admin.api.dto.UserInfo;
|
||||
@@ -138,7 +139,7 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
|
||||
// 4. 执行领取逻辑
|
||||
ActCouponRecordEntity record = actCouponComUtilService.doReceive(actCouponEntity, sysUser);
|
||||
// 5. 优惠券领取成功后,执行生命周期方法
|
||||
actCouponComUtilService.afterReceive(record, sysUser);
|
||||
actCouponComUtilService.afterReceive(actCouponEntity, record, sysUser);
|
||||
// 6. 领取后特殊处理
|
||||
specialReceive(actCouponEntity, record, sysUser);
|
||||
// 7. 生成核销二维码
|
||||
@@ -161,6 +162,31 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程退回优惠券
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean remoteCancel(Long actCouponRecordId) {
|
||||
ActCouponRecordEntity detail = baseMapper.selectById(actCouponRecordId);
|
||||
if (ObjectUtil.isEmpty(detail)) {
|
||||
log.error("|{}|远程退回优惠券,优惠券不存在", TAG);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 使用UpdateWrapper将useTime设置为null
|
||||
LambdaUpdateWrapper<ActCouponRecordEntity> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper
|
||||
.eq(ActCouponRecordEntity::getId, detail.getId())
|
||||
.set(ActCouponRecordEntity::getStatus, ActCouponRecordStatusEnum.UNUSED.getCode())
|
||||
.set(ActCouponRecordEntity::getUseTime, null)
|
||||
.set(ActCouponRecordEntity::getOrderId, null)
|
||||
.set(ActCouponRecordEntity::getUseAmount, null);
|
||||
|
||||
int rows = baseMapper.update(null, updateWrapper);
|
||||
return rows > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 远程查询优惠券详情
|
||||
*/
|
||||
@@ -192,7 +218,7 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
|
||||
if (totalPrice < detail.getMinPoint() && detail.getMinPoint() > 0) {
|
||||
return 0;
|
||||
}
|
||||
return detail.getUseAmount();
|
||||
return detail.getFaceValue();
|
||||
}
|
||||
// 折扣券
|
||||
else if (ObjectUtil.equals(detail.getCouponType(), ActCouponTypeEnum.ZHEKOU_QUAN.getCode())) {
|
||||
@@ -203,7 +229,7 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
|
||||
}
|
||||
// 立减券
|
||||
else if (ObjectUtil.equals(detail.getCouponType(), ActCouponTypeEnum.LIJIAN_QUAN.getCode())) {
|
||||
return detail.getUseAmount();
|
||||
return detail.getFaceValue();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -335,6 +361,10 @@ public class ActCouponRecordServiceImpl extends ServiceImpl<ActCouponRecordMappe
|
||||
ActUserReceiveEnum specialCouponStatus = specialCoupon(actCouponEntity, userInfo.getSysUser());
|
||||
if (ObjectUtil.isNotEmpty(specialCouponStatus)) {
|
||||
userReceiveEnum = specialCouponStatus;
|
||||
} else if (ObjectUtil.isNotEmpty(actCouponEntity.getTotalCount()) && actCouponEntity.getTotalCount() > 0) {
|
||||
if (ObjectUtil.isNotEmpty(actCouponEntity.getSurplusCount()) && actCouponEntity.getSurplusCount() <= 0) {
|
||||
userReceiveEnum = ActUserReceiveEnum.GET_DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-2
@@ -3,6 +3,7 @@ package com.bsd.pjcloud.wallet.utils.act.service;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.bsd.pjcloud.admin.api.entity.SysUser;
|
||||
import com.bsd.pjcloud.wallet.api.constant.act.*;
|
||||
import com.bsd.pjcloud.wallet.api.entity.act.ActCouponEntity;
|
||||
@@ -42,6 +43,14 @@ public class ActCouponComUtilService implements ActCouponLifecycleService {
|
||||
throw new RuntimeException("此优惠券活动不存在");
|
||||
}
|
||||
|
||||
if (ObjectUtil.isNotEmpty(coupon.getTotalCount()) && coupon.getTotalCount() > 0) {
|
||||
if (ObjectUtil.isNotEmpty(coupon.getSurplusCount())) {
|
||||
if (coupon.getSurplusCount() <= 0) {
|
||||
throw new RuntimeException("此优惠券已领完");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assertStatus(coupon);
|
||||
assertReceiveWindow(coupon);
|
||||
assertLimit(coupon, userId);
|
||||
@@ -89,8 +98,12 @@ public class ActCouponComUtilService implements ActCouponLifecycleService {
|
||||
* 领取优惠券后的处理
|
||||
*/
|
||||
@Override
|
||||
public void afterReceive(ActCouponRecordEntity record, SysUser sysUser) {
|
||||
|
||||
public void afterReceive(ActCouponEntity coupon, ActCouponRecordEntity record, SysUser sysUser) {
|
||||
// 使用原子更新操作,避免并发问题
|
||||
int rows = actCouponMapper.deductStock(coupon.getId());
|
||||
if (rows == 0) {
|
||||
throw new RuntimeException("优惠券库存不足或已被领完");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+34
-24
@@ -4,30 +4,30 @@
|
||||
<mapper namespace="com.bsd.pjcloud.wallet.mapper.act.ActCouponMapper">
|
||||
<sql id="selectA">
|
||||
select a.id,
|
||||
a.unique_code,
|
||||
a.bind_notify_id,
|
||||
a.name,
|
||||
a.type,
|
||||
a.face_value,
|
||||
a.min_point,
|
||||
a.total_count,
|
||||
a.surplus_count,
|
||||
a.limit_count,
|
||||
a.limit_type,
|
||||
a.valid_type,
|
||||
a.valid_start_time,
|
||||
a.valid_end_time,
|
||||
a.valid_days,
|
||||
a.use_scope_type,
|
||||
a.scope_id,
|
||||
a.status,
|
||||
a.description,
|
||||
a.create_by,
|
||||
a.create_time,
|
||||
a.update_by,
|
||||
a.update_time,
|
||||
a.del_flag,
|
||||
a.tenant_id
|
||||
a.unique_code,
|
||||
a.bind_notify_id,
|
||||
a.name,
|
||||
a.type,
|
||||
a.face_value,
|
||||
a.min_point,
|
||||
a.total_count,
|
||||
a.surplus_count,
|
||||
a.limit_count,
|
||||
a.limit_type,
|
||||
a.valid_type,
|
||||
a.valid_start_time,
|
||||
a.valid_end_time,
|
||||
a.valid_days,
|
||||
a.use_scope_type,
|
||||
a.scope_id,
|
||||
a.status,
|
||||
a.description,
|
||||
a.create_by,
|
||||
a.create_time,
|
||||
a.update_by,
|
||||
a.update_time,
|
||||
a.del_flag,
|
||||
a.tenant_id
|
||||
</sql>
|
||||
|
||||
<sql id="whereA">
|
||||
@@ -51,4 +51,14 @@
|
||||
</where>
|
||||
order by a.create_time desc , a.id desc
|
||||
</select>
|
||||
|
||||
<!-- 原子扣减库存(乐观锁) -->
|
||||
<update id="deductStock">
|
||||
UPDATE act_coupon
|
||||
SET surplus_count = surplus_count - 1,
|
||||
update_time = NOW()
|
||||
WHERE id = #{couponId}
|
||||
AND surplus_count > 0
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
+7
@@ -63,8 +63,15 @@
|
||||
<select id="findList" resultType="com.bsd.pjcloud.wallet.api.vo.act.ActCouponRecordVo">
|
||||
<include refid="selectA"/>
|
||||
from act_coupon_record a
|
||||
left join act_coupon c on c.id = a.coupon_id and c.del_flag = '0'
|
||||
<where>
|
||||
<include refid="whereA"/>
|
||||
<if test="dto.useScopeType != null and dto.useScopeType != '' ">
|
||||
and c.use_scope_type = #{dto.useScopeType}
|
||||
</if>
|
||||
<if test="dto.scopeId != null and dto.scopeId != '' ">
|
||||
and c.scope_id = #{dto.scopeId}
|
||||
</if>
|
||||
</where>
|
||||
order by a.create_time desc , a.id desc
|
||||
</select>
|
||||
|
||||
Reference in new issue
Block a user