From c4a0a66f61e1ccfefb0793fba5a9b62ccb7818ae Mon Sep 17 00:00:00 2001 From: Administrator <15274802129@163.com> Date: Tue, 22 Apr 2025 16:10:29 +0800 Subject: [PATCH] feat(mall): 重构活动模块接口和数据结构 --- src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java | 341 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 304 insertions(+), 37 deletions(-) diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java index b088dd0..773d5c5 100644 --- a/src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/HappyActivityServiceImpl.java @@ -1,25 +1,28 @@ package cc.mrbird.febs.mall.service.impl; import cc.mrbird.febs.common.entity.FebsResponse; -import cc.mrbird.febs.common.enumerates.StateUpDownEnum; +import cc.mrbird.febs.common.enumerates.*; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.common.utils.LoginUserUtil; -import cc.mrbird.febs.mall.entity.HappyActivity; -import cc.mrbird.febs.mall.entity.HappyActivityOption; -import cc.mrbird.febs.mall.entity.HappyFollow; -import cc.mrbird.febs.mall.entity.MallMember; -import cc.mrbird.febs.mall.mapper.HappyActivityMapper; -import cc.mrbird.febs.mall.mapper.HappyActivityOptionMapper; -import cc.mrbird.febs.mall.mapper.HappyFollowMapper; -import cc.mrbird.febs.mall.mapper.MallMemberMapper; +import cc.mrbird.febs.common.utils.MallUtils; +import cc.mrbird.febs.common.utils.ShareCodeUtil; +import cc.mrbird.febs.mall.dto.*; +import cc.mrbird.febs.mall.entity.*; +import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.HappyActivityService; -import cc.mrbird.febs.mall.vo.api.activity.*; -import cc.mrbird.febs.mall.vo.api.activity.follow.ApiOperateDoDto; -import cc.mrbird.febs.mall.vo.api.activity.options.*; +import cc.mrbird.febs.mall.service.IApiMallMemberWalletService; +import cc.mrbird.febs.mall.vo.*; +import cc.mrbird.febs.mall.dto.ApiOperateDoDto; +import cc.mrbird.febs.pay.model.BrandWCPayRequestData; +import cc.mrbird.febs.pay.service.IXcxPayService; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -28,6 +31,8 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; @@ -40,6 +45,11 @@ private final HappyFollowMapper happyFollowMapper; private final MallMemberMapper mallMemberMapper; private final HappyActivityOptionMapper happyActivityOptionMapper; + private final HappyActivityConnectMapper happyActivityConnectMapper; + private final HappyActivityOrderMapper happyActivityOrderMapper; + private final HappyActivityOrderItemMapper happyActivityOrderItemMapper; + private final IXcxPayService iXcxPayService; + private final IApiMallMemberWalletService iApiMallMemberWalletService; @Override public FebsResponse activityList(ApiActivityInfoDto dto) { @@ -189,6 +199,7 @@ throw new FebsException("选项ID不能为空"); } this.operateDoVote(memberId, StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode(), sourceId, sourceOptionId, type); + this.addLikeCnt(sourceOptionId); } else { this.operateDo(memberId, StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode(), sourceId, type); } @@ -235,6 +246,18 @@ Integer sourceType = dto.getSourceType(); Integer type = StateUpDownEnum.VOTE.getCode(); + HappyActivity happyActivity = this.baseMapper.selectById(sourceId); + if(StateUpDownEnum.ACTIVITY_TYPE_VOTE.getCode() != happyActivity.getType()){ + throw new FebsException("当前活动无法投票"); + } + + HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId); + if (happyActivityOption == null) { + throw new FebsException("投票对象不存在"); + } + if (StateUpDownEnum.VOTE_OPTION_STATE_AUDIT_SUCCESS.getCode() != happyActivityOption.getState()) { + throw new FebsException("请重新选择投票对象"); + } //验证当前登录人员今日是否已经投票 List<HappyFollow> happyFollows = happyFollowMapper.selectList( new LambdaQueryWrapper<HappyFollow>() @@ -244,33 +267,11 @@ .eq(HappyFollow::getType, type) .gt(HappyFollow::getCreatedTime, DateUtil.beginOfDay(new Date())) ); - if (CollUtil.isNotEmpty(happyFollows)){ + if (CollUtil.isNotEmpty(happyFollows) && happyFollows.size() >= happyActivity.getVoteCnt()){ throw new FebsException("今日已经投票"); } - - if (StateUpDownEnum.SOURCE_TYPE_ACTIVITY.getCode() == sourceType) { - HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId); - if (happyActivityOption == null) { - throw new FebsException("投票对象不存在"); - } - if (StateUpDownEnum.VOTE_OPTION_STATE_AUDIT_SUCCESS.getCode() != happyActivityOption.getState()) { - throw new FebsException("请重新选择投票对象"); - } - - Integer likesCnt = happyActivityOption.getLikesCnt(); - if (likesCnt == null) { - likesCnt = 0; - } - likesCnt += 1; - happyActivityOption.setLikesCnt(likesCnt); - - boolean updateSuccess = happyActivityOptionMapper.updateById(happyActivityOption) > 0; - if (!updateSuccess) { - throw new FebsException("更新票数失败"); - } - - this.operateDoVote(memberId, sourceType, sourceId, sourceOptionId, type); - } + this.operateDoVote(memberId, sourceType, sourceId, sourceOptionId, type); + this.addLikeCnt(sourceOptionId); return new FebsResponse().success(); } @@ -307,9 +308,275 @@ @Override public FebsResponse operateRegister(ApiOperateRegisterActivityDto dto) { + Long memberId = LoginUserUtil.getLoginUser().getId(); return null; } + @Override + public FebsResponse addConnect(ApiOperateRegisterUserDto dto) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + + HappyActivityConnect happyActivityConnect = new HappyActivityConnect(); + happyActivityConnect.setMemberId(memberId); + happyActivityConnect.setName(dto.getName()); + happyActivityConnect.setPhone(dto.getPhone()); + happyActivityConnect.setAddress(dto.getAddress()); + happyActivityConnectMapper.insert(happyActivityConnect); + return new FebsResponse().success(); + } + + @Override + public FebsResponse connectList(ApiConnectListDto dto) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + dto.setMemberId(memberId); + // 创建分页对象,传入当前页和每页大小 + Page<ApiConnectListInPageVo> page = new Page<>(dto.getPageNow(), dto.getPageSize()); + Page<ApiConnectListInPageVo> voteRecordInPage = happyActivityConnectMapper.selectConnectListPage(page, dto); + return new FebsResponse().success().data(voteRecordInPage); + } + + @Override + public FebsResponse connectInfo(Long id) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(id); + ApiConnectListInPageVo apiConnectListInPageVo = new ApiConnectListInPageVo(); + BeanUtil.copyProperties(happyActivityConnect,apiConnectListInPageVo); + return new FebsResponse().success().data(apiConnectListInPageVo); + } + + @Override + public FebsResponse connectDel(Long id) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + happyActivityConnectMapper.deleteById(id); + return new FebsResponse().success(); + } + + @Override + public FebsResponse connectSave(ApiConnectSaveDto dto) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + Long id = dto.getId(); + HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(id); + if (happyActivityConnect == null) { + throw new FebsException("记录不存在"); + } + happyActivityConnect.setName(dto.getName()); + happyActivityConnect.setPhone(dto.getPhone()); + happyActivityConnect.setAddress(dto.getAddress()); + happyActivityConnectMapper.updateById(happyActivityConnect); + return new FebsResponse().success(); + } + + @Override + public FebsResponse createOrder(ApiCreateOrderDto dto) { + Long memberId = LoginUserUtil.getLoginUser().getId(); + if(CollUtil.isEmpty(dto.getConnectIds())){ + throw new FebsException("请选择报名人"); + } + + List<Long> connectIds = dto.getConnectIds(); + Integer numCnt = dto.getNumCnt(); + if(numCnt != connectIds.size()){ + throw new FebsException("报名人数与票的数量不匹配"); + } + + Long activityId = dto.getActivityId(); + HappyActivity happyActivity = this.baseMapper.selectById(activityId); + if (ObjectUtil.isEmpty(happyActivity)) { + throw new FebsException("活动不存在"); + } + + Integer joinCnt = happyActivity.getJoinCnt(); + if(joinCnt < numCnt){ + throw new FebsException("报名额度剩下"+joinCnt+",请减少报名人数"); + } + //支付总金额 + BigDecimal amount = happyActivity.getPayAmount().multiply(new BigDecimal(dto.getNumCnt())).setScale(2, RoundingMode.DOWN); + if(amount.compareTo(BigDecimal.ZERO) < 0){ + throw new FebsException("支付金额错误"); + } + HappyActivityOrder happyActivityOrder = new HappyActivityOrder(); + happyActivityOrder.setOrderNo(MallUtils.getOrderNum()); + happyActivityOrder.setMemberId(memberId); + happyActivityOrder.setActivityId(dto.getActivityId()); + happyActivityOrder.setPrice(happyActivity.getPayAmount()); + happyActivityOrder.setNumCnt(dto.getNumCnt()); + happyActivityOrder.setAmount(amount); + happyActivityOrder.setPayState(StateUpDownEnum.PAY_STATE_NOT_PAY.getCode()); + happyActivityOrderMapper.insert(happyActivityOrder); + + for(Long connectId : connectIds){ + HappyActivityConnect happyActivityConnect = happyActivityConnectMapper.selectById(connectId); + HappyActivityOrderItem happyActivityOrderItem = new HappyActivityOrderItem(); + happyActivityOrderItem.setMemberId(memberId); + happyActivityOrderItem.setActivityId(dto.getActivityId()); + happyActivityOrderItem.setOrderId(happyActivityOrder.getId()); + happyActivityOrderItem.setConnectId(connectId); + happyActivityOrderItem.setPrice(happyActivity.getPayAmount()); + + happyActivityOrderItem.setName(happyActivityConnect.getName()); + happyActivityOrderItem.setPhone(happyActivityConnect.getPhone()); + happyActivityOrderItem.setAddress(happyActivityConnect.getAddress()); + happyActivityOrderItem.setState(StateUpDownEnum.DOWN.getCode()); + happyActivityOrderItemMapper.insert(happyActivityOrderItem); + } + + this.substructJoinCnt(activityId, happyActivityOrder.getNumCnt()); + HashMap<String, Object> stringObjectHashMap = new HashMap<>(); + stringObjectHashMap.put("orderId",happyActivityOrder.getId()); + stringObjectHashMap.put("amount",amount); + + return new FebsResponse().success().data(stringObjectHashMap); + } + + /** + * 支付订单函数,根据传入的支付订单数据对象处理不同支付类型的订单支付逻辑。 + * + * @param dto 包含支付订单相关信息的数据传输对象,包括订单ID和支付类型等信息。 + * - orderId: 订单ID,用于查询订单信息。 + * - payType: 支付类型,决定支付逻辑的分支。 + * - tradePwd: 交易密码(可选),用于余额或积分支付时验证。 + * @return FebsResponse 返回支付结果的响应对象,包含支付状态、订单信息等数据。 + * - orderInfo: 支付结果信息,可能是预支付ID或其他支付相关数据。 + * - orderNo: 订单编号。 + * - orderId: 订单ID。 + * - wxResultStr: 微信支付相关的结果字符串(仅在微信支付时返回)。 + * @throws FebsException 如果订单不存在、已支付、支付失败或支付类型不支持,则抛出异常。 + */ + @Override + public FebsResponse payOrder(ApiPayOrderDto dto) { + // 获取当前登录用户的ID + Long memberId = LoginUserUtil.getLoginUser().getId(); + Long orderId = dto.getOrderId(); + Integer payType = dto.getPayType(); + + // 查询订单信息,确保订单存在且未支付 + HappyActivityOrder happyActivityOrder = happyActivityOrderMapper.selectById(orderId); + if (ObjectUtil.isEmpty(happyActivityOrder)) { + throw new FebsException("订单不存在"); + } + if (happyActivityOrder.getPayState() == StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()) { + throw new FebsException("订单已支付"); + } + + String payResultStr = ""; + String wxResultStr = ""; + + try { + // 根据支付类型处理不同的支付逻辑 + if (StateUpDownEnum.PAY_METHOD_NO_PAY.getCode() == payType) { + // 处理无需支付的订单逻辑 + processNoPayOrder(happyActivityOrder, orderId); + } else if (StateUpDownEnum.PAY_METHOD_WECHAT.getCode() == payType) { + // 处理微信支付逻辑,生成支付请求数据并更新订单状态 + BrandWCPayRequestData brandWCPayRequestData = iXcxPayService.startPaymentActivity(happyActivityOrder); + wxResultStr = JSONUtil.toJsonStr(brandWCPayRequestData); + payResultStr = brandWCPayRequestData.getPrepay_id(); + updateOrderState(happyActivityOrder, payType, StateUpDownEnum.PAY_STATE_NOT_PAY.getCode()); + } else if (StateUpDownEnum.PAY_METHOD_BALANCE.getCode() == payType || + StateUpDownEnum.PAY_METHOD_INTEGRAL.getCode() == payType) { + // 处理余额或积分支付逻辑,验证交易密码并完成支付 + String payMethod = StateUpDownEnum.PAY_METHOD_BALANCE.getCode() == payType ? "balance" : "prizeScore"; + payResultStr = balancePay(happyActivityOrder, dto.getTradePwd(), payMethod); + processPaidOrder(happyActivityOrder, orderId, payType); + } else { + // 如果支付类型不支持,抛出异常 + throw new FebsException("不支持的支付类型"); + } + } catch (Exception e) { + // 捕获支付过程中的异常,记录日志并抛出自定义异常 + log.error("支付失败,订单ID:{},支付类型:{}", orderId, payType, e); + throw new FebsException("支付失败:" + e.getMessage()); + } + + // todo 支付失败要把对应的人数加回来 + + // 构造返回结果,包含支付相关信息 + Map<String, Object> map = new HashMap<>(); + map.put("orderInfo", payResultStr); + map.put("orderNo", happyActivityOrder.getOrderNo()); + map.put("orderId", happyActivityOrder.getId()); + map.put("wxResultStr", wxResultStr); + + return new FebsResponse().success().data(map).message("支付成功"); + } + + + @Override + public void addLikeCnt(Long sourceOptionId) { + HappyActivityOption happyActivityOption = happyActivityOptionMapper.selectById(sourceOptionId); + happyActivityOption.setLikesCnt(happyActivityOption.getLikesCnt() + 1); + happyActivityOptionMapper.updateById(happyActivityOption); + } + + @Override + public void substructJoinCnt(Long activityId, Integer numCnt) { + HappyActivity happyActivity = this.baseMapper.selectById(activityId); + if(ObjectUtil.isNotEmpty(happyActivity)){ + happyActivity.setJoinCnt(happyActivity.getJoinCnt() -numCnt); + this.baseMapper.updateById(happyActivity); + } + } + + // 处理未支付订单 + private void processNoPayOrder(HappyActivityOrder order, Long orderId) { + updateOrderState(order, StateUpDownEnum.PAY_METHOD_NO_PAY.getCode(), StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()); + generateOrderItemCodes(orderId); + } + + // 处理已支付订单 + private void processPaidOrder(HappyActivityOrder order, Long orderId, Integer payType) { + updateOrderState(order, payType, StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()); + generateOrderItemCodes(orderId); + } + + // 更新订单状态 + private void updateOrderState(HappyActivityOrder order, Integer payType, Integer payState) { + order.setPayState(payState); + order.setPayType(payType); + if (payState == StateUpDownEnum.PAY_STATE_PAY_SUCCESS.getCode()) { + order.setPayTime(new Date()); + } + happyActivityOrderMapper.updateById(order); + } + + // 批量生成订单项编码 + private void generateOrderItemCodes(Long orderId) { + List<HappyActivityOrderItem> items = happyActivityOrderItemMapper.selectList( + new LambdaQueryWrapper<HappyActivityOrderItem>() + .eq(HappyActivityOrderItem::getOrderId, orderId) + ); + if (CollUtil.isNotEmpty(items)) { + for (HappyActivityOrderItem item : items) { + String code = ShareCodeUtil.toSerialCode(item.getOrderId()) + MallUtils.getRandomNum(8); + item.setCode(code); + happyActivityOrderItemMapper.updateById(item); + } + } + } + + + private String balancePay(HappyActivityOrder happyActivityOrder, String tradePwd, String field) { + if (StrUtil.isBlank(tradePwd)) { + throw new FebsException("支付密码错误"); + } + + MallMember mallMember = mallMemberMapper.selectById(happyActivityOrder.getMemberId()); + if (StrUtil.isBlank(mallMember.getTradePassword())) { + throw new FebsException("未设置支付密码"); + } + + if (!SecureUtil.md5(tradePwd).equals(mallMember.getTradePassword())) { + throw new FebsException("支付密码错误"); + } + + int reduce = iApiMallMemberWalletService.reduce(happyActivityOrder.getAmount(), mallMember.getId(), field); + if (reduce == 2) { + throw new FebsException("余额不足"); + } + return happyActivityOrder.getOrderNo(); + } + + public static void main(String[] args) { Date date = new Date(); //获取今日的凌晨的时间 -- Gitblit v1.9.1