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

import static com.ym.mec.biz.dal.entity.ApprovalStatus.PROCESSING;
import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED;
import static com.ym.mec.biz.dal.enums.DealStatusEnum.ING;
import static com.ym.mec.biz.dal.enums.DealStatusEnum.SUCCESS;
import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.ACCESSORIES;
import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.MAINTENANCE;
import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.MUSICAL;
import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.TEACHING;
import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;
import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.thirdparty.yqpay.DateUtils;
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.context.annotation.Lazy;
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 com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.ChargeTypeDao;
import com.ym.mec.biz.dal.dao.ClassGroupDao;
import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
import com.ym.mec.biz.dal.dao.ClassGroupTeacherMapperDao;
import com.ym.mec.biz.dal.dao.CooperationOrganDao;
import com.ym.mec.biz.dal.dao.CourseScheduleDao;
import com.ym.mec.biz.dal.dao.CourseScheduleTeacherSalaryDao;
import com.ym.mec.biz.dal.dao.GoodsDao;
import com.ym.mec.biz.dal.dao.MusicGroupBuildLogDao;
import com.ym.mec.biz.dal.dao.MusicGroupDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderCourseSettingsDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderStudentDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentEntitiesDao;
import com.ym.mec.biz.dal.dao.MusicGroupPaymentStudentCourseDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupPurchaseListDao;
import com.ym.mec.biz.dal.dao.MusicGroupQuitDao;
import com.ym.mec.biz.dal.dao.MusicGroupSchoolTermCourseDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupSchoolTermStudentCourseDetailDao;
import com.ym.mec.biz.dal.dao.MusicGroupStudentFeeDao;
import com.ym.mec.biz.dal.dao.MusicGroupSubjectGoodsGroupDao;
import com.ym.mec.biz.dal.dao.MusicGroupSubjectPlanDao;
import com.ym.mec.biz.dal.dao.OrganizationDao;
import com.ym.mec.biz.dal.dao.SchoolDao;
import com.ym.mec.biz.dal.dao.SporadicChargeInfoDao;
import com.ym.mec.biz.dal.dao.StudentDao;
import com.ym.mec.biz.dal.dao.StudentInstrumentDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDao;
import com.ym.mec.biz.dal.dao.StudentPaymentOrderDetailDao;
import com.ym.mec.biz.dal.dao.StudentPreRegistrationDao;
import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
import com.ym.mec.biz.dal.dao.StudentVisitDao;
import com.ym.mec.biz.dal.dao.SubjectChangeDao;
import com.ym.mec.biz.dal.dao.SubjectDao;
import com.ym.mec.biz.dal.dao.SysConfigDao;
import com.ym.mec.biz.dal.dao.SysUserCashAccountDao;
import com.ym.mec.biz.dal.dao.SysUserCashAccountLogDao;
import com.ym.mec.biz.dal.dao.TeacherAttendanceDao;
import com.ym.mec.biz.dal.dao.TeacherDao;
import com.ym.mec.biz.dal.entity.ApprovalStatus;
import com.ym.mec.biz.dal.entity.ChargeType;
import com.ym.mec.biz.dal.entity.ClassGroup;
import com.ym.mec.biz.dal.entity.CooperationOrgan;
import com.ym.mec.biz.dal.entity.CouponPayParam;
import com.ym.mec.biz.dal.entity.CourseSchedule;
import com.ym.mec.biz.dal.entity.CourseScheduleTeacherSalary;
import com.ym.mec.biz.dal.entity.FinancialExpenditure;
import com.ym.mec.biz.dal.entity.Goods;
import com.ym.mec.biz.dal.entity.ImGroup;
import com.ym.mec.biz.dal.entity.MusicGroup;
import com.ym.mec.biz.dal.entity.MusicGroupBuildLog;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderCourseSettings;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderDetail;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderStudentDetail;
import com.ym.mec.biz.dal.entity.MusicGroupPurchaseList;
import com.ym.mec.biz.dal.entity.MusicGroupQuit;
import com.ym.mec.biz.dal.entity.MusicGroupReturnFeeDto;
import com.ym.mec.biz.dal.entity.MusicGroupSchoolTermCourseDetail;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee;
import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
import com.ym.mec.biz.dal.entity.MusicGroupPaymentStudentCourseDetail;
import com.ym.mec.biz.dal.entity.MusicGroupSubjectGoodsGroup;
import com.ym.mec.biz.dal.entity.MusicGroupSubjectPlan;
import com.ym.mec.biz.dal.entity.MusicMemberDto;
import com.ym.mec.biz.dal.entity.Organization;
import com.ym.mec.biz.dal.entity.School;
import com.ym.mec.biz.dal.entity.SporadicChargeInfo;
import com.ym.mec.biz.dal.entity.Student;
import com.ym.mec.biz.dal.entity.StudentInstrument;
import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
import com.ym.mec.biz.dal.entity.StudentPaymentOrderDetail;
import com.ym.mec.biz.dal.entity.StudentPreRegistration;
import com.ym.mec.biz.dal.entity.StudentRegistration;
import com.ym.mec.biz.dal.entity.Subject;
import com.ym.mec.biz.dal.entity.SubjectChange;
import com.ym.mec.biz.dal.entity.SysUserCashAccount;
import com.ym.mec.biz.dal.entity.SysUserCashAccountDetail;
import com.ym.mec.biz.dal.entity.SysUserCashAccountLog;
import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
import com.ym.mec.biz.dal.enums.CouponDetailTypeEnum;
import com.ym.mec.biz.dal.enums.CourseStatusEnum;
import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
import com.ym.mec.biz.dal.enums.DealStatusEnum;
import com.ym.mec.biz.dal.enums.FivePlusGradeEnum;
import com.ym.mec.biz.dal.enums.GoodsType;
import com.ym.mec.biz.dal.enums.GradeTypeEnum;
import com.ym.mec.biz.dal.enums.GroupType;
import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
import com.ym.mec.biz.dal.enums.OrderTypeEnum;
import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
import com.ym.mec.biz.dal.enums.ReturnFeeEnum;
import com.ym.mec.biz.dal.enums.SixPlusGradeEnum;
import com.ym.mec.biz.dal.enums.SporadicChargeTypeEnum;
import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
import com.ym.mec.biz.dal.enums.SysUserRoleEnum;
import com.ym.mec.biz.dal.enums.TeachTypeEnum;
import com.ym.mec.biz.dal.enums.YesOrNoEnum;
import com.ym.mec.biz.dal.page.MusicGroupQueryInfo;
import com.ym.mec.biz.dal.page.MusicMemberQueryInfo;
import com.ym.mec.biz.event.source.GroupEventSource;
import com.ym.mec.biz.event.source.SendSeoMessageSource;
import com.ym.mec.biz.service.ClassGroupService;
import com.ym.mec.biz.service.ClassGroupStudentMapperService;
import com.ym.mec.biz.service.ContractService;
import com.ym.mec.biz.service.CourseScheduleStudentPaymentService;
import com.ym.mec.biz.service.GoodsService;
import com.ym.mec.biz.service.ImGroupMemberService;
import com.ym.mec.biz.service.ImGroupService;
import com.ym.mec.biz.service.ImUserFriendService;
import com.ym.mec.biz.service.MusicGroupPaymentCalenderService;
import com.ym.mec.biz.service.MusicGroupService;
import com.ym.mec.biz.service.MusicGroupSubjectGoodsGroupService;
import com.ym.mec.biz.service.MusicGroupSubjectPlanService;
import com.ym.mec.biz.service.PayService;
import com.ym.mec.biz.service.StudentPaymentOrderDetailService;
import com.ym.mec.biz.service.StudentPaymentOrderService;
import com.ym.mec.biz.service.StudentPaymentRouteOrderService;
import com.ym.mec.biz.service.StudentRegistrationService;
import com.ym.mec.biz.service.StudentService;
import com.ym.mec.biz.service.SysConfigService;
import com.ym.mec.biz.service.SysCouponCodeService;
import com.ym.mec.biz.service.SysEmployeePositionService;
import com.ym.mec.biz.service.SysMessageService;
import com.ym.mec.biz.service.SysTenantConfigService;
import com.ym.mec.biz.service.SysUserCashAccountDetailService;
import com.ym.mec.biz.service.SysUserCashAccountService;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.entity.ImGroupMember;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext.MessageSender;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.http.HttpUtil;
import com.ym.mec.util.json.JsonUtil;
import com.ym.mec.util.validator.CommonValidator;

@Service
public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> implements MusicGroupService {

    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private ChargeTypeDao chargeTypeDao;
    @Autowired
    private TeacherDao teacherDao;
    @Autowired
    private StudentService studentService;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private SchoolDao schoolDao;
    @Autowired
    private MusicGroupPaymentCalenderDao musicGroupPaymentCalenderDao;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private MusicGroupPaymentEntitiesDao musicGroupPaymentEntitiesDao;
    @Autowired
    private MusicGroupSubjectGoodsGroupDao musicGroupSubjectGoodsGroupDao;
    @Autowired
    private MusicGroupSubjectPlanDao musicGroupSubjectPlanDao;
    @Autowired
    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
    @Autowired
    private MusicGroupBuildLogDao musicGroupBuildLogDao;
    @Autowired
    private MusicGroupPurchaseListDao musicGroupPurchaseListDao;
    @Autowired
    private MusicGroupStudentFeeDao musicGroupStudentFeeDao;
    @Autowired
    private ClassGroupStudentMapperDao classGroupStudentMapperDao;
    @Autowired
    private ClassGroupTeacherMapperDao classGroupTeacherMapperDao;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private MusicGroupPaymentCalenderStudentDetailDao musicGroupPaymentCalenderStudentDetailDao;
    @Autowired
    private MusicGroupQuitDao musicGroupQuitDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private ClassGroupDao classGroupDao;
    @Autowired
    private OrganizationDao organizationDao;
    @Autowired
    private CourseScheduleTeacherSalaryDao courseScheduleTeacherSalaryDao;
    @Autowired
    private CourseScheduleStudentPaymentService courseScheduleStudentPaymentService;
    @Autowired
    private CooperationOrganDao cooperationOrganDao;
    @Autowired
    private TeacherAttendanceDao teacherAttendanceDao;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;
    @Autowired
    private PayService payService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private SysTenantConfigService sysTenantConfigService;
    @Autowired
    private ClassGroupService classGroupService;
    @Autowired
    private StudentPaymentOrderDetailDao studentPaymentOrderDetailDao;
    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    private SporadicChargeInfoDao sporadicChargeInfoDao;
    @Autowired
    private MusicGroupSubjectGoodsGroupService musicGroupSubjectGoodsGroupService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ClassGroupStudentMapperService classGroupStudentMapperService;
    @Autowired
    private MusicGroupPaymentCalenderDetailDao musicGroupPaymentCalenderDetailDao;
    @Autowired
    private ImGroupMemberService imGroupMemberService;
    @Autowired
    private ImUserFriendService imUserFriendService;
    @Autowired
    private ImGroupService imGroupService;
    @Autowired
    private StudentPaymentRouteOrderService studentPaymentRouteOrderService;
    @Autowired
    private MusicGroupPaymentCalenderCourseSettingsDao musicGroupPaymentCalenderCourseSettingsDao;
    @Autowired
    private MusicGroupPaymentStudentCourseDetailDao musicGroupPaymentStudentCourseDetailDao;
    @Autowired
    private SubjectChangeDao subjectChangeDao;
    @Autowired
    private StudentVisitDao studentVisitDao;
    @Autowired
    private SubjectDao subjectDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    @Lazy
    private ContractService contractService;
    @Autowired
    private StudentPreRegistrationDao studentPreRegistrationDao;
    @Autowired
    private GroupEventSource groupEventSource;
    @Autowired
    private StudentInstrumentDao studentInstrumentDao;
    @Autowired
    private SysUserCashAccountLogDao sysUserCashAccountLogDao;
    @Autowired
    private MusicGroupSchoolTermCourseDetailDao musicGroupSchoolTermCourseDetailDao;
    @Autowired
    private MusicGroupSchoolTermStudentCourseDetailDao musicGroupSchoolTermStudentCourseDetailDao;
    @Autowired
    private SysCouponCodeService sysCouponCodeService;
    @Autowired
    private SendSeoMessageSource sendSeoMessageSource;
    @Autowired
    private SysEmployeePositionService employeePositionService;
    @Autowired
    private SysUserCashAccountDao sysUserCashAccountDao;
    @Autowired
    private StudentDao studentDao;

    private SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyy-MM-dd");

    private SimpleDateFormat sdf_hms = new SimpleDateFormat("HH:mm:ss");

    private SimpleDateFormat sdf_ymdhms = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    public BaseDAO<String, MusicGroup> getDAO() {
        return musicGroupDao;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
	public boolean importStudentToMusicGroup(String musicGroupId, Map<String, List<Map<String, Object>>> excelData) {

    	MusicGroup musicGroup = musicGroupDao.get(musicGroupId);

    	if(musicGroup == null){
    		throw new BizException("乐团[{}]信息查询失败", musicGroupId);
    	}

    	if(musicGroup.getStatus() != MusicGroupStatusEnum.PAY){
    		throw new BizException("只有[缴费中]状态的乐团才能导入数据");
    	}

    	Integer tenantId = musicGroup.getTenantId();

    	List<StudentImportDto> studentBasicList = new ArrayList<StudentImportDto>();
    	List<Map<String, Object>> sheet = null;
    	StudentImportDto dto = null;
    	for (String sheetName : excelData.keySet()) {
    		sheet = excelData.get(sheetName);
    		for(Map<String,Object> row : sheet){
        		dto = new StudentImportDto();
        		if(row.get("学生姓名") == null || StringUtils.isBlank(row.get("学生姓名").toString())){
        			throw new BizException("学生姓名不能为空");
        		}
        		dto.setName(row.get("学生姓名").toString());
        		if(!CommonValidator.isUserName(dto.getName())){
        			throw new BizException("学生姓名[{}]填写错误", dto.getName());
        		}

        		if(row.get("性别") == null || StringUtils.isBlank(row.get("性别").toString())){
        			throw new BizException("性别不能为空");
        		}
    			dto.setSex(row.get("性别").toString());

        		if(row.get("手机号码") == null || StringUtils.isBlank(row.get("手机号码").toString())){
        			throw new BizException("手机号码不能为空");
        		}
    			dto.setMobileNo(row.get("手机号码").toString());
        		if(!CommonValidator.isMobileNo(dto.getMobileNo())){
        			throw new BizException("手机号码[{}]填写错误", dto.getMobileNo());
        		}

        		if(row.get("学习声部") == null || StringUtils.isBlank(row.get("学习声部").toString())){
        			throw new BizException("学习声部不能为空");
        		}
    			dto.setSubjectName(row.get("学习声部").toString());

        		if(row.get("所在年级") == null || StringUtils.isBlank(row.get("所在年级").toString())){
        			throw new BizException("所在年级不能为空");
        		}
    			dto.setGradeName(row.get("所在年级").toString());

    			studentBasicList.add(dto);
    		}
    	}

    	Date nowDate = new Date();

    	//查询导入的声部是否正确
    	List<String> subjectNameList = studentBasicList.stream().distinct().map(t->t.getSubjectName()).collect(Collectors.toList());

    	List<MusicGroupSubjectPlan> musicGroupSubjectPlanList = musicGroupSubjectPlanDao.getMusicSubjectClassPlan(musicGroupId);

    	Map<String,Integer> subjectMap = musicGroupSubjectPlanList.stream().collect(Collectors.toMap(MusicGroupSubjectPlan :: getSubName, MusicGroupSubjectPlan :: getSubjectId));

    	List<String> allSubjectNameList = musicGroupSubjectPlanList.stream().map(t -> t.getSubName()).collect(Collectors.toList());

    	for(String subName : subjectNameList){
    		if(!allSubjectNameList.contains(subName)){
    			throw new BizException("当前乐团不支持[{}]声部", subName);
    		}
    	}

    	//查询课程费用是否是0
    	MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
    	if(musicGroupPaymentCalender == null){
    		throw new BizException("请先创建乐团报名缴费");
    	}

    	List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.queryCalenderCourseSettings(musicGroupPaymentCalender.getId());
    	double d = musicGroupPaymentCalenderCourseSettingsList.stream().mapToDouble(t -> t.getCourseCurrentPrice().doubleValue()).sum();

    	if(d > 0){
    		throw new BizException("缴费项目中的课程费用为[{}]元，不能导入", d);
    	}

    	//检查用户是否已入团或在其他机构已注册
    	for(StudentImportDto si : studentBasicList){
    		SysUser sysUser = studentRegistrationDao.getSysUserByPhone(si.getMobileNo());
            if (sysUser != null) {
            	throw new BizException("该手机号[{}]已注册", si.getMobileNo());
            }
    	}

    	SysUser sysUser = null;
    	Integer userId = null;
    	Student student = null;
    	StudentRegistration studentRegistration = null;
    	List<StudentRegistration> insertList = new ArrayList<StudentRegistration>();
		Organization organization = organizationDao.get(musicGroup.getOrganId());
    	//插入记录
		for (StudentImportDto si : studentBasicList) {
			sysUser = new SysUser();
			sysUser.setPhone(si.getMobileNo());
			int phoneStrLen = sysUser.getPhone().length();
			sysUser.setPassword(new BCryptPasswordEncoder().encode("gym" + sysUser.getPhone().substring(phoneStrLen - 4, phoneStrLen)));
			sysUser.setUsername(si.getName());
			sysUser.setGender(si.getSex().equals("男") ? 1 : 0);
			sysUser.setUserType("STUDENT");
			sysUser.setOrganId(musicGroup.getOrganId());
			sysUser.setCreateTime(nowDate);
			sysUser.setUpdateTime(nowDate);
			teacherDao.addSysUser(sysUser);
			userId = sysUser.getId();

			si.setUserId(userId);

			student = new Student(userId, subjectMap.get(si.getSubjectName()) + "");
	        student.setCurrentGradeNum(SixPlusGradeEnum.get(si.getGradeName()).getCode());
			studentDao.insert(student);
			// 添加用户现金账户
			sysUserCashAccountDao.insert(new SysUserCashAccount(userId, "CNY"));

			studentRegistration = new StudentRegistration();
	        String studentGrade = studentService.getStudentGrade(organization.getGradeType(), student.getCurrentGradeNum());
	        studentRegistration.setCurrentGrade(studentGrade);
	        studentRegistration.setActualSubjectId(subjectMap.get(si.getSubjectName()));
	        studentRegistration.setIsAllowAdjust(YesOrNoEnum.YES);
	        studentRegistration.setSubjectId(subjectMap.get(si.getSubjectName()));
	        studentRegistration.setUserId(userId);
	        studentRegistration.setParentsPhone(si.getMobileNo());
	        studentRegistration.setName(si.getName());
	        studentRegistration.setGender(sysUser.getGender());
	        studentRegistration.setPaymentStatus(PaymentStatusEnum.YES);
	        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
	        studentRegistration.setTemporaryCourseFee(BigDecimal.ZERO);
	        studentRegistration.setMusicGroupPaymentCalenderId(null);
	        studentRegistration.setTenantId(musicGroup.getTenantId());
	        studentRegistration.setMusicGroupId(musicGroupId);
	        studentRegistration.setCreateTime(nowDate);
	        studentRegistration.setUpdateTime(nowDate);

	        insertList.add(studentRegistration);
		}

		if (insertList.size() > 0) {
			studentRegistrationService.batchInsert(insertList);

			Map<Integer, Long> subjectCountMap = insertList.stream().collect(
					Collectors.groupingBy(StudentRegistration::getActualSubjectId, Collectors.counting()));

			MusicGroupSubjectPlan musicOneSubjectClassPlan = null;
			int totalStudentNum = 0;
			for (Entry<Integer, Long> entry : subjectCountMap.entrySet()) {

				musicOneSubjectClassPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, entry.getKey());
				if (musicOneSubjectClassPlan == null) {
					throw new BizException("系统数据[乐团声部设置]异常");
				}
				int applyNum = musicOneSubjectClassPlan.getApplyStudentNum() == null ? 0 : musicOneSubjectClassPlan.getApplyStudentNum();
				musicOneSubjectClassPlan.setApplyStudentNum(applyNum + entry.getValue().intValue());
				musicOneSubjectClassPlan.setPaidStudentNum((musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan
						.getPaidStudentNum()) + entry.getValue().intValue());
				musicOneSubjectClassPlan.setPaidZeroNum((musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum())
						+ entry.getValue().intValue());
				musicOneSubjectClassPlan.setUpdateTime(nowDate);
				musicGroupSubjectPlanDao.update(musicOneSubjectClassPlan);

				totalStudentNum += entry.getValue().intValue();
			}

			// 缴费相关
			// 更新实际缴费人数
			if (musicGroupPaymentCalender.getActualNum() == null) {
				musicGroupPaymentCalender.setActualNum(totalStudentNum);
			} else {
				musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + totalStudentNum);
			}
			if (musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY) {
				if (musicGroupPaymentCalender.getExpectNum() == null) {
					musicGroupPaymentCalender.setExpectNum(totalStudentNum);
				} else {
					musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + totalStudentNum);
				}
			}
			musicGroupPaymentCalender.setUpdateTime(nowDate);
			musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);

			MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
			List<MusicGroupPaymentCalenderDetail> insertMusicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();

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

			List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao
					.getWithPaymentCalender(musicGroupPaymentCalender.getId());

			for (StudentImportDto si : studentBasicList) {
				musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
				musicGroupPaymentCalenderDetail.setTenantId(tenantId);
				musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
				musicGroupPaymentCalenderDetail.setUserId(si.getUserId());
				musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
				musicGroupPaymentCalenderDetail.setPaymentStatus(PAID_COMPLETED);
				musicGroupPaymentCalenderDetail.setPayTime(nowDate);
				musicGroupPaymentCalenderDetail.setPaymentOrderId(null);
				musicGroupPaymentCalenderDetail.setUseInCourse(0);
				musicGroupPaymentCalenderDetail.setOpen(1);
				musicGroupPaymentCalenderDetail.setUserStatus(null);
				musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
				musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
				musicGroupPaymentCalenderDetail.setCreateTime(nowDate);
				musicGroupPaymentCalenderDetail.setUpdateTime(nowDate);

				insertMusicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);

				for (MusicGroupPaymentCalenderCourseSettings courseSetting : courseSettingsList) {
					if (courseSetting.getCourseTotalMinuties() == null || courseSetting.getCourseTotalMinuties() == 0) {
						continue;
					}
					MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
					//musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetail.getId());
					musicGroupPaymentStudentCourseDetail.setUserId(si.getUserId());
					musicGroupPaymentStudentCourseDetail.setCourseType(courseSetting.getCourseType());
					musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSetting.getCourseTotalMinuties());
					musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSetting.getCourseOriginalPrice());
					musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSetting.getCourseCurrentPrice());
					musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
					musicGroupPaymentStudentCourseDetail.setCreateTime(nowDate);
					musicGroupPaymentStudentCourseDetail.setUpdateTime(nowDate);
					musicGroupPaymentStudentCourseDetail.setTenantId(tenantId);
					musicGroupPaymentStudentCourseDetails.add(musicGroupPaymentStudentCourseDetail);
				}
			}
			if (insertMusicGroupPaymentCalenderDetailList.size() > 0) {
				musicGroupPaymentCalenderDetailDao.batchInsert(insertMusicGroupPaymentCalenderDetailList);

				Map<Integer,Long> musicGroupPaymentCalenderDetailIdMap =  insertMusicGroupPaymentCalenderDetailList.stream().collect(Collectors.toMap(MusicGroupPaymentCalenderDetail :: getUserId, MusicGroupPaymentCalenderDetail :: getId));

				if (musicGroupPaymentStudentCourseDetails.size() > 0) {
					for(MusicGroupPaymentStudentCourseDetail cd : musicGroupPaymentStudentCourseDetails){
						cd.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetailIdMap.get(cd.getUserId()));
					}
					musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetails);
				}
			}
		}

		return true;
	}

	@Override
    @Transactional(rollbackFor = Exception.class)
    public String createGroup(SubFeeSettingDto subFeeSettingDto) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null || sysUser.getId() == null) {
            throw new BizException("获取用户信息失败");
        }
        MusicGroup musicGroup = subFeeSettingDto.getMusicGroup();
        List<MusicGroupSubjectGoodsGroup> musicGroupSubjectGoodsGroups = subFeeSettingDto.getMusicGroupSubjectGoodsGroups();
        List<MusicGroupSubjectPlan> musicGroupSubjectPlans = subFeeSettingDto.getMusicGroupSubjectPlans();
        List<SubjectRegisterDto> subjectRegisters = subFeeSettingDto.getSubjectRegisters();
        String musicGroupId = idGeneratorService.generatorId() + "";
        musicGroup.setId(musicGroupId);
        if (musicGroup.getStatus() != MusicGroupStatusEnum.DRAFT && musicGroup.getStatus() != MusicGroupStatusEnum.AUDIT) {
            throw new BizException("乐团初始状态错误");
        }
        musicGroup.setDelFlag(false);
        CooperationOrgan cooperationOrgan = cooperationOrganDao.get(musicGroup.getCooperationOrganId());
        if (cooperationOrgan.getEducationUserId() == null) {
            throw new BizException("操作失败：请先配置合作单位: {} 关联的乐团主管", cooperationOrgan.getName());
        }
        musicGroup.setEducationalTeacherId(cooperationOrgan.getEducationUserId());
        // 保存乐团基本信息
        musicGroupDao.insert(musicGroup);

        // 记录创建日志
        String event = musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT ? "新建乐团，提交审核" : "保存乐团草稿";
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, event, sysUser.getId(), ""));
        if (musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT) {
            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    null, null, MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_APPLY, sysUser.getRealName(), musicGroup.getName());
        }
        // 保存乐团付费主体列表
        //批量新增
        if (subFeeSettingDto.getMusicGroupPaymentEntities() != null && subFeeSettingDto.getMusicGroupPaymentEntities().size() > 0) {
            musicGroupPaymentEntitiesDao.batchAdd(subFeeSettingDto.getMusicGroupPaymentEntities(), musicGroupId);
        }

        //乐团科目学生
        if (subjectRegisters != null && subjectRegisters.size() > 0) {
            List<StudentRegistration> studentRegistrationList = new ArrayList<>();
            subjectRegisters.forEach(e -> {
                if (e.getRegisterIdList().size() == 0) {
                    return;
                }
                //原来乐团的注册学生
                List<StudentRegistration> musicGroupStudentRegistrationList = studentRegistrationDao.findStudentListByIdList(e.getRegisterIdList());

                for (MusicGroupSubjectPlan musicGroupSubjectPlan : musicGroupSubjectPlans) {
                    if (!musicGroupSubjectPlan.getSubjectId().equals(e.getSubjectId())) continue;
                    musicGroupSubjectPlan.setExpectedStudentNum(e.getRegisterIdList().size());
                    musicGroupSubjectPlan.setApplyStudentNum(e.getRegisterIdList().size());
                    if (musicGroupSubjectPlan.getFee().compareTo(BigDecimal.ZERO) == 0) {
                        musicGroupSubjectPlan.setPaidStudentNum(e.getRegisterIdList().size());
                    }

                    for (StudentRegistration studentRegistration : musicGroupStudentRegistrationList) {
                        studentRegistration.setId(null);
                        if (musicGroupSubjectPlan.getFee().compareTo(BigDecimal.ZERO) == 0) {
                            studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
                            studentRegistration.setPaymentStatus(YES);
                        } else {
                            studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.APPLY);
                            studentRegistration.setPaymentStatus(PaymentStatusEnum.OPEN);
                        }
                        studentRegistration.setMusicGroupId(musicGroupId);
                        studentRegistration.setSubjectId(e.getSubjectId());
                        studentRegistration.setActualSubjectId(e.getSubjectId());
                        studentRegistration.setTemporaryCourseFee(null);
                    }
                }

                studentRegistrationList.addAll(musicGroupStudentRegistrationList);
            });
            musicGroup.setStatus(MusicGroupStatusEnum.PAY);
            //是否是免费团
            if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
                int size = (int) musicGroupSubjectPlans.stream().filter(e -> e.getFee().compareTo(BigDecimal.ZERO) > 0).count();
                if (size < 1) {
                    musicGroup.setStatus(MusicGroupStatusEnum.PREPARE);
                }
            }
            if (studentRegistrationList.size() > 0) {
                studentRegistrationDao.batchInsert(studentRegistrationList);
            }
            musicGroupDao.update(musicGroup);
//            List<MusicGroupStudentFee> musicGroupStudentFees = musicGroupStudentFeeDao.initMusicGroupStudentFee(musicGroupId);
//            if(musicGroupStudentFees != null && musicGroupStudentFees.size() > 0){
//                Date nextPaymentDate = musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null,null);
//                musicGroupStudentFeeDao.batchInsert(musicGroupStudentFees,nextPaymentDate,"PAID_COMPLETED");
//            }
            musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "跨团调整", sysUser.getId(), ""));
        }

        // 保存乐团声部规划
        if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
            musicGroupSubjectPlanDao.batchAdd(musicGroupSubjectPlans, musicGroupId);
        }
        // 保存乐团声部商品规划
        if (musicGroupSubjectGoodsGroups != null && musicGroupSubjectGoodsGroups.size() > 0) {
            for (MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup : musicGroupSubjectGoodsGroups) {
                if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT) && (musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson() == null
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().isEmpty()
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().equals("{}"))) {
                    throw new BizException(musicGroupSubjectGoodsGroup.getName() + " 请选择提供方式");
                }
                if (musicGroupSubjectGoodsGroup.getGroupRemissionCourseFee() == null) {
                    musicGroupSubjectGoodsGroup.setGroupRemissionCourseFee(0);
                }
            }
            musicGroupSubjectGoodsGroupDao.batchInsert(musicGroupSubjectGoodsGroups, musicGroupId);
        }
        return musicGroupId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean preRegister(StudentPreRegistration studentPreRegistration) {
        String musicGroupId = studentPreRegistration.getMusicGroupId();
        // 查询乐团状态
        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息查询失败");
        }
        if (musicGroup.getStatus() != MusicGroupStatusEnum.PRE_APPLY) {
            throw new BizException("乐团当前状态不能预报名");
        }
        StudentPreRegistration originRegistration = studentPreRegistrationDao.queryByMusicGroupIdAndPhone(studentPreRegistration.getPhone(), musicGroupId);
        if (originRegistration != null) {
            throw new BizException("您已预报名成功，请勿重复提交资料");
        }
        TenantContextHolder.setTenantId(musicGroup.getTenantId());
        studentPreRegistration.setTenantId(musicGroup.getTenantId());
        studentPreRegistration.setOrganId(musicGroup.getOrganId());
        //保存学员信息
        SysUser user = studentService.upSetStudent(studentPreRegistration);

        if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {
            //该学员是否在其他的会员团
            boolean hasMemberGroup = studentRegistrationDao.checkHasMemberGroup(musicGroupId, user.getId());
            if (hasMemberGroup) {
                throw new BizException("乐团报名失败：该学员已在其他系统收费乐团中，不可报名该乐团请联系教务老师");
            }
        }

        Organization organization = organizationDao.get(musicGroup.getOrganId());
        if (organization.getGradeType().equals(GradeTypeEnum.SIX_PLUS)) {
            for (SixPlusGradeEnum value : SixPlusGradeEnum.values()) {
                if (value.getCode().equals(studentPreRegistration.getCurrentGradeNum())) {
                    studentPreRegistration.setCurrentGrade(value.getDesc());
                    break;
                }
            }
        } else {
            for (FivePlusGradeEnum value : FivePlusGradeEnum.values()) {
                if (value.getCode().equals(studentPreRegistration.getCurrentGradeNum())) {
                    studentPreRegistration.setCurrentGrade(value.getDesc());
                    break;
                }
            }
        }
        studentPreRegistrationDao.insert(studentPreRegistration);
        // 添加成员
        imGroupMemberService.join(musicGroupId, user.getId(), null, false);
        TenantContextHolder.clearTenantId();
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean finishPreApply(String musicGroupId, boolean isCheckStudentNum) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息查询失败");
        }
        if (musicGroup.getTenantId() == null) {
            throw new BizException("乐团机构信息异常，请联系管理员");
        }
        if (musicGroup.getStatus() != MusicGroupStatusEnum.PRE_APPLY) {
            throw new BizException("操作失败：只有乐团在[{}]状态才能操作", MusicGroupStatusEnum.PRE_APPLY.getMsg());
        }
        if (isCheckStudentNum) {
            String configValue = sysTenantConfigService.getTenantConfigValue(SysConfigService.MUSIC_MIN_STUDENT_NUM, musicGroup.getTenantId());
            if (StringUtils.isNotEmpty(configValue)) {
                Integer minStudentNum = Integer.parseInt(configValue);
                // 查询乐团已报名人数
                List<StudentPreRegistration> studentPreRegistrationList = studentPreRegistrationDao.queryByMusicGroupId(musicGroupId);
                if (studentPreRegistrationList == null || studentPreRegistrationList.size() < minStudentNum) {
                    throw new BizException("操作失败：报名人数没有达到{}人", minStudentNum);
                }
            }
        }
        musicGroup.setStatus(MusicGroupStatusEnum.PRE_BUILD_FEE);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null || sysUser.getId() == null) {
            throw new BizException("请重新登录");
        }

        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroup.getId(), "报名缴费项目失败（预报名 -> 准备创建缴费）", sysUser.getId(), ""));

        return true;
    }

    @Override
    public boolean sendParentMeetingNotice(Integer userId, String musicGroupId, Date meetingDate, String address) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息查询失败");
        }
        Map<Integer, String> receiverList = null;
        if (musicGroup.getStatus() == MusicGroupStatusEnum.PRE_APPLY || musicGroup.getStatus() == MusicGroupStatusEnum.PRE_BUILD_FEE) {
            List<StudentPreRegistration> studentPreRegistrationList = studentPreRegistrationDao.queryByMusicGroupId(musicGroupId);
            receiverList = studentPreRegistrationList.stream().collect(Collectors.toMap(StudentPreRegistration::getUserId, StudentPreRegistration::getPhone));
        } else {
            receiverList = MapUtil.convertMybatisMap(studentRegistrationDao.findMapByMusicGroupId(musicGroupId, 2));
        }

        String meetingDateStr = sdf_ymdhms.format(meetingDate);
        sysMessageService.batchSendImGroupMessage(MessageTypeEnum.STUDENT_SMS_IM_MUSIC_GROUP_PARENT_MEETING_NOTICE, userId + "", null, new String[]{musicGroupId}, null, meetingDateStr, address);
        sysMessageService.batchSendMessage(MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_IM_MUSIC_GROUP_PARENT_MEETING_NOTICE, receiverList, null, 1, null, null, meetingDateStr, address);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map sporadicPay(SporadicPayDto sporadicPayDto) throws Exception {
        //获取收费项价格
        SporadicChargeInfo chargeInfo = sporadicChargeInfoDao.get(sporadicPayDto.getSporadicId());
        if (chargeInfo == null) {
            throw new BizException("支付项不存在");
        }
        if (chargeInfo.getOpenFlag().equals(1)) {
            throw new BizException("项目已关闭");
        }
        if (sporadicPayDto.getNum() == null) {
            sporadicPayDto.setNum(1);
        }
        BigDecimal amount = chargeInfo.getAmount().multiply(new BigDecimal(sporadicPayDto.getNum()));
        if (chargeInfo.getDiscountAmount() != null && chargeInfo.getDiscountAmount().compareTo(BigDecimal.ZERO) > 0) {
            amount = amount.subtract(chargeInfo.getDiscountAmount().multiply(new BigDecimal(sporadicPayDto.getNum())));
        }
        if (chargeInfo.getMaxAmount() != null) {
            if (chargeInfo.getOpenMaxTerm().equals(YesOrNoEnum.YES) && chargeInfo.getMaxAmount().compareTo(chargeInfo.getPaidAmount()) <= 0) {
                throw new Exception("活动名额已满，谢谢您的支持！");
            }
            if (chargeInfo.getOpenMaxTerm().equals(YesOrNoEnum.YES) && chargeInfo.getMaxAmount().compareTo(chargeInfo.getPaidAmount().add(amount)) < 0) {
                throw new Exception("活动名额已满，谢谢您的支持！");
            }
        }

        Date date = new Date();

        OrderTypeEnum type = OrderTypeEnum.SPORADIC;
        if (chargeInfo.getChargeType().equals(SporadicChargeTypeEnum.DOUBLE_ELEVEN2020)) {
            throw new Exception("活动已结束，谢谢您的支持！");
        }
        Integer tenantId = chargeInfo.getTenantId();
        Integer userId = sporadicPayDto.getUserId();
        String orderNo = idGeneratorService.generatorId("payment") + "";
        String channelType = "";
        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(sporadicPayDto.getCouponIdList(), amount,
                true,
                CouponDetailTypeEnum.getAllowType());
        amount = studentPaymentOrder.getActualAmount();
        if (!(amount.compareTo(sporadicPayDto.getAmount()) == 0)) {
            throw new BizException("订单金额异常");
        }
        studentPaymentOrder.setTenantId(tenantId);
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setGroupType(GroupType.SPORADIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(type);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(sporadicPayDto.getSporadicId().toString());
        studentPaymentOrder.setClassGroupId(sporadicPayDto.getNum());
        studentPaymentOrderService.insert(studentPaymentOrder);

        studentPaymentOrder.setVersion(0);
        BigDecimal balance = BigDecimal.ZERO;
        if (sporadicPayDto.getUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            if (chargeInfo.getChargeType().getCode().equals(9) ||
                    chargeInfo.getChargeType().getCode().equals(13) ||
                    chargeInfo.getChargeType().getCode().equals(14)) {
                throw new BizException(chargeInfo.getChargeType().getMsg() + "不支持余额支付");
            }
            SysUserCashAccount userCashAccount = sysUserCashAccountService.get(userId);

            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setPaymentChannel("BALANCE");
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.SPORADIC, chargeInfo.getTitle());
            }
        }

        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setRoutingOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, chargeInfo.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", BigDecimal.ZERO);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", amount);

        String receiver = "sporadic";

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/callback",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                chargeInfo.getTitle(),
                chargeInfo.getTitle(),
                chargeInfo.getOrganId(),
                receiver
        );
        studentPaymentOrder.setOrganId(chargeInfo.getOrganId());
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public HttpResponseResult renew(RegisterPayDto renewParamDto) throws Exception {
        Long calenderId = renewParamDto.getCalenderId();
        Integer userId = renewParamDto.getUserId();
        MusicGroupPaymentCalender calender = musicGroupPaymentCalenderDao.get(calenderId);
        StudentRegistration studentRegistration = studentRegistrationService.queryByUserIdAndMusicGroupId(userId, calender.getMusicGroupId());
        if (studentRegistration == null) {
            throw new BizException("请走报名缴费流程");
        }
        Integer organId = studentRegistration.getOrganId();
        MusicGroupPaymentCalenderDetail calenderDetail = musicGroupPaymentCalenderDetailDao.findByCalenderIdAndUserId(calenderId, userId);
        //关闭之前的订单
        if (calenderDetail.getPaymentOrderId() != null) {
            StudentPaymentOrder oldStudentPaymentOrder = studentPaymentOrderDao.get(calenderDetail.getPaymentOrderId());
            if(oldStudentPaymentOrder.getStatus() == ING){
                HttpResponseResult result = studentPaymentOrderService.checkRepeatPay(oldStudentPaymentOrder, renewParamDto.getRepeatPay());
                if (result.getCode() != 200) {
                    return result;
                }
            }
        }

        //获取订单总金额
        MusicGroupApplyGoodsDto goodsDto = getCalenderTotalAmount(renewParamDto, calender);

        String orderNo = idGeneratorService.generatorId("payment") + "";

        Date date = new Date();
        //使用优惠券
        CouponPayParam couponPayParam = checkCoupon(renewParamDto.getCouponIdList(), renewParamDto.getAmount());
        StudentPaymentOrder studentPaymentOrder = couponPayParam.getStudentPaymentOrder();
        studentPaymentOrder.setGroupType(GroupType.MUSIC);
        studentPaymentOrder.setUserId(userId);
        studentPaymentOrder.setOrderNo(orderNo);
        if (calender.getPaymentType() == PaymentType.ADD_STUDENT) {
            studentPaymentOrder.setType(OrderTypeEnum.ADD_STUDENT);
        } else {
            studentPaymentOrder.setType(OrderTypeEnum.RENEW);
        }
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(calender.getMusicGroupId());
        studentPaymentOrder.setBatchNo(calender.getId() + "");
        studentPaymentOrder.setCreateTime(date);
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrder.setVersion(0);
        studentPaymentOrder.setCalenderId(calenderId);
        studentPaymentOrder.setOrganId(organId);
        studentPaymentOrder.setRoutingOrganId(organId);
        studentPaymentOrderService.insert(studentPaymentOrder);

        // 拆分各商品，如果有优惠券则计算使用券后的金额，并写入订单详情
        studentPaymentOrder = studentRegistrationService.addOrder(studentRegistration, studentPaymentOrder, goodsDto, renewParamDto, couponPayParam);

        //goodsDto.getOrderAmount 真实的原价(已经扣减了送课的钱)  -  优惠券的钱 = 本次订单应付的钱
        BigDecimal actualAmount = goodsDto.getOrderAmount()
                .subtract(studentPaymentOrder.getCouponRemitFee());
        //前端获取的价格
        BigDecimal amount = renewParamDto.getAmount();
        //校验 页面传入的价格 和 （本次原价-优惠价后的价格） 是否一致
        if (amount.compareTo(actualAmount) != 0) {
            throw new BizException("商品价格不符");
        }
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new BizException("价格异常");
        }
        calenderDetail.setPaymentStatus(PaymentStatus.PROCESSING);
        calenderDetail.setPaymentOrderId(studentPaymentOrder.getId());
        musicGroupPaymentCalenderDetailDao.update(calenderDetail);

        BigDecimal balance = BigDecimal.ZERO;
        if (renewParamDto.getUseBalancePayment() || amount.doubleValue() == 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            studentPaymentOrder.setPaymentChannel("BALANCE");
            if (userCashAccount.getBalance().subtract(amount).doubleValue() >= 0) {
                // 更新订单信息
                balance = amount;
                studentPaymentOrder.setActualAmount(BigDecimal.ZERO);
                studentPaymentOrder.setBalancePaymentAmount(amount);
                studentPaymentOrder.setActualAmount(new BigDecimal(0));
                studentPaymentOrder.setUpdateTime(date);
                studentPaymentOrderService.update(studentPaymentOrder);
                sysUserCashAccountService.updateBalance(userId, amount.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团续费");
                amount = BigDecimal.ZERO;
            } else {
                if (userCashAccount.getBalance().doubleValue() > 0) {
                    balance = userCashAccount.getBalance();
                    sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团续费");
                    amount = amount.subtract(userCashAccount.getBalance());
                    studentPaymentOrder.setBalancePaymentAmount(userCashAccount.getBalance());
                    studentPaymentOrder.setActualAmount(studentPaymentOrder.getActualAmount().subtract(userCashAccount.getBalance()));
                } else {
                    studentPaymentOrder.setBalancePaymentAmount(new BigDecimal(0));
                }
            }
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, organId, balance);
            Map<String, String> notifyMap = new HashMap<>(4);
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", "");
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return BaseController.failed(HttpStatus.CREATED, notifyMap, "恭喜您,缴费成功!");
        }

        Map<String, Object> payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/callback",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + studentPaymentOrder.getOrderNo(),
                "续费",
                "乐团续费",
                organId,
                "renew"
        );

        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setOrganId(organId);
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return BaseController.succeed(payMap);
    }

    private MusicGroupApplyGoodsDto getCalenderTotalAmount(RegisterPayDto registerPayDto, MusicGroupPaymentCalender calender) {

    	String musicGroupId = calender.getMusicGroupId();
    	MusicGroup musicGroup = musicGroupDao.get(musicGroupId);

    	if(musicGroup == null){
    		throw new BizException("乐团[{}]信息查询失败", musicGroupId);
    	}

    	boolean isGiveAccessories = musicGroup.getIsGiveAccessories();

        MusicGroupApplyGoodsDto goodsDto = new MusicGroupApplyGoodsDto();
        //乐器及打包辅件价格
        List<MusicGroupSubjectGoodsGroup> goodsGroups;
        if (registerPayDto.getGoodsGroups() != null && registerPayDto.getGoodsGroups().size() > 0) {
            String goodsGroupIds = registerPayDto.getGoodsGroups().keySet().stream().map(Object::toString).collect(Collectors.joining(","));
            goodsGroups = musicGroupSubjectGoodsGroupService.findGoodsGroupByIds(goodsGroupIds);
            goodsDto.setGoodsGroups(goodsGroups);
            for (MusicGroupSubjectGoodsGroup goodsGroup : goodsGroups) {
                Map<String, BigDecimal> groupType = JSONObject.parseObject(goodsGroup.getKitGroupPurchaseTypeJson(), new TypeReference<Map<String, BigDecimal>>() {
                });

                if(isGiveAccessories && registerPayDto.getBuyCloudTeacher()){
                	if (goodsGroup.getType().equals(GoodsType.ACCESSORIES)) {
                		continue;
                	}
                }

                if (goodsGroup.getType().equals(GoodsType.INSTRUMENT)) {
                    String kitGroupPurchaseType = registerPayDto.getGoodsGroups().get(goodsGroup.getId());
                    if (!groupType.containsKey(kitGroupPurchaseType)) {
                        throw new BizException("乐器提供方式不存在,请核查");
                    }
                    if (!kitGroupPurchaseType.equals("GROUP")) {
                        goodsGroup.setPrice(kitGroupPurchaseType.equals("FREE") ? new BigDecimal(0) : goodsGroup.getDepositFee());
                    } else {
                        //购买乐器是否减免课程费用
                        goodsDto.setRemitCourseRFeeFlag(goodsGroup.getGroupRemissionCourseFee().equals(1));
                    }
                    goodsGroup.setKitGroupPurchaseType(KitGroupPurchaseTypeEnum.valueOf(kitGroupPurchaseType));
                    goodsDto.setRemitFee(groupType.get(kitGroupPurchaseType) == null ? BigDecimal.ZERO : groupType.get(kitGroupPurchaseType));
                }
                goodsGroup.setGoodsList(goodsService.findGoodsByIds(goodsGroup.getGoodsIdList()));

                //齐齐哈尔走特殊规则
                if (calender.getOrganId() == 55 && (registerPayDto.getNewCourse() == null || registerPayDto.getNewCourse().size() == 0) && !(registerPayDto.getBuyCloudTeacher() || registerPayDto.getBuyCloudTeacherPlus())) {
                    //取商品零售价
                    if (StringUtils.isNotBlank(goodsGroup.getGoodsIdList())) {
                        List<Goods> goodsList = goodsDao.findGoodsByIds(goodsGroup.getGoodsIdList());
                        for (Goods goods : goodsList) {
                            goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(goods.getDiscountPrice()));
                        }
                    }
                } else {
                    goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(goodsGroup.getPrice()));
                }
            }
            goodsDto.setOrderAmount(goodsDto.getOrderAmount().subtract(goodsDto.getRemitFee()));
        }
        //新课程形态
        List<MusicGroupPaymentCalenderCourseSettings> newCourses;
        //因为前端会传newCourse过来所以这里加了合班缴费判断
        if (calender.getPaymentType() != PaymentType.SPAN_GROUP_CLASS_ADJUST &&
                calender.getPayUserType() == PayUserType.STUDENT && registerPayDto.getNewCourse() != null && registerPayDto.getNewCourse().size() > 0) {
            newCourses = musicGroupPaymentCalenderCourseSettingsDao.getCalenderCourseSettings(registerPayDto.getNewCourse());
            for (MusicGroupPaymentCalenderCourseSettings calenderCourseSetting : newCourses) {
                if (goodsDto.isRemitCourseRFeeFlag()) {
                    goodsDto.setCourseRemitFee(goodsDto.getCourseRemitFee().add(calenderCourseSetting.getCourseCurrentPrice()));
                } else {
                    goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(calenderCourseSetting.getCourseCurrentPrice()));
                }
            }
            goodsDto.setNewCourses(newCourses);
        }
        //活动价格
        List<Long> buyCalenderActivityIdList = registerPayDto.getBuyCalenderActivityId();
        if (buyCalenderActivityIdList != null && buyCalenderActivityIdList.size() > 0) {
            goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(musicGroupPaymentCalenderService.getActivityAmount(buyCalenderActivityIdList)));
        }
        //乐器保养价格
        if (registerPayDto.getBuyMaintenance()) {
            goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(musicGroupPaymentCalenderService.getRepairAmount(calender.getId())));
        }
        //云教练价格和订单
        if (registerPayDto.getBuyCloudTeacher()) {
            goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(musicGroupPaymentCalenderService.getMemberAmount(calender.getId())));
        }
        //合班缴费
        List<MusicGroupPaymentCalenderStudentDetail> studentDetails = musicGroupPaymentCalenderStudentDetailDao.findByBatchNoAndUserId(registerPayDto.getBatchNo(), registerPayDto.getUserId());
        if (studentDetails != null && studentDetails.size() > 0) {
            goodsDto.setOrderAmount(goodsDto.getOrderAmount().add(studentDetails.stream().map(e -> e.getCourseCurrentPrice()).reduce(BigDecimal.ZERO, BigDecimal::add)));
        }
        return goodsDto;
    }

    //校验如果使用了优惠券，优惠券的信息是否合法
    public CouponPayParam checkCoupon(List<Integer> couponIdList, BigDecimal amount) {
        CouponPayParam couponPayParam = new CouponPayParam();
        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        //没有使用优惠券
        if (CollectionUtils.isEmpty(couponIdList)) {
            studentPaymentOrder.setCouponRemitFee(BigDecimal.ZERO);
        } else {
            //校验优惠券的使用
            couponPayParam = sysCouponCodeService.getCouponPayParam(couponIdList);
            studentPaymentOrder.setCouponCodeId(StringUtils.join(couponIdList, ","));
            studentPaymentOrder.setCouponRemitFee(couponPayParam.getCouponRemitTotal());
        }
        couponPayParam.setStudentPaymentOrder(studentPaymentOrder);

        return couponPayParam;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult pay(RegisterPayDto registerPayDto) throws Exception {
        //判断用户是否已存在订单
        List<StudentPaymentOrder> applyOrderList = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(registerPayDto.getUserId(), registerPayDto.getMusicGroupId(), DealStatusEnum.ING);
        if (CollectionUtils.isNotEmpty(applyOrderList)) {
            HttpResponseResult result = studentPaymentOrderService.checkRepeatPay(applyOrderList.get(0), registerPayDto.getRepeatPay());
            if (result.getCode() != 200) {
                return result;
            }
        }
        StudentRegistration studentRegistration = studentRegistrationService.get(registerPayDto.getRegisterId().longValue());
        if (studentRegistration == null) {
            throw new BizException("报名信息有误，请核查");
        }
        MusicGroupPaymentCalender musicGroupRegCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(studentRegistration.getMusicGroupId());
        if (musicGroupRegCalender == null) {
            throw new BizException("缴费信息不存在");
        }
        registerPayDto.setBatchNo(musicGroupRegCalender.getBatchNo());
        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
        if (musicGroup == null) {
            throw new BizException("查询乐团信息失败");
        }

        Long calenderId = musicGroupRegCalender.getId();
        Integer userId = studentRegistration.getUserId();

        //获取缴费项目金额
        MusicGroupApplyGoodsDto goodsDto = getCalenderTotalAmount(registerPayDto, musicGroupRegCalender);

        studentRegistration.setMusicGroupPaymentCalenderId(musicGroupRegCalender.getId());
        studentRegistration.setOrganId(musicGroup.getOrganId());
        studentRegistration.setPayingStatus(1);

        Date date = new Date();

        String orderNo = idGeneratorService.generatorId("payment") + "";

        String channelType = "";
        //生成订单，校验优惠券的使用情况
        CouponPayParam couponPayParam = checkCoupon(registerPayDto.getCouponIdList(), registerPayDto.getAmount());
        StudentPaymentOrder studentPaymentOrder = couponPayParam.getStudentPaymentOrder();
        studentPaymentOrder.setUserId(studentRegistration.getUserId());
        studentPaymentOrder.setGroupType(GroupType.MUSIC);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.APPLY);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setPaymentChannel(channelType);
        studentPaymentOrder.setMusicGroupId(studentRegistration.getMusicGroupId());
        studentPaymentOrder.setCalenderId(calenderId);
        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
        studentPaymentOrder.setRoutingOrganId(musicGroup.getOrganId());
        studentPaymentOrderService.insert(studentPaymentOrder);

        // 拆分各商品，如果有优惠券则计算使用券后的金额，并写入订单详情
        studentPaymentOrder = studentRegistrationService.addOrder(studentRegistration, studentPaymentOrder, goodsDto, registerPayDto, couponPayParam);
        //goodsDto.getOrderAmount 真实的原价(已经扣减了送课的钱)  -  优惠券的钱 = 本次订单应付的钱
        BigDecimal actualAmount = goodsDto.getOrderAmount()
                .subtract(studentPaymentOrder.getCouponRemitFee());

        //前端获取的价格
        BigDecimal amount = registerPayDto.getAmount();
        //校验 页面传入的价格 和 （本次原价-优惠价后的价格） 是否一致
        if (amount.compareTo(actualAmount) != 0) {
            throw new BizException("商品价格不符");
        }
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            throw new BizException("价格异常");
        }
        studentPaymentOrder = studentPaymentOrderService.get(studentPaymentOrder.getId());
        boolean canPay = studentPaymentOrder.getClassGroupId() != null && studentPaymentOrder.getClassGroupId().equals(206);

        BigDecimal balance = BigDecimal.ZERO;
        if (registerPayDto.getUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setPaymentChannel("BALANCE");
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团报名");
            }
        }
        studentPaymentOrder.setBatchNo(musicGroupRegCalender.getId() + "");
        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setRemitFee(goodsDto.getRemitFee());
        studentPaymentOrder.setCourseRemitFee(goodsDto.getCourseRemitFee());
        studentPaymentOrder.setUpdateTime(date);

        if ("205".equals(studentPaymentOrder.getPaymentAccountNo())) {
            if (!canPay) {
                studentPaymentOrder.setPaymentChannel("ADAPAY");
            }
            studentRegistration.setPayingStatus(2);
        }
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        //更新注册信息
        studentRegistrationService.update(studentRegistration);

        if ("205".equals(studentPaymentOrder.getPaymentAccountNo())) {
            Integer teacherId = musicGroup.getEducationalTeacherId();
            SysUser endTeacher = sysUserFeignService.queryUserById(teacherId);
            Map<Integer, String> userPhoneMap = new HashMap<>();
            userPhoneMap.put(endTeacher.getId(), endTeacher.getPhone());
            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.AWSMS, MessageTypeEnum.NO_BUY_CLOUD_TEACHER_MSG,
                    userPhoneMap, null, 0, null, null, musicGroup.getName(), studentRegistration.getName());
            if (!canPay && studentRegistration.getMusicGroupStatus() == StudentMusicGroupStatusEnum.APPLY) {
                Map<String, String> notifyMap = new HashMap<>();
                notifyMap.put("hasPaidZero", "205");
                notifyMap.put("orderNo", studentPaymentOrder.getOrderNo());
                return BaseController.failed(HttpStatus.RESET_CONTENT, notifyMap, "报名审核中");
            }
        }

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, musicGroup.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            return BaseController.failed(HttpStatus.CREATED, notifyMap, "恭喜您,报名成功!");
        }

        String orderSubject = "乐团报名";
        String receiver = "register";
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType().equals(CooperationOrgan.OwnershipType.COOPERATION)) {
            orderSubject = "乐团相关费用";
        }
        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/callback",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                orderSubject,
                orderSubject,
                musicGroup.getOrganId(),
                receiver
        );

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

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSubjectInfo(SubFeeSettingDto subFeeSettingDto) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("身份校验失败");
        }
        String musicGroupId = subFeeSettingDto.getMusicGroupId();
        //乐团状态是否正确
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        if (subFeeSettingDto.getMusicGroupStatus() == null) {
            throw new BizException("参数校验异常");
        }
        //声部存在学生不容许删除声部
        List<StudentRegistration> registrations = studentRegistrationDao.findClassGroupStu(musicGroupId, null);
        Map<Integer, List<StudentRegistration>> regMap = registrations.stream().collect(Collectors.groupingBy(StudentRegistration::getActualSubjectId));
        List<MusicGroupSubjectPlan> musicGroupSubjectPlans = subFeeSettingDto.getMusicGroupSubjectPlans();
        List<Integer> waringSubjectIds = new ArrayList<>();
        regMap.forEach((subjectId, regs) -> {
            boolean hasSubject = false;
            for (MusicGroupSubjectPlan musicGroupSubjectPlan : musicGroupSubjectPlans) {
                if (musicGroupSubjectPlan.getSubjectId().equals(subjectId)) {
                    hasSubject = true;
                    musicGroupSubjectPlan.setApplyStudentNum(regs.size());
                }
            }
            if (!hasSubject) {
                waringSubjectIds.add(subjectId);
            }
        });

        if (waringSubjectIds.size() > 0) {
            List<Subject> waringSubjects = subjectDao.findBySubjectIds(waringSubjectIds);
            String waringSubjectStr = waringSubjects.stream().map(Subject::getName).collect(Collectors.joining(","));
            throw new BizException(waringSubjectStr + "存在学生，不能删除");
        }

        if (musicGroup.getStatus() == MusicGroupStatusEnum.DRAFT || musicGroup.getStatus() == MusicGroupStatusEnum.AUDIT_FAILED) {
            musicGroup.setStatus(subFeeSettingDto.getMusicGroupStatus());
            musicGroup.setUpdateTime(new Date());
            musicGroupDao.update(musicGroup);
        }
        //记录日志信息
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "基础信息提交审核(编辑中 -> 审核中)", sysUser.getId(), JSONObject.toJSONString(subFeeSettingDto)));
        //删除原有的乐团声部规划
        musicGroupSubjectPlanDao.delByMusicGroupId(musicGroupId);
        //删除原有的声部商品组合
        musicGroupSubjectGoodsGroupDao.delByMusicGroupId(subFeeSettingDto.getMusicGroupId());
        if (musicGroupSubjectPlans != null && musicGroupSubjectPlans.size() > 0) {
            musicGroupSubjectPlans.forEach(e -> {
                //修改课程费用
                musicGroupStudentFeeDao.updateCourseFee(musicGroupId, e.getSubjectId(), e.getFee());
            });
            musicGroupSubjectPlanDao.batchAdd(musicGroupSubjectPlans, musicGroupId);
        }
        if (subFeeSettingDto.getMusicGroupSubjectGoodsGroups() != null && subFeeSettingDto.getMusicGroupSubjectGoodsGroups().size() > 0) {
            for (MusicGroupSubjectGoodsGroup musicGroupSubjectGoodsGroup : subFeeSettingDto.getMusicGroupSubjectGoodsGroups()) {
                if (musicGroupSubjectGoodsGroup.getType().equals(GoodsType.INSTRUMENT) && (musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson() == null
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().isEmpty()
                        || musicGroupSubjectGoodsGroup.getKitGroupPurchaseTypeJson().equals("{}"))) {
                    throw new BizException(musicGroupSubjectGoodsGroup.getName() + " 请选择提供方式");
                }
                if (musicGroupSubjectGoodsGroup.getGroupRemissionCourseFee() == null) {
                    musicGroupSubjectGoodsGroup.setGroupRemissionCourseFee(0);
                }
            }

            musicGroupSubjectGoodsGroupDao.batchInsert(subFeeSettingDto.getMusicGroupSubjectGoodsGroups(), musicGroupId);
        }
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                null, null, MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_APPLY, sysUser.getRealName(), musicGroup.getName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateExpectedStudentNum(List<UpdateExpectedNumDto> updateExpectedNumDtos) {
        updateExpectedNumDtos.forEach(e -> {
            MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.get(e.getMusicGroupSubjectPlanId());
            musicGroupSubjectPlan.setExpectedStudentNum(e.getExpectedStudentNum());
            if (musicGroupSubjectPlanDao.update(musicGroupSubjectPlan) <= 0) {
                throw new BizException("更新失败,请重试");
            }
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAction(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.PREPARE);

        //乐器采购清单是否确认
        List<StudentPaymentOrderDetail> applyOrder = studentPaymentOrderDetailService.findApplyOrderSuccess(musicGroupId, DealStatusEnum.SUCCESS);
        if (applyOrder != null && applyOrder.size() > 0) {
            //是否购买了乐器，支持无乐器乐团
            long count = applyOrder.stream().filter(e -> e != null && StringUtils.isNotEmpty(e.getGoodsIdList())).count();
            if (count > 0L) {
                Map<String, Object> param = new HashMap<>();
                param.put("musicGroupId", musicGroupId);
                param.put("tenantId", musicGroup.getTenantId());
                int i = musicGroupPurchaseListDao.queryCount(param);
                if (i <= 0) {
                    throw new BizException("采购清单未确认");
                }
            }
        }

        //课酬是否确认
        Integer courseScheduleNum = courseScheduleDao.countCourseScheduleByMusicGroupId(musicGroupId);
        if (courseScheduleNum != null && courseScheduleNum > 0) {
            if (classGroupService.checkSetSalary(musicGroupId) == false) {
                throw new BizException("课酬未确认");
            }
        }
        musicGroupStudentFeeDao.batchUpdateCalenders(musicGroupId);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "确认开团(筹备中 -> 进行中)", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.PROGRESS);
        //获取所有已缴费学员人数
        List<StudentRegistration> studentRegistrations = studentRegistrationDao.queryStudentByMusicGroupId(musicGroupId);
        studentRegistrationDao.updateOriginalFlag(musicGroupId);
        musicGroup.setGroupMemberNum(studentRegistrations == null ? 0 : studentRegistrations.size());
        musicGroup.setBillStartDate(new Date());
        musicGroupDao.update(musicGroup);
        //获取乐团班级列表
        List<ClassGroup> classGroups = classGroupDao.queryClassGroups(musicGroupId, "MUSIC");
        for (ClassGroup classGroup : classGroups) {
            //获取班级关联的老师列表
            Set<Integer> teacherIds = classGroupTeacherMapperDao.queryTeacherIdsByClassGroupId(classGroup.getId(), null, null);
            //获取班级关联的学员列表
            Set<Integer> studentIds = classGroupStudentMapperDao.queryStudentIdsByClassGroupId(classGroup.getId(), null, null);
            //创建IM群组
            classGroupService.addImGroup(classGroup, new ArrayList<>(studentIds), new ArrayList<>(teacherIds));
        }
        imUserFriendService.refreshGroupImUserFriend(musicGroupId, GroupType.MUSIC);
        //给老师发送乐团成立通知
        Map<Integer, String> map = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertMybatisMap(musicGroupDao.queryTeacherIdMap(musicGroupId))), HashMap.class);
        if (map != null && map.size() > 0) {
            sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.TEACHER_PUSH_MUSIC_GROUP_COURSE_ADD_PLAN,
                    map, null, 0, "1", "TEACHER", musicGroup.getName());
        }
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                "1", musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_ACTION_GROUP, musicGroup.getName());

        //统计变更学员数
        groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.NORMAL, null);
    }

    private MusicGroup saveLog(String musicGroupId, MusicGroupStatusEnum statusEnum) throws Exception {
        Date date = new Date();
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        if (musicGroup.getStatus() != statusEnum) {
            throw new BizException("当前乐团状态不支持此操作");
        }
        musicGroup.setUpdateTime(date);
        return musicGroup;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAudit(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.DRAFT);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "提交审核（草稿 -> 审核中）", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.AUDIT);
        musicGroupDao.update(musicGroup);
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                null, null, MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_APPLY, sysUser.getRealName(), musicGroup.getName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAuditFailed(String musicGroupId, String memo) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.AUDIT);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "乐团审核失败（审核中 -> 审核失败）", sysUser.getId(), memo));
        musicGroup.setMemo(memo);
        musicGroup.setStatus(MusicGroupStatusEnum.AUDIT_FAILED);
        musicGroupDao.update(musicGroup);
        //修改缴费项目状态
        List<MusicGroupPaymentCalender> musicGroupPaymentCalenders = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId);
        if (musicGroupPaymentCalenders != null && musicGroupPaymentCalenders.size() > 0) {
            musicGroupPaymentCalenders.forEach(e -> {
                e.setStatus(MusicGroupPaymentCalender.PaymentCalenderStatusEnum.REJECT);
            });
            musicGroupPaymentCalenderDao.batchUpdate(musicGroupPaymentCalenders);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupAuditSuccess(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.AUDIT);
        if (musicGroup.getTenantId() == null) {
            throw new BizException("乐团机构信息异常，请联系管理员");
        }
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "审核通过（审核中 -> 预报名）", sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.PRE_APPLY);
        musicGroupDao.update(musicGroup);

        // 创建群
        imGroupService.create(musicGroupId, null, "乐团预报名", null,
                musicGroup.getName(), musicGroup.getName(), null, GroupType.MUSIC.getCode(), ImGroup.GroupTypeEnum.PARENT_MEETING);

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

        if (musicGroup.getTeamTeacherId() != null) {
            userRoleMap.put(musicGroup.getTeamTeacherId(), "运营主管");
        }
        if (musicGroup.getEducationalTeacherId() != null) {
            userRoleMap.put(musicGroup.getEducationalTeacherId(), "乐团主管");
        }
        if (musicGroup.getDirectorUserId() != null) {
            userRoleMap.put(musicGroup.getDirectorUserId(), "乐队指导");
        }
        if (musicGroup.getTransactionTeacherId() != null) {
            userRoleMap.put(musicGroup.getTransactionTeacherId(), "衔接老师");
        }
        // 添加成员
        imGroupMemberService.join(musicGroupId, userRoleMap);
        //缴费老师推送消息
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), null,
                null, musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_ADJUST_SUCCESS, musicGroup.getName());
        Map<Integer, String> map = new HashMap<>(1);
        map.put(musicGroup.getEducationalTeacherId(), musicGroup.getEducationalTeacherId().toString());
        if (map != null && map.size() > 0) {
            sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.BACKSTAGE_CREATE_MUSIC_GROUP_ADJUST_SUCCESS,
                    map, null, 0, null, "SYSTEM", musicGroup.getName());
        }
    }

    @Override
    public int pushMessage(String musicGroupId, String classGroupIds) throws IOException {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup.getOwnershipType() == null || musicGroup.getOwnershipType() != CooperationOrgan.OwnershipType.OWN) {
            throw new BizException("三方乐团，不推送报名信息");
        }
        List<HighClassGroupDto> highClassGroup = classGroupDao.findHighClassGroup(musicGroupId, classGroupIds);

        if (classGroupIds != null && !classGroupIds.isEmpty()) {
            List<Integer> classGroupSet = highClassGroup.stream().map(HighClassGroupDto::getId).collect(Collectors.toList());
            Map<Integer, Long> totalNumMap = MapUtil.convertIntegerMap(courseScheduleDao.countTotalNumByClassGroupId(classGroupSet, null, 0));
            highClassGroup.removeIf(next -> totalNumMap.get(next.getId()) != null && totalNumMap.get(next.getId()) > 0);
        }
        Set<ClassGroupTypeEnum> classGroupTypeSet = highClassGroup.stream().map(HighClassGroupDto::getType).collect(Collectors.toSet());
        String HighClassGroupSubjectIds = highClassGroup.stream().filter(e -> e.getType().equals(ClassGroupTypeEnum.HIGH)).map(HighClassGroupDto::getSubjectIdList).collect(Collectors.joining(","));
        String HighOnlineClassGroupSubjectIds = highClassGroup.stream().filter(e -> e.getType().equals(ClassGroupTypeEnum.HIGH_ONLINE)).map(HighClassGroupDto::getMemo).collect(Collectors.joining(","));
        if (!HighClassGroupSubjectIds.isEmpty() && !HighOnlineClassGroupSubjectIds.isEmpty()) {
            HighClassGroupSubjectIds += "," + HighOnlineClassGroupSubjectIds;
        } else {
            HighClassGroupSubjectIds += HighOnlineClassGroupSubjectIds;
        }

        String[] subjectIds = HighClassGroupSubjectIds.split(",");

        List<StudentRegistration> students = new ArrayList<>();
        if (classGroupTypeSet.contains(ClassGroupTypeEnum.HIGH)) {
            List<StudentRegistration> noHighClassGroupStudents = studentRegistrationService.findMusicGroupStuNoClassType(musicGroupId, null, ClassGroupTypeEnum.HIGH, null);
            students.addAll(noHighClassGroupStudents);
        }
        if (classGroupTypeSet.contains(ClassGroupTypeEnum.HIGH_ONLINE)) {
            List<StudentRegistration> noHighOnlineClassGroupStudents = studentRegistrationService.findMusicGroupStuNoClassType(musicGroupId, null, ClassGroupTypeEnum.HIGH_ONLINE, null);
            students.addAll(noHighOnlineClassGroupStudents);
        }


        Map<Integer, String> studentMap = new HashMap<>();
        for (StudentRegistration student : students) {
            if (!Arrays.asList(subjectIds).contains(student.getActualSubjectId().toString())) {
                continue;
            }
            studentMap.put(student.getUserId(), student.getUserId().toString());
        }

        if (studentMap.size() == 0) {
            throw new BizException("开启报名失败，没有可推送的学生");
        }

        String baseURL = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);
        String url = baseURL + "/#/smallRegister?musicGroupId=" + musicGroupId;
        classGroupIds = highClassGroup.stream().map(e -> e.getId().toString()).collect(Collectors.joining(","));
        if (classGroupIds != null && !classGroupIds.isEmpty()) {
            url = baseURL + "/#/smallRegister?musicGroupId=" + musicGroupId + "&classGroupIds=" + classGroupIds;
        }
        String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
        sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_BASICS_SKILL_APPLY_MESSAGE,
                studentMap, null, 0, "5?" + url, "STUDENT", musicGroup.getName(), HttpUtil.getSortUrl(url), serverPhone);

        return studentMap.size();
    }

    @Override
    public List<MusicCardDto> queryOrganMusicInfos(Integer organId) {
        return musicGroupDao.queryOrganMusicInfos(organId, TenantContextHolder.getTenantId());
    }

    @Override
    public List<MusicCardDto> queryUserMusicGroups(Integer userId) {
        List<MusicCardDto> musicCardDtos = musicGroupDao.queryUserMusicGroups(userId);
        Set<String> musicGroupIds = musicCardDtos.stream().map(MusicCardDto::getMusicGroupId).collect(Collectors.toSet());
        Map<String, String> paymentStatus = MapUtil.convertMybatisMap(musicGroupPaymentCalenderDao.queryUserPaymentStatus(userId, StringUtils.join(musicGroupIds, ",")));
        // 获取学员在该乐团续费状态
        musicCardDtos.forEach(e -> {
            e.setPaymentStatus(paymentStatus.get(e.getMusicGroupId()));
        });
        return musicCardDtos;
    }


    @Override
    public MusicCardDto queryPersonalMusicGroups(Integer userId) {
        SysUser sysUser = sysUserFeignService.queryUserById(userId);
        if (sysUser == null) {
            throw new BizException("用户不存在");
        }
        MusicCardDto musicCardDto = musicGroupDao.queryPersonalMusicGroups(userId);
        if (musicCardDto == null) {
            musicCardDto = new MusicCardDto();
            musicCardDto.setUserName(sysUser.getUsername());
        }
        musicCardDto.setMusicGroupNum(musicGroupDao.countUserMusicGroups(userId));
        musicCardDto.setVipClassNum(classGroupStudentMapperDao.countUserGroups(userId, ClassGroupTypeEnum.VIP.getCode()));
        return musicCardDto;
    }

    @Override
    public List<BasicUserDto> findTeachersByStuId(Integer studentId, String search) {
        //获取相关课程，班级老师列表
        Set<Integer> teacherIds = teacherDao.findMusicTeacherIds(studentId);
        //获取学员所在乐团列表
        List<String> musicGroupIds = studentRegistrationDao.queryStudentMusicGroup(studentId);
        if (musicGroupIds != null && musicGroupIds.size() > 0) {
            List<MusicGroup> musicGroups = musicGroupDao.queryListByIds(StringUtils.join(musicGroupIds, ","));
            musicGroups.forEach(e -> {
                teacherIds.add(e.getDirectorUserId());
                teacherIds.add(e.getEducationalTeacherId());
                teacherIds.add(e.getTeamTeacherId());
            });
        }
        //获取相关vip课老师列表
        teacherIds.addAll(teacherDao.findVipTeacherIds(studentId));
        //获取陪练课老师列表
        teacherIds.addAll(teacherDao.findPracticeTeacherIds(studentId));
        //获取对外课程老师列表
        teacherIds.addAll(teacherDao.findCloseCourseTeacherIds(studentId));
        //获取陪练课课程教务老师
        teacherIds.addAll(teacherDao.findPracticeEducationalTeacherId(studentId));
        //获取VIP课程教务老师
        teacherIds.addAll(teacherDao.findVipEducationalTeacherId(studentId));
        //获取对外课程务老师
        teacherIds.addAll(teacherDao.findCommEducationalTeacherId(studentId));
        //获取关联的指导老师
        Student student = studentService.get(studentId);
        if (student != null && student.getTeacherId() != null) {
            teacherIds.add(student.getTeacherId());
        }
        if (teacherIds.size() > 0) {
            return teacherDao.queryTeacherBaseInfo(teacherIds, search);
        }
        return new ArrayList<>();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean cancelMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.getLocked(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            musicGroup.setStatus(MusicGroupStatusEnum.CANCELED);
            musicGroup.setUpdateTime(new Date());
            musicGroupDao.update(musicGroup);
        } else {
            throw new BizException("乐团当前状态是{}，不能取消", musicGroup.getStatus().getMsg());
        }

        // 查询是否有中间状态的缴费信息
        List<StudentPaymentOrder> studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, DealStatusEnum.ING);

        if (studentPaymentOrders != null && studentPaymentOrders.size() > 0) {
            throw new BizException("缴费存在交易中的数据，不能取消乐团");
        }

        //删除续费记录
        musicGroupStudentFeeDao.deleteByMusicGroupId(musicGroupId, null);

        // 删除课表
        courseScheduleDao.deleteCourseSchedulesByMusicGroupID(musicGroupId, GroupType.MUSIC);
        // 删除每节课的课酬
        courseScheduleStudentPaymentService.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);
        courseScheduleTeacherSalaryDao.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);

        //删除考勤
        teacherAttendanceDao.deleteByMusicGroupId(musicGroupId, GroupType.MUSIC);

        /*// 查询已缴费信息
        studentPaymentOrders = studentPaymentOrderDao.queryByDealStatus(musicGroupId, OrderTypeEnum.APPLY, SUCCESS);

        // 退费
        for (StudentPaymentOrder order : studentPaymentOrders) {
            // 增加交易流水
            sysUserCashAccountDetailService.addCashAccountDetail(order.getUserId(), order.getActualAmount().add(order.getBalancePaymentAmount()), SysUserCashAccountDetailService.MUSIC_GROUP
                    + musicGroupId, "", PlatformCashAccountDetailTypeEnum.REFUNDS, null, SUCCESS, "取消乐团", null);
        }*/
        //获取当前乐团所有已报名学员
        List<StudentRegistration> registrations = studentRegistrationDao.findClassGroupStu(musicGroupId, null);
        String configValue = sysConfigDao.findConfigValue(SysConfigService.REFUND_PERIOD);
        if (StringUtils.isNotEmpty(configValue) && musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            if (registrations != null && registrations.size() > 0) {
                Map<Integer, String> map = new HashMap<>(registrations.size());
                registrations.forEach(e -> {
                    map.put(e.getUserId(), e.getUserId().toString());
                });
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_PUSH_MUSIC_GROUP_CLOSE,
                        map, null, 0, "1", "STUDENT", musicGroup.getName(), configValue);
            }
        }
        //将学生退团
        if (registrations.size() > 0 && studentRegistrationService.quitAllStudent(musicGroup.getId(), "退团（乐团取消）") <= 0) {
            throw new BizException("处理学生退团失败，请重试");
        }
        //记录建团日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "取消乐团", sysUser.getId(), ""));
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                "1", musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_STOP, musicGroup.getName());
        return true;
    }

    @Override
    public boolean deleteMusicGroup(String musicGroupId) {

        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);

        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }

        if (musicGroup.getDelFlag() == true) {
            throw new BizException("乐团已删除");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.CANCELED) {
            throw new BizException("乐团当前状态是{}，不能删除", musicGroup.getStatus().getMsg());
        }

        musicGroup.setUpdateTime(new Date());
        musicGroup.setDelFlag(true);
        musicGroupDao.update(musicGroup);

        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean pauseMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            throw new BizException("乐团当前状态是{}，不能暂停", musicGroup.getStatus().getMsg());
        }

        musicGroup.setStatus(MusicGroupStatusEnum.PAUSE);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        // 清除下次缴费时间
        musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, null);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "暂停乐团", sysUser.getId(), ""));

        //删除课表
        courseScheduleDao.logicDeleteCourseSchedulesByMusicGroupID(musicGroup.getId());

        //统计变更学员数
        groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, null);

        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean resumeMusicGroup(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PAUSE) {
            throw new BizException("乐团当前状态是{}，不能恢复", musicGroup.getStatus().getMsg());
        }

        musicGroup.setStatus(MusicGroupStatusEnum.PROGRESS);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        // 重新设置下次缴费时间
        /*List<MusicGroupStudentFee> fees = musicGroupStudentFeeDao.queryByMusicGroupId(musicGroupId);
        Date date = new Date();
        fees.forEach(e -> {
            e.setNextPaymentDate(musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null, e));
            e.setUpdateTime(date);
        });
        musicGroupStudentFeeDao.batchUpdate(fees);*/
//        musicGroupStudentFeeDao.updateNextPaymentDate(musicGroupId, musicGroupPaymentCalenderService.getNextPaymentDate(musicGroupId, null));
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "恢复乐团", sysUser.getId(), ""));

        //恢复课表
        courseScheduleDao.resumeCourseScheduleByMusicGroupId(musicGroup.getId());

        //统计变更学员数
        groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.NORMAL, null);

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean extensionPaymentExpireDate(String musicGroupId, Date expireDate) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (!(musicGroup.getStatus() == MusicGroupStatusEnum.APPLY ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PAY ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PREPARE ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS)) {
            throw new BizException("乐团当前状态是[{}]，不能延长缴费", musicGroup.getStatus().getMsg());
        }

        Date date = new Date();

        if (DateUtil.getLastTimeWithDay(expireDate).before(date)) {
            throw new BizException("日期设置错误");
        }

        musicGroup.setPaymentExpireDate(expireDate);
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);

        MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderService.findByMusicGroupRegCalender(musicGroup.getId());
        if (regCalender != null && regCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)) {
            regCalender.setDeadlinePaymentDate(expireDate);
            regCalender.setStatus(MusicGroupPaymentCalender.PaymentCalenderStatusEnum.OPEN);
            regCalender.setUpdateTime(date);
            musicGroupPaymentCalenderService.update(regCalender);
        }

        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "延长缴费", sysUser.getId(), ""));
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                null, musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_LENGTHEN_PAYMENT, musicGroup.getName());
        return true;
    }

    @Override
    public boolean extensionApplyExpireDate(String musicGroupId, Date expireDate) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (!(musicGroup.getStatus() == MusicGroupStatusEnum.APPLY ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PAY ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PREPARE ||
                musicGroup.getStatus() == MusicGroupStatusEnum.PROGRESS)) {
            throw new BizException("乐团当前状态是[{}]，不能延长报名", musicGroup.getStatus().getMsg());
        }

        Date date = new Date();

        if (date.after(DateUtil.getLastTimeWithDay(expireDate))) {
            throw new BizException("日期设置错误");
        }

        musicGroup.setApplyExpireDate(expireDate);
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "延长报名时间", sysUser.getId(), ""));
        return true;
    }

    @Override
    public boolean extensionPreApplyExpireDate(String musicGroupId, Date expireDate) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PRE_APPLY) {
            throw new BizException("乐团当前状态是[{}]，不能延长预报名", musicGroup.getStatus().getMsg());
        }

        Date date = new Date();

        if (date.after(DateUtil.getLastTimeWithDay(expireDate))) {
            throw new BizException("日期设置错误");
        }

        musicGroup.setPreApplyExpireDate(expireDate);
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "延长预报名时间", sysUser.getId(), ""));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean applyQuitMusicGroup(List<SysUserRoleEnum> currentOperatorRoleIds, MusicGroupQuit reqMusicGroupQuit, Integer operatorId) {

        Integer userId = reqMusicGroupQuit.getUserId();
        String musicGroupId = reqMusicGroupQuit.getMusicGroupId();
        String reason = reqMusicGroupQuit.getReason();

        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }

        if (musicGroup.getStatus() == MusicGroupStatusEnum.CANCELED || musicGroup.getStatus() == MusicGroupStatusEnum.PAUSE) {
            throw new BizException("申请失败，乐团状态[已取消]或[已暂停]");
        }

        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("用户注册信息不存在");
        }

        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (musicGroupQuit != null) {
            if (musicGroupQuit.getStatus() == PROCESSING) {
                throw new BizException("申请失败，存在[申请中]的记录");
            }
        }

        musicGroupQuit = new MusicGroupQuit();
        musicGroupQuit.setCreateTime(new Date());
        musicGroupQuit.setJoinDate(studentRegistration.getCreateTime());
        musicGroupQuit.setMusicGroupId(musicGroupId);
        musicGroupQuit.setUserId(userId);
        musicGroupQuit.setUserComment(reqMusicGroupQuit.getUserComment());
        musicGroupQuit.setApplyUserId(userId);
        musicGroupQuit.setReason(reason);
		musicGroupQuit.setReasonEnum(reqMusicGroupQuit.getReasonEnum());

        MusicGroupReturnFeeDto returnFeeDto = reqMusicGroupQuit.getReturnFeeDto();
        if (returnFeeDto != null) {
            musicGroupQuit.setFeeJson(JsonUtil.toJSONString(returnFeeDto));
            musicGroupQuit.setReturnFeeDto(returnFeeDto);
        }
        musicGroupQuit.setIsVisit(reqMusicGroupQuit.getIsVisit());
        musicGroupQuit.setVisitTime(reqMusicGroupQuit.getVisitTime());
        musicGroupQuit.setStatus(PROCESSING);
        //加一的原因是为了和positionId同步，枚举是从0开始
        musicGroupQuit.setCurrentApproveRole(SysUserRoleEnum.EDUCATION.ordinal() + 1 + "");

        if (currentOperatorRoleIds != null && currentOperatorRoleIds.size() > 0) {
            if (!currentOperatorRoleIds.contains(SysUserRoleEnum.ORGAN_MANAGER) && currentOperatorRoleIds.contains(SysUserRoleEnum.EDUCATION)) {

                if (musicGroupQuit.getStatus() == ApprovalStatus.APPROVED) {
                    throw new BizException("只能分部经理操作退团");
                }
                //加一的原因是为了和positionId同步，枚举是从0开始
                musicGroupQuit.setCurrentApproveRole(SysUserRoleEnum.ORGAN_MANAGER.ordinal() + 1 + "");
            }
            if (currentOperatorRoleIds.contains(SysUserRoleEnum.ORGAN_MANAGER) && !currentOperatorRoleIds.contains(SysUserRoleEnum.EDUCATION)) {

                throw new BizException("只能乐团主管操作退团申请");
            }

            BigDecimal returnTotalFee = BigDecimal.ZERO;

            if (returnFeeDto.getIsReturnAccessoriesFee()) {
                returnTotalFee = returnTotalFee.add(returnFeeDto.getAccessoriesFee());
            }
            if (returnFeeDto.getIsReturnCourseFee()) {
                returnTotalFee = returnTotalFee.add(returnFeeDto.getCourseFee());
            }
            if (returnFeeDto.getIsReturnMaintenanceFee()) {
                returnTotalFee = returnTotalFee.add(returnFeeDto.getMaintenanceFee());
            }
            if (returnFeeDto.getIsReturnMemberFee()) {
                returnTotalFee = returnTotalFee.add(returnFeeDto.getMemberFee());
            }
            if (returnFeeDto.getIsReturnMusicalFee()) {
                returnTotalFee = returnTotalFee.add(returnFeeDto.getMusicalFee());
            }

            musicGroupQuit.setReturnTotalFee(returnTotalFee);
        }

        musicGroupQuitDao.insert(musicGroupQuit);

        if (reqMusicGroupQuit.getStatus() == PROCESSING) {
            SysUser sysUser = sysUserFeignService.queryUserById(userId);

            Set<Integer> integers = employeePositionService.queryUserIdByRoleId(new SysUserRoleEnum[]{ORGAN_MANAGER}, musicGroup.getOrganId());
            if (currentOperatorRoleIds == null || currentOperatorRoleIds.size() == 0) {
                integers.add(musicGroup.getEducationalTeacherId());
            }
            if (integers.size() > 0) {
                Map<Integer, String> receivers = new HashMap<>(integers.size());
                for (Integer integer : integers) {
                    receivers.put(integer, integer.toString());
                }
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.SYSTEM_PUSH_STUDENT_COMMIT_QUIT_MUSIC_APPLY, receivers, null, 0, null,
                        "SYSTEM", musicGroup.getName(), sysUser.getUsername());
            }
            Map<String, Object> memo = new HashMap<>(2);
            memo.put("Id", musicGroupQuit.getId());
            memo.put("type", "MUSICGROUP");
            sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                    JSONObject.toJSONString(memo), null, MessageTypeEnum.BACKSTAGE_STUDENT_APPLY_QUIT_GROUP, sysUser.getUsername());
        } else {
            musicGroupQuit.setStatus(reqMusicGroupQuit.getStatus());
            approveQuitMusicGroup(currentOperatorRoleIds, musicGroupQuit);
        }
        return true;
    }

    @Override
    public boolean cancelQuitMusicGroup(Integer userId, String musicGroupId, String reason) {
        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (musicGroupQuit == null) {
            throw new BizException("操作失败，没有查询到退团记录");
        }
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }
        if (musicGroupQuit.getStatus() != PROCESSING) {
            throw new BizException("当前状态下不能取消");
        }
        musicGroupQuit.setStatus(ApprovalStatus.CANCELED);
        musicGroupQuit.setReason(reason);
        musicGroupQuit.setQuitDate(new Date());
        musicGroupQuitDao.update(musicGroupQuit);

        Map<Integer, String> receivers = new HashMap<>(1);
        receivers.put(musicGroup.getEducationalTeacherId(), musicGroup.getEducationalTeacherId().toString());
        sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.SYSTEM_PUSH_STUDENT_REVOKE_QUIT_MUSIC_APPLY,
                receivers, null, 0, null, "SYSTEM", musicGroup.getName(), sysUser.getUsername());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean approveQuitMusicGroup(List<SysUserRoleEnum> currentOperatorRoleIds, MusicGroupQuit reqMusicGroupQuit) {
        Long id = reqMusicGroupQuit.getId();
        ApprovalStatus status = reqMusicGroupQuit.getStatus();
        String reason = reqMusicGroupQuit.getReason();
        Date visitDate = reqMusicGroupQuit.getVisitTime();
        MusicGroupReturnFeeDto returnFeeDto = reqMusicGroupQuit.getReturnFeeDto();

        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.get(id);
        if (musicGroupQuit == null) {
            throw new BizException("数据不存在");
        }

        Date date = new Date();

        //如果发起退团申请的是乐团主管
        if (!currentOperatorRoleIds.contains(SysUserRoleEnum.ORGAN_MANAGER) && currentOperatorRoleIds.contains(SysUserRoleEnum.EDUCATION)) {

            if (!StringUtils.equals(musicGroupQuit.getCurrentApproveRole(), SysUserRoleEnum.EDUCATION.ordinal() + 1 + "")) {
                throw new BizException("只有分部经理才能审核");
            }

            if (status == ApprovalStatus.APPROVED) {
                throw new BizException("只能分部经理操作退团");
            }
        }

        if (currentOperatorRoleIds.contains(SysUserRoleEnum.ORGAN_MANAGER) && !currentOperatorRoleIds.contains(SysUserRoleEnum.EDUCATION)) {
            if (!StringUtils.equals(musicGroupQuit.getCurrentApproveRole(), SysUserRoleEnum.ORGAN_MANAGER.ordinal() + 1 + "")) {
                throw new BizException("先需乐团主管审核");
            }
        }

        String musicGroupId = musicGroupQuit.getMusicGroupId();
        Integer userId = musicGroupQuit.getUserId();

        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }

        if (musicGroup.getStatus() == MusicGroupStatusEnum.CANCELED || musicGroup.getStatus() == MusicGroupStatusEnum.PAUSE) {
            throw new BizException("申请失败，乐团状态[已取消]或[已暂停]");
        }

        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("用户注册信息不存在");
        }

        StudentMusicGroupStatusEnum currentStudentMusicGroupStatus = studentRegistration.getMusicGroupStatus();
        if (currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.NORMAL && currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.APPLY) {
            throw new BizException("用户当前在团状态不能退团");
        }

        // 有进行中的课程不能退团
        List<CourseSchedule> courseScheduleList = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(),
                "UNDERWAY", userId);
        if (courseScheduleList != null && courseScheduleList.size() > 0) {
            throw new BizException("退团失败，存在[进行中]的课程");
        }

        boolean hasPaid = studentRegistration.getMusicGroupStatus().equals(StudentMusicGroupStatusEnum.NORMAL);

        musicGroupQuit.setStatus(status);
        musicGroupQuit.setReason(reason);
        musicGroupQuit.setQuitDate(date);
		musicGroupQuit.setReasonEnum(reqMusicGroupQuit.getReasonEnum());
		musicGroupQuit.setIsVisit(reqMusicGroupQuit.getIsVisit());
		musicGroupQuit.setVisitTime(reqMusicGroupQuit.getVisitTime());
		musicGroupQuit.setUserComment(reqMusicGroupQuit.getUserComment());


/*        if (visitDate != null) {
            musicGroupQuit.setVisitTime(visitDate);
            musicGroupQuit.setIsVisit(true);
        } else {
            musicGroupQuit.setIsVisit(false);
        }

        if (StringUtils.isBlank(musicGroupQuit.getUserComment())) {
            musicGroupQuit.setUserComment(reqMusicGroupQuit.getUserComment());
        }*/

        BigDecimal returnTotalFee = BigDecimal.ZERO;

        if (returnFeeDto == null) {
            returnFeeDto = new MusicGroupReturnFeeDto();
        }
        musicGroupQuit.setFeeJson(JsonUtil.toJSONString(returnFeeDto));
        if (returnFeeDto.getIsReturnAccessoriesFee()) {
            returnTotalFee = returnTotalFee.add(returnFeeDto.getAccessoriesFee());
        }
        if (returnFeeDto.getIsReturnCourseFee()) {
            returnTotalFee = returnTotalFee.add(returnFeeDto.getCourseFee());
        }
        if (returnFeeDto.getIsReturnMaintenanceFee()) {
            returnTotalFee = returnTotalFee.add(returnFeeDto.getMaintenanceFee());
        }
//        if (returnFeeDto.getIsReturnMemberFee()) {
//            returnTotalFee = returnTotalFee.add(returnFeeDto.getMemberFee());
//        }
        if (returnFeeDto.getIsReturnMusicalFee()) {
            returnTotalFee = returnTotalFee.add(returnFeeDto.getMusicalFee());
        }

        musicGroupQuit.setReturnTotalFee(returnTotalFee);

        if (status != ApprovalStatus.PROCESSING) {
            courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(musicGroupId), Arrays.asList(userId), GroupType.MUSIC);
        } else {
            //加一的原因是为了和positionId同步，枚举是从0开始
            musicGroupQuit.setCurrentApproveRole(ORGAN_MANAGER.ordinal() + 1 + "");
        }
        musicGroupQuitDao.update(musicGroupQuit);

        if (status == ApprovalStatus.APPROVED) {

            List<Integer> classGroupIdList = classGroupStudentMapperDao.queryClassGroupIdList(musicGroupId, userId, GroupType.MUSIC);
            //更新学员在班级的状态
            for (Integer classGroupId : classGroupIdList) {
                ClassGroup classGroup = classGroupService.get(classGroupId);
                if (classGroup.getType().equals(ClassGroupTypeEnum.MUSIC_NETWORK)) {
                    classGroupService.delSingle(classGroupId);
                } else {
                    classGroupStudentMapperService.delClassGroupStudent(userId, classGroupId, true);
                }
            }

            //删除续费周期
            musicGroupStudentFeeDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);
            // 退团
            BigDecimal surplusCourseFee = studentRegistration.getSurplusCourseFee();
            studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.QUIT);
            studentRegistration.setSurplusCourseFee(BigDecimal.ZERO);
            studentRegistration.setHasCloudTeacher(0);
            studentRegistration.setUpdateTime(date);
            studentRegistrationDao.update(studentRegistration);

            //删除进行中加学生，且在审批中或拒绝的缴费
            List<Long> paymentCalenderIdList = musicGroupPaymentCalenderDao.findStudentNoPaymentCalender(userId, musicGroupId);
            if (paymentCalenderIdList != null && paymentCalenderIdList.size() > 0) {
                musicGroupPaymentCalenderDao.delByIds(paymentCalenderIdList);
            }

            //查询未交费的项目
            List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = musicGroupPaymentCalenderDetailDao.queryNotPaymentStudentByUserIdAndMusicGroupId(userId, musicGroupId);

            for (MusicGroupPaymentCalenderDetail mgpcd : musicGroupPaymentCalenderDetailList) {
                MusicGroupPaymentCalender mgpc = musicGroupPaymentCalenderDao.get(mgpcd.getMusicGroupPaymentCalenderId());
                if (mgpc != null) {
                    if (mgpc.getPaymentType() == PaymentType.ADD_STUDENT) {
                        musicGroupPaymentCalenderDao.delete(mgpc.getId());
                    } else {
                        // 缴费项目预计人数减一
                        mgpc.setExpectNum(mgpc.getExpectNum() - 1);
                        mgpc.setUpdateTime(date);
                        musicGroupPaymentCalenderDao.update(mgpc);
                    }
                }
                musicGroupPaymentCalenderDetailDao.delete(mgpcd.getId());
            }
            //删除用户购买的课程记录
            musicGroupPaymentStudentCourseDetailDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

            BigDecimal amount = new BigDecimal(0);

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

            if (studentRegistration.getMusicGroupPaymentCalenderId() == null) {
                if (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.NORMAL || (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.APPLY
                        && studentRegistration.getPaymentStatus() == PaymentStatusEnum.YES)) {
                    studentPaymentOrderList = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
                }

            } else {
                studentPaymentOrderList = studentPaymentOrderService.queryByBatchNo(userId, studentRegistration.getMusicGroupPaymentCalenderId() + "",
                        DealStatusEnum.SUCCESS);
            }

            // 缴费人数更新
            MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
            if (hasPaid && musicGroupSubjectPlan != null) {
                musicGroupSubjectPlan.setUpdateTime(date);
                //减去缴费人数（器乐收费，0元时不减缴费人数）
                if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {

                    for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList) {
                        if (studentPaymentOrder != null && "200".equals(studentPaymentOrder.getPaymentAccountNo())) {
                            musicGroupSubjectPlan.setPaidZeroNum(musicGroupSubjectPlan.getPaidZeroNum() - 1);
                            musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                            break;
                        } else if (studentPaymentOrder != null && studentPaymentOrder.getPaymentAccountNo() == null) {
                            musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                            break;
                        }
                    }

                } else {
                    musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                }
                musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
            }

            if (MusicGroupStatusEnum.PROGRESS.equals(musicGroup.getStatus())) {
                //统计变更学员数
                groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, new ArrayList<>(Arrays.asList(userId)));

            }
            if (returnFeeDto.getIsReturnCourseFee()) {
                // 退课程费用
                amount = amount.add(surplusCourseFee);
            }

            if (studentPaymentOrderList.size() > 0) {

                List<Long> paymentOrderIdList = studentPaymentOrderList.stream().map(t -> t.getId()).collect(Collectors.toList());
                //获取最近的一笔报名订单编号
                Long minPaymentOrderId = Collections.min(paymentOrderIdList);
                List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.getWithIds(paymentOrderIdList);

                SubjectChange studentLastChange = null;
                //如果退乐器和辅件，那么查找最近的一笔声部更换订单
                if (returnFeeDto.getIsReturnMusicalFee() || returnFeeDto.getIsReturnAccessoriesFee()) {
                    studentLastChange = subjectChangeDao.getStudentLastChange(userId, musicGroupId);
                }

                //如果声部更换过
                if (studentLastChange != null && (studentLastChange.getOriginalOrderId() == null || minPaymentOrderId <= studentLastChange.getOriginalOrderId())) {
                    //退乐器的同时，退乐保
                    if (returnFeeDto.getIsReturnMusicalFee()) {
                        //乐器金额是否正确
                        amount = amount.add(studentLastChange.getChangeMusicalPrice());
                        StudentInstrument studentMaintenance = studentInstrumentDao.getByOrderId(studentLastChange.getOrderId().longValue());
                        if (studentMaintenance != null) {
                            studentMaintenance.setDelFlag(1);
                            studentInstrumentDao.update(studentMaintenance);
                        }
                    }
                    //退辅件
                    if (returnFeeDto.getIsReturnAccessoriesFee()) {
                        amount = amount.add(studentLastChange.getChangeAccessoriesPrice());
                    }
                } else {
                    for (StudentPaymentOrderDetail detail : orderDetailList) {

                        // 退乐器费用
                        if (returnFeeDto.getIsReturnMusicalFee() && detail.getType() == MUSICAL) {
                            amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());

                            StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
                            if (studentMaintenance != null) {
                                studentMaintenance.setDelFlag(1);
                                studentInstrumentDao.update(studentMaintenance);
                            }
                        }

                        // 退教辅费用
                        if (returnFeeDto.getIsReturnAccessoriesFee()
                                && (detail.getType() == ACCESSORIES || detail.getType() == TEACHING)) {
                            amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
                        }
                    }
                }

                //退乐保费用
                if (returnFeeDto.getIsReturnMaintenanceFee()) {
                    //是否有乐保、乐保是否退过、金额是否正确
                    StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
                    if (returnFeeDto.getMaintenanceFee().compareTo(BigDecimal.ZERO) > 0) {
                        if (studentMaintenance == null) {
                            throw new BizException("学生没有有效期内的乐保，不能退乐保费用");
                        }
                        //金额是否正确
                        List<StudentPaymentOrderDetail> orderDetails = orderDetailList.stream().filter(e -> e.getType() == MAINTENANCE).collect(Collectors.toList());
                        BigDecimal maintenanceFee = BigDecimal.ZERO;
                        if(orderDetails != null && orderDetails.size() > 0){
                            maintenanceFee = orderDetails.stream().map(e -> e.getPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
                        }
                        if(returnFeeDto.getMaintenanceFee().compareTo(maintenanceFee) > 0){
                            throw new BizException("乐保退费金额异常");
                        }
                    }
                    amount = amount.add(returnFeeDto.getMaintenanceFee());
                    if (returnFeeDto.getMaintenanceFee().compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
                        studentMaintenance.setStatus(0);
                        studentMaintenance.setStartTime(null);
                        studentMaintenance.setEndTime(null);
                        studentInstrumentDao.update(studentMaintenance);
                    }
                }
            }

            if (returnTotalFee.doubleValue() > 0) {
                SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
                sysUserCashAccountLog.setGroupType(GroupType.MUSIC);
                sysUserCashAccountLog.setUserId(userId);
                sysUserCashAccountLog.setOrganId(musicGroup.getOrganId());
                sysUserCashAccountLog.setGroupId(musicGroupId);
                sysUserCashAccountLog.setAmount(returnTotalFee);
                sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.MUSIC);
                sysUserCashAccountLog.setComment("退出乐团");
                sysUserCashAccountLogDao.insert(sysUserCashAccountLog);
                // 增加交易流水
//                sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",
//                        PlatformCashAccountDetailTypeEnum.REFUNDS, null, SUCCESS, "退出乐团", null);
            }
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean directQuitMusicGroup(MusicGroupQuitDto musicGroupQuitDto) {
		Integer userId = musicGroupQuitDto.getUserId();
		String musicGroupId = musicGroupQuitDto.getMusicGroupId();
		SysUser sysUser = sysUserFeignService.queryUserById(userId);
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团不存在");
        }
        if (musicGroup.getStatus() == MusicGroupStatusEnum.CANCELED || musicGroup.getStatus() == MusicGroupStatusEnum.PAUSE) {
            throw new BizException("退团失败，乐团状态[已取消]或[已暂停]");
        }

        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("用户注册信息不存在");
        }

        StudentMusicGroupStatusEnum currentStudentMusicGroupStatus = studentRegistration.getMusicGroupStatus();
        if (currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.NORMAL && currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.APPLY) {
            throw new BizException("用户当前在团状态不能退团");
        }

        // 有进行中的课程不能退团
        List<CourseSchedule> courseScheduleList = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(),
                "UNDERWAY", userId);
        if (courseScheduleList != null && courseScheduleList.size() > 0) {
            throw new BizException("退团失败，存在[进行中]的课程");
        }

        boolean hasPaid = studentRegistration.getMusicGroupStatus().equals(StudentMusicGroupStatusEnum.NORMAL);

        //如果是会员团，并且有预排课计划
        MusicGroupSchoolTermCourseDetail termCourseDetail = musicGroupSchoolTermCourseDetailDao.findByCourseDateAndMusicGroupId(musicGroupId, null, 0);
        if (termCourseDetail != null) {
            //是否已经预排部分课程
            List<CourseSchedule> courseSchedules = courseScheduleDao.queryPreCourseListByMusicGroupId(musicGroup.getId());
            if (courseSchedules.size() > 0) {
                throw new BizException("退团失败：该乐团存在预排课课程，请优先完成预排课");
            } else {
                musicGroupSchoolTermStudentCourseDetailDao.deleteByDetailId(termCourseDetail.getId(), userId);
            }
        }

        courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(musicGroupId), Arrays.asList(userId), GroupType.MUSIC);

        Date date = new Date();

        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (musicGroupQuit != null && musicGroupQuit.getStatus() == PROCESSING) {
            musicGroupQuit.setStatus(ApprovalStatus.APPROVED);
            musicGroupQuit.setReason(musicGroupQuitDto.getReason());
			musicGroupQuit.setReasonEnum(musicGroupQuitDto.getReasonEnum());
            musicGroupQuit.setQuitDate(date);
            musicGroupQuitDao.update(musicGroupQuit);
        } else {
            musicGroupQuit = new MusicGroupQuit();
            musicGroupQuit.setCreateTime(date);
            musicGroupQuit.setJoinDate(studentRegistration.getCreateTime());
            musicGroupQuit.setMusicGroupId(musicGroupId);
            musicGroupQuit.setUserId(sysUser.getId());
            musicGroupQuit.setStatus(ApprovalStatus.APPROVED);
			musicGroupQuit.setReason(musicGroupQuitDto.getReason());
			musicGroupQuit.setReasonEnum(musicGroupQuitDto.getReasonEnum());
            musicGroupQuit.setQuitDate(date);
            musicGroupQuitDao.insert(musicGroupQuit);
        }

        List<Integer> classGroupIdList = classGroupStudentMapperDao.queryClassGroupIdList(musicGroupId, userId, GroupType.MUSIC);
        for (Integer classGroupId : classGroupIdList) {
            ClassGroup classGroup = classGroupService.get(classGroupId);
            if (classGroup.getType().equals(ClassGroupTypeEnum.MUSIC_NETWORK)) {
                classGroupService.delSingle(classGroupId);
            } else {
                classGroupStudentMapperService.delClassGroupStudent(userId, classGroupId, true);
            }
        }

        //删除续费周期
        musicGroupStudentFeeDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

        BigDecimal surplusCourseFee = studentRegistration.getSurplusCourseFee();
        // 退团
        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.QUIT);
        studentRegistration.setSurplusCourseFee(BigDecimal.ZERO);
        studentRegistration.setHasCloudTeacher(0);
        studentRegistration.setUpdateTime(date);
        studentRegistrationDao.update(studentRegistration);

        //删除进行中加学生，且在审批中或拒绝的缴费
        List<Long> paymentCalenderIdList = musicGroupPaymentCalenderDao.findStudentNoPaymentCalender(userId, musicGroupId);
        if (paymentCalenderIdList != null && paymentCalenderIdList.size() > 0) {
            musicGroupPaymentCalenderDao.delByIds(paymentCalenderIdList);
        }

        //查询未交费的项目
        List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = musicGroupPaymentCalenderDetailDao.queryNotPaymentStudentByUserIdAndMusicGroupId(userId, musicGroupId);

        for (MusicGroupPaymentCalenderDetail mgpcd : musicGroupPaymentCalenderDetailList) {
            MusicGroupPaymentCalender mgpc = musicGroupPaymentCalenderDao.get(mgpcd.getMusicGroupPaymentCalenderId());
            if (mgpc != null) {
                if (mgpc.getPaymentType() == PaymentType.ADD_STUDENT) {
                    musicGroupPaymentCalenderDao.delete(mgpc.getId());
                } else {
                    // 缴费项目预计人数减一
                    mgpc.setExpectNum(mgpc.getExpectNum() - 1);
                    mgpc.setUpdateTime(date);
                    musicGroupPaymentCalenderDao.update(mgpc);
                }
            }
            musicGroupPaymentCalenderDetailDao.delete(mgpcd.getId());
        }
        //删除用户购买的课程记录
        musicGroupPaymentStudentCourseDetailDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

        BigDecimal amount = new BigDecimal(0);

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

        if (studentRegistration.getMusicGroupPaymentCalenderId() == null) {
            if (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.NORMAL || (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.APPLY && studentRegistration.getPaymentStatus() == PaymentStatusEnum.YES)) {
                studentPaymentOrderList = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
            }

        } else {
            studentPaymentOrderList = studentPaymentOrderService.queryByBatchNo(sysUser.getId(), studentRegistration.getMusicGroupPaymentCalenderId() + "",
                    DealStatusEnum.SUCCESS);
        }

        // 判断乐器是否是租赁
        MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
        if (hasPaid && musicGroupSubjectPlan != null) {
            musicGroupSubjectPlan.setUpdateTime(date);
            //减去缴费人数（器乐收费，0元时不减缴费人数）
            if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {

                for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList) {
                    if (studentPaymentOrder != null && studentPaymentOrder.getPaymentAccountNo() != null && studentPaymentOrder.getPaymentAccountNo().equals("200")) {
                        musicGroupSubjectPlan.setPaidZeroNum(musicGroupSubjectPlan.getPaidZeroNum() - 1);
                        musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                        break;
                    } else if (studentPaymentOrder != null && studentPaymentOrder.getPaymentAccountNo() == null) {
                        musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                        break;
                    }
                }
            } else {
                musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
            }
            musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
        }

        if (MusicGroupStatusEnum.PROGRESS.equals(musicGroup.getStatus())) {
            //统计变更学员数
            groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, new ArrayList<>(Arrays.asList(userId)));
        }
        if (musicGroupQuitDto.getIsRefundCourseFee()) {
            // 退课程费用
            amount = amount.add(surplusCourseFee);
        }

        if (studentPaymentOrderList.size() > 0) {

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

            Long minPaymentOrderId = Collections.min(paymentOrderIdList);

            List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.getWithIds(paymentOrderIdList);

            SubjectChange studentLastChange = null;
            if (musicGroupQuitDto.getIsRefundInstrumentFee() || musicGroupQuitDto.getIsRefundTeachingAssistantsFee()) {
                studentLastChange = subjectChangeDao.getStudentLastChange(userId, musicGroupId);
            }

            if (studentLastChange != null && minPaymentOrderId <= studentLastChange.getOriginalOrderId()) {
                if (musicGroupQuitDto.getIsRefundInstrumentFee()) {
                    amount = amount.add(studentLastChange.getChangeMusicalPrice());

                    StudentInstrument studentMaintenance = studentInstrumentDao.getByOrderId(studentLastChange.getOrderId().longValue());
                    if (studentMaintenance != null) {
                        studentMaintenance.setDelFlag(1);
                        studentInstrumentDao.update(studentMaintenance);
                    }
                }

                if (musicGroupQuitDto.getIsRefundTeachingAssistantsFee()) {
                    amount = amount.add(studentLastChange.getChangeAccessoriesPrice());
                }
            } else {
                for (StudentPaymentOrderDetail detail : orderDetailList) {

                    // 退乐器费用
                    if (musicGroupQuitDto.getIsRefundInstrumentFee() && detail.getType() == MUSICAL) {
                        amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());

                        StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
                        if (studentMaintenance != null) {
                            studentMaintenance.setDelFlag(1);
                            studentInstrumentDao.update(studentMaintenance);
                        }
                    }

                    // 退教辅费用
                    if (musicGroupQuitDto.getIsRefundTeachingAssistantsFee()
                            && (detail.getType() == ACCESSORIES || detail.getType() == TEACHING)) {
                        amount = amount.add(detail.getPrice()).subtract(detail.getRemitFee());
                    }
                }
            }

        }

        //退乐保费用
        if (musicGroupQuitDto.getMaintenanceFee() != null) {
            StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
            if (musicGroupQuitDto.getMaintenanceFee().compareTo(BigDecimal.ZERO) > 0) {
                if (studentMaintenance == null) {
                    throw new BizException("学生没有有效期内的乐保，不能退乐保费用");
                }
            }
            amount = amount.add(musicGroupQuitDto.getMaintenanceFee());
            if (musicGroupQuitDto.getMaintenanceFee().compareTo(BigDecimal.ZERO) > 0 && studentMaintenance != null) {
                studentMaintenance.setStatus(0);
                studentMaintenance.setStartTime(null);
                studentMaintenance.setEndTime(null);
                studentInstrumentDao.update(studentMaintenance);
            }
        }

        if (amount.doubleValue() > 0) {
            //这个接口没有退费的操作了
//            SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
//            sysUserCashAccountLog.setGroupType(GroupType.MUSIC);
//            sysUserCashAccountLog.setUserId(userId);
//            sysUserCashAccountLog.setOrganId(musicGroup.getOrganId());
//            sysUserCashAccountLog.setGroupId(musicGroupId);
//            sysUserCashAccountLog.setAmount(amount);
//            sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.MUSIC);
//            sysUserCashAccountLog.setComment("退出乐团");
//            sysUserCashAccountLogDao.insert(sysUserCashAccountLog);
            // 增加交易流水
//            sysUserCashAccountDetailService.addCashAccountDetail(userId, amount, SysUserCashAccountDetailService.MUSIC_GROUP + musicGroupId, "",
//                    PlatformCashAccountDetailTypeEnum.REFUNDS, null, SUCCESS, "退出乐团", null);
        }

        return true;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void directQuitMusicGroupOa(FinancialExpenditure financialExpenditure) {
        String musicGroupId = financialExpenditure.getMusicGroupId();
        Integer userId = financialExpenditure.getStudentId();
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            return;
        }
        financialExpenditure.setCooperationOrganId(musicGroup.getCooperationOrganId());
        if (musicGroup.getStatus() == MusicGroupStatusEnum.CANCELED || musicGroup.getStatus() == MusicGroupStatusEnum.PAUSE) {
            return;
        }

        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            return;
        }

        StudentMusicGroupStatusEnum currentStudentMusicGroupStatus = studentRegistration.getMusicGroupStatus();
        if (currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.NORMAL && currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.APPLY) {
            return;
        }

        // 有进行中的课程不能退团
        List<CourseSchedule> courseScheduleList = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(),
                "UNDERWAY", userId);
        if (courseScheduleList != null && courseScheduleList.size() > 0) {
            return;
        }

        boolean hasPaid = studentRegistration.getMusicGroupStatus().equals(StudentMusicGroupStatusEnum.NORMAL);

        //如果是会员团，并且有预排课计划
        MusicGroupSchoolTermCourseDetail termCourseDetail = musicGroupSchoolTermCourseDetailDao.findByCourseDateAndMusicGroupId(musicGroupId, null, 0);
        if (termCourseDetail != null) {
            //是否已经预排部分课程
            List<CourseSchedule> courseSchedules = courseScheduleDao.queryPreCourseListByMusicGroupId(musicGroup.getId());
            if (courseSchedules.size() > 0) {
                return;
            } else {
                musicGroupSchoolTermStudentCourseDetailDao.deleteByDetailId(termCourseDetail.getId(), userId);
            }
        }

        courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(musicGroupId), Arrays.asList(userId), GroupType.MUSIC);

        Date date = new Date();

        MusicGroupQuit musicGroupQuit = new MusicGroupQuit();
        musicGroupQuit.setCreateTime(date);
        musicGroupQuit.setJoinDate(studentRegistration.getCreateTime());
        musicGroupQuit.setMusicGroupId(musicGroupId);
        musicGroupQuit.setUserId(userId);
        musicGroupQuit.setStatus(ApprovalStatus.APPROVED);
        musicGroupQuit.setReason(financialExpenditure.getCause());
        musicGroupQuit.setQuitDate(date);
        musicGroupQuitDao.insert(musicGroupQuit);

        List<Integer> classGroupIdList = classGroupStudentMapperDao.queryClassGroupIdList(musicGroupId, userId, GroupType.MUSIC);
        for (Integer classGroupId : classGroupIdList) {
            ClassGroup classGroup = classGroupService.get(classGroupId);
            if (classGroup.getType().equals(ClassGroupTypeEnum.MUSIC_NETWORK)) {
                classGroupService.delSingle(classGroupId);
            } else {
                classGroupStudentMapperService.delClassGroupStudent(userId, classGroupId, true);
            }
        }

        //删除续费周期
        musicGroupStudentFeeDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

        // 退团
        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.QUIT);
        studentRegistration.setSurplusCourseFee(BigDecimal.ZERO);
        studentRegistration.setHasCloudTeacher(0);
        studentRegistration.setUpdateTime(date);
        studentRegistrationDao.update(studentRegistration);

        //删除进行中加学生，且在审批中或拒绝的缴费
        List<Long> paymentCalenderIdList = musicGroupPaymentCalenderDao.findStudentNoPaymentCalender(userId, musicGroupId);
        if (paymentCalenderIdList != null && paymentCalenderIdList.size() > 0) {
            musicGroupPaymentCalenderDao.delByIds(paymentCalenderIdList);
        }

        //查询未交费的项目
        List<MusicGroupPaymentCalenderDetail> musicGroupPaymentCalenderDetailList = musicGroupPaymentCalenderDetailDao.queryNotPaymentStudentByUserIdAndMusicGroupId(userId, musicGroupId);

        for (MusicGroupPaymentCalenderDetail mgpcd : musicGroupPaymentCalenderDetailList) {
            MusicGroupPaymentCalender mgpc = musicGroupPaymentCalenderDao.get(mgpcd.getMusicGroupPaymentCalenderId());
            if (mgpc != null) {
                if (mgpc.getPaymentType() == PaymentType.ADD_STUDENT) {
                    musicGroupPaymentCalenderDao.delete(mgpc.getId());
                } else {
                    // 缴费项目预计人数减一
                    mgpc.setExpectNum(mgpc.getExpectNum() - 1);
                    mgpc.setUpdateTime(date);
                    musicGroupPaymentCalenderDao.update(mgpc);
                }
            }
            musicGroupPaymentCalenderDetailDao.delete(mgpcd.getId());
        }
        //删除用户购买的课程记录
        musicGroupPaymentStudentCourseDetailDao.deleteByUserIdAndMusicGroupId(userId, musicGroupId);

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

        if (studentRegistration.getMusicGroupPaymentCalenderId() == null) {
            if (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.NORMAL || (currentStudentMusicGroupStatus == StudentMusicGroupStatusEnum.APPLY && studentRegistration.getPaymentStatus() == PaymentStatusEnum.YES)) {
                studentPaymentOrderList = studentPaymentOrderService.findMusicGroupApplyOrderByStatus(userId, musicGroupId, SUCCESS);
            }

        } else {
            studentPaymentOrderList = studentPaymentOrderService.queryByBatchNo(userId, studentRegistration.getMusicGroupPaymentCalenderId() + "",
                    DealStatusEnum.SUCCESS);
        }

        // 判断乐器是否是租赁
        MusicGroupSubjectPlan musicGroupSubjectPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
        if (hasPaid && musicGroupSubjectPlan != null) {
            musicGroupSubjectPlan.setUpdateTime(date);
            //减去缴费人数（器乐收费，0元时不减缴费人数）
            if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {

                for (StudentPaymentOrder studentPaymentOrder : studentPaymentOrderList) {
                    if (studentPaymentOrder != null && studentPaymentOrder.getPaymentAccountNo() != null && studentPaymentOrder.getPaymentAccountNo().equals("200")) {
                        musicGroupSubjectPlan.setPaidZeroNum(musicGroupSubjectPlan.getPaidZeroNum() - 1);
                        musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                        break;
                    } else if (studentPaymentOrder != null && studentPaymentOrder.getPaymentAccountNo() == null) {
                        musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
                        break;
                    }
                }
            } else {
                musicGroupSubjectPlan.setPaidStudentNum(musicGroupSubjectPlan.getPaidStudentNum() - 1);
            }
            musicGroupSubjectPlanDao.update(musicGroupSubjectPlan);
        }

        if (MusicGroupStatusEnum.PROGRESS.equals(musicGroup.getStatus())) {
            //统计变更学员数
            groupEventSource.musicGroupStudentChangeEvent(musicGroupId, StudentMusicGroupStatusEnum.QUIT, new ArrayList<>(Arrays.asList(userId)));
        }

        if (studentPaymentOrderList.size() > 0) {

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

            Long minPaymentOrderId = Collections.min(paymentOrderIdList);

            List<StudentPaymentOrderDetail> orderDetailList = studentPaymentOrderDetailDao.getWithIds(paymentOrderIdList);

            SubjectChange studentLastChange = null;
            if (financialExpenditure.isRefundInstrumentFeeFlag() || financialExpenditure.isRefundTeachingAssistantsFeeFlag()) {
                studentLastChange = subjectChangeDao.getStudentLastChange(userId, musicGroupId);
            }

            if (studentLastChange != null && minPaymentOrderId <= studentLastChange.getOriginalOrderId()) {
                if (financialExpenditure.isRefundInstrumentFeeFlag()) {
                    StudentInstrument studentMaintenance = studentInstrumentDao.getByOrderId(studentLastChange.getOrderId().longValue());
                    if (studentMaintenance != null) {
                        studentMaintenance.setDelFlag(1);
                        studentInstrumentDao.update(studentMaintenance);
                    }
                }
            } else {
                for (StudentPaymentOrderDetail detail : orderDetailList) {
                    // 退乐器费用
                    if (financialExpenditure.isRefundInstrumentFeeFlag() && detail.getType() == MUSICAL) {
                        StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
                        if (studentMaintenance != null) {
                            studentMaintenance.setDelFlag(1);
                            studentInstrumentDao.update(studentMaintenance);
                        }
                    }
                }
            }

        }
        //退乐保费用
        if (financialExpenditure.isMaintenanceFeeFlag()) {
            StudentInstrument studentMaintenance = studentInstrumentDao.getStudentMaintenance(userId, musicGroupId);
            if (studentMaintenance != null) {
                studentMaintenance.setStatus(0);
                studentMaintenance.setStartTime(null);
                studentMaintenance.setEndTime(null);
                studentInstrumentDao.update(studentMaintenance);
            }
        }

        if (financialExpenditure.getAmount().doubleValue() > 0) {
            //这个接口没有退费的操作了
            SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
            sysUserCashAccountLog.setGroupType(GroupType.MUSIC);
            sysUserCashAccountLog.setUserId(userId);
            sysUserCashAccountLog.setOrganId(musicGroup.getOrganId());
            sysUserCashAccountLog.setGroupId(musicGroupId);
            sysUserCashAccountLog.setAmount(financialExpenditure.getAmount());
            sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.MUSIC);
            sysUserCashAccountLog.setComment("OA审批退团");
            sysUserCashAccountLogDao.insert(sysUserCashAccountLog);
        }
    }

    @Override
    public void checkDirectQuitMusicGroupOa(FinancialExpenditure financialExpenditure) {
        Integer userId = financialExpenditure.getStudentId();
        String musicGroupId = financialExpenditure.getMusicGroupId();
        SysUser user = teacherDao.getUser(userId);
        if (user == null) {
            throw new BizException("学员 {} 信息不存在", userId);
        }
        Student student = studentService.get(userId);
        if (student == null) {
            throw new BizException("学员 {} 信息不存在", userId);
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团 {} 不存在", musicGroupId);
        }
        financialExpenditure.setCooperationOrganId(musicGroup.getCooperationOrganId());
        if (musicGroup.getStatus() == MusicGroupStatusEnum.CANCELED || musicGroup.getStatus() == MusicGroupStatusEnum.PAUSE) {
            throw new BizException("退团失败，乐团 {} {} 状态[已取消]或[已暂停]", musicGroupId, musicGroup.getName());
        }

        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);
        if (studentRegistration == null) {
            throw new BizException("学员 {} {} 注册信息不存在", userId, user.getUsername());
        }

        StudentMusicGroupStatusEnum currentStudentMusicGroupStatus = studentRegistration.getMusicGroupStatus();
        if (currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.NORMAL && currentStudentMusicGroupStatus != StudentMusicGroupStatusEnum.APPLY) {
            throw new BizException("学员 {} {} 当前在团状态不能退团", userId, user.getUsername());
        }

        // 有进行中的课程不能退团
        List<CourseSchedule> courseScheduleList = courseScheduleDao.findMusicGroupCourseSchedulesWithStudent(musicGroupId, GroupType.MUSIC.getCode(),
                "UNDERWAY", userId);
        if (courseScheduleList != null && courseScheduleList.size() > 0) {
            throw new BizException("学员 {} {} 存在[进行中]的课程", userId, user.getUsername());
        }

        //如果是会员团，并且有预排课计划
        MusicGroupSchoolTermCourseDetail termCourseDetail = musicGroupSchoolTermCourseDetailDao.findByCourseDateAndMusicGroupId(musicGroupId, null, 0);
        if (termCourseDetail != null) {
            //是否已经预排部分课程
            List<CourseSchedule> courseSchedules = courseScheduleDao.queryPreCourseListByMusicGroupId(musicGroup.getId());
            if (courseSchedules.size() > 0) {
                throw new BizException("乐团 {} {} 存在预排课课程，请优先完成预排课", musicGroupId, musicGroup.getName());
            }
        }
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean renewForCallback(StudentPaymentOrder studentPaymentOrder) throws IOException {
        int updateNum = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateNum <= 0) {
            throw new BizException("订单更新失败");
        }
        Integer userId = studentPaymentOrder.getUserId();
        String musicGroupId = studentPaymentOrder.getMusicGroupId();

        Date date = new Date();
        StudentRegistration studentRegistration = studentRegistrationDao.queryByUserIdAndMusicGroupId(userId, musicGroupId);

        if (studentPaymentOrder.getStatus() == SUCCESS) {
            //当前乐团报名是否赠送乐团网管课
//            MusicGroupStudentFee musicGroupStudentFee = musicGroupPaymentCalenderService.updateCalender(calenderDetail.getId(), studentRegistration.getUserId());
//            if (musicGroupStudentFee != null) {
//                musicGroupStudentFee.setUpdateTime(date);
//                musicGroupStudentFee.setLatestPaidTime(date);
//                musicGroupStudentFee.setPaymentStatus(PaymentStatus.PAID_COMPLETED);
//                musicGroupStudentFee.setTemporaryCourseFee(new BigDecimal(0));
//                musicGroupStudentFeeDao.update(musicGroupStudentFee);
//            }
            //如果是进行中加学员
            MusicGroupPaymentCalender paymentCalender = musicGroupPaymentCalenderDao.get(studentPaymentOrder.getCalenderId());
            if (paymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.ADD_STUDENT) {
                studentRegistration.setPaymentStatus(YES);
                studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
                studentRegistration.setMusicGroupPaymentCalenderId(paymentCalender.getId());
                studentRegistrationDao.update(studentRegistration);
                //统计变更学员数
                groupEventSource.musicGroupStudentChangeEvent(studentRegistration.getMusicGroupId(), StudentMusicGroupStatusEnum.NORMAL, new ArrayList<>(Arrays.asList(userId)));
            }

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

            //插入交易明细
            SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            //充值
            SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
            rechargeDetail.setAmount(amount);
            rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
            rechargeDetail.setComment("缴费前充值");
            rechargeDetail.setCreateTime(date);
            rechargeDetail.setStatus(SUCCESS);
            rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
            rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
            rechargeDetail.setUpdateTime(date);
            rechargeDetail.setUserId(userId);
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
            rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
            sysUserCashAccountDetailService.insert(rechargeDetail);
            //缴费
            SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
            paymentDetail.setAmount(amount.negate());
            paymentDetail.setBalance(cashAccount.getBalance());
            paymentDetail.setComment("续费");
            paymentDetail.setCreateTime(date);
            paymentDetail.setStatus(SUCCESS);
            paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
            paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
            paymentDetail.setUpdateTime(date);
            paymentDetail.setUserId(userId);
            paymentDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            sysUserCashAccountDetailService.insert(paymentDetail);

            try {
                contractService.transferProduceContract(userId, musicGroupId, null);
            } catch (Exception e) {
                logger.error("产品协议生成失败", e);
            }
            if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
                Map<Integer, String> yimei = new HashMap<>(1);
                Map<Integer, String> push = new HashMap<>(1);
                push.put(userId, userId.toString());
                yimei.put(userId, studentRegistration.getParentsPhone());
                // 发送续费结果通知
                sysMessageService.batchSendMessage(MessageSender.JIGUANG, MessageTypeEnum.STUDENT_SMS_PUSH_MUSIC_GROUP_RENEW_SUCCESS, push, null, 0, "1", "STUDENT",
                        studentRegistration.getName(), studentPaymentOrder.getActualAmount());
                sysMessageService.batchSendMessage(MessageSender.AWSMS, MessageTypeEnum.STUDENT_SMS_PUSH_MUSIC_GROUP_RENEW_SUCCESS, yimei, null, 0, "1", "",
                        studentRegistration.getName(), studentPaymentOrder.getActualAmount());
            }
            return true;
        } else {
            //更新学生的缴费记录状态
            MusicGroupPaymentCalenderDetail calenderDetail = musicGroupPaymentCalenderDetailDao.findByOrderId(studentPaymentOrder.getId());
            calenderDetail.setPaymentStatus(MusicGroupStudentFee.PaymentStatus.NON_PAYMENT);
            calenderDetail.setUpdateTime(date);
            musicGroupPaymentCalenderDetailDao.update(calenderDetail);
            sysCouponCodeService.quit(studentPaymentOrder.getCouponCodeId());
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().doubleValue() > 0) {
                sysUserCashAccountService.updateBalance(userId, studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS,
                        "乐团续费失败");
            }
        }
        return false;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean updateTeacherCoursesSalary(Long courseScheduleId, Integer teacherId, BigDecimal salary, BigDecimal subsidy, String scope) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        CourseSchedule courseSchedule = courseScheduleDao.get(courseScheduleId);
        if (courseSchedule == null) {
            throw new BizException("课程信息不存在");
        }

        if ("all".equals(scope)) {
            Integer classGrpupId = courseSchedule.getClassGroupId();
            String startDateTime = sdf_ymd.format(courseSchedule.getClassDate()) + " " + sdf_hms.format(courseSchedule.getStartClassTime());
            // 未结算的课酬都修改
            courseScheduleTeacherSalaryDao.batchUpdateWages(classGrpupId, teacherId, salary, subsidy, startDateTime);
        } else {
            CourseScheduleTeacherSalary courseScheduleTeacherSalary = courseScheduleTeacherSalaryDao.queryByCourseScheduleIdAndUserId(courseScheduleId,
                    teacherId);
            if (courseScheduleTeacherSalary == null) {
                throw new BizException("课程结算信息不存在");
            }
            // 判断当前课程是否结算
            if (courseScheduleTeacherSalary.getSettlementTime() != null) {
                throw new BizException("课程已结算");
            }
            if (Objects.nonNull(salary)) {
                courseScheduleTeacherSalary.setExpectSalary(salary);
            }
            courseScheduleTeacherSalary.setSubsidy(subsidy);
            courseScheduleTeacherSalary.setUpdateTime(new Date());
            if (TeachTypeEnum.BISHOP.equals(courseScheduleTeacherSalary.getTeacherRole())) {
                courseScheduleTeacherSalary.setEnableChangeSalary(false);
            } else {
                courseScheduleTeacherSalary.setEnableChangeSalary(true);
            }
            courseScheduleTeacherSalaryDao.update(courseScheduleTeacherSalary);
        }
        return true;
    }

    @Override
    public PageInfo<MusicGroup> queryMusicGroupPage(MusicGroupQueryInfo queryInfo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("获取用户信息失败");
        }
        //查询有剩余排课时长的乐团
        if("MUSIC_GROUP_HAS_COURSE_TIMES".equals(queryInfo.getSearchType())){
            List<String> musicGroupIds = musicGroupDao.queryHasSubCourseTimes(queryInfo.getOrganId(),queryInfo.getTenantId());
            if(musicGroupIds == null || musicGroupIds.size() == 0){
                return new PageInfo<>();
            }
            queryInfo.setMusicGroupIds(musicGroupIds);
        }
        PageInfo<MusicGroup> musicGroupPageInfo = queryPage(queryInfo);
        List<MusicGroup> musicGroupList = musicGroupPageInfo.getRows();

        if (musicGroupList == null || musicGroupList.size() == 0) {
            return musicGroupPageInfo;
        }

        // 获取教务老师编号列表
        Set<Integer> educationalTeacherIds = musicGroupList.stream().map(e -> e.getEducationalTeacherId()).collect(Collectors.toSet());
        Map<Integer, String> educationalTeacherNameMap = MapUtil.convertMybatisMap(teacherDao.queryNameByIds(StringUtils.join(educationalTeacherIds, ",")));

        // 获取运营主管编号列表
        //Set<Integer> teamTeacherIds = musicGroupList.stream().map(e -> e.getTeamTeacherId()).collect(Collectors.toSet());
        //Map<Integer, String> teamTeacherNameMap = MapUtil.convertMybatisMap(teacherDao.queryNameByIds(StringUtils.join(teamTeacherIds, ",")));

        // 获取乐队指导编号列表
        Set<Integer> directorUserIds = musicGroupList.stream().map(e -> e.getDirectorUserId()).collect(Collectors.toSet());
        directorUserIds.removeAll(Collections.singleton(null));
        Map<Integer, String> directorUserNameMap = new HashMap<>();
        if (directorUserIds.size() > 0) {
            List<Map<Integer, String>> repairUserNames = teacherDao.queryNameByIds(StringUtils.join(directorUserIds, ","));
            directorUserNameMap = MapUtil.convertMybatisMap(repairUserNames);
        }

        // 获取维修技师编号列表
        Set<Integer> repairUserIds = musicGroupList.stream().map(e -> e.getRepairUserId()).collect(Collectors.toSet());
        repairUserIds.removeAll(Collections.singleton(null));
        Map<Integer, String> repairUserNameMap = new HashMap<>();
        if (repairUserIds.size() > 0) {
            List<Map<Integer, String>> repairUserNames = teacherDao.queryNameByIds(StringUtils.join(repairUserIds, ","));
            repairUserNameMap = MapUtil.convertMybatisMap(repairUserNames);
        }

        // 获取乐团编号列表
        Set<String> musicGroupIds = musicGroupList.stream().map(e -> e.getId()).collect(Collectors.toSet());

        Map<String, Integer> payNumMap = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertIntegerMap(studentRegistrationDao.countNormalNum(StringUtils.join(musicGroupIds, ",")))), HashMap.class);


        Map<String, BigDecimal> chargeStandardMap = MapUtil.convertIntegerMap(musicGroupPaymentCalenderDao.queryChargeStandard(StringUtils.join(musicGroupIds, ",")));

        // 获取收费类型编号列表
        Set<Integer> chargeTypeIds = musicGroupList.stream().map(e -> e.getChargeTypeId()).collect(Collectors.toSet());
        if (chargeTypeIds == null) {
            chargeTypeIds = new HashSet<>();
        }
        List<Map<Integer, String>> chargeTypeNames = chargeTypeDao.queryNameByIds(StringUtils.join(chargeTypeIds, ","));
        Map<Integer, String> chargeTypeNameMap = MapUtil.convertMybatisMap(chargeTypeNames);

        //获取教学点编号
        Map<Integer, String> cooperationOrganNames = MapUtil.convertMybatisMap(cooperationOrganDao.queryNameByIds(StringUtils.join(musicGroupList.stream().map(MusicGroup::getCooperationOrganId).collect(Collectors.toSet()), ",")));

        Set<Integer> organIds = musicGroupList.stream().map(e -> e.getOrganId()).collect(Collectors.toSet());
        Map<Integer, String> organNames = MapUtil.convertMybatisMap(organizationDao.findOrganNameMap(StringUtils.join(organIds, ",")));

        List<MusicGroupPurchaseList> musicGroupPurchaseListCount = musicGroupPurchaseListDao.getCount(musicGroupIds);
        Map<String, Integer> purchaseListMap = musicGroupPurchaseListCount.stream().collect(Collectors.toMap(MusicGroupPurchaseList::getMusicGroupId, MusicGroupPurchaseList::getPurchaseNum));

        Map<String, Boolean> viewRegButtonMap = studentRegistrationService.checkMusicGroupsRegOrPayStatus(new ArrayList<>(musicGroupIds));
        //获取分部名称map
        for (MusicGroup e : musicGroupList) {
//            e.setSchoolName(schoolNameMap.get(e.getSchoolId()));
            e.setOrganName(organNames.get(e.getOrganId()));
            e.setCooperationOrganName(cooperationOrganNames.get(e.getCooperationOrganId()));
            e.setEducationalTeacherName(educationalTeacherNameMap.get(e.getEducationalTeacherId()));
            //e.setTeamTeacherName(teamTeacherNameMap.get(e.getTeamTeacherId()));
            e.setRepairUserName(repairUserNameMap.get(e.getRepairUserId()));
            e.setDirectorUserName(directorUserNameMap.get(e.getDirectorUserId()));
            e.setPayNum(payNumMap.get(e.getId()) == null ? 0 : payNumMap.get(e.getId()));
            e.setGroupMemberNum(e.getGroupMemberNum() == null ? 0 : e.getGroupMemberNum());
            e.setChargeTypeName(chargeTypeNameMap.get(e.getChargeTypeId()));
            e.setHasVerifyMusicalList(purchaseListMap.get(e.getId()) != null);
            if (e.getStatus().equals(MusicGroupStatusEnum.PREPARE) || e.getStatus().equals(MusicGroupStatusEnum.PROGRESS)) {
                if (viewRegButtonMap.containsKey(e.getId())) {
                    e.setIsRemedy(true);
                }
            }
            e.setChargeStandard(chargeStandardMap.get(e.getId()));
        }
        return musicGroupPageInfo;
    }

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

        List<MusicGroup> dataList = null;
        int count = musicGroupDao.countMusicGroups(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupDao.findMusicGroups(params);
            List<String> musicGroupIds = dataList.stream().map(e -> e.getId()).collect(Collectors.toList());
            List<MusicGroup> instrument = studentRegistrationDao.countInstrument(musicGroupIds);
            if (instrument != null && instrument.size() > 0) {
                Map<String, List<MusicGroup>> collect = instrument.stream().collect(Collectors.groupingBy(MusicGroup::getId));
                for (MusicGroup musicGroup : dataList) {
                    List<MusicGroup> musicGroups = collect.get(musicGroup.getId());
                    if (musicGroups != null && musicGroups.size() > 0) {
                        MusicGroup musicGroup1 = musicGroups.get(0);
                        musicGroup.setPayNum(musicGroup1.getPayNum());
                        musicGroup.setHasInstrumentNum(musicGroup1.getHasInstrumentNum());
                    }
                }
            }
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    private void updateTeamTeacher(MusicGroup oldMusicGroup, MusicGroup newMusicGroup) {
        //获取当前乐团所有班级
        List<ClassGroup> classGroups = classGroupDao.findClassGroups(newMusicGroup.getId());
        if (classGroups == null || classGroups.size() == 0) {
            return;
        }
        List<Integer> quitUserIdList = new ArrayList<>();
        if (oldMusicGroup.getTeamTeacherId() != null) {
            quitUserIdList.add(oldMusicGroup.getTeamTeacherId());
        }
        if (oldMusicGroup.getEducationalTeacherId() != null) {
            quitUserIdList.add(oldMusicGroup.getEducationalTeacherId());
        }
        if (oldMusicGroup.getDirectorUserId() != null) {
            quitUserIdList.add(oldMusicGroup.getDirectorUserId());
        }
        if (oldMusicGroup.getTransactionTeacherId() != null) {
            quitUserIdList.add(oldMusicGroup.getTransactionTeacherId());
        }
        Map<Integer, String> userRoleMap = new HashMap<>(4);
        if (newMusicGroup.getTeamTeacherId() != null) {
            userRoleMap.put(newMusicGroup.getTeamTeacherId(), "运营主管");
        }
        if (newMusicGroup.getEducationalTeacherId() != null) {
            userRoleMap.put(newMusicGroup.getEducationalTeacherId(), "乐团主管");
        }
        if (newMusicGroup.getDirectorUserId() != null) {
            userRoleMap.put(newMusicGroup.getDirectorUserId(), "乐队指导");
        }
        if (newMusicGroup.getTransactionTeacherId() != null) {
            userRoleMap.put(newMusicGroup.getTransactionTeacherId(), "衔接老师");
        }
        classGroups.forEach(e -> {
            imGroupMemberService.quit(e.getId().toString(), quitUserIdList);
            imGroupMemberService.join(e.getId().toString(), userRoleMap);
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBaseInfo(SubFeeSettingDto subFeeSettingDto) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        String musicGroupId = subFeeSettingDto.getMusicGroup().getId();
        MusicGroup group = musicGroupDao.getLocked(musicGroupId);
        if (group == null) {
            throw new BizException("乐团信息不存在");
        }

        if (!(group.getStatus() == MusicGroupStatusEnum.DRAFT || group.getStatus() == MusicGroupStatusEnum.AUDIT_FAILED
                || group.getStatus() == MusicGroupStatusEnum.PROGRESS)) {
            throw new BizException("当前乐团状态不能修改基本信息");
        }

        MusicGroup musicGroup = subFeeSettingDto.getMusicGroup();
        musicGroup.setStatus(group.getStatus());
        if (!group.getSchoolId().equals(musicGroup.getSchoolId())) {
            //如果已生成课表，那么修改未上课时教学点
            courseScheduleDao.updateCourseScheduleSchool("MUSIC", musicGroupId, musicGroup.getSchoolId());
        }
        CooperationOrgan cooperationOrgan = cooperationOrganDao.get(musicGroup.getCooperationOrganId());
        if (cooperationOrgan.getEducationUserId() == null) {
            throw new BizException("操作失败：请先配置合作单位: {} 关联的乐团主管", cooperationOrgan.getName());
        }
        boolean refresh = false;
        musicGroup.setEducationalTeacherId(cooperationOrgan.getEducationUserId());
        if (group.getStatus() == MusicGroupStatusEnum.PROGRESS) {
            refresh = true;
            updateTeamTeacher(group, musicGroup);
        }
        //修改了维修技师
        if (musicGroup.getRepairUserId() != null && !musicGroup.getRepairUserId().equals(group.getRepairUserId())) {
            refresh = true;
        }
        //不是导入的乐团
        if (musicGroupId.length() > 10) {
            //是否有预报名的群聊
            ImGroup imGroup = imGroupService.get(musicGroupId);
            if (imGroup != null) {
                refresh = true;
                List<Integer> quitUserIdList = new ArrayList<>();
                if (group.getTeamTeacherId() != null) {
                    quitUserIdList.add(group.getTeamTeacherId());
                }
                if (group.getEducationalTeacherId() != null) {
                    quitUserIdList.add(group.getEducationalTeacherId());
                }
                if (group.getDirectorUserId() != null) {
                    quitUserIdList.add(group.getDirectorUserId());
                }
                if (group.getTransactionTeacherId() != null) {
                    quitUserIdList.add(group.getTransactionTeacherId());
                }
                Map<Integer, String> userRoleMap = new HashMap<>(4);
                if (musicGroup.getTeamTeacherId() != null) {
                    userRoleMap.put(musicGroup.getTeamTeacherId(), "运营主管");
                }
                if (musicGroup.getEducationalTeacherId() != null) {
                    userRoleMap.put(musicGroup.getEducationalTeacherId(), "乐团主管");
                }
                if (musicGroup.getDirectorUserId() != null) {
                    userRoleMap.put(musicGroup.getDirectorUserId(), "乐队指导");
                }
                if (musicGroup.getTransactionTeacherId() != null) {
                    userRoleMap.put(musicGroup.getTransactionTeacherId(), "衔接老师");
                }
                imGroupMemberService.quit(musicGroupId, quitUserIdList);
                imGroupMemberService.join(musicGroupId, userRoleMap);
            }
        }

        Date date = new Date();
        //缴费方式不同
        if ((group.getStatus().equals(MusicGroupStatusEnum.AUDIT_FAILED) || group.getStatus().equals(MusicGroupStatusEnum.DRAFT))
                && !group.getChargeTypeId().equals(musicGroup.getChargeTypeId())) {
            //删除原有的声部商品组合
            musicGroupSubjectGoodsGroupDao.delByMusicGroupId(musicGroupId);
            //删除原有的缴费项目
            MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
            if (regCalender != null) {
                musicGroupPaymentCalenderDao.delByGroupId(musicGroupId);

                List<Long> calenderIds = new ArrayList<Long>();
                calenderIds.add(regCalender.getId());
                musicGroupPaymentCalenderCourseSettingsDao.deleteByMusicGroupPaymentCalenderId(calenderIds);
            }
        }
        //课程团和amr可以互相修改，但不可以改为会员团
        if (group.getCourseViewType() != musicGroup.getCourseViewType()) {
            if (group.getStatus() == MusicGroupStatusEnum.PROGRESS && group.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {
                throw new BizException("会员收费乐团不可更改收费模式");
            }
            if (musicGroup.getCourseViewType() == CourseViewTypeEnum.MEMBER_FEE) {

                //如果有进行中的缴费，不能修改会员
                List<PaymentCalenderStatusEnum> statusList = new ArrayList<>();
                statusList.add(PaymentCalenderStatusEnum.NO);
                statusList.add(PaymentCalenderStatusEnum.OPEN);
                statusList.add(PaymentCalenderStatusEnum.AUDITING);
                List<MusicGroupPaymentCalender> musicGroupPaymentCalenderList = musicGroupPaymentCalenderDao.queryByPaymentStatus(musicGroupId, statusList, PayUserType.STUDENT.getCode());

                if (musicGroupPaymentCalenderList != null && musicGroupPaymentCalenderList.size() > 0) {
                    throw new BizException("存在未完结[审核中/未开启缴费/开启缴费]的缴费项目，请检查");
                }

            }
        }
        musicGroup.setUpdateTime(date);
        musicGroupDao.update(musicGroup);
        // 删除乐团付费主体列表
        musicGroupPaymentEntitiesDao.delByGroupId(musicGroupId);
        //批量新增
        if (subFeeSettingDto.getMusicGroupPaymentEntities() != null && subFeeSettingDto.getMusicGroupPaymentEntities().size() > 0) {
            musicGroupPaymentEntitiesDao.batchAdd(subFeeSettingDto.getMusicGroupPaymentEntities(), musicGroupId);
        }
        if (refresh) {
            imUserFriendService.refreshGroupImUserFriend(musicGroupId, GroupType.MUSIC);
        }
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "修改乐团基本信息数据", sysUser.getId(), JSONObject.toJSONString(subFeeSettingDto)));
    }

    @Override
    public SubFeeSettingDto findMusicGroupBasicInfo(String musicGroupId) {
        SubFeeSettingDto subFeeSettingDto = new SubFeeSettingDto();
        //获取乐团信息
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        ChargeType chargeType = chargeTypeDao.get(musicGroup.getChargeTypeId());
        musicGroup.setChargeTypeName(chargeType.getName());
        MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderService.findByMusicGroupRegCalender(musicGroup.getId());
        if (regCalender != null && regCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)) {
            musicGroup.setPaymentExpireDate(regCalender.getDeadlinePaymentDate());
        }
        subFeeSettingDto.setMusicGroup(musicGroup);
        //获取付费主体
        subFeeSettingDto.setMusicGroupPaymentEntities(musicGroupPaymentEntitiesDao.findByMusicGroupId(musicGroupId));
        //获取缴费周期
        //List<Integer> paymentMonth = musicGroupPaymentCalenderDao.findByMusicGroupId(musicGroupId).stream().map(e -> e.getPaymentMonth()).collect(Collectors.toList());
        //subFeeSettingDto.setMonths(paymentMonth);
        return subFeeSettingDto;
    }

    @Override
    public SubFeeSettingDto findMusicGroupSubjectInfo(String musicGroupId) {
        SubFeeSettingDto subFeeSettingDto = new SubFeeSettingDto();
        //获取乐团声部规划列表
        subFeeSettingDto.setMusicGroupSubjectPlans(musicGroupSubjectPlanDao.getMusicSubjectClassPlan(musicGroupId));
        //获取乐团声部商品组
        subFeeSettingDto.setMusicGroupSubjectGoodsGroups(musicGroupSubjectGoodsGroupDao.findGoodsGroup(musicGroupId, null));
        return subFeeSettingDto;
    }

    @Override
    public List<MusicGroup> queryListByIds(Set<String> musicGroupIds) {
        return musicGroupDao.queryListByIds(StringUtils.join(musicGroupIds, ","));
    }

    @Override
    public List<CourseScheduleTeachersDto> queryTeacherSalary(Long courseScheduleId, Integer teacherId) {
        return courseScheduleTeacherSalaryDao.queryTeacherSalary(courseScheduleId, teacherId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MusicGroup openPay(String musicGroupId, String expireDate) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = saveLog(musicGroupId, MusicGroupStatusEnum.APPLY);
        //记录操作日志
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "开启缴费（报名中 -->  缴费中）", sysUser.getId(), ""));
        musicGroup.setPaymentExpireDate(DateUtil.toDate(expireDate));
        musicGroup.setStatus(MusicGroupStatusEnum.PAY);
        musicGroupDao.update(musicGroup);
        List<Map<Integer, String>> mapList = studentRegistrationDao.findMapByMusicGroupId(musicGroupId, 0);
        //所有人开启缴费
        studentRegistrationDao.musicGroupOpenPay(musicGroupId, PaymentStatusEnum.OPEN);
        MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
        if (regCalender != null && regCalender.getPayUserType().equals(MusicGroupPaymentCalender.PayUserType.STUDENT)) {
            regCalender.setStatus(MusicGroupPaymentCalender.PaymentCalenderStatusEnum.OPEN);
            regCalender.setDeadlinePaymentDate(DateUtil.toDate(expireDate));
            regCalender.setUpdateTime(new Date());
            musicGroupPaymentCalenderDao.update(regCalender);
        }
        //三方乐团不发送缴费通知
        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
            //获取所有已报名学员列表
            HashMap<Integer, String> map = JSONObject.parseObject(JSONObject.toJSONString(MapUtil.convertMybatisMap(mapList)), HashMap.class);
            if (map != null && map.size() > 0) {
                String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + musicGroupId;
//                String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
                sysMessageService.batchSendMessage(MessageSender.AWSMS, MessageTypeEnum.SMS_PAYMENT_MESSAGE,
                        map, null, 0, "", "", musicGroup.getName(), studentApplyUrl);
            }
        }
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER}, null,
                musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_ACTION_PAYMENT, musicGroup.getName());
        return musicGroup;
    }

    @Override
    public MusicGroup getMusicGroupDetail(String musicGroupId) {
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        musicGroup.setEducationalTeacherName(teacherDao.queryNameById(musicGroup.getEducationalTeacherId()));
        musicGroup.setTeamTeacherName(teacherDao.queryNameById(musicGroup.getTeamTeacherId()));
        musicGroup.setDirectorUserName(teacherDao.queryNameById(musicGroup.getDirectorUserId()));
        musicGroup.setRepairUserName(teacherDao.queryNameById(musicGroup.getRepairUserId()));
        Organization organization = organizationDao.get(musicGroup.getOrganId());
        if (organization != null) {
            musicGroup.setOrganName(organization.getName());
        }
        School school = schoolDao.get(musicGroup.getSchoolId());
        if (school != null) {
            musicGroup.setSchoolName(school.getName());
            musicGroup.setAddress(school.getAddress());
        }
        ChargeType chargeType = chargeTypeDao.get(musicGroup.getChargeTypeId());
        if (chargeType != null) {
            musicGroup.setChargeTypeName(chargeType.getName());
        }
        int highClassGroupNum = studentRegistrationDao.findMusicGroupStudentNum(musicGroupId) / 5;
        musicGroup.setImproventClassesNum(highClassGroupNum);
        return musicGroup;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void musicGroupFound(String musicGroupId) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息不存在");
        }
        if (musicGroup.getTenantId() == null) {
            throw new BizException("乐团机构信息异常，请联系管理员");
        }
        //记录操作日志
        String event;
        if (musicGroup.getStatus() == MusicGroupStatusEnum.APPLY) {
            event = "确认开团(报名中 -> 筹备中)";
        } else if (musicGroup.getStatus() == MusicGroupStatusEnum.PAY) {
            event = "确认开团(缴费中 -> 筹备中)";
        } else {
            throw new BizException("当前乐团状态不支持此操作");
        }
        //有已付费，在储备中的人，不容许到储备中
        int payAndCheckNum = studentRegistrationDao.countPayAndCheckNum(musicGroupId);
        if (payAndCheckNum > 0) {
            throw new BizException("有订单审核中的学生，请处理后再进行下一步");
        }

        //新建团：（乐团合作单位没有进行中 、暂停、关闭 的乐团）

        //报名未交费的学生，完成回访才能到下一步

        //获取乐团合作单位乐团数量
        Integer cooperationMusicGroupNum = musicGroupDao.getCooperationMusicGroupNum(musicGroup.getCooperationOrganId(), musicGroupId);
        Integer paymentStudentNum = studentRegistrationDao.getPaymentStudentNum(musicGroupId);

        //若乐团新建团，则操作【确认开团】时，若【已缴费】学员达到98人，则无需对【未缴费】学员新增回访
        String configValue = sysTenantConfigService.getTenantConfigValue(SysConfigService.NEW_MUSIC_PAYMENT_STUDENT_NUM, musicGroup.getTenantId());
        //若乐团不是新建团，则操作【确认开团】时，若【已缴费】学员达到58人，则无需对【未缴费】学员新增回访
        String configValue1 = sysTenantConfigService.getTenantConfigValue(SysConfigService.OLD_MUSIC_PAYMENT_STUDENT_NUM, musicGroup.getTenantId());
        if ((StringUtils.isNotEmpty(configValue) && cooperationMusicGroupNum <= 0 && paymentStudentNum < Integer.parseInt(configValue)) ||
                (StringUtils.isNotEmpty(configValue1) && cooperationMusicGroupNum > 0 && paymentStudentNum < Integer.parseInt(configValue1))) {
            checkStudentVisit(musicGroupId);
        }

        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, event, sysUser.getId(), ""));
        musicGroup.setStatus(MusicGroupStatusEnum.PREPARE);
        musicGroupDao.update(musicGroup);
//        if (musicGroup.getOwnershipType() != null && musicGroup.getOwnershipType() == CooperationOrgan.OwnershipType.OWN) {
//            //给家长发送乐团基础训练课短信
//            //获取所有乐团学员列表
//            List<StudentRegistration> students = studentRegistrationDao.queryStudentByMusicGroupId(musicGroupId);
//            if (students != null && students.size() > 0) {
//                // 获取所有家长电话
//                Set<String> parentsPhones = students.stream().map(StudentRegistration::getParentsPhone).collect(Collectors.toSet());
//                // 获取对应家长的用户编号
//                Map<Integer, String> userIds = MapUtil.convertMybatisMap(studentRegistrationDao.findParentId(StringUtils.join(parentsPhones, ",")));
//                userIds = JSONObject.parseObject(JSONObject.toJSONString(userIds), HashMap.class);
//                if (userIds != null && userIds.size() > 0) {
//                    String studentApplyUrl = sysConfigDao.findConfigValue(SysConfigService.STUDENT_APPLY_URL) + musicGroupId;
//                    String serverPhone = sysConfigDao.findConfigValue(SysConfigService.SERVER_PHONE);
//                    sysMessageService.batchSendMessage(MessageSender.YIMEI, MessageTypeEnum.SMS_BASICS_SKILL_APPLY_MESSAGE, userIds, null, 0, "", "", musicGroup.getName(), studentApplyUrl, serverPhone);
//                }
//            }
//        }
        sendSeoMessageSource.sendSeoMessage(musicGroup.getOrganId(), new SysUserRoleEnum[]{ORGAN_MANAGER},
                null, musicGroup.getEducationalTeacherId(), MessageTypeEnum.BACKSTAGE_MUSIC_GROUP_MARKING, musicGroup.getName());
    }

    /**
     * 校验回访
     *
     * @param musicGroupId
     */
    private void checkStudentVisit(String musicGroupId) {
        boolean hasNoVisit = false;
        StringBuilder tipsMsg = new StringBuilder();
        List<StudentRegistration> noPaymentStudents = studentRegistrationDao.getNoPaymentStudent(musicGroupId);
        if (noPaymentStudents.size() > 0) {
            tipsMsg.append("以下学生未完成回访，");
            List<Integer> studentIds = noPaymentStudents.stream().map(StudentRegistration::getUserId).collect(Collectors.toList());
            List<Integer> musicGroupVisitStudent = studentVisitDao.getMusicGroupVisitStudent(musicGroupId, studentIds);
            for (StudentRegistration noPaymentStudent : noPaymentStudents) {
                if (!musicGroupVisitStudent.contains(noPaymentStudent.getUserId())) {
                    hasNoVisit = true;
                    tipsMsg.append(noPaymentStudent.getName()).append("(").append(noPaymentStudent.getUserId()).append(")、");
                }
            }
        }
        if (hasNoVisit) {
            throw new BizException(tipsMsg.append("请完成回访").toString());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult addMusicGroupRegs(String musicGroupId, List<Long> registerIds) throws Exception {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null || sysUser.getId() == null) {
            throw new BizException("获取用户信息失败");
        }
        List<StudentRegistration> studentRegistrations = studentRegistrationDao.findStudentListByIdList(registerIds);
        List<StudentRegistration> oldRegs = studentRegistrationDao.getMusicGroupStu(musicGroupId);
        Map<Integer, List<StudentRegistration>> oldRegMap = oldRegs.stream().collect(Collectors.groupingBy(StudentRegistration::getUserId));
        //去掉相同的人
        List<StudentRegistration> newRegs = new ArrayList<>();
        Set<Integer> hasUsers = new HashSet<>();
        for (StudentRegistration studentRegistration : studentRegistrations) {
            if (oldRegMap.containsKey(studentRegistration.getUserId()) || hasUsers.contains(studentRegistration.getUserId())) {
                continue;
            }
            hasUsers.add(studentRegistration.getUserId());
            newRegs.add(studentRegistration);
        }
        if (registerIds.size() > 0 && newRegs.size() <= 0) {
            throw new BizException("添加的学员,乐团已存在");
        }
        studentRegistrations = newRegs;

        List<Integer> subjectIds = studentRegistrations.stream().map(StudentRegistration::getActualSubjectId).collect(Collectors.toList());
        List<Subject> subjects = subjectDao.findBySubjectIds(subjectIds);
        Map<Integer, List<Subject>> subjectMap = subjects.stream().collect(Collectors.groupingBy(Subject::getId));
        List<MusicGroupSubjectPlan> musicSubjectClassPlans = musicGroupSubjectPlanDao.getMusicSubjectClassPlan(musicGroupId);

        Map<Integer, List<StudentRegistration>> regsMap = studentRegistrations.stream().collect(Collectors.groupingBy(StudentRegistration::getActualSubjectId));
        List<StudentRegistration> studentRegistrationList = new ArrayList<>();
        regsMap.forEach((subjectId, regs) -> {
            boolean hasSubject = false;
            MusicGroupSubjectPlan subjectPlan = null;
            for (MusicGroupSubjectPlan musicGroupSubjectPlan : musicSubjectClassPlans) {
                if (!subjectId.equals(musicGroupSubjectPlan.getSubjectId())) continue;
                hasSubject = true;
                musicGroupSubjectPlan.setApplyStudentNum(musicGroupSubjectPlan.getApplyStudentNum() + regs.size());
                subjectPlan = musicGroupSubjectPlan;
            }
            if (!hasSubject) {
                String name = subjectMap.get(subjectId).get(0).getName();
                throw new BizException("当前乐团没有学员包含的声部（" + name + ")");
            }
            //更新乐团声部计划信息
            musicGroupSubjectPlanDao.update(subjectPlan);

            for (StudentRegistration studentRegistration : regs) {
                studentRegistration.setId(null);
                studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.APPLY);
                studentRegistration.setPaymentStatus(PaymentStatusEnum.OPEN); //开启缴费
                studentRegistration.setMusicGroupId(musicGroupId);
                studentRegistration.setSubjectId(subjectId);
                studentRegistration.setActualSubjectId(subjectId);
                studentRegistration.setIsMerge(1);
                studentRegistration.setTemporaryCourseFee(null);
                studentRegistration.setHasCloudTeacher(0);
            }
            studentRegistrationList.addAll(regs);
        });

        //添加的学生
        if (studentRegistrationList.size() > 0) {
            studentRegistrationDao.batchInsert(studentRegistrationList);
        }
        //0元的和学校缴费的默认缴费
        boolean autoPay = false;
        MusicGroupPaymentCalender regCalender = musicGroupPaymentCalenderService.findByMusicGroupRegCalender(musicGroupId);
        List<MusicGroupPaymentCalenderCourseSettings> musicGroupRegCalenderCourseSettings = musicGroupPaymentCalenderCourseSettingsDao.getMusicGroupRegCalenderCourseSettings(musicGroupId);
        BigDecimal courseSettingsPrice = musicGroupRegCalenderCourseSettings.stream().map(MusicGroupPaymentCalenderCourseSettings::getCourseCurrentPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
        if (regCalender == null || courseSettingsPrice.compareTo(BigDecimal.ZERO) == 0) {
            autoPay = true;
        }
        if (autoPay) {
            List<Integer> courseSettings = musicGroupRegCalenderCourseSettings.stream().map(MusicGroupPaymentCalenderCourseSettings::getId).collect(Collectors.toList());
            RegisterPayDto registerPayDto = new RegisterPayDto();
            registerPayDto.setAmount(BigDecimal.ZERO);
            registerPayDto.setNewCourse(courseSettings);
            for (StudentRegistration studentRegistration : studentRegistrationList) {
                registerPayDto.setRegisterId(studentRegistration.getId().intValue());
                this.pay(registerPayDto);
            }
        }

        //修改乐团信息
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        musicGroup.setIsExtraClass(YesOrNoEnum.YES);
        musicGroupDao.update(musicGroup);
        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(musicGroupId, "添加报名学员", sysUser.getId(), ""));
        return BaseController.succeed(studentRegistrationList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean closeMusicGroup(CloseMusicGroupDto closeMusicGroupDto) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        MusicGroup musicGroup = musicGroupDao.get(closeMusicGroupDto.getMusicGroupId());
        if (musicGroup == null) {
            throw new BizException("乐团找不到");
        }

        if (musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS) {
            throw new BizException("乐团当前状态是{}，不能关闭", musicGroup.getStatus().getMsg());
        }

        //有进行中的课不能关闭乐团
        Integer underwayCourseNum = courseScheduleDao.getUnderwayCourseNum(musicGroup.getId(), GroupType.MUSIC, CourseStatusEnum.UNDERWAY);
        if (underwayCourseNum > 0) {
            throw new BizException("乐团有进行的课程，不能关闭");
        }
        musicGroup.setStatus(MusicGroupStatusEnum.CLOSE);
        musicGroup.setUpdateTime(new Date());
        musicGroupDao.update(musicGroup);

        courseScheduleStudentPaymentService.updateCourseActualPrice(Arrays.asList(musicGroup.getId()), null, GroupType.MUSIC);

        musicGroupBuildLogDao.insert(new MusicGroupBuildLog(closeMusicGroupDto.getMusicGroupId(), "关闭乐团", sysUser.getId(), ""));

        List<StudentRegistration> musicGroupRegs = studentRegistrationDao.findMusicGroupStudent(closeMusicGroupDto.getMusicGroupId(), null);
        Map<Integer, BigDecimal> userReBackMap = closeMusicGroupDto.getUserReBack();
        //退还没上课程费用
        for (StudentRegistration musicGroupReg : musicGroupRegs) {
            BigDecimal userReBack = userReBackMap.getOrDefault(musicGroupReg.getUserId(), BigDecimal.ZERO);

            if (userReBack.compareTo(musicGroupReg.getSurplusCourseFee()) > 0) {
                throw new BizException(musicGroupReg.getName() + "退费金额不能大于实际金额");
            }
            //退用户余额
            if (userReBack.compareTo(BigDecimal.ZERO) > 0) {
                SysUserCashAccountLog sysUserCashAccountLog = new SysUserCashAccountLog();
                sysUserCashAccountLog.setGroupType(GroupType.MUSIC);
                sysUserCashAccountLog.setUserId(musicGroupReg.getUserId());
                sysUserCashAccountLog.setOrganId(musicGroup.getOrganId());
                sysUserCashAccountLog.setGroupId(musicGroup.getId());
                sysUserCashAccountLog.setAmount(userReBack);
                sysUserCashAccountLog.setReturnFeeType(ReturnFeeEnum.MUSIC);
                sysUserCashAccountLog.setComment("关闭乐团");
                sysUserCashAccountLogDao.insert(sysUserCashAccountLog);
//                sysUserCashAccountService.updateBalance(musicGroupReg.getUserId(), userReBack, PlatformCashAccountDetailTypeEnum.REFUNDS, "关闭乐团");
            }
            //清除剩余课程费用
            if (musicGroupReg.getSurplusCourseFee().compareTo(BigDecimal.ZERO) > 0) {
                studentRegistrationService.updateUserSurplusCourseFee(musicGroupReg.getUserId(), musicGroupReg.getMusicGroupId(), musicGroupReg.getSurplusCourseFee().negate(), "关闭乐团", sysUser.getId());
            }
        }

        //删除未上课表
        courseScheduleDao.logicDeleteCourseSchedulesByMusicGroupID(musicGroup.getId());

        //将学生退团
        List<StudentRegistration> registrations = studentRegistrationDao.findClassGroupStu(musicGroup.getId(), null);
        if (registrations.size() > 0 && studentRegistrationService.quitAllStudent(musicGroup.getId(), "退团（乐团关闭）") <= 0) {
            throw new BizException("处理学生退团失败，请重试");
        }

        //统计变更学员数
        groupEventSource.musicGroupStudentChangeEvent(closeMusicGroupDto.getMusicGroupId(), StudentMusicGroupStatusEnum.QUIT, null);

        return true;
    }

    @Override
    public List<MusicGroup> findByCooperationId(Integer cooperationId) {
        return musicGroupDao.findByCooperationId(cooperationId);
    }

    @Override
    public PageInfo<MusicMemberDto> queryMusicMemberList(MusicMemberQueryInfo queryInfo) {
        String configValue = sysTenantConfigService.getTenantConfigValue(SysConfigService.PUSH_MEMBER_RENEW_QUIT, queryInfo.getTenantId());
        if (StringUtils.isEmpty(configValue)) {
            configValue = "15";
        }
        queryInfo.setMemberEndAutoQuitMusic(configValue);
        PageInfo<MusicMemberDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);
        List<MusicMemberDto> dataList = null;
        int count = musicGroupDao.countMusicMemberList(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = musicGroupDao.queryMusicMemberList(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public MusicGroupBasicDto queryBasicInfo(String id) {
        return musicGroupDao.queryBasicInfo(id);
    }

    @Override
    public Object getQuitGroupDetail(String musicGroupId) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        Map<String, Object> resultMap = new HashMap<>(8);
        String username = sysUser.getUsername();
        resultMap.put("username", StringUtils.isEmpty(username) ? sysUser.getRealName() : username);
        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        resultMap.put("musicGroupName", musicGroup.getName());
        int musicGroupStudentNum = studentRegistrationDao.findMusicGroupStudentNum(musicGroupId);
        resultMap.put("musicGroupStudentNum", musicGroupStudentNum);
        StudentRegistration studentRegistration = studentRegistrationDao.getStudentRegister(musicGroupId, sysUser.getId());
        int daysBetween = DateUtil.daysBetween(studentRegistration.getCreateTime(), new Date());
        resultMap.put("days", daysBetween);
        MusicGroupQuit musicGroupQuit = musicGroupQuitDao.queryByUserIdAndMusicGroupId(sysUser.getId(), musicGroupId);
        if (musicGroupQuit != null && musicGroupQuit.getStatus() == PROCESSING) {
			resultMap.put("reasonEnum",musicGroupQuit.getReasonEnum());
			resultMap.put("memo", musicGroupQuit.getUserComment());
			resultMap.put("quitTime", musicGroupQuit.getCreateTime());
        }
        if (musicGroup.getEducationalTeacherId() != null) {
            SysUser user = sysUserFeignService.queryUserById(musicGroup.getEducationalTeacherId());
            resultMap.put("teacherMobile", user.getPhone());
        } else {
            resultMap.put("teacherMobile", "027-87718176");
        }
        return resultMap;
    }

    @Override
    public boolean takeEffectOfinstrumentInsurance(String musicGroupId) {

        MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
        if (musicGroup == null) {
            throw new BizException("乐团信息查询失败");
        }

        if (musicGroup.getMusicalInstrumentsProvideStatus() != 0) {
            throw new BizException("乐器已发货，请勿重复操作");
        }

        Set<String> musicGroupIds = new HashSet<String>();
        musicGroupIds.add(musicGroupId);
        List<MusicGroupPurchaseList> musicGroupPurchaseListCount = musicGroupPurchaseListDao.getCount(musicGroupIds);
        if (musicGroupPurchaseListCount == null || musicGroupPurchaseListCount.size() == 0) {
            throw new BizException("乐器清单未确认，不能确认发货");
        }

        Date date = new Date();

        musicGroup.setMusicalInstrumentsProvideStatus(1);
        musicGroup.setUpdateTime(date);
		musicGroup.setMusicalInstrumentsProvideTime(DateUtil.format(date,DateUtil.ISO_YEAR_MONTH_FORMAT));
        musicGroupDao.update(musicGroup);

        //查询当前乐团报名订单中购买了乐保的订单
        List<StudentApplyInstrumentDto> maintenanceList = studentPaymentOrderDetailDao.queryByType(musicGroupId, OrderDetailTypeEnum.MAINTENANCE);

        if (maintenanceList == null || maintenanceList.size() == 0) {
            return true;
        }

        List<Long> instrumentIdList = maintenanceList.stream().map(t -> t.getStudentInstrumentId()).collect(Collectors.toList());

        List<StudentInstrument> studentInstrumentList = studentInstrumentDao.queryById(instrumentIdList);

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

        for (StudentInstrument si : studentInstrumentList) {
            if (si.getDelFlag() == 1) {
                continue;
            }
            if (si.getStatus() == 0 && si.getStartTime() == null) {
                si.setStatus(1);
                si.setStartTime(date);
                si.setEndTime(DateUtil.addYears(date, 1));
                si.setUpdateTime(date);

                updateList.add(si);
            }
        }

        if (updateList.size() > 0) {
            studentInstrumentDao.batchModify(updateList);
        }

        return true;
    }
}
