فهرست منبع

小组课人满就成课

刘俊驰 7 ماه پیش
والد
کامیت
6883ce37c4

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserOrderDetailDao.java

@@ -56,4 +56,6 @@ public interface UserOrderDetailDao extends BaseMapper<UserOrderDetail>{
 
 	List<TeacherIndexWrapper.CourseExposureTotal> musicSheetBuyTotal(@Param("param") TeacherIndexWrapper.CourseExposureSearch search,
 																	 @Param("groupBy") String groupBy);
+
+	List<String> getPayingCourseGroupOrder(@Param("groupId") Long groupId);
 }

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CourseGroupService.java

@@ -274,6 +274,8 @@ public interface CourseGroupService extends IService<CourseGroup> {
     @Transactional
     void closeCourseGroup(CourseGroup courseGroup);
 
+    void groupSuccess(CourseGroup courseGroup);
+
     /**
      * 课程组管理-琴房课
      *

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderService.java

@@ -252,4 +252,5 @@ public interface UserOrderService extends IService<UserOrder> {
     void discountCard(UserPaymentOrderWrapper.OrderGoodsInfo orderGoodsInfo);
 
     void updateOrderBizId(String subOrderNo, Long groupId);
+
 }

+ 7 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentCoreService.java

@@ -114,4 +114,11 @@ public interface UserPaymentCoreService {
     void paymentStatus(String orderNo);
 
     void scanRefundOrderRecord();
+
+    /**
+     * 关闭课程组订单未支付成功的订单
+     *
+     * @param groupId 课程组id
+     */
+    void closeCourseGroupOrder(Long groupId);
 }

+ 90 - 46
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/CourseGroupServiceImpl.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.google.common.collect.Lists;
+import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
 import com.yonge.cooleshow.auth.api.entity.SysUser;
 import com.yonge.cooleshow.biz.dal.constant.CourseConstant;
 import com.yonge.cooleshow.biz.dal.dao.CourseGroupDao;
@@ -36,6 +37,7 @@ import com.yonge.toolset.base.page.PageInfo;
 import com.yonge.toolset.base.string.MessageFormatter;
 import com.yonge.toolset.mybatis.support.PageUtil;
 import com.yonge.toolset.payment.core.util.SpringBeansUtil;
+import com.yonge.toolset.payment.util.DistributedLock;
 import com.yonge.toolset.thirdparty.message.MessageSenderPluginContext;
 import com.yonge.toolset.utils.date.DateUtil;
 import org.apache.commons.collections.CollectionUtils;
@@ -121,6 +123,10 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
     @Autowired
     private StudentService studentService;
 
+
+    @Autowired
+    private RedisCacheService redisCacheService;
+
     @Override
     public CourseGroupDao getDao() {
         return this.baseMapper;
@@ -1539,31 +1545,15 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
     @Override
     public void closeCourseGroup(CourseGroup courseGroup) {
         try {
+            // 关闭未支付的订单
+            userPaymentCoreService.closeCourseGroupOrder(courseGroup.getId());
+
+
             List<CourseScheduleStudentPayment> list = courseScheduleStudentPaymentService.list(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
-                                       .eq(CourseScheduleStudentPayment::getCourseGroupId, courseGroup.getId()));
+                    .eq(CourseScheduleStudentPayment::getCourseGroupId, courseGroup.getId()));
             Set<Long> userIds = list.stream().map(CourseScheduleStudentPayment::getUserId).collect(Collectors.toSet());
             if (courseGroup.getPreStudentNum() >= courseGroup.getMixStudentNum() && courseGroup.getStatus().equals(CourseGroupEnum.APPLY.getCode())) {
-                //人数达标则修改课程组为进行中状态
-                courseGroup.setStatus(CourseGroupEnum.ING.getCode());
-                List<Long> noGroupJoinUserIds = Lists.newArrayList();
-                //创建群聊 并添加人员到群中
-                String imGroupId = imGroupService.autoCreate(courseGroup.getId(), courseGroup.getType(), noGroupJoinUserIds);
-
-                // 排除未进群的学生
-                if (CollectionUtils.isNotEmpty(noGroupJoinUserIds)) {
-                    noGroupJoinUserIds.forEach(userIds::remove);
-                }
-                // 更新已进群用户身份
-                imGroupMemberService.initGroupMembers(imGroupId, userIds, ImGroupMemberRoleType.STUDENT);
-                //添加老师进群
-                imGroupMemberService.initGroupMembers(imGroupId, Collections.singleton(courseGroup.getTeacherId()), ImGroupMemberRoleType.TEACHER);
-                courseGroup.setImGroupId(imGroupId);
-
-                // 小组课成课推送
-                if (courseGroup.getType().equals(CourseScheduleEnum.GROUP.getCode())) {
-                    // 极光-消息推送-老师端-通知老师小组课程组成课
-                    sendGroupSuccessMessage(courseGroup,true);
-                }
+                groupSuccess(courseGroup);
             } else {
                 //人数未达标则修改课程组为取消状态
                 courseGroup.setStatus(CourseGroupEnum.CANCEL.getCode());
@@ -1591,9 +1581,9 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
                     this.sendStudentMessage(userIds, courseGroup);
                 }
 
+                courseGroup.setUpdatedTime(new Date());
+                this.updateById(courseGroup);
             }
-            courseGroup.setUpdatedTime(new Date());
-            this.updateById(courseGroup);
         } catch (Exception e) {
             log.error("closeCourseGroup error >>> courseGroup: {} ", JSON.toJSONString(courseGroup));
             log.error("closeCourseGroup error >>> ", e);
@@ -1601,6 +1591,48 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
         }
     }
 
+    @Transactional
+    @Override
+    public void groupSuccess(CourseGroup courseGroup){
+
+
+        List<CourseScheduleStudentPayment> list = courseScheduleStudentPaymentService.list(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
+                .eq(CourseScheduleStudentPayment::getCourseGroupId, courseGroup.getId()));
+        Set<Long> userIds = list.stream().map(CourseScheduleStudentPayment::getUserId).collect(Collectors.toSet());
+
+        if (courseGroup.getPreStudentNum() < courseGroup.getMixStudentNum() || !courseGroup.getStatus().equals(CourseGroupEnum.APPLY.getCode())) {
+            return;
+        }
+        //人数达标则修改课程组为进行中状态
+        courseGroup.setStatus(CourseGroupEnum.ING.getCode());
+        List<Long> noGroupJoinUserIds = Lists.newArrayList();
+        //创建群聊 并添加人员到群中
+        String imGroupId = null;
+        try {
+            imGroupId = imGroupService.autoCreate(courseGroup.getId(), courseGroup.getType(), noGroupJoinUserIds);
+        } catch (Exception e) {
+            log.error("创建群聊失败,{}", JSON.toJSONString(courseGroup),e);
+        }
+
+        // 排除未进群的学生
+        if (CollectionUtils.isNotEmpty(noGroupJoinUserIds)) {
+            noGroupJoinUserIds.forEach(userIds::remove);
+        }
+        // 更新已进群用户身份
+        imGroupMemberService.initGroupMembers(imGroupId, userIds, ImGroupMemberRoleType.STUDENT);
+        //添加老师进群
+        imGroupMemberService.initGroupMembers(imGroupId, Collections.singleton(courseGroup.getTeacherId()), ImGroupMemberRoleType.TEACHER);
+        courseGroup.setImGroupId(imGroupId);
+
+        courseGroup.setUpdatedTime(new Date());
+        this.updateById(courseGroup);
+        // 小组课成课推送
+        if (courseGroup.getType().equals(CourseScheduleEnum.GROUP.getCode())) {
+            // 极光-消息推送-老师端-通知老师小组课程组成课
+            sendGroupSuccessMessage(courseGroup,true);
+        }
+    }
+
     private void sendGroupSuccessMessage(CourseGroup courseGroup,boolean success) {
         // 老师
         SysUser sysUser = sysUserService.getByUserId(courseGroup.getTeacherId());
@@ -1673,32 +1705,44 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
         Collection<UserOrder> userOrders = mapByOrderNos.values();
 
         for (UserOrder order : userOrders) {
-            try {
 
-                // 直播课成课失败退款,只退课程费用,不退畅学卡
-                UserOrderVo detail = userOrderService.detail(order.getId());
+            // 任务执行锁
+            String lockName = redisCacheService.getPaymentCacheKey(order.getOrderNo());
+            DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
 
-                List<Long> orderDetailIds = new ArrayList<>();
-                if (CollectionUtils.isNotEmpty(detail.getOrderDetailList())) {
-                    detail.getOrderDetailList().stream()
-                            .filter(orderDetail -> orderDetail.getGoodType() == GoodTypeEnum.LIVE || orderDetail.getGoodType() == GoodTypeEnum.GROUP)
-                            .filter(orderDetail -> orderDetail.getBizId().equals(courseGroup.getId()))
-                            .forEach(orderDetail -> orderDetailIds.add(orderDetail.getId()));
-                }
-                if (order.getPaymentVersion().equals(EPaymentVersion.V1)) {
-                    userOrderRefundService.orderRefund(order.getOrderNo(), CourseScheduleEnum.valueOf(courseGroup.getType()).getMsg() +"成课失败退款");
-                } else {
-                    userPaymentCoreService.refundPayment(order.getOrderNo(),CourseScheduleEnum.valueOf(courseGroup.getType()).getMsg() +"成课失败退款", orderDetailIds);
-                }
+                try {
+                    if (order.getStatus() == OrderStatusEnum.WAIT_PAY || order.getStatus() == OrderStatusEnum.PAYING) {
+                        // 取消订单
+                        userPaymentCoreService.cancelPayment(JwtUserInfo.builder().userId(order.getUserId().toString()).clientType(ClientEnum.STUDENT.getCode()).build(),order.getOrderNo());
+                    } else if (order.getStatus() == OrderStatusEnum.PAID) {
+
+                        // 直播课成课失败退款,只退课程费用,不退畅学卡
+                        UserOrderVo detail = userOrderService.detail(order.getId());
+
+                        List<Long> orderDetailIds = new ArrayList<>();
+                        if (CollectionUtils.isNotEmpty(detail.getOrderDetailList())) {
+                            detail.getOrderDetailList().stream()
+                                    .filter(orderDetail -> orderDetail.getGoodType() == GoodTypeEnum.LIVE || orderDetail.getGoodType() == GoodTypeEnum.GROUP)
+                                    .filter(orderDetail -> orderDetail.getBizId().equals(courseGroup.getId()))
+                                    .forEach(orderDetail -> orderDetailIds.add(orderDetail.getId()));
+                        }
+                        if (order.getPaymentVersion().equals(EPaymentVersion.V1)) {
+                            userOrderRefundService.orderRefund(order.getOrderNo(), CourseScheduleEnum.valueOf(courseGroup.getType()).getMsg() + "成课失败退款");
+                        } else {
+                            userPaymentCoreService.refundPayment(order.getOrderNo(), CourseScheduleEnum.valueOf(courseGroup.getType()).getMsg() + "成课失败退款", orderDetailIds);
+                        }
 
-                //退还优惠券
-                if (orderDetailIds.size() == detail.getOrderDetailList().size()) {
-                    couponInfoService.updateUserOrderCouponInfo(CouponOrderWrapper.builder().orderNo(order.getOrderNo()).reset(true).build());
+                        //退还优惠券
+                        if (orderDetailIds.size() == detail.getOrderDetailList().size()) {
+                            couponInfoService.updateUserOrderCouponInfo(CouponOrderWrapper.builder().orderNo(order.getOrderNo()).reset(true).build());
+                        }
+                    }
+                } catch (Exception e) {
+                    log.warn("成课失败退款 退款失败,退款订单号 {}", order);
+                    log.error("成课失败退款 退款失败", e);
                 }
-            } catch (Exception e) {
-                log.warn("成课失败退款 退款失败,退款订单号 {}", order);
-                log.error("成课失败退款 退款失败", e);
-            }
+
+            }, 10L, TimeUnit.SECONDS);
         }
     }
 

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/PaymentDivMemberRecordServiceImpl.java

@@ -640,6 +640,7 @@ public class PaymentDivMemberRecordServiceImpl extends ServiceImpl<PaymentDivMem
 
             saveData(userPaymentOrder, tenantdivMap, teacherMap, bizMap, serviceFeeAmount);
         }
+        courseGroupService.groupSuccess(courseGroupService.getById(courseGroup.getId()));
         log.info("buyLiveCourseSuccess ok");
         //课程购买成功后进行消息推送
 

+ 51 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentCoreServiceImpl.java

@@ -412,6 +412,7 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
         }
     }
 
+
     /**
      * 取消订单支付
      *
@@ -421,6 +422,15 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
     @Transactional
     @Override
     public void cancelPayment(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp) {
+        cancelPayment(paymentOrder, paymentResp, false);
+    }
+    /**
+     * 取消订单支付
+     *
+     * @param paymentOrder UserPaymentOrderWrapper.UserPaymentOrder
+     * @param paymentResp  PaymentResp
+     */
+    private void cancelPayment(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp,boolean closeFlag) {
 
         // 同步三方订单支付状态
         String lockName = redisCacheService.getPaymentCacheKey(paymentOrder.getOrderNo());
@@ -478,6 +488,9 @@ public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
 
                                 // 更新订单退款异常信息
                                 userPaymentOrderService.updateById(order);
+                                if (closeFlag) {
+                                    closeWaitOrder(paymentOrder);
+                                }
 
                             });
                             throw new BizException("查询交易中,请耐心等待!");
@@ -1238,6 +1251,8 @@ DISCOUNT("畅学卡")
 
     }
 
+
+
     /**
      * 用户取消支付
      *
@@ -1247,6 +1262,16 @@ DISCOUNT("畅学卡")
     @Transactional
     @Override
     public void cancelPayment(JwtUserInfo<?> userInfo, String orderNo) {
+        cancelPayment(userInfo, orderNo, false);
+
+    }
+    /**
+     * 用户取消支付
+     *
+     * @param userInfo JwtUserInfo
+     * @param orderNo  订单编号
+     */
+    private void cancelPayment(JwtUserInfo<?> userInfo, String orderNo,boolean closeFlag) {
 
         // 查询订单信息,支付状态
         UserPaymentOrderWrapper.UserPaymentOrder paymentOrder = userPaymentOrderService.getUserPaymentOrderByUserId(Long.parseLong(userInfo.getUserId()), orderNo);
@@ -1289,7 +1314,7 @@ DISCOUNT("畅学卡")
                 UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(paymentOrder));
 
                 // 订单取消执行流程
-                cancelPayment(order, paymentResp);
+                cancelPayment(order, paymentResp,closeFlag);
             }
 
         }, 10L, TimeUnit.SECONDS);
@@ -1379,6 +1404,7 @@ DISCOUNT("畅学卡")
                 }
                 break;
             }
+            case GROUP:
             case LIVE: {
                 CourseGroup courseGroup = courseGroupService.getById(payTypeReq.getBizId());
                 if (Objects.isNull(courseGroup)) {
@@ -1956,4 +1982,28 @@ DISCOUNT("畅学卡")
         }
 
     }
+
+    @Override
+    @Transactional
+    public void closeCourseGroupOrder(Long groupId) {
+        List<String> payingCourseGroupOrder = userOrderDetailDao.getPayingCourseGroupOrder(groupId);
+        if (CollectionUtils.isEmpty(payingCourseGroupOrder)) {
+            return;
+        }
+
+        for (String orderNo : payingCourseGroupOrder) {
+            // 任务执行锁
+            String lockName = redisCacheService.getPaymentCacheKey(orderNo);
+            DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+                try {
+                    UserOrder userOrder = userOrderService.getByOrderNo(orderNo);
+                    this.cancelPayment(JwtUserInfo.builder().userId(userOrder.getUserId().toString()).clientType(ClientEnum.STUDENT.getCode()).build(), orderNo,true);
+                } catch (Exception e) {
+                    log.error("closeCourseGroupOrder orderNo={}", orderNo, e);
+                }
+            }, 10L, TimeUnit.SECONDS);
+        }
+
+    }
 }

+ 8 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderDetailMapper.xml

@@ -183,4 +183,12 @@
           AND DATE_FORMAT(uod.create_time_, '%Y-%m-%d') BETWEEN #{param.startTime} AND #{param.endTime}
         group by 'date' order by 'date'
     </select>
+
+	<select id="getPayingCourseGroupOrder" resultType="java.lang.String">
+        SELECT distinct t.order_no_ FROM user_order_detail t
+        LEFT JOIN user_order o ON t.order_no_ = o.order_no_
+        WHERE t.biz_id_ = #{groupId}
+        AND t.good_type_ in ('LIVE','GROUP')
+        AND o.status_ IN ('WAIT_PAY','PAYING')
+    </select>
 </mapper>