|
@@ -1,6 +1,6 @@
|
|
|
package com.yonge.cooleshow.biz.dal.service.impl;
|
|
|
-import java.math.BigDecimal;
|
|
|
-import java.util.Date;
|
|
|
+
|
|
|
+import com.yonge.cooleshow.biz.dal.enums.GoodTypeEnum;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
@@ -14,20 +14,24 @@ import com.yonge.cooleshow.biz.dal.dao.CourseGroupDao;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.CheckCourseTimeDto;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.LiveCourseGroupDto.CoursePlanDto;
|
|
|
+import com.yonge.cooleshow.biz.dal.dto.req.OrderReq;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupSearch;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupStudentCourseSearch;
|
|
|
import com.yonge.cooleshow.biz.dal.dto.search.LiveCourseGroupStudentSearch;
|
|
|
import com.yonge.cooleshow.biz.dal.entity.*;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.CourseGroupEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.enums.CourseScheduleEnum;
|
|
|
+
|
|
|
import com.yonge.cooleshow.biz.dal.enums.StudentCourseEnum;
|
|
|
+
|
|
|
+import com.yonge.cooleshow.biz.dal.enums.TeacherSalaryEnum;
|
|
|
import com.yonge.cooleshow.biz.dal.service.*;
|
|
|
import com.yonge.cooleshow.biz.dal.support.PageUtil;
|
|
|
-import com.yonge.cooleshow.biz.dal.vo.*;
|
|
|
import com.yonge.cooleshow.biz.dal.support.WrapperUtil;
|
|
|
-import com.yonge.cooleshow.biz.dal.vo.CourseGroupVo;
|
|
|
-import com.yonge.cooleshow.biz.dal.vo.LiveCourseInfoVo;
|
|
|
+import com.yonge.cooleshow.biz.dal.vo.*;
|
|
|
+import com.yonge.cooleshow.biz.dal.vo.res.OrderCreateRes;
|
|
|
import com.yonge.cooleshow.common.constant.SysConfigConstant;
|
|
|
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
|
|
|
import com.yonge.cooleshow.common.exception.BizException;
|
|
|
import com.yonge.cooleshow.common.page.PageInfo;
|
|
|
import com.yonge.toolset.utils.date.DateUtil;
|
|
@@ -40,13 +44,15 @@ import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
-import rx.subjects.Subject;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.time.LocalDate;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
+import java.util.function.BiFunction;
|
|
|
import java.util.function.Consumer;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
@@ -78,6 +84,8 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
|
|
|
private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;
|
|
|
@Autowired
|
|
|
private TeacherFreeTimeService teacherFreeTimeService;
|
|
|
+ @Autowired
|
|
|
+ private CourseScheduleTeacherSalaryService courseScheduleTeacherSalaryService;
|
|
|
|
|
|
@Override
|
|
|
public CourseGroupDao getDao() {
|
|
@@ -171,6 +179,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
|
|
|
group.setCourseIntroduce(dto.getCourseIntroduce());
|
|
|
group.setCoursePrice(dto.getCoursePrice());
|
|
|
group.setStatus(CourseGroupEnum.NOT_SALE.getCode());
|
|
|
+ group.setCourseStartTime(dto.getStartTime());
|
|
|
group.setSalesStartDate(dto.getSalesStartDate());
|
|
|
group.setSalesEndDate(dto.getSalesEndDate());
|
|
|
group.setBackgroundPic(dto.getBackgroundPic());
|
|
@@ -193,6 +202,7 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
|
|
|
course.setEndTime(o.getEndTime());
|
|
|
course.setCreatedBy(dto.getTeacherId());
|
|
|
course.setCreatedTime(now);
|
|
|
+ course.setLock(0);
|
|
|
course.setStatus(CourseScheduleEnum.NOT_START.getCode());
|
|
|
courseList.add(course);
|
|
|
|
|
@@ -475,7 +485,6 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
|
|
|
|
|
|
@Override
|
|
|
public List<LiveCourseGroupPlanVo> selectAdminLivePlan(Long courseGroupId) {
|
|
|
-
|
|
|
return baseMapper.selectAdminLivePlan(courseGroupId);
|
|
|
}
|
|
|
|
|
@@ -508,69 +517,173 @@ public class CourseGroupServiceImpl extends ServiceImpl<CourseGroupDao, CourseGr
|
|
|
/**
|
|
|
* 学生购买直播课程组
|
|
|
*
|
|
|
- * @param param 传入参数
|
|
|
- * <p> - groupId 直播课程组id
|
|
|
- * <p> - studentId 学员id
|
|
|
+ * @param orderReqInfo 订单信息
|
|
|
*/
|
|
|
- public void buyLiveCourse(Map<String, Object> param) {
|
|
|
- Long studentId = WrapperUtil.toLong(param, "studentId", "学员id不能为空!");
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public HttpResponseResult<OrderCreateRes> buyLiveCourse(OrderReq.OrderReqInfo orderReqInfo) {
|
|
|
+ Map<String, Object> param = WrapperUtil.toMap(orderReqInfo.getBizContent());
|
|
|
Long groupId = WrapperUtil.toLong(param, "groupId", "课程组id不能为空!");
|
|
|
- //学生信息
|
|
|
+ Long studentId = orderReqInfo.getUserId();
|
|
|
+ //校验学生信息
|
|
|
getSysUser(studentId);
|
|
|
//课程组信息
|
|
|
- CourseGroup liveCourseGroup = this.getOne(Wrappers.<CourseGroup>lambdaQuery()
|
|
|
+ CourseGroup courseGroup = this.getOne(Wrappers.<CourseGroup>lambdaQuery()
|
|
|
.eq(CourseGroup::getId, groupId)
|
|
|
.eq(CourseGroup::getType, CourseScheduleEnum.LIVE.getCode())
|
|
|
);
|
|
|
- if (Objects.isNull(liveCourseGroup)) {
|
|
|
+ if (Objects.isNull(courseGroup)) {
|
|
|
throw new BizException("课程组不存在!");
|
|
|
}
|
|
|
//课程信息
|
|
|
List<CourseSchedule> courseList = courseScheduleService.list(Wrappers.<CourseSchedule>lambdaQuery()
|
|
|
- .eq(CourseSchedule::getCourseGroupId, groupId)
|
|
|
- );
|
|
|
+ .eq(CourseSchedule::getCourseGroupId, groupId));
|
|
|
if (CollectionUtils.isEmpty(courseList)) {
|
|
|
throw new BizException("课程组课程不存在!");
|
|
|
}
|
|
|
//校验购买的课程组每节课时间是否和自己的课时冲突
|
|
|
batchCheckStudentCourseTime(studentId, courseList, CourseSchedule::getStartTime, CourseSchedule::getEndTime);
|
|
|
- //todo 写订单 返回订单号数据(订单号 金额 等等)
|
|
|
- String orderNo = "";
|
|
|
- Date now = new Date();
|
|
|
+ //返回的数据 有用后面aftet的方法使用
|
|
|
+ Map<String, Object> bizContent = new HashMap<>();
|
|
|
+ bizContent.put("courseGroup", courseGroup);
|
|
|
+ bizContent.put("courseList", courseList);
|
|
|
+ bizContent.put("studentId", studentId);
|
|
|
+ OrderCreateRes orderCreateRes = new OrderCreateRes();
|
|
|
+ orderCreateRes.setRes(true);
|
|
|
+ orderCreateRes.setMerchId(courseGroup.getTeacherId());
|
|
|
+ orderCreateRes.setBizId(courseGroup.getId());
|
|
|
+ orderCreateRes.setOriginalPrice(courseGroup.getCoursePrice());
|
|
|
+ orderCreateRes.setExpectPrice(courseGroup.getCoursePrice());
|
|
|
+ orderCreateRes.setBizParam(bizContent);
|
|
|
+ orderCreateRes.setGoodNum(courseGroup.getCourseNum());
|
|
|
+ orderCreateRes.setGoodType(GoodTypeEnum.LIVE);
|
|
|
+
|
|
|
+ HttpResponseResult<OrderCreateRes> httpResponseResult = new HttpResponseResult<>();
|
|
|
+ httpResponseResult.setData(orderCreateRes);
|
|
|
+ return httpResponseResult;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 待订单创建完毕后继续后续操作
|
|
|
+ *
|
|
|
+ * @param afterParam 传入参数
|
|
|
+ * <p> - courseList 课程列表
|
|
|
+ * <p> - studentId 学员id
|
|
|
+ * <p> - courseGroup 直播课程组信息
|
|
|
+ */
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ @Override
|
|
|
+ public void buyLiveCourseAfter(UserOrderDetailVo afterParam) {
|
|
|
+ Map<String, Object> param = WrapperUtil.toMap(afterParam.getBizParam());
|
|
|
+ String orderNo = afterParam.getOrderNo();
|
|
|
+ Long studentId = (Long) param.get("studentId");
|
|
|
+ List<CourseSchedule> courseList = (List<CourseSchedule>) param.get("courseList");
|
|
|
+ CourseGroup courseGroup = (CourseGroup) param.get("courseGroup");
|
|
|
+
|
|
|
//写course_schedule_student_payment表 作为记录锁定时间用,防止重复购买,如果支付失败则删除该数据
|
|
|
List<CourseScheduleStudentPayment> studentPaymentList = new ArrayList<>();
|
|
|
+ Date now = new Date();
|
|
|
courseList.forEach(course -> {
|
|
|
CourseScheduleStudentPayment studentPayment = new CourseScheduleStudentPayment();
|
|
|
studentPayment.setUserId(studentId);
|
|
|
- studentPayment.setCourseGroupId(groupId);
|
|
|
+ studentPayment.setCourseGroupId(courseGroup.getId());
|
|
|
studentPayment.setCourseId(course.getId());
|
|
|
studentPayment.setOrderNo(orderNo);
|
|
|
- studentPayment.setOriginalPrice(liveCourseGroup.getCoursePrice());
|
|
|
- studentPayment.setExpectPrice(liveCourseGroup.getCoursePrice());
|
|
|
- studentPayment.setActualPrice(liveCourseGroup.getCoursePrice());
|
|
|
+ studentPayment.setOriginalPrice(courseGroup.getCoursePrice());
|
|
|
+ studentPayment.setExpectPrice(courseGroup.getCoursePrice());
|
|
|
+ studentPayment.setActualPrice(courseGroup.getCoursePrice());
|
|
|
studentPayment.setCreatedTime(now);
|
|
|
studentPayment.setUpdatedTime(now);
|
|
|
- studentPayment.setCourseType(liveCourseGroup.getType());
|
|
|
+ studentPayment.setCourseType(courseGroup.getType());
|
|
|
studentPaymentList.add(studentPayment);
|
|
|
});
|
|
|
courseScheduleStudentPaymentService.getDao().insertBatch(studentPaymentList);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 学生购买直播课程成功-回调成功
|
|
|
+ * 学生购买直播课程-成功-回调
|
|
|
*/
|
|
|
- public void buyLiveCourseSuccess() {
|
|
|
- //写course_group表 pre_student_num_(预计上课人数) +1
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void buyLiveCourseSuccess(String orderNo) {
|
|
|
+ //更新课程组的购买人数+1
|
|
|
+ CourseScheduleStudentPayment studentPayment = courseScheduleStudentPaymentService.getOne(Wrappers.<CourseScheduleStudentPayment>lambdaQuery()
|
|
|
+ .eq(CourseScheduleStudentPayment::getOrderNo, orderNo)
|
|
|
+ );
|
|
|
+ if (Objects.isNull(studentPayment)) {
|
|
|
+ throw new BizException("订单不存在!");
|
|
|
+ }
|
|
|
+ //更新课程组的购买人数+1
|
|
|
+ this.baseMapper.opsPreStudentNum(studentPayment.getCourseGroupId(), 1);
|
|
|
+ //课程组信息
|
|
|
+ CourseGroup courseGroup = this.getOne(Wrappers.<CourseGroup>lambdaQuery()
|
|
|
+ .eq(CourseGroup::getId, studentPayment.getCourseGroupId()));
|
|
|
+ //课程信息
|
|
|
+ List<CourseSchedule> courseList = courseScheduleService.list(Wrappers.<CourseSchedule>lambdaQuery()
|
|
|
+ .eq(CourseSchedule::getCourseGroupId, studentPayment.getCourseGroupId()));
|
|
|
+ //计算课程组单节课价格 取CourseScheduleStudentPayment expectPrice
|
|
|
+ BigDecimal expectPrice = studentPayment.getExpectPrice();
|
|
|
+ //查询直播课服务费
|
|
|
+ String liveServiceRateStr = sysConfigService.findConfigValue(SysConfigConstant.LIVE_SERVICE_RATE);
|
|
|
+ BigDecimal liveServiceRate = new BigDecimal(liveServiceRateStr).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
|
|
|
+ //获取每节课的课酬 key 课堂数 value 课酬
|
|
|
+ Map<Integer, BigDecimal> singerCourseSalary = getSingerCourseSalary(expectPrice, courseGroup.getCourseNum(), liveServiceRate);
|
|
|
//写入课酬表计算-根据课程组总金额计算分配到每节课的金额
|
|
|
- //修改订单为成功
|
|
|
+ Date now = new Date();
|
|
|
+ List<CourseScheduleTeacherSalary> teacherSalaryList = new ArrayList<>();
|
|
|
+ courseList.forEach(course -> {
|
|
|
+ CourseScheduleTeacherSalary teacherSalary = new CourseScheduleTeacherSalary();
|
|
|
+ teacherSalary.setTeacherId(course.getTeacherId());
|
|
|
+ teacherSalary.setStudentId(course.getTeacherId());
|
|
|
+ teacherSalary.setCourseScheduleId(course.getId());
|
|
|
+ teacherSalary.setCourseGroupType(course.getType());
|
|
|
+ teacherSalary.setCourseGroupId(course.getCourseGroupId());
|
|
|
+ teacherSalary.setClassNum(course.getClassNum());
|
|
|
+ teacherSalary.setExpectSalary(singerCourseSalary.get(course.getClassNum()));
|
|
|
+ teacherSalary.setReduceSalary(BigDecimal.ZERO);
|
|
|
+ teacherSalary.setCreateTime(now);
|
|
|
+ teacherSalary.setStatus(TeacherSalaryEnum.NOT_START.getCode());
|
|
|
+ teacherSalaryList.add(teacherSalary);
|
|
|
+ });
|
|
|
+ courseScheduleTeacherSalaryService.getDao().insertBatch(teacherSalaryList);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 学生购买直播课失败-回调
|
|
|
+ * 学生购买直播课程,计算每节课课酬
|
|
|
+ *
|
|
|
+ * @param totalPrice 课酬总金额
|
|
|
+ * @param totalCourseNum 课程总数
|
|
|
+ * @param rate 课酬费率
|
|
|
+ * @return key 课堂数 value 课酬
|
|
|
+ */
|
|
|
+ private Map<Integer, BigDecimal> getSingerCourseSalary(BigDecimal totalPrice, Integer totalCourseNum, BigDecimal rate) {
|
|
|
+ //1 - (1 * 手续费率)
|
|
|
+ BiFunction<BigDecimal, BigDecimal, BigDecimal> getPrice = (p, r) -> p.subtract(p.multiply(r)).setScale(2, RoundingMode.HALF_UP);
|
|
|
+ //总课酬
|
|
|
+ BigDecimal totalRatePrice = getPrice.apply(totalPrice, rate);
|
|
|
+ //每节课累计总额
|
|
|
+ BigDecimal cumulativeAmount = BigDecimal.ZERO;
|
|
|
+ //每节课的课酬
|
|
|
+ BigDecimal singerSalary = totalRatePrice.divide(BigDecimal.valueOf(totalCourseNum), 2, RoundingMode.HALF_UP);
|
|
|
+ Map<Integer, BigDecimal> map = new HashMap<>();
|
|
|
+ for (int i = 1; i <= totalCourseNum; i++) {
|
|
|
+ //最后一节课,直接用总课酬减去累计课酬
|
|
|
+ if (i == totalCourseNum) {
|
|
|
+ singerSalary = totalRatePrice.subtract(cumulativeAmount);
|
|
|
+ }
|
|
|
+ cumulativeAmount = cumulativeAmount.add(singerSalary);
|
|
|
+ map.put(i, singerSalary);
|
|
|
+ }
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 学生购买直播课-失败-回调
|
|
|
*/
|
|
|
- public void buyLiveCourseFailed() {
|
|
|
- //修改 course_group表 pre_student_num_(预计上课人数) - 1
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void buyLiveCourseFailed(String orderNo) {
|
|
|
//删除 course_schedule_student_payment表 数据
|
|
|
+
|
|
|
+
|
|
|
//修改订单为失败
|
|
|
}
|
|
|
|