Browse Source

取消订单增加授权支付退还额度逻辑

FengChaoYu 1 week ago
parent
commit
f2349fb705

+ 1 - 1
mall-miniapp-service/src/main/java/com/gree/mall/miniapp/logic/user/UserCompanyCreditLogic.java

@@ -38,7 +38,7 @@ public class UserCompanyCreditLogic {
         if(!TransactionSynchronizationManager.isSynchronizationActive()) {
             throw new RemoteServiceException("请先开启事务");
         }
-        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_USER_COMPANY_CREDIT + user.getUserId() + ":" + orderInfo.getCompanyWechatId());
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_USER_COMPANY_CREDIT + orderInfo.getUserId() + ":" + orderInfo.getCompanyWechatId());
         if(!obtain.tryLock(10, TimeUnit.SECONDS)){
             throw new RemoteServiceException("订单创建过于频繁, 请稍后再试");
         }

+ 4 - 1
mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/MaterialMapper.java → mall-server-api/src/main/java/com/gree/mall/manager/commonmapper/LockQueryMapper.java

@@ -5,12 +5,13 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.manager.bean.goods.GoodsMaterialStockDTO;
 import com.gree.mall.manager.bean.material.vender.WebsitVenderVO;
 import com.gree.mall.manager.plus.entity.GoodsMaterialStorage;
+import com.gree.mall.manager.plus.entity.UserCompanyCredit;
 import com.gree.mall.manager.zfire.bean.ZfireParamBean;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
-public interface MaterialMapper {
+public interface LockQueryMapper {
 
     /**
      * 供应商列表
@@ -28,4 +29,6 @@ public interface MaterialMapper {
      */
     List<GoodsMaterialStorage> queryExistGoodsMaterialStockList(@Param("dto") GoodsMaterialStockDTO dto,
                                                                 @Param("stockList") List<GoodsMaterialStockDTO> stockList);
+
+    UserCompanyCredit queryExistUserCompanyCredit(@Param("companyWechatId") String companyWechatId, @Param("userId") String userId);
 }

+ 3 - 3
mall-server-api/src/main/java/com/gree/mall/manager/logic/goods/GoodsMaterialStockLogic.java

@@ -2,7 +2,7 @@ package com.gree.mall.manager.logic.goods;
 
 import cn.hutool.core.collection.CollectionUtil;
 import com.gree.mall.manager.bean.goods.GoodsMaterialStockDTO;
-import com.gree.mall.manager.commonmapper.MaterialMapper;
+import com.gree.mall.manager.commonmapper.LockQueryMapper;
 import com.gree.mall.manager.constant.Constant;
 import com.gree.mall.manager.enums.material.DirectFlagEnum;
 import com.gree.mall.manager.exception.RemoteServiceException;
@@ -35,7 +35,7 @@ public class GoodsMaterialStockLogic {
     private final RedisLockRegistry redisLockRegistry;
     private final GoodsMaterialStorageService goodsMaterialStorageService;
     private final GoodsMaterialStockAccService goodsMaterialStockAccService;
-    private final MaterialMapper materialMapper;
+    private final LockQueryMapper lockQueryMapper;
     private final GoodsMaterialAccService goodsMaterialAccService;
 
     /**
@@ -81,7 +81,7 @@ public class GoodsMaterialStockLogic {
 
     private void saveGoodsMaterialStock(GoodsMaterialStockDTO dto, List<GoodsMaterialStockDTO> stockList) {
         // 查询存在的仓库物料库存
-        List<GoodsMaterialStorage> existStockList = materialMapper.queryExistGoodsMaterialStockList(dto, stockList);
+        List<GoodsMaterialStorage> existStockList = lockQueryMapper.queryExistGoodsMaterialStockList(dto, stockList);
         // 全部仓库物料库存
         Map<String, GoodsMaterialStorage> existStockMap = this.createNotExistStock(stockList, existStockList);
         // 计算仓库物料库存

+ 7 - 1
mall-server-api/src/main/java/com/gree/mall/manager/logic/order/OrderLogic.java

@@ -29,6 +29,7 @@ import com.gree.mall.manager.logic.common.CommonLogic;
 import com.gree.mall.manager.logic.goods.GoodsMaterialStockAccLogic;
 import com.gree.mall.manager.logic.goods.GoodsMaterialStockLogic;
 import com.gree.mall.manager.logic.goods.JxGoodsLogic;
+import com.gree.mall.manager.logic.user.UserCompanyCreditLogic;
 import com.gree.mall.manager.logic.user.UserLogic;
 import com.gree.mall.manager.logic.workorder.OrderBaseLogic;
 import com.gree.mall.manager.logic.workorder.OrderFlagLogic;
@@ -147,6 +148,8 @@ public class OrderLogic {
     GoodsMaterialStockLogic goodsMaterialStockLogic;
     @Resource
     UserCompanyDeliveryService userCompanyDeliveryService;
+    @Resource
+    UserCompanyCreditLogic userCompanyCreditLogic;
 
 
     /**
@@ -357,7 +360,10 @@ public class OrderLogic {
                     .list();
             this.handleGoodsMaterialStock(orderInfo, orderDetailList, adminUser, DirectFlagEnum.ADD, "订单取消", "取消订单");
 
-            // TODO 授权支付退还额度逻辑
+            // 授权支付退还额度逻辑
+            if (orderInfo.getIsCreditOrder()) {
+                userCompanyCreditLogic.refundOrder(orderInfo);
+            }
         }
 
         // 授权支付不需要确认退款

+ 112 - 0
mall-server-api/src/main/java/com/gree/mall/manager/logic/user/UserCompanyCreditLogic.java

@@ -1,17 +1,37 @@
 package com.gree.mall.manager.logic.user;
 
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.manager.bean.admin.AdminUserCom;
 import com.gree.mall.manager.bean.user.UserCompanyCreditBillItemVO;
 import com.gree.mall.manager.bean.user.UserCompanyCreditBillVO;
 import com.gree.mall.manager.commonmapper.CommonMapper;
+import com.gree.mall.manager.commonmapper.LockQueryMapper;
+import com.gree.mall.manager.constant.Constant;
+import com.gree.mall.manager.enums.TransactionTypeEnum;
+import com.gree.mall.manager.exception.RemoteServiceException;
 import com.gree.mall.manager.logic.common.CommonLogic;
+import com.gree.mall.manager.plus.entity.OrderInfo;
+import com.gree.mall.manager.plus.entity.UserCompanyCredit;
+import com.gree.mall.manager.plus.entity.UserCompanyCreditBillItem;
+import com.gree.mall.manager.plus.service.UserCompanyCreditService;
 import com.gree.mall.manager.zfire.bean.ZfireParamBean;
 import com.gree.mall.manager.zfire.util.FieldUtils;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.integration.redis.util.RedisLockRegistry;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import java.math.BigDecimal;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Lock;
 
 @Service
 @Slf4j
@@ -20,6 +40,9 @@ public class UserCompanyCreditLogic {
 
     private final CommonMapper commonMapper;
     private final CommonLogic commonLogic;
+    private final RedisLockRegistry redisLockRegistry;
+    private final LockQueryMapper lockQueryMapper;
+    private final UserCompanyCreditService userCompanyCreditService;
 
     public IPage<UserCompanyCreditBillVO> list(ZfireParamBean zfireParamBean) {
         AdminUserCom adminUser = commonLogic.getAdminUser();
@@ -38,4 +61,93 @@ public class UserCompanyCreditLogic {
         IPage<UserCompanyCreditBillItemVO> page = commonMapper.userCompanyCreditBillItemPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
         return page;
     }
+
+    /**
+     * 授信订单退款
+     * @param orderInfo
+     */
+    public void refundOrder(OrderInfo orderInfo) throws Exception {
+        if (!orderInfo.getIsCreditOrder()) {
+            return;
+        }
+
+        this.repay(orderInfo.getOrderId(), orderInfo.getUserId(), orderInfo.getCompanyWechatId(), orderInfo.getPayAmount());
+    }
+
+    private void repay(String orderId, String userId, String companyWechatId, BigDecimal amount) throws Exception {
+        if(!TransactionSynchronizationManager.isSynchronizationActive()) {
+            throw new RemoteServiceException("请先开启事务");
+        }
+        Lock obtain = redisLockRegistry.obtain(Constant.RedisPrefix.LOCK_USER_COMPANY_CREDIT + userId + ":" + companyWechatId);
+        if(!obtain.tryLock(10, TimeUnit.SECONDS)){
+            throw new RemoteServiceException("订单操作过于频繁, 请稍后再试");
+        }
+        // 处理授信
+        try{
+            // 验证金额
+            if (Objects.isNull(amount) || amount.compareTo(BigDecimal.ZERO) <= 0) {
+                throw new RemoteServiceException("还示金额必须大于0");
+            }
+
+            final UserCompanyCredit userCompanyCredit = lockQueryMapper.queryExistUserCompanyCredit(companyWechatId, userId);
+
+            // 计算恢复后的可用额度
+            BigDecimal newAvailableCredit = userCompanyCredit.getCreditLimit().subtract(userCompanyCredit.getAvailableCredit());
+
+            // 如果恢复后的可用额度超过信用额度上限,则设置为信用额度
+            if (newAvailableCredit.compareTo(userCompanyCredit.getCreditLimit()) > 0) {
+                newAvailableCredit = userCompanyCredit.getCreditLimit();
+            }
+
+            final DateTime curDate = DateUtil.date();
+
+            // 更新用户商户授信记录
+            userCompanyCreditService.lambdaUpdate()
+                    .set(UserCompanyCredit::getAvailableCredit, newAvailableCredit)
+                    .set(UserCompanyCredit::getUpdateTime, curDate)
+                    .eq(UserCompanyCredit::getId, userCompanyCredit.getId())
+                    .update();
+
+            // 生成授信记录三级账明细
+            UserCompanyCreditBillItem item = new UserCompanyCreditBillItem();
+            item.setId(IdWorker.getIdStr())
+                    .setOrderId(orderId)
+                    .setTransactionType(StringUtils.isNotBlank(orderId) ? TransactionTypeEnum.REFUND.getKey() : TransactionTypeEnum.REPAYMENT.getKey())
+                    .setDescription(StringUtils.isNotBlank(orderId) ? TransactionTypeEnum.CONSUMPTION.getRemark() : TransactionTypeEnum.REPAYMENT.getRemark())
+                    .setCompanyWechatId(userCompanyCredit.getCompanyWechatId())
+                    .setCompanyWechatName(userCompanyCredit.getCompanyWechatName())
+                    .setUserId(userCompanyCredit.getUserId())
+                    .setAmount(amount)
+                    .setCreateTime(curDate)
+                    .insert();
+        } finally {
+            this.txCallUnlock(obtain);
+        }
+
+    }
+
+
+    private void txCallUnlock(Lock obtain) {
+        //事务提交完成后才释放锁,此方法禁止执行mysql相关操作,否则将导致重大问题。
+        if (TransactionSynchronizationManager.isActualTransactionActive()) {
+            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
+                @Override
+                public void afterCompletion(int status) {
+
+                    if(TransactionSynchronization.STATUS_COMMITTED == status){
+                        log.info("=========【授信支付】======事务提交==============");
+                    }else if(TransactionSynchronization.STATUS_ROLLED_BACK == status){
+                        log.info("========【授信支付】=========事务回滚============");
+                    }
+
+                    obtain.unlock();
+                }
+            });
+        } else {
+            log.info("【授信支付】====没有事务===释放锁");
+            obtain.unlock();
+        }
+    }
+
+
 }

+ 3 - 4
mall-server-api/src/main/java/com/gree/mall/manager/logic/vender/VenderLogic.java

@@ -5,12 +5,11 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.gree.mall.manager.bean.admin.AdminUserCom;
 import com.gree.mall.manager.bean.material.vender.WebsitVenderVO;
-import com.gree.mall.manager.commonmapper.MaterialMapper;
+import com.gree.mall.manager.commonmapper.LockQueryMapper;
 import com.gree.mall.manager.exception.RemoteServiceException;
 import com.gree.mall.manager.logic.common.CommonLogic;
 import com.gree.mall.manager.plus.entity.WebsitVender;
 import com.gree.mall.manager.plus.service.WebsitVenderService;
-import com.gree.mall.manager.zfire.bean.QueryParamBean;
 import com.gree.mall.manager.zfire.bean.ZfireParamBean;
 import com.gree.mall.manager.zfire.util.FieldUtils;
 import lombok.RequiredArgsConstructor;
@@ -29,7 +28,7 @@ import java.util.Objects;
 public class VenderLogic {
 
     private final CommonLogic commonLogic;
-    private final MaterialMapper materialMapper;
+    private final LockQueryMapper lockQueryMapper;
     private final WebsitVenderService websitVenderService;
 
     public IPage<WebsitVenderVO> page(ZfireParamBean zfireParamBean) {
@@ -39,7 +38,7 @@ public class VenderLogic {
         }
 
         FieldUtils.materialParam(zfireParamBean, WebsitVenderVO.class, adminUser);
-        return materialMapper.websitVenderPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
+        return lockQueryMapper.websitVenderPage(new Page(zfireParamBean.getPageNum(), zfireParamBean.getPageSize()), zfireParamBean);
     }
 
     public WebsitVender detail(String id) {

+ 12 - 1
mall-server-api/src/main/resources/mapper/MaterialMapper.xml → mall-server-api/src/main/resources/mapper/LockQueryMapper.xml

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.gree.mall.manager.commonmapper.MaterialMapper">
+<mapper namespace="com.gree.mall.manager.commonmapper.LockQueryMapper">
 
     <select id="websitVenderPage" resultType="com.gree.mall.manager.bean.material.vender.WebsitVenderVO">
         SELECT
@@ -31,6 +31,17 @@
             </foreach>
         FOR UPDATE
     </select>
+    <select id="queryExistUserCompanyCredit" resultType="com.gree.mall.manager.plus.entity.UserCompanyCredit">
+        SELECT
+            *
+        FROM
+            user_company_credit
+        WHERE
+            company_wechat_id = #{companyWechatId}
+            AND
+            user_id = #{userId}
+        FOR UPDATE
+    </select>
 
 
 </mapper>