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

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.enums.CertificateTypeEnum;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.*;
import com.ym.mec.biz.event.source.SendSeoMessageSource;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
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.page.WrapperUtil;
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;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

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.OrderDetailTypeEnum.*;
import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;
import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;

@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 SendSeoMessageSource sendSeoMessageSource;
    @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 SysTenantConfigService sysTenantConfigService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private SubjectChangeDao subjectChangeDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
    @Autowired
    private StudentCourseFeeDetailDao studentCourseFeeDetailDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private ImGroupDao imGroupDao;
    @Autowired
    private StudentInstrumentDao studentInstrumentDao;
    
    @Autowired
    private GoodsProcurementDao goodsProcurementDao;
    
    @Autowired
    private MusicGroupPaymentCalenderStudentDetailDao musicGroupPaymentCalenderStudentDetailDao;
    @Autowired
    private CloudTeacherOrderService cloudTeacherOrderService;
    @Autowired
    private SysCouponCodeService sysCouponCodeService;
    @Autowired
    private SysUserCashAccountLogService sysUserCashAccountLogService;
    @Autowired
    private MusicGroupPaymentCalenderActivityService musicGroupPaymentCalenderActivityService;
    @Autowired
    private MusicGroupPaymentCalenderMemberService musicGroupPaymentCalenderMemberService;
    @Autowired
    private MusicGroupPaymentCalenderRepairService musicGroupPaymentCalenderRepairService;

    @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("学员信息不存在");
        }
        
        Student student = studentService.get(userId);
        if(student == null){
        	throw new BizException("用户[{}]信息获取失败", userId);
        }
        
        if(!StringUtils.equals(student.getSubjectIdList(), subId+"")){
        	student.setSubjectIdList(subId + "");
        	student.setUpdateTime(new Date());
        	studentService.update(student);
        }
        
        //批量调剂（未缴费学员）
        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);

            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    null, musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_STUDENT_SUBJECT_CHANGE, musicGroup.getName());
        }
        return i;
    }

    @Override
    public List<StudentPaymentOrderDetail> queryFeeDetail(Integer studentId, String musicGroupId) {

        List<StudentPaymentOrder> studentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC, musicGroupId, studentId,
                DealStatusEnum.SUCCESS, OrderTypeEnum.APPLY);

        List<Long> orderIdList = studentPaymentOrderList.stream().map(t -> t.getId()).collect(Collectors.toList());

        List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = new ArrayList<StudentPaymentOrderDetail>();
        if (orderIdList != null && orderIdList.size() > 0) {
            studentPaymentOrderDetailList = studentPaymentOrderDetailService.getOrderDetail(orderIdList);
        }

        SubjectChange studentLastChange = subjectChangeDao.getStudentLastChange(studentId, musicGroupId);

        if (studentLastChange != null) {
            Iterator<StudentPaymentOrderDetail> iterator = studentPaymentOrderDetailList.iterator();
            StudentPaymentOrderDetail spod = null;
            while (iterator.hasNext()) {
                spod = iterator.next();
                if ((spod.getType() == OrderDetailTypeEnum.ACCESSORIES || spod.getType() == OrderDetailTypeEnum.MUSICAL) && (studentLastChange.getOriginalOrderId() != null && spod.getPaymentOrderId() <= studentLastChange.getOriginalOrderId())) {
                    iterator.remove();
                }
            }

            if (StringUtils.isNoneBlank(studentLastChange.getChangeAccessories())) {
                StudentPaymentOrderDetail detail = new StudentPaymentOrderDetail();
                detail.setGoodsIdList(studentLastChange.getChangeAccessories());
                List<Goods> goods = goodsDao.findGoodsByIds(detail.getGoodsIdList());
                if (goods != null && goods.size() > 0) {
                    detail.setName(goods.stream().map(t -> t.getName()).collect(Collectors.joining(",")));
                }
                if (studentLastChange.getOriginalOrderId() != null) {
                    detail.setPaymentOrderId((long) studentLastChange.getOriginalOrderId());
                }
                detail.setPrice(studentLastChange.getChangeAccessoriesPrice());
                detail.setType(OrderDetailTypeEnum.ACCESSORIES);
                detail.setCreateTime(studentLastChange.getCreateTime());

                studentPaymentOrderDetailList.add(detail);
            }
            if (studentLastChange.getChangeMusical() != null) {
                StudentPaymentOrderDetail detail = new StudentPaymentOrderDetail();
                detail.setGoodsIdList(studentLastChange.getChangeMusical() + "");
                List<Goods> goods = goodsDao.findGoodsByIds(detail.getGoodsIdList());
                if (goods != null && goods.size() > 0) {
                    detail.setName(goods.stream().map(t -> t.getName()).collect(Collectors.joining(",")));
                }
                if (studentLastChange.getOriginalOrderId() != null) {
                    detail.setPaymentOrderId((long) studentLastChange.getOriginalOrderId());
                }
                detail.setPrice(studentLastChange.getChangeMusicalPrice());
                detail.setType(OrderDetailTypeEnum.MUSICAL);
                detail.setCreateTime(studentLastChange.getCreateTime());

                studentPaymentOrderDetailList.add(detail);
            }
        }

        return studentPaymentOrderDetailList;
    }

    @Override
    public Map<String, BigDecimal> queryRefundsDetail(Integer studentId, String musicGroupId) {

        List<StudentPaymentOrderDetail> detailList = queryFeeDetail(studentId, musicGroupId);

        Map<OrderDetailTypeEnum, List<StudentPaymentOrderDetail>> detailMap = detailList.stream().collect(
                Collectors.groupingBy(StudentPaymentOrderDetail::getType));

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

        if (detailMap.containsKey(OrderDetailTypeEnum.MUSICAL)) {
            detailList = detailMap.get(OrderDetailTypeEnum.MUSICAL);
            if (detailList == null) {
                detailList = new ArrayList<StudentPaymentOrderDetail>();
            }
            BigDecimal reduce = detailList.stream().map(StudentPaymentOrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

            map.put(OrderDetailTypeEnum.MUSICAL.getCode(), sysUserCashAccountLogService.musicReturnFeeCharges(reduce, 0));
        } else {
            map.put(OrderDetailTypeEnum.MUSICAL.getCode(), BigDecimal.ZERO);
        }

        if (detailMap.containsKey(MAINTENANCE)) {

            BigDecimal totalAmount = BigDecimal.ZERO;

            Date date = new Date();

            // 查询当前乐团报名订单中购买了乐保的订单
            List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = studentPaymentOrderDetailDao.findUserApplyOrder(studentId, musicGroupId,
                    DealStatusEnum.SUCCESS);

            if (studentPaymentOrderDetailList != null && studentPaymentOrderDetailList.size() > 0) {

                Map<Long, StudentPaymentOrderDetail> maintenanceMap = studentPaymentOrderDetailList.stream()
                        .filter(t -> (t.getType() == MAINTENANCE))
                        .collect(Collectors.toMap(t -> t.getStudentInstrumentId(), StudentPaymentOrderDetail -> StudentPaymentOrderDetail));

                List<Long> instrumentIdList = new ArrayList<Long>(maintenanceMap.keySet());
                if (instrumentIdList != null && instrumentIdList.size() > 0) {
                    List<StudentInstrument> studentInstrumentList = studentInstrumentDao.queryById(instrumentIdList);

                    for (StudentInstrument si : studentInstrumentList) {
                        if (si.getDelFlag() == 1) {
                            continue;
                        }

                        if ((si.getStatus() == 0 && si.getStartTime() == null) || si.getEndTime().after(date)) {
                            totalAmount = totalAmount.add(maintenanceMap.get(si.getId()).getPrice());
                        }
                    }
                }
            }
            map.put(MAINTENANCE.getCode(), sysUserCashAccountLogService.musicReturnFeeCharges(totalAmount, 0));
        } else {
            map.put(MAINTENANCE.getCode(), BigDecimal.ZERO);
        }

        if (detailMap.containsKey(OrderDetailTypeEnum.ACCESSORIES)) {
            detailList = detailMap.get(OrderDetailTypeEnum.ACCESSORIES);
            if (detailList == null) {
                detailList = new ArrayList<StudentPaymentOrderDetail>();
            }
            BigDecimal reduce = detailList.stream().map(StudentPaymentOrderDetail::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
            map.put(OrderDetailTypeEnum.ACCESSORIES.getCode(), sysUserCashAccountLogService.musicReturnFeeCharges(reduce, 0));
        } else {
            map.put(OrderDetailTypeEnum.ACCESSORIES.getCode(), BigDecimal.ZERO);
        }

        StudentRegistration studentRegistration = studentRegistrationDao.getStudentRegister(musicGroupId, studentId);
        if (studentRegistration == null) {
            throw new BizException("学生报名信息查询失败");
        }
        //未上课*0995手续费、以上课*0.8
        List<StudentCourseInfoDto> history = courseScheduleDao.findUserCourseInfos(GroupType.MUSIC, musicGroupId, studentId, "history");
        map.put(OrderDetailTypeEnum.COURSE.getCode(), sysUserCashAccountLogService.musicReturnFeeCharges(studentRegistration.getSurplusCourseFee(), history.size()));
        return map;
    }

    @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
    @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 (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());
        student.setSubjectIdList(studentRegistration.getSubjectId() + "");
        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());
        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,
                                        StudentPaymentOrder studentPaymentOrder,
                                        MusicGroupApplyGoodsDto goodsDto,
                                        RegisterPayDto registerPayDto,
                                        CouponPayParam couponPayParam) throws Exception {
    	
        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
        
        if(musicGroup == null){
        	throw new BizException("乐团[{}]信息查询失败", studentRegistration.getMusicGroupId());
        }
        
        boolean isGiveAccessories = musicGroup.getIsGiveAccessories() == null ? false : musicGroup.getIsGiveAccessories();
        
        Date date = new Date();
        List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = new ArrayList<>();
        //乐器及打包辅件
        String maintenanceGoodsId = "";
        List<MusicGroupSubjectGoodsGroup> goodsGroups = goodsDto.getGoodsGroups();
        List<MusicGroupPaymentCalenderCourseSettings> newCourses = goodsDto.getNewCourses();
        BigDecimal remitFee = goodsDto.getRemitFee();
        if (CollectionUtils.isNotEmpty(goodsGroups)) {
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                StudentPaymentOrderDetail studentPaymentOrderDetail4goodsGroup = new StudentPaymentOrderDetail();
                studentPaymentOrderDetail4goodsGroup.setRemitFee(BigDecimal.ZERO);
                OrderDetailTypeEnum type = null;
                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    type = OrderDetailTypeEnum.MUSICAL;//todo  乐器
                    goodsGroup.setPrice(goodsGroup.getPrice().subtract(remitFee));
                    studentPaymentOrderDetail4goodsGroup.setRemitFee(remitFee);
                } else if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                    type = OrderDetailTypeEnum.ACCESSORIES;//todo 辅件
                } else if (goodsGroup.getType().equals(GoodsType.OTHER)) {
                    type = OrderDetailTypeEnum.TEACHING;//todo 教谱
                }
                studentPaymentOrderDetail4goodsGroup.setType(type);

                BigDecimal goodsPrice = new BigDecimal(0);
                
				if (!(type == OrderDetailTypeEnum.ACCESSORIES && (isGiveAccessories && registerPayDto.getBuyCloudTeacher()))) {

	                if (studentRegistration.getOrganId() == 55 && (newCourses == null || newCourses.size() == 0) && !registerPayDto.getBuyCloudTeacher()) {
	                    //取商品零售价
	                    if (StringUtils.isNotBlank(goodsGroup.getGoodsIdList())) {
	                        List<Goods> goodsList = goodsDao.findGoodsByIds(goodsGroup.getGoodsIdList());
	                        for (Goods goods : goodsList) {
	                            goodsPrice = goodsPrice.add(goods.getDiscountPrice());
	                        }
	                    }
	                } else {
	                    goodsPrice = goodsGroup.getPrice();
	                }
				}
                studentPaymentOrderDetail4goodsGroup.setPrice(goodsPrice);
                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();
                }
            }
        }

        //新的课程形态  todo  合奏课  单技课
        if (CollectionUtils.isNotEmpty(newCourses)) {
            BigDecimal courseRemitFee = goodsDto.getCourseRemitFee();
            for (MusicGroupPaymentCalenderCourseSettings newCourse : newCourses) {
                StudentPaymentOrderDetail studentPaymentOrderDetailCourse = new StudentPaymentOrderDetail();
                studentPaymentOrderDetailCourse.setType(OrderDetailTypeEnum.valueOf(newCourse.getCourseType().getCode()));
                if (courseRemitFee.compareTo(BigDecimal.ZERO) > 0) {
                    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);
            }
        }

        //合班缴费
        List<MusicGroupPaymentCalenderStudentDetail> studentDetails = musicGroupPaymentCalenderStudentDetailDao.findByBatchNoAndUserId(registerPayDto.getBatchNo(), studentPaymentOrder.getUserId());
        if (CollectionUtils.isNotEmpty(studentDetails)) {
            for (MusicGroupPaymentCalenderStudentDetail studentDetail : studentDetails) {
                StudentPaymentOrderDetail studentPaymentOrderDetail = new StudentPaymentOrderDetail();
                studentPaymentOrderDetail.setType(OrderDetailTypeEnum.valueOf(studentDetail.getCourseType()));
                studentPaymentOrderDetail.setPrice(studentDetail.getCourseCurrentPrice());
                studentPaymentOrderDetail.setCreateTime(date);
                studentPaymentOrderDetail.setUpdateTime(date);
                studentPaymentOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
                studentPaymentOrderDetailList.add(studentPaymentOrderDetail);
            }
        }

        //乐保 todo  乐保
        if (registerPayDto.getBuyMaintenance()) {
            if (StringUtils.isEmpty(maintenanceGoodsId)) {
                throw new BizException("有乐器才能购买乐保，请核查");
            }
            MusicGroupPaymentCalenderRepair calenderRepair = musicGroupPaymentCalenderRepairService.findByCalenderId(studentPaymentOrder.getCalenderId());
            StudentPaymentOrderDetail maintenanceOrderDetail = new StudentPaymentOrderDetail();
            maintenanceOrderDetail.setType(MAINTENANCE);
            maintenanceOrderDetail.setPrice(calenderRepair.getActualAmount());
            maintenanceOrderDetail.setRemitFee(BigDecimal.ZERO);
            maintenanceOrderDetail.setCreateTime(date);
            maintenanceOrderDetail.setUpdateTime(date);
            maintenanceOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            maintenanceOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(maintenanceOrderDetail);
        }

        //活动 todo  VIP 或 网管课
        List<Long> buyCalenderActivityId = registerPayDto.getBuyCalenderActivityId();
        if (CollectionUtils.isNotEmpty(buyCalenderActivityId)) {
            List<MusicGroupPaymentCalenderActivity> calenderActivities = musicGroupPaymentCalenderActivityService.findByIds(buyCalenderActivityId);
            for (MusicGroupPaymentCalenderActivity calenderActivity : calenderActivities) {
                StudentPaymentOrderDetail maintenanceOrderDetail = new StudentPaymentOrderDetail();
                maintenanceOrderDetail.setType("网管课".equals(calenderActivity.getCategoryName()) ? PRACTICE : VIP);
                maintenanceOrderDetail.setPrice(calenderActivity.getActualAmount());
                maintenanceOrderDetail.setRemitFee(BigDecimal.ZERO);
                maintenanceOrderDetail.setCreateTime(date);
                maintenanceOrderDetail.setUpdateTime(date);
                maintenanceOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
                maintenanceOrderDetail.setIsRenew(0);
                //保存的是活动编号
                maintenanceOrderDetail.setStudentInstrumentId(calenderActivity.getActivityId().longValue());
                studentPaymentOrderDetailList.add(maintenanceOrderDetail);
            }
        }

        //云教练/云教练+  todo  团练宝
        if (registerPayDto.getBuyCloudTeacher()) {
            MusicGroupPaymentCalenderMember calenderMember = musicGroupPaymentCalenderMemberService.findByCalenderId(studentPaymentOrder.getCalenderId());
            StudentPaymentOrderDetail cloudTeacherOrderDetail = new StudentPaymentOrderDetail();
            cloudTeacherOrderDetail.setType(OrderDetailTypeEnum.CLOUD_TEACHER);
            cloudTeacherOrderDetail.setPrice(calenderMember.getActualAmount());
            cloudTeacherOrderDetail.setRemitFee(BigDecimal.ZERO);
            cloudTeacherOrderDetail.setCreateTime(date);
            cloudTeacherOrderDetail.setUpdateTime(date);
            cloudTeacherOrderDetail.setPaymentOrderId(studentPaymentOrder.getId());
            cloudTeacherOrderDetail.setIsRenew(0);
            studentPaymentOrderDetailList.add(cloudTeacherOrderDetail);
        }

        //开始计算商品的优惠券
        if (Objects.nonNull(couponPayParam) && Objects.nonNull(couponPayParam.getCouponTypeInfo())) {
            //如果买乐器送课,那么就是0元买课，那么就先剔除送的课程再算优惠券，但是写入数据流水要加上
            List<StudentPaymentOrderDetail> collect = new ArrayList<>();
            //按OrderDetailTypeEnum类型 进行聚合分组
            Map<OrderDetailTypeEnum, List<StudentPaymentOrderDetail>> orderDetailGroupList;
            BigDecimal freeNewCourse = BigDecimal.ZERO;
            //如果送课 并且 课程不为空,那么就是0元买课
            if (goodsDto.isRemitCourseRFeeFlag() && CollectionUtils.isNotEmpty(newCourses)) {
                List<String> newCourseType = newCourses.stream().map(a -> a.getCourseType().getCode()).collect(Collectors.toList());
                //获取剔除送的课程的订单明细
                collect = studentPaymentOrderDetailList.stream()
                        .filter(a -> !newCourseType.contains(a.getType().getCode()))
                        .collect(Collectors.toList());
                //得到送课的减免的总额
                freeNewCourse = studentPaymentOrderDetailList.stream()
                        .filter(a -> newCourseType.contains(a.getType().getCode()))
                        .map(StudentPaymentOrderDetail::getRemitFee)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                orderDetailGroupList =
                        WrapperUtil.groupList(collect, StudentPaymentOrderDetail::getType);
            } else {
                orderDetailGroupList =
                        WrapperUtil.groupList(studentPaymentOrderDetailList, StudentPaymentOrderDetail::getType);
            }

            //获取本次交易中各优惠券的使用信息
            Map<String, CouponPayTypeInfo> couponParam = couponPayParam.getCouponTypeInfo();
            //计算使用优惠券后的对应的商品应该均摊的金额
            calculateCoupon(couponParam, orderDetailGroupList);
            //获取使用了优惠券之后的总金额
            BigDecimal useCouponAmount = WrapperUtil.sumList(studentPaymentOrderDetailList, StudentPaymentOrderDetail::getRemitFee);
            //赋值
            if (Objects.isNull(studentPaymentOrder.getRemitFee())) {
                studentPaymentOrder.setRemitFee(freeNewCourse);
            } else {
                studentPaymentOrder.setRemitFee(studentPaymentOrder.getRemitFee().add(freeNewCourse));
            }
            //优惠券减免金额应该是要减去 送课金额
            studentPaymentOrder.setCouponRemitFee(useCouponAmount.subtract(freeNewCourse));
            //核销优惠券
            sysCouponCodeService.useCoupon(registerPayDto.getCouponIdList());
        }
        //添加订单明细
        studentPaymentOrderDetailService.batchAdd(studentPaymentOrderDetailList);

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

        MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(studentRegistration.getMusicGroupId(), studentRegistration.getActualSubjectId());

        if (studentRegistration.getMusicGroupStatus() != StudentMusicGroupStatusEnum.NORMAL) {
            // 判断之前是否已有订单
            List<StudentPaymentOrder> oldStudentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC,
                    studentRegistration.getMusicGroupId(), studentRegistration.getUserId(), DealStatusEnum.SUCCESS, OrderTypeEnum.APPLY);

            int paidNum = musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum();
            int paidZeroNum = musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum();
            if ((musicGroup.getCourseViewType().equals(CourseViewTypeEnum.MEMBER_FEE) && !registerPayDto.getBuyCloudTeacher() && StringUtils.isBlank(maintenanceGoodsId))) {
                if (studentRegistration.getPaymentStatus() != YES) {
                    paidZeroFlag = true;
                }
                if (studentRegistration.getNoneNeedCloudTeacher().equals(1) && (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0)) {
                    musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
                    musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
                }
            } else {
                if (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0) {
                    musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
                }
            }
            if (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);
            studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);
        }
        return studentPaymentOrder;
    }

    /**
     * 计算使用优惠券后的每个明细均摊的金额
     *
     * @param couponParam          优惠券的信息
     * @param orderDetailGroupList 订单信息
     */
    private void calculateCoupon(Map<String, CouponPayTypeInfo> couponParam,
                                 Map<OrderDetailTypeEnum, List<StudentPaymentOrderDetail>> orderDetailGroupList) {
        List<StudentPaymentOrderDetail> singleTypeList = new ArrayList<>();
        List<StudentPaymentOrderDetail> allTypeList = new ArrayList<>();
        //先处理”非全类型券“的数据
        orderDetailGroupList.forEach((e, list) -> {
            //根据OrderDetailTypeEnum类型找到对应的券类型，默认全类型
            String couponDetailCode = CouponDetailTypeEnum.of(e.getCode());
            //获取本次支付中该类型优惠券的详情，如果该商品没有找到本次支付时选择的优惠券则当作全类型
            CouponPayTypeInfo couponPayTypeInfo = couponParam.get(couponDetailCode);
            //全类型券数据后面处理
            if (Objects.isNull(couponPayTypeInfo) || couponDetailCode.equals(CouponDetailTypeEnum.FULLCOUPON.getCode())) {
                allTypeList.addAll(list);
                return;
            }
            analyzeAmount(couponPayTypeInfo, singleTypeList, list);
        });
        List<StudentPaymentOrderDetail> allList = new ArrayList<>();
        allTypeList.addAll(singleTypeList);
        //有全类型优惠券就再处理全类型优惠券数据
        if (Objects.nonNull(couponParam.get(CouponDetailTypeEnum.FULLCOUPON.getCode()))) {
            analyzeAmount(couponParam.get(CouponDetailTypeEnum.FULLCOUPON.getCode()), allList, allTypeList);
        } else {
            allList.addAll(allTypeList);
        }
    }

    /**
     * 计算分配优惠券金额
     */
    private void analyzeAmount(CouponPayTypeInfo couponPayTypeInfo, List<StudentPaymentOrderDetail> resultList,
                               List<StudentPaymentOrderDetail> list) {
        //获取该优惠券对应的商品的总金额
        BigDecimal totalAmount = WrapperUtil.sumList(list, StudentPaymentOrderDetail::getPrice);
        //校验本次优惠券的 ”满额“ 是否大于 该类型的总金额
        if (couponPayTypeInfo.getCouponAmount().compareTo(totalAmount) <= 0) {
            List<StudentPaymentOrderDetail> details = studentPaymentOrderDetailService.allocateAmount(list, couponPayTypeInfo.getFaceValue());
            resultList.addAll(details);
        } else {
            throw new BizException("交易失败，请重新选择优惠券！");
        }
    }

    @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("参数校验失败");
        }
        Date date = new Date();
        String musicGroupId = studentRegistration.getMusicGroupId();
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);

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

        SysUser sysUser = studentRegistrationDao.getSysUserByPhone(studentRegistration.getParentsPhone());
        StudentRegistration phoneAndMusicGroupId = null;
        if (sysUser != null) {
            if (!musicGroup.getTenantId().equals(sysUser.getTenantId())) {
                throw new BizException("该手机号已注册");
            }
            phoneAndMusicGroupId = studentRegistrationDao.getByUserIdAndMusicGroupId(musicGroupId, sysUser.getId());
        } else {
            phoneAndMusicGroupId = studentRegistrationDao.getByPhoneAndMusicGroupId(musicGroupId, studentRegistration.getParentsPhone());
        }

        if (phoneAndMusicGroupId != null && phoneAndMusicGroupId.getMusicGroupStatus() != StudentMusicGroupStatusEnum.QUIT && phoneAndMusicGroupId.getMusicGroupStatus() != StudentMusicGroupStatusEnum.APPLY) {
            throw new BizException("该学员已存在");
        }

        Integer userId;
        if (sysUser == null) {
            //新增user
            sysUser = new SysUser();
            sysUser.setPhone(studentRegistration.getParentsPhone());
            int phoneStrLen = sysUser.getPhone().length();
            sysUser.setPassword(new BCryptPasswordEncoder().encode("gym" + sysUser.getPhone().substring(phoneStrLen - 4, phoneStrLen)));
//            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 (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 {
                student.setSubjectIdList(studentRegistration.getSubjectId().toString());
                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());
        studentRegistration.setMusicGroupPaymentCalenderId(null);

        //增加报名学生数
        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);

        //当前学员是否以前存在过当前乐团
        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()));

        //学生报名表
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                null, musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_ADD_STUDENT, musicGroup.getName(), studentRegistration.getName());
        return userId;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void insertStudent(String studentIds, String oldMusicGroupId, String newMusicGroupId,
                              Map<Integer, List<MusicGroupPaymentCalenderStudentDetail>> collect,String batchNo) {
        //获取欠费学员列表
        List<Integer> studentIdList = Arrays.asList(studentIds.split(",")).stream().mapToInt(idStr -> Integer.valueOf(idStr)).boxed().collect(Collectors.toList());
        List<Integer> noPaymentUserIds = musicGroupPaymentCalenderDetailDao.queryNoPaymentUserIds(newMusicGroupId, studentIdList,batchNo);
        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);
            }
            //用户是否在主乐团
            StudentRegistration registration = studentRegistrationDao.getStudentRegister(newMusicGroupId, studentRegistration.getUserId());
            if (registration != null) {
                //修改剩余课程余额
                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);
                }
            }
            //主班新增余额日志
            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.toString(), 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("订单更新失败");
        }
        Integer tenantId = studentPaymentOrder.getTenantId();
        Date nowDate = new Date();

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

        if (studentPaymentOrder.getStatus().equals(DealStatusEnum.SUCCESS)) {
            MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
            //支付成功后处理课程、云教练、活动等数据
            studentPaymentOrderDetailService.addOrderDetailTo(studentPaymentOrder, musicGroup, studentRegistration);

            //插入交易明细
            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());
            rechargeDetail.setTenantId(tenantId);
            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());
            }
            paymentDetail.setTenantId(tenantId);
            sysUserCashAccountDetailService.insert(paymentDetail);

            //合并学员处理
            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);
            studentRegistrationDao.update(studentRegistration);
            //减去缴费人数（器乐收费，0元时不减缴费人数）
            studentPaymentOrderService.cutSubjectPlan(studentPaymentOrder);
            
            //增加商品库存
            List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = studentPaymentOrderDetailService.queryOrderDetail(studentPaymentOrder.getId());
            String goodsIds = studentPaymentOrderDetailList.stream().filter(t -> StringUtils.isNotBlank(t.getMinuendStockGoodsIdList())).map(t -> t.getMinuendStockGoodsIdList()).collect(Collectors.joining(","));
            if(StringUtils.isNotBlank(goodsIds)){
            	GoodsProcurement goodsProcurement = null;
            	List<Goods> goodsList = goodsService.getGoodsWithLocked(goodsIds);
            	Map<Integer,Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods :: getId, t -> t));
            	Goods goods = null;
    			Map<Integer, Goods> batchUpdateGoodsMap = new HashMap<Integer, Goods>();
    			Map<Long, GoodsProcurement> goodsProcurementMap = new HashMap<Long, GoodsProcurement>();
            	
            	for(String goodsIdStr : goodsIds.split(",")){
            		if(StringUtils.isBlank(goodsIdStr)){
						continue;
					}
					goods = goodsMap.get(Integer.parseInt(goodsIdStr));
					if(batchUpdateGoodsMap.get(goods.getId()) != null){
						goods = batchUpdateGoodsMap.get(goods.getId());
					}
					goods.setStockCount(new AtomicInteger(goods.getStockCount()).incrementAndGet());
					goods.setSellCount(new AtomicInteger(goods.getSellCount()).decrementAndGet());
					goods.setUpdateTime(nowDate);
					
					batchUpdateGoodsMap.put(goods.getId(), goods);
					
					// 进货清单
					goodsProcurement = goodsProcurementDao.getWithStockSurplusProcurement(goods.getId());
					if(goodsProcurement != null){
						if(goodsProcurementMap.get(goodsProcurement.getId()) != null){
							goodsProcurement = goodsProcurementMap.get(goodsProcurement.getId());
						}
						goodsProcurement.setStockSoldNum(new AtomicInteger(goodsProcurement.getStockSoldNum()).decrementAndGet());
						goodsProcurement.setUpdateTime(nowDate);
						goodsProcurementMap.put(goodsProcurement.getId(), goodsProcurement);
					}
					
            	}
            	
            	if(goodsProcurementMap.size() > 0){
            		goodsProcurementDao.batchUpdate(new ArrayList<GoodsProcurement>(goodsProcurementMap.values()));
            	}
                
                if(batchUpdateGoodsMap.size() > 0){
                	goodsService.batchUpdate(new ArrayList<Goods>(batchUpdateGoodsMap.values()));
                }
            }

            //退还优惠券和余额
            studentPaymentOrderService.returnBalanceAndCoupon(studentPaymentOrder,"报名缴费失败");
            //三方乐团不发送缴费通知
            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));
            }
        }
        return studentPaymentOrder;
    }

    @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 int batchInsert(List<StudentRegistration> studentRegistrationList) {
        return studentRegistrationDao.batchInsert(studentRegistrationList);
    }

    @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.SMS_PAYMENT_MESSAGE, receivers, null, 0, null, "",
                        musicGroup.getName(), HttpUtil.getSortUrl(configValue + musicGroup.getId()));
            }
        }
        return studentRegistrationDao.batchOpenPay(ids, PaymentStatusEnum.OPEN);
    }

    @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())) {
                    if(Objects.equals(classGroupId,classGroupStudentMapper.getClassGroupId()) || type != ClassGroupTypeEnum.HIGH_ONLINE){
                        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 originalZeroPaidNum = originalSubjectPlan.getPaidZeroNum() == null ? 0 : originalSubjectPlan.getPaidZeroNum();
            int originalPaidCount = 1;
            if (originalPaidNum > 0) {
                originalSubjectPlan.setPaidStudentNum(originalPaidNum - 1);
                //是否是0元入团
                if (studentRegistration.getNoneNeedCloudTeacher() != null && studentRegistration.getNoneNeedCloudTeacher() == 1) {
                    originalSubjectPlan.setPaidZeroNum(originalZeroPaidNum - 1);
                }
                originalPaidCount = musicGroupSubjectPlanService.update(originalSubjectPlan);
            }
            MusicGroupSubjectPlan changeSubjectPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, changeSubjectId);
            int changelPaidNum = changeSubjectPlan.getPaidStudentNum() == null ? 0 : changeSubjectPlan.getPaidStudentNum();
            changeSubjectPlan.setPaidStudentNum(changelPaidNum + 1);
            if (studentRegistration.getNoneNeedCloudTeacher() != null && studentRegistration.getNoneNeedCloudTeacher() == 1) {
                if (changeSubjectPlan.getPaidZeroNum() != null && changeSubjectPlan.getPaidZeroNum() > 0) {
                    throw new BizException("声部更换失败，当前用户是0元入团，且当前声部已有0元入团学生");
                }
                changeSubjectPlan.setPaidZeroNum(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)
    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, String musicGroupId) {
        return studentRegistrationDao.queryStudentMusicGroupInfo(userId, musicGroupId);
    }

    @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);
            }
        });
        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);
        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);
            if(totalPayNum == 0){
                pageInfo.setPayScale(new BigDecimal(0));
            }else {
                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
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult<Boolean> addPaidNum(Long id, boolean isContinue) {
        StudentRegistration studentRegistration = studentRegistrationDao.lock(id);
        if (!studentRegistration.getPayingStatus().equals(2)) {
            throw new BizException("该学生不在审核");
        }
        if (studentRegistration.getNoneNeedCloudTeacher().equals(1)) {
            throw new BizException("该学生已设置");
        }
        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        if (musicGroup.getTenantId() == null) {
            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();
        String configValue = sysTenantConfigService.getTenantConfigValue(SysConfigService.MEMBER_GROUP_FEE_STUDENT_NUM, musicGroup.getTenantId());
        if (StringUtils.isNotEmpty(configValue)) {
            if (paidZeroNum >= Integer.parseInt(configValue)) {
                throw new BizException("每个声部只能有{}个免费入团名额", configValue);
            }
        }
        if (!isContinue) {
            if (musicOneSubjectClassPlan.getPaidStudentNum() >= musicOneSubjectClassPlan.getExpectedStudentNum()) {
                return new HttpResponseResult<Boolean>(true, HttpStatus.CONTINUE, null, "乐团该声部招生人数已满，是否继续操作？");
            }
        }

        studentRegistration.setPayingStatus(0);
        studentRegistration.setNoneNeedCloudTeacher(1);
        studentRegistration.setPaymentStatus(YES);
        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
        studentRegistrationDao.update(studentRegistration);

        List<StudentPaymentOrder> studentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC, studentRegistration.getMusicGroupId(), studentRegistration.getUserId(), DealStatusEnum.ING, OrderTypeEnum.APPLY);

        List<StudentPaymentOrder> updateList = new ArrayList<StudentPaymentOrder>();

        if (studentPaymentOrderList != null && studentPaymentOrderList.size() > 0) {
            for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList) {
                if (StringUtils.equals("205", studentPaymentOrder.getPaymentAccountNo())) {
                    studentPaymentOrder.setStatus(DealStatusEnum.CLOSE);
                    studentPaymentOrder.setMemo("用户未支付");
                    updateList.add(studentPaymentOrder);
                    studentPaymentOrderService.quitCouponAndBalance(studentPaymentOrder);
                }
            }
        }

        if (updateList.size() > 0) {
            studentPaymentOrderService.batchUpdate(updateList);
        }

        musicOneSubjectClassPlan.setPaidZeroNum(paidZeroNum + 1);
        musicOneSubjectClassPlan.setPaidStudentNum(paidNum + 1);
        int count = musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
        if (count <= 0) {
            throw new BizException("缴费人数更新失败，请重试");
        }
        return new HttpResponseResult<Boolean>(true, HttpStatus.OK, null, null);
    }

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setCloudTeacherToFailed(StudentRegistration studentRegistration) {

        if (studentRegistration.getPayingStatus() != 2) {
            throw new BizException("只有'审核中'的记录才能取消审核");
        }

        Date date = new Date();

        studentRegistration.setPayingStatus(0);
        studentRegistration.setUpdateTime(date);
        update(studentRegistration);

        List<StudentPaymentOrder> studentPaymentOrderList = studentPaymentOrderService.queryByCondition(GroupType.MUSIC, studentRegistration.getMusicGroupId(), studentRegistration.getUserId(), DealStatusEnum.ING, OrderTypeEnum.APPLY);

        List<StudentPaymentOrder> updateList = new ArrayList<StudentPaymentOrder>();

        if (studentPaymentOrderList != null && studentPaymentOrderList.size() > 0) {
            for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList) {
                if (StringUtils.equals("205", studentPaymentOrder.getPaymentAccountNo())) {
                    studentPaymentOrder.setStatus(DealStatusEnum.CLOSE);
                    studentPaymentOrder.setMemo("云教练审核拒绝");
                    updateList.add(studentPaymentOrder);
                    studentPaymentOrderService.quitCouponAndBalance(studentPaymentOrder);
                }
            }
        }

        if (updateList.size() > 0) {
            studentPaymentOrderService.batchUpdate(updateList);
        }

        return true;
    }

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

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

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

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