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