【同步】BOOT 和 CLOUD 的功能(所有)
parent
554ee6f02b
commit
b012b2ce71
|
@ -375,7 +375,7 @@ public class CombinationRecordServiceImpl implements CombinationRecordService {
|
|||
CombinationRecordDO updateRecord = new CombinationRecordDO().setId(item.getId())
|
||||
.setStatus(status.getStatus()).setEndTime(now);
|
||||
if (CombinationRecordStatusEnum.isSuccess(status.getStatus())) { // 虚拟成团完事更改状态成功后还需要把参与人数修改为成团需要人数
|
||||
updateRecord.setUserCount(records.size());
|
||||
updateRecord.setUserCount(records.size()).setVirtualGroup(Boolean.TRUE); // 标记为虚拟成团
|
||||
}
|
||||
updateRecords.add(updateRecord);
|
||||
});
|
||||
|
|
|
@ -178,6 +178,9 @@ public class CouponServiceImpl implements CouponService {
|
|||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void invalidateCoupon(Long couponId, Long userId) {
|
||||
if (couponId == null || couponId <= 0) {
|
||||
return;
|
||||
}
|
||||
// 1.1 校验优惠券
|
||||
CouponDO coupon = couponMapper.selectByIdAndUserId(couponId, userId);
|
||||
if (coupon == null) {
|
||||
|
|
|
@ -100,7 +100,7 @@ public class PointActivityServiceImpl implements PointActivityService {
|
|||
}
|
||||
pointActivityMapper.updateById(updateObj);
|
||||
// 2.2 更新商品
|
||||
updateSeckillProduct(updateObj, updateReqVO.getProducts());
|
||||
updatePointProduct(updateObj, updateReqVO.getProducts());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -157,12 +157,12 @@ public class PointActivityServiceImpl implements PointActivityService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 更新秒杀商品
|
||||
* 更新积分商品
|
||||
*
|
||||
* @param activity 秒杀活动
|
||||
* @param activity 积分活动
|
||||
* @param products 该活动的最新商品配置
|
||||
*/
|
||||
private void updateSeckillProduct(PointActivityDO activity, List<PointProductSaveReqVO> products) {
|
||||
private void updatePointProduct(PointActivityDO activity, List<PointProductSaveReqVO> products) {
|
||||
// 第一步,对比新老数据,获得添加、修改、删除的列表
|
||||
List<PointProductDO> newList = buildPointProductDO(activity, products);
|
||||
List<PointProductDO> oldList = pointProductMapper.selectListByActivityId(activity.getId());
|
||||
|
@ -211,10 +211,10 @@ public class PointActivityServiceImpl implements PointActivityService {
|
|||
}
|
||||
|
||||
/**
|
||||
* 校验秒杀商品是否都存在
|
||||
* 校验积分商品是否都存在
|
||||
*
|
||||
* @param spuId 商品 SPU 编号
|
||||
* @param products 秒杀商品
|
||||
* @param products 积分商品
|
||||
*/
|
||||
private void validateProductExists(Long spuId, List<PointProductSaveReqVO> products) {
|
||||
// 1. 校验商品 spu 是否存在
|
||||
|
|
|
@ -37,6 +37,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
|
||||
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
|
||||
ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_034, "交易订单自提失败,原因:你没有核销该门店订单的权限");
|
||||
ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_035, "交易订单创建失败,原因:用户积分不足");
|
||||
|
||||
// ========== After Sale 模块 1-011-000-100 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||
|
|
|
@ -13,23 +13,24 @@ import cn.iocoder.yudao.module.trade.enums.brokerage.BrokerageWithdrawStatusEnum
|
|||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageRecordService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageUserService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.BrokerageWithdrawService;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.BrokerageWithdrawSummaryRespBO;
|
||||
import cn.iocoder.yudao.module.trade.service.brokerage.bo.UserBrokerageSummaryRespBO;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
@Tag(name = "管理后台 - 分销用户")
|
||||
@RestController
|
||||
|
@ -110,7 +111,7 @@ public class BrokerageUserController {
|
|||
// 合计分佣的提现
|
||||
// TODO @疯狂:如果未来支持了打款这个动作,可能 status 会不对;
|
||||
Map<Long, BrokerageWithdrawSummaryRespBO> withdrawMap = brokerageWithdrawService.getWithdrawSummaryMapByUserId(
|
||||
userIds, BrokerageWithdrawStatusEnum.AUDIT_SUCCESS);
|
||||
userIds, asList(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS));
|
||||
// 拼接返回
|
||||
return success(BrokerageUserConvert.INSTANCE.convertPage(pageResult, userMap, brokerageUserCountMap,
|
||||
brokerageOrderSummaryMap, withdrawMap));
|
||||
|
|
|
@ -35,6 +35,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
|||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
@Tag(name = "用户 APP - 分销用户")
|
||||
@RestController
|
||||
|
@ -84,7 +85,7 @@ public class AppBrokerageUserController {
|
|||
BrokerageRecordBizTypeEnum.ORDER, BrokerageRecordStatusEnum.SETTLEMENT, beginTime, endTime);
|
||||
// 统计用户提现的佣金
|
||||
Integer withdrawPrice = brokerageWithdrawService.getWithdrawSummaryListByUserId(Collections.singleton(userId),
|
||||
BrokerageWithdrawStatusEnum.AUDIT_SUCCESS).stream()
|
||||
asList(BrokerageWithdrawStatusEnum.AUDIT_SUCCESS, BrokerageWithdrawStatusEnum.WITHDRAW_SUCCESS)).stream()
|
||||
.findFirst().map(BrokerageWithdrawSummaryRespBO::getPrice).orElse(0);
|
||||
// 统计分销用户数量(一级)
|
||||
Long firstBrokerageUserCount = brokerageUserService.getBrokerageUserCountByBindUserId(userId, 1);
|
||||
|
|
|
@ -41,13 +41,14 @@ public interface BrokerageWithdrawMapper extends BaseMapperX<BrokerageWithdrawDO
|
|||
.eq(BrokerageWithdrawDO::getStatus, status));
|
||||
}
|
||||
|
||||
default List<BrokerageWithdrawSummaryRespBO> selectCountAndSumPriceByUserIdAndStatus(Collection<Long> userIds, Integer status) {
|
||||
default List<BrokerageWithdrawSummaryRespBO> selectCountAndSumPriceByUserIdAndStatus(Collection<Long> userIds,
|
||||
Collection<Integer> status) {
|
||||
List<Map<String, Object>> list = selectMaps(new MPJLambdaWrapper<BrokerageWithdrawDO>()
|
||||
.select(BrokerageWithdrawDO::getUserId)
|
||||
.selectCount(BrokerageWithdrawDO::getId, BrokerageWithdrawSummaryRespBO::getCount)
|
||||
.selectSum(BrokerageWithdrawDO::getPrice)
|
||||
.in(BrokerageWithdrawDO::getUserId, userIds)
|
||||
.eq(BrokerageWithdrawDO::getStatus, status)
|
||||
.in(BrokerageWithdrawDO::getStatus, status)
|
||||
.groupBy(BrokerageWithdrawDO::getUserId));
|
||||
return BeanUtil.copyToList(list, BrokerageWithdrawSummaryRespBO.class);
|
||||
// selectJoinList有BUG,会与租户插件冲突:解析SQL时,发生异常 https://gitee.com/best_handsome/mybatis-plus-join/issues/I84GYW
|
||||
|
|
|
@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX;
|
|||
import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
|
@ -106,10 +107,22 @@ public interface TradeOrderMapper extends BaseMapperX<TradeOrderDO> {
|
|||
.eq(TradeOrderDO::getCommentStatus, commentStatus));
|
||||
}
|
||||
|
||||
default List<TradeOrderDO> selectListByUserIdAndSeckillActivityId(Long userId, Long seckillActivityId) {
|
||||
return selectList(new LambdaUpdateWrapper<>(TradeOrderDO.class)
|
||||
.eq(TradeOrderDO::getUserId, userId)
|
||||
.eq(TradeOrderDO::getSeckillActivityId, seckillActivityId));
|
||||
default List<TradeOrderDO> selectListByUserIdAndActivityId(Long userId, Long activityId, TradeOrderTypeEnum type) {
|
||||
LambdaQueryWrapperX<TradeOrderDO> queryWrapperX = new LambdaQueryWrapperX<>();
|
||||
queryWrapperX.eq(TradeOrderDO::getUserId, userId);
|
||||
if (TradeOrderTypeEnum.isSeckill(type.getType())) {
|
||||
queryWrapperX.eq(TradeOrderDO::getSeckillActivityId, activityId);
|
||||
}
|
||||
if (TradeOrderTypeEnum.isBargain(type.getType())) {
|
||||
queryWrapperX.eq(TradeOrderDO::getBargainActivityId, activityId);
|
||||
}
|
||||
if (TradeOrderTypeEnum.isCombination(type.getType())) {
|
||||
queryWrapperX.eq(TradeOrderDO::getCombinationActivityId, activityId);
|
||||
}
|
||||
if (TradeOrderTypeEnum.isPoint(type.getType())) {
|
||||
queryWrapperX.eq(TradeOrderDO::getPointActivityId, activityId);
|
||||
}
|
||||
return selectList(queryWrapperX);
|
||||
}
|
||||
|
||||
default TradeOrderDO selectOneByPickUpVerifyCode(String pickUpVerifyCode) {
|
||||
|
|
|
@ -74,7 +74,7 @@ public interface BrokerageWithdrawService {
|
|||
* @return 用户提现汇总 List
|
||||
*/
|
||||
List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
|
||||
BrokerageWithdrawStatusEnum status);
|
||||
Collection<BrokerageWithdrawStatusEnum> status);
|
||||
|
||||
/**
|
||||
* 按照 userId,汇总每个用户的提现
|
||||
|
@ -84,7 +84,7 @@ public interface BrokerageWithdrawService {
|
|||
* @return 用户提现汇总 Map
|
||||
*/
|
||||
default Map<Long, BrokerageWithdrawSummaryRespBO> getWithdrawSummaryMapByUserId(Set<Long> userIds,
|
||||
BrokerageWithdrawStatusEnum status) {
|
||||
Collection<BrokerageWithdrawStatusEnum> status) {
|
||||
return convertMap(getWithdrawSummaryListByUserId(userIds, status), BrokerageWithdrawSummaryRespBO::getUserId);
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.*;
|
||||
|
||||
|
@ -98,7 +99,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
|||
// 3.1 审批通过的后续处理
|
||||
if (BrokerageWithdrawStatusEnum.AUDIT_SUCCESS.equals(status)) {
|
||||
auditBrokerageWithdrawSuccess(withdraw);
|
||||
// 3.2 审批不通过的后续处理
|
||||
// 3.2 审批不通过的后续处理
|
||||
} else if (BrokerageWithdrawStatusEnum.AUDIT_FAIL.equals(status)) {
|
||||
brokerageRecordService.addBrokerage(withdraw.getUserId(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT,
|
||||
String.valueOf(withdraw.getId()), withdraw.getPrice(), BrokerageRecordBizTypeEnum.WITHDRAW_REJECT.getTitle());
|
||||
|
@ -114,11 +115,11 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
|||
.setUserId(withdraw.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue())
|
||||
.setBizType(PayWalletBizTypeEnum.BROKERAGE_WITHDRAW.getType()).setBizId(withdraw.getId().toString())
|
||||
.setPrice(withdraw.getPrice())).checkError();
|
||||
// 1.2 微信 API
|
||||
// 1.2 微信 API
|
||||
} else if (BrokerageWithdrawTypeEnum.WECHAT_API.getType().equals(withdraw.getType())) {
|
||||
// TODO @luchi:这里,要加个转账单号的记录;另外,调用 API 转账,是立马成功,还是有延迟的哈?
|
||||
Long payTransferId = createPayTransfer(withdraw);
|
||||
// 1.3 剩余类型,都是手动打款,所以不处理
|
||||
// 1.3 剩余类型,都是手动打款,所以不处理
|
||||
} else {
|
||||
// TODO 可优化:未来可以考虑,接入支付宝、银联等 API 转账,实现自动打款
|
||||
log.info("[auditBrokerageWithdrawSuccess][withdraw({}) 类型({}) 手动打款,无需处理]", withdraw.getId(), withdraw.getType());
|
||||
|
@ -239,11 +240,12 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService {
|
|||
|
||||
@Override
|
||||
public List<BrokerageWithdrawSummaryRespBO> getWithdrawSummaryListByUserId(Collection<Long> userIds,
|
||||
BrokerageWithdrawStatusEnum status) {
|
||||
if (CollUtil.isEmpty(userIds)) {
|
||||
Collection<BrokerageWithdrawStatusEnum> statuses) {
|
||||
if (CollUtil.isEmpty(userIds) || CollUtil.isEmpty(statuses)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds, status.getStatus());
|
||||
return brokerageWithdrawMapper.selectCountAndSumPriceByUserIdAndStatus(userIds,
|
||||
convertSet(statuses, BrokerageWithdrawStatusEnum::getStatus));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderSummary
|
|||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.AppTradeOrderPageReqVO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -110,13 +111,14 @@ public interface TradeOrderQueryService {
|
|||
List<ExpressTrackRespDTO> getExpressTrackList(Long id);
|
||||
|
||||
/**
|
||||
* 【会员】在指定秒杀活动下,用户购买的商品数量
|
||||
* 【会员】在指定活动下,用户购买的商品数量
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param activityId 活动编号
|
||||
* @return 秒杀商品数量
|
||||
* @param type 订单类型
|
||||
* @return 活动商品数量
|
||||
*/
|
||||
int getSeckillProductCount(Long userId, Long activityId);
|
||||
int getActivityProductCount(Long userId, Long activityId, TradeOrderTypeEnum type);
|
||||
|
||||
// =================== Order Item ===================
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.trade.dal.mysql.order.TradeOrderMapper;
|
|||
import cn.iocoder.yudao.module.trade.dal.redis.RedisKeyConstants;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderRefundStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderStatusEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.ExpressClientFactory;
|
||||
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackQueryReqDTO;
|
||||
import cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.ExpressTrackRespDTO;
|
||||
|
@ -174,9 +175,9 @@ public class TradeOrderQueryServiceImpl implements TradeOrderQueryService {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int getSeckillProductCount(Long userId, Long activityId) {
|
||||
public int getActivityProductCount(Long userId, Long activityId, TradeOrderTypeEnum type) {
|
||||
// 获得订单列表
|
||||
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndSeckillActivityId(userId, activityId);
|
||||
List<TradeOrderDO> orders = tradeOrderMapper.selectListByUserIdAndActivityId(userId, activityId, type);
|
||||
orders.removeIf(order -> TradeOrderStatusEnum.isCanceled(order.getStatus())); // 过滤掉【已取消】的订单
|
||||
if (CollUtil.isEmpty(orders)) {
|
||||
return 0;
|
||||
|
|
|
@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.trade.service.order.handler;
|
|||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.point.PointActivityApi;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
|
@ -13,6 +15,9 @@ import org.springframework.stereotype.Component;
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS;
|
||||
|
||||
/**
|
||||
* 积分商城活动订单的 {@link TradeOrderHandler} 实现类
|
||||
*
|
||||
|
@ -23,6 +28,8 @@ public class TradePointOrderHandler implements TradeOrderHandler {
|
|||
|
||||
@Resource
|
||||
private PointActivityApi pointActivityApi;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Override
|
||||
public void beforeOrderCreate(TradeOrderDO order, List<TradeOrderItemDO> orderItems) {
|
||||
|
@ -31,10 +38,15 @@ public class TradePointOrderHandler implements TradeOrderHandler {
|
|||
}
|
||||
// 明确校验一下
|
||||
Assert.isTrue(orderItems.size() == 1, "积分商城活动兑换商品兑换时,只允许选择一个商品");
|
||||
// 校验用户剩余积分是否足够兑换商品
|
||||
MemberUserRespDTO user = memberUserApi.getUser(order.getUserId()).getCheckedData();
|
||||
if (user.getPoint() < order.getUsePoint()) {
|
||||
throw exception(ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS);
|
||||
}
|
||||
|
||||
// 扣减积分商城活动的库存
|
||||
pointActivityApi.updatePointStockDecr(order.getPointActivityId(),
|
||||
orderItems.get(0).getSkuId(), orderItems.get(0).getCount()).getCheckedData();
|
||||
orderItems.get(0).getSkuId(), orderItems.get(0).getCount()).checkError();
|
||||
|
||||
// 如果支付金额为 0,则直接设置为已支付
|
||||
if (Objects.equals(order.getPayPrice(), 0)) {
|
||||
|
@ -65,7 +77,7 @@ public class TradePointOrderHandler implements TradeOrderHandler {
|
|||
}
|
||||
// 恢复积分商城活动的库存
|
||||
pointActivityApi.updatePointStockIncr(order.getPointActivityId(),
|
||||
orderItem.getSkuId(), orderItem.getCount()).getCheckedData();
|
||||
orderItem.getSkuId(), orderItem.getCount()).checkError();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -56,36 +56,36 @@ public class TradePointActivityPriceCalculator implements TradePriceCalculator {
|
|||
Assert.isTrue(param.getItems().size() == 1, "积分商城兑换商品时,只允许选择一个商品");
|
||||
// 2. 校验是否可以参与积分商城活动
|
||||
TradePriceCalculateRespBO.OrderItem orderItem = result.getItems().get(0);
|
||||
PointValidateJoinRespDTO activity = validateJoinSeckill(
|
||||
PointValidateJoinRespDTO activity = validateJoinPointActivity(
|
||||
param.getUserId(), param.getPointActivityId(),
|
||||
orderItem.getSkuId(), orderItem.getCount());
|
||||
|
||||
// 3.1 记录优惠明细
|
||||
int discountPrice = orderItem.getPayPrice(); // 情况一:单使用积分兑换
|
||||
// 3.0 积分兑换前置校验
|
||||
Assert.isTrue(activity.getPoint() >= 1, "积分商城商品兑换积分必须大于 1");
|
||||
result.setUsePoint(activity.getPoint() * orderItem.getCount());
|
||||
orderItem.setUsePoint(activity.getPoint() * orderItem.getCount());
|
||||
// 3.1 记录优惠明细
|
||||
int usePoint = activity.getPoint() * orderItem.getCount();
|
||||
result.setUsePoint(usePoint);
|
||||
orderItem.setUsePoint(usePoint);
|
||||
int discountPrice = orderItem.getPayPrice(); // 情况一:单使用积分兑换
|
||||
if (activity.getPrice() != null && activity.getPrice() > 0) { // 情况二:积分 + 金额
|
||||
discountPrice = orderItem.getPayPrice() - activity.getPrice() * orderItem.getCount();
|
||||
}
|
||||
// 3.2 记录优惠明细
|
||||
TradePriceCalculatorHelper.addPromotion(result, orderItem,
|
||||
param.getPointActivityId(), "积分商城活动", PromotionTypeEnum.POINT.getType(),
|
||||
StrUtil.format("积分商城活动:省 {} 元", TradePriceCalculatorHelper.formatPrice(discountPrice)),
|
||||
discountPrice);
|
||||
|
||||
// 3.3 更新 SKU 优惠金额
|
||||
// 3.2 更新 SKU 优惠金额
|
||||
orderItem.setDiscountPrice(orderItem.getDiscountPrice() + discountPrice);
|
||||
TradePriceCalculatorHelper.recountPayPrice(orderItem);
|
||||
TradePriceCalculatorHelper.recountAllPrice(result);
|
||||
}
|
||||
|
||||
private PointValidateJoinRespDTO validateJoinSeckill(Long userId, Long activityId, Long skuId, Integer count) {
|
||||
private PointValidateJoinRespDTO validateJoinPointActivity(Long userId, Long activityId, Long skuId, Integer count) {
|
||||
// 1. 校验是否可以参与积分商城活动
|
||||
PointValidateJoinRespDTO pointValidateJoinRespDTO = pointActivityApi.validateJoinPointActivity(activityId, skuId, count).getCheckedData();
|
||||
// 2. 校验总限购数量,目前只有 trade 有具体下单的数据,需要交给 trade 价格计算使用
|
||||
int activityProductCount = tradeOrderQueryService.getSeckillProductCount(userId, activityId);
|
||||
if (activityProductCount + count > pointValidateJoinRespDTO.getCount()) {
|
||||
int pointProductCount = tradeOrderQueryService.getActivityProductCount(userId, activityId, TradeOrderTypeEnum.POINT);
|
||||
if (pointProductCount + count > pointValidateJoinRespDTO.getCount()) {
|
||||
throw exception(PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT);
|
||||
}
|
||||
return pointValidateJoinRespDTO;
|
||||
|
|
|
@ -5,18 +5,19 @@ import cn.hutool.core.util.StrUtil;
|
|||
import cn.iocoder.yudao.module.promotion.api.seckill.SeckillActivityApi;
|
||||
import cn.iocoder.yudao.module.promotion.api.seckill.dto.SeckillValidateJoinRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.enums.order.TradeOrderTypeEnum;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateReqBO;
|
||||
import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT;
|
||||
|
||||
// TODO huihui:单测需要补充
|
||||
|
||||
/**
|
||||
* 秒杀活动的 {@link TradePriceCalculator} 实现类
|
||||
*
|
||||
|
@ -61,7 +62,7 @@ public class TradeSeckillActivityPriceCalculator implements TradePriceCalculator
|
|||
// 1. 校验是否可以参与秒杀
|
||||
SeckillValidateJoinRespDTO seckillActivity = seckillActivityApi.validateJoinSeckill(activityId, skuId, count).getCheckedData();
|
||||
// 2. 校验总限购数量,目前只有 trade 有具体下单的数据,需要交给 trade 价格计算使用
|
||||
int seckillProductCount = tradeOrderQueryService.getSeckillProductCount(userId, activityId);
|
||||
int seckillProductCount = tradeOrderQueryService.getActivityProductCount(userId, activityId, TradeOrderTypeEnum.SECKILL);
|
||||
if (seckillProductCount + count > seckillActivity.getTotalLimitCount()) {
|
||||
throw exception(PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT);
|
||||
}
|
||||
|
|
|
@ -158,11 +158,11 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
// 补充说明:从安全性来说,老手机也校验 oldCode 验证码会更安全。但是由于 uni-app 商城界面暂时没做,所以这里不强制校验
|
||||
if (StrUtil.isNotEmpty(reqVO.getOldCode())) {
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getOldCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).getCheckedData();
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
}
|
||||
// 2.2 使用新验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(reqVO.getMobile()).setCode(reqVO.getCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).getCheckedData();
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_MOBILE.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
|
||||
// 3. 更新用户手机
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
|
||||
|
@ -187,7 +187,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
MemberUserDO user = validateUserExists(userId);
|
||||
// 校验验证码
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO().setMobile(user.getMobile()).setCode(reqVO.getCode())
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())).getCheckedData();
|
||||
.setScene(SmsSceneEnum.MEMBER_UPDATE_PASSWORD.getScene()).setUsedIp(getClientIP())).checkError();
|
||||
|
||||
// 更新用户密码
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(userId)
|
||||
|
@ -201,7 +201,7 @@ public class MemberUserServiceImpl implements MemberUserService {
|
|||
|
||||
// 使用验证码
|
||||
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_RESET_PASSWORD,
|
||||
getClientIP())).getCheckedData();
|
||||
getClientIP())).checkError();
|
||||
|
||||
// 更新密码
|
||||
memberUserMapper.updateById(MemberUserDO.builder().id(user.getId())
|
||||
|
|
|
@ -43,6 +43,7 @@ public interface ErrorCodeConstants {
|
|||
ErrorCode USER_IS_DISABLE = new ErrorCode(1_002_003_006, "名字为【{}】的用户已被禁用");
|
||||
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})!");
|
||||
ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
|
||||
ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册");
|
||||
|
||||
// ========== 部门模块 1-002-004-000 ==========
|
||||
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
|
||||
|
|
|
@ -7,7 +7,14 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
|||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
|
||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthLoginRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthPermissionInfoRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthResetPasswordReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSmsSendReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthSocialLoginReqVO;
|
||||
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
|
||||
|
@ -23,14 +30,19 @@ import io.swagger.v3.oas.annotations.Operation;
|
|||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.annotation.security.PermitAll;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -139,6 +151,14 @@ public class AuthController {
|
|||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/reset-password")
|
||||
@PermitAll
|
||||
@Operation(summary = "重置密码")
|
||||
public CommonResult<Boolean> resetPassword(@RequestBody @Valid AuthResetPasswordReqVO reqVO) {
|
||||
authService.resetPassword(reqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// ========== 社交登录相关 ==========
|
||||
|
||||
@GetMapping("/social-auth-redirect")
|
||||
|
|
|
@ -18,7 +18,7 @@ import org.hibernate.validator.constraints.Length;
|
|||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthLoginReqVO {
|
||||
public class AuthLoginReqVO extends CaptchaVerificationReqVO {
|
||||
|
||||
@Schema(description = "账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "登录账号不能为空")
|
||||
|
@ -31,13 +31,6 @@ public class AuthLoginReqVO {
|
|||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
// ========== 图片验证码相关 ==========
|
||||
|
||||
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
private String captchaVerification;
|
||||
|
||||
// ========== 绑定社交登录时,需要传递如下参数 ==========
|
||||
|
||||
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举值", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
|
||||
|
@ -50,11 +43,6 @@ public class AuthLoginReqVO {
|
|||
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
private String socialState;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
public interface CodeEnableGroup {}
|
||||
|
||||
@AssertTrue(message = "授权码不能为空")
|
||||
public boolean isSocialCodeValid() {
|
||||
return socialType == null || StrUtil.isNotEmpty(socialCode);
|
||||
|
|
|
@ -11,7 +11,7 @@ import org.hibernate.validator.constraints.Length;
|
|||
|
||||
@Schema(description = "管理后台 - Register Request VO")
|
||||
@Data
|
||||
public class AuthRegisterReqVO {
|
||||
public class AuthRegisterReqVO extends CaptchaVerificationReqVO {
|
||||
|
||||
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
|
||||
@NotBlank(message = "用户账号不能为空")
|
||||
|
@ -28,12 +28,4 @@ public class AuthRegisterReqVO {
|
|||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
// ========== 图片验证码相关 ==========
|
||||
|
||||
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
||||
@NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class)
|
||||
private String captchaVerification;
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.validation.Mobile;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
@Schema(description = "管理后台 - 短信重置账号密码 Request VO")
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthResetPasswordReqVO {
|
||||
|
||||
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "1234")
|
||||
@NotEmpty(message = "密码不能为空")
|
||||
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
|
||||
private String password;
|
||||
|
||||
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13312341234")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
@Mobile
|
||||
private String mobile;
|
||||
|
||||
@Schema(description = "手机短信验证码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
@NotEmpty(message = "手机手机短信验证码不能为空")
|
||||
private String code;
|
||||
}
|
|
@ -16,7 +16,7 @@ import lombok.NoArgsConstructor;
|
|||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Builder
|
||||
public class AuthSmsSendReqVO {
|
||||
public class AuthSmsSendReqVO extends CaptchaVerificationReqVO {
|
||||
|
||||
@Schema(description = "手机号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudaoyuanma")
|
||||
@NotEmpty(message = "手机号不能为空")
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Schema(description = "管理后台 - 验证码 Request VO")
|
||||
@Data
|
||||
public class CaptchaVerificationReqVO {
|
||||
|
||||
// ========== 图片验证码相关 ==========
|
||||
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
|
||||
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
|
||||
@NotEmpty(message = "验证码不能为空", groups = CodeEnableGroup.class)
|
||||
private String captchaVerification;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
public interface CodeEnableGroup {
|
||||
}
|
||||
}
|
|
@ -51,7 +51,7 @@ public interface AdminAuthService {
|
|||
* @param reqVO 登录信息
|
||||
* @return 登录结果
|
||||
*/
|
||||
AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO) ;
|
||||
AuthLoginRespVO smsLogin(AuthSmsLoginReqVO reqVO);
|
||||
|
||||
/**
|
||||
* 社交快捷登录,使用 code 授权码
|
||||
|
@ -77,4 +77,11 @@ public interface AdminAuthService {
|
|||
*/
|
||||
AuthLoginRespVO register(AuthRegisterReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 重置密码
|
||||
*
|
||||
* @param reqVO 验证码信息
|
||||
*/
|
||||
void resetPassword(AuthResetPasswordReqVO reqVO);
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
|||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
|
||||
import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
|
||||
|
@ -32,6 +33,7 @@ import jakarta.validation.Validator;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
@ -111,6 +113,14 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||
|
||||
@Override
|
||||
public void sendSmsCode(AuthSmsSendReqVO reqVO) {
|
||||
// 如果是重置密码场景,需要校验图形验证码是否正确
|
||||
if (Objects.equals(SmsSceneEnum.ADMIN_MEMBER_RESET_PASSWORD.getScene(), reqVO.getScene())) {
|
||||
ResponseModel response = doValidateCaptcha(reqVO);
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg());
|
||||
}
|
||||
}
|
||||
|
||||
// 登录场景,验证是否存在
|
||||
if (userService.getUserByMobile(reqVO.getMobile()) == null) {
|
||||
throw exception(AUTH_MOBILE_NOT_EXISTS);
|
||||
|
@ -174,16 +184,8 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||
|
||||
@VisibleForTesting
|
||||
void validateCaptcha(AuthLoginReqVO reqVO) {
|
||||
// 如果验证码关闭,则不进行校验
|
||||
if (!captchaEnable) {
|
||||
return;
|
||||
}
|
||||
ResponseModel response = doValidateCaptcha(reqVO);
|
||||
// 校验验证码
|
||||
ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
||||
ResponseModel response = captchaService.verification(captchaVO);
|
||||
// 验证不通过
|
||||
if (!response.isSuccess()) {
|
||||
// 创建登录失败日志(验证码不正确)
|
||||
createLoginLog(null, reqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME, LoginResultEnum.CAPTCHA_CODE_ERROR);
|
||||
|
@ -191,6 +193,17 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||
}
|
||||
}
|
||||
|
||||
private ResponseModel doValidateCaptcha(CaptchaVerificationReqVO reqVO) {
|
||||
// 如果验证码关闭,则不进行校验
|
||||
if (!captchaEnable) {
|
||||
return ResponseModel.success();
|
||||
}
|
||||
ValidationUtils.validate(validator, reqVO, CaptchaVerificationReqVO.CodeEnableGroup.class);
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
||||
return captchaService.verification(captchaVO);
|
||||
}
|
||||
|
||||
private AuthLoginRespVO createTokenAfterLoginSuccess(Long userId, String username, LoginLogTypeEnum logType) {
|
||||
// 插入登陆日志
|
||||
createLoginLog(userId, username, logType, LoginResultEnum.SUCCESS);
|
||||
|
@ -261,19 +274,28 @@ public class AdminAuthServiceImpl implements AdminAuthService {
|
|||
|
||||
@VisibleForTesting
|
||||
void validateCaptcha(AuthRegisterReqVO reqVO) {
|
||||
// 如果验证码关闭,则不进行校验
|
||||
if (!captchaEnable) {
|
||||
return;
|
||||
}
|
||||
// 校验验证码
|
||||
ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);
|
||||
CaptchaVO captchaVO = new CaptchaVO();
|
||||
captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
|
||||
ResponseModel response = captchaService.verification(captchaVO);
|
||||
ResponseModel response = doValidateCaptcha(reqVO);
|
||||
// 验证不通过
|
||||
if (!response.isSuccess()) {
|
||||
throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void resetPassword(AuthResetPasswordReqVO reqVO) {
|
||||
AdminUserDO userByMobile = userService.getUserByMobile(reqVO.getMobile());
|
||||
if (userByMobile == null) {
|
||||
throw exception(USER_MOBILE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
smsCodeApi.useSmsCode(new SmsCodeUseReqDTO()
|
||||
.setCode(reqVO.getCode())
|
||||
.setMobile(reqVO.getMobile())
|
||||
.setScene(SmsSceneEnum.ADMIN_MEMBER_RESET_PASSWORD.getScene())
|
||||
.setUsedIp(getClientIP())
|
||||
).checkError();
|
||||
|
||||
userService.updateUserPassword(userByMobile.getId(), reqVO.getPassword());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ public class RoleServiceImpl implements RoleService {
|
|||
roleMapper.updateById(updateObj);
|
||||
|
||||
// 3. 记录操作日志上下文
|
||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(role, RoleSaveReqVO.class));
|
||||
LogRecordContext.putVariable("role", role);
|
||||
}
|
||||
|
||||
|
@ -118,7 +119,6 @@ public class RoleServiceImpl implements RoleService {
|
|||
permissionService.processRoleDeleted(id);
|
||||
|
||||
// 3. 记录操作日志上下文
|
||||
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(role, RoleSaveReqVO.class));
|
||||
LogRecordContext.putVariable("role", role);
|
||||
}
|
||||
|
||||
|
|
|
@ -297,7 +297,8 @@ public class AdminAuthServiceImplTest extends BaseDbUnitTest {
|
|||
@Test
|
||||
public void testValidateCaptcha_constraintViolationException() {
|
||||
// 准备参数
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class).setCaptchaVerification(null);
|
||||
AuthLoginReqVO reqVO = randomPojo(AuthLoginReqVO.class);
|
||||
reqVO.setCaptchaVerification(null);
|
||||
|
||||
// mock 验证码打开
|
||||
ReflectUtil.setFieldValue(authService, "captchaEnable", true);
|
||||
|
|
Loading…
Reference in New Issue