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

import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.NON_PAYMENT;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED;
import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.page.NoClassMusicStudentQueryInfo;
import com.ym.mec.biz.dal.page.RegistrationOrPreQueryInfo;
import com.ym.mec.biz.service.*;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
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.util.CollectionUtils;

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.auth.api.entity.SysUserRole;
import com.ym.mec.auth.api.enums.CertificateTypeEnum;
import com.ym.mec.biz.dal.dto.StudentAddDto;
import com.ym.mec.biz.dal.dto.StudentApplyDetailDto;
import com.ym.mec.biz.dal.dto.StudentFeeDetailDto;
import com.ym.mec.biz.dal.dto.StudentInfo;
import com.ym.mec.biz.dal.dto.StudentMusicDetailDto;
import com.ym.mec.biz.dal.dto.StudentMusicGroupDto;
import com.ym.mec.biz.dal.page.StudentRegistrationQueryInfo;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.ImResult;
import com.ym.mec.common.entity.ImUserModel;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.im.ImFeignService;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.http.HttpUtil;

@Service
public class StudentRegistrationServiceImpl extends BaseServiceImpl<Long, StudentRegistration> implements StudentRegistrationService {

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

    @Resource
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;
    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;
    @Autowired
    private CourseScheduleService courseScheduleService;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private ClassGroupService classGroupDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
    @Autowired
    private ClassGroupStudentMapperService classGroupStudentMapperDao;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private MusicGroupSubjectPlanDao musicGroupSubjectPlanDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private SysUserCashAccountDao sysUserCashAccountDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private ContractService contractService;
    @Autowired
    private ImFeignService imFeignService;
    @Autowired
    private ImGroupMemberService imGroupMemberService;
    @Autowired
    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private SubjectService subjectService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SellOrderService sellOrderService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private SubjectChangeDao subjectChangeDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
    @Autowired
    private StudentCourseFeeDetailDao studentCourseFeeDetailDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private StudentInstrumentService studentInstrumentService;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private ImGroupDao imGroupDao;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private StudentInstrumentDao studentInstrumentDao;
    @Autowired
    private OrganizationCloudTeacherFeeDao organizationCloudTeacherFeeDao;
    @Autowired
    private CloudTeacherOrderService cloudTeacherOrderService;

    @Override
    public BaseDAO<Long, StudentRegistration> getDAO() {
        return studentRegistrationDao;
    }

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

        List<StudentApplyDetailDto> dataList = new ArrayList<>();
        int count = studentRegistrationDao.queryStudentDetailCount(params);
        if (queryInfo.getIsExport() && count > 50000) {
            throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
        }
        pageInfo.setTotal(count);
        params.put("offset", pageInfo.getOffset());
        if (queryInfo.getPage() <= pageInfo.getTotalPage()) {
            dataList = studentRegistrationDao.queryStudentDetailPage(params);
            Set<Integer> subjectIds = dataList.stream().map(StudentApplyDetailDto::getActualSubjectId).collect(Collectors.toSet());
            List<Integer> studentIds = dataList.stream().map(StudentApplyDetailDto::getStudentId).collect(Collectors.toList());
            Map<Integer, String> subjectMap = MapUtil.convertIntegerMap(musicGroupSubjectPlanDao.findSubjectMap(subjectIds, queryInfo.getMusicGroupId()));
            List<SubjectChange> waitPayChange = subjectChangeDao.getMusicGroupWaitPay(queryInfo.getMusicGroupId());
            Map<Integer, List<SubjectChange>> studentWaitPayChange = waitPayChange.stream().collect(Collectors.groupingBy(SubjectChange::getStudentId));
            //查询是否有有效期内乐保
            List<StudentInstrument> studentsMaintenanceNum = studentInstrumentDao.getStudentsMaintenanceNum(studentIds, queryInfo.getMusicGroupId());
            Map<Integer, Integer> studentMaintenanceMap = studentsMaintenanceNum.stream().collect(Collectors.toMap(StudentInstrument::getStudentId, StudentInstrument::getGoodsId));

            //查询云教练订单
            List<CloudTeacherOrder> studentCloudTeacherOrders = cloudTeacherOrderService.getStudentCloudTeacherOrders(studentIds, queryInfo.getMusicGroupId());
            Map<Integer, List<CloudTeacherOrder>> studentCloudTeacherMap = studentCloudTeacherOrders.stream().collect(Collectors.groupingBy(CloudTeacherOrder::getStudentId));
            Date nowDate = new Date();
            dataList.forEach(e -> {
                if (StringUtils.isNotBlank(subjectMap.get(e.getActualSubjectId()))) {
                    e.setKitGroupPurchaseTypeEnum(KitGroupPurchaseTypeEnum.valueOf(subjectMap.get(e.getActualSubjectId())));
                }
                if (studentWaitPayChange.containsKey(e.getStudentId())) {
                    e.setSubjectChange(studentWaitPayChange.get(e.getStudentId()).get(0));
                }
                if (studentMaintenanceMap.containsKey(e.getStudentId())) {
                    e.setHasMaintenance(true);
                }
                if (studentCloudTeacherMap.containsKey(e.getStudentId())) {
                    List<CloudTeacherOrder> cloudTeacherOrders = studentCloudTeacherMap.get(e.getStudentId());
                    if(cloudTeacherOrders != null && cloudTeacherOrders.size() > 0){
                        BigDecimal cloudAmount = BigDecimal.ZERO;
                        for (CloudTeacherOrder cloudTeacherOrder : cloudTeacherOrders) {
                            if (cloudTeacherOrder.getEndTime() == null || DateUtil.stringToDate(DateUtil.format(cloudTeacherOrder.getEndTime(),DateUtil.ISO_EXPANDED_DATE_FORMAT),DateUtil.ISO_EXPANDED_DATE_FORMAT).compareTo(
                                    DateUtil.stringToDate(DateUtil.format(nowDate,DateUtil.ISO_EXPANDED_DATE_FORMAT),DateUtil.ISO_EXPANDED_DATE_FORMAT)) >= 0) {
                                cloudAmount = cloudAmount.add(cloudTeacherOrder.getAmount());
                            }
                        }
                        e.setCloudTeacherAmount(cloudAmount);
                    }
                }
            });
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchUpdateSubject(Integer userId, Integer subId, String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        //获取当前学员的当前声部
        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("学员信息不存在");
        }
        //批量调剂（未缴费学员）
        int i = studentRegistrationDao.batchUpdateSubject(userId, subId, musicGroupId);
        if (i > 0) {
            //当前专业报名人数减一
            musicGroupSubjectPlanService.addApplyStudentNum(musicGroupId, studentRegistration.getActualSubjectId(), -1);
            //修改专业已报名人数
            musicGroupSubjectPlanService.addApplyStudentNum(musicGroupId, subId, 1);
            MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
            Set<Integer> roleIds = new HashSet<>(1);
            roleIds.add(SysUserRole.SECTION_MANAGER);
            Set<Integer> integers = musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId());
            integers.add(musicGroup.getEducationalTeacherId());
            sysMessageService.batchSeoMessage(integers, MessageTypeEnum.BACKSTAGE_STUDENT_SUBJECT_CHANGE, "", musicGroup.getName());
        }
        return i;
    }

    @Override
    public StudentFeeDetailDto queryFeeDetail(Integer studentId, String musicGroupId) {
        StudentFeeDetailDto studentFeeDetailDto = new StudentFeeDetailDto();
        List<MusicalListDetailDto> musicalList = studentPaymentOrderDetailService.getMusicalListDetail(musicGroupId, studentId);
        if (musicalList.size() <= 0) {
            return studentFeeDetailDto;
        }
        MusicalListDetailDto detailDto = musicalList.get(0);
        studentFeeDetailDto.setTotalAmount(detailDto.getOrderAmount());
        studentFeeDetailDto.setCourseFee(detailDto.getCourseAmount());
        if (KitGroupPurchaseTypeEnum.LEASE.equals(detailDto.getKitGroupPurchaseTypeEnum())) {
            studentFeeDetailDto.setDepositFee(detailDto.getMusicalAmount());
        }
        List<StudentFeeDto> studentFeeDtos = new ArrayList<>();
        if (detailDto.getMusicalName() != null) {
            StudentFeeDto studentFeeDto = new StudentFeeDto();
            studentFeeDto.setGoodsName(detailDto.getMusicalName());
            studentFeeDto.setGoodsType("INSTRUMENT");
            studentFeeDto.setMusicalFee(detailDto.getMusicalAmount());
            studentFeeDtos.add(studentFeeDto);
        }
        if (detailDto.getAccessoriesName() != null) {
            StudentFeeDto studentFeeDto = new StudentFeeDto();
            studentFeeDto.setGoodsName(detailDto.getAccessoriesName());
            studentFeeDto.setGoodsType("ACCESSORIES");
            studentFeeDto.setMusicalFee(detailDto.getAccessoriesAmount());
            studentFeeDtos.add(studentFeeDto);
        }
        StudentFeeDto studentFeeDto = new StudentFeeDto();
        studentFeeDto.setGoodsType("COURSE");
        studentFeeDto.setMusicalFee(detailDto.getCourseAmount());
        studentFeeDtos.add(studentFeeDto);
        studentFeeDetailDto.setGoods(studentFeeDtos);

        return studentFeeDetailDto;
        //return studentRegistrationDao.queryFeeDetail(studentId, musicGroupId);
    }

    @Override
    public List<Map<String, Object>> getNoClassStuBySubjectId(String musicGroupId, String actualSubjectId) {
        List<StudentRegistration> students = studentRegistrationDao.getNoClassStuBySubjectId(musicGroupId, actualSubjectId);
        List<Map<String, Object>> mapArrayList = new ArrayList<>();
        if (students != null && students.size() > 0) {
            String[] subjectIds = actualSubjectId.split(",");
            if (subjectIds != null && subjectIds.length > 0) {
                List<Map<Integer, String>> subjectNames = subjectDao.queryNameByIds(actualSubjectId);
                Map<Integer, String> subjectNameMap = MapUtil.convertMybatisMap(subjectNames);
                for (int i = 0; i < subjectIds.length; i++) {
                    Map<String, Object> resultMap = new HashMap<>(3);
                    int subjectId = Integer.parseInt(subjectIds[i]);
                    List<StudentRegistration> collect = students.stream().filter(e -> e.getActualSubjectId().equals(subjectId)).collect(Collectors.toList());
                    resultMap.put("subjectId", subjectId);
                    resultMap.put("subjectName", subjectNameMap.get(subjectId));
                    resultMap.put("rows", collect);
                    mapArrayList.add(resultMap);
                }
            }
        }
        return mapArrayList;
    }

    @Override
    public List<MusicGroupSubjectPlan> getNoClassStuCountByMusicGroupId(String musicGroupId) {
        return studentRegistrationDao.getNoClassStuCountByMusicGroupId(musicGroupId);
    }

    @Override
    public Integer updateByUserIdAndMusicGroupId(StudentRegistration studentRegistration) {
        return studentRegistrationDao.updateByUserIdAndMusicGroupId(studentRegistration);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentRegistration addStudent(StudentRegistration studentRegistration) throws Exception {
        Integer userId = studentRegistration.getUserId();

        Student student = studentDao.getLocked(userId);
        if (student == null) {
            throw new BizException("您已登录超时，请重新登录后再次报名");
        }

        StudentRegistration hasReg = getByPhoneAndMusicGroupId(studentRegistration.getMusicGroupId(), studentRegistration.getParentsPhone());
        if (hasReg != null && hasReg.getMusicGroupStatus() != StudentMusicGroupStatusEnum.QUIT) {
            throw new BizException("该乐团您已报名");
        }

        Date date = new Date();
        SysUser sysUser = sysUserFeignService.queryUserByMobile(studentRegistration.getParentsPhone());
        if (sysUser == null) {
            throw new BizException("用户信息查询失败");
        }

        if (!sysUser.getUserType().contains("STUDENT")) {
            sysUser.setUserType(sysUser.getUserType() + ",STUDENT");
        }
        sysUser.setPhone(studentRegistration.getParentsPhone());
        sysUser.setOrganId(studentRegistration.getOrganId());

        Boolean updateNameFlag = false;
//        if (sysUser.getRealName() == null) {
//            sysUser.setRealName(studentRegistration.getParentsName());
//        }

        if (StringUtils.isEmpty(sysUser.getUsername())) {
            sysUser.setUsername(studentRegistration.getName());
            updateNameFlag = true;
        }
        sysUser.setGender(studentRegistration.getGender());
        sysUser.setBirthdate(studentRegistration.getBirthdate());
        sysUser.setCreateTime(date);
        sysUser.setUpdateTime(date);
        teacherDao.updateUser(sysUser);

        studentRegistration.setCurrentGradeDate(date);
        studentRegistration.setActualSubjectId(studentRegistration.getSubjectId());
        studentRegistration.setCreateTime(date);
        studentRegistration.setUpdateTime(date);
        studentRegistration.setUserId(sysUser.getId());
        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.APPLY);

        Organization organization = organizationDao.get(studentRegistration.getOrganId());
        String studentGrade = studentService.getStudentGrade(organization.getGradeType(), studentRegistration.getCurrentGradeNum());
        studentRegistration.setCurrentGrade(studentGrade);

        if (hasReg != null) {
            studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.APPLY);
            studentRegistration.setId(hasReg.getId());
            studentRegistrationDao.update(studentRegistration);
        } else {
            studentRegistrationDao.insert(studentRegistration);
        }
        //更新年级信息
        student.setCurrentGradeNum(studentRegistration.getCurrentGradeNum());
        student.setCurrentClass(studentRegistration.getCurrentClass());
        studentDao.update(student);

        if (updateNameFlag) {
            imGroupDao.updateNickname(userId, studentRegistration.getName());
            imGroupDao.updateUserFriendNickname(userId, studentRegistration.getName());
        }

        imFeignService.update(new ImUserModel(userId.toString(), studentRegistration.getName(), sysUser.getAvatar()));
        // 增加报名学生数
        musicGroupSubjectPlanService.addApplyStudentNum(studentRegistration.getMusicGroupId(), studentRegistration.getSubjectId(), 1);
        // 报名成功后，发送短信
        // String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + studentRegistration.getMusicGroupId();
        String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
        Subject subject = subjectDao.get(studentRegistration.getSubjectId());
        // MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());

        Map<Integer, String> map = new HashMap<>(1);
        map.put(sysUser.getId(), studentRegistration.getParentsPhone());
        sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.SMS_APPLY_MESSAGE, map, null, 0, "", "",
                studentRegistration.getParentsName(), subject.getName(), serverPhone);

        return studentRegistration;
    }

    @Override
    public StudentInfo queryStudentInfo(Integer userId) {
        return studentRegistrationDao.queryStudentInfo(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentPaymentOrder addOrder(StudentRegistration studentRegistration, BigDecimal amount, String orderNo, String paymentChannel,
                                        BigDecimal courseFee, List<MusicGroupSubjectGoodsGroup> goodsGroups, BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses, Boolean buyMaintenance, Boolean buyCloudTeacher, Boolean buyCloudTeacherPlus) throws Exception {
        Date date = new Date();
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(studentRegistration.getUserId());
        studentPaymentOrder.setGroupType(GroupType.MUSIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.APPLY);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setPaymentChannel(paymentChannel);
        studentPaymentOrder.setMusicGroupId(studentRegistration.getMusicGroupId());
        studentPaymentOrderService.insert(studentPaymentOrder);

        ArrayList<StudentPaymentOrderDetail> studentPaymentOrderDetailList = new ArrayList<>();
        /*StudentPaymentOrderDetail studentPaymentOrderDetail = new StudentPaymentOrderDetail();
        studentPaymentOrderDetail.setType(OrderDetailTypeEnum.COURSE);
        studentPaymentOrderDetail.setPrice(BigDecimal.ZERO);
        studentPaymentOrderDetail.setRemitFee(BigDecimal.ZERO);
        studentPaymentOrderDetail.setCreateTime(date);
        studentPaymentOrderDetail.setUpdateTime(date);
        studentPaymentOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
        studentPaymentOrderDetailList.add(studentPaymentOrderDetail);*/
        //乐器及打包辅件
        String maintenanceGoodsId = "";
        if (goodsGroups != null && goodsGroups.size() > 0) {
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                StudentPaymentOrderDetail studentPaymentOrderDetail4goodsGroup = new StudentPaymentOrderDetail();
                studentPaymentOrderDetail4goodsGroup.setRemitFee(BigDecimal.ZERO);
                OrderDetailTypeEnum type = null;
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    type = OrderDetailTypeEnum.MUSICAL;
                    goodsGroup.setPrice(goodsGroup.getPrice().subtract(remitFee));
                    studentPaymentOrderDetail4goodsGroup.setRemitFee(remitFee);
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    type = OrderDetailTypeEnum.ACCESSORIES;
                } else if (goodsGroup.getType().equals(GoodsType.OTHER)) {
                    type = OrderDetailTypeEnum.TEACHING;
                }
                studentPaymentOrderDetail4goodsGroup.setType(type);
                studentPaymentOrderDetail4goodsGroup.setPrice(goodsGroup.getPrice());
                studentPaymentOrderDetail4goodsGroup.setGoodsIdList(goodsGroup.getGoodsIdList());
                studentPaymentOrderDetail4goodsGroup.setCreateTime(date);
                studentPaymentOrderDetail4goodsGroup.setUpdateTime(date);
                studentPaymentOrderDetail4goodsGroup.setPaymentOrderId(studentPaymentOrder.getId());
                studentPaymentOrderDetail4goodsGroup.setKitGroupPurchaseType(goodsGroup.getKitGroupPurchaseType());
                studentPaymentOrderDetailList.add(studentPaymentOrderDetail4goodsGroup);
                if (OrderDetailTypeEnum.MUSICAL.equals(type)) {
                    maintenanceGoodsId = goodsGroup.getGoodsIdList();
                }
            }
        }

        //新的课程形态
        if (newCourses != null && newCourses.size() > 0) {
            for (MusicGroupPaymentCalenderCourseSettings newCourse : newCourses) {
                StudentPaymentOrderDetail studentPaymentOrderDetailCourse = new StudentPaymentOrderDetail();
                studentPaymentOrderDetailCourse.setType(OrderDetailTypeEnum.valueOf(newCourse.getCourseType().getCode()));
                if (courseRemitFee.compareTo(BigDecimal.ZERO) > 0 && !newCourse.getIsStudentOptional()) {
                    studentPaymentOrderDetailCourse.setPrice(BigDecimal.ZERO);
                    studentPaymentOrderDetailCourse.setRemitFee(newCourse.getCourseCurrentPrice());
                } else {
                    studentPaymentOrderDetailCourse.setPrice(newCourse.getCourseCurrentPrice());
                    studentPaymentOrderDetailCourse.setRemitFee(BigDecimal.ZERO);
                }
                studentPaymentOrderDetailCourse.setCreateTime(date);
                studentPaymentOrderDetailCourse.setUpdateTime(date);
                studentPaymentOrderDetailCourse.setPaymentOrderId(studentPaymentOrder.getId());
                studentPaymentOrderDetailList.add(studentPaymentOrderDetailCourse);
            }
        }
        if (buyMaintenance) {
            if ("".equals(maintenanceGoodsId)) {
                throw new BizException("有乐器才能购买乐保，请核查");
            }
            BigDecimal maintenancePrice = new BigDecimal(sysConfigDao.findConfigValue("maintenance_price"));
            StudentPaymentOrderDetail maintenanceOrderDetail = new StudentPaymentOrderDetail();
            maintenanceOrderDetail.setType(OrderDetailTypeEnum.MAINTENANCE);
            maintenanceOrderDetail.setPrice(maintenancePrice);
            maintenanceOrderDetail.setRemitFee(BigDecimal.ZERO);
            maintenanceOrderDetail.setCreateTime(date);
            maintenanceOrderDetail.setUpdateTime(date);
            maintenanceOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            maintenanceOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(maintenanceOrderDetail);
        }
        //云教练/云教练+
        if (buyCloudTeacher || buyCloudTeacherPlus) {
            // OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(studentRegistration.getOrganId());
            // BigDecimal cloudTeacherPrice = buyCloudTeacher ? cloudTeacher.getPrice() : cloudTeacher.getPlusPrice();
            
            MusicGroupPaymentCalender musicGroupRegCalender = musicGroupPaymentCalenderDao.getMusicGroupRegCalender(studentRegistration.getMusicGroupId());
            if(musicGroupRegCalender == null){
            	throw new BizException("缴费信息不存在");
            }
            BigDecimal cloudTeacherPrice = musicGroupRegCalender.getMemberPaymentAmount();
            
            OrderDetailTypeEnum orderDetailTypeEnum = OrderDetailTypeEnum.CLOUD_TEACHER;
            StudentPaymentOrderDetail cloudTeacherOrderDetail = new StudentPaymentOrderDetail();
            cloudTeacherOrderDetail.setType(orderDetailTypeEnum);
            cloudTeacherOrderDetail.setPrice(cloudTeacherPrice);
            cloudTeacherOrderDetail.setRemitFee(BigDecimal.ZERO);
            cloudTeacherOrderDetail.setCreateTime(date);
            cloudTeacherOrderDetail.setUpdateTime(date);
            cloudTeacherOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            cloudTeacherOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(cloudTeacherOrderDetail);
        }
        studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);

        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());

        //增加缴费学生数,0元订单不增加报名人数(没买云教练/云教练+的)
        boolean paidZeroFlag = false;
        boolean firstPaidZeroFlag = false;

        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
        int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
        int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
        if ((musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE) && !buyCloudTeacher))
        {
            paidZeroFlag = true;
            if (studentRegistration.getNoneNeedCloudTeacher().equals(1)) {
                musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
                musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
                firstPaidZeroFlag = true;
            }
        } else {
            musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
        }
        if (studentRegistration.getTemporaryCourseFee() == null && musicOneSubjectClassPlan.getPaidStudentNum() > musicOneSubjectClassPlan.getExpectedStudentNum()) {
            throw new BizException("乐团该声部人数暂时已满，请稍后再试");
        }
        int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
        if (count <= 0) {
            throw new BizException("排队人数过多，请重试");
        }
        if (paidZeroFlag) {
            studentPaymentOrder.setVersion(0);
            String code = studentRegistration.getNoneNeedCloudTeacher().equals(1) ? "200" : "205";
            studentPaymentOrder.setPaymentAccountNo(code);
            if (code.equals("205") && !"".equals(maintenanceGoodsId)) {
                studentPaymentOrder.setClassGroupId(206);
            }
            studentPaymentOrderService.update(studentPaymentOrder);
        }
        return studentPaymentOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentPaymentOrder reAddOrder(Integer userId, BigDecimal amount, String orderNo, String paymentChannel, BigDecimal courseFee,
                                          List<MusicGroupSubjectGoodsGroup> goodsGroups, String musicGroupId, StudentPaymentOrder oldOrder,
                                          BigDecimal remitFee, BigDecimal courseRemitFee, List<MusicGroupPaymentCalenderCourseSettings> newCourses,
                                          Boolean buyMaintenance,
                                          Boolean buyCloudTeacher) {
        //关闭老订单
        oldOrder.setStatus(DealStatusEnum.CLOSE);
        studentPaymentOrderService.update(oldOrder);
        if (oldOrder.getBalancePaymentAmount() != null && oldOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
            sysUserCashAccountService.updateBalance(oldOrder.getUserId(), oldOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "关闭订单");
        }
        Date date = new Date();
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setGroupType(GroupType.MUSIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.APPLY);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setPaymentChannel(paymentChannel);
        studentPaymentOrder.setMusicGroupId(musicGroupId);
        studentPaymentOrderService.insert(studentPaymentOrder);

        List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = new ArrayList<>();
        StudentPaymentOrderDetail studentPaymentOrderDetail = new StudentPaymentOrderDetail();
        studentPaymentOrderDetail.setType(OrderDetailTypeEnum.COURSE);
        studentPaymentOrderDetail.setPrice(BigDecimal.ZERO);
        studentPaymentOrderDetail.setRemitFee(BigDecimal.ZERO);
        studentPaymentOrderDetail.setCreateTime(date);
        studentPaymentOrderDetail.setUpdateTime(date);
        studentPaymentOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
        studentPaymentOrderDetailList.add(studentPaymentOrderDetail);
        //乐器及打包辅件
        String maintenanceGoodsId = "";
        if (goodsGroups != null && goodsGroups.size() > 0) {
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                StudentPaymentOrderDetail studentPaymentOrderDetail4goodsGroup = new StudentPaymentOrderDetail();
                studentPaymentOrderDetail4goodsGroup.setRemitFee(BigDecimal.ZERO);
                OrderDetailTypeEnum type = null;
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    type = OrderDetailTypeEnum.MUSICAL;
                    goodsGroup.setPrice(goodsGroup.getPrice().subtract(remitFee));
                    studentPaymentOrderDetail4goodsGroup.setRemitFee(remitFee);
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    type = OrderDetailTypeEnum.ACCESSORIES;
                } else if (goodsGroup.getType().equals(GoodsType.OTHER)) {
                    type = OrderDetailTypeEnum.TEACHING;
                }
                studentPaymentOrderDetail4goodsGroup.setType(type);
                studentPaymentOrderDetail4goodsGroup.setPrice(goodsGroup.getPrice());
                studentPaymentOrderDetail4goodsGroup.setGoodsIdList(goodsGroup.getGoodsIdList());
                studentPaymentOrderDetail4goodsGroup.setCreateTime(date);
                studentPaymentOrderDetail4goodsGroup.setUpdateTime(date);
                studentPaymentOrderDetail4goodsGroup.setPaymentOrderId(studentPaymentOrder.getId());
                studentPaymentOrderDetail4goodsGroup.setKitGroupPurchaseType(goodsGroup.getKitGroupPurchaseType());
                studentPaymentOrderDetailList.add(studentPaymentOrderDetail4goodsGroup);
                if (OrderDetailTypeEnum.MUSICAL.equals(type)) {
                    maintenanceGoodsId = goodsGroup.getGoodsIdList();
                }
            }
        }

        //新的课程形态
        if (newCourses != null && newCourses.size() > 0) {
            for (MusicGroupPaymentCalenderCourseSettings newCourse : newCourses) {
                StudentPaymentOrderDetail studentPaymentOrderDetailCourse = new StudentPaymentOrderDetail();
                studentPaymentOrderDetailCourse.setType(OrderDetailTypeEnum.valueOf(newCourse.getCourseType().getCode()));
                if (courseRemitFee.compareTo(BigDecimal.ZERO) > 0 && !newCourse.getIsStudentOptional()) {
                    studentPaymentOrderDetailCourse.setPrice(BigDecimal.ZERO);
                    studentPaymentOrderDetailCourse.setRemitFee(newCourse.getCourseCurrentPrice());
                } else {
                    studentPaymentOrderDetailCourse.setPrice(newCourse.getCourseCurrentPrice());
                    studentPaymentOrderDetailCourse.setRemitFee(BigDecimal.ZERO);
                }
                studentPaymentOrderDetailCourse.setCreateTime(date);
                studentPaymentOrderDetailCourse.setUpdateTime(date);
                studentPaymentOrderDetailCourse.setPaymentOrderId(studentPaymentOrder.getId());
                studentPaymentOrderDetailList.add(studentPaymentOrderDetailCourse);
            }
        }
        if (buyMaintenance) {
            if ("".equals(maintenanceGoodsId)) {
                throw new BizException("有乐器才能购买乐保，请核查");
            }
            BigDecimal maintenancePrice = new BigDecimal(sysConfigDao.findConfigValue("maintenance_price"));
            StudentPaymentOrderDetail maintenanceOrderDetail = new StudentPaymentOrderDetail();
            maintenanceOrderDetail.setType(OrderDetailTypeEnum.MAINTENANCE);
            maintenanceOrderDetail.setPrice(maintenancePrice);
            maintenanceOrderDetail.setRemitFee(BigDecimal.ZERO);
            maintenanceOrderDetail.setCreateTime(date);
            maintenanceOrderDetail.setUpdateTime(date);
            maintenanceOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            maintenanceOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(maintenanceOrderDetail);
        }
        //云教练
        if (buyCloudTeacher) {
            OrganizationCloudTeacherFee cloudTeacher = organizationCloudTeacherFeeDao.getByOrganId(oldOrder.getOrganId());
            BigDecimal cloudTeacherPrice = cloudTeacher.getPrice();
            StudentPaymentOrderDetail cloudTeacherOrderDetail = new StudentPaymentOrderDetail();
            cloudTeacherOrderDetail.setType(OrderDetailTypeEnum.CLOUD_TEACHER);
            cloudTeacherOrderDetail.setPrice(cloudTeacherPrice);
            cloudTeacherOrderDetail.setRemitFee(BigDecimal.ZERO);
            cloudTeacherOrderDetail.setCreateTime(date);
            cloudTeacherOrderDetail.setUpdateTime(date);
            cloudTeacherOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            cloudTeacherOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(cloudTeacherOrderDetail);
        }
        studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);

        return studentPaymentOrder;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentRegistration queryByUserIdAndMusicGroupId(Integer userId, String musicGroupId) {
        StudentRegistration registration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (registration == null) {
            return null;
        }
        SysUserCashAccount account = sysUserCashAccountDao.getLocked(userId);
        registration.setBalance(account == null ? BigDecimal.ZERO : account.getBalance());
        registration.setTransferStudent(0);
        return registration;
    }

    @Override
    public StudentRegistration getByPhoneAndMusicGroupId(String musicGroupId, String parentsPhone) {
        return studentRegistrationDao.getByPhoneAndMusicGroupId(musicGroupId, parentsPhone);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer insertStudent(StudentAddDto studentAddDto) throws Exception {
        StudentRegistration studentRegistration = studentAddDto.getStudentRegistration();
        if (studentRegistration == null) {
            throw new BizException("参数校验失败");
        }
        /*if(studentAddDto.getSignClassId() == null && studentAddDto.getMixClassId() == null){
            throw new BizException("参数校验失败: 单技班或合奏班必填一项");
        }*/
        Date date = new Date();
        String musicGroupId = studentRegistration.getMusicGroupId();

        studentRegistration.setCreateTime(date);
        studentRegistration.setUpdateTime(date);

        StudentRegistration phoneAndMusicGroupId = studentRegistrationDao.getByPhoneAndMusicGroupId(musicGroupId, studentRegistration.getParentsPhone());
        if (phoneAndMusicGroupId != null && phoneAndMusicGroupId.getMusicGroupStatus() != StudentMusicGroupStatusEnum.QUIT && phoneAndMusicGroupId.getMusicGroupStatus() != StudentMusicGroupStatusEnum.APPLY) {
            throw new BizException("该学员已存在");
        } else {
            SysUser sysUser = studentRegistrationDao.getSysUserByPhone(studentRegistration.getParentsPhone());
            MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
            Integer userId;
            if (sysUser == null) {
                //新增user
                sysUser = new SysUser();
                sysUser.setPhone(studentRegistration.getParentsPhone());
//                sysUser.setRealName(studentRegistration.getParentsName());
                sysUser.setUsername(studentRegistration.getName());
                sysUser.setGender(studentRegistration.getGender());
                sysUser.setUserType("STUDENT");
//                sysUser.setIdCardNo(studentRegistration.getIdCardNo());
                sysUser.setOrganId(musicGroup.getOrganId());
                sysUser.setBirthdate(studentRegistration.getBirthdate());
                teacherDao.addSysUser(sysUser);
                userId = sysUser.getId();
                studentDao.insert(new Student(userId, studentRegistration.getSubjectId().toString()));
                //添加用户现金账户
                sysUserCashAccountDao.insert(new SysUserCashAccount(userId, "CNY"));
                ImResult register = imFeignService.register(new ImUserModel(userId.toString(), sysUser.getUsername(), null));
                sysUser.setImToken(register.getToken());
                teacherDao.updateUser(sysUser);
            } else {
                if(musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE){
                    //该学员是否在其他的会员团
                    boolean hasMemberGroup = studentRegistrationDao.checkHasMemberGroup(musicGroupId,sysUser.getId());
                    if(hasMemberGroup){
                        throw new BizException("操作失败：该学员已在其他系统收费乐团中，不可报名该乐团请联系教务老师");
                    }
                }
                StudentRegistration oldReg = studentRegistrationDao.getByUserIdAndMusicGroupId(musicGroupId, sysUser.getId());
                if (oldReg != null && oldReg.getMusicGroupStatus() != StudentMusicGroupStatusEnum.QUIT && oldReg.getMusicGroupStatus() != StudentMusicGroupStatusEnum.APPLY) {
                    throw new BizException("该学员已存在,原手机号为" + oldReg.getParentsPhone());
                }
                if (oldReg != null) {
                    phoneAndMusicGroupId = oldReg;
                }
                if (StringUtils.isNotEmpty(sysUser.getUsername())) {
                    if (!sysUser.getUsername().equals(studentRegistration.getName())) {
                        throw new BizException("操作失败：账户已被注册");
                    }
                }
                if (!sysUser.getUserType().contains("STUDENT")) {
                    sysUser.setUserType(sysUser.getUserType() + ",STUDENT");
                }
                sysUser.setPhone(studentRegistration.getParentsPhone());
//                sysUser.setRealName(studentRegistration.getParentsName());
                sysUser.setUsername(studentRegistration.getName());
                sysUser.setGender(studentRegistration.getGender());
                sysUser.setOrganId(musicGroup.getOrganId());
                sysUser.setBirthdate(studentRegistration.getBirthdate());
                teacherDao.updateUser(sysUser);
                userId = sysUser.getId();
                Student student = studentDao.get(userId);
                if (student == null) {
                    studentDao.insert(new Student(userId, studentRegistration.getSubjectId().toString()));
                } else if (StringUtils.isEmpty(student.getSubjectIdList())) {
                    student.setSubjectIdList(studentRegistration.getSubjectId().toString());
                    student.setUpdateTime(date);
                    studentDao.update(student);
                } else if (StringUtils.isNotEmpty(student.getSubjectIdList())) {
                    String[] split = student.getSubjectIdList().split(",");
                    List<String> list = new ArrayList<>(Arrays.asList(split));
                    if (!list.contains(studentRegistration.getSubjectId().toString())) {
                        list.add(studentRegistration.getSubjectId().toString());
                        student.setSubjectIdList(StringUtils.join(list, ","));
                        student.setUpdateTime(date);
                        studentDao.update(student);
                    }
                }
                imGroupDao.updateNickname(userId, sysUser.getUsername());
                imGroupDao.updateUserFriendNickname(userId, sysUser.getUsername());
            }
            MusicGroupStudentFee studentFeeDaoByUser = musicGroupStudentFeeDao.findByUser(userId, musicGroupId);
            if (studentFeeDaoByUser != null) {
                throw new BizException("该学员已存在");
            }
            Organization organization = organizationDao.get(musicGroup.getOrganId());
            String studentGrade = studentService.getStudentGrade(organization.getGradeType(), studentRegistration.getCurrentGradeNum());
            studentRegistration.setCurrentGrade(studentGrade);
            studentRegistration.setActualSubjectId(studentRegistration.getSubjectId());
            studentRegistration.setUserId(userId);
            studentRegistration.setPaymentStatus(PaymentStatusEnum.OPEN);
            studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.APPLY);
            studentRegistration.setTemporaryCourseFee(studentAddDto.getTemporaryCourseFee());
            //学生报名表
            Set<Integer> roleIds = new HashSet<>(1);
            roleIds.add(SysUserRole.SECTION_MANAGER);
            Set<Integer> integers = musicGroupDao.queryUserIdByRoleId(roleIds, musicGroup.getOrganId());
            integers.add(musicGroup.getEducationalTeacherId());
            sysMessageService.batchSeoMessage(integers, MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_ADD_STUDENT, "", musicGroup.getName(), studentRegistration.getName());
            //增加报名学生数
            musicGroupSubjectPlanService.addApplyStudentNum(musicGroupId, studentRegistration.getSubjectId(), 1);
            //汇总金额

            MusicGroupStudentFee musicGroupStudentFee = new MusicGroupStudentFee(musicGroupId,
                    userId, studentRegistration.getSubjectId(), studentAddDto.getCourseFee(),
                    null, studentAddDto.getTemporaryCourseFee(), null);

            /*if (musicGroup.getFeeType() != null && musicGroup.getFeeType() != MusicGroupPaymentCalender.FeeType.OFFLINE && musicGroupStudentFee.getTemporaryCourseFee().doubleValue() * 100 == 0) {
                musicGroupStudentFee.setRemainNetworkClassTimes(musicGroupStudentFee.getRemainNetworkClassTimes() + 1);
            }*/
            musicGroupStudentFeeDao.insert(musicGroupStudentFee);

            StudentPaymentOrder waitPayOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, studentRegistration.getMusicGroupId(), DealStatusEnum.WAIT_PAY);

            if (waitPayOrder != null) {
                waitPayOrder.setStatus(DealStatusEnum.CLOSE);
                studentPaymentOrderService.update(waitPayOrder);
            }
            //生成订单
            StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
            studentPaymentOrder.setUserId(userId);
            studentPaymentOrder.setGroupType(GroupType.MUSIC);
            studentPaymentOrder.setType(OrderTypeEnum.APPLY);
            studentPaymentOrder.setStatus(DealStatusEnum.WAIT_PAY);
            studentPaymentOrder.setMusicGroupId(musicGroupId);
            studentPaymentOrder.setClassGroupId(studentAddDto.getSignClassId());
            studentPaymentOrder.setOrganId(musicGroup.getOrganId());
            studentPaymentOrder.setRoutingOrganId(musicGroup.getOrganId());

            //生成订单明细
            List<StudentPaymentOrderDetail> studentPaymentOrderDetails = studentAddDto.getStudentPaymentOrderDetails();
            if (studentPaymentOrderDetails == null) {
                studentPaymentOrderDetails = new ArrayList<>();
            }
            //汇总金额

            BigDecimal reduce = studentPaymentOrderDetails.stream().map(StudentPaymentOrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (reduce.compareTo(BigDecimal.ZERO) == 0) {
                studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
                studentPaymentOrder.setActualAmount(reduce);
                studentPaymentOrder.setPayTime(date);
            }
            studentPaymentOrder.setExpectAmount(reduce);
            studentPaymentOrderService.insert(studentPaymentOrder);

            //当前学员是否以前存在过当前乐团
            if (phoneAndMusicGroupId != null) {
                studentRegistration.setId(phoneAndMusicGroupId.getId());
                studentRegistrationDao.update(studentRegistration);
            } else {
                studentRegistrationDao.insertBasic(studentRegistration);
            }
            Student student = studentDao.get(userId);
            student.setCurrentGradeNum(studentRegistration.getCurrentGradeNum());
            student.setCurrentClass(studentRegistration.getCurrentClass());
            studentDao.update(student);
            //studentRegistrationDao.updateCurrentClass(studentRegistration);
            imFeignService.update(new ImUserModel(userId.toString(), sysUser.getUsername(), sysUser.getAvatar()));
            return userId;
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId, Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect) {
        //获取欠费学员列表
        List<Integer> studentIdList = Arrays.asList(studentIds.split(",")).stream().mapToInt(idStr -> Integer.valueOf(idStr)).boxed().collect(Collectors.toList());
        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(newMusicGroupId, studentIdList);
        if (noPaymentUserIds.size() > 0) {
            throw new BizException("操作失败：有欠费的学员不允许创建缴费");
        }
        SysUser sysUser1 = sysUserFeignService.queryUserInfo();
        //获取旧乐团学员注册信息
        List<StudentRegistration> studentRegistrations = studentRegistrationDao.queryByUserIdsAndMusicGroupId(studentIds, oldMusicGroupId);
        List<StudentCourseFeeDetail> studentCourseFeeDetails = new ArrayList<>();
        BigDecimal amount = BigDecimal.ZERO;
        for (StudentRegistration studentRegistration : studentRegistrations) {
            List<MusicGroupPaymentCalenderStudentDetail> details = collect.get(studentRegistration.getUserId());
            BigDecimal masterTotalPrice = details.stream().map(e -> e.getCutAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (masterTotalPrice.doubleValue() > studentRegistration.getSurplusCourseFee().doubleValue()) {
                throw new BizException("用户信息发生变动，请重新提交");
            }
            if (oldMusicGroupId.equals(newMusicGroupId)) {
                continue;
            }
            courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(oldMusicGroupId), null, GroupType.MUSIC);
            //记录课程余额消费日志
            if (studentRegistration.getSurplusCourseFee().doubleValue() > 0d && masterTotalPrice.doubleValue() > 0d) {
                StudentCourseFeeDetail studentCourseFeeDetail = new StudentCourseFeeDetail();
                if (studentRegistration.getSurplusCourseFee().doubleValue() > masterTotalPrice.doubleValue()) {
                    amount = masterTotalPrice;
                    studentCourseFeeDetail.setAmount(masterTotalPrice.negate());
                    studentCourseFeeDetail.setSurplusCourseFee(studentRegistration.getSurplusCourseFee().subtract(masterTotalPrice));
                } else {
                    amount = studentRegistration.getSurplusCourseFee();
                    studentCourseFeeDetail.setAmount(studentRegistration.getSurplusCourseFee().negate());
                    studentCourseFeeDetail.setSurplusCourseFee(BigDecimal.ZERO);
                }
                studentCourseFeeDetail.setStudentRegistrationId(studentRegistration.getId());
                studentRegistration.setSurplusCourseFee(studentCourseFeeDetail.getSurplusCourseFee());
                studentCourseFeeDetail.setMemo("跨团合班消费");
                studentCourseFeeDetail.setOperator(sysUser1.getId());
                studentCourseFeeDetails.add(studentCourseFeeDetail);
                //修改原有乐团注册信息
                studentRegistrationDao.update(studentRegistration);
            }
            Boolean orderFlag = true;
            //用户是否在主乐团
            StudentRegistration registration = studentRegistrationDao.getStudentRegister(newMusicGroupId, studentRegistration.getUserId());
            if (registration != null) {
                if (registration.getMusicGroupStatus() == StudentMusicGroupStatusEnum.NORMAL) {
                    orderFlag = false;
                }
                //修改剩余课程余额
                Date date = new Date();
                registration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
                registration.setCreateTime(date);
                registration.setUpdateTime(date);
                registration.setSurplusCourseFee(registration.getSurplusCourseFee().add(amount));
                studentRegistrationDao.update(registration);
            } else {
                //生成学员乐团注册表
                studentRegistration.setOrganId(musicGroupDao.get(newMusicGroupId).getOrganId());
                studentRegistration.setSurplusCourseFee(amount);
                studentRegistration.setMusicGroupId(newMusicGroupId);
                studentRegistrationDao.insert(studentRegistration);
                registration = studentRegistration;

                //增加报名学生数
                musicGroupSubjectPlanService.addApplyStudentNum(newMusicGroupId, studentRegistration.getActualSubjectId(), 1);
                //新增Fee表
                MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(studentRegistration.getUserId(), newMusicGroupId);
                if (musicGroupStudentFee == null) {
                    musicGroupStudentFee = new MusicGroupStudentFee(newMusicGroupId,
                            studentRegistration.getUserId(), studentRegistration.getSubjectId(), BigDecimal.ZERO,
                            null, studentRegistration.getTemporaryCourseFee(), studentRegistration.getPaymentStatus() == YES ? PAID_COMPLETED : NON_PAYMENT);
                    musicGroupStudentFeeDao.insert(musicGroupStudentFee);
                }
            }
            StudentPaymentOrder waitPayOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(registration.getUserId(), studentRegistration.getMusicGroupId(), DealStatusEnum.WAIT_PAY);

            if (waitPayOrder != null) {
                waitPayOrder.setStatus(DealStatusEnum.CLOSE);
                studentPaymentOrderService.update(waitPayOrder);
            }
            if (orderFlag) {
                //生成订单
                StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
                studentPaymentOrder.setUserId(registration.getUserId());
                studentPaymentOrder.setGroupType(GroupType.MUSIC);
                studentPaymentOrder.setType(OrderTypeEnum.APPLY);
                studentPaymentOrder.setMusicGroupId(registration.getMusicGroupId());
                studentPaymentOrder.setClassGroupId(registration.getClassGroupId());
                studentPaymentOrder.setOrganId(registration.getOrganId());
                studentPaymentOrder.setRoutingOrganId(registration.getOrganId());
                studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
                studentPaymentOrder.setActualAmount(BigDecimal.ZERO);
                studentPaymentOrder.setPayTime(new Date());
                studentPaymentOrder.setExpectAmount(BigDecimal.ZERO);
                studentPaymentOrderService.insert(studentPaymentOrder);
            }
            //主班新增余额日志
            if (amount.doubleValue() != 0d && masterTotalPrice.doubleValue() > 0d) {
                StudentCourseFeeDetail studentCourseFeeDetail = new StudentCourseFeeDetail();
                studentCourseFeeDetail.setAmount(amount);
                studentCourseFeeDetail.setSurplusCourseFee(registration.getSurplusCourseFee());
                studentCourseFeeDetail.setStudentRegistrationId(registration.getId());
                studentCourseFeeDetail.setMemo("跨团合班费用转移");
                studentCourseFeeDetail.setOperator(sysUser1.getId());
                studentCourseFeeDetails.add(studentCourseFeeDetail);
            }
        }
        if (studentCourseFeeDetails.size() > 0) {
            studentCourseFeeDetailDao.batchInsert(studentCourseFeeDetails);
        }
    }

    private List<CourseSchedule> addStudent(Integer classGroupId, Integer userId, Date date, List<CourseSchedule> courseScheduleList) {
        ClassGroup classGroup = classGroupDao.get(classGroupId);
        ClassGroupStudentMapper classGroupStudentMapper = classGroupStudentMapperDao.findClassStudentMapperByUserIdAndClassGroupId(userId, classGroupId, null);
        if (classGroupStudentMapper != null) {
            classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
            classGroupStudentMapper.setClassGroupId(classGroup.getId());
            classGroupStudentMapperDao.update(classGroupStudentMapper);
        } else {
            classGroupStudentMapper = new ClassGroupStudentMapper();
            classGroupStudentMapper.setMusicGroupId(classGroup.getMusicGroupId());
            classGroupStudentMapper.setClassGroupId(classGroupId);
            classGroupStudentMapper.setUserId(userId);
            classGroupStudentMapper.setCreateTime(date);
            classGroupStudentMapper.setStatus(ClassGroupStudentStatusEnum.NORMAL);
            classGroupStudentMapper.setGroupType(GroupType.MUSIC);
            classGroupStudentMapperDao.insert(classGroupStudentMapper);
        }
        imGroupMemberService.join(classGroupId.longValue(), userId, null, false);
        //2、班级人数调整
//        classGroupDao.updateClassStudentNum(classGroupId.longValue(), 1);
        //3、学生加入新班级未开始课程
        List<CourseSchedule> noStartCoursesByClassGroupId = courseScheduleService.findNoStartCoursesByClassGroupId(classGroupId);
        if (noStartCoursesByClassGroupId != null && noStartCoursesByClassGroupId.size() > 0) {
            courseScheduleList.addAll(noStartCoursesByClassGroupId);
        }
        return courseScheduleList;
    }

    public void addStudents(StudentAddDto studentAddDto, Integer userId) {
        Date nowDate = new Date();

        String musicGroupId = studentAddDto.getStudentRegistration().getMusicGroupId();
        Integer signClassId = studentAddDto.getSignClassId();
        List<CourseSchedule> courseScheduleList = new ArrayList<>();
        if (signClassId != null) {
            addStudent(signClassId, userId, nowDate, courseScheduleList);
        }
        Integer mixClassId = studentAddDto.getMixClassId();
        if (mixClassId != null) {
            addStudent(mixClassId, userId, nowDate, courseScheduleList);
        }
        Integer highClassId = studentAddDto.getHighClassId();
        if (highClassId != null) {
            addStudent(highClassId, userId, nowDate, courseScheduleList);
        }
        String snapClassIds = studentAddDto.getSnapClassIds();
        if (StringUtils.isNotEmpty(snapClassIds)) {
            String[] split = snapClassIds.split(",");
            for (int i = 0; i < split.length; i++) {
                addStudent(Integer.parseInt(split[i]), userId, nowDate, courseScheduleList);
            }
        }
        List<CourseScheduleStudentPayment> courseScheduleStudentPayments = new ArrayList<>();
        for (CourseSchedule courseSchedule : courseScheduleList) {
            CourseScheduleStudentPayment courseScheduleStudentPayment = new CourseScheduleStudentPayment();
            courseScheduleStudentPayment.setGroupType(GroupType.MUSIC);
            courseScheduleStudentPayment.setMusicGroupId(musicGroupId);
            courseScheduleStudentPayment.setCourseScheduleId(courseSchedule.getId());
            courseScheduleStudentPayment.setUserId(userId);
            courseScheduleStudentPayment.setExpectPrice(BigDecimal.ZERO);
            courseScheduleStudentPayment.setClassGroupId(signClassId);
            courseScheduleStudentPayment.setCreateTime(nowDate);
            courseScheduleStudentPayment.setUpdateTime(nowDate);
            courseScheduleStudentPayments.add(courseScheduleStudentPayment);
        }

        if (courseScheduleStudentPayments.size() == 0) {
            return;
        }
        courseScheduleStudentPaymentService.batchInsert(courseScheduleStudentPayments);
    }

    @Override
    public List<StudentRegistration> findClassGroupStu(String musicGroupId, Integer classGroupId) {
        //获取所有声部
        List<Subject> subjectList = subjectService.findAll(new HashMap<>());
        List<StudentRegistration> classGroupStuList = studentRegistrationDao.findClassGroupStu(musicGroupId, classGroupId);
        for (StudentRegistration studentRegistration : classGroupStuList) {
            for (Subject subject : subjectList) {
                if (studentRegistration.getActualSubjectId().equals(subject.getId())) {
                    studentRegistration.setSubjectName(subject.getName());
                    break;
                }
            }
        }
        return classGroupStuList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentPaymentOrder updateApplyOrder(StudentPaymentOrder studentPaymentOrder) throws Exception {
        //更新订单状态
        int updateCount = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }
        Date nowDate = new Date();

        //成功报名状态变更
        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(studentPaymentOrder.getUserId(), studentPaymentOrder.getMusicGroupId());

        if (studentRegistration.getPaymentStatus().equals(YES)) {
            return studentPaymentOrder;
        }
        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());

        if (studentPaymentOrder.getStatus().equals(DealStatusEnum.SUCCESS)) {
            MusicGroup musicGroup = musicGroupDao.getLocked(studentRegistration.getMusicGroupId());

            if (studentRegistration.getTemporaryCourseFee() != null) {
                studentRegistration.setTemporaryCourseFee(new BigDecimal(0));
            }
            studentRegistration.setPaymentStatus(YES);
            
            if (studentPaymentOrder.getClassGroupId() == null || !studentPaymentOrder.getClassGroupId().equals(206)) {
                studentRegistration.setPayingStatus(0);
            }

            List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailService.getOrderDetail(studentPaymentOrder.getId());

            List<StudentPaymentOrderDetail> allDetails = studentPaymentOrderDetailDao.getOrderDetailByOrderId(studentPaymentOrder.getId());
            BigDecimal courseFee = allDetails.stream().filter(o -> !o.getType().getCode().equals("MUSICAL"))
                    .filter(o -> !o.getType().getCode().equals("ACCESSORIES"))
                    .filter(o -> !o.getType().getCode().equals("MAINTENANCE"))
                    .filter(o -> !o.getType().getCode().equals("CLOUD_TEACHER"))
                    .filter(o -> !o.getType().getCode().equals("CLOUD_TEACHER_PLUS"))
                    .map(o -> o.getPrice().subtract(o.getRemitFee() == null ? BigDecimal.ZERO : o.getRemitFee()))
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            //已购买内容
            List<OrderDetailTypeEnum> orderTypeList = allDetails.stream().map(t -> t.getType()).collect(Collectors.toList());
            
			if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {
				if (studentRegistration.getNoneNeedCloudTeacher() == 1 || orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER)
						|| orderTypeList.contains(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS)) {
					studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
				}
			} else {
				studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
			}

            //累加充值金额
            studentRegistration.setSurplusCourseFee(studentRegistration.getSurplusCourseFee().add(courseFee));
            studentRegistrationDao.update(studentRegistration);

            //添加日志
            StudentCourseFeeDetail studentCourseFeeDetail = new StudentCourseFeeDetail();
            studentCourseFeeDetail.setStudentRegistrationId(studentRegistration.getId());
            studentCourseFeeDetail.setAmount(courseFee);
            studentCourseFeeDetail.setSurplusCourseFee(studentRegistration.getSurplusCourseFee());
            studentCourseFeeDetail.setMemo("充值");
            studentCourseFeeDetail.setOperator(studentPaymentOrder.getUserId());
            studentCourseFeeDetailDao.insert(studentCourseFeeDetail);

            MusicGroupStudentFee musicGroupStudentFee = musicGroupStudentFeeDao.findByUser(studentRegistration.getUserId(), studentRegistration.getMusicGroupId());
            //进行中乐团加入学生缴费
            if (studentRegistration.getTemporaryCourseFee() != null) {
                //关闭待支付订单
                StudentPaymentOrder waitPayOrder = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(studentRegistration.getUserId(), studentRegistration.getMusicGroupId(), DealStatusEnum.WAIT_PAY);
                waitPayOrder.setStatus(DealStatusEnum.CLOSE);
                studentPaymentOrderService.update(waitPayOrder);
                musicGroupStudentFee.setLatestPaidTime(nowDate);
                musicGroupStudentFee.setPaymentStatus(PAID_COMPLETED);
                musicGroupStudentFee.setTemporaryCourseFee(BigDecimal.ZERO);
                musicGroupStudentFee.setUpdateTime(nowDate);
            }
            //插入交易明细
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            SysUserCashAccount cashAccount = sysUserCashAccountService.get(studentRegistration.getUserId());
            //充值
            SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
            rechargeDetail.setAmount(amount);
            rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
            rechargeDetail.setComment("缴费前充值");
            rechargeDetail.setCreateTime(nowDate);
            rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
            rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
            rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
            rechargeDetail.setUpdateTime(nowDate);
            rechargeDetail.setUserId(studentRegistration.getUserId());
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
            rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
            sysUserCashAccountDetailService.insert(rechargeDetail);

            //缴费
            SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
            paymentDetail.setAmount(amount.negate());
            paymentDetail.setBalance(cashAccount.getBalance());
            paymentDetail.setComment("报名缴费");
            paymentDetail.setCreateTime(nowDate);
            paymentDetail.setStatus(DealStatusEnum.SUCCESS);
            paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
            paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
            paymentDetail.setUpdateTime(nowDate);
            paymentDetail.setUserId(studentRegistration.getUserId());
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            if (studentPaymentOrder.getComAmount() != null) {
                rechargeDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
                rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
            }
            sysUserCashAccountDetailService.insert(paymentDetail);

            //销售订单详情
            if (orderDetails.size() > 0) {
                sellOrderService.addOrderDetail2SellOrder(orderDetails, studentPaymentOrder, musicGroup);
            }

            //课程处理
            addCalenderDetail(studentPaymentOrder, studentRegistration);

            //学生乐器与月保处理
            studentInstrumentService.addOrderDetail2Instrument(studentPaymentOrder);

            //学生云教练处理
            cloudTeacherOrderService.addOrderDetail2CloudTeacher(studentPaymentOrder);

            //合并学员处理
            if (studentRegistration.getIsMerge().equals(1) && studentPaymentOrder.getExpectAmount().compareTo(BigDecimal.ZERO) <= 0) {
                return studentPaymentOrder;
            }

            //三方乐团不发送缴费通知
            if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                //发送缴费成功通知（短信 + push）
                Map<Integer, String> map = new HashMap<>(1);
                map.put(studentPaymentOrder.getUserId(), studentRegistration.getParentsPhone());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS,
                        MessageTypeEnum.STUDENT_SMS_PUSH_PAYMENT_SUCCESS, map, null, 0, null, "",
                        studentRegistration.getName(), studentPaymentOrder.getActualAmount());
                //push
                Map<Integer, String> map1 = new HashMap<>(1);
                map1.put(studentPaymentOrder.getUserId(), studentPaymentOrder.getUserId().toString());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,
                        MessageTypeEnum.STUDENT_SMS_PUSH_PAYMENT_SUCCESS, map1, null, 0, null, "STUDENT",
                        studentRegistration.getName(), studentPaymentOrder.getActualAmount());
            }
            try {
                //生成课程协议
                contractService.transferMusicGroupCoursesContract(studentRegistration.getUserId(), studentRegistration.getMusicGroupId());
                // 商品协议(租赁时候有)
                StudentPaymentOrderDetail applyOrderMusical = studentPaymentOrderDetailService.findApplyOrderMusical(studentPaymentOrder.getId());
                if (applyOrderMusical != null && applyOrderMusical.getKitGroupPurchaseType() != null && applyOrderMusical.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                    contractService.transferGoodsContract(studentPaymentOrder.getUserId(), studentPaymentOrder.getMusicGroupId(),
                            applyOrderMusical.getGoodsIdList(), applyOrderMusical.getKitGroupPurchaseType());
                }
            } catch (Exception e) {
                LOGGER.error("协议生成失败", e);
            }
        }

        if (studentPaymentOrder.getStatus().equals(DealStatusEnum.FAILED)) {
            MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
            studentRegistration.setPayingStatus(0);
            studentRegistration.setHasCloudTeacher(0);
            studentRegistrationDao.update(studentRegistration);

            //减去缴费人数（器乐收费，0元时不减缴费人数）
            if (musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE) || musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE)) {
                if (studentPaymentOrder.getPaymentAccountNo() != null && studentPaymentOrder.getPaymentAccountNo().equals("200")) {
                    musicOneSubjectClassPlan.setPaidZeroNum(musicOneSubjectClassPlan.getPaidZeroNum() - 1);
                    musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() - 1);
                } else if (studentPaymentOrder.getPaymentAccountNo() == null) {
                    musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() - 1);
                }
            } else {
                musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() - 1);
            }
            updateCount = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
            if (updateCount <= 0) {
                throw new BizException("减去缴费人数失败");
            }
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "报名缴费失败");
            }
            //三方乐团不发送缴费通知
            if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + studentRegistration.getMusicGroupId();
                Map<Integer, String> map = new HashMap<>(1);
                map.put(studentPaymentOrder.getUserId(), studentRegistration.getParentsPhone());
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS,
                        MessageTypeEnum.STUDENT_SMS_PAYMENT_FAILED, map, null, 0, null, "",
                        HttpUtil.getSortUrl(studentApplyUrl));
            }
//            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG,
//                    MessageTypeEnum.STUDENT_SMS_PAYMENT_FAILED,map,null,0,"1",
//                    studentApplyUrl);
        }

        return studentPaymentOrder;
    }


    private boolean addCalenderDetail(StudentPaymentOrder studentPaymentOrder, StudentRegistration studentRegistration) {
        Date nowDate = new Date();
        MusicGroupStudentFee musicGroupStudentFee = new MusicGroupStudentFee();
        musicGroupStudentFee.setLatestPaidTime(nowDate);
        musicGroupStudentFee.setPaymentStatus(PAID_COMPLETED);
        musicGroupStudentFee.setUpdateTime(nowDate);
        musicGroupStudentFee.setContinuousAbsenteeismTimes(0);
        musicGroupStudentFee.setSubjectId(studentRegistration.getActualSubjectId());
        musicGroupStudentFee.setIsLock(0);
        musicGroupStudentFee.setMusicGroupId(studentRegistration.getMusicGroupId());
        musicGroupStudentFee.setUserId(studentRegistration.getUserId());

        String currentMusicGroupId = studentRegistration.getMusicGroupId();

        //缴费详情 calender detail
        MusicGroupPaymentCalender musicGroupRegCalender = musicGroupPaymentCalenderService.findByMusicGroupRegCalender(currentMusicGroupId);
        if (musicGroupRegCalender == null) {
            musicGroupStudentFeeDao.insert(musicGroupStudentFee);
            return true;
        }

        String batchNo = musicGroupRegCalender.getBatchNo();
        Long currentPaymentCalenderId = musicGroupRegCalender.getId();

        List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.findByBatchNo(batchNo);

        if (musicGroupRegCalender.getIsGiveMusicNetwork() != null && musicGroupRegCalender.getIsGiveMusicNetwork()) {
            //赠送网管课
            musicGroupStudentFee.setRemainNetworkClassTimes(musicGroupStudentFee.getRemainNetworkClassTimes() + musicGroupPaymentCalenderList.size());
        }
        musicGroupStudentFeeDao.insert(musicGroupStudentFee);

        for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenderList) {
            if (currentPaymentCalenderId.longValue() == musicGroupPaymentCalender.getId()) {
                // 更新实际缴费人数
                if (musicGroupPaymentCalender.getActualNum() == null) {
                    musicGroupPaymentCalender.setActualNum(1);
                } else {
                    musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + 1);
                }
            }
            if (musicGroupPaymentCalender.getExpectNum() == null) {
                musicGroupPaymentCalender.setExpectNum(1);
            } else {
                musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + 1);
            }
            musicGroupPaymentCalender.setUpdateTime(nowDate);
        }
        if (musicGroupPaymentCalenderList.size() > 0) {
            musicGroupPaymentCalenderDao.batchUpdate(musicGroupPaymentCalenderList);
        }

        List<String> orderDetailTypes = studentPaymentOrderDetailDao.getOrderDetailType(studentPaymentOrder.getId());
        List<MusicGroupPaymentCalenderCourseSettings> courseSettings = musicGroupPaymentCalenderCourseSettingsDao.getWithPaymentCalender(musicGroupRegCalender.getId());
        BigDecimal courseTotalPrice = courseSettings.stream().filter(e -> orderDetailTypes.contains(e.getCourseType().getCode())).map(MusicGroupPaymentCalenderCourseSettings::getCourseCurrentPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        BigDecimal optionalCourseFee = courseSettings.stream().filter(MusicGroupPaymentCalenderCourseSettings::getIsStudentOptional).filter(e -> orderDetailTypes.contains(e.getCourseType().getCode())).map(MusicGroupPaymentCalenderCourseSettings::getCourseCurrentPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

        List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetails = new ArrayList<>();

        for (MusicGroupPaymentCalender musicGroupPaymentCalender : musicGroupPaymentCalenderList) {
            MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
            musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
            musicGroupPaymentCalenderDetail.setUserId(studentPaymentOrder.getUserId());
            musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());

            if (currentPaymentCalenderId.longValue() == musicGroupPaymentCalender.getId()) {
                musicGroupPaymentCalenderDetail.setExpectAmount(courseTotalPrice);
                if (studentPaymentOrder.getCourseRemitFee() != null && (studentPaymentOrder.getCourseRemitFee().compareTo(BigDecimal.ZERO) > 0)) {
                    musicGroupPaymentCalenderDetail.setActualAmount(optionalCourseFee);
                } else {
                    musicGroupPaymentCalenderDetail.setActualAmount(courseTotalPrice);
                }
                musicGroupPaymentCalenderDetail.setPaymentStatus(PAID_COMPLETED);
                musicGroupPaymentCalenderDetail.setPayTime(nowDate);
                musicGroupPaymentCalenderDetail.setPaymentOrderId(studentPaymentOrder.getId());
                musicGroupPaymentCalenderDetail.setUseInCourse(0);
                musicGroupPaymentCalenderDetail.setOpen(1);
            } else {
                musicGroupPaymentCalenderDetail.setExpectAmount(musicGroupPaymentCalender.getPaymentAmount());
                musicGroupPaymentCalenderDetail.setPaymentStatus(MusicGroupStudentFee.PaymentStatus.NON_PAYMENT);
            }
            if(orderDetailTypes.contains(OrderDetailTypeEnum.CLOUD_TEACHER.name()) || orderDetailTypes.contains(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS.name())){
            	musicGroupPaymentCalenderDetail.setExpectAmount(musicGroupPaymentCalenderDetail.getExpectAmount().add(musicGroupPaymentCalender.getMemberPaymentAmount()));
            	musicGroupPaymentCalenderDetail.setActualAmount(musicGroupPaymentCalenderDetail.getActualAmount().add(musicGroupPaymentCalender.getMemberPaymentAmount()));
            }
            
            musicGroupPaymentCalenderDetail.setUserStatus(null);
            musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
            musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
            musicGroupPaymentCalenderDetail.setCreateTime(nowDate);
            musicGroupPaymentCalenderDetail.setUpdateTime(nowDate);

            musicGroupPaymentCalenderDetailDao.insert(musicGroupPaymentCalenderDetail);

            List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao
                    .getWithPaymentCalender(musicGroupPaymentCalender.getId());
            for (MusicGroupPaymentCalenderCourseSettings courseSetting : courseSettingsList) {
                if (musicGroupRegCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)
                        && !orderDetailTypes.contains(courseSetting.getCourseType().getCode())) {
                    continue;
                }
                if (courseSetting.getCourseTotalMinuties() == null || courseSetting.getCourseTotalMinuties() == 0) {
                    continue;
                }
                MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
                musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
                musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetail.getId());
                musicGroupPaymentStudentCourseDetail.setUserId(studentPaymentOrder.getUserId());
                musicGroupPaymentStudentCourseDetail.setCourseType(courseSetting.getCourseType());
                musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSetting.getCourseTotalMinuties());
                musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSetting.getCourseOriginalPrice());
                musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSetting.getCourseCurrentPrice());
                musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
                musicGroupPaymentStudentCourseDetail.setCreateTime(nowDate);
                musicGroupPaymentStudentCourseDetail.setUpdateTime(nowDate);

                musicGroupPaymentStudentCourseDetails.add(musicGroupPaymentStudentCourseDetail);
            }
        }

        if (musicGroupPaymentStudentCourseDetails.size() > 0) {
            musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetails);
        }
        return true;
    }

    @Override
    public List<StudentRegistration> findMusicGroupNoClassGroupStudent(String musicGroupId, Integer actualSubjectId) {
        //获取所有声部
        List<Subject> subjectList = subjectService.findAll(new HashMap<>());
        List<StudentRegistration> classGroupStuList = studentRegistrationDao.findMusicGroupNoClassGroupStudent(musicGroupId, actualSubjectId);
        for (StudentRegistration studentRegistration : classGroupStuList) {
            for (Subject subject : subjectList) {
                if (studentRegistration.getActualSubjectId().equals(subject.getId())) {
                    studentRegistration.setSubjectName(subject.getName());
                    break;
                }
            }
        }
        return classGroupStuList;
    }

    @Override
    public List<StudentRegistration> findStudentListByIdList(List<Long> idList) {
        return studentRegistrationDao.findStudentListByIdList(idList);
    }

    @Override
    public int batchInsert(List<StudentRegistration> studentRegistrationList) {
        return studentRegistrationDao.batchInsert(studentRegistrationList);
    }

    @Override
    public StudentRegistration findStudentByClassGroupIdAndUserId(Integer userId, Integer classGroupId) {
        return studentRegistrationDao.findStudentByClassGroupIdAndUserId(userId, classGroupId);
    }

    @Override
    public List<StudentRegistration> findMusicGroupStudent(String musicGroupId, String actualSubjectId) {
        List<Subject> subjectList = subjectService.findAll(new HashMap<>());
        List<StudentRegistration> musicGroupStudents = studentRegistrationDao.findMusicGroupStudent(musicGroupId, actualSubjectId);
        for (StudentRegistration musicGroupStudent : musicGroupStudents) {
            for (Subject subject : subjectList) {
                if (musicGroupStudent.getActualSubjectId().equals(subject.getId())) {
                    musicGroupStudent.setSubjectName(subject.getName());
                }
            }
        }
        return musicGroupStudents;
    }

    @Override
    public List<StudentRegistration> findStudentListByUserIdList(String musicGroupId, List<Integer> userIdList) {
        return studentRegistrationDao.findStudentListByUserIdList(musicGroupId, userIdList);
    }

    @Override
    public int openPayment(String ids) throws IOException {
        if (StringUtils.isNotEmpty(ids)) {
            //发送短信通知
            List<Long> list = JSONObject.parseArray(JSONObject.toJSONString(Arrays.asList(ids.split(","))), Long.class);
            MusicGroup musicGroup = musicGroupDao.findMusicGroup(list);
            MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderService.findByMusicGroupRegCalender(musicGroup.getId());
            if (regCalender != null && regCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)) {
                regCalender.setStatus(MusicGroupPaymentCalender.PaymentCalenderStatusEnum.OPEN);
                musicGroupPaymentCalenderService.update(regCalender);
            }

            //三方乐团不发送缴费通知
            if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                List<StudentRegistration> registrations = studentRegistrationDao.findStudentListByIdList(list);
                String configValue = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL);
                HashMap<Integer, String> receivers = new HashMap<>(registrations.size());
                registrations.forEach(e -> {
                    receivers.put(e.getUserId(), e.getParentsPhone());
                });
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS,
                        MessageTypeEnum.STUDENT_SMS_OPEN_PAYMENT, receivers, null, 0, null, "",
                        musicGroup.getName(), HttpUtil.getSortUrl(configValue + musicGroup.getId()));
            }
        }
        return studentRegistrationDao.batchOpenPay(ids, PaymentStatusEnum.OPEN);
    }

    @Override
    public List<StudentRegistration> queryStudentByMusicGroupId(String musicGroupId) {
        return studentRegistrationDao.queryStudentByMusicGroupId(musicGroupId);
    }

    @Override
    public List<Map<Integer, String>> findParentId(String parentPhones) {
        return studentRegistrationDao.findParentId(parentPhones);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentRegistration updateStudent(StudentRegistration studentRegistration) {
        if (StringUtils.isBlank(studentRegistration.getCertificateType())) {
            studentRegistration.setCertificateType(CertificateTypeEnum.IDENTITY.getCode());
        }
        StudentRegistration student = get(studentRegistration.getId());
        if (student == null) {
            throw new BizException("用户注册信息不存在，无法更新");
        }
        student.setName(studentRegistration.getName());
        student.setParentsName(studentRegistration.getParentsName());
        student.setIdCardNo(studentRegistration.getIdCardNo());
        student.setGender(studentRegistration.getGender());
        Organization organization = organizationDao.get(studentRegistration.getOrganId());
        String studentGrade = studentService.getStudentGrade(organization.getGradeType(), studentRegistration.getCurrentGradeNum());
        studentRegistration.setCurrentGrade(studentGrade);
        update(studentRegistration);
        studentRegistrationDao.updateUser(student.getUserId(), student.getName(), student.getParentsName(), student.getIdCardNo(), student.getGender(), studentRegistration.getCertificateType());
        //更新年级信息
        Student studentInfo = studentDao.get(student.getUserId());
        studentInfo.setCurrentGradeNum(studentRegistration.getCurrentGradeNum());
        studentInfo.setCurrentClass(studentRegistration.getCurrentClass());
        studentDao.update(studentInfo);
        // 添加用户电子签章账户
        contractService.register(student.getUserId(), student.getParentsName(), student.getIdCardNo(), student.getParentsPhone());
        return student;
    }

    @Override
    public StudentRegistration queryUserByPhone(String mobile) {
        return studentRegistrationDao.queryUserByPhone(mobile);
    }

    @Override
    public List<StudentRegistration> findMusicGroupStuNoClassType(String musicGroupId, Long classGroupId, ClassGroupTypeEnum type, String subjectId) {
        List<StudentRegistration> students = studentRegistrationDao.findMusicGroupStudent(musicGroupId, subjectId);
        List<Subject> subjectList = subjectService.findAll(new HashMap<>());

        Map<CourseSchedule.CourseScheduleType, Integer> courseTypeCourseDurationMap = new HashMap<>();
        Map<CourseSchedule.CourseScheduleType, List<CourseSchedule>> typeCourseMap = new HashMap<>();
        if (Objects.nonNull(classGroupId)) {
            List<CourseSchedule> classGroupNotStartCourse = courseScheduleDao.findCoursesByClassGroupId(classGroupId.intValue(), CourseStatusEnum.NOT_START);
            typeCourseMap = classGroupNotStartCourse.stream().collect(Collectors.groupingBy(CourseSchedule::getType));
            for (Map.Entry<CourseSchedule.CourseScheduleType, List<CourseSchedule>> typeCoursesEntry : typeCourseMap.entrySet()) {
                int totalCourseDuration = 0;
                for (CourseSchedule courseSchedule : typeCoursesEntry.getValue()) {
                    //课程时长
                    int courseDuration = DateUtil.minutesBetween(courseSchedule.getStartClassTime(), courseSchedule.getEndClassTime());
                    totalCourseDuration += courseDuration;
                }
                courseTypeCourseDurationMap.put(typeCoursesEntry.getKey(), totalCourseDuration);
            }
        }

        List<ClassGroupStudentMapper> classGroupStudentMappers = classGroupStudentMapperDao.findMusicGroupClassGroupByType(musicGroupId, type);
        Iterator<StudentRegistration> iterator = students.iterator();
        while (iterator.hasNext()) {
            StudentRegistration student = iterator.next();

            boolean courseMinutesNotEnough = false;

            for (Map.Entry<CourseSchedule.CourseScheduleType, List<CourseSchedule>> courseScheduleTypeListEntry : typeCourseMap.entrySet()) {
                //当前课程类型总课程时长
                Integer typeCourseDuration = courseTypeCourseDurationMap.get(courseScheduleTypeListEntry.getKey());

                String batchNo = musicGroupPaymentStudentCourseDetailDao.getUnUseBatchNoWithStudentAndCourseTypeAndCourseMinutes(musicGroupId, student.getUserId(), courseScheduleTypeListEntry.getKey(), null);

                List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetails = musicGroupPaymentStudentCourseDetailDao.getUnUseWithStudentAndCourseTypeAndCourseMinutes(batchNo, student.getUserId(), courseScheduleTypeListEntry.getKey());
                int totalCourseMinutes = musicGroupPaymentStudentCourseDetails.stream().mapToInt(MusicGroupPaymentStudentCourseDetail::getTotalCourseMinutes).reduce(0, Integer::sum);
                if (CollectionUtils.isEmpty(musicGroupPaymentStudentCourseDetails) || totalCourseMinutes < typeCourseDuration) {
                    iterator.remove();
                    courseMinutesNotEnough = true;
                    break;
                }
            }

            if (courseMinutesNotEnough) {
                continue;
            }

            for (Subject subject : subjectList) {
                if (student.getActualSubjectId().equals(subject.getId())) {
                    student.setSubjectName(subject.getName());
                    break;
                }
            }
            if (type.equals(ClassGroupTypeEnum.SNAP)) continue;
            for (ClassGroupStudentMapper classGroupStudentMapper : classGroupStudentMappers) {
                if (student.getUserId().equals(classGroupStudentMapper.getUserId())) {
                    iterator.remove();
                    break;
                }
            }
        }
        return students;
    }

    @Override
    public List<Subject> findMusicGroupAllStudentSubjects(String musicGroupId) {
        return studentRegistrationDao.findMusicGroupAllStudentSubjects(musicGroupId);
    }

    @Override
    public StudentMusicDetailDto getStudentDetail(Integer studentId) {
        return studentRegistrationDao.getStudentDetail(studentId);
    }

    @Override
    public List<StudentPaymentOrderDetail> getStudentApplyDetail(Integer studentId, String musicGroupId) {
        SubjectChange studentLastChange = subjectChangeDao.getStudentLastChange(studentId, musicGroupId);
        List<StudentPaymentOrderDetail> details = new ArrayList<>();
        if (studentLastChange != null) {
            StudentPaymentOrderDetail course = new StudentPaymentOrderDetail();
            course.setType(OrderDetailTypeEnum.COURSE);
            course.setPrice(studentLastChange.getChangeCourseFee());
            details.add(course);
            if (studentLastChange.getChangeMusical() != null) {
                StudentPaymentOrderDetail musical = new StudentPaymentOrderDetail();
                musical.setType(OrderDetailTypeEnum.MUSICAL);
                musical.setKitGroupPurchaseType(studentLastChange.getKitGroupPurchaseType());
                musical.setPrice(studentLastChange.getChangeMusicalPrice());
                musical.setGoodsList(goodsDao.findGoodsByIds(studentLastChange.getChangeMusical().toString()));
                details.add(musical);
            }

            if (studentLastChange.getChangeAccessories() != null) {
                StudentPaymentOrderDetail accessories = new StudentPaymentOrderDetail();
                accessories.setType(OrderDetailTypeEnum.ACCESSORIES);
                accessories.setPrice(studentLastChange.getChangeAccessoriesPrice());
                accessories.setGoodsList(goodsDao.findGoodsByIds(studentLastChange.getChangeAccessories()));
                details.add(accessories);
            }
        }
        if (details.size() <= 0) {
            details = studentPaymentOrderDetailDao.getStudentApplyDetail(studentId, musicGroupId);
        }
        return details;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentRegistration changeStudentSubject(Integer studentId, String musicGroupId, Integer originalSubjectId, Integer changeSubjectId) {
        studentDao.lockUser(studentId);
        //1、更换学生的声部
        StudentRegistration studentRegistration = studentRegistrationDao.getStudentRegister(musicGroupId, studentId);
        studentRegistration.setActualSubjectId(changeSubjectId);
        studentRegistrationDao.update(studentRegistration);

        //2、减去原声部的已缴费数量,加上现声部的缴费人数
        boolean updateFlag = false;
        for (int i = 0; i < 10; i++) {
            MusicGroupSubjectPlan originalSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, originalSubjectId);
            int originalPaidNum = originalSubjectPlan.getPaidStudentNum() == null ? 0 : originalSubjectPlan.getPaidStudentNum();
            int originalPaidCount = 1;
            if (originalPaidNum > 0) {
                originalSubjectPlan.setPaidStudentNum(originalPaidNum - 1);
                originalPaidCount = musicGroupSubjectPlanService.update(originalSubjectPlan);
            }
            MusicGroupSubjectPlan changeSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, changeSubjectId);
            int changelPaidNum = changeSubjectPlan.getPaidStudentNum() == null ? 0 : changeSubjectPlan.getPaidStudentNum();
            changeSubjectPlan.setPaidStudentNum(changelPaidNum + 1);
            int changePaidCount = musicGroupSubjectPlanService.update(changeSubjectPlan);
            if (originalPaidCount > 0 && changePaidCount > 0) {
                updateFlag = true;
                break;
            }
        }
        if (!updateFlag) {
            throw new BizException("系统繁忙，更新学生声部失败，请重试");
        }
        return studentRegistration;
    }

    @Override
    public BigDecimal getClassGroupCourseExpectPrice(List<Integer> classGroupIds) {
        List<CourseScheduleStudentPayment> classGroupNoStartCourse = courseScheduleStudentPaymentService.getClassGroupNoStartCourse(classGroupIds);
        return classGroupNoStartCourse.stream().map(CourseScheduleStudentPayment::getExpectPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public BigDecimal updateUserSurplusCourseFee(Integer userId, String musicGroupId, BigDecimal amount, String memo, Integer operatorId) {
        StudentRegistration studentRegistration = studentRegistrationDao.lockWithUserAndMusic(userId, musicGroupId);
        if (Objects.isNull(studentRegistration)) {
            LOGGER.error("学员{}-{}可用排课余额更新失败：学员注册信息不存在", amount);
            return BigDecimal.ZERO;
        }

        if (BigDecimal.ZERO.compareTo(amount) > 0 && amount.abs().compareTo(studentRegistration.getSurplusCourseFee()) > 0) {
            amount = studentRegistration.getSurplusCourseFee().negate();
        }

        studentRegistration.setSurplusCourseFee(studentRegistration.getSurplusCourseFee().add(amount));

        if (BigDecimal.ZERO.compareTo(amount) == 0) {
            return BigDecimal.ZERO;
        }

        StudentCourseFeeDetail studentCourseFeeDetail = new StudentCourseFeeDetail();
        studentCourseFeeDetail.setStudentRegistrationId(studentRegistration.getId());
        studentCourseFeeDetail.setAmount(amount);
        studentCourseFeeDetail.setSurplusCourseFee(studentRegistration.getSurplusCourseFee());
        studentCourseFeeDetail.setMemo(memo);
        studentCourseFeeDetail.setOperator(operatorId);
        studentCourseFeeDetailDao.insert(studentCourseFeeDetail);

        studentRegistrationDao.update(studentRegistration);
        return amount;
    }

    @Override
    public List<StudentMusicGroupDto> queryStudentMusicGroupInfo(Integer userId) {
        return studentRegistrationDao.queryStudentMusicGroupInfo(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delReg(Long id) {
        StudentRegistration studentRegistration = studentRegistrationDao.get(id);
        MusicGroupSubjectPlan subjectPlan = musicGroupSubjectPlanDao.findSubjectPlan(studentRegistration.getMusicGroupId(), studentRegistration.getSubjectId());
        int delNum = studentRegistrationDao.delete(id);
        subjectPlan.setApplyStudentNum(subjectPlan.getApplyStudentNum() - 1);
        int updateNum = musicGroupSubjectPlanDao.update(subjectPlan);
        if (delNum <= 0 || updateNum <= 0) {
            throw new BizException("删除失败，请重试");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDelRegs(String musicGroupId, List<Integer> userIds) {
        List<StudentRegistration> registrations = studentRegistrationDao.findStudentListByUserIdList(musicGroupId, userIds);
        for (StudentRegistration registration : registrations) {
            if (registration.getPaymentStatus().equals(PaymentStatusEnum.OPEN) || registration.getPaymentStatus().equals(PaymentStatusEnum.YES)) {
                throw new BizException(registration.getName() + "（" + registration.getPaymentStatus().getDesc() + "），不能删除");
            }
        }
        if (registrations.size() <= 0) {
            throw new BizException("删除的学员不存在，请核查");
        }
        Map<Integer, List<StudentRegistration>> regMap = registrations.stream().collect(Collectors.groupingBy(StudentRegistration::getSubjectId));
        //更新声部信息
        for (Map.Entry<Integer, List<StudentRegistration>> regEntry : regMap.entrySet()) {
            MusicGroupSubjectPlan subjectPlan = musicGroupSubjectPlanDao.findSubjectPlan(musicGroupId, regEntry.getKey());
            subjectPlan.setApplyStudentNum(subjectPlan.getApplyStudentNum() - regEntry.getValue().size());
            int updateNum = musicGroupSubjectPlanDao.update(subjectPlan);
            if (updateNum <= 0) {
                throw new BizException("声部信息更新失败");
            }
        }
        //删除注册信息
        List<Long> ids = registrations.stream().map(StudentRegistration::getId).collect(Collectors.toList());
        int delNum = studentRegistrationDao.batchDelete(ids);
        if (delNum <= 0) {
            throw new BizException("学员删除失败");
        }
        return true;
    }

    @Override
    public List<StudentRegistration> getMusicGroupStuReBack(String musicGroupId) {
        courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(musicGroupId), null, GroupType.MUSIC);
        return this.findMusicGroupStudent(musicGroupId, null);
    }

    @Override
    public String checkRegOrPayStatus(String musicGroupId) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup.getStatus() == MusicGroupStatusEnum.PAY ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PREPARE ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS) {
            Date now = new Date();
            MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroup.getId());
            if (regCalender != null && regCalender.getDeadlinePaymentDate() != null) {
                musicGroup.setPaymentExpireDate(regCalender.getDeadlinePaymentDate());
            }

            if (musicGroup.getPaymentExpireDate() != null && now.compareTo(DateUtil.getLastTimeWithDay(musicGroup.getPaymentExpireDate())) > 0) {
                return "乐团缴费时间已截止";
            }
        }
        //储备中、进行中，乐团没有报名缴费项、有多批次缴费项不能缴费、有已上的课程不能缴费
        if (musicGroup.getStatus() == MusicGroupStatusEnum.PREPARE ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS) {
            MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroup.getId());
            if (regCalender == null) {
                return "乐团没有报名缴费项";
            }
            List<MusicGroupPaymentCalender> musicGroupCalenderBatchNoTimes = musicGroupPaymentCalenderDao.getMusicGroupCalenderBatchNoTimes(musicGroup.getId());
            if (musicGroupCalenderBatchNoTimes.size() > 1) {
                return "乐团已进入续费阶段";
            }

//            Integer hasStartCourseNum = courseScheduleDao.getMusicGroupHasStartCourseNum(musicGroup.getId());
//            if (hasStartCourseNum != null && hasStartCourseNum > 0) {
//                return "乐团已开课";
//            }
        }
        return null;
    }

    @Override
    public Map<String, Boolean> checkMusicGroupsRegOrPayStatus(List<String> ids) {
        Map<String, Boolean> viewMap = new HashMap<>();
        List<MusicGroupPaymentCalender> regCalenders = musicGroupPaymentCalenderDao.getMusicGroupRegCalenderByIds(ids);
        for (MusicGroupPaymentCalender regCalender : regCalenders) {
            viewMap.put(regCalender.getMusicGroupId(), true);
        }

        Map<String, List<MusicGroupPaymentCalender>> musicGroupBatchNoTimes = musicGroupPaymentCalenderDao.getMusicGroupCalenderBatchNoByIds(ids).stream().collect(Collectors.groupingBy(MusicGroupPaymentCalender::getMusicGroupId));
        musicGroupBatchNoTimes.forEach((musicGroupId, calenders) -> {
            if (viewMap.containsKey(musicGroupId) && calenders.size() > 1) {
                viewMap.remove(musicGroupId);
            }
        });
//        List<CourseSchedule> musicGroupsHasStartCourseNums = courseScheduleDao.getMusicGroupsHasStartCourseNum(ids);
//        for (CourseSchedule musicGroupsHasStartCourseNum : musicGroupsHasStartCourseNums) {
//            if(viewMap.containsKey(musicGroupsHasStartCourseNum.getMusicGroupId())){
//                viewMap.remove(musicGroupsHasStartCourseNum.getMusicGroupId());
//            }
//        }
        return viewMap;
    }

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

        if (StringUtils.isNotBlank(queryInfo.getOrganIds())) {
            List<Integer> organIds = Arrays.stream(queryInfo.getOrganIds().split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
            params.put("organIds", organIds);
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        List<Integer> userRole = employeeDao.queryUserRole(sysUser.getId());
        //如果当前用户只有教务老师角色，那么只能看到他所管理的课程组的信息
        if (userRole.size() == 1 && userRole.contains(SysUserRole.EDUCATIONAL_TEACHER)) {
            params.put("educationUserId", sysUser.getId());
        }

        List<NoClassMusicStudentDto> dataList = new ArrayList<>();
        int count = studentRegistrationDao.countNoClassMusicStudents(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentRegistrationDao.queryNoClassMusicStudents(params);
        }

        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Integer quitAllStudent(String musicGroupId, String remark) {
        return studentRegistrationDao.quitAllStudent(musicGroupId, remark);
    }

    @Override
    public List<Map<String, Integer>> countNormalNum(List<String> musicGroupIds) {
        return studentRegistrationDao.countNormalNum(StringUtils.join(musicGroupIds, ","));
    }

    @Override
    public PageInfoReg<RegisterDto> getRegisterOrPreList(RegistrationOrPreQueryInfo queryInfo) {
        PageInfoReg<RegisterDto> pageInfo = new PageInfoReg<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<RegisterDto> dataList = new ArrayList<>();
        int count = studentRegistrationDao.getRegisterOrPreCount(params);
        if (queryInfo.getIsExport() && count > 50000) {
            throw new BizException("数据集太大，不能导出.最大数据集不能超过50000");
        }
        int registerNum = studentRegistrationDao.getRegisterNum(queryInfo.getMusicGroupId());
        pageInfo.setRegNum(registerNum);
        RegisterDto registerOrPreMinTime = studentRegistrationDao.getRegisterOrPreMinTime(queryInfo.getMusicGroupId());
        if (registerOrPreMinTime != null && registerOrPreMinTime.getMinPayTime() != null) {
            Date startTime = DateUtil.trunc(registerOrPreMinTime.getMinPayTime());
            Date endTime = DateUtil.getLastTimeWithDay(startTime);
            int firstPayNum = studentRegistrationDao.getFirstPayNum(queryInfo.getMusicGroupId(), startTime, endTime);
            int totalPayNum = studentRegistrationDao.getFirstPayNum(queryInfo.getMusicGroupId(), startTime, null);
            pageInfo.setFirstDayPayNum(firstPayNum);
            pageInfo.setPayNum(totalPayNum);
            pageInfo.setPayScale(new BigDecimal(firstPayNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalPayNum), 2, BigDecimal.ROUND_HALF_UP));
        }

        pageInfo.setTotal(count);
        params.put("offset", pageInfo.getOffset());
        if (queryInfo.getPage() <= pageInfo.getTotalPage()) {
            Date firstPreTime = registerOrPreMinTime != null ? registerOrPreMinTime.getMinPerRegisterTime() : null;
            Date firstPayTime = registerOrPreMinTime != null ? registerOrPreMinTime.getMinPayTime() : null;
            dataList = studentRegistrationDao.getRegisterOrPreList(params);
            for (RegisterDto registerDto : dataList) {
                if (DateUtil.dateToString(registerDto.getPerRegisterTime()).equals("2099-12-31") ||
                        DateUtil.dateToString(registerDto.getPerRegisterTime()).equals("1990-12-31")
                ) {
                    registerDto.setPerRegisterTime(null);
                }

                if (DateUtil.dateToString(registerDto.getPayTime()).equals("2099-12-31") ||
                        DateUtil.dateToString(registerDto.getPayTime()).equals("1990-12-31")
                ) {
                    registerDto.setPayTime(null);
                }
                if (firstPreTime != null && registerDto.getPerRegisterTime() != null) {
                    int perRegInterval = DateUtil.secondsBetween(firstPreTime, registerDto.getPerRegisterTime());
                    registerDto.setPerRegInterval(perRegInterval);
                    registerDto.setPerRegIntervalStr(DateUtil.secondsFormat(perRegInterval));
                }

                if (firstPayTime != null && registerDto.getPayTime() != null) {
                    int payTimeInterval = DateUtil.secondsBetween(firstPayTime, registerDto.getPayTime());
                    registerDto.setPayInterval(payTimeInterval);
                    registerDto.setPayIntervalStr(DateUtil.secondsFormat(payTimeInterval));
                }
            }
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Boolean setNoneCloudTeacher(Long id) {
        StudentRegistration studentRegistration = studentRegistrationDao.get(id);
        if (!studentRegistration.getPayingStatus().equals(2)) {
            throw new BizException("该学生不在审核中");
        }
        if (studentRegistration.getNoneNeedCloudTeacher().equals(1)) {
            throw new BizException("该学生已设置");
        }
        studentRegistration.setNoneNeedCloudTeacher(1);
        if (studentRegistrationDao.update(studentRegistration) <= 0) {
            throw new BizException("设置失败，请重试");
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addPaidNum(Long id) {
        StudentRegistration studentRegistration = studentRegistrationDao.get(id);
        if (!studentRegistration.getPayingStatus().equals(2)) {
            throw new BizException("该学生不在审核");
        }
        if (!studentRegistration.getPaymentStatus().equals(YES)) {
            throw new BizException("该学生状态已更新，请刷新查看");
        }
        studentRegistration.setPayingStatus(0);
        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
        studentRegistrationDao.update(studentRegistration);
        StudentPaymentOrder order = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(studentRegistration.getUserId(), studentRegistration.getMusicGroupId(), DealStatusEnum.SUCCESS);
        order.setPaymentAccountNo("200");
        if(studentPaymentOrderService.update(order)<=0){
            throw new BizException("订单处理失败，请重试");
        }

        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());
        int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
        int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
        musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
        musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
        int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
        if (count <= 0) {
            throw new BizException("缴费人数更新失败，请重试");
        }
        return true;
    }

    @Override
    public StudentRegistration getStudentRegister(String musicGroupId, Integer studentId) {
        return studentRegistrationDao.getStudentRegister(musicGroupId,studentId);
    }
}
