package com.ym.mec.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.entity.StudentApplyRefunds.StudentApplyRefundsStatus;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.*;
import com.ym.mec.biz.event.source.SendSeoMessageSource;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.constant.CommonConstants;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateConvertor;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.string.MessageFormatter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.enums.GroupType.VIP;
import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;
import static java.math.BigDecimal.ROUND_DOWN;
import static java.math.BigDecimal.ZERO;

@Service
public class VipGroupServiceImpl extends BaseServiceImpl<Long, VipGroup> implements VipGroupService {

    @Autowired
    private VipGroupDao vipGroupDao;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
    @Autowired
    @Lazy
    private CourseScheduleService courseScheduleService;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private VipGroupDefaultClassesUnitPriceDao vipGroupDefaultClassesUnitPriceDao;
    @Autowired
    private VipGroupActivityDao vipGroupActivityDao;
    @Autowired
    private VipGroupCategoryService vipGroupCategoryService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private TeacherDefaultVipGroupSalaryDao teacherDefaultVipGroupSalaryDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private StudentApplyRefundsDao studentApplyRefundsDao;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserCashAccountDetailDao sysUserCashAccountDetailDao;
    @Autowired
    private SysUserCashAccountLogDao sysUserCashAccountLogDao;
    @Autowired
    private ClassGroupTeacherSalaryDao classGroupTeacherSalaryDao;
    @Autowired
    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
    @Autowired
    private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
    @Autowired
    private ImGroupMemberService imGroupMemberService;
    @Autowired
    private ImUserFriendService imUserFriendService;
    @Autowired
    private ImGroupService imGroupService;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    @Lazy
    private CourseScheduleTeacherSalaryService courseScheduleTeacherSalaryService;
    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;
    @Autowired
    private PayService payService;
    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private SendSeoMessageSource sendSeoMessageSource;
    @Autowired
    private VipGroupDefaultClassesCycleDao vipGroupDefaultClassesCycleDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private TeacherAttendanceDao teacherAttendanceDao;
    @Autowired
    private ClassGroupService classGroupService;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    @Lazy
    private ContractService contractService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private StudentPauseInfoDao studentPauseInfoDao;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private StudentAttendanceDao studentAttendanceDao;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private GroupDao groupDao;
    @Autowired
    private TeacherCourseRewardService teacherCourseRewardService;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private GroupClassService groupClassService;
    @Autowired
    private StudentPaymentRouteOrderService studentPaymentRouteOrderService;
    @Autowired
    private VipGroupStudentCoursePriceDao vipGroupStudentCoursePriceDao;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private SysTenantConfigService sysTenantConfigService;
    @Autowired
    private SysCouponCodeService sysCouponCodeService;
    @Autowired
    private ActivityUserMapperService activityUserMapperService;
    @Autowired
    private PracticeGroupService practiceGroupService;
    @Autowired
    private SysUserCashAccountLogService sysUserCashAccountLogService;

    private static final Logger LOGGER = LoggerFactory
            .getLogger(VipGroup.class);

    @Override
    public BaseDAO<Long, VipGroup> getDAO() {
        return vipGroupDao;
    }

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    @Override
    public HttpResponseResult createVipGroup(VipGroupApplyDto vipGroup) {

        if (Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getUserId())) {
            throw new BizException("请选择指导老师");
        }

        if (vipGroup.getCourseSchedules().size() != (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() + vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum())) {
            throw new BizException("建课失败，当前课程存在未排课课程，请调整相关设置");
        }

        Map<TeachModeEnum, List<CourseSchedule>> courseScheduleGroup;
        try {
            courseScheduleGroup = vipGroup.getCourseSchedules().stream().collect(Collectors.groupingBy(CourseSchedule::getTeachMode));
        } catch (Exception e) {
            throw new BizException("教学模式错误");
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && (courseScheduleGroup.get(TeachModeEnum.OFFLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum()))) {
            throw new BizException("线下课课时数量安排有误");
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && (courseScheduleGroup.get(TeachModeEnum.ONLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum()))) {
            throw new BizException("线上课课时数量安排有误");
        }

        if (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() > 0
                && Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId())) {
            throw new BizException("请设置教学点");
        }

        Date now = new Date();

        VipGroupApplyBaseInfoDto vipGroupApplyBaseInfoDto = vipGroup.getVipGroupApplyBaseInfo();

        if (Objects.isNull(vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice())
                && Objects.isNull(vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice())) {
            throw new BizException("请设置课程单价");
        }

        if (StringUtils.isBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            throw new BizException("请选择学员");
        }
        //校验机构可排线上课人数上线
        if (vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum() > 0) {
            courseScheduleService.checkOnlineCategory(vipGroupApplyBaseInfoDto.getStudentNum());
        }

        if (Objects.isNull(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary())) {
            throw new BizException("请设置教师课酬");
        }

        Integer totalClassTimes = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
        //获取第一节课
        CourseSchedule firstCourseSchedule = vipGroup.getCourseSchedules().stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
        //获取最后一节课
        CourseSchedule latestCourseSchedule = vipGroup.getCourseSchedules().stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();

        if (firstCourseSchedule.getStartClassTime().before(now)) {
            throw new BizException("开课时间不能小于当前时间");
        }

        if (vipGroupApplyBaseInfoDto.getRegistrationStartTime().after(vipGroupApplyBaseInfoDto.getPaymentExpireDate())) {
            throw new BizException("报名开始时间必须在报名截至时间之前");
        }

        if (vipGroupApplyBaseInfoDto.getPaymentExpireDate().after(firstCourseSchedule.getStartClassTime())
                || DateUtil.isSameDay(vipGroupApplyBaseInfoDto.getPaymentExpireDate(), firstCourseSchedule.getEndClassTime())) {
            throw new BizException("创建失败，报名截止时间必须在开课时间前一天");
        }

        List<Integer> canBuyStudentIds = Arrays.stream(vipGroupApplyBaseInfoDto.getStudentIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());
        List<VipGroupStudentCoursePrice> vscps = vipGroup.getVipGroupApplyBaseInfo().getVipGroupStudentCoursePrices();

        //获取活动信息
        VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupApplyBaseInfo().getVipGroupActivityId());
        if (!vipGroup.getAllowOverstepActivityStudentNum() && Objects.nonNull(vipGroupActivity)
                && Objects.nonNull(vipGroupActivity.getStudentMaxUsedTimes()) && vipGroupActivity.getStudentMaxUsedTimes() != -1 &&

                StringUtils.isNotBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            List<String> tempStudentIds = Arrays.asList(vipGroupApplyBaseInfoDto.getStudentIdList().split(","));
            List<Integer> errStudentIds = new ArrayList<>();
            for (String studentIdStr : tempStudentIds) {
                int useNum = activityUserMapperService.countActivityBuyNum(vipGroupActivity.getId(), Integer.valueOf(studentIdStr));
                if (useNum >= vipGroupActivity.getStudentMaxUsedTimes()) {
                    errStudentIds.add(Integer.valueOf(studentIdStr));
                }
            }
            if (errStudentIds.size() > 0) {
                List<SimpleUserDto> students = teacherDao.getUsersSimpleInfo(errStudentIds);
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                String studentNames = StringUtils.join(students.stream().map(SimpleUserDto::getNickName).collect(Collectors.toList()), "、");
                throw new BizException("该活动{}学员已超过该活动购买次数限制", studentNames);
            }
        }
        //判断课程安排是否超出范围
        if (Objects.nonNull(vipGroupActivity) && (Objects.nonNull(vipGroupActivity.getCoursesEndTime()) || Objects.nonNull(vipGroupActivity.getCoursesStartTime()))) {
            if (latestCourseSchedule.getEndClassTime().after(vipGroupActivity.getCoursesEndTime())
                    || firstCourseSchedule.getStartClassTime().before(vipGroupActivity.getCoursesStartTime())) {
                throw new BizException("课时安排时间超出范围!");
            }
        } else {
            VipGroupDefaultClassesCycle vipGroupDefaultClassesCycle = vipGroupDefaultClassesCycleDao.findByOrganAndClassTimes(totalClassTimes, TenantContextHolder.getTenantId());

            if (vipGroupDefaultClassesCycle != null) {
                int month = DateUtil.monthsBetween(firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
                if (month > vipGroupDefaultClassesCycle.getMonth()) {
                    throw new BizException("课时安排时间超出范围!");
                }
            }
        }

        if (Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getMinCourseNum()) && vipGroupActivity.getMinCourseNum() != -1 && Objects.nonNull(vipGroupActivity.getMaxCourseNum()) && vipGroupActivity.getMaxCourseNum() != -1) {
            Integer requestCourseNum = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
            if (requestCourseNum.compareTo(vipGroupActivity.getMinCourseNum()) < 0 || requestCourseNum.compareTo(vipGroupActivity.getMaxCourseNum()) > 0) {
                throw new BizException("该活动课时数为{}节~{}节", vipGroupActivity.getMinCourseNum(), vipGroupActivity.getMaxCourseNum());
            }
        }

        int repeatVipGroups = vipGroupDao.countUserRepeatVipGroupInCourseStartEndTime(vipGroupApplyBaseInfoDto.getUserId(), firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
        if (repeatVipGroups > 0) {
            throw new BizException("请勿重复提交");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroupApplyBaseInfoDto.getVipGroupCategoryId());
        if (Objects.isNull(vipGroupCategory)) {
            throw new BizException("课程形式不存在");
        }
        List<String> studentNames = studentDao.getStudentNames(canBuyStudentIds);

        //生成vip课信息
        List<String> bySubIds = subjectDao.findBySubIds(vipGroupApplyBaseInfoDto.getSubjectIdList());
        StringBuffer className = new StringBuffer();
        if (Objects.isNull(vipGroupCategory.getMusicTheory()) || !vipGroupCategory.getMusicTheory()) {
            className.append(StringUtils.join(bySubIds, ","));
            className.append(vipGroupCategory.getName());
        } else {
            className.append("乐理课•");
        }
        className.append(StringUtils.join(studentNames, ","));
        vipGroupApplyBaseInfoDto.setName(className.toString());
        vipGroupDao.insert(vipGroupApplyBaseInfoDto);
        //计算课程相关费用信息
        Map<String, BigDecimal> costInfo = countVipGroupPredictFee1(vipGroupApplyBaseInfoDto,
                vipGroupApplyBaseInfoDto.getUserId(), null);

        vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.PASS);

        vipGroupApplyBaseInfoDto.setStatus(VipGroupStatusEnum.APPLYING);
        //如果默认课酬与实际课酬不匹配则需要审批
//		if(costInfo.get("offlineTeacherSalary").compareTo(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary()) < 0){
//			vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.ING);
//		}

        vipGroupApplyBaseInfoDto.setTotalPrice(costInfo.get("totalPrice"));
        if (CollectionUtils.isEmpty(vscps)) {
            vscps = new ArrayList<>();
            for (Integer canBuyStudentId : canBuyStudentIds) {
                vscps.add(new VipGroupStudentCoursePrice(canBuyStudentId, vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getTotalPrice()));
            }
        }
        //开课时间为排课的第一节课的开始时间
        vipGroupApplyBaseInfoDto.setCourseStartDate(firstCourseSchedule.getStartClassTime());
        //课程结束时间为排课的最后一节课的结束时间
        vipGroupApplyBaseInfoDto.setCoursesExpireDate(latestCourseSchedule.getEndClassTime());

        vipGroupApplyBaseInfoDto.setPaymentExpireDate(DateUtil.getLastSecondWithDay(vipGroupApplyBaseInfoDto.getPaymentExpireDate()));

        if (vipGroup.getOnlyProgress()) {
            vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.PASS);
        }

        vscps.forEach(e -> e.setVipGroupId(vipGroupApplyBaseInfoDto.getId()));
        vipGroupStudentCoursePriceDao.batchInsert(vscps);

        vipGroup.getVipGroupApplyBaseInfo().setId(vipGroupApplyBaseInfoDto.getId());

        //创建班级信息
        ClassGroup classGroup = new ClassGroup();
        classGroup.setSubjectIdList(vipGroupApplyBaseInfoDto.getSubjectIdList());
        //如果是乐理课实际人数为所选学员数量
        if (vipGroupCategory.getMusicTheory()) {
            classGroup.setExpectStudentNum(canBuyStudentIds.size());
        } else {
            classGroup.setExpectStudentNum(vipGroupCategory.getStudentNum());
        }
        classGroup.setStudentNum(0);
        classGroup.setName(vipGroupApplyBaseInfoDto.getName());
        classGroup.setTotalClassTimes(totalClassTimes);
        classGroup.setType(ClassGroupTypeEnum.VIP);
        classGroup.setDelFlag(1);
        classGroup.setGroupType(GroupType.VIP);
        classGroup.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroup.setCreateTime(now);
        classGroup.setUpdateTime(now);
        classGroupDao.insert(classGroup);

        //创建班级老师关联记录
        ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
        classGroupTeacherMapper.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherMapper.setClassGroupId(classGroup.getId());
        classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherMapper.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherMapper.setGroupType(GroupType.VIP);
        classGroupTeacherMapper.setCreateTime(now);
        classGroupTeacherMapper.setUpdateTime(now);
        classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

        //创建班级与老师课酬记录
        ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
        classGroupTeacherSalary.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherSalary.setClassGroupId(classGroup.getId());
        classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherSalary.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherSalary.setSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setOnlineClassesSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setGroupType(GroupType.VIP);
        classGroupTeacherSalary.setCreateTime(now);
        classGroupTeacherSalary.setUpdateTime(now);
        classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);

        //课程信息调整
        List<CourseSchedule> courseSchedules = vipGroup.getCourseSchedules();
        courseSchedules.forEach(courseSchedule -> {
            courseSchedule.setGroupType(GroupType.VIP);
            courseSchedule.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
            if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                courseSchedule.setSchoolId(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId());
            }
            courseSchedule.setTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setActualTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setStatus(CourseStatusEnum.NOT_START);
            courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
            courseSchedule.setClassGroupId(classGroup.getId());
            courseSchedule.setName(vipGroupApplyBaseInfoDto.getName());
            courseSchedule.setOrganId(vipGroupApplyBaseInfoDto.getOrganId());
        });
        courseScheduleService.checkNewCourseSchedules(courseSchedules, false, false);
        vipGroupApplyBaseInfoDto.setCourseSchedulesJson(JSON.toJSONString(courseSchedules));
        vipGroupDao.update(vipGroupApplyBaseInfoDto);
        return BaseController.succeed(vipGroupApplyBaseInfoDto.getAuditStatus().getCode());
    }

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    @Override
    public HttpResponseResult createVipGroup1(VipGroupApplyDto vipGroup) {

        if (Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getUserId())) {
            throw new BizException("请选择指导老师");
        }

        if (vipGroup.getCourseSchedules().size() != (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() + vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum())) {
            throw new BizException("建课失败，当前课程存在未排课课程，请调整相关设置");
        }

        Map<TeachModeEnum, List<CourseSchedule>> courseScheduleGroup;
        try {
            courseScheduleGroup = vipGroup.getCourseSchedules().stream().collect(Collectors.groupingBy(CourseSchedule::getTeachMode));
        } catch (Exception e) {
            throw new BizException("教学模式错误");
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && (courseScheduleGroup.get(TeachModeEnum.OFFLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum()))) {
            throw new BizException("线下课课时数量安排有误");
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && (courseScheduleGroup.get(TeachModeEnum.ONLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum()))) {
            throw new BizException("线上课课时数量安排有误");
        }

        if (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() > 0
                && Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId())) {
            throw new BizException("请设置教学点");
        }

        String studentIds = vipGroup.getStudentIds();
        List<String> studentIdList = new ArrayList<>();
        if (StringUtils.isNotBlank(studentIds)) {
            studentIdList = Arrays.asList(studentIds.split(","));
        }

        Date now = new Date();

        VipGroupApplyBaseInfoDto vipGroupApplyBaseInfoDto = vipGroup.getVipGroupApplyBaseInfo();

        if (Objects.isNull(vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice())
                && Objects.isNull(vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice())) {
            throw new BizException("请设置课程单价");
        }

        if (StringUtils.isBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            throw new BizException("请选择学员");
        }

        if (Objects.isNull(Objects.isNull(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary()))) {
            throw new BizException("请设置教师课酬");
        }

        Integer totalClassTimes = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
        //获取第一节课
        CourseSchedule firstCourseSchedule = vipGroup.getCourseSchedules().stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
        //获取最后一节课
        CourseSchedule latestCourseSchedule = vipGroup.getCourseSchedules().stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();

        if (firstCourseSchedule.getStartClassTime().before(now)) {
            throw new BizException("开课时间不能小于当前时间");
        }

        if (vipGroupApplyBaseInfoDto.getRegistrationStartTime().after(vipGroupApplyBaseInfoDto.getPaymentExpireDate())) {
            throw new BizException("报名开始时间必须在报名截至时间之前");
        }

        if (vipGroupApplyBaseInfoDto.getPaymentExpireDate().after(firstCourseSchedule.getStartClassTime())
                || DateUtil.isSameDay(vipGroupApplyBaseInfoDto.getPaymentExpireDate(), firstCourseSchedule.getEndClassTime())) {
            throw new BizException("创建失败，报名截止时间必须在开课时间前一天");
        }

        List<Integer> canBuyStudentIds = Arrays.stream(vipGroupApplyBaseInfoDto.getStudentIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());
        List<VipGroupStudentCoursePrice> vscps = vipGroup.getVipGroupApplyBaseInfo().getVipGroupStudentCoursePrices();

        //获取活动信息
        VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupApplyBaseInfo().getVipGroupActivityId());
        if (!vipGroup.getAllowOverstepActivityStudentNum() && Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getStudentMaxUsedTimes()) && vipGroupActivity.getStudentMaxUsedTimes() != -1 && StringUtils.isNotBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            List<String> tempStudentIds = Arrays.asList(vipGroupApplyBaseInfoDto.getStudentIdList().split(","));
            List<Integer> errStudentIds = new ArrayList<>();
            for (String studentIdStr : tempStudentIds) {
                int useNum = vipGroupDao.countStudentUserActivityNum(vipGroup.getVipGroupApplyBaseInfo().getVipGroupActivityId(), Integer.valueOf(studentIdStr));
                if (useNum >= vipGroupActivity.getStudentMaxUsedTimes()) {
                    errStudentIds.add(Integer.valueOf(studentIdStr));
                }
            }
            if (errStudentIds.size() > 0) {
                List<SimpleUserDto> students = teacherDao.getUsersSimpleInfo(errStudentIds);
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                String studentNames = StringUtils.join(students.stream().map(SimpleUserDto::getNickName).collect(Collectors.toList()), "、");
                return BaseController.failed(HttpStatus.PARTIAL_CONTENT, "该活动" + studentNames + "学员创建及成课之和已达上限，是否继续创建该课程？");
            }
        }
        //判断课程安排是否超出范围
        if (Objects.nonNull(vipGroupActivity) && (Objects.nonNull(vipGroupActivity.getCoursesEndTime()) || Objects.nonNull(vipGroupActivity.getCoursesStartTime()))) {
            if (latestCourseSchedule.getEndClassTime().after(vipGroupActivity.getCoursesEndTime())
                    || firstCourseSchedule.getStartClassTime().before(vipGroupActivity.getCoursesStartTime())) {
                throw new BizException("课时安排时间超出范围!");
            }
        } else {
            VipGroupDefaultClassesCycle vipGroupDefaultClassesCycle = vipGroupDefaultClassesCycleDao.findByOrganAndClassTimes(totalClassTimes, TenantContextHolder.getTenantId());

            if (vipGroupDefaultClassesCycle != null) {
                int month = DateUtil.monthsBetween(firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
                if (month > vipGroupDefaultClassesCycle.getMonth()) {
                    throw new BizException("课时安排时间超出范围!");
                }
            }
        }

        if (Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getMinCourseNum()) && vipGroupActivity.getMinCourseNum() != -1 && Objects.nonNull(vipGroupActivity.getMaxCourseNum()) && vipGroupActivity.getMaxCourseNum() != -1) {
            Integer requestCourseNum = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
            if (requestCourseNum.compareTo(vipGroupActivity.getMinCourseNum()) < 0 || requestCourseNum.compareTo(vipGroupActivity.getMaxCourseNum()) > 0) {
                throw new BizException("该活动课时数为{}节~{}节", vipGroupActivity.getMinCourseNum(), vipGroupActivity.getMaxCourseNum());
            }
        }

        int repeatVipGroups = vipGroupDao.countUserRepeatVipGroupInCourseStartEndTime(vipGroupApplyBaseInfoDto.getUserId(), firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
        if (repeatVipGroups > 0) {
            throw new BizException("请勿重复提交");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroupApplyBaseInfoDto.getVipGroupCategoryId());
        if (Objects.isNull(vipGroupCategory)) {
            throw new BizException("课程形式不存在");
        }
        List<String> studentNames = studentDao.getStudentNames(canBuyStudentIds);

        //生成vip课信息
        List<String> bySubIds = subjectDao.findBySubIds(vipGroupApplyBaseInfoDto.getSubjectIdList());
        StringBuffer className = new StringBuffer();
        if (Objects.isNull(vipGroupCategory.getMusicTheory()) || !vipGroupCategory.getMusicTheory()) {
            className.append(StringUtils.join(bySubIds, ","));
            className.append(vipGroupCategory.getName());
        } else {
            className.append("乐理课•");
        }
        className.append(StringUtils.join(studentNames, ","));
        vipGroupApplyBaseInfoDto.setName(className.toString());

        //计算课程相关费用信息
        Map<String, BigDecimal> costInfo = countVipGroupPredictFee(vipGroupApplyBaseInfoDto,
                vipGroupApplyBaseInfoDto.getUserId());

        vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.PASS);

        //如果默认课酬与实际课酬不匹配则需要审批
        if (costInfo.get("offlineTeacherSalary").compareTo(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary()) < 0 && StringUtils.isBlank(studentIds)) {
            vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.ING);
        }

        vipGroupApplyBaseInfoDto.setTotalPrice(costInfo.get("totalPrice"));
        if (StringUtils.isNotBlank(studentIds)) {
            vipGroupApplyBaseInfoDto.setStatus(VipGroupStatusEnum.PROGRESS);
        } else {
            vipGroupApplyBaseInfoDto.setStatus(VipGroupStatusEnum.APPLYING);
        }
        if (CollectionUtils.isEmpty(vscps)) {
            vscps = new ArrayList<>();
            for (Integer canBuyStudentId : canBuyStudentIds) {
                vscps.add(new VipGroupStudentCoursePrice(canBuyStudentId, vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getTotalPrice()));
            }
        }
        Teacher teacher = teacherService.get(vipGroupApplyBaseInfoDto.getUserId());
        if (Objects.isNull(teacher)) {
            throw new BizException("教师不存在");
        }
        if (Objects.isNull(teacher.getTeacherOrganId())) {
            throw new BizException("教师部门异常");
        }
//        vipGroupApplyBaseInfoDto.setOrganId(Integer.parseInt(teacher.getOrganId()));
        //开课时间为排课的第一节课的开始时间
        vipGroupApplyBaseInfoDto.setCourseStartDate(firstCourseSchedule.getStartClassTime());
        //课程结束时间为排课的最后一节课的结束时间
        vipGroupApplyBaseInfoDto.setCoursesExpireDate(latestCourseSchedule.getEndClassTime());

        vipGroupApplyBaseInfoDto.setPaymentExpireDate(DateUtil.getLastSecondWithDay(vipGroupApplyBaseInfoDto.getPaymentExpireDate()));

        VipGroupDefaultClassesUnitPrice vipGroupDefaultClassesUnitPrice = vipGroupDefaultClassesUnitPriceDao.getByVipGroupCategory(vipGroup.getVipGroupApplyBaseInfo().getVipGroupCategoryId(), vipGroup.getVipGroupApplyBaseInfo().getOrganId());

        if (Objects.isNull(vipGroupDefaultClassesUnitPrice)) {
            vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.ING);
        } else {
            if (Objects.nonNull(vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice())
                    && vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice().compareTo(vipGroupDefaultClassesUnitPrice.getOfflineClassesUnitPrice()) != 0) {
                vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.ING);
            }
            if (Objects.nonNull(vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice())
                    && vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice().compareTo(vipGroupDefaultClassesUnitPrice.getOnlineClassesUnitPrice()) != 0) {
                vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.ING);
            }
        }

        if (StringUtils.isBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            vipGroupApplyBaseInfoDto.setStudentIdList(StringUtils.join(vscps.stream().map(VipGroupStudentCoursePrice::getStudentId).collect(Collectors.toList()), ","));
        }

        if (vipGroup.getOnlyProgress()) {
            vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.PASS);
        }

        vipGroupDao.insert(vipGroupApplyBaseInfoDto);

        vscps.forEach(e -> e.setVipGroupId(vipGroupApplyBaseInfoDto.getId()));
        vipGroupStudentCoursePriceDao.batchInsert(vscps);

        vipGroup.getVipGroupApplyBaseInfo().setId(vipGroupApplyBaseInfoDto.getId());

        //创建班级信息
        ClassGroup classGroup = new ClassGroup();
        classGroup.setSubjectIdList(vipGroupApplyBaseInfoDto.getSubjectIdList());
        classGroup.setExpectStudentNum(vipGroupCategory.getStudentNum());
        if (StringUtils.isNotBlank(studentIds)) {
            classGroup.setStudentNum(studentIdList.size());
        }
        classGroup.setName(vipGroupApplyBaseInfoDto.getName());
        classGroup.setExpectStudentNum(vipGroupApplyBaseInfoDto.getStudentNum());
        classGroup.setTotalClassTimes(totalClassTimes);
        classGroup.setType(ClassGroupTypeEnum.VIP);
        classGroup.setDelFlag(1);
        classGroup.setGroupType(GroupType.VIP);
        classGroup.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroup.setCreateTime(now);
        classGroup.setUpdateTime(now);
        classGroupDao.insert(classGroup);

        //创建班级老师关联记录
        ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
        classGroupTeacherMapper.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherMapper.setClassGroupId(classGroup.getId());
        classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherMapper.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherMapper.setGroupType(GroupType.VIP);
        classGroupTeacherMapper.setCreateTime(now);
        classGroupTeacherMapper.setUpdateTime(now);
        classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

        //创建班级与老师课酬记录
        ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
        classGroupTeacherSalary.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherSalary.setClassGroupId(classGroup.getId());
        classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherSalary.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherSalary.setSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setOnlineClassesSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setGroupType(GroupType.VIP);
        classGroupTeacherSalary.setCreateTime(now);
        classGroupTeacherSalary.setUpdateTime(now);
        classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);

        //课程信息调整
        vipGroup.getCourseSchedules().forEach(courseSchedule -> {
            courseSchedule.setGroupType(GroupType.VIP);
            courseSchedule.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
            if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                courseSchedule.setSchoolId(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId());
            }
            courseSchedule.setTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setActualTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setStatus(CourseStatusEnum.NOT_START);
            courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
            courseSchedule.setClassGroupId(classGroup.getId());
            courseSchedule.setName(vipGroupApplyBaseInfoDto.getName());
            courseSchedule.setOrganId(vipGroupApplyBaseInfoDto.getOrganId());
        });
        courseScheduleService.checkNewCourseSchedules(vipGroup.getCourseSchedules(), false, false);
        vipGroupApplyBaseInfoDto.setCourseSchedulesJson(JSON.toJSONString(vipGroup.getCourseSchedules()));
        vipGroupDao.update(vipGroupApplyBaseInfoDto);

        if (StringUtils.isNotBlank(studentIds)) {
            List<Integer> collect = studentIdList.stream().mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
            classGroupService.addStudentIntoClassGroup(vipGroupApplyBaseInfoDto.getId().toString(), classGroup.getId(), collect);
            createVipGroupCourseScheInfo(vipGroupApplyBaseInfoDto.getId(), classGroup);
        }

        if (Objects.isNull(teacher)) {
            throw new BizException("该用户不存在");
        }
        Map<String, Long> memo = new HashMap<>(1);
        memo.put("vipGroupId", vipGroupApplyBaseInfoDto.getId());
        sendSeoMessageSource.sendSeoMessage(teacher.getTeacherOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                JSONObject.toJSONString(memo), vipGroupApplyBaseInfoDto.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_TEACHER_APPLY_VIP, teacher.getRealName());
        return BaseController.succeed(vipGroupApplyBaseInfoDto.getAuditStatus().getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public HttpResponseResult createActivityVipGroup(VipGroupApplyDto vipGroup) {
        if (Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getUserId())) {
            throw new BizException("请选择指导老师");
        }

        if (vipGroup.getCourseSchedules().size() != (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() + vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum())) {
            throw new BizException("建课失败，当前课程存在未排课课程，请调整相关设置");
        }

        Map<TeachModeEnum, List<CourseSchedule>> courseScheduleGroup;
        try {
            courseScheduleGroup = vipGroup.getCourseSchedules().stream().collect(Collectors.groupingBy(CourseSchedule::getTeachMode));
        } catch (Exception e) {
            throw new BizException("教学模式错误");
        }

        if (StringUtils.isBlank(vipGroup.getVipGroupApplyBaseInfo().getSubjectIdList())) {
            throw new BizException("请选择声部");
        }

        if (ActivityCourseType.FREE_VIP.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
            List<VipGroupCategory> vipGroupCategories = vipGroupCategoryService.findAllByOrgan(vipGroup.getVipGroupApplyBaseInfo().getOrganId().toString());
            VipGroupCategory vipGroupCategory = vipGroupCategories.stream().filter(v -> v.getName().equals("1v2")).findFirst().get();
            vipGroup.getVipGroupApplyBaseInfo().setVipGroupCategoryId(vipGroupCategory.getId());
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.OFFLINE)) && (courseScheduleGroup.get(TeachModeEnum.OFFLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum()))) {
            throw new BizException("线下课课时数量安排有误");
        }

        if ((Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum() != 0)
                || (!Objects.isNull(courseScheduleGroup.get(TeachModeEnum.ONLINE)) && (courseScheduleGroup.get(TeachModeEnum.ONLINE).size() < vipGroup.getVipGroupApplyBaseInfo().getOnlineClassesNum()))) {
            throw new BizException("线上课课时数量安排有误");
        }

        if (vipGroup.getVipGroupApplyBaseInfo().getOfflineClassesNum() > 0
                && Objects.isNull(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId())) {
            throw new BizException("请设置教学点");
        }

        String studentIds = vipGroup.getVipGroupApplyBaseInfo().getStudentIdList();
        if (StringUtils.isBlank(studentIds)) {
            throw new BizException("请选择学员");
        }
        List<Integer> studentIdList = Arrays.stream(studentIds.split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());

        List<Student> studentDetail = studentDao.lockStudents(studentIdList);
        List<SimpleUserDto> studentSimpleInfos = teacherDao.getUsersSimpleInfo(studentIdList);
        if (studentDetail.size() != studentSimpleInfos.size()) {
            throw new BizException("学员信息错误");
        }
        Map<Integer, SimpleUserDto> idUserInfoMap = studentSimpleInfos.stream().collect(Collectors.toMap(SimpleUserDto::getUserId, s -> s, (s1, s2) -> s1));
        Map<Integer, BigDecimal> studentTheoryPriceMap = new HashMap<>();
        for (Student student : studentDetail) {
            if (StringUtils.isEmpty(student.getActivityCourseDetail())) {
                SimpleUserDto studentInfo = idUserInfoMap.get(student.getUserId());
                throw new BizException("{}暂无排课资格", studentInfo.getNickName());
            }
            JSONObject courseDetail = JSON.parseObject(student.getActivityCourseDetail());
            Integer surplusTimes = courseDetail.getInteger(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType().getCode());
            if (surplusTimes <= 0) {
                SimpleUserDto studentInfo = idUserInfoMap.get(student.getUserId());
                throw new BizException("{}暂无排课资格", studentInfo.getNickName());
            }
            courseDetail.fluentPut(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType().getCode(), surplusTimes - 1);
            student.setActivityCourseDetail(courseDetail.toJSONString());
            if (ActivityCourseType.MUSIC_THEORY.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
                studentTheoryPriceMap.put(student.getUserId(), courseDetail.getBigDecimal("music_theory_price"));
            }
        }
        studentDao.batchUpdate(studentDetail);

        Date now = new Date();

        VipGroupApplyBaseInfoDto vipGroupApplyBaseInfoDto = vipGroup.getVipGroupApplyBaseInfo();

        if (Objects.isNull(vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice())
                && Objects.isNull(vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice())) {
            throw new BizException("请设置课程单价");
        }

        if (StringUtils.isBlank(vipGroupApplyBaseInfoDto.getStudentIdList())) {
            throw new BizException("请选择学员");
        }

        Integer totalClassTimes = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
        //获取第一节课
        CourseSchedule firstCourseSchedule = vipGroup.getCourseSchedules().stream().min(Comparator.comparing(CourseSchedule::getStartClassTime)).get();
        //获取最后一节课
        CourseSchedule latestCourseSchedule = vipGroup.getCourseSchedules().stream().max(Comparator.comparing(CourseSchedule::getEndClassTime)).get();

        if (firstCourseSchedule.getStartClassTime().before(now)) {
            throw new BizException("开课时间不能小于当前时间");
        }

        vipGroupApplyBaseInfoDto.setRegistrationStartTime(now);
        vipGroupApplyBaseInfoDto.setPaymentExpireDate(now);

        if (vipGroupApplyBaseInfoDto.getRegistrationStartTime().after(vipGroupApplyBaseInfoDto.getPaymentExpireDate())) {
            throw new BizException("报名开始时间必须在报名截至时间之前");
        }

        List<Integer> canBuyStudentIds = Arrays.stream(vipGroupApplyBaseInfoDto.getStudentIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());
        List<VipGroupStudentCoursePrice> vscps = vipGroup.getVipGroupApplyBaseInfo().getVipGroupStudentCoursePrices();

        //获取活动信息
        VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupApplyBaseInfo().getVipGroupActivityId());
//		if(!vipGroup.getAllowOverstepActivityStudentNum()&&Objects.nonNull(vipGroupActivity)&&Objects.nonNull(vipGroupActivity.getStudentMaxUsedTimes())&&vipGroupActivity.getStudentMaxUsedTimes()!=-1&&StringUtils.isNotBlank(vipGroupApplyBaseInfoDto.getStudentIdList())){
//			List<String> tempStudentIds = Arrays.asList(vipGroupApplyBaseInfoDto.getStudentIdList().split(","));
//			List<Integer> errStudentIds = new ArrayList<>();
//			for (String studentIdStr : tempStudentIds) {
//				int useNum = vipGroupDao.countStudentUserActivityNum(vipGroup.getVipGroupApplyBaseInfo().getVipGroupActivityId(), Integer.valueOf(studentIdStr));
//				if(useNum>=vipGroupActivity.getStudentMaxUsedTimes()){
//					errStudentIds.add(Integer.valueOf(studentIdStr));
//				}
//			}
//			if(errStudentIds.size()>0){
//				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//				String studentNames = StringUtils.join(studentSimpleInfos.stream().map(SimpleUserDto::getNickName).collect(Collectors.toList()), "、");
//				return BaseController.failed(HttpStatus.PARTIAL_CONTENT,"该活动"+studentNames+"学员创建及成课之和已达上限，是否继续创建该课程？");
//			}
//		}
        //判断课程安排是否超出范围
        if (Objects.nonNull(vipGroupActivity) && (Objects.nonNull(vipGroupActivity.getCoursesEndTime()) || Objects.nonNull(vipGroupActivity.getCoursesStartTime()))) {
            if (latestCourseSchedule.getEndClassTime().after(vipGroupActivity.getCoursesEndTime())
                    || firstCourseSchedule.getStartClassTime().before(vipGroupActivity.getCoursesStartTime())) {
                throw new BizException("课时安排时间超出范围!");
            }
        } else {
            VipGroupDefaultClassesCycle vipGroupDefaultClassesCycle = vipGroupDefaultClassesCycleDao.findByOrganAndClassTimes(totalClassTimes, TenantContextHolder.getTenantId());

            if (vipGroupDefaultClassesCycle != null) {
                int month = DateUtil.monthsBetween(firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
                if (month > vipGroupDefaultClassesCycle.getMonth()) {
                    throw new BizException("课时安排时间超出范围!");
                }
            }
        }

        if (Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getMinCourseNum()) && vipGroupActivity.getMinCourseNum() != -1 && Objects.nonNull(vipGroupActivity.getMaxCourseNum()) && vipGroupActivity.getMaxCourseNum() != -1) {
            Integer requestCourseNum = vipGroupApplyBaseInfoDto.getOnlineClassesNum() + vipGroupApplyBaseInfoDto.getOfflineClassesNum();
            if (requestCourseNum.compareTo(vipGroupActivity.getMinCourseNum()) < 0 || requestCourseNum.compareTo(vipGroupActivity.getMaxCourseNum()) > 0) {
                throw new BizException("该活动课时数为{}节~{}节", vipGroupActivity.getMinCourseNum(), vipGroupActivity.getMaxCourseNum());
            }
        }

        int repeatVipGroups = vipGroupDao.countUserRepeatVipGroupInCourseStartEndTime(vipGroupApplyBaseInfoDto.getUserId(), firstCourseSchedule.getStartClassTime(), latestCourseSchedule.getEndClassTime());
        if (repeatVipGroups > 0) {
            SysUser sysUser = sysUserFeignService.queryUserById(vipGroupApplyBaseInfoDto.getUserId());
            throw new BizException("{}课程时间冲突({}-{})", sysUser.getRealName(), DateUtil.dateToString(firstCourseSchedule.getStartClassTime(), "yyyy-MM-dd HH:mm:ss"), DateUtil.dateToString(latestCourseSchedule.getEndClassTime(), "HH:mm:ss"));
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroupApplyBaseInfoDto.getVipGroupCategoryId());
        if (Objects.isNull(vipGroupCategory)) {
            throw new BizException("课程形式不存在");
        }
        List<String> studentNames = studentDao.getStudentNames(canBuyStudentIds);

        //生成vip课信息
        List<String> bySubIds = subjectDao.findBySubIds(vipGroupApplyBaseInfoDto.getSubjectIdList());
        StringBuffer className = new StringBuffer();
        if (ActivityCourseType.FREE_VIP.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
            className.append("体验课•");
        } else if (Objects.isNull(vipGroupCategory.getMusicTheory()) || !vipGroupCategory.getMusicTheory()) {
            className.append(StringUtils.join(bySubIds, ","));
            className.append(vipGroupCategory.getName());
        } else {
            className.append("乐理课•");
        }
        className.append(StringUtils.join(studentNames, ","));
        vipGroupApplyBaseInfoDto.setName(className.toString());

        vipGroupApplyBaseInfoDto.setAuditStatus(AuditStatusEnum.PASS);
        vipGroupApplyBaseInfoDto.setStatus(VipGroupStatusEnum.PROGRESS);

        if (CollectionUtils.isEmpty(vscps)) {
            vscps = new ArrayList<>();
            for (Integer canBuyStudentId : canBuyStudentIds) {
                vscps.add(new VipGroupStudentCoursePrice(canBuyStudentId, vipGroupApplyBaseInfoDto.getOnlineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getOfflineClassesUnitPrice(), vipGroupApplyBaseInfoDto.getTotalPrice()));
            }
        }
        Teacher teacher = teacherService.get(vipGroupApplyBaseInfoDto.getUserId());
        if (Objects.isNull(teacher)) {
            throw new BizException("教师不存在");
        }

        //开课时间为排课的第一节课的开始时间
        vipGroupApplyBaseInfoDto.setCourseStartDate(firstCourseSchedule.getStartClassTime());
        //课程结束时间为排课的最后一节课的结束时间
        vipGroupApplyBaseInfoDto.setCoursesExpireDate(latestCourseSchedule.getEndClassTime());

        vipGroupApplyBaseInfoDto.setPaymentExpireDate(DateUtil.getLastSecondWithDay(vipGroupApplyBaseInfoDto.getPaymentExpireDate()));

        vipGroupDao.insert(vipGroupApplyBaseInfoDto);

        vscps.forEach(e -> e.setVipGroupId(vipGroupApplyBaseInfoDto.getId()));
        vipGroupStudentCoursePriceDao.batchInsert(vscps);

        vipGroup.getVipGroupApplyBaseInfo().setId(vipGroupApplyBaseInfoDto.getId());

        //创建班级信息
        ClassGroup classGroup = new ClassGroup();
        classGroup.setSubjectIdList(vipGroupApplyBaseInfoDto.getSubjectIdList());
        classGroup.setExpectStudentNum(vipGroupCategory.getStudentNum());
        classGroup.setStudentNum(studentIdList.size());
        classGroup.setName(vipGroupApplyBaseInfoDto.getName());
        classGroup.setTotalClassTimes(totalClassTimes);
        classGroup.setType(ClassGroupTypeEnum.VIP);
        classGroup.setDelFlag(0);
        classGroup.setGroupType(GroupType.VIP);
        classGroup.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroup.setCreateTime(now);
        classGroup.setUpdateTime(now);
        classGroupDao.insert(classGroup);

        //班级学员关联记录
        List<ClassGroupStudentMapper> classGroupStudentMapperList = new ArrayList<>();
        for (Integer studentId : studentIdList) {
            ClassGroupStudentMapper classGroupStudentMapper = new ClassGroupStudentMapper();
            classGroupStudentMapper.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
            classGroupStudentMapper.setClassGroupId(classGroup.getId());
            classGroupStudentMapper.setUserId(studentId);
            classGroupStudentMapper.setCreateTime(now);
            classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
            classGroupStudentMapper.setGroupType(GroupType.VIP);
            classGroupStudentMapperList.add(classGroupStudentMapper);
        }
        classGroupStudentMapperDao.classGroupStudentsInsert(classGroupStudentMapperList);

        if (!ActivityCourseType.FREE_VIP.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
            //计算课程相关费用信息
            Map<String, BigDecimal> costInfo = countVipGroupPredictFee1(vipGroupApplyBaseInfoDto,
                    vipGroupApplyBaseInfoDto.getUserId(), null);
            BigDecimal teacherSalary = costInfo.get("offlineTeacherSalary");
            //是否是赠送课程
            ActivityUserMapper activityUserMapper = activityUserMapperService.findVipUserMapper(vipGroupApplyBaseInfoDto.getId(), "VIP", null);
            if (activityUserMapper != null) {
                if (vipGroupApplyBaseInfoDto.getId().equals(activityUserMapper.getGiveVipGroupId())) {
                    teacherSalary = costInfo.get("giveOfflineTeacherSalary");
                }
            }
            vipGroupApplyBaseInfoDto.setOfflineTeacherSalary(teacherSalary);
            vipGroupApplyBaseInfoDto.setTotalPrice(costInfo.get("totalPrice"));
        } else {
            vipGroupApplyBaseInfoDto.setOfflineTeacherSalary(BigDecimal.ZERO);
            vipGroupApplyBaseInfoDto.setTotalPrice(BigDecimal.ZERO);
        }
        vipGroupDao.update(vipGroupApplyBaseInfoDto);

        //创建班级老师关联记录
        ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
        classGroupTeacherMapper.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherMapper.setClassGroupId(classGroup.getId());
        classGroupTeacherMapper.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherMapper.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherMapper.setGroupType(GroupType.VIP);
        classGroupTeacherMapper.setCreateTime(now);
        classGroupTeacherMapper.setUpdateTime(now);
        classGroupTeacherMapperDao.insert(classGroupTeacherMapper);

        //创建班级与老师课酬记录
        ClassGroupTeacherSalary classGroupTeacherSalary = new ClassGroupTeacherSalary();
        classGroupTeacherSalary.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
        classGroupTeacherSalary.setClassGroupId(classGroup.getId());
        classGroupTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
        classGroupTeacherSalary.setUserId(vipGroupApplyBaseInfoDto.getUserId());
        classGroupTeacherSalary.setSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setOnlineClassesSalary(vipGroupApplyBaseInfoDto.getOfflineTeacherSalary());
        classGroupTeacherSalary.setGroupType(GroupType.VIP);
        classGroupTeacherSalary.setCreateTime(now);
        classGroupTeacherSalary.setUpdateTime(now);
        classGroupTeacherSalaryDao.insert(classGroupTeacherSalary);

        //课程信息调整
        vipGroup.getCourseSchedules().forEach(courseSchedule -> {
            courseSchedule.setGroupType(GroupType.VIP);
            courseSchedule.setMusicGroupId(vipGroupApplyBaseInfoDto.getId().toString());
            if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                courseSchedule.setSchoolId(vipGroup.getVipGroupApplyBaseInfo().getTeacherSchoolId());
            }
            courseSchedule.setTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setActualTeacherId(vipGroupApplyBaseInfoDto.getUserId());
            courseSchedule.setStatus(CourseStatusEnum.NOT_START);
            courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
            courseSchedule.setClassGroupId(classGroup.getId());
            courseSchedule.setName(vipGroupApplyBaseInfoDto.getName());
            courseSchedule.setOrganId(vipGroupApplyBaseInfoDto.getOrganId());
        });

        vipGroupApplyBaseInfoDto.setCourseSchedulesJson(JSON.toJSONString(vipGroup.getCourseSchedules()));
        vipGroupDao.update(vipGroupApplyBaseInfoDto);

        //创建课程
        List<CourseSchedule> courseSchedules = vipGroup.getCourseSchedules();
        courseScheduleService.batchAddCourseSchedule(courseSchedules);
        //创建老师单节课课酬信息
        if (ActivityCourseType.FREE_VIP.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
            List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
            BigDecimal teacherDefaultSalary = new BigDecimal("16.67");
            SysConfig practiceCourseSalaryConfig = sysConfigService.findByParamName(SysConfigService.PRACTICE_COURSE_SALARY);
            if (Objects.nonNull(practiceCourseSalaryConfig) && StringUtils.isNotBlank(practiceCourseSalaryConfig.getParanValue())) {
                teacherDefaultSalary = new BigDecimal(practiceCourseSalaryConfig.getParanValue());
            }
            for (CourseSchedule courseSchedule : courseSchedules) {
                CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
                courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
                courseScheduleTeacherSalary.setGroupType(GroupType.VIP);
                courseScheduleTeacherSalary.setMusicGroupId(classGroup.getMusicGroupId());
                courseScheduleTeacherSalary.setTeacherRole(classGroupTeacherMapper.getTeacherRole());
                courseScheduleTeacherSalary.setUserId(vipGroupApplyBaseInfoDto.getTeacherId().intValue());
                courseScheduleTeacherSalary.setExpectSalary(teacherDefaultSalary);
                courseScheduleTeacherSalary.setCreateTime(now);
                courseScheduleTeacherSalary.setUpdateTime(now);
                courseScheduleTeacherSalary.setClassGroupId(classGroup.getId());
                courseScheduleTeacherSalary.setEnableChangeSalary(false);
                courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);
            }
            List<TeacherAttendance> teacherAttendances = new ArrayList<>();
            for (CourseScheduleTeacherSalary courseScheduleTeacherSalary : courseScheduleTeacherSalaries) {
                TeacherAttendance teacherAttendance = new TeacherAttendance();
                teacherAttendance.setGroupType(courseScheduleTeacherSalary.getGroupType());
                teacherAttendance.setClassGroupId(courseScheduleTeacherSalary.getClassGroupId());
                teacherAttendance.setMusicGroupId(courseScheduleTeacherSalary.getMusicGroupId());
                teacherAttendance.setTeacherId(courseScheduleTeacherSalary.getUserId());
                teacherAttendance.setCourseScheduleId(courseScheduleTeacherSalary.getCourseScheduleId());
                teacherAttendances.add(teacherAttendance);
            }
            courseScheduleTeacherSalaryDao.batchInsert(courseScheduleTeacherSalaries);
            if (!CollectionUtils.isEmpty(teacherAttendances)) {
                teacherAttendanceDao.batchInsert(teacherAttendances);
            }
        } else {
            courseScheduleTeacherSalaryService.createCourseScheduleTeacherVipSalary(vipGroupApplyBaseInfoDto,
                    courseSchedules,
                    classGroupTeacherSalary.getSalary());
        }

        SysUser sysUser = sysUserFeignService.queryUserById(vipGroupApplyBaseInfoDto.getUserId());

        List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentMapperDao.findByClassGroup(classGroup.getId());

        Map<Integer, String> userRoleMap = new HashMap<>();
        if (Objects.nonNull(vipGroupApplyBaseInfoDto.getEducationalTeacherId())) {
            userRoleMap.put(vipGroupApplyBaseInfoDto.getEducationalTeacherId(), "乐团主管");
        }
        userRoleMap.put(vipGroupApplyBaseInfoDto.getUserId(), "指导老师");
        //生成学生单课缴费信息
        for (ClassGroupStudentMapper classGroupStudent : classGroupStudents) {
            if (ActivityCourseType.FREE_VIP.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())
                    || ActivityCourseType.MUSIC_THEORY.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
                List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
                BigDecimal price = studentTheoryPriceMap.get(classGroupStudent.getUserId());
                BigDecimal coursePrice = BigDecimal.ZERO;
                if (Objects.nonNull(price)) {
                    coursePrice = price.divide(new BigDecimal(courseSchedules.size()), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP);
                }
                for (CourseSchedule courseSchedule : courseSchedules) {
                    CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
                    courseScheduleStudentPayment.setUserId(classGroupStudent.getUserId());
                    courseScheduleStudentPayment.setGroupType(courseSchedule.getGroupType());
                    courseScheduleStudentPayment.setMusicGroupId(courseSchedule.getMusicGroupId());
                    courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
                    courseScheduleStudentPayment.setClassGroupId(courseSchedule.getClassGroupId());
                    if (ActivityCourseType.MUSIC_THEORY.equals(vipGroup.getVipGroupApplyBaseInfo().getActivityCourseType())) {
                        courseScheduleStudentPayment.setExpectPrice(coursePrice);
                        courseScheduleStudentPayment.setOriginalPrice(coursePrice);
                    } else {
                        courseScheduleStudentPayment.setExpectPrice(BigDecimal.ZERO);
                        courseScheduleStudentPayment.setOriginalPrice(BigDecimal.ZERO);
                    }
                    courseScheduleStudentPayment.setActualPrice(courseScheduleStudentPayment.getExpectPrice());
                    courseScheduleStudentPayments.add(courseScheduleStudentPayment);
                }
                courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
            } else {
                courseScheduleStudentPaymentService.createCourseScheduleStudentPaymentForVipGroup(vipGroupApplyBaseInfoDto.getId(), classGroupStudent.getUserId());
            }
            userRoleMap.put(classGroupStudent.getUserId(), null);
            studentDao.updateStudentServiceTag(classGroupStudent.getUserId(), null, YesOrNoEnum.YES.getCode());
        }

//		courseScheduleService.checkNewCourseSchedules(courseSchedules, false,false);

        try {
            imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(), classGroup.getName(),
                    vipGroupApplyBaseInfoDto.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
            imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
            imUserFriendService.refreshGroupImUserFriend(classGroup.getMusicGroupId(), classGroup.getGroupType());
            //发送推送
            Map<Integer, String> map = new HashMap<>(1);
            map.put(vipGroupApplyBaseInfoDto.getUserId(), sysUser.getPhone());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.CHILDREN_DAY_VIP_COURSE_TEACHER_PUSH,
                    map, null, 0, "", "TEACHER", StringUtils.join(studentNames, ","), vipGroupApplyBaseInfoDto.getName());

            Map<Integer, String> studentIdStrMap = new HashMap<>(1);
            studentIdList.forEach(id -> studentIdStrMap.put(id, id.toString()));
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.CHILDREN_DAY_VIP_COURSE_STUDENT_PUSH, studentIdStrMap, null, 0, "", "STUDENT",
                    vipGroupApplyBaseInfoDto.getName());
        } catch (Exception e) {
            e.printStackTrace();
            LOGGER.error("消息发送失败：{}", e);
        }
        return BaseController.succeed(vipGroupApplyBaseInfoDto.getAuditStatus().getCode());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult importActivityVipGroup(String data) {
        if (StringUtils.isBlank(data)) {
            return BaseController.succeed();
        }
        List<JSONObject> datas = JSON.parseArray(data, JSONObject.class);
        Date date = new Date();
        for (JSONObject courseData : datas) {
            boolean skipHoliday = "是".equals(courseData.getString("skip_holiday")) ? true : false;
            String vipGroupActivityName = courseData.getString("vip_group_activity");
            String vipGroupCategoryStr = courseData.getString("vip_group_category");
            boolean freeCourse = "考前辅导课".equals(vipGroupCategoryStr);
            int courseMinute = freeCourse ? 25 : 45;
            String vipGroupCategoryName = "1v1".equals(vipGroupCategoryStr) ? "1v1" : "1v2";
            Integer schoolId = courseData.getInteger("school_id");
            int onlineCourseNum = StringUtils.isBlank(courseData.getString("online_course_num")) ? 0 : courseData.getIntValue("online_course_num");
            int onlineWeekNum = 0;
            if (onlineCourseNum > 0) {
                onlineWeekNum = courseData.getIntValue("online_course_week_num");
            }
            String onlineCourseStartTime = courseData.getString("online_course_start_time");
            int offlineCourseNum = StringUtils.isBlank(courseData.getString("offline_course_num")) ? 0 : courseData.getIntValue("offline_course_num");
            int offlineWeekNum = 0;
            if (offlineCourseNum > 0) {
                offlineWeekNum = courseData.getIntValue("offline_course_week_num");
            }
            String offlineCourseStartTime = courseData.getString("offline_course_start_time");
            int totalCourseNum = onlineCourseNum + offlineCourseNum;
            Integer teacherId = courseData.getInteger("teacher_id");
            Integer eduTeacherId = StringUtils.isBlank(courseData.getString("edu_teacher_id")) ? null : courseData.getInteger("edu_teacher_id");
            String studentIdsStr = courseData.getString("student_ids");
            if (StringUtils.isBlank(studentIdsStr)) {
                throw new BizException("请选择学员");
            }
            List<Integer> studentIds = Arrays.stream(studentIdsStr.split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
            SysUser student = studentDao.getUser(studentIds.get(0));
            Student stu = studentDao.get(studentIds.get(0));
            if (Objects.isNull(student)) {
                throw new BizException("学员信息异常");
            }

            List<VipGroupCategory> vipGroupCategories = vipGroupCategoryService.findAllByOrgan(student.getOrganId().toString());
            VipGroupCategory vipGroupCategory = vipGroupCategories.stream().filter(v -> v.getName().equals(vipGroupCategoryName)).findFirst().get();

            List<VipGroupActivity> vipGroupActivities = vipGroupActivityDao.findByName(vipGroupActivityName, TenantContextHolder.getTenantId());
            VipGroupActivity vipGroupActivity = null;
            if (!CollectionUtils.isEmpty(vipGroupActivities)) {
                vipGroupActivity = vipGroupActivities.get(0);
            }

            LocalDate courseStartDay = null;
            LocalDate onlineCourseStartDay = null;
            LocalDate offlineCourseStartDay = null;

            if (onlineCourseNum > 0) {
                onlineCourseStartDay = LocalDate.parse(courseData.getString("online_course_start_day").replace(" 00:00:00", ""), DateUtil.dateFormatter);
                courseStartDay = onlineCourseStartDay;
            }

            if (offlineCourseNum > 0) {
                offlineCourseStartDay = LocalDate.parse(courseData.getString("offline_course_start_day").replace(" 00:00:00", ""), DateUtil.dateFormatter);
                if (Objects.isNull(courseStartDay) || onlineCourseStartDay.compareTo(offlineCourseStartDay) > 0) {
                    courseStartDay = offlineCourseStartDay;
                }
            }

            Set<String> holidayDays = new HashSet<>();

            if (skipHoliday) {
                Integer tenantId = TenantContextHolder.getTenantId();
                String holidaySetting = sysTenantConfigService.getTenantConfigValue(SysConfigService.HOLIDAY_SETTING,tenantId);
                if(StringUtils.isNotBlank(holidaySetting)){
                    holidayDays = new HashSet<>(JSON.parseArray(holidaySetting, String.class));
                }
            }

            List<CourseSchedule> courseSchedules = new ArrayList<>();
            int onlineCourseNumCreated = 0;
            int offlineCourseNumCreated = 0;

            while (true) {
                if (skipHoliday && holidayDays.contains(courseStartDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")))) {
                    courseStartDay = courseStartDay.plusDays(1);
                    continue;
                }
                int dayOfWeek = courseStartDay.getDayOfWeek().getValue();//当前星期

                if (onlineCourseNumCreated < onlineCourseNum && (onlineWeekNum < 1 || onlineWeekNum > 7)) {
                    throw new BizException("排课循环周期错误，请核查");
                }
                if (onlineCourseNumCreated < onlineCourseNum && courseStartDay.compareTo(onlineCourseStartDay) >= 0 && dayOfWeek == onlineWeekNum) {
                    Date classDate = DateConvertor.toDate(courseStartDay);
                    String startClassTime = DateUtil.getDate(classDate) + " " + onlineCourseStartTime;
                    String endClassTime = DateUtil.dateToString(DateUtil.addMinutes(DateUtil.stringToDate(startClassTime, "yyyy-MM-dd HH:mm:ss"), courseMinute), "yyyy-MM-dd HH:mm:ss");

                    CourseSchedule courseSchedule = new CourseSchedule();
                    courseSchedule.setStatus(CourseStatusEnum.NOT_START);
                    courseSchedule.setClassDate(classDate);
                    courseSchedule.setStartClassTime(DateUtil.stringToDate(startClassTime));
                    courseSchedule.setEndClassTime(DateUtil.stringToDate(endClassTime));
                    courseSchedule.setCreateTime(date);
                    courseSchedule.setUpdateTime(date);
                    courseSchedule.setTeachMode(TeachModeEnum.ONLINE);
                    courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
                    courseSchedule.setGroupType(VIP);
                    courseSchedule.setOrganId(student.getOrganId());
                    courseSchedule.setTeacherId(teacherId);
                    courseSchedule.setActualTeacherId(teacherId);
                    courseSchedules.add(courseSchedule);

                    onlineCourseNumCreated++;
                }

                if (offlineCourseNumCreated < offlineCourseNum && (offlineWeekNum < 1 || offlineWeekNum > 7)) {
                    throw new BizException("排课循环周期错误，请核查");
                }
                if (offlineCourseNumCreated < offlineCourseNum && courseStartDay.compareTo(offlineCourseStartDay) >= 0 && dayOfWeek == offlineWeekNum) {
                    Date classDate = DateConvertor.toDate(courseStartDay);
                    String startClassTime = DateUtil.getDate(classDate) + " " + offlineCourseStartTime;
                    String endClassTime = DateUtil.dateToString(DateUtil.addMinutes(DateUtil.stringToDate(startClassTime, "yyyy-MM-dd HH:mm:ss"), courseMinute), "yyyy-MM-dd HH:mm:ss");

                    CourseSchedule courseSchedule = new CourseSchedule();
                    courseSchedule.setStatus(CourseStatusEnum.NOT_START);
                    courseSchedule.setClassDate(classDate);
                    courseSchedule.setStartClassTime(DateUtil.stringToDate(startClassTime));
                    courseSchedule.setEndClassTime(DateUtil.stringToDate(endClassTime));
                    courseSchedule.setCreateTime(date);
                    courseSchedule.setUpdateTime(date);
                    courseSchedule.setSchoolId(schoolId);
                    courseSchedule.setTeachMode(TeachModeEnum.OFFLINE);
                    courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
                    courseSchedule.setGroupType(VIP);
                    courseSchedule.setOrganId(student.getOrganId());
                    courseSchedule.setTeacherId(teacherId);
                    courseSchedule.setActualTeacherId(teacherId);
                    courseSchedules.add(courseSchedule);

                    offlineCourseNumCreated++;
                }

                if (courseSchedules.size() >= totalCourseNum) {
                    break;
                }

                courseStartDay = courseStartDay.plusDays(1);
            }

            VipGroupApplyDto vipGroupApplyDto = new VipGroupApplyDto();
            VipGroupApplyBaseInfoDto vipGroupApplyBaseInfoDto = new VipGroupApplyBaseInfoDto();
            vipGroupApplyBaseInfoDto.setStudentIdList(studentIdsStr);

            vipGroupApplyBaseInfoDto.setAllCourseNum(totalCourseNum);
            vipGroupApplyBaseInfoDto.setTeacherId(teacherId.longValue());
            vipGroupApplyBaseInfoDto.setEducationalTeacherId(eduTeacherId);
            vipGroupApplyBaseInfoDto.setSubjectIdList(stu.getSubjectIdList());
            vipGroupApplyBaseInfoDto.setFirstStudentId(studentIds.get(0));
            vipGroupApplyBaseInfoDto.setUserId(teacherId);
            vipGroupApplyBaseInfoDto.setSingleClassMinutes(courseMinute);
            vipGroupApplyBaseInfoDto.setRegistrationStartTime(date);
            vipGroupApplyBaseInfoDto.setPaymentExpireDate(date);
            vipGroupApplyBaseInfoDto.setCourseStartDate(courseSchedules.get(0).getStartClassTime());
            vipGroupApplyBaseInfoDto.setCoursesExpireDate(courseSchedules.get(courseSchedules.size() - 1).getEndClassTime());
            vipGroupApplyBaseInfoDto.setTeacherSchoolId(schoolId);
            vipGroupApplyBaseInfoDto.setOnlineClassesNum(onlineCourseNum);
            vipGroupApplyBaseInfoDto.setOfflineClassesNum(offlineCourseNum);
            vipGroupApplyBaseInfoDto.setVipGroupCategoryId(vipGroupCategory.getId());
            if (freeCourse) {
                vipGroupApplyBaseInfoDto.setActivityCourseType(ActivityCourseType.FREE_VIP);
            }
            if (Objects.nonNull(vipGroupActivity)) {
                vipGroupApplyBaseInfoDto.setVipGroupActivityId(vipGroupActivity.getId());
            }
            vipGroupApplyBaseInfoDto.setOrganId(student.getOrganId());
            vipGroupApplyBaseInfoDto.setOnlineClassesUnitPrice(vipGroupCategory.getOnlineClassesUnitPrice());
            vipGroupApplyBaseInfoDto.setOfflineClassesUnitPrice(vipGroupCategory.getOfflineClassesUnitPrice());
            vipGroupApplyDto.setVipGroupApplyBaseInfo(vipGroupApplyBaseInfoDto);

            vipGroupApplyDto.setCourseSchedules(courseSchedules);
            createActivityVipGroup(vipGroupApplyDto);
        }

        return BaseController.succeed();
    }

    @Override
    public List<Organization> getPublicOrgans(Integer eduTeacherId, Integer teacherId) {
        if (Objects.isNull(eduTeacherId)) {
            throw new BizException("教务老师不存在");
        }
        if (Objects.isNull(teacherId)) {
            throw new BizException("请指定指导老师");
        }
        Employee employee = employeeDao.get(eduTeacherId);
        if (Objects.isNull(employee)) {
            throw new BizException("教务老师不存在");
        }
        Teacher teacher = teacherDao.get(teacherId);
        if (Objects.isNull(teacher)) {
            throw new BizException("指导老师不存在");
        }
        List<Integer> employeeOrganIds = new ArrayList<>();
        if (StringUtils.isNotBlank(employee.getOrganIdList())) {
            employeeOrganIds = Arrays.stream(employee.getOrganIdList().split(",")).map(e -> Integer.valueOf(e)).collect(Collectors.toList());
        }
        List<Integer> teacherOrganIds = new ArrayList<>();
        if (Objects.nonNull(teacher.getTeacherOrganId())) {
            teacherOrganIds.add(teacher.getTeacherOrganId());
        }
        if (StringUtils.isNotBlank(teacher.getFlowOrganRange())) {
            Arrays.stream(teacher.getFlowOrganRange().split(","))
                    .map(e -> Integer.valueOf(e)).collect(Collectors.toSet())
                    .forEach(organId -> {
                        teacherOrganIds.add(organId);
                    });
        }
        List<Integer> publicOrganIds = employeeOrganIds.stream().filter(employeeOrganId -> teacherOrganIds.contains(employeeOrganId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(publicOrganIds)) {
            return Collections.emptyList();
        }
        return organizationDao.findOrgans(publicOrganIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteVipGroup(Long vipGroupId) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定课程组");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("课程组不存在");
        }
        Integer courseEndNum = courseScheduleDao.findCourseEndNum(vipGroupId);
        if (courseEndNum > 0) {
            throw new BizException("此状态课程组不支持删除");
        }
        vipGroup.setStatus(VipGroupStatusEnum.DELETE);
        vipGroupDao.update(vipGroup);
        groupClassService.hideGroupInfo(vipGroupId.toString(), GroupType.VIP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkVipCourseIsInScore(Long vipGroupId) {
        if (Objects.isNull(vipGroupId)) {
            return;
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("课程不存在");
        }
        Date groupCourseStartTime = courseScheduleDao.findGroupCourseStartTime(GroupType.VIP, vipGroupId.toString());
        Date groupCourseEndTime = courseScheduleDao.findGroupCourseEndTime(GroupType.VIP, vipGroupId.toString());

        //获取活动信息
        if (Objects.nonNull(vipGroup.getVipGroupActivityId())) {
            VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId().intValue());
            if (Objects.nonNull(vipGroupActivity) && (Objects.nonNull(vipGroupActivity.getCoursesEndTime()) || Objects.nonNull(vipGroupActivity.getCoursesStartTime()))) {
                if (groupCourseEndTime.after(vipGroupActivity.getCoursesEndTime())
                        || groupCourseStartTime.before(vipGroupActivity.getCoursesStartTime())) {
                    throw new BizException("课时安排时间超出范围!");
                }
            } else {
                int totalClassTimes = courseScheduleDao.countGroupAllCourses(GroupType.VIP, vipGroupId.toString());
                VipGroupDefaultClassesCycle vipGroupDefaultClassesCycle = vipGroupDefaultClassesCycleDao.findByOrganAndClassTimes(totalClassTimes, TenantContextHolder.getTenantId());

                if (vipGroupDefaultClassesCycle != null) {
                    Date expectEndCourseTime = DateUtil.addMonths(groupCourseStartTime, vipGroupDefaultClassesCycle.getMonth());
                    if (groupCourseEndTime.after(expectEndCourseTime)) {
                        throw new BizException("课时安排时间超出范围!");
                    }
                }
            }
        }
    }

    @Override
    public void vipApplyAudit(Long vipGroupId, AuditStatusEnum auditStatus, String reason) {
        if (Objects.isNull(vipGroupId) || Objects.isNull(auditStatus)) {
            throw new BizException("请指定vip课及审核结果");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("vip课不存在");
        }
        if (vipGroup.getAuditStatus() != AuditStatusEnum.ING) {
            throw new BizException("该课程已被审核");
        }
        if (StringUtils.isBlank(reason)) {
            throw new BizException("请填写拒绝原因");
        }
        vipGroup.setAuditStatus(auditStatus);
        vipGroup.setMemo(reason);
        vipGroupDao.update(vipGroup);
        //给老师推送审批短信
        Teacher teacher = teacherDao.get(vipGroup.getUserId());
        if (teacher != null) {
            Map<Integer, String> map = new HashMap<>(1);
            map.put(vipGroup.getUserId(), vipGroup.getUserId().toString());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_SMS_PUSH_VIP_COURSE_APPLY_RESULT,
                    map, null, 0, "7", "TEACHER", vipGroup.getName(), vipGroup.getAuditStatus().getMsg());
            Map<Integer, String> map1 = new HashMap<>(1);
            map1.put(vipGroup.getUserId(), teacher.getPhone());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.TEACHER_SMS_PUSH_VIP_COURSE_APPLY_RESULT,
                    map1, null, 0, "7", "", vipGroup.getName(), vipGroup.getAuditStatus().getMsg());
        }
    }

    @Override
    public PageInfo findStudentVipGroupList(StudentVipGroupQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);
        List dataList = null;
        int count = vipGroupDao.countVipGorups(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findVipGroups(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo<VipGroup> findVipGroups(VipGroupQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<VipGroup> dataList = null;
        int count = vipGroupDao.countVipGroupByOrgan(params);
        if (queryInfo.getIsExport() && count > 50000) {
            throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
        }
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findAllByOrgan(params);
            if (dataList != null && dataList.size() > 0) {
                List<String> vipGroupIds = dataList.stream().map(vipGroup -> String.valueOf(vipGroup.getId())).distinct().collect(Collectors.toList());
                List<Map<Long, Integer>> vipGroupOverCourses = courseScheduleDao.countGroupOverCourse(vipGroupIds, "VIP");
                Map<String, Integer> vipGroupOverCourseMaps = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(vipGroupOverCourses)), HashMap.class);
                List<Integer> educationalTeacherIds = dataList.stream().filter(data -> Objects.nonNull(data.getEducationalTeacherId())).map(VipGroup::getEducationalTeacherId).collect(Collectors.toList());

                List<ClassGroup> classGroupsByVipGroups = classGroupDao
                        .findByMusicGroupsAndType(vipGroupIds.stream().map(vipGroupId -> String.valueOf(vipGroupId)).collect(Collectors.toList()),
                                GroupType.VIP.getCode());

                Map<String, ClassGroup> vipGroupClassGroupMap = classGroupsByVipGroups.stream().collect(Collectors.toMap(ClassGroup::getMusicGroupId, classGroup -> classGroup));

                Map<String, Long> totalClassTimeMap = MapUtil.convertIntegerMap(courseScheduleDao.countTotalCourseScheduleNum(vipGroupIds, "VIP"));
                Map<String, Long> currentClassTimeMap = MapUtil.convertIntegerMap(courseScheduleDao.countCourseScheduleNum(vipGroupIds, "VIP"));
                Map<String, String> lastOverTimeMap = MapUtil.convertIntegerMap(courseScheduleDao.findLastOverTime(vipGroupIds));

                List<Map<String, BigDecimal>> groupCoursesUnitPriceMaps = courseScheduleStudentPaymentDao.findGroupCoursesUnitPrice(GroupType.VIP, vipGroupIds);
                Map<String, BigDecimal> groupCoursesUnitPrice = new HashMap<>();
                if (!CollectionUtils.isEmpty(groupCoursesUnitPriceMaps)) {
                    groupCoursesUnitPrice = MapUtil.convertIntegerMap(groupCoursesUnitPriceMaps);
                }

                List<Integer> organIds = dataList.stream().map(VipGroup::getOrganId).collect(Collectors.toList());
                List<Organization> organs = organizationDao.findOrgans(organIds);
                Map<Integer, String> organNameMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(organs)) {
                    organNameMap = organs.stream().collect(Collectors.toMap(Organization::getId, o -> o.getName(), (o1, o2) -> o1));
                }

                Map<Integer, String> idNameMap = new HashMap<>();
                if (!CollectionUtils.isEmpty(educationalTeacherIds)) {
                    List<SimpleUserDto> educationalUsers = employeeDao.findByIds(educationalTeacherIds);
                    idNameMap = educationalUsers.stream().filter(e -> Objects.nonNull(e.getUserId()) && Objects.nonNull(e.getUserName())).collect(Collectors.toMap(SimpleUserDto::getUserId, user -> user.getUserName()));
                }

                Map<String, List<GroupUserDto>> groupStudentsMap = new HashMap<>();
                if (queryInfo.getIsExport()) {
                    List<GroupUserDto> groupsStudents = groupDao.findGroupsStudents(vipGroupIds, GroupType.VIP);
                    groupStudentsMap = groupsStudents.stream().collect(Collectors.groupingBy(GroupUserDto::getGroupId));
                }

                for (VipGroup vipGroup : dataList) {
                    Integer overCourses = vipGroupOverCourseMaps.get(vipGroup.getId().toString());
                    ClassGroup classGroup = vipGroupClassGroupMap.get(vipGroup.getId().toString());
                    if (Objects.nonNull(classGroup)) {
                        vipGroup.setStudentNum(classGroup.getStudentNum());
                    }
                    vipGroup.setLastOverTime(lastOverTimeMap.get(vipGroup.getId().toString()));
                    Long aLong = totalClassTimeMap.get(vipGroup.getId() + "");
                    vipGroup.setTotalClassTimes(aLong == null ? 0 : aLong.intValue());
                    Long aLong1 = currentClassTimeMap.get(vipGroup.getId() + "");
                    vipGroup.setCurrentClassTimes(aLong1 == null ? 0 : aLong1.intValue());

                    vipGroup.setOrganName(organNameMap.get(vipGroup.getOrganId()));

                    if ((Objects.isNull(aLong1) || aLong1 <= 0)
                            && (classGroup.getStudentNum() <= 0)) {
                        vipGroup.setEnableDelete(1);
                    }

                    vipGroup.setEducationalTeacherName(idNameMap.get(vipGroup.getEducationalTeacherId()));

                    vipGroup.setCourseUnitPrice(groupCoursesUnitPrice.get(String.valueOf(vipGroup.getId())));

                    if (queryInfo.getIsExport()) {
                        List<GroupUserDto> groupStudents = groupStudentsMap.get(vipGroup.getId().toString());
                        if (!CollectionUtils.isEmpty(groupStudents)) {
                            List<String> userInfos = groupStudents.stream().map(u -> u.getUserName() + "(" + u.getUserId() + ")").collect(Collectors.toList());
                            vipGroup.setUserInfo(StringUtils.join(userInfos, ","));
                        }
                    }

                    Integer totalClassTimes = vipGroup.getTotalClassTimes();
                    if (Objects.isNull(totalClassTimes) || Objects.isNull(overCourses)) {
                        vipGroup.setMonthConsumeRate(0);
                    } else {
                        if (totalClassTimes <= 0) {
                            vipGroup.setMonthConsumeRate(0);
                        } else {
                            BigDecimal overCoursesOfMonth = new BigDecimal(overCourses), allClassTimes = new BigDecimal(totalClassTimes);

                            Integer monthConsumeRate = overCoursesOfMonth.divide(allClassTimes, CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue();
                            vipGroup.setMonthConsumeRate(monthConsumeRate);
                        }
                    }
                }
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Map<String, Object> findVipGroupTeachingRecord(VipGroupTeachingRecordQueryInfo queryInfo) {
        Long vipGroupId = queryInfo.getVipGroupId();
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定vip课程!");
        }
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<VipGroupCourseSchduleRecordDto> dataList = null;
        int count = vipGroupDao.countTeachingRecord(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findTeachingRecord(params);
            List<Long> courseScheduleIds = dataList.stream().map(VipGroupCourseSchduleRecordDto::getId).collect(Collectors.toList());
            List<Map<Integer, Integer>> maps = studentAttendanceDao.countStudentAttendancesByCoursesAndStatus(courseScheduleIds, StudentAttendanceStatusEnum.NORMAL);
            if (!CollectionUtils.isEmpty(maps)) {
                Map<Long, Long> courseStudentNumMap = MapUtil.convertIntegerMap(maps);
                for (VipGroupCourseSchduleRecordDto vipGroupCourseSchduleRecordDto : dataList) {
                    if (Objects.nonNull(courseStudentNumMap.get(vipGroupCourseSchduleRecordDto.getId()))) {
                        vipGroupCourseSchduleRecordDto.setAttendanceNum(courseStudentNumMap.get(vipGroupCourseSchduleRecordDto.getId()).intValue());
                    }
                }
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
//		TeachingRecordBaseInfo classTimes = vipGroupDao.getClassTimes(queryInfo.getVipGroupId());
        TeachingRecordBaseInfo classTimes = new TeachingRecordBaseInfo();
        classTimes.setCourseNoStartNum(courseScheduleDao.findCourseNoStartNum(vipGroupId));
        classTimes.setCourseEndNum(courseScheduleDao.findCourseEndNum(vipGroupId));
        classTimes.setIsSalaryNum(vipGroupDao.countIsSalaryNum(vipGroupId));
        classTimes.setComplaintsNum(vipGroupDao.countComplaintsNum(vipGroupId));
        Map<String, Object> result = new HashMap<>();
        result.put("pageInfo", pageInfo);
        result.put("baseInfo", classTimes);
        return result;
    }

    @Override
    public TeachingRecordBaseInfo findTeachingRecordBaseInfo(Long vipGroupId) {
        TeachingRecordBaseInfo classTimes = vipGroupDao.getClassTimes(vipGroupId);
        classTimes.setIsSalaryNum(vipGroupDao.countIsSalaryNum(vipGroupId));
        classTimes.setComplaintsNum(vipGroupDao.countComplaintsNum(vipGroupId));
        return classTimes;
    }

    @Override
    public PageInfo findVipGroupStudents(VipGroupQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<VipGroupStudentDto> dataList = null;
        int count = vipGroupDao.countVipGroupStudents(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findVipGroupStudents(params);
            List<StudentApplyRefunds> applyRefunds = studentApplyRefundsDao.findByGroupAndType(queryInfo.getVipGroupId().toString(), GroupType.VIP.getCode());
            Map<Integer, List<StudentApplyRefunds>> studentApplyRefundsMap = applyRefunds.stream()
                    .collect(Collectors.groupingBy(StudentApplyRefunds::getUserId));
            dataList.forEach(data -> {
                List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsMap.get(data.getId());
                if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
                    StudentApplyRefunds studentApplyRefund = studentApplyRefunds.get(0);
                    if (data.getStudentStatus() == 0 && studentApplyRefund.getStatus().equals(StudentApplyRefundsStatus.ING)) {
                        data.setStudentStatus(2);
                    }
                } else if (data.getStudentStatus() == 0) {
                    data.setRefundDate(null);
                }
            });
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfo findHaveCourseBalanceStudents(VipGroupQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<String> organIds = new ArrayList<>();
        if (StringUtils.isNotBlank(queryInfo.getOrganId())) {
            organIds = Arrays.stream(queryInfo.getOrganId().split(",")).collect(Collectors.toList());
        }
        params.put("organIds", organIds);

        List<VipGroupStudentDto> dataList = null;
        int count = vipGroupDao.countHaveCourseBalanceStudentNum(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findHaveCourseBalanceStudents(params);

            List<VipGroupStudentCoursePrice> vipGroupStudentCoursePrices = vipGroupStudentCoursePriceDao.getVipGroupStudentCoursePrice(queryInfo.getVipGroupId(), null);
            Map<Integer, VipGroupStudentCoursePrice> userPriceMap = new HashMap<>();
            if (!CollectionUtils.isEmpty(vipGroupStudentCoursePrices)) {
                userPriceMap = vipGroupStudentCoursePrices.stream().collect(Collectors.toMap(VipGroupStudentCoursePrice::getStudentId, v -> v, (v1, v2) -> v1));
            }
            VipGroup vipGroup = vipGroupDao.get(queryInfo.getVipGroupId());
            List<Integer> studentIds = dataList.stream().map(e -> e.getId()).collect(Collectors.toList());
            ActivityUserQueryInfo activityUserQueryInfo = new ActivityUserQueryInfo();
            activityUserQueryInfo.setCategoryId(vipGroup.getVipGroupCategoryId());
            activityUserQueryInfo.setOrganIds(queryInfo.getOrganId());
            activityUserQueryInfo.setSingleCourseTime(vipGroup.getSingleClassMinutes());
            activityUserQueryInfo.setStudentIds(studentIds);
            List<ActivityUserDto> activityUserDtos = activityUserMapperService.queryActivityStudentList(activityUserQueryInfo);
            Map<Integer, Integer> collect = new HashMap<>();
            if(!CollectionUtils.isEmpty(activityUserDtos)){
                collect = activityUserDtos.stream().
                        collect(Collectors.groupingBy(ActivityUserDto::getUserId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0).getSubCourseNum())));
            }
            for (VipGroupStudentDto vipGroupStudentDto : dataList) {
                vipGroupStudentDto.setTotalClassTimes(collect.get(vipGroupStudentDto.getId()));
                if (!userPriceMap.containsKey(Integer.valueOf(vipGroupStudentDto.getId().toString()))) {
                    continue;
                }
                VipGroupStudentCoursePrice vipGroupStudentCoursePrice = userPriceMap.get(Integer.valueOf(vipGroupStudentDto.getId().toString()));
                vipGroupStudentDto.setOnlineClassesUnitPrice(vipGroupStudentCoursePrice.getOnlineClassesUnitPrice());
                vipGroupStudentDto.setOfflineClassesUnitPrice(vipGroupStudentCoursePrice.getOfflineClassesUnitPrice());
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public VipGroupManageDetailDto getVipGroupDetail(Long vipGroupId) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定vip课程");
        }
        VipGroupManageDetailDto vipGroupBaseInfo = vipGroupDao.getVipGroupBaseInfo(vipGroupId);
        if (Objects.nonNull(vipGroupBaseInfo.getEducationalTeacherId())) {
            SysUser eduUser = sysUserFeignService.queryUserById(vipGroupBaseInfo.getEducationalTeacherId());
            if (Objects.nonNull(eduUser)) {
                vipGroupBaseInfo.setEducationalTeacherName(eduUser.getRealName());
            }
        }
        vipGroupBaseInfo.setSubjectName(StringUtils.join(subjectDao.findBySubIds(vipGroupBaseInfo.getSubjectIdList()), ","));
        ClassGroupTeacherSalary byVipGoupAndTeacher = classGroupTeacherSalaryDao.findByVipGoupAndTeacher(vipGroupId.intValue(), vipGroupBaseInfo.getUserId());
        Integer onlineNum = courseScheduleDao.countCourseNum(vipGroupId, "ONLINE");
        Integer offlineNum = courseScheduleDao.countCourseNum(vipGroupId, "OFFLINE");
        vipGroupBaseInfo.setOnlineClassesNum(onlineNum);
        vipGroupBaseInfo.setOfflineClassesNum(offlineNum);
        if (Objects.nonNull(byVipGoupAndTeacher)) {
            vipGroupBaseInfo.setOnlineTeacherSalary(byVipGoupAndTeacher.getOnlineClassesSalary());
            vipGroupBaseInfo.setOfflineTeacherSalary(byVipGoupAndTeacher.getSalary());
        }
        return vipGroupBaseInfo;
    }

    @Override
    public VipGroupManageDetailDto getVipGroupDetailForAudit(Long vipGroupId) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定vip课程");
        }
        VipGroupManageDetailDto vipGroupBaseInfo = vipGroupDao.getVipGroupBaseInfo(vipGroupId);
        vipGroupBaseInfo.setSubjectName(StringUtils.join(subjectDao.findBySubIds(vipGroupBaseInfo.getSubjectIdList()), ","));
        ClassGroupTeacherSalary byVipGoupAndTeacher = classGroupTeacherSalaryDao.findByVipGoupAndTeacher(vipGroupId.intValue(), vipGroupBaseInfo.getUserId());
        if (Objects.nonNull(byVipGoupAndTeacher)) {
            vipGroupBaseInfo.setOnlineTeacherSalary(byVipGoupAndTeacher.getOnlineClassesSalary());
            vipGroupBaseInfo.setOfflineTeacherSalary(byVipGoupAndTeacher.getSalary());
        }
        return vipGroupBaseInfo;
    }

    @Override
    public PageInfo findVipGroupAttendances(VipGroupAttendanceQueryInfo queryInfo) {
        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List dataList = null;
        int count = vipGroupDao.countVipGroupAttendance(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = vipGroupDao.findVipGroupAttendances(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public StudentVipGroupDetailDto getVipGroupShowDetail(Long groupId, String groupType) {
        if (Objects.isNull(groupId)) {
            throw new BizException("请指定课程组");
        }
        if ("PRACTICE".equals(groupType)) {
            PracticeGroup practiceGroup = practiceGroupService.get(groupId);
            if (Objects.isNull(practiceGroup)) {
                throw new BizException("未找到指定课程组");
            }
            StudentVipGroupDetailDto vipGroupDetail = practiceGroupService.getPracticeGroupDetail(groupId);
            if (StringUtils.isNotEmpty(practiceGroup.getCourseScheduleJson())) {
                vipGroupDetail.setCourseSchedules(JSON.parseArray(practiceGroup.getCourseScheduleJson(), CourseSchedule.class));
                List<CourseSchedule> collect = vipGroupDetail.getCourseSchedules().stream()
                        .sorted(Comparator.comparing(CourseSchedule::getStartClassTime))
                        .collect(Collectors.toList());
                vipGroupDetail.setCourseSchedules(collect);
                vipGroupDetail.setTotalClassTimes(collect.size());
            }
            vipGroupDetail.setNumberOfClasses(practiceGroupService.countTeacherPracticeGroups(vipGroupDetail.getTeacherId()));
            return vipGroupDetail;
        } else {
            VipGroup vipGroup = vipGroupDao.get(groupId);
            if (Objects.isNull(vipGroup)) {
                throw new BizException("未找到指定课程");
            }
            StudentVipGroupDetailDto vipGroupDetail = vipGroupDao.getVipGroupDetail(groupId);
            if (StringUtils.isNotEmpty(vipGroup.getCourseSchedulesJson())) {
                vipGroupDetail.setCourseSchedules(JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class));
                List<CourseSchedule> collect = vipGroupDetail.getCourseSchedules().stream()
                        .sorted(Comparator.comparing(CourseSchedule::getStartClassTime))
                        .collect(Collectors.toList());
                vipGroupDetail.setCourseSchedules(collect);
                vipGroupDetail.setTotalClassTimes(collect.size());
            }
            VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId());
            vipGroupDetail.setCategoryName(vipGroupCategory.getName());
            vipGroupDetail.setNumberOfClasses(vipGroupDao.countTeacherVipGroups(vipGroupDetail.getTeacherId().longValue()));
            return vipGroupDetail;
        }
    }

    @Override
    public <K extends VipGroup> Map<String, BigDecimal> countVipGroupPredictFee1(K vipGroup,
                                                                                 Integer teacherId,
                                                                                 Long courseId) {
        if (Objects.isNull(teacherId)) {
            throw new BizException("请指定教师");
        }

        if (Objects.isNull(vipGroup.getVipGroupCategoryId())) {
            throw new BizException("请指定课程形式");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId().intValue());
        if (Objects.isNull(vipGroupCategory)) {
            throw new BizException("课程形式不存在");
        }

        TeacherDefaultVipGroupSalary teacherDefaultVipGroupSalary = teacherDefaultVipGroupSalaryDao.findByTeacherAndCategory(teacherId,
                vipGroup.getVipGroupCategoryId());

        if (Objects.isNull(teacherDefaultVipGroupSalary)) {
            throw new BizException("请设置教师课酬");
        }

        if (Objects.isNull(teacherDefaultVipGroupSalary) || Objects.isNull(teacherDefaultVipGroupSalary.getOfflineClassesSalary())) {
            throw new BizException("请设置教师VIP课课酬");
        }

        Map<String, BigDecimal> results = new HashMap<>(2);

        VipGroupSalarySettlementTypeDto vipOfflineSalarySettlement = null;
        VipGroupSalarySettlementTypeDto giveVipOfflineSalarySettlement = null;
        BigDecimal discount = new BigDecimal(100);
        if (vipGroup.getVipGroupActivityId() != null) {
            VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId());
            discount = vipGroupActivity.getDiscount();
            VipGroupSalarySettlementDto vipGroupSalarySettlementDto = JSON.parseObject(vipGroupActivity.getSalarySettlementJson(), VipGroupSalarySettlementDto.class);
            if (Objects.isNull(vipGroupSalarySettlementDto)) {
                throw new BizException("课酬结算方案错误");
            }
            vipOfflineSalarySettlement = vipGroupSalarySettlementDto.getOfflineSalarySettlement();
            giveVipOfflineSalarySettlement = vipGroupSalarySettlementDto.getGiveVipOfflineSalarySettlement();

            //是否是赠送课程
            ActivityUserMapper activityUserMapper = activityUserMapperService.findVipUserMapper(vipGroup.getId(), "VIP", null);
            if (activityUserMapper != null) {
                if (vipGroup.getId().equals(activityUserMapper.getGiveVipGroupId())) {
                    giveVipOfflineSalarySettlement = vipGroupSalarySettlementDto.getGiveVipOfflineSalarySettlement();
                } else {
                    vipOfflineSalarySettlement = vipGroupSalarySettlementDto.getOfflineSalarySettlement();
                }
            }

        }

        BigDecimal offlineClassNum = new BigDecimal(vipGroup.getOfflineClassesNum());
        BigDecimal onlineClassNum = new BigDecimal(vipGroup.getOnlineClassesNum());
        BigDecimal onlineClassesUnitPrice = vipGroup.getOnlineClassesUnitPrice();
        if (Objects.isNull(onlineClassesUnitPrice)) {
            throw new BizException("课程单价异常");
        }
        BigDecimal onlineVipGroupCharge = onlineClassesUnitPrice.multiply(onlineClassNum);

        BigDecimal offlineClassesUnitPrice = vipGroup.getOfflineClassesUnitPrice();
        if (Objects.isNull(offlineClassesUnitPrice)) {
            throw new BizException("课程单价异常");
        }
        BigDecimal offlineVipGroupCharge = offlineClassesUnitPrice.multiply(offlineClassNum);
        BigDecimal teacherOfflineSalary = BigDecimal.ZERO;
        BigDecimal giveTeacherOfflineSalary = BigDecimal.ZERO;

        //课程购买费用计算
        BigDecimal totalPrice = onlineVipGroupCharge.add(offlineVipGroupCharge);
        totalPrice = totalPrice.multiply(discount).divide(new BigDecimal(100), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);

        results.put("totalPrice", totalPrice.setScale(0, BigDecimal.ROUND_CEILING));
        vipGroup.setTotalPrice(totalPrice.setScale(0, BigDecimal.ROUND_CEILING));

        int normalStudentNum = classGroupStudentMapperDao.countGroupNormalStudentNum(VIP, vipGroup.getId().toString());

        //教师线下单课酬计算
        if (vipGroupCategory.getMusicTheory()) {
            teacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary().multiply(new BigDecimal(normalStudentNum > 5 ? 5 : normalStudentNum)).setScale(CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP);
        } else {
            teacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.nonNull(vipOfflineSalarySettlement)) {
            if (vipOfflineSalarySettlement.getSalarySettlementType() == SalarySettlementTypeEnum.FIXED_SALARY) {
                teacherOfflineSalary = vipOfflineSalarySettlement.getSettlementValue();
            }
        }
        results.put("offlineTeacherSalary", teacherOfflineSalary.setScale(2, BigDecimal.ROUND_HALF_UP));

        //教师赠送线下单课酬计算
        if (vipGroupCategory.getMusicTheory()) {
            giveTeacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary().multiply(new BigDecimal(normalStudentNum > 5 ? 5 : normalStudentNum)).setScale(CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP);
        } else {
            giveTeacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.nonNull(giveVipOfflineSalarySettlement)) {
            if (giveVipOfflineSalarySettlement.getSalarySettlementType() == SalarySettlementTypeEnum.FIXED_SALARY) {
                giveTeacherOfflineSalary = giveVipOfflineSalarySettlement.getSettlementValue();
            }
        }
        results.put("giveOfflineTeacherSalary", giveTeacherOfflineSalary.setScale(2, BigDecimal.ROUND_HALF_UP));

        BigDecimal ofts = results.get("offlineTeacherSalary");
        if (Objects.isNull(ofts)) {
            ofts = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.isNull(ofts)) {
            ofts = BigDecimal.ZERO;
        }
        BigDecimal gofts = results.get("giveOfflineTeacherSalary");
        if (Objects.isNull(gofts)) {
            gofts = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.isNull(gofts)) {
            gofts = BigDecimal.ZERO;
        }
        if (!vipGroupCategory.getMusicTheory()) {
            gofts = gofts.divide(new BigDecimal(vipGroupCategory.getStudentNum()), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(normalStudentNum)).setScale(CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP);
            ofts = ofts.divide(new BigDecimal(vipGroupCategory.getStudentNum()), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN).multiply(new BigDecimal(normalStudentNum)).setScale(CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP);
        }
        results.put("offlineTeacherSalary", ofts);
        results.put("giveOfflineTeacherSalary", gofts);
        return results;
    }

    @Override
    public <K extends VipGroup> Map<String, BigDecimal> countVipGroupPredictFee(K vipGroup,
                                                                                Integer teacherId) {
        if (Objects.isNull(teacherId)) {
            throw new BizException("请指定教师");
        }

        if (Objects.isNull(vipGroup.getVipGroupCategoryId())) {
            throw new BizException("请指定课程形式");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId().intValue());
        if (Objects.isNull(vipGroupCategory)) {
            throw new BizException("课程形式不存在");
        }

        TeacherDefaultVipGroupSalary teacherDefaultVipGroupSalary = teacherDefaultVipGroupSalaryDao.findByTeacherAndCategory(teacherId,
                vipGroup.getVipGroupCategoryId());

        if (Objects.isNull(teacherDefaultVipGroupSalary)) {
            throw new BizException("请设置教师课酬");
        }

        if (Objects.isNull(teacherDefaultVipGroupSalary) || Objects.isNull(teacherDefaultVipGroupSalary.getOfflineClassesSalary())) {
            throw new BizException("请设置教师VIP课课酬");
        }

        Map<String, BigDecimal> results = new HashMap<>(2);

        VipGroupSalarySettlementTypeDto vipOfflineSalarySettlement = null;
        VipGroupSalarySettlementTypeDto giveVipOfflineSalarySettlement = null;
        BigDecimal discount = new BigDecimal(100);
        if (vipGroup.getVipGroupActivityId() != null) {
            VipGroupActivity vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId());
            discount = vipGroupActivity.getDiscount();
            VipGroupSalarySettlementDto vipGroupSalarySettlementDto = JSON.parseObject(vipGroupActivity.getSalarySettlementJson(), VipGroupSalarySettlementDto.class);
            if (Objects.isNull(vipGroupSalarySettlementDto)) {
                throw new BizException("课酬结算方案错误");
            }
            vipOfflineSalarySettlement = vipGroupSalarySettlementDto.getOfflineSalarySettlement();
            giveVipOfflineSalarySettlement = vipGroupSalarySettlementDto.getGiveVipOfflineSalarySettlement();
        }

        BigDecimal offlineClassNum = new BigDecimal(vipGroup.getOfflineClassesNum());
        BigDecimal onlineClassNum = new BigDecimal(vipGroup.getOnlineClassesNum());
        BigDecimal onlineClassesUnitPrice = vipGroup.getOnlineClassesUnitPrice();
        if (Objects.isNull(onlineClassesUnitPrice)) {
            throw new BizException("课程单价异常");
        }
        BigDecimal onlineVipGroupCharge = onlineClassesUnitPrice.multiply(onlineClassNum);

        BigDecimal offlineClassesUnitPrice = vipGroup.getOfflineClassesUnitPrice();
        if (Objects.isNull(offlineClassesUnitPrice)) {
            throw new BizException("课程单价异常");
        }
        BigDecimal offlineVipGroupCharge = offlineClassesUnitPrice.multiply(offlineClassNum);
        BigDecimal teacherOfflineSalary = BigDecimal.ZERO;
        BigDecimal giveTeacherOfflineSalary = BigDecimal.ZERO;

        //课程购买费用计算
        BigDecimal totalPrice = onlineVipGroupCharge.add(offlineVipGroupCharge);
        totalPrice = totalPrice.multiply(discount).divide(new BigDecimal(100), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);

        results.put("totalPrice", totalPrice.setScale(0, BigDecimal.ROUND_CEILING));
        vipGroup.setTotalPrice(totalPrice.setScale(0, BigDecimal.ROUND_CEILING));

        //教师线下单课酬计算
        teacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        if (Objects.nonNull(vipOfflineSalarySettlement)) {
            if (vipOfflineSalarySettlement.getSalarySettlementType() == SalarySettlementTypeEnum.FIXED_SALARY) {
                teacherOfflineSalary = vipOfflineSalarySettlement.getSettlementValue();
            }
        }
        results.put("offlineTeacherSalary", teacherOfflineSalary.setScale(2, BigDecimal.ROUND_HALF_UP));

        //教师赠送线下单课酬计算
        giveTeacherOfflineSalary = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        if (Objects.nonNull(giveVipOfflineSalarySettlement)) {
            if (giveVipOfflineSalarySettlement.getSalarySettlementType() == SalarySettlementTypeEnum.FIXED_SALARY) {
                giveTeacherOfflineSalary = giveVipOfflineSalarySettlement.getSettlementValue();
            }
        }
        results.put("giveOfflineTeacherSalary", giveTeacherOfflineSalary.setScale(2, BigDecimal.ROUND_HALF_UP));

        BigDecimal ofts = results.get("offlineTeacherSalary");
        if (Objects.isNull(ofts)) {
            ofts = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.isNull(ofts)) {
            ofts = BigDecimal.ZERO;
        }
        BigDecimal gofts = results.get("giveOfflineTeacherSalary");
        if (Objects.isNull(gofts)) {
            gofts = teacherDefaultVipGroupSalary.getOfflineClassesSalary();
        }
        if (Objects.isNull(gofts)) {
            gofts = BigDecimal.ZERO;
        }
        results.put("offlineTeacherSalary", ofts);
        results.put("giveOfflineTeacherSalary", gofts);
        return results;
    }

    @Override
    public void enableBuyVipGroup(Long vipGroupId, Integer userId, String groupType) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定课程组");
        }
        if ("PRACTICE".equals(groupType)) {
            PracticeGroup practiceGroup = practiceGroupService.get(vipGroupId);
            if (Objects.nonNull(practiceGroup.getStudentId())) {
                if (!practiceGroup.getStudentId().equals(userId)) {
                    throw new BizException("您无法购买此课程");
                }
            }
            ClassGroup classGroup = classGroupDao.findByGroupAndType(vipGroupId.toString(), "PRACTICE");
            Boolean exist = classGroupStudentMapperDao.existByClassGroupIds(classGroup.getId().toString(), userId);
            if (exist) {
                throw new BizException("您已加入此课程");
            }
//
//			if(classGroup.getStudentNum()>0 && (VipGroupStatusEnum.APPLYING.equals(practiceGroup.getGroupStatus()))){
//				int i = studentPaymentOrderDao.countGroupOrderWithoutFailed(vipGroupId.toString(), GroupType.PRACTICE);
//				if(i<=0){
//					throw new BizException("该课程已经无法通过购买加入，请联系教务老师!");
//				}
//			}

            List<CourseSchedule> courseSchedules = JSON.parseArray(practiceGroup.getCourseScheduleJson(), CourseSchedule.class);
            courseScheduleService.checkNewCourseSchedules(courseSchedules, false, false);
        } else {
            VipGroup vipGroup = get(vipGroupId.longValue());
            if (Objects.nonNull(vipGroup.getStudentIdList())) {
                Set<Integer> userIds = Arrays.asList(vipGroup.getStudentIdList().split(",")).stream().mapToInt(Integer::parseInt).boxed().collect(Collectors.toSet());
                if (!userIds.contains(userId)) {
                    throw new BizException("您无法购买此课程");
                }
            }
            ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId.longValue(), null);
            //是否已经购买
            Boolean exist = classGroupStudentMapperDao.existByClassGroupIds(classGroup.getId().toString(), userId);
            if (exist) {
                throw new BizException("您已加入此课程");
            }

            if (classGroup.getStudentNum() > 0 && (VipGroupStatusEnum.APPLYING.equals(vipGroup.getStatus()))) {
                int i = studentPaymentOrderDao.countGroupOrderWithoutFailed(vipGroupId.toString(), GroupType.VIP);
                if (i <= 0) {
                    throw new BizException("该课程已经无法通过购买加入，请联系教务老师!");
                }
            }

            List<CourseSchedule> courseSchedules = JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
            courseScheduleService.checkNewCourseSchedules(courseSchedules, false, false);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void createVipGroupCourseScheInfo(Long vipGroupId, ClassGroup classGroup) {
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        List<CourseSchedule> courseSchedules = JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
        int courseNum = courseScheduleDao.countVipGroupCourses(vipGroupId.intValue(), "VIP");
        if (courseNum == 0) {
            courseScheduleService.batchAddCourseSchedule(courseSchedules);

            ClassGroupTeacherSalary classGroupTeacherSalary = classGroupTeacherSalaryDao.findByVipGoupAndTeacher(vipGroupId.intValue(), vipGroup.getUserId());

            //创建老师单节课课酬信息
            courseScheduleTeacherSalaryService.createCourseScheduleTeacherVipSalary(vipGroup,
                    courseSchedules,
                    classGroupTeacherSalary.getSalary());
        }

        SysUser sysUser = sysUserFeignService.queryUserById(vipGroup.getUserId());

        List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentMapperDao.findByClassGroup(classGroup.getId());

        Map<Integer, String> userRoleMap = new HashMap<Integer, String>();
        if (Objects.nonNull(vipGroup.getEducationalTeacherId())) {
            userRoleMap.put(vipGroup.getEducationalTeacherId(), "乐团主管");
        }
        userRoleMap.put(vipGroup.getUserId(), "指导老师");
        //生成学生单课缴费信息
        for (ClassGroupStudentMapper classGroupStudent : classGroupStudents) {
            courseScheduleStudentPaymentService.createCourseScheduleStudentPaymentForVipGroup(vipGroupId, classGroupStudent.getUserId());
            try {
                if (vipGroup.getOnlineClassesNum() > 0) {
                    teacherCourseRewardService.addConvertReward(classGroupStudent.getUserId(), vipGroup.getUserId());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            userRoleMap.put(classGroupStudent.getUserId(), null);
            studentDao.updateStudentServiceTag(classGroupStudent.getUserId(), null, YesOrNoEnum.YES.getCode());
        }

//		courseScheduleService.checkNewCourseSchedules(courseSchedules, false,false);

        try {
            imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(), classGroup.getName(),
                    vipGroup.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
            imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
            imUserFriendService.refreshGroupImUserFriend(classGroup.getMusicGroupId(), classGroup.getGroupType());
            //发送推送短信
            Map<Integer, String> map = new HashMap<>(1);
            map.put(vipGroup.getUserId(), sysUser.getPhone());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.TEACHER_SMS_VIP_COURSE_ADD,
                    map, null, 0, "", "", vipGroup.getName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public HttpResponseResult buyVipGroup(VipGroupBuyParamsDto vipGroupBuyParams) throws Exception {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (user == null) {
            throw new BizException("用户信息获取失败");
        }
        // 判断是否存在支付中的记录
        List<StudentPaymentOrder> list = studentPaymentOrderService
                .queryByCondition(GroupType.VIP,
                        vipGroupBuyParams.getVipGroupId().toString(),
                        vipGroupBuyParams.getUserId(),
                        DealStatusEnum.ING,
                        OrderTypeEnum.SMALL_CLASS_TO_BUY);

        ClassGroup classGroup = classGroupDao.findByMusicGroupAndType(vipGroupBuyParams.getVipGroupId().toString(), ClassGroupTypeEnum.VIP.getCode());
        if (Objects.isNull(classGroup)) {
            throw new BizException("班级信息错误");
        }
        classGroup = classGroupDao.lockClassGroup(classGroup.getId());
        Boolean exist = classGroupStudentMapperDao.existByClassGroupIds(classGroup.getId().toString(), vipGroupBuyParams.getUserId());
        if (exist) {
            throw new BizException("您已加入此课程");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupBuyParams.getVipGroupId());
        int courseNum = courseScheduleDao.countVipGroupCourses(vipGroup.getId().intValue(), "VIP");
        if (vipGroup.getStatus() != VipGroupStatusEnum.APPLYING || classGroup.getDelFlag() != 1 || courseNum > 0) {
            throw new BizException("当前VIP课已无法通过购买加入，请联系教务老师");
        }

        if (list.size() > 0) {
            StudentPaymentOrder applyOrder = list.get(list.size() - 1);
            //校验重复支付
            HttpResponseResult result = studentPaymentOrderService.checkRepeatPay(applyOrder, vipGroupBuyParams.isRepeatPay());
            if (result.getCode() != 200) {
                return result;
            }
            classGroup.setStudentNum(classGroup.getStudentNum() - 1);
        }

        Date date = new Date();

        if (classGroup.getStudentNum() >= classGroup.getExpectStudentNum()) {
            throw new BizException("该VIP课人数已满，请联系教务老师!");
        }

        VipGroupActivity vipGroupActivity = null;
        if (Objects.nonNull(vipGroup.getVipGroupActivityId())) {
            vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId());
        }

        if (Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getStudentMaxUsedTimes()) && vipGroupActivity.getStudentMaxUsedTimes() != -1) {
            int useNum = activityUserMapperService.countActivityBuyNum(vipGroupActivity.getId(), user.getId());
            if (useNum >= vipGroupActivity.getStudentMaxUsedTimes()) {
                throw new BizException("您已超过该活动购买限制{}次", vipGroupActivity.getStudentMaxUsedTimes());
            }
        }

        if (vipGroup.getPaymentExpireDate().before(date)) {
            throw new BizException("该课程已结束报名!");
        }

        if (Objects.nonNull(vipGroup.getStudentIdList())) {
            Set<Integer> userIds = Arrays.asList(vipGroup.getStudentIdList().split(",")).stream().mapToInt(Integer::parseInt).boxed().collect(Collectors.toSet());
            if (!userIds.contains(user.getId())) {
                throw new BizException("您无法购买此课程");
            }
        }
        //增加学员数
        classGroup.setStudentNum(classGroup.getStudentNum() + 1);
        classGroupDao.update(classGroup);

        List<CourseSchedule> courseSchedules = JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
        courseScheduleService.checkNewCourseSchedules(courseSchedules, false, false);

        //校验优惠券
        String[] checkCoupon = CouponDetailTypeEnum.getAllowType(CouponDetailTypeEnum.VIP);
        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(vipGroupBuyParams.getCouponIdList(), vipGroup.getTotalPrice(), true, checkCoupon);
        studentPaymentOrder.setUserId(user.getId());
        studentPaymentOrder.setGroupType(GroupType.VIP);
        String orderNo = idGeneratorService.generatorId("payment") + "";
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setType(OrderTypeEnum.SMALL_CLASS_TO_BUY);
        studentPaymentOrder.setMusicGroupId(vipGroup.getId().toString());
        studentPaymentOrder.setMusicGroupId(vipGroup.getId().toString());
        studentPaymentOrder.setClassGroupId(classGroup.getId());
        studentPaymentOrder.setOrganId(vipGroup.getOrganId());
        studentPaymentOrder.setVersion(0);
        studentPaymentOrder.setActivityBuyNum(vipGroup.getOnlineClassesNum() + vipGroup.getOfflineClassesNum());
        Integer vipGroupActivityId = vipGroup.getVipGroupActivityId();
        studentPaymentOrder.setActivityId(vipGroupActivityId == null ? "" : vipGroupActivityId.toString());
        studentPaymentOrderDao.insert(studentPaymentOrder);

        BigDecimal amount = studentPaymentOrder.getActualAmount();
        BigDecimal balance = BigDecimal.ZERO;
        if (vipGroupBuyParams.isUseBalancePayment() || amount.doubleValue() == 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(user.getId());
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            studentPaymentOrder.setPaymentChannel("BALANCE");
            if (userCashAccount.getBalance().subtract(amount).doubleValue() >= 0) {
                studentPaymentRouteOrderService.addRouteOrder(orderNo, vipGroup.getOrganId(), vipGroup.getTotalPrice());
                // 更新订单信息
                studentPaymentOrder.setActualAmount(new BigDecimal(0));
                studentPaymentOrder.setBalancePaymentAmount(amount);
                studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
                studentPaymentOrder.setUpdateTime(date);
                studentPaymentOrder.setOrganId(vipGroup.getOrganId());
                studentPaymentOrder.setRoutingOrganId(vipGroup.getOrganId());

                this.orderCallback(studentPaymentOrder);

                sysUserCashAccountService.updateBalance(user.getId(), amount.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "VIP课购买");

                Map<String, Object> result = new HashMap<>();
                result.put("orderNo", studentPaymentOrder.getOrderNo());

                return BaseController.succeed(result);
            } else {
                if (userCashAccount.getBalance().doubleValue() > 0) {
                    balance = userCashAccount.getBalance();
                    sysUserCashAccountService.updateBalance(user.getId(), balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "VIP课购买");
                    amount = amount.subtract(userCashAccount.getBalance());
                    studentPaymentOrder.setActualAmount(amount);
                    studentPaymentOrder.setBalancePaymentAmount(userCashAccount.getBalance());
                } else {
                    studentPaymentOrder.setBalancePaymentAmount(new BigDecimal(0));
                }
            }
        }
        try {
            contractService.register(user.getId(), user.getRealName(), user.getIdCardNo(), user.getPhone());
        } catch (Exception e) {
            LOGGER.error("[{}]小课购买协议生成错误：{}", vipGroup.getId(), e.getCause());
        }

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");
        //分类费用 course，instrument，accessories，other
        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", amount);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", BigDecimal.ZERO);
        Map<String, Object> payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/callback",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                "vip课购买",
                vipGroup.getName(),
                vipGroup.getOrganId(),
                "vipBuy"
        );

        studentPaymentOrder.setOrganId(vipGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(vipGroup.getOrganId());
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return BaseController.succeed(payMap);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void orderCallback(StudentPaymentOrder studentPaymentOrder) {
        Integer userId = studentPaymentOrder.getUserId();
        Integer tenantId = studentPaymentOrder.getTenantId();
        StudentPaymentOrder order = studentPaymentOrderDao.lockOrder(studentPaymentOrder.getId());
        if (!order.getStatus().equals(DealStatusEnum.ING)) {
            return;
        }
        //更新订单状态
        int updateCount = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }
        Date date = new Date();
        ClassGroup classGroup = classGroupDao.get(order.getClassGroupId());
        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            VipGroup vipGroup = vipGroupDao.get(Long.parseLong(classGroup.getMusicGroupId()));
            if (vipGroup.getStatus() == VipGroupStatusEnum.DELETE ||
                    vipGroup.getStatus() == VipGroupStatusEnum.CANCEL ||
                    vipGroup.getStatus() == VipGroupStatusEnum.PAUSE) {
                //增加用户余额
                sysUserCashAccountService.updateBalance(order.getUserId(), order.getActualAmount().add(order.getBalancePaymentAmount()),
                        PlatformCashAccountDetailTypeEnum.REFUNDS, "课程组关闭退还课程余额,订单号:" + order.getOrderNo());

                //退还优惠券
                sysCouponCodeService.quit(order.getCouponCodeId());
            } else {
                //活动赠送
                Integer activityUserMapperId = studentPaymentOrderService.activityGive(vipGroup.getVipGroupActivityId(), studentPaymentOrder,
                        vipGroup.getId().toString(), null, vipGroup.getUserId());

                //生成班级学员关联
                ClassGroupStudentMapper classGroupStudentMapper = new ClassGroupStudentMapper();
                classGroupStudentMapper.setMusicGroupId(classGroup.getMusicGroupId());
                classGroupStudentMapper.setClassGroupId(classGroup.getId());
                classGroupStudentMapper.setUserId(userId);
                classGroupStudentMapper.setCreateTime(date);
                classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
                classGroupStudentMapper.setGroupType(GroupType.VIP);
                classGroupStudentMapperDao.insert(classGroupStudentMapper);

                //获取班级实际人数
                Integer studentNum = classGroupStudentMapperDao.countGroupNormalStudentNum(VIP, classGroup.getMusicGroupId());
                //课程组人数已满，变更状态
                if (studentNum.equals(classGroup.getExpectStudentNum())) {
                    vipGroup.setStatus(VipGroupStatusEnum.PROGRESS);
                    classGroup.setDelFlag(0);
                    VipGroupDefaultClassesUnitPrice vipGroupDefaultClassesUnitPrice = vipGroupDefaultClassesUnitPriceDao.getByVipGroupCategory(vipGroup.getVipGroupCategoryId(), vipGroup.getOrganId());

                    //生成课表
                    List<CourseSchedule> courseSchedules = JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
                    classGroup.setTotalClassTimes(courseSchedules.size());

                    courseScheduleService.batchAddCourseSchedule1(courseSchedules);

                    //考勤信息
                    List<TeacherAttendance> teacherAttendances = new ArrayList<>();
                    //创建课酬信息
                    List<CourseScheduleTeacherSalary> courseScheduleTeacherSalaries = new ArrayList<>();
                    Map<String, BigDecimal> stringBigDecimalMap = countVipGroupPredictFee1(vipGroup, vipGroup.getUserId(), null);
                    for (CourseSchedule courseSchedule : courseSchedules) {
                        //创建教师课程薪水记录
                        CourseScheduleTeacherSalary courseScheduleTeacherSalary = new CourseScheduleTeacherSalary();
                        courseScheduleTeacherSalary.setCourseScheduleId(courseSchedule.getId());
                        courseScheduleTeacherSalary.setGroupType(courseSchedule.getGroupType());
                        courseScheduleTeacherSalary.setMusicGroupId(courseSchedule.getMusicGroupId());
                        courseScheduleTeacherSalary.setTeacherRole(TeachTypeEnum.BISHOP);
                        courseScheduleTeacherSalary.setUserId(courseSchedule.getActualTeacherId().intValue());
                        courseScheduleTeacherSalary.setClassGroupId(courseSchedule.getClassGroupId());
                        courseScheduleTeacherSalary.setExpectSalary(stringBigDecimalMap.get("offlineTeacherSalary"));
                        courseScheduleTeacherSalary.setActualSalary(null);
                        courseScheduleTeacherSalary.setTenantId(tenantId);
                        courseScheduleTeacherSalaries.add(courseScheduleTeacherSalary);

                        TeacherAttendance teacherAttendance = new TeacherAttendance();
                        teacherAttendance.setGroupType(courseSchedule.getGroupType());
                        teacherAttendance.setClassGroupId(courseSchedule.getClassGroupId());
                        teacherAttendance.setMusicGroupId(courseSchedule.getMusicGroupId());
                        teacherAttendance.setTeacherId(courseSchedule.getActualTeacherId());
                        teacherAttendance.setCourseScheduleId(courseSchedule.getId());
                        teacherAttendance.setTenantId(tenantId);
                        teacherAttendances.add(teacherAttendance);
                    }
                    courseScheduleTeacherSalaryDao.batchInsert(courseScheduleTeacherSalaries);
                    teacherAttendanceDao.batchInsert(teacherAttendances);

                    //群聊数据
                    Map<Integer, String> userRoleMap = new HashMap<Integer, String>(5);
                    if (Objects.nonNull(vipGroup.getEducationalTeacherId())) {
                        userRoleMap.put(vipGroup.getEducationalTeacherId(), "乐团主管");
                    }
                    userRoleMap.put(vipGroup.getUserId(), "指导老师");
                    //生成课程学员关联
                    List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
                    List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentMapperDao.findByClassGroup(classGroup.getId());

                    List<Integer> studentIdList = classGroupStudents.stream().map(e -> e.getUserId()).collect(Collectors.toList());
                    for (ClassGroupStudentMapper classGroupStudent : classGroupStudents) {
                        StudentPaymentOrder successOrder = studentPaymentOrderDao.findByStudentVipGroup(vipGroup.getId(), classGroupStudent.getUserId(), "SUCCESS");
                        //实际支付金额，去除优惠券
                        BigDecimal actualPrice = successOrder.getExpectAmount();
                        BigDecimal divide = actualPrice.divide(new BigDecimal(courseSchedules.size()), ROUND_DOWN);
                        BigDecimal firstAmount = actualPrice.subtract(divide.multiply(new BigDecimal(courseSchedules.size()))).add(divide);
                        for (int i = 0; i < courseSchedules.size(); i++) {
                            CourseSchedule courseSchedule = courseSchedules.get(i);
                            CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
                            courseScheduleStudentPayment.setUserId(classGroupStudent.getUserId());
                            courseScheduleStudentPayment.setGroupType(courseSchedule.getGroupType());
                            courseScheduleStudentPayment.setMusicGroupId(courseSchedule.getMusicGroupId());
                            courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
                            courseScheduleStudentPayment.setClassGroupId(courseSchedule.getClassGroupId());
                            if (i == 0) {
                                courseScheduleStudentPayment.setExpectPrice(firstAmount);
                            } else {
                                courseScheduleStudentPayment.setExpectPrice(divide);
                            }
                            courseScheduleStudentPayment.setOriginalPrice(TeachModeEnum.ONLINE.equals(courseSchedule.getTeachMode()) ? vipGroupDefaultClassesUnitPrice.getOnlineClassesUnitPrice() : vipGroupDefaultClassesUnitPrice.getOfflineClassesUnitPrice());
                            courseScheduleStudentPayment.setActualPrice(courseScheduleStudentPayment.getExpectPrice());
                            courseScheduleStudentPayments.add(courseScheduleStudentPayment);
                        }
                        userRoleMap.put(classGroupStudent.getUserId(), null);
                    }
                    studentDao.updateStudentServiceTag(null, studentIdList, YesOrNoEnum.YES.getCode());

                    courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);

                    imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(), classGroup.getName(),
                            vipGroup.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
                    imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
                    imUserFriendService.refreshGroupImUserFriend(classGroup.getMusicGroupId(), classGroup.getGroupType());
                }
                SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(userId);
                //插入缴费明细
                //收入
                SysUserCashAccountDetail sysUserIncomeCashAccountDetail = new SysUserCashAccountDetail();
                sysUserIncomeCashAccountDetail.setUserId(userId);
                sysUserIncomeCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
                sysUserIncomeCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
                sysUserIncomeCashAccountDetail.setAmount(order.getActualAmount());
                sysUserIncomeCashAccountDetail.setBalance(sysUserCashAccount.getBalance().add(order.getActualAmount()));
                sysUserIncomeCashAccountDetail.setAttribute(order.getTransNo());
                sysUserIncomeCashAccountDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                sysUserIncomeCashAccountDetail.setComAmount(studentPaymentOrder.getComAmount());
                sysUserIncomeCashAccountDetail.setPerAmount(studentPaymentOrder.getPerAmount());

                //支出
                SysUserCashAccountDetail sysUserExpendCashAccountDetail = new SysUserCashAccountDetail();
                sysUserExpendCashAccountDetail.setUserId(userId);
                sysUserExpendCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
                sysUserExpendCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
                sysUserExpendCashAccountDetail.setAmount(order.getActualAmount().negate());
                sysUserExpendCashAccountDetail.setBalance(sysUserCashAccount.getBalance());
                sysUserExpendCashAccountDetail.setAttribute(order.getTransNo());
                sysUserExpendCashAccountDetail.setChannel(studentPaymentOrder.getPaymentChannel());
                if (studentPaymentOrder.getComAmount() != null) {
                    sysUserExpendCashAccountDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
                }
                if (studentPaymentOrder.getPerAmount() != null) {
                    sysUserExpendCashAccountDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
                }

                sysUserCashAccountDetailService.insert(sysUserIncomeCashAccountDetail);
                sysUserCashAccountDetailService.insert(sysUserExpendCashAccountDetail);

                Map<Integer, String> map = new HashMap<>(1);
                map.put(userId, userId.toString());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_VIP_BUY, map, null, 0, "2", "STUDENT",
                        vipGroup.getName());

                //更新所属分部列表
                List<Integer> organIds = classGroupDao.findStudentOrganIdsByClassGroup(classGroup.getId().longValue());
                organIds.add(vipGroup.getOrganId());
                HashSet<Integer> hashSet = new HashSet<>(organIds);
                String organIdsString = StringUtils.join(hashSet, ",");
                vipGroup.setOrganIdList(organIdsString);
                vipGroupDao.update(vipGroup);
                try {
                    contractService.transferVipGroupCoursesContract(userId, vipGroup.getId());
                } catch (Exception e) {
                    LOGGER.error(MessageFormatter.arrayFormat("小课[{}]购买协议错误:{}", vipGroup.getId(), e.getMessage()), e);
                }
            }
        } else {
            classGroup.setStudentNum(classGroup.getStudentNum() - 1);
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().doubleValue() > 0) {
                sysUserCashAccountService.updateBalance(userId, studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS,
                        "VIP课购买失败");
            }
            sysCouponCodeService.quit(order.getCouponCodeId());
        }
        classGroupDao.update(classGroup);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void applyRefund(Long vipGroupId) {
        if (true) {
            throw new BizException("暂不支持退课");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (null == sysUser) {
            throw new BizException("获取用户信息失败");
        }
        Integer userId = sysUser.getId();
        StudentApplyRefunds studentApplyRefunds = new StudentApplyRefunds();
        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.findByStudentVipGroup(vipGroupId, userId, DealStatusEnum.SUCCESS.getCode());
        if (null == studentPaymentOrder) {
            throw new BizException("未找到相关订单信息！");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        //剩余课时数
        int surplusCourses = studentPaymentOrderDao.countSurplusCourseByMusicGroupAndUser(vipGroup.getId().toString(), userId);
        if (surplusCourses <= 0) {
            throw new BizException("此vip课程没有剩余排课");
        }
        Date now = new Date();
        BigDecimal surplusCourseFee;
        List<StudentCourseInfoDto> userCourseInfos = courseScheduleDao.findUserCourseInfos(GroupType.VIP, vipGroupId.toString(), userId, null);
        if (CollectionUtils.isEmpty(userCourseInfos) && vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING)) {
            if (Objects.isNull(studentPaymentOrder)) {
                surplusCourseFee = new BigDecimal(0);
            } else {
                surplusCourseFee = studentPaymentOrder.getActualAmount();
            }
        } else if (!CollectionUtils.isEmpty(userCourseInfos)) {
            BigDecimal historyPrice = new BigDecimal(0);
            BigDecimal allPrice = new BigDecimal(0);
            for (StudentCourseInfoDto userCourseInfo : userCourseInfos) {
                allPrice = allPrice.add(userCourseInfo.getExpectPrice());
                if (now.after(userCourseInfo.getStartClassTime())) {
                    historyPrice = historyPrice.add(userCourseInfo.getTeachMode().equals(TeachModeEnum.ONLINE) ? vipGroup.getOnlineClassesUnitPrice() : vipGroup.getOfflineClassesUnitPrice());
                }
            }
            surplusCourseFee = allPrice.subtract(historyPrice);
            if (surplusCourseFee.longValue() < 0) {
                surplusCourseFee = new BigDecimal(0);
            }
        } else {
            surplusCourseFee = new BigDecimal(0);
        }
        if (Objects.isNull(surplusCourseFee)) {
            surplusCourseFee = new BigDecimal(0);
        }
        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId().intValue());
        surplusCourseFee = sysUserCashAccountLogService.vipReturnFeeCharges(surplusCourseFee, vipGroupCategory == null ? 0 : vipGroupCategory.getStudentNum());

        studentApplyRefunds.setExpectAmount(surplusCourseFee);
        studentApplyRefunds.setStatus(StudentApplyRefundsStatus.ING);
        String orderNo = StringUtils.join(new String[]{userId.toString(), String.valueOf(System.currentTimeMillis())});
        studentApplyRefunds.setOrderNo(orderNo);
        studentApplyRefunds.setOrigPaymentOrderId(studentPaymentOrder.getId());
        studentApplyRefunds.setUserId(userId);
        studentApplyRefundsDao.insert(studentApplyRefunds);
        Map<String, Object> memo = new HashMap<>(2);
        memo.put("Id", studentApplyRefunds.getId());
        memo.put("type", "VIPGROUP");
        sendSeoMessageSource.sendSeoMessage(sysUser.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                JSONObject.toJSONString(memo), vipGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_STUDENT_APPLY_QUIT_COURSE, sysUser.getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult applyRefundForStudent(ReturnFeeDto returnFeeDto) {
        Long vipGroupId = returnFeeDto.getVipGroupId();
        Integer studentId = returnFeeDto.getStudentId();
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            throw new BizException("请指定小课与学生");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("指定的课程不存在");
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            throw new BizException("不能对已停止的课程进行此操作");
        }
        if (vipGroup.getName().startsWith("考前辅导课")) {
            throw new BizException("当前课程类型不支持退学");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId());

        List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsDao.findByGroupAndUser(vipGroupId.toString(), GroupType.VIP.getCode(), studentId);
        if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
            throw new BizException("此学生存在退课申请，请到系统日志中查看");
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(),
                studentId);

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            throw new BizException("指定学生不在此课程中");
        }

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT)) {
            throw new BizException("当前学生已经是退学状态");
        }
        BigDecimal amount = returnFeeDto.getAmount();
        if (!classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            if (Objects.isNull(amount)) {
                throw new BizException("请确定退费金额");
            }
            Map<String, BigDecimal> studentSurplusCourseFee = getStudentSurplusCourseFee(vipGroupId, studentId);
            BigDecimal suplusCourseFee = studentSurplusCourseFee.get("suplusCourseOriginalFee");
            if (amount.compareTo(suplusCourseFee) > 0) {
                throw new BizException("学员最大可退费金额为{}元", suplusCourseFee.toString());
            }
        }
        //退还活动购买
//        groupClassService.quitActivityGive(activityUserMapperService.findByStudentId(vipGroup.getId(), studentId));

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
            classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);
            studentPauseInfoDao.deleteUserPauseInfoWithGroup(GroupType.VIP, vipGroupId.toString(), studentId);

            classGroup.setStudentNum(classGroup.getStudentNum() - 1);
            classGroupDao.update(classGroup);
            return BaseController.succeed();
        }

//		sysUserCashAccountService.updateBalance(studentId, amount);
//		SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(studentId);
        //记录日志
        SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
        sysUserCashAccountLog.setUserId(studentId);
        sysUserCashAccountLog.setGroupType(VIP);
        sysUserCashAccountLog.setOrganId(vipGroup.getOrganId());
        sysUserCashAccountLog.setGroupId(vipGroupId.toString());
        sysUserCashAccountLog.setAmount(amount);
        sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.VIP);
        sysUserCashAccountLog.setComment("VIP退课");
        sysUserCashAccountLogDao.insert(sysUserCashAccountLog);

        classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
        classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);

        courseScheduleService.batchDeleteMusicGroupCourseWithStudent(vipGroupId.toString(), studentId, GroupType.VIP);

        List<Integer> studentPaymentIds = courseScheduleStudentPaymentDao.findNotStartCourseStudentPaymentIdsWithClassGroupAndStudent(classGroup.getId(), studentId);
        if (!CollectionUtils.isEmpty(studentPaymentIds)) {
            courseScheduleStudentPaymentDao.batchDeleteWithID(studentPaymentIds);
        }

        if (!vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING) || (Objects.nonNull(vipGroupCategory) && vipGroupCategory.getMusicTheory())) {
            courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroupId.intValue(), vipGroup.getUserId());
        }

        classGroup.setStudentNum(classGroup.getStudentNum() - 1);

        classGroupDao.update(classGroup);

        //学员退出班级群
        imGroupMemberService.quit(classGroup.getId().toString(), studentId);
        return BaseController.succeed();
    }

    @Override
    public void checkApplyRefundForStudentOa(ReturnFeeDto returnFeeDto) {
        Long vipGroupId = returnFeeDto.getVipGroupId();
        Integer studentId = returnFeeDto.getStudentId();
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            throw new BizException("请指定小课与学生");
        }
        SysUser user = teacherDao.getUser(studentId);
        if (user == null) {
            throw new BizException("用户 {} 信息不存在", studentId);
        }
        Student student = studentDao.get(studentId);
        if (student == null) {
            throw new BizException("学员 {} 信息不存在", studentId);
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("课程 {} 不存在", vipGroupId);
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            throw new BizException("课程 {} {} 已停止", vipGroupId, vipGroup.getName());
        }
        if (vipGroup.getName().startsWith("考前辅导课")) {
            throw new BizException("课程 {} {} 不支持退学", vipGroupId, vipGroup.getName());
        }

        List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsDao.findByGroupAndUser(vipGroupId.toString(), GroupType.VIP.getCode(), studentId);
        if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
            throw new BizException("学生 {} {} 存在退课申请", studentId, user.getUsername());
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(),
                studentId);

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            throw new BizException("学生 {} {} 不在此课程中", studentId, user.getUsername());
        }

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT)) {
            throw new BizException("学生 {} {} 已经是退学状态", studentId, user.getUsername());
        }
        BigDecimal amount = returnFeeDto.getAmount();
        if (!classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            if (Objects.isNull(amount)) {
                throw new BizException("请确定退费金额");
            }
            Map<String, BigDecimal> studentSurplusCourseFee = getStudentSurplusCourseFee(vipGroupId, studentId);
            BigDecimal suplusCourseFee = studentSurplusCourseFee.get("suplusCourseOriginalFee");
            if (amount.compareTo(suplusCourseFee) > 0) {
                throw new BizException("学员 {} {} 最大可退费金额为{}元", studentId, user.getUsername(), suplusCourseFee.toString());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyRefundForStudentOa(ReturnFeeDto returnFeeDto) {
        Long vipGroupId = returnFeeDto.getVipGroupId();
        Integer studentId = returnFeeDto.getStudentId();
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            return;
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            return;
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            return;
        }
        if (vipGroup.getName().startsWith("考前辅导课")) {
            return;
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId());

        List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsDao.findByGroupAndUser(vipGroupId.toString(), GroupType.VIP.getCode(), studentId);
        if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
            return;
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(),
                studentId);

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            return;
        }

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT)) {
            return;
        }
        BigDecimal amount = returnFeeDto.getAmount();
        if (!classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            if (Objects.isNull(amount)) {
                return;
            }
//			Map<String, BigDecimal> studentSurplusCourseFee = getStudentSurplusCourseFee(vipGroupId, studentId);
//			BigDecimal suplusCourseFee = studentSurplusCourseFee.get("suplusCourseOriginalFee");
//			if(amount.compareTo(suplusCourseFee) > 0){
//				throw new BizException("学员最大可退费金额为{}元", suplusCourseFee.toString());
//			}
        }
        //退还活动购买
//        ActivityUserMapper activityUserMapper = activityUserMapperService.findByStudentId(vipGroup.getId(), studentId);
//        HttpResponseResult result = groupClassService.quitActivityGive(activityUserMapper, returnFeeDto.getConfirmReturnActivityGive(), vipGroup.getId(), VIP);

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
            classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);
            studentPauseInfoDao.deleteUserPauseInfoWithGroup(GroupType.VIP, vipGroupId.toString(), studentId);

            classGroup.setStudentNum(classGroup.getStudentNum() - 1);
            classGroupDao.update(classGroup);
            return;
        }

        //记录日志
        SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
        sysUserCashAccountLog.setUserId(studentId);
        sysUserCashAccountLog.setGroupType(VIP);
        sysUserCashAccountLog.setOrganId(vipGroup.getOrganId());
        sysUserCashAccountLog.setGroupId(vipGroupId.toString());
        sysUserCashAccountLog.setAmount(amount);
        sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.VIP);
        sysUserCashAccountLog.setComment("OA审批VIP退课");
        sysUserCashAccountLogDao.insert(sysUserCashAccountLog);

        classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
        classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);

        courseScheduleService.batchDeleteMusicGroupCourseWithStudent(vipGroupId.toString(), studentId, GroupType.VIP);

        List<Integer> studentPaymentIds = courseScheduleStudentPaymentDao.findNotStartCourseStudentPaymentIdsWithClassGroupAndStudent(classGroup.getId(), studentId);
        if (!CollectionUtils.isEmpty(studentPaymentIds)) {
            courseScheduleStudentPaymentDao.batchDeleteWithID(studentPaymentIds);
        }

        if (!vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING) || (Objects.nonNull(vipGroupCategory) && vipGroupCategory.getMusicTheory())) {
            courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroupId.intValue(), vipGroup.getUserId());
        }

        classGroup.setStudentNum(classGroup.getStudentNum() - 1);

        classGroupDao.update(classGroup);

        //学员退出班级群
        imGroupMemberService.quit(classGroup.getId().toString(), studentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pauseForStudent(Long vipGroupId, Integer studentId) {
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            throw new BizException("请指定小课与学生");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("指定的课程不存在");
        }
        if (!VipGroupStatusEnum.PROGRESS.equals(vipGroup.getStatus())) {
            throw new BizException("当前课程组状态非进行中，无法进行该操作");
        }
        List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsDao.findByGroupAndUser(vipGroupId.toString(), GroupType.VIP.getCode(), studentId);
        if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
            throw new BizException("此学生存在退课申请，请到系统日志中查看");
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(),
                studentId);

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            throw new BizException("指定学生不在此课程中");
        }

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT)) {
            throw new BizException("当前学生已经退学");
        }

        if (classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            throw new BizException("当前学生已是休学状态");
        }

        BigDecimal surplusCourseFee = courseScheduleStudentPaymentDao.countSurplusCourseFee(classGroup.getId(), studentId);

        if (Objects.isNull(surplusCourseFee)) {
            surplusCourseFee = new BigDecimal(0);
        }

        Map<String, Object> pauseInfos = new HashMap<>();
        //学生剩余课时
        List<StudentCourseInfoDto> userSurplusCourseInfoByGroup = courseScheduleDao.findUserSurplusCourseInfoByGroup(GroupType.VIP, vipGroupId.toString(), studentId);

        int[] teachModeSequence = new int[userSurplusCourseInfoByGroup.size()];
        List<BigDecimal> coursePrices = new ArrayList<>();
        List<Long> courseScheduleIds = new ArrayList<>();
        for (int i = 0; i < userSurplusCourseInfoByGroup.size(); i++) {
            teachModeSequence[i] = userSurplusCourseInfoByGroup.get(i).getTeachMode().equals(TeachModeEnum.ONLINE) ? 1 : 0;
            coursePrices.add(userSurplusCourseInfoByGroup.get(i).getExpectPrice());
            courseScheduleIds.add(userSurplusCourseInfoByGroup.get(i).getId());
        }
        pauseInfos.put("teaChModeSequence", teachModeSequence);
        pauseInfos.put("coursePriceInfo", coursePrices);

        StudentPauseInfo studentPauseInfo = new StudentPauseInfo();
        studentPauseInfo.setUserId(studentId);
        studentPauseInfo.setGroupType(GroupType.VIP);
        studentPauseInfo.setMusicGroupId(vipGroup.getId().intValue());
        studentPauseInfo.setClassGroupId(classGroup.getId());
        studentPauseInfo.setCoursesJson(JSON.toJSONString(pauseInfos));
        studentPauseInfo.setSurplusCourseNum(userSurplusCourseInfoByGroup.size());

        studentPauseInfoDao.insert(studentPauseInfo);

//        sysUserCashAccountService.appendCourseBalance(studentId, surplusCourseFee, PlatformCashAccountDetailTypeEnum.REFUNDS, "学生休学剩余课时转化为课程余额");

        classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT_SCHOOL);
        classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);

        if (!CollectionUtils.isEmpty(courseScheduleIds)) {
            studentAttendanceDao.deleteByCourseAndUser(courseScheduleIds, studentId);
        }

        List<CourseScheduleStudentPayment> studentPayments = courseScheduleStudentPaymentDao.findNotStartCourseStudentPaymentsWithClassGroupAndStudent(classGroup.getId(), studentId);
        if (!CollectionUtils.isEmpty(studentPayments)) {
            //学员休学转化排课资格
            activityUserMapperService.subCourseConvert(studentPayments,studentId,vipGroup.getSingleClassMinutes(),vipGroup.getVipGroupCategoryId());
            List<Integer> studentPaymentIds = studentPayments.stream().map(e -> e.getId().intValue()).collect(Collectors.toList());
            courseScheduleStudentPaymentDao.batchDeleteWithID(studentPaymentIds);
        }

        int studentCourseNum = classGroupStudentMapperDao.countClassGroupNormalStudentNum(classGroup.getId());
        if (studentCourseNum <= 0 && classGroup.getStudentNum().equals(classGroup.getExpectStudentNum())) {
            vipGroup.setStatus(VipGroupStatusEnum.PAUSE);
            List<CourseSchedule> groupNotFinishCourses = courseScheduleDao.findGroupNotFinishCourses(vipGroupId.toString(), GroupType.VIP);
            List<Long> csIds = groupNotFinishCourses.stream().map(CourseSchedule::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(csIds)) {
                courseScheduleTeacherSalaryDao.batchDeleteByCourseScheduleIds(csIds);
                courseScheduleDao.batchDeleteCourseSchedules(csIds);
                teacherAttendanceDao.batchDeleteByCourseSchedules(csIds);
            }
            vipGroupDao.update(vipGroup);
        }

        courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroupId.intValue(), vipGroup.getUserId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void recoverForStudent(StudentRecoverDto studentRecoverInfo) {
        if (Objects.isNull(studentRecoverInfo.getVipGroupId()) || Objects.isNull(studentRecoverInfo.getUserId())) {
            throw new BizException("请指定小课与学生");
        }
        Date now = new Date();
        VipGroup vipGroup = vipGroupDao.get(studentRecoverInfo.getVipGroupId().longValue());
        if (Objects.isNull(vipGroup)) {
            throw new BizException("指定的课程不存在");
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            throw new BizException("不能对已停止的课程进行此操作");
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.FINISHED)) {
            throw new BizException("此课程已结束");
        }
        List<StudentApplyRefunds> studentApplyRefunds = studentApplyRefundsDao.findByGroupAndUser(studentRecoverInfo.getVipGroupId().toString(), GroupType.VIP.getCode(), studentRecoverInfo.getUserId());
        if (!CollectionUtils.isEmpty(studentApplyRefunds)) {
            throw new BizException("此学生存在退课申请，请到系统日志中查看");
        }
        VipGroupDefaultClassesUnitPrice vipGroupDefaultClassesUnitPrice = vipGroupDefaultClassesUnitPriceDao.getByVipGroup(vipGroup.getId());
        if (Objects.isNull(vipGroupDefaultClassesUnitPrice)) {
            throw new BizException("课程单价设置错误");
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(studentRecoverInfo.getVipGroupId().longValue(), null);

        Integer oldTeacherId = vipGroup.getUserId();
        if (Objects.nonNull(studentRecoverInfo.getTeacherId()) && !studentRecoverInfo.getTeacherId().equals(vipGroup.getUserId())) {
            vipGroup.setUserId(studentRecoverInfo.getTeacherId());

            imGroupMemberService.quit(classGroup.getId().toString(), oldTeacherId);

            imGroupMemberService.join(classGroup.getId().toString(), vipGroup.getUserId(), "指导老师", false);
        }

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(),
                studentRecoverInfo.getUserId());

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            throw new BizException("指定学生不在此课程中");
        }

        if (!classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            throw new BizException("当前学生不是休学状态");
        }

        StudentPauseInfo studentPauseInfo = studentPauseInfoDao.findByGroupAndUser(GroupType.VIP, studentRecoverInfo.getVipGroupId().toString(), studentRecoverInfo.getUserId());
        if (Objects.isNull(studentPauseInfo)) {
            throw new BizException("未找到休学信息");
        }

        classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.NORMAL);
        classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);

        if (Objects.nonNull(studentRecoverInfo.getTeacherId())) {
            vipGroup.setUserId(studentRecoverInfo.getTeacherId());
        }

        Map<String, Object> courseInfo = JSON.parseObject(studentPauseInfo.getCoursesJson(), Map.class);
        List<BigDecimal> coursePrices = (List<BigDecimal>) courseInfo.get("coursePriceInfo");
        coursePrices.sort(Comparator.naturalOrder());
        Collections.reverse(coursePrices);

        if (vipGroup.getStatus().equals(VipGroupStatusEnum.PAUSE)) {
            List<StudentPauseInfo> studentPauseInfos = studentPauseInfoDao.findByGroup(GroupType.VIP, vipGroup.getId().toString());
            StudentPauseInfo studentPauseInfo1 = studentPauseInfos.stream().min(Comparator.comparing(StudentPauseInfo::getSurplusCourseNum)).get();
            Map<String, Object> courseInfo1 = JSON.parseObject(studentPauseInfo1.getCoursesJson(), Map.class);
            Integer[] teachModeSequence1 = JSON.parseArray(courseInfo1.get("teaChModeSequence").toString(), Integer.class).stream().toArray(Integer[]::new);
            if (teachModeSequence1.length <= 0) {
                throw new BizException("此学员无剩余课时");
            }
            studentRecoverInfo.setCourseCount(teachModeSequence1.length);
            List<CourseSchedule> newCourseSchedules = courseScheduleService.createCourses(studentRecoverInfo, false);
            for (int i = 0; i < newCourseSchedules.size(); i++) {
                CourseSchedule courseSchedule = newCourseSchedules.get(i);
                if (courseSchedule.getStartClassTime().before(now)) {
                    throw new BizException("排课起始时间不得小于当前时间");
                }
                courseSchedule.setName(vipGroup.getName());
                courseSchedule.setGroupType(GroupType.VIP);
                courseSchedule.setMusicGroupId(vipGroup.getId().toString());
                courseSchedule.setClassGroupId(classGroup.getId());
                courseSchedule.setStatus(CourseStatusEnum.NOT_START);
                courseSchedule.setActualTeacherId(vipGroup.getUserId());
                courseSchedule.setTeacherId(vipGroup.getUserId());
                courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
                courseSchedule.setTeachMode(teachModeSequence1[i] == 0 ? TeachModeEnum.OFFLINE : TeachModeEnum.ONLINE);
                if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                    courseSchedule.setSchoolId(vipGroup.getTeacherSchoolId());
                }
                courseSchedule.setOrganId(vipGroup.getOrganId());
            }

            CourseSchedule courseSchedule = newCourseSchedules.stream().max(Comparator.comparing(CourseSchedule::getClassDate)).get();
            if (vipGroup.getCoursesExpireDate().compareTo(courseSchedule.getEndClassTime()) <= 0 && !DateUtil.isSameDay(vipGroup.getCoursesExpireDate(), courseSchedule.getEndClassTime())) {
                throw new BizException("排课时间不可超过{}", DateUtil.dateToString(vipGroup.getCoursesExpireDate(), "yyyy年MM月dd日"));
            }

            courseScheduleService.batchAddCourseSchedule(newCourseSchedules);

            ClassGroupTeacherMapper oldClassGroupTeacherMapper = classGroupTeacherMapperDao.findByClassGroupAndTeacher(classGroup.getId(), oldTeacherId);
            if (Objects.nonNull(oldClassGroupTeacherMapper)) {
                ClassGroupTeacherMapper classGroupTeacherMapper = new ClassGroupTeacherMapper();
                BeanUtils.copyProperties(oldClassGroupTeacherMapper, classGroupTeacherMapper);
                classGroupTeacherMapper.setUserId(vipGroup.getUserId());
                classGroupTeacherMapper.setCreateTime(now);
                classGroupTeacherMapper.setUpdateTime(now);
                classGroupTeacherMapperDao.delete(oldClassGroupTeacherMapper.getId());
                classGroupTeacherMapperDao.insert(classGroupTeacherMapper);
            }

            Map<String, BigDecimal> salaryMap = countVipGroupPredictFee1(vipGroup, vipGroup.getUserId(), null);
            BigDecimal teacherSalary = salaryMap.get("offlineTeacherSalary");
            //是否是赠送课程
            ActivityUserMapper activityUserMapper = activityUserMapperService.findVipUserMapper(vipGroup.getId(), "VIP", null);
            if (activityUserMapper != null) {
                if (vipGroup.getId().equals(activityUserMapper.getGiveVipGroupId())) {
                    teacherSalary = salaryMap.get("giveOfflineTeacherSalary");
                }
            }
            //创建老师单节课课酬信息
            courseScheduleTeacherSalaryService.createCourseScheduleTeacherVipSalary(vipGroup,
                    newCourseSchedules, teacherSalary);
        }

        BigDecimal surplusCourseFee = new BigDecimal(0);

        List<CourseSchedule> surplusCourseWithGroup = courseScheduleDao.findSurplusCourseWithGroup(GroupType.VIP, studentRecoverInfo.getVipGroupId().toString());
        surplusCourseWithGroup.sort(Comparator.comparing(CourseSchedule::getStartClassTime));

        if (coursePrices.size() < surplusCourseWithGroup.size()) {
            throw new BizException("剩余课时不足,无法与现有课时对齐");
        }


        CourseSchedule lastCourseSchedule = surplusCourseWithGroup.stream().max(Comparator.comparing(CourseSchedule::getClassDate)).get();
        if (vipGroup.getCoursesExpireDate().compareTo(lastCourseSchedule.getEndClassTime()) <= 0 && !DateUtil.isSameDay(vipGroup.getCoursesExpireDate(), lastCourseSchedule.getEndClassTime())) {
            throw new BizException("排课时间不可超过{}", DateUtil.dateToString(vipGroup.getCoursesExpireDate(), "yyyy年MM月dd日"));
        }

        List<CourseScheduleStudentPayment> courseScheduleStudentPaymentList = new ArrayList<>();
        //获取账户信息
        SysUserCashAccount cashAccount = sysUserCashAccountService.getLocked(studentRecoverInfo.getUserId());
        if (cashAccount == null) {
            throw new BizException("用户[{}]现金账户不存在", studentRecoverInfo.getUserId());
        }
        BigDecimal courseBalance = cashAccount.getCourseBalance();
        //获取学员排课资格
        List studentIdList = new ArrayList<>();
        studentIdList.add(studentRecoverInfo.getUserId());
        //获取学员付费排课资格
        List<ActivityUserMapper> activityUserMappers = activityUserMapperService.getDao().findByStudents(studentIdList,vipGroup.getVipGroupCategoryId(),vipGroup.getSingleClassMinutes());
        //获取学员赠送排课资格
        List<ActivityUserMapper> freeActivityUserMappers = activityUserMapperService.getDao().findByStudents1(studentIdList,vipGroup.getVipGroupCategoryId(),vipGroup.getSingleClassMinutes());
        BaseMapDto<Integer, Integer> indexDto = new BaseMapDto<>(0, 0);
        for (int i = 0; i < surplusCourseWithGroup.size(); i++) {
            CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
            BigDecimal actualPrice = coursePrices.get(i);
            courseScheduleStudentPayment.setExpectPrice(actualPrice);
            courseScheduleStudentPayment.setActualPrice(actualPrice);
            //按课扣除课程余额
            if(courseBalance.compareTo(actualPrice) >= 0){
                courseBalance = courseBalance.subtract(actualPrice);
            }else {
                //扣除排课资格
                activityUserMapperService.use(activityUserMappers,freeActivityUserMappers,indexDto,vipGroup.getId(),courseScheduleStudentPayment);
            }
            courseScheduleStudentPayment.setGroupType(GroupType.VIP);
            courseScheduleStudentPayment.setMusicGroupId(studentRecoverInfo.getVipGroupId().toString());
            courseScheduleStudentPayment.setMusicGroupId(classGroup.getMusicGroupId());
            courseScheduleStudentPayment.setCourseScheduleId(surplusCourseWithGroup.get(i).getId());
            courseScheduleStudentPayment.setUserId(studentRecoverInfo.getUserId());
            courseScheduleStudentPayment.setOriginalPrice(TeachModeEnum.ONLINE.equals(surplusCourseWithGroup.get(i)) ? vipGroupDefaultClassesUnitPrice.getOnlineClassesUnitPrice() : vipGroupDefaultClassesUnitPrice.getOfflineClassesUnitPrice());
            courseScheduleStudentPayment.setCreateTime(now);
            courseScheduleStudentPayment.setUpdateTime(now);
            courseScheduleStudentPayment.setClassGroupId(classGroup.getId());
            courseScheduleStudentPaymentList.add(courseScheduleStudentPayment);
            surplusCourseFee = surplusCourseFee.add(coursePrices.get(i));
        }
        if (!CollectionUtils.isEmpty(courseScheduleStudentPaymentList)) {
            studentDao.updateStudentServiceTag(studentRecoverInfo.getUserId(), null, YesOrNoEnum.YES.getCode());
            courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPaymentList);
        }
        //扣余额，如果余额不足，那么扣排课资格
        if(cashAccount.getCourseBalance().compareTo(courseBalance) != 0){
            sysUserCashAccountService.appendCourseBalance(studentRecoverInfo.getUserId(), cashAccount.getCourseBalance().subtract(courseBalance).negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "学生复学扣除课程余额");
        }
        //更新资格
        if(!CollectionUtils.isEmpty(activityUserMappers)){
            activityUserMapperService.getDao().batchUpdate(activityUserMappers);
        }
        if(!CollectionUtils.isEmpty(freeActivityUserMappers)){
            activityUserMapperService.getDao().batchUpdateFree(freeActivityUserMappers);
        }
        studentPauseInfo.setDelFlag(1);
        studentPauseInfoDao.update(studentPauseInfo);
        vipGroup.setStatus(VipGroupStatusEnum.PROGRESS);
        vipGroupDao.update(vipGroup);
        classGroup.setTotalClassTimes(courseScheduleDao.countClassGroupCourses(classGroup.getId()));
        classGroupDao.update(classGroup);
        courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroup.getId().intValue(), oldTeacherId);
        imUserFriendService.refreshGroupImUserFriend(classGroup.getMusicGroupId(), classGroup.getGroupType());
    }

    @Override
    public StudentRecoverInfoDto getStudentPauseInfo(Long vipGroupId, Integer studentId) {
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            throw new BizException("请指定小课与学生");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("指定的课程不存在");
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            throw new BizException("不能对已停止的课程进行此操作");
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(classGroup.getId(), studentId);

        if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
            throw new BizException("未找到指定学生");
        }

        if (!classStudentMapperByUserIdAndClassGroupId.getStatus().equals(ClassGroupStudentStatusEnum.QUIT_SCHOOL)) {
            throw new BizException("当前学生不是休学状态");
        }

        StudentPauseInfo studentPauseInfo = studentPauseInfoDao.findByGroupAndUser(GroupType.VIP, vipGroupId.toString(), studentId);
        if (Objects.isNull(studentPauseInfo)) {
            throw new BizException("未找到此学生休学信息");
        }
        Map<String, Object> courseInfo = JSON.parseObject(studentPauseInfo.getCoursesJson(), Map.class);
        List<BigDecimal> coursePrices = (List<BigDecimal>) courseInfo.get("coursePriceInfo");

        StudentRecoverInfoDto studentRecoverInfoDto = new StudentRecoverInfoDto();
        studentRecoverInfoDto.setVipGroupId(vipGroupId.intValue());
        studentRecoverInfoDto.setTeacherId(vipGroup.getUserId());
        studentRecoverInfoDto.setStudentId(studentPauseInfo.getUserId());
        studentRecoverInfoDto.setIsPause(vipGroup.getStatus().equals(VipGroupStatusEnum.PAUSE) ? 1 : 0);
        Map<BigDecimal, Long> collect = coursePrices.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
        studentRecoverInfoDto.setGiveCourseTimes(Objects.isNull(collect.get(new BigDecimal("0.00"))) ? 0 : collect.get(new BigDecimal("0.00")).intValue());
        studentRecoverInfoDto.setTotalCourseTimes(coursePrices.size() - studentRecoverInfoDto.getGiveCourseTimes());
        studentRecoverInfoDto.setExpireDate(vipGroup.getCoursesExpireDate());

        return studentRecoverInfoDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, BigDecimal> getStudentSurplusCourseFee(Long vipGroupId, Integer studentId) {
        if (Objects.isNull(vipGroupId) || Objects.isNull(studentId)) {
            throw new BizException("请指定课程和学生");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("未找到指定vip课");
        }
        if (vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
            throw new BizException("不能对已停止的课程进行退课操作");
        }
        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId().intValue());
        Map<String, BigDecimal> result = new HashMap<>();
        Date now = new Date();
        BigDecimal bigDecimal = ZERO;
        List<StudentCourseInfoDto> userCourseInfos  = courseScheduleDao.findUserCourseInfos(GroupType.VIP, vipGroupId.toString(), studentId, null);

        if (CollectionUtils.isEmpty(userCourseInfos) && vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING)) {
            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.findByStudentVipGroup(vipGroupId, studentId, DealStatusEnum.SUCCESS.getCode());
            if (Objects.nonNull(studentPaymentOrder)) {
                bigDecimal = studentPaymentOrder.getActualAmount().add(studentPaymentOrder.getBalancePaymentAmount());
            }
            result.put("suplusCourseOriginalFee", bigDecimal);
        } else if (!CollectionUtils.isEmpty(userCourseInfos)) {
            BigDecimal historyPrice = ZERO;
            BigDecimal allPrice = ZERO;
            int overNum = 0;
            for (StudentCourseInfoDto userCourseInfo : userCourseInfos) {
                allPrice = allPrice.add(userCourseInfo.getExpectPrice());
                if (now.after(userCourseInfo.getStartClassTime())) {
                    overNum++;
                    historyPrice = historyPrice.add(userCourseInfo.getOriginalPrice());
                }
            }
            bigDecimal = allPrice.subtract(historyPrice);
            if (bigDecimal.compareTo(ZERO) < 0 || overNum == userCourseInfos.size()) {
                bigDecimal = ZERO;
            }
            result.put("suplusCourseOriginalFee", allPrice);
        } else {
            result.put("suplusCourseOriginalFee", bigDecimal);
        }
        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);
        if (Objects.isNull(classGroup)) {
            throw new BizException("未找到对应班级");
        }
        bigDecimal = sysUserCashAccountLogService.vipReturnFeeCharges(bigDecimal, vipGroupCategory == null ? 0 : vipGroupCategory.getStudentNum());
        result.put("suplusCourseFee", bigDecimal);

        if (VipGroupStatusEnum.APPLYING.equals(vipGroup.getStatus())) {
            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.findByStudentVipGroup(vipGroupId, studentId, DealStatusEnum.SUCCESS.getCode());
            if (Objects.nonNull(studentPaymentOrder)) {
                BigDecimal suplusCourseOriginalFee = studentPaymentOrder.getActualAmount().add(studentPaymentOrder.getBalancePaymentAmount());
                result.put("suplusCourseOriginalFee", suplusCourseOriginalFee);
                result.put("suplusCourseFee", sysUserCashAccountLogService.vipReturnFeeCharges(suplusCourseOriginalFee, vipGroupCategory == null ? 0 : vipGroupCategory.getStudentNum()));
            }
        }
        return result;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public HttpResponseResult applyRefundAudit(Long id, StudentApplyRefundsStatus status, String remark, BigDecimal amount, boolean confirmReturnActivityGive) {

        StudentApplyRefunds studentApplyRefunds = studentApplyRefundsDao.get(id);
        if (studentApplyRefunds == null) {
            throw new BizException("退课申请记录不存在");
        }

        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.get(studentApplyRefunds.getOrigPaymentOrderId());
        if (null == studentPaymentOrder) {
            throw new BizException("未找到原订单信息！");
        }

        if (status == StudentApplyRefundsStatus.ING) {
            throw new BizException("状态不正确");
        }
        VipGroup vipGroup = vipGroupDao.get(id);
        studentApplyRefunds.setStatus(status);
        if (studentApplyRefunds.getStatus() == StudentApplyRefundsStatus.DONE) {
            //退还活动购买

//            ActivityUserMapper activityUserMapper = activityUserMapperService.findByStudentId(vipGroup.getId(), studentPaymentOrder.getUserId());
//            HttpResponseResult result = groupClassService.quitActivityGive(activityUserMapper, confirmReturnActivityGive, id, VIP);
//            if (result.getCode() != 200) {
//                return result;
//            }
            studentApplyRefunds.setActualAmount(amount);
        } else {
            studentApplyRefunds.setActualAmount(new BigDecimal(0));
        }
        studentApplyRefunds.setRemark(remark);
        studentApplyRefunds.setUpdateTime(new Date());
        studentApplyRefundsDao.update(studentApplyRefunds);
        switch (studentApplyRefunds.getStatus()) {
            case DONE:
//				sysUserCashAccountService.updateBalance(studentApplyRefunds.getUserId(), studentApplyRefunds.getActualAmount());
//				SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(studentApplyRefunds.getUserId().intValue());
                //记录日志
                SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
                sysUserCashAccountLog.setGroupId(vipGroup.getId().toString());
                sysUserCashAccountLog.setUserId(studentApplyRefunds.getUserId());
                sysUserCashAccountLog.setGroupType(VIP);
                sysUserCashAccountLog.setOrganId(vipGroup.getOrganId());
                sysUserCashAccountLog.setAmount(amount);
                sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.VIP);
                sysUserCashAccountLog.setComment("VIP退课审核");
                sysUserCashAccountLogDao.insert(sysUserCashAccountLog);

                ClassGroupStudentMapper classStudentMapperByUserIdAndClassGroupId = classGroupStudentMapperDao.query(studentPaymentOrder.getClassGroupId(),
                        studentPaymentOrder.getUserId());

                if (Objects.isNull(classStudentMapperByUserIdAndClassGroupId)) {
                    throw new BizException("此学员不在指定班级上");
                }

                classStudentMapperByUserIdAndClassGroupId.setStatus(ClassGroupStudentStatusEnum.QUIT);
                classGroupStudentMapperDao.update(classStudentMapperByUserIdAndClassGroupId);

//				ClassGroup classGroup=new ClassGroup();
//				classGroup.setId(classStudentMapperByUserIdAndClassGroupId.getClassGroupId());
//				classGroup.setStudentNum(classGroupStudentMapperDao.countClassGroupStudentNum(classGroup.getId()));
//				classGroupDao.update(classGroup);

                List<Integer> studentPaymentIds = courseScheduleStudentPaymentDao.findNotStartCourseStudentPaymentIdsWithClassGroupAndStudent(classStudentMapperByUserIdAndClassGroupId.getClassGroupId(), studentApplyRefunds.getUserId());
                if (!CollectionUtils.isEmpty(studentPaymentIds)) {
                    courseScheduleStudentPaymentDao.batchDeleteWithID(studentPaymentIds);
                }

                courseScheduleService.batchDeleteMusicGroupCourseWithStudent(studentPaymentOrder.getMusicGroupId(), studentApplyRefunds.getUserId(), GroupType.VIP);


                courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(Integer.parseInt(studentPaymentOrder.getMusicGroupId()), null);

                //学员退出班级群
                imGroupMemberService.quit(studentPaymentOrder.getClassGroupId().toString(), studentApplyRefunds.getUserId());

                break;
            case REJECT:

                break;
            default:
                throw new BizException("审核状态错误!");
        }
        return BaseController.succeed();
    }

    @Override
    public Map<String, Object> findVipGroupSalarys(VipGroupSalaryQueryInfo queryInfo) {

        if (Objects.isNull(queryInfo.getVipGroupId())) {
            throw new BizException("请指定vip课程!");
        }

        VipGroup vipGroup = vipGroupDao.get(queryInfo.getVipGroupId());

        if (Objects.isNull(vipGroup)) {
            throw new BizException("未找到指定vip课");
        }

        PageInfo pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<VipGroupSalaryDto> dataList = null;
        int count = courseScheduleTeacherSalaryDao.countVipGroupSalarys(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = courseScheduleTeacherSalaryDao.findVipGroupSalarys(params);
            List<Long> courseScheduleIds = dataList.stream().map(VipGroupSalaryDto::getCourseScheduleId).collect(Collectors.toList());
            List<Map<Integer, BigDecimal>> courseAmountMapList = courseScheduleTeacherSalaryDao.countActualAmount(courseScheduleIds);
            Map<Integer, BigDecimal> courseAmountMap = MapUtil.convertIntegerMap(courseAmountMapList);
            if (!CollectionUtils.isEmpty(dataList)) {
                dataList.forEach(vipGroupSalaryDto -> {
                    if (Objects.isNull(vipGroupSalaryDto.getExpectSalary())) {
                        vipGroupSalaryDto.setExpectSalary(new BigDecimal(0));
                    }
                    if (Objects.isNull(vipGroupSalaryDto.getActualSalary())) {
                        vipGroupSalaryDto.setActualSalary(new BigDecimal(0));
                        vipGroupSalaryDto.setDeductionFee(new BigDecimal(0));
                        vipGroupSalaryDto.setIsSalary(YesOrNoEnum.NO);
                    } else {
                        vipGroupSalaryDto.setDeductionFee(vipGroupSalaryDto.getExpectSalary().subtract(vipGroupSalaryDto.getActualSalary()));
                        vipGroupSalaryDto.setIsSalary(YesOrNoEnum.YES);
                    }
                    BigDecimal actualAmount = courseAmountMap.get(vipGroupSalaryDto.getCourseScheduleId());
                    if (Objects.nonNull(actualAmount)) {
                        vipGroupSalaryDto.setDeductionFee(actualAmount);
                    }
                });
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);

        VipGroupSalaryBaseInfo vipGroupSalaryBaseInfo = vipGroupDao.getVipGroupSalaryInfo(queryInfo.getVipGroupId());
        if (Objects.isNull(vipGroupSalaryBaseInfo)) {
            vipGroupSalaryBaseInfo = new VipGroupSalaryBaseInfo();
        }
        //预计总课酬
        if (Objects.isNull(vipGroupSalaryBaseInfo.getExpectTotalSalary())) {
            vipGroupSalaryBaseInfo.setExpectTotalSalary(new BigDecimal(0));
        }
        //实际总课酬
        if (Objects.isNull(vipGroupSalaryBaseInfo.getTotalSalary())) {
            vipGroupSalaryBaseInfo.setTotalSalary(new BigDecimal(0));
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroup.getId(), null);

        //扣费笔数
        vipGroupSalaryBaseInfo.setFeeDeductionNum(vipGroupDao.countStudentPaymentNum(classGroup.getId()));
        //扣费总额
        if (vipGroupSalaryBaseInfo.getFeeDeductionNum() > 0) {
            vipGroupSalaryBaseInfo.setTotalFeeDeduction(vipGroupDao.countStudentPaymentFee(classGroup.getId()));
        } else {
            vipGroupSalaryBaseInfo.setTotalFeeDeduction(new BigDecimal(0));
        }

        BigDecimal totalCoursePrice = studentPaymentOrderDao.sumGroupIncomeFee(vipGroup.getId());
        if (Objects.isNull(totalCoursePrice)) {
            totalCoursePrice = new BigDecimal(0);
        }

        //课程总价
        vipGroupSalaryBaseInfo.setTotalCoursePrice(totalCoursePrice);

        List<Map<String, BigDecimal>> teacherSalaryCount = courseScheduleTeacherSalaryDao.countTeacherOnlineOfflineSalaryByClass(classGroup.getId());
        Map<String, BigDecimal> teacherTeachModeSalaryMap = MapUtil.convertIntegerMap(teacherSalaryCount);
        vipGroupSalaryBaseInfo.setTotalOfflineTeacherSalary(teacherTeachModeSalaryMap.get(TeachModeEnum.OFFLINE.getCode()));
        vipGroupSalaryBaseInfo.setTotalOnlineTeacherSalary(teacherTeachModeSalaryMap.get(TeachModeEnum.ONLINE.getCode()));

        Map<String, Object> result = new HashMap<>();
        result.put("pageInfo", pageInfo);
        result.put("baseInfo", vipGroupSalaryBaseInfo);
        return result;
    }

    @Override
    public List<String> findVipGroupAttendanceStudents(Long courseScheduleId) {
        if (Objects.isNull(courseScheduleId)) {
            throw new BizException("请指定课程");
        }
        return courseScheduleDao.findStudentNamesByCourseSchedule(courseScheduleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stopGroup(Long vipGroupId, String stopReason) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定vip课");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("该课程不存在");
        }
        if (vipGroup.getStatus() == VipGroupStatusEnum.CANCEL) {
            throw new BizException("该课程已结束或者已被停止,无法进行此操作");
        }
        ClassGroup classGroup = classGroupDao.findByMusicGroupAndType(vipGroupId.toString(), "VIP");
        if (Objects.isNull(classGroup)) {
            throw new BizException("班级不存在");
        }
        vipGroup.setStopReason(stopReason);
        List<Long> courseScheduleIds = courseScheduleDao.findVipGroupNotStartCourseScheduleIds(vipGroupId.toString(), GroupType.VIP.getCode());
        if (vipGroup.getStatus() == VipGroupStatusEnum.NOT_START) {
            vipGroup.setStatus(VipGroupStatusEnum.CANCEL);
            vipGroupDao.update(vipGroup);
            classGroup.setDelFlag(1);
            classGroupDao.update(classGroup);
            if (courseScheduleIds != null && courseScheduleIds.size() > 0) {
                courseScheduleDao.batchDeleteCourseSchedules(courseScheduleIds);
                courseScheduleTeacherSalaryDao.batchDeleteByCourseScheduleIds(courseScheduleIds);
            }
            teacherPush(vipGroup);
//			stopVipPush(vipGroup.getId(),vipGroup.getName());
            return;
        }

        Integer studentNum = classGroupStudentMapperDao.countClassGroupStudentNum(classGroup.getId());
        if (studentNum > 0) {
            throw new BizException("无法停止课程，需要全部学员退学后，才能停止，请先操作学员退学。");
        }

        List<Map<Integer, BigDecimal>> maps = vipGroupDao.countSurplusCourseFee(vipGroupId);
        if (CollectionUtils.isEmpty(maps) || (maps.size() == 1 && Objects.isNull(maps.get(0)))) {
            if (courseScheduleIds != null && courseScheduleIds.size() > 0) {
                courseScheduleDao.batchDeleteCourseSchedules(courseScheduleIds);
                courseScheduleTeacherSalaryDao.batchDeleteByCourseScheduleIds(courseScheduleIds);
            }
            vipGroup.setStatus(VipGroupStatusEnum.CANCEL);
            vipGroupDao.update(vipGroup);
            classGroup.setDelFlag(1);
            classGroupDao.update(classGroup);
            teacherPush(vipGroup);
//			stopVipPush(vipGroup.getId(),vipGroup.getName());
            return;
        }
        Map<Integer, BigDecimal> studentSurplusClassFees = MapUtil.convertIntegerMap(maps);
        for (Integer userId : studentSurplusClassFees.keySet()) {
            StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.findByStudentVipGroup(vipGroupId, userId, DealStatusEnum.SUCCESS.getCode());
            if (null == studentPaymentOrder) {
                throw new BizException("无法停止课程，需要全部学员退学后，才能停止，请先操作学员退学。");
            }
//			sysUserCashAccountService.updateBalance(userId.intValue(),studentSurplusClassFees.get(userId));
//			SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(userId.intValue());
            SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
            sysUserCashAccountLog.setGroupId(vipGroupId.toString());
            sysUserCashAccountLog.setUserId(userId);
            sysUserCashAccountLog.setGroupType(VIP);
            sysUserCashAccountLog.setOrganId(vipGroup.getOrganId());
            sysUserCashAccountLog.setAmount(studentSurplusClassFees.get(userId));
            sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.VIP);
            sysUserCashAccountLog.setComment("VIP课关闭");
            sysUserCashAccountLogDao.insert(sysUserCashAccountLog);
        }

        vipGroup.setStatus(VipGroupStatusEnum.CANCEL);
        vipGroupDao.update(vipGroup);
        classGroup.setDelFlag(1);
        classGroupDao.update(classGroup);

        courseScheduleDao.batchDeleteCourseSchedules(courseScheduleIds);
        courseScheduleTeacherSalaryDao.batchDeleteByCourseScheduleIds(courseScheduleIds);
        courseScheduleStudentPaymentDao.deleteByCourseSchedule(courseScheduleIds);
        teacherAttendanceDao.batchDeleteByCourseSchedules(courseScheduleIds);
        //vip课停止通知
//		Teacher teacher = teacherDao.get(vipGroup.getUserId());
//		Map<Integer,String> map = new HashMap<>(1);
//		map.put(vipGroup.getUserId(),vipGroup.getUserId().toString());
//		sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,MessageTypeEnum.TEACHER_PUSH_VIP_COURSE_STOP,
//				map,null,0,"1",vipGroup.getName());
        teacherPush(vipGroup);
//		stopVipPush(vipGroup.getId(),vipGroup.getName());
    }

    private void teacherPush(VipGroup vipGroup) {
        Map<Integer, String> map = new HashMap<>(1);
        map.put(vipGroup.getUserId(), vipGroup.getUserId().toString());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_PUSH_VIP_COURSE_STOP,
                map, null, 0, "1", "TEACHER", vipGroup.getName());
    }

    private void stopVipPush(Long vipGroupId, String vipGroupName, Integer tenantId) {
        if (tenantId == null) {
            throw new BizException("课程机构信息异常");
        }
        String refundPeriod = sysConfigDao.findConfigValue(SysConfigService.REFUND_PERIOD);
        if (StringUtils.isNotEmpty(refundPeriod)) {
            Map<Integer, String> map1 = MapUtil.convertMybatisMap(classGroupStudentMapperDao.queryStudentIdMap(vipGroupId));
            if (map1 != null && map1.size() > 0) {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_VIP_STOP,
                        map1, null, 0, null, "STUDENT", vipGroupName, refundPeriod);
            }
        }
//		老师推送消息
        Map<Integer, String> map2 = MapUtil.convertMybatisMap(classGroupStudentMapperDao.queryTeacherIdMap(vipGroupId));
        if (map2 != null && map2.size() > 0) {
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.TEACHER_PUSH_VIP_STOP,
                    map2, null, 0, null, "TEACHER", vipGroupName);
        }
    }

    @Override
    public List<School> querySchoolByUserId(Integer userId) {
        return vipGroupDao.querySchoolByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateVipGroupBaseInfo(VipGroupApplyBaseInfoDto vipGroupApplyBaseInfo) {
        if (Objects.isNull(vipGroupApplyBaseInfo.getId())) {
            throw new BizException("请指定vip课");
        }
        VipGroup oldVipGroupInfo = vipGroupDao.get(vipGroupApplyBaseInfo.getId());
        if (Objects.isNull(oldVipGroupInfo)) {
            throw new BizException("指定的vip课不存在");
        }
        if (Objects.isNull(vipGroupApplyBaseInfo.getId())) {
            return;
        }
        Date now = new Date();
        boolean isChange = false;
        if (Objects.nonNull(vipGroupApplyBaseInfo.getOnlineClassesUnitPrice())
                && vipGroupApplyBaseInfo.getOnlineClassesUnitPrice().compareTo(oldVipGroupInfo.getOnlineClassesUnitPrice()) != 0) {
            oldVipGroupInfo.setOnlineClassesUnitPrice(vipGroupApplyBaseInfo.getOnlineClassesUnitPrice());
            isChange = true;
        }
        if (Objects.nonNull(vipGroupApplyBaseInfo.getOfflineClassesUnitPrice())
                && vipGroupApplyBaseInfo.getOfflineClassesUnitPrice().compareTo(oldVipGroupInfo.getOfflineClassesUnitPrice()) != 0) {
            oldVipGroupInfo.setOfflineClassesUnitPrice(vipGroupApplyBaseInfo.getOfflineClassesUnitPrice());
            isChange = true;
        }
        if (Objects.nonNull(vipGroupApplyBaseInfo.getTeacherSchoolId())) {
            oldVipGroupInfo.setTeacherSchoolId(vipGroupApplyBaseInfo.getTeacherSchoolId());
            courseScheduleDao.updateCourseSchoolByGroup(oldVipGroupInfo.getId().toString(), GroupType.VIP.getCode(), oldVipGroupInfo.getTeacherSchoolId());
            isChange = true;
        }
        if (Objects.nonNull(vipGroupApplyBaseInfo.getEducationalTeacherId()) && !vipGroupApplyBaseInfo.getEducationalTeacherId().equals(oldVipGroupInfo.getEducationalTeacherId())) {
            ClassGroup classGroup = classGroupDao.findByMusicGroupAndType(oldVipGroupInfo.getId().toString(), GroupType.VIP.getCode());
            if (Objects.nonNull(oldVipGroupInfo.getEducationalTeacherId())) {

                imGroupMemberService.quit(classGroup.getId().toString(), oldVipGroupInfo.getEducationalTeacherId());
            }

            oldVipGroupInfo.setEducationalTeacherId(vipGroupApplyBaseInfo.getEducationalTeacherId());
            isChange = true;

            imGroupMemberService.join(classGroup.getId().toString(), oldVipGroupInfo.getEducationalTeacherId(), "乐团主管", false);
        }
        if (Objects.nonNull(vipGroupApplyBaseInfo.getOrganId()) && !vipGroupApplyBaseInfo.getOrganId().equals(oldVipGroupInfo.getOrganId())) {
            isChange = true;
            oldVipGroupInfo.setOrganId(vipGroupApplyBaseInfo.getOrganId());
        }
        //更新vip课
        if (isChange) {
            oldVipGroupInfo.setUpdateTime(now);
            vipGroupDao.update(oldVipGroupInfo);
        }
        imUserFriendService.refreshGroupImUserFriend(oldVipGroupInfo.getId().toString(), GroupType.VIP);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void appendVipGroupCourseSchedules(VipGroupApplyDto vipGroupApplyDto) {
        if (Objects.isNull(vipGroupApplyDto.getVipGroupApplyBaseInfo().getId())) {
            throw new BizException("请指定vip课");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupApplyDto.getVipGroupApplyBaseInfo().getId());
        if (Objects.isNull(vipGroup)) {
            throw new BizException("指定的vip课不存在");
        }
        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroup.getId(), null);
        if (Objects.isNull(classGroup)) {
            throw new BizException("班级不存在");
        }

        if (!vipGroup.getStatus().equals(VipGroupStatusEnum.PROGRESS)) {
            throw new BizException("此状态的vip课程不支持加课");
        }

        VipGroupDefaultClassesUnitPrice vipGroupDefaultClassesUnitPrice = vipGroupDefaultClassesUnitPriceDao.getByVipGroup(vipGroup.getId());
        if (Objects.isNull(vipGroupDefaultClassesUnitPrice)) {
            throw new BizException("课程单价设置错误");
        }

        Date now = new Date();

//		BigDecimal onlineCoursePrice = courseScheduleStudentPaymentDao.findVipGroupCoursePrice(vipGroup.getId().intValue(),TeachModeEnum.ONLINE.getCode());
//		if(Objects.isNull(onlineCoursePrice)||onlineCoursePrice.compareTo(new BigDecimal(0))==0){
//			onlineCoursePrice = vipGroup.getOnlineClassesUnitPrice();
//		}
//		BigDecimal offlineCoursePrice = courseScheduleStudentPaymentDao.findVipGroupCoursePrice(vipGroup.getId().intValue(),TeachModeEnum.OFFLINE.getCode());
//		if(Objects.isNull(offlineCoursePrice)||offlineCoursePrice.compareTo(new BigDecimal(0))==0){
//			offlineCoursePrice = vipGroup.getOfflineClassesUnitPrice();
//		}

        BigDecimal surplusCourseTotalPrice = new BigDecimal(0);
        BigDecimal singleClassPrice = vipGroupApplyDto.getSingleClassPrice();


        //课程信息调整
        for (CourseSchedule courseSchedule : vipGroupApplyDto.getCourseSchedules()) {
            if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                courseSchedule.setSchoolId(vipGroup.getTeacherSchoolId());
            }
            courseSchedule.setTeacherId(vipGroup.getUserId());
            courseSchedule.setActualTeacherId(vipGroup.getUserId());
            courseSchedule.setStatus(CourseStatusEnum.NOT_START);
            courseSchedule.setType(CourseSchedule.CourseScheduleType.VIP);
            courseSchedule.setClassGroupId(classGroup.getId());
            courseSchedule.setGroupType(GroupType.VIP);
            courseSchedule.setMusicGroupId(vipGroup.getId().toString());
            courseSchedule.setName(vipGroup.getName());
            courseSchedule.setOrganId(vipGroup.getOrganId());
            surplusCourseTotalPrice = surplusCourseTotalPrice.add(singleClassPrice);
        }

        courseScheduleService.batchAddCourseSchedule(vipGroupApplyDto.getCourseSchedules());

        Map<String, BigDecimal> map = countVipGroupPredictFee1(vipGroup, vipGroup.getUserId(), null);
        BigDecimal offlineTeacherSalary = map.get("offlineTeacherSalary");
        //是否是赠送课程
        ActivityUserMapper activityUserMapper = activityUserMapperService.findVipUserMapper(vipGroup.getId(), "VIP", null);
        if (activityUserMapper != null) {
            if (vipGroup.getId().equals(activityUserMapper.getGiveVipGroupId())) {
                offlineTeacherSalary = map.get("giveOfflineTeacherSalary");
            }
        }

        if (Objects.isNull(offlineTeacherSalary)) {
            offlineTeacherSalary = new BigDecimal(0);
        }

        //创建老师单节课课酬信息
        courseScheduleTeacherSalaryService.createCourseScheduleTeacherVipSalary(vipGroup,
                vipGroupApplyDto.getCourseSchedules(),
                offlineTeacherSalary);


        List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentMapperDao.findByClassGroup(classGroup.getId());

        Map<Integer, String> userRoleMap = new HashMap<Integer, String>();
        //生成学生单课缴费信息
        for (ClassGroupStudentMapper classGroupStudent : classGroupStudents) {
            SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(classGroupStudent.getUserId());
            if (sysUserCashAccount.getCourseBalance().compareTo(surplusCourseTotalPrice) < 0) {
                throw new BizException("学生[{}]的课程余额不足", classGroupStudent.getUserName());
            }
            List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
            for (CourseSchedule vipGroupCourseSchedule : vipGroupApplyDto.getCourseSchedules()) {
                CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
                courseScheduleStudentPayment.setGroupType(GroupType.VIP);
                courseScheduleStudentPayment.setMusicGroupId(vipGroup.getId().toString());
                courseScheduleStudentPayment.setClassGroupId(vipGroupCourseSchedule.getClassGroupId());
                courseScheduleStudentPayment.setCourseScheduleId(vipGroupCourseSchedule.getId());
                courseScheduleStudentPayment.setUserId(classGroupStudent.getUserId());
//				if(vipGroupCourseSchedule.getTeachMode().equals(TeachModeEnum.ONLINE)){
//					courseScheduleStudentPayment.setExpectPrice(onlineCoursePrice);
//				}else if(vipGroupCourseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)){
//					courseScheduleStudentPayment.setExpectPrice(offlineCoursePrice);
//				}
                courseScheduleStudentPayment.setOriginalPrice(TeachModeEnum.ONLINE.equals(vipGroupCourseSchedule.getTeachMode()) ? vipGroupDefaultClassesUnitPrice.getOnlineClassesUnitPrice() : vipGroupDefaultClassesUnitPrice.getOfflineClassesUnitPrice());
                courseScheduleStudentPayment.setExpectPrice(singleClassPrice);
                courseScheduleStudentPayment.setActualPrice(singleClassPrice);
                courseScheduleStudentPayment.setCreateTime(now);
                courseScheduleStudentPayment.setUpdateTime(now);
                courseScheduleStudentPayments.add(courseScheduleStudentPayment);
            }
            sysUserCashAccountService.updateCourseBalance(classGroupStudent.getUserId(), sysUserCashAccount.getCourseBalance().subtract(surplusCourseTotalPrice), PlatformCashAccountDetailTypeEnum.PAY_FEE, surplusCourseTotalPrice.negate(), "后台加课扣除课程余额");

            courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
            userRoleMap.put(classGroupStudent.getUserId(), null);
        }

        classGroupService.updateClassGroupInfo(classGroup.getId());

//		courseScheduleStudentPaymentService.updateVipGiveCourse(vipGroup.getId());

        imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void addVipGroupStudents(Long vipGroupId, List<Integer> studentIds, Map<Integer, VipGroupStudentCoursePrice> studentCoursePriceMap) {
        if (CollectionUtils.isEmpty(studentIds)) {
            throw new BizException("请选择学生");
        }
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定vip课程");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId);
        if (Objects.isNull(vipGroup)) {
            throw new BizException("未找到指定的vip课程");
        }

        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId, null);

        if (classGroup.getStudentNum() > 0 && (VipGroupStatusEnum.APPLYING.equals(vipGroup.getStatus()))) {
            int num = studentPaymentOrderDao.countGroupOrderWithoutFailed(vipGroupId.toString(), GroupType.VIP);
            if (num > 0) {
                throw new BizException("已有学员购买了该课程组，无法添加，请走学员购买流程!");
            }
        }

        if (VipGroupStatusEnum.PAUSE.equals(vipGroup.getStatus())
                || VipGroupStatusEnum.FINISHED.equals(vipGroup.getStatus())
                || VipGroupStatusEnum.CANCEL.equals(vipGroup.getStatus())) {
            throw new BizException("当前课程组已经停止，无法进行添加学员操作。");
        }

        Integer exitStudentNum = classGroupStudentMapperDao.countClassGroupExitStudentNum(classGroup.getId(), studentIds);
        if (exitStudentNum > 0) {
            throw new BizException("选择的学生中存在此课程中已存在的学生");
        }

        VipGroupCategory vipGroupCategory = vipGroupCategoryService.get(vipGroup.getVipGroupCategoryId());

        if (vipGroupCategory == null) {
            throw new BizException("请修改VIP课课程形式");
        }
        Integer studentNum = classGroupStudentMapperDao.countClassGroupStudentNum(classGroup.getId());
        if (studentNum.compareTo(vipGroupCategory.getStudentNum()) >= 0) {
            throw new BizException("该班级人数已达上限");
        }

        if (vipGroupCategory.getStudentNum() < (studentCoursePriceMap.size() + studentNum)) {
            throw new BizException("学生人数超过{}人，请调整", vipGroupCategory.getStudentNum());
        }

        VipGroupActivity vipGroupActivity = null;
        if (Objects.nonNull(vipGroup.getVipGroupActivityId())) {
            vipGroupActivity = vipGroupActivityDao.get(vipGroup.getVipGroupActivityId().intValue());
        }

        if (Objects.nonNull(vipGroupActivity) && Objects.nonNull(vipGroupActivity.getStudentMaxUsedTimes()) &&
                vipGroupActivity.getStudentMaxUsedTimes() != -1 && !CollectionUtils.isEmpty(studentIds)) {
            List<Integer> errStudentIds = new ArrayList<>();
            for (Integer studentId : studentIds) {
                int useNum = vipGroupDao.countStudentUseingActivityNum(vipGroup.getVipGroupActivityId(), Integer.valueOf(studentId));
                if (useNum >= vipGroupActivity.getStudentMaxUsedTimes()) {
                    errStudentIds.add(studentId);
                }
            }
            if (errStudentIds.size() > 0) {
                List<SimpleUserDto> students = teacherDao.getUsersSimpleInfo(errStudentIds);
                throw new BizException("学员{}已超过该活动购买次数限制", StringUtils.join(students.stream().map(SimpleUserDto::getNickName).collect(Collectors.toList()), ","));
            }
        }

        Date now = new Date();
        Map<Integer, String> userRoleMap = new HashMap<Integer, String>();

        if (vipGroup.getStatus().equals(VipGroupStatusEnum.APPLYING) || vipGroup.getStatus().equals(VipGroupStatusEnum.NOT_START)) {
            List<CourseSchedule> courseSchedules = JSON.parseArray(vipGroup.getCourseSchedulesJson(), CourseSchedule.class);
            int courseNum = courseScheduleDao.countVipGroupCourses(vipGroupId.intValue(), "VIP");
            if (courseNum == 0) {
                courseScheduleService.batchAddCourseSchedule(courseSchedules);

                Map<String, BigDecimal> salaryMap = countVipGroupPredictFee1(vipGroup, vipGroup.getUserId(), null);
                BigDecimal offlineTeacherSalary = salaryMap.get("offlineTeacherSalary");
                //是否是赠送课程
                ActivityUserMapper activityUserMapper = activityUserMapperService.findVipUserMapper(vipGroup.getId(), "VIP", null);
                if (activityUserMapper != null) {
                    if (vipGroup.getId().equals(activityUserMapper.getGiveVipGroupId())) {
                        offlineTeacherSalary = salaryMap.get("giveOfflineTeacherSalary");
                    }
                }

                //创建老师单节课课酬信息
                courseScheduleTeacherSalaryService.createCourseScheduleTeacherVipSalary(vipGroup,
                        courseSchedules, offlineTeacherSalary);
            }
            userRoleMap.put(vipGroup.getUserId(), "指导老师");

            if (vipGroup.getEducationalTeacherId() != null) {
                userRoleMap.put(vipGroup.getEducationalTeacherId(), "乐团主管");
            }
        }

        List<CourseSchedule> surplusCourses = courseScheduleDao.findByClassGroupAndStatus(classGroup.getId(), CourseStatusEnum.NOT_START.getCode());

        List<ClassGroupStudentMapper> classGroupStudentMappers = new ArrayList<>();

        List<ClassGroupStudentMapper> classGroupStudentsList = classGroupStudentMapperDao.findByClassGroupAndStudent(classGroup.getId(), studentIds);
        Map<Integer, List<ClassGroupStudentMapper>> classGroupStudentsMap = classGroupStudentsList.stream()
                .collect(Collectors.groupingBy(ClassGroupStudentMapper::getUserId));

        if (CollectionUtils.isEmpty(surplusCourses)) {
            for (Integer studentId : studentIds) {
                //创建班级学生关联记录
                ClassGroupStudentMapper classGroupStudentMapper;

                List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentsMap.get(studentId);
                if (!CollectionUtils.isEmpty(classGroupStudents)) {
                    classGroupStudentMapper = classGroupStudents.get(0);
                    classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
                    classGroupStudentMapperDao.update(classGroupStudentMapper);
                } else {
                    classGroupStudentMapper = new ClassGroupStudentMapper();
                    classGroupStudentMapper.setGroupType(classGroup.getGroupType());
                    classGroupStudentMapper.setMusicGroupId(classGroup.getMusicGroupId());
                    classGroupStudentMapper.setClassGroupId(classGroup.getId());
                    classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
                    classGroupStudentMapper.setUserId(studentId);
                    classGroupStudentMappers.add(classGroupStudentMapper);
                }

                userRoleMap.put(studentId, null);
            }

            if (!CollectionUtils.isEmpty(classGroupStudentMappers)) {
                classGroupStudentMapperDao.classGroupStudentsInsert(classGroupStudentMappers);
            }

            Integer currentStudentNum = classGroupStudentMapperDao.countClassGroupStudentNum(classGroup.getId());
            if ((!vipGroup.getStatus().equals(VipGroupStatusEnum.FINISHED) || !vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL))
                    && currentStudentNum.compareTo(classGroup.getExpectStudentNum()) >= 0) {
                vipGroup.setStatus(VipGroupStatusEnum.PROGRESS);
                vipGroupDao.update(vipGroup);
            }
            classGroup.setStudentNum(currentStudentNum);
            classGroup.setDelFlag(0);
            classGroupDao.update(classGroup);

            try {
                imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(),
                        classGroup.getName(), vipGroup.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
                imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);
                imUserFriendService.refreshClassImUserFriend(classGroup.getId());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return;
        }

        BigDecimal surplusCoursesPrice = new BigDecimal(0);

        //生成学生单课缴费信息
        for (Integer studentId : studentIds) {
            surplusCoursesPrice = new BigDecimal(0);

            if (studentCoursePriceMap.containsKey(studentId)) {
                VipGroupStudentCoursePrice vipGroupStudentCoursePrice = studentCoursePriceMap.get(studentId);
                vipGroup.setOfflineClassesUnitPrice(vipGroupStudentCoursePrice.getOfflineClassesUnitPrice());
                vipGroup.setOnlineClassesUnitPrice(vipGroupStudentCoursePrice.getOnlineClassesUnitPrice());
            }


            for (int i = 0; i < surplusCourses.size(); i++) {
                CourseSchedule courseSchedule = surplusCourses.get(i);
                if (courseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                    surplusCoursesPrice = surplusCoursesPrice.add(vipGroup.getOfflineClassesUnitPrice());
                } else if (courseSchedule.getTeachMode().equals(TeachModeEnum.ONLINE)) {
                    surplusCoursesPrice = surplusCoursesPrice.add(vipGroup.getOnlineClassesUnitPrice());
                }
            }

            BigDecimal discount = null;
            if (Objects.nonNull(vipGroupActivity)) {
                discount = vipGroupActivity.getDiscount().divide(new BigDecimal(100), CommonConstants.DECIMAL_PLACE, BigDecimal.ROUND_DOWN);
                surplusCoursesPrice = surplusCoursesPrice.multiply(discount).setScale(0, BigDecimal.ROUND_CEILING);
            }

//            sysUserCashAccountService.subtractFromCourseBalanceAndBalance(studentId, surplusCoursesPrice.setScale(0, BigDecimal.ROUND_CEILING), PlatformCashAccountDetailTypeEnum.PAY_FEE, "后台添加学员金额扣减", vipGroupId);

            List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();

            //获取账户信息
            SysUserCashAccount cashAccount = sysUserCashAccountService.getLocked(studentId);
            if (cashAccount == null) {
                throw new BizException("用户[{}]现金账户不存在", studentId);
            }
            BigDecimal courseBalance = cashAccount.getCourseBalance();
            //获取学员排课资格
            List studentIdList = new ArrayList<>();
            studentIdList.add(studentId);
            //获取学员付费排课资格
            List<ActivityUserMapper> activityUserMappers = activityUserMapperService.getDao().findByStudents(studentIdList,vipGroup.getVipGroupCategoryId(),vipGroup.getSingleClassMinutes());
            //获取学员赠送排课资格
            List<ActivityUserMapper> freeActivityUserMappers = activityUserMapperService.getDao().findByStudents1(studentIdList,vipGroup.getVipGroupCategoryId(),vipGroup.getSingleClassMinutes());
            BaseMapDto<Integer, Integer> indexDto = new BaseMapDto<>(0, 0);
            //实际支付金额，去除优惠券
            BigDecimal divide = ZERO;
            BigDecimal firstAmount = ZERO;

            if (surplusCoursesPrice.compareTo(ZERO) > 0) {
                divide = surplusCoursesPrice.divide(new BigDecimal(surplusCourses.size()), ROUND_DOWN);
                firstAmount = surplusCoursesPrice.subtract(divide.multiply(new BigDecimal(surplusCourses.size()))).add(divide);
            }
            for (int i = 0; i < surplusCourses.size(); i++) {
                CourseSchedule vipGroupCourseSchedule = surplusCourses.get(i);
                CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
                if (i == 0) {
                    courseScheduleStudentPayment.setExpectPrice(firstAmount);
                    courseScheduleStudentPayment.setActualPrice(firstAmount);
                } else {
                    courseScheduleStudentPayment.setExpectPrice(divide);
                    courseScheduleStudentPayment.setActualPrice(divide);
                }
                BigDecimal actualPrice = courseScheduleStudentPayment.getActualPrice();
                //按课扣除课程余额
                if(courseBalance.compareTo(actualPrice) >= 0){
                    courseBalance = courseBalance.subtract(actualPrice);
                }else {
                    //扣除排课资格
                    activityUserMapperService.use(activityUserMappers, freeActivityUserMappers,indexDto, vipGroup.getId(),courseScheduleStudentPayment);
                }
                courseScheduleStudentPayment.setGroupType(GroupType.VIP);
                courseScheduleStudentPayment.setMusicGroupId(vipGroupId.toString());
                courseScheduleStudentPayment.setClassGroupId(vipGroupCourseSchedule.getClassGroupId());
                courseScheduleStudentPayment.setCourseScheduleId(vipGroupCourseSchedule.getId());
                courseScheduleStudentPayment.setUserId(studentId);
                if (vipGroupCourseSchedule.getTeachMode().equals(TeachModeEnum.OFFLINE)) {
                    courseScheduleStudentPayment.setOriginalPrice(vipGroup.getOfflineClassesUnitPrice());
                } else if (vipGroupCourseSchedule.getTeachMode().equals(TeachModeEnum.ONLINE)) {
                    courseScheduleStudentPayment.setOriginalPrice(vipGroup.getOnlineClassesUnitPrice());
                }
                courseScheduleStudentPayment.setCreateTime(now);
                courseScheduleStudentPayment.setUpdateTime(now);
                courseScheduleStudentPayments.add(courseScheduleStudentPayment);
            }
            courseScheduleStudentPaymentDao.batchInsert(courseScheduleStudentPayments);
            //扣余额，如果余额不足，那么扣排课资格
            if(cashAccount.getCourseBalance().compareTo(courseBalance) != 0){
                sysUserCashAccountService.appendCourseBalance(studentId, cashAccount.getCourseBalance().subtract(courseBalance).negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "vip课加学员扣除课程余额");
            }
            //更新资格
            if(!CollectionUtils.isEmpty(activityUserMappers)){
                activityUserMapperService.getDao().batchUpdate(activityUserMappers);
            }
            if(!CollectionUtils.isEmpty(freeActivityUserMappers)){
                activityUserMapperService.getDao().batchUpdateFree(freeActivityUserMappers);
            }

            //创建班级学生关联记录
            ClassGroupStudentMapper classGroupStudentMapper;

            List<ClassGroupStudentMapper> classGroupStudents = classGroupStudentsMap.get(studentId);
            if (!CollectionUtils.isEmpty(classGroupStudents)) {
                classGroupStudentMapper = classGroupStudents.get(0);
                classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
                classGroupStudentMapperDao.update(classGroupStudentMapper);
            } else {
                classGroupStudentMapper = new ClassGroupStudentMapper();
                classGroupStudentMapper.setGroupType(classGroup.getGroupType());
                classGroupStudentMapper.setMusicGroupId(classGroup.getMusicGroupId());
                classGroupStudentMapper.setClassGroupId(classGroup.getId());
                classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
                classGroupStudentMapper.setUserId(studentId);
                classGroupStudentMappers.add(classGroupStudentMapper);
            }

            userRoleMap.put(studentId, null);

            if (vipGroup.getOnlineClassesNum() > 0) {
                try {
                    teacherCourseRewardService.addConvertReward(studentId, vipGroup.getUserId());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        if (!CollectionUtils.isEmpty(classGroupStudentMappers)) {
            classGroupStudentMapperDao.classGroupStudentsInsert(classGroupStudentMappers);
        }

        courseScheduleService.checkNewCourseSchedules(surplusCourses, false, false);

        Integer currentStudentNum = classGroupStudentMapperDao.countClassGroupStudentNum(classGroup.getId());
        if ((!vipGroup.getStatus().equals(VipGroupStatusEnum.FINISHED)
                || !vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL))
                && currentStudentNum.compareTo(classGroup.getExpectStudentNum()) >= 0) {
            vipGroup.setStatus(VipGroupStatusEnum.PROGRESS);
            vipGroupDao.update(vipGroup);
        }
        classGroup.setStudentNum(currentStudentNum);
        classGroup.setDelFlag(0);
        classGroupDao.update(classGroup);
        classGroupService.updateClassGroupInfo(classGroup.getId());

        courseScheduleTeacherSalaryService.updateVipGroupCourseTeacherSalary(vipGroupId.intValue(), null);

        studentDao.updateStudentServiceTag(null, studentIds, YesOrNoEnum.YES.getCode());

        try {
            imGroupService.create(classGroup.getId().toString(), null, classGroup.getName(), classGroup.getName(),
                    vipGroup.getName(), null, null, GroupType.VIP.getCode(), ImGroup.GroupTypeEnum.VIP);
            imGroupMemberService.join(classGroup.getId().toString(), userRoleMap);

            imUserFriendService.refreshGroupImUserFriend(vipGroup.getId().toString(), GroupType.VIP);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void stopVipGroupWithNoCreate(Integer tenantId) {
        List<VipGroup> noCreateSuccessVipGroups = vipGroupDao.findNoCreateSuccessVipGroup(tenantId);
        if (CollectionUtils.isEmpty(noCreateSuccessVipGroups)) {
            return;
        }
        //用户账户资金变动信息列表
        List<SysUserCashAccountDetail> userCashAccountDetails = new ArrayList<>();
        for (VipGroup noCreateSuccessVipGroup : noCreateSuccessVipGroups) {
            int i = courseScheduleStudentPaymentDao.countStudentCourseNumWithGroup(GroupType.VIP, noCreateSuccessVipGroup.getId().toString());
            if (i > 0) {
                continue;
            }
            noCreateSuccessVipGroup.setStatus(VipGroupStatusEnum.CANCEL);
            List<StudentPaymentOrder> studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(noCreateSuccessVipGroup.getId().toString(),
                    OrderTypeEnum.SMALL_CLASS_TO_BUY, DealStatusEnum.SUCCESS);

            for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrders) {
                //生成账户资金明细
                if (studentPaymentOrder.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                    if(Objects.equals("关闭订单,实际支付成功,退到用户余额",studentPaymentOrder.getMemo())){
                        continue;
                    }
                    sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getExpectAmount());
                    SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(studentPaymentOrder.getUserId());
                    SysUserCashAccountDetail sysUserIncomeCashAccountDetail = new SysUserCashAccountDetail();
                    sysUserIncomeCashAccountDetail.setTenantId(studentPaymentOrder.getTenantId());
                    sysUserIncomeCashAccountDetail.setUserId(studentPaymentOrder.getUserId());
                    sysUserIncomeCashAccountDetail.setType(PlatformCashAccountDetailTypeEnum.REFUNDS);
                    sysUserIncomeCashAccountDetail.setStatus(DealStatusEnum.SUCCESS);
                    sysUserIncomeCashAccountDetail.setAmount(studentPaymentOrder.getExpectAmount());
                    sysUserIncomeCashAccountDetail.setBalance(sysUserCashAccount.getBalance());
                    sysUserIncomeCashAccountDetail.setAttribute(studentPaymentOrder.getTransNo());
                    sysUserIncomeCashAccountDetail.setDescription("达到报名截止时间，未满员系统自动取消课程组，并退费");
                    sysUserIncomeCashAccountDetail.setComment("达到报名截止时间，未满员系统自动取消课程组，并退费");
                    userCashAccountDetails.add(sysUserIncomeCashAccountDetail);
                }
            }
            classGroupStudentMapperDao.updateVipGroupStudentStatus(noCreateSuccessVipGroup.getId().toString(), GroupType.VIP.getCode(), ClassGroupStudentStatusEnum.QUIT.getCode());
        }
        if (!CollectionUtils.isEmpty(userCashAccountDetails)) {
            sysUserCashAccountDetailDao.batchInsert(userCashAccountDetails);
        }
        if (noCreateSuccessVipGroups != null && noCreateSuccessVipGroups.size() > 0) {
            vipGroupDao.batchUpdate(noCreateSuccessVipGroups);

            for (VipGroup noCreateSuccessVipGroup : noCreateSuccessVipGroups) {
                //推送消息
                if (noCreateSuccessVipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)) {
                    stopVipPush(noCreateSuccessVipGroup.getId(), noCreateSuccessVipGroup.getName(), noCreateSuccessVipGroup.getTenantId());
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void updateVipGroupStatusToFinished() {
        List<VipGroup> vipGroupList = vipGroupDao.queryRequiredOverList();
        if (vipGroupList != null && vipGroupList.size() > 0) {
            Date date = new Date();
            for (VipGroup vipGroup : vipGroupList) {
                if (Objects.nonNull(vipGroup.getCoursesExpireDate()) && (vipGroup.getCoursesExpireDate().compareTo(date) > 0 || DateUtil.isSameDay(vipGroup.getCoursesExpireDate(), date))) {
//					continue;
                }
                vipGroup.setStatus(VipGroupStatusEnum.FINISHED);
                vipGroup.setUpdateTime(date);
            }
            vipGroupDao.batchUpdate(vipGroupList);
            Set<Long> collect = vipGroupList.stream().filter(v -> VipGroupStatusEnum.FINISHED.equals(v.getStatus())).map(e -> e.getId()).collect(Collectors.toSet());
            if (!CollectionUtils.isEmpty(collect)) {
                Set<Integer> classGroupIds = classGroupDao.queryClassGroupIds(collect);
                //解散群
                for (Integer classGroupId : classGroupIds) {
                    imGroupService.cancel(classGroupId.toString());
                }
            }
        }
        List<VipGroup> normalVipGroupList = vipGroupDao.queryNormalStatusList();
        if (!CollectionUtils.isEmpty(normalVipGroupList)) {
            Date now = new Date();
            List<VipGroup> needUpdateVipGroups = new ArrayList<>();
            for (VipGroup vipGroup : normalVipGroupList) {
                try {
                    if (Objects.isNull(vipGroup.getRegistrationStartTime())) {
                        continue;
                    }
                    if (vipGroup.getStatus().equals(VipGroupStatusEnum.PAUSE) || vipGroup.getStatus().equals(VipGroupStatusEnum.CANCEL)
                            || vipGroup.getStatus().equals(VipGroupStatusEnum.FINISHED) || vipGroup.getStatus().equals(VipGroupStatusEnum.PROGRESS)) {
                        continue;
                    }
                    if (now.before(vipGroup.getRegistrationStartTime())) {
                        vipGroup.setStatus(VipGroupStatusEnum.NOT_START);
                    } else if (vipGroup.getRegistrationStartTime().before(now)
                            && vipGroup.getPaymentExpireDate().after(now)
                            && VipGroupStatusEnum.NOT_START.equals(vipGroup.getStatus())) {
                        vipGroup.setStatus(VipGroupStatusEnum.APPLYING);
                    } else {
                        continue;
                    }
                    VipGroup vipGroup1 = new VipGroup();
                    vipGroup1.setId(vipGroup.getId());
                    vipGroup1.setStatus(vipGroup.getStatus());
                    vipGroup1.setUpdateTime(now);
                    vipGroup1.setTotalPrice(vipGroup.getTotalPrice());
                    needUpdateVipGroups.add(vipGroup1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (!CollectionUtils.isEmpty(needUpdateVipGroups)) {
                vipGroupDao.batchUpdate(needUpdateVipGroups);
            }
        }
    }

    @Override
    public VipGroupPayInfoDto getVipGroupPayInfo(Integer vipGroupId, Integer userId) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定需要购买的小课");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId.longValue());
        if (Objects.isNull(vipGroup)) {
            throw new BizException("未找到此课程");
        }
        VipGroupPayInfoDto vipGroupPayInfo = new VipGroupPayInfoDto();
        vipGroupPayInfo.setTenantId(vipGroup.getTenantId());
        vipGroupPayInfo.setVipGroupId(vipGroup.getId().intValue());
        vipGroupPayInfo.setViipGroupName(vipGroup.getName());
        vipGroupPayInfo.setPrice(vipGroup.getTotalPrice());
        SysUserCashAccount sysUserCashAccount = sysUserCashAccountService.get(userId);
        if (Objects.isNull(sysUserCashAccount)) {
            throw new BizException("当前用户没有现金账户");
        }
        vipGroupPayInfo.setBalance(sysUserCashAccount.getBalance());
        return vipGroupPayInfo;
    }

    @Override
    public VipBuyResultDto findVipBuyResultInfo(Integer vipGroupId) {
        return vipGroupDao.getVipBuyResultInfo(vipGroupId);
    }

    @Override
    public List<TeacherBasicDto> findTeacherWithVipGroupOrganAndSubject(Long vipGroupId) {
        if (Objects.isNull(vipGroupId)) {
            throw new BizException("请指定小课");
        }
        VipGroup vipGroup = vipGroupDao.get(vipGroupId.longValue());
        if (Objects.isNull(vipGroup)) {
            throw new BizException("未找到指定课程");
        }
        ClassGroup classGroup = classGroupDao.findByVipGroup(vipGroupId.longValue(), null);
        List<TeacherBasicDto> teacherByOrganAndSubject = teacherDao.findTeacherByOrganAndSubject(vipGroup.getOrganId().toString(), classGroup.getSubjectIdList());
        if (CollectionUtils.isEmpty(teacherByOrganAndSubject)) {
            teacherByOrganAndSubject = new ArrayList<>();
            teacherByOrganAndSubject.add(teacherDao.findByTeacherId(vipGroup.getUserId()));
        }
        return teacherByOrganAndSubject;
    }

    @Override
    public List<StudentVipGroupShowListDto> queryVipPracticeGroups(StudentVipGroupQueryInfo queryInfo) {
        queryInfo.setExpireFlag(true);
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);
        List<StudentVipGroupShowListDto> vipGroups = vipGroupDao.findVipGroups(params);
        vipGroups.addAll(practiceGroupService.findPracticeGroups(params));
        vipGroups.removeAll(Collections.singleton(null));
        List<StudentVipGroupShowListDto> collect = vipGroups.stream().sorted(Comparator.comparing(StudentVipGroupShowListDto::getCreateTime).reversed()).collect(Collectors.toList());
        return collect;
    }
}
