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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.*;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.constant.CommonConstants;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.thirdparty.adapay.ConfigInit;
import com.ym.mec.thirdparty.adapay.Payment;
import com.ym.mec.thirdparty.adapay.entity.HfMerchantConfig;
import com.ym.mec.thirdparty.storage.StoragePluginContext;
import com.ym.mec.thirdparty.storage.provider.KS3StoragePlugin;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import com.ym.mec.util.excel.POIUtil;
import com.ym.mec.util.ini.IniFileUtil;
import com.ym.mec.util.upload.UploadUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.enums.OrderTypeEnum.OUTORDER;
import static com.ym.mec.biz.dal.enums.OrderTypeEnum.SPORADIC;
import static com.ym.mec.common.controller.BaseController.succeed;

@Service
public class ExportServiceImpl implements ExportService {

    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    private StudentPaymentRouteOrderDao studentPaymentRouteOrderDao;
    @Autowired
    private VipGroupDao vipGroupDao;
    @Autowired
    private PracticeGroupDao practiceGroupDao;
    @Autowired
    private SellOrderDao sellOrderDao;
    @Autowired
    private StudentRegistrationDao studentRegistrationDao;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private StoragePluginContext storagePluginContext;
    @Autowired
    private ManagerDownloadDao managerDownloadDao;
    @Autowired
    private CooperationOrganDao cooperationOrganDao;
    @Autowired
    private ReplacementInstrumentActivityDao replacementInstrumentActivityDao;
    @Autowired
    private CourseScheduleService courseScheduleService;
    @Autowired
    private StudentService studentService;
    @Autowired
    private TenantConfigService tenantConfigService;
    @Autowired
    private CourseScheduleStudentPaymentDao courseScheduleStudentPaymentDao;
    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    private StudentManageService studentManageService;
    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;
    @Autowired
    private CourseScheduleTeacherSalaryService courseScheduleTeacherSalaryService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private OrganizationService organizationService;
    @Autowired
    private StudentInstrumentDao studentInstrumentDao;
    @Autowired
    private VipGroupService vipGroupService;
    @Autowired
    private PracticeGroupService practiceGroupService;
    @Autowired
    private SporadicChargeInfoService sporadicChargeInfoService;
    @Autowired
    private CourseReviewService courseReviewService;
    @Autowired
    private TenantPaymentOrderService tenantPaymentOrderService;
    @Autowired
    private CourseScheduleDao courseScheduleDao;
    @Autowired
    private ExtracurricularExercisesReplyService extracurricularExercisesReplyService;
    @Autowired
    private StudentExtracurricularExercisesSituationService studentExtracurricularExercisesSituationService;
    @Autowired
    private TeacherSalaryComplaintsService teacherSalaryComplaintsService;
    @Autowired
    private TeacherAttendanceService teacherAttendanceService;
    @Autowired
    private StudentAttendanceService studentAttendanceService;
    @Autowired
    private TeacherCourseRewardService teacherCourseRewardService;
    @Autowired
    private DegreeRegistrationService degreeRegistrationService;
    @Autowired
    private CooperationOrganService cooperationOrganService;
    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private MusicGroupPaymentCalenderDetailService musicGroupPaymentCalenderDetailService;
    @Autowired
    private TeacherService teacherService;
    @Autowired
    private MusicGroupBuildLogDao musicGroupBuildLogDao;
    @Autowired
    private MusicGroupPaymentCalenderService musicGroupPaymentCalenderService;
    @Autowired
    private SellOrderService sellOrderService;
    @Autowired
    private VipGroupActivityService vipGroupActivityService;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private ClassGroupService classGroupService;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private MusicGroupQuitService musicGroupQuitService;
    @Autowired
    private IndexBaseMonthDataService indexService;
    @Autowired
    private TeacherCourseStatisticsService teacherCourseStatisticsService;
    @Autowired
    private SysUserCashAccountDetailDao sysUserCashAccountDetailDao;
    @Autowired
    private SysUserCoursesAccountDetailDao sysUserCoursesAccountDetailDao;
    @Autowired
    private ChildrenDayReserveService childrenDayReserveService;
    @Autowired
    private IndexErrDataRecordService indexErrDataRecordService;
    @Autowired
    private EmployeeInfoService employeeInfoService;
    @Autowired
    private MusicEnlightenmentQuestionnaireService musicEnlightenmentQuestionnaireService;
    @Autowired
    private MusicGroupService musicGroupService;
    @Autowired
    private SysUserCashAccountLogService sysUserCashAccountLogService;
    @Autowired
    private StudentStatisticsService studentStatisticsService;
    @Autowired
    private ActivityUserMapperService activityUserMapperService;
    @Autowired
    private SysMusicCompareRecordDao sysMusicCompareRecordDao;

    private static final ExecutorService exportExecutorService = Executors.newFixedThreadPool(10);
    @Autowired
    private HfMerchantConfigService hfMerchantConfigService;

    @Value("${spring.profiles.active:dev}")
    private String profiles;

    public static String goodsSellReceiptMerNo = "";


    @Override
    public Map<String, String> getExportMap(ExportDto exportDto){
        if (exportDto.getExportEnum() == null) {
            throw new BizException("请选择导出类型");
        }
        Map<String, String> columns = loadColumnMapper(exportDto.getExportEnum());
        List<String> headColumns = JSONObject.parseObject(columns.get("headColumns"), List.class);
        List<String> fieldColumns = JSONObject.parseObject(columns.get("fieldColumns"), List.class);
        Map<String, String> headMap = new LinkedHashMap<>(headColumns.size());
        for (int i = 0; i < headColumns.size(); i++) {
            headMap.put(headColumns.get(i), fieldColumns.get(i));
        }
//        headMap.keySet().removeAll(org.apache.commons.collections.CollectionUtils.subtract(headColumns, fieldColumns));
        return headMap;
    }

    @Override
    public List<String> getExportFields(ExportEnum exportEnum){
        SysUser sysUser = sysUserService.getUser();
        if (exportEnum == ExportEnum.ORDER_LIST1 || exportEnum == ExportEnum.ORDER_LIST2) {
            if (sysUser.getTenantId() <= 1) {
                exportEnum = ExportEnum.ORDER_LIST1;
            } else {
                exportEnum = ExportEnum.ORDER_LIST2;
            }
        } else if (exportEnum == ExportEnum.ROUTE_ORDER_LIST1 || exportEnum == ExportEnum.ROUTE_ORDER_LIST2) {
            if (sysUser.getTenantId() <= 1) {
                exportEnum = ExportEnum.ROUTE_ORDER_LIST1;
            } else {
                exportEnum = ExportEnum.ROUTE_ORDER_LIST2;
            }
        }
        return JSONObject.parseObject(loadColumnMapper(exportEnum).get("headColumns"), List.class);
    }

    private Map<String, String> loadColumnMapper(ExportEnum exportEnum){
        Map<String, String> map = null;
        try {
            InputStream inputStream = new ClassPathResource("exportColumnMapper.ini").getInputStream();
            map = IniFileUtil.readIniFile(inputStream, exportEnum.getMsg());
        } catch (Exception e) {
            throw new BizException(e);
        }
        return map;
    }

    @Override
    public <T> void export(HttpServletResponse response, List<T> rows, ExportDto exportDto) throws IOException {
        if (rows == null || rows.size() == 0) {
            throw new BizException("没有可导出数据");
        }
        //获取表头和字段
        Map<String, String> headMap = getExportMap(exportDto);
        OutputStream outputStream = response.getOutputStream();
        try {
            String[] head = headMap.keySet().toArray(new String[headMap.keySet().size()]);
            String[] field = headMap.values().toArray(new String[headMap.keySet().size()]);
            HSSFWorkbook workbook = POIUtil.exportExcel(head, field, rows);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attac:wq" +
                    "hment;filename=" + DateUtil.getDate(new Date()) + ".xls");
            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //导出到报表中心
    private Map<ExportEnum, Function<Map<String, Object>, HttpResponseResult>> exportManageFuncMap = new HashMap<>(ExportEnum.values().length);
    //直接导出
    private Map<ExportEnum, Function<Map<String, Object>, List>> exportFuncMap = new HashMap<>(ExportEnum.values().length);

    @Override
    public Map<ExportEnum, Function<Map<String, Object>, HttpResponseResult>> getExportManageFuncMap() {
        return exportManageFuncMap;
    }

    @Override
    public Map<ExportEnum, Function<Map<String, Object>, List>> getExportFuncMap() {
        return exportFuncMap;
    }

    @PostConstruct
    public void exportFuncMapInit() {
        exportFuncMap.put(ExportEnum.USER_CASH_ACCOUNT_LOG, info -> sysUserCashAccountLogService.queryPage(getQueryInfo(info, AccountLogQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.MUSIC_GROUP, info -> musicGroupService.queryMusicGroupPage(getQueryInfo(info, MusicGroupQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.STATISTICS_DETAIL, info -> childrenDayReserveService.exportStatisticsDetail(getQueryInfo(info, ChildrenReserveQueryInfo.class, true)));
        exportFuncMap.put(ExportEnum.DOUBLE_ELEVEN2021_ORDER_DETAIL, info -> vipGroupActivityService.doubleEleven2021OrderDetail(getQueryInfo(info, DoubleEleven2021QueryInfo.class, false)).getRows());
        exportFuncMap.put(ExportEnum.ORGAN_DOUBLE_ELEVEN2021_STATIS, info -> vipGroupActivityService.organDoubleEleven2021Statis(getQueryInfo(info, OrganDoubleEleven2021StatisDto.class, false)));
        exportFuncMap.put(ExportEnum.USER_CASH_ACCOUNT_DETAIL, info -> sysUserCashAccountDetailDao.exportDetail(getQueryInfo(info, ExportUserAccountQueryInfo.class, true)));
        exportFuncMap.put(ExportEnum.USER_COURSES_ACCOUNT, info -> sysUserCoursesAccountDetailDao.exportDetail(getQueryInfo(info, ExportUserAccountQueryInfo.class, true)));
        exportFuncMap.put(ExportEnum.CLASS_GROUP, info -> exportClassGroup(info));
        exportFuncMap.put(ExportEnum.GOODS, info -> goodsService.queryPage(getQueryInfo(info, GoodsQueryInfo.class, false)).getRows());
        exportFuncMap.put(ExportEnum.VIP_GROUP_ACTIVITY, info -> vipGroupActivityService.exportVipGroupActivity(getQueryInfo(info, VipGroupActivityQueryInfo.class, true)));
        exportFuncMap.put(ExportEnum.EXPORT_STUDENT_ATTENDANCES, info -> studentAttendanceService.exportStudentAttendancesQueryPage(getQueryInfo(info, ExportStudentAttendanceQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.MUSIC_GROUP_PAYMENT_CALENDER_DETAIL, info -> musicGroupPaymentCalenderDetailService.queryDetailPage(getQueryInfo(info, MusicCalenderDetailQueryInfo.class, false)).getRows());
        exportFuncMap.put(ExportEnum.EXPORT_PAYMENT_CALENDER_AUDIT_LIST, info -> musicGroupPaymentCalenderService.auditList(getQueryInfo(info, MusicGroupPaymentCalenderQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.QUERY_TEACHER_ATTENDANCES, info -> teacherAttendanceService.queryTeacherAttendances(getQueryInfo(info, TeacherCloseQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TEACHER_SALARY_COMPLAINTS, info -> teacherSalaryComplaintsService.queryPage(getQueryInfo(info, TeacherSalaryModifyQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.STUDENT_BUY_PRACTICE, info -> practiceGroupService.studentBuys(getQueryInfo(info, StudentBuyPracticeQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TENANT_PAYMENT_ORDER, info -> tenantPaymentOrderService.queryPage(getQueryInfo(info, TenantPaymentOrderQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TEACHER_SALARY, info -> courseScheduleTeacherSalaryService.exportTeacherSalary(getQueryInfo(info, ExportTeacherSalaryQueryInfo.class, false)));
        exportFuncMap.put(ExportEnum.TEACHER_COURSE_REWARD, info -> teacherCourseReward(info));
        exportFuncMap.put(ExportEnum.STUDENT_HAS_COURSE, info -> studentManageService.findStudentsByOrganId(getQueryInfo(info, StudentManageQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.PRACTICE_GROUP_LIST, info -> practiceGroupList(info));
        exportFuncMap.put(ExportEnum.VIP_GROUP_LIST, info -> vipGroupService.findVipGroups(getQueryInfo(info, VipGroupQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.SPORADIC_CHARGE_INFO, info -> sporadicChargeInfoService.queryDetailPage(getQueryInfo(info, SporadicChargeInfoQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.MUSICAL_LIST_EXPORT, info -> studentPaymentOrderDetailService.getMusicalList(getParam(info, "musicGroupId", String.class)));
        exportFuncMap.put(ExportEnum.MUSICAL_LIST_DETAIL_EXPORT, info -> studentPaymentOrderDetailService.getMusicalListDetail(getParam(info, "musicGroupId", String.class), null));
        exportFuncMap.put(ExportEnum.QUERY_STUDENT_APPLY_DETAIL_EXPORT, info -> queryStudentApplyDetailExport(info));
        exportFuncMap.put(ExportEnum.COURSE_SCHEDULE_TEACHER_SALARY, info -> courseScheduleTeacherSalaryService.querySalaries(getQueryInfo(info, CourseScheduleTeacherSalaryQueryInfo.class, false)).getRows());
        exportFuncMap.put(ExportEnum.MUSIC_GROUP_STUDENT, info -> queryMusicGroupStudent(info));
        exportFuncMap.put(ExportEnum.COURSE_REVIEWS, info -> courseReviews(info));
        exportFuncMap.put(ExportEnum.PRACTICE_GROUP, info -> practiceGroup());
        exportFuncMap.put(ExportEnum.VIP_GROUP, info -> vipGroup());
        exportFuncMap.put(ExportEnum.EXTRA_EXERCISES_REPLYS, info -> extraExercisesReplys(info));
        exportFuncMap.put(ExportEnum.EXERCISES_SITUATIONS, info -> studentExtracurricularExercisesSituationService.findStudentExtracurricularExercisesSituations(getQueryInfo(info, StudentExercisesSituationQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.IS_SETTLEMENT_COURSE_SALARYS, info -> isSettlementCourseSalarys(info));
        exportFuncMap.put(ExportEnum.OPERATING_STUDENTS, info -> operatingStudents(info));
        exportFuncMap.put(ExportEnum.VIP_COURSE_REVIEWS, info -> vipCourseReviews(info));
        exportFuncMap.put(ExportEnum.DEGREE_REGISTRATION, info -> degreeRegistration(info));
        exportFuncMap.put(ExportEnum.COOPERATION_ORGAN, info -> cooperationOrganService.queryPage(getQueryInfo(info, CooperationOrganQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TEACHER_DEFAULT_SALARY, info -> teacherService.queryTeacherDefaultSalary(getParam(info, "organIdList", String.class)));
        exportFuncMap.put(ExportEnum.STUDENT_ORDER, info -> studentOrder(info));
        exportFuncMap.put(ExportEnum.EXPORT_SELL_ORDERS, info -> exportSellOrders(info));
        exportFuncMap.put(ExportEnum.ARREARAGE_STUDENTS, info -> musicGroupPaymentCalenderDetailService.queryArrearageStudents(getQueryInfo(info, ArrearageStudentsQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.MUSIC_GROUP_QUIT, info -> musicGroupQuitService.queryPage(getQueryInfo(info, MusicGroupQuitQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TEACHER_SERVE_INFO, info -> teacherServeInfo(info));
        exportFuncMap.put(ExportEnum.EXPORT_INDEX_ERR_DATA, info -> exportIndexErrData(info));
        exportFuncMap.put(ExportEnum.TEACHER_COURSE_STATISTICS, info -> teacherCourseStatisticsService.queryPageDetail(getQueryInfo(info, TeacherCourseStatisticsQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.EXPORT_INDEX_HISTORY_ERR_DATA, info -> indexErrDataRecordService.queryRecord(getQueryInfo(info, IndexErrRecordQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.TEACHER_LIST, info -> teacherService.queryPageDetail(getQueryInfo(info, TeacherQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.EMPLOYEE_INFO, info -> employeeInfoService.queryPage(getQueryInfo(info, EmployeeInfoQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.ORGAN_TEACHER_MEMBER_STUDENT_DATA, info -> teacherService.queryMemberStudentData(getQueryInfo(info, TeacherServeQueryInfo.class, true)).getRows());
        exportFuncMap.put(ExportEnum.ORGAN_STUDENT_OVER_VIEW, info -> organStudentOverView(info));
        exportFuncMap.put(ExportEnum.CLOUD_STUDY_STUDENT_OVER_VIEW, info -> cloudStudyStudentOverView(info));
        exportFuncMap.put(ExportEnum.CLOUD_STUDY_STUDENT_TRAIN_DATA, info -> cloudStudyStudentTrainData(info));
        exportFuncMap.put(ExportEnum.COUNT_CLOUD_TEACHER_ACTIVE, info -> countCloudTeacherActive(info));
        exportFuncMap.put(ExportEnum.COUNT_CLOUD_TEACHER_ACTIVE_DETAIL, info -> countCloudTeacherActiveDetail(info));
        exportFuncMap.put(ExportEnum.MUSIC_ENLIGHTENMENT_QUESTIONNAIRES, info -> musicEnlightenmentQuestionnaireService.queryPage(getQueryInfo(info, TeacherServeQueryInfo.class, false)).getRows());
        exportFuncMap.put(ExportEnum.EXERCISES_SITUATION, info -> studentExtracurricularExercisesSituationService.queryTeacherPerformanceIndicator(getQueryInfo(info, TeacherServeQueryInfo.class, false)));
        exportFuncMap.put(ExportEnum.STUDENT_INSTRUMENT, info -> exportStudentInstrument(info));
        exportFuncMap.put(ExportEnum.EXPORT_BILL, info -> exportBill(info));


        //导出到报表中心
//        exportManageFuncMap.put(ExportEnum.SUPER_FIND_COURSE_SCHEDULES, (info,headColumns) -> this.superFindCourseSchedules(info,headColumns));
        //针对不同的用户有不同的模板
        exportManageFuncMap.put(ExportEnum.ROUTE_ORDER_LIST1, (info) -> routeOrderList(info));
        exportManageFuncMap.put(ExportEnum.ROUTE_ORDER_LIST2, (info) -> routeOrderList(info));
        exportManageFuncMap.put(ExportEnum.ORDER_LIST1, (info) -> orderList(info));
        exportManageFuncMap.put(ExportEnum.ORDER_LIST2, (info) -> orderList(info));
        exportManageFuncMap.put(ExportEnum.ORDER_LIST_SUM, (info) -> orderListSum(info));
        exportManageFuncMap.put(ExportEnum.STUDENT_VIP_PRACTICE, (info) -> exportStudentVipPractice(info));
        exportManageFuncMap.put(ExportEnum.STUDENT_VIP_COURSE_INFO, (info) -> exportStudentVipCourseInfo(info));
        exportManageFuncMap.put(ExportEnum.STUDENT_MUSIC_THEORY_COURSE_INFO, (info) -> exportStudentMusicTheoryCourseInfo(info));
        exportManageFuncMap.put(ExportEnum.VIP_STUDENT_COURSE_MANAGE, (info) -> exportVipStudentCourseManage(info));
        exportManageFuncMap.put(ExportEnum.EXPORT_STUDENT_SUBCOURSE, (info) -> exportStudentSubCourse(info));
        exportManageFuncMap.put(ExportEnum.EXPORT_STUDENT_SERVE_INFO, (info) -> exportStudentServeInfo(info));
        exportManageFuncMap.put(ExportEnum.EXPORT_TRAINING_STATISTICS, (info) -> exportCompareRecord(info));


    }


    //导出对账单
    @Override
    public List exportBill(Map<String, Object> info) {
        String startTimeStr = getParam(info, "startTime", String.class);
        Date startTime = null;
        if (StringUtils.isNotEmpty(startTimeStr)) {
            startTime = DateUtil.stringToDate(startTimeStr, DateUtil.ISO_EXPANDED_DATE_FORMAT);
        }
        Date endTime = null;
        String endTimeStr = getParam(info, "endTime", String.class);
        if (StringUtils.isNotEmpty(endTimeStr)) {
            endTime = DateUtil.stringToDate(endTimeStr, DateUtil.ISO_EXPANDED_DATE_FORMAT);
        }
        long createdGte = startTime.getTime();
        long createdLte = DateUtil.getLastSecondWithDay(endTime).getTime();
        int pageIndex = 1;
        List<Map<String, Object>> data = new ArrayList<>();
        while (profiles.equals("prod")) {
            Map<String, Object> paymentList = null;
            HfMerchantConfig hfMerchantConfig = hfMerchantConfigService.queryByTenantId(TenantContextHolder.getTenantId());
            if (hfMerchantConfig == null) {
                throw new BizException("机构[{}]汇付商户信息找不到", TenantContextHolder.getTenantId());
            }
            try {
                paymentList = Payment.queryList(hfMerchantConfig.getAppId(), hfMerchantConfig.getMerKey(), pageIndex, createdGte, createdLte);
            } catch (Exception e) {
                e.printStackTrace();
            }
            JSONArray payments = (JSONArray) paymentList.get("payments");
            if (!paymentList.get("status").equals("succeeded")) {
                throw new BizException("查询失败，请重试");
            }

            if (payments != null && payments.size() > 0) {
                for (Object payment : payments) {
                    Map<String, Object> paymentMap = (Map<String, Object>) payment;
                    if (!paymentMap.get("status").equals("succeeded")) {
                        continue;
                    }
                    paymentMap.put("created_time", DateUtil.timeStamp2Date(paymentMap.get("created_time").toString(), null));
                    if (paymentMap.get("pay_channel").equals("alipay_qr")) {
                        paymentMap.put("pay_channel", "支付宝正扫");
                    } else if (paymentMap.get("pay_channel").equals("alipay_wap")) {
                        paymentMap.put("pay_channel", "支付宝H5支付");
                    } else {
                        paymentMap.put("pay_channel", "微信公众号支付");
                    }

                    if (paymentMap.get("status").equals("pending")) {
                        paymentMap.put("status", "交易处理中");
                    } else if (paymentMap.get("status").equals("succeeded")) {
                        paymentMap.put("status", "交易成功");
                    } else {
                        paymentMap.put("status", "交易失败");
                    }
                    if (paymentMap.get("pay_mode").equals("delay")) {
                        if (!paymentMap.containsKey("payment_confirms")) {
                            Map<String, Object> confirmMap = null;
                            try {
                                confirmMap = Payment.queryConfirmList(hfMerchantConfig.getAppId(), hfMerchantConfig.getMerKey(), paymentMap.get("id").toString());
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            if (confirmMap.containsKey("payment_confirms")) {
                                paymentMap.put("payment_confirms", confirmMap.get("payment_confirms"));
                            }
                        }
                        if (!paymentMap.containsKey("payment_confirms")) {
                            paymentMap.put("memo", "没有提交分账信息，请联系技术核查");
                            data.add(paymentMap);
                            continue;
                        }
                        JSONArray confirms = (JSONArray) paymentMap.get("payment_confirms");
                        for (Object confirm : confirms) {
                            Map<String, Object> divMemberMap = (Map<String, Object>) confirm;
                            paymentMap.put("fee_amt", divMemberMap.get("fee_amt"));
                            divMemberMap.putAll(paymentMap);

                            JSONArray divMembers = (JSONArray) divMemberMap.get("div_members");
                            Map<String, Object> divMember = (Map<String, Object>) divMembers.get(0);
                            divMemberMap.putAll(divMember);
                            if (divMemberMap.get("member_id").equals("0")) {
                                divMemberMap.put("member_id", ConfigInit.merNo);
                            }
                            data.add(divMemberMap);
                        }
                    } else {
                        JSONArray divMembers = (JSONArray) paymentMap.get("div_members");
                        for (Object divMember : divMembers) {
                            Map<String, Object> divMemberMap = (Map<String, Object>) divMember;
                            divMemberMap.putAll(paymentMap);
                            if (divMemberMap.get("member_id").equals("0")) {
                                divMemberMap.put("member_id", ConfigInit.merNo);
                            }
                            if (divMemberMap.get("fee_flag").equals("N")) {
                                divMemberMap.put("fee_amt", "0.00");
                            }
                            data.add(divMemberMap);
                        }
                    }
                }
            }
            if (paymentList.get("has_more").equals(false)) {
                break;
            }
            pageIndex++;
        }
        return data;
    }

    //乐保导出
    @Override
    public List exportStudentInstrument(Map<String, Object> info) {
        String startTimeStr = getParam(info, "startTime", String.class);
        Date startTime = null;
        if (StringUtils.isNotEmpty(startTimeStr)) {
            startTime = DateUtil.stringToDate(startTimeStr, DateUtil.ISO_EXPANDED_DATE_FORMAT);
        }
        Date endTime = null;
        String endTimeStr = getParam(info, "endTime", String.class);
        if (StringUtils.isNotEmpty(endTimeStr)) {
            endTime = DateUtil.stringToDate(endTimeStr, DateUtil.ISO_EXPANDED_DATE_FORMAT);
        }
        String organId = organizationService.getEmployeeOrgan("");

        if (startTime != null) {
            startTime = DateUtil.trunc(startTime);
        }
        if (endTime != null) {
            endTime = DateUtil.getLastTimeWithDay(endTime);
        }
        List<StudentInstrumentExportDto> instruments = studentInstrumentDao.getInstruments(startTime, endTime, organId, TenantContextHolder.getTenantId());

        if (instruments.size() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        for (StudentInstrumentExportDto instrument : instruments) {
            StudentRegistration studentMusicGroup = studentInstrumentDao.findStudentMusicGroup(instrument.getStudentId());
            if (studentMusicGroup != null) {
                instrument.setRepairerName(studentMusicGroup.getParentsName());
                instrument.setMusicGroupName(studentMusicGroup.getClassGroupName());
                instrument.setStudentStatus(studentMusicGroup.getMusicGroupStatus());
            }
        }
        return instruments;
    }

    //班级列表导出
    @Override
    public List exportClassGroup(Map<String, Object> info) {
        ClassGroupQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), ClassGroupQueryInfo.class);
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        List<ClassGroupTeachersDto> rows = classGroupService.queryClassGroupPage(queryInfo).getRows();
        for (ClassGroupTeachersDto row : rows) {
            List<ClassGroupTeacherMapper> classGroupTeacherMapperList = row.getClassGroupTeacherMapperList();
            if (classGroupTeacherMapperList.size() > 0) {
                List<ClassGroupTeacherMapper> teachingTeachers = classGroupTeacherMapperList.stream().filter(e -> e.getTeacherRole() == TeachTypeEnum.TEACHING).collect(Collectors.toList());
                if (teachingTeachers.size() > 0) {
                    row.setTeachingTeacherName(StringUtils.join(teachingTeachers.stream().map(e -> e.getUserName()).collect(Collectors.toList()), ","));
                }
                List<ClassGroupTeacherMapper> bishopTeachers = classGroupTeacherMapperList.stream().filter(e -> e.getTeacherRole() == TeachTypeEnum.BISHOP).collect(Collectors.toList());
                if (bishopTeachers.size() > 0) {
                    row.setBishopTeacherName(StringUtils.join(bishopTeachers.stream().map(e -> e.getUserName()).collect(Collectors.toList()), ","));
                }
            }
        }
        return rows;
    }

    //导出老师结转奖励
    @Override
    public List teacherCourseReward(Map<String, Object> info) {
        TeacherCourseRewardQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), TeacherCourseRewardQueryInfo.class);
        Date endTime = queryInfo.getEndTime();
        if (endTime != null) {
            queryInfo.setEndTime(DateUtil.addDays(endTime, 1));
        }
        return teacherCourseRewardService.queryPage(queryInfo).getRows();
    }

    //导出陪练课列表
    @Override
    public List practiceGroupList(Map<String, Object> info) {
        PracticeGroupQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), PracticeGroupQueryInfo.class);
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        List<PracticeGroupDto> rows = practiceGroupService.findPracticeGroups(queryInfo).getRows();
        if (rows != null && rows.size() > 0) {
            rows.forEach(e -> {
                e.setSubClassTimes(e.getTotalClassTimes() == null ? 0 : e.getTotalClassTimes() - (e.getCurrentClassTimes() == null ? 0 : e.getCurrentClassTimes()));
                if (e.getBuyMonths() == null || e.getBuyMonths() == 0) {
                    e.setPayStatus("免费");
                } else {
                    if (e.getBeRenewGroupId() == null || e.getBeRenewGroupId() == 0l) {
                        e.setPayStatus("首充");
                    } else {
                        e.setPayStatus("续费");
                    }
                }
            });
        }
        return rows;
    }

    //乐团【报名中、缴费中】 学生详情列表导出
    @Override
    public List queryStudentApplyDetailExport(Map<String, Object> info) {
        StudentRegistrationQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentRegistrationQueryInfo.class);
        List<StudentApplyDetailDto> studentApplyDetail = studentRegistrationService.queryStudentDetailPage(queryInfo).getRows();
        if (studentApplyDetail.size() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        List<MusicalListDetailDto> musicalListDetails = studentPaymentOrderDetailService.getMusicalListDetail(queryInfo.getMusicGroupId(), null);
        //获取分部年级列表
        MusicGroup musicGroup = musicGroupDao.get(queryInfo.getMusicGroupId());
        Map<Integer, String> gradeList = organizationService.getGradeList(musicGroup.getOrganId());
        for (StudentApplyDetailDto studentApplyDetailDto : studentApplyDetail) {
            if (StringUtils.isNotEmpty(studentApplyDetailDto.getCurrentGrade())) {
                String grade = gradeList.get(Integer.parseInt(studentApplyDetailDto.getCurrentGrade()));
                if (StringUtils.isNotEmpty(grade)) {
                    studentApplyDetailDto.setCurrentGrade(grade);
                }
            }
            for (MusicalListDetailDto musicalListDetail : musicalListDetails) {
                if (!musicalListDetail.getUserId().equals(studentApplyDetailDto.getStudentId())) continue;
                studentApplyDetailDto.setKitGroupPurchaseTypeEnum(musicalListDetail.getKitGroupPurchaseTypeEnum());
            }
            if (PaymentStatusEnum.YES.equals(studentApplyDetailDto.getPaymentStatus()) && studentApplyDetailDto.getKitGroupPurchaseTypeEnum() == null) {
                studentApplyDetailDto.setKitGroupPurchaseTypeEnum(KitGroupPurchaseTypeEnum.OWNED);
            }
            if (studentApplyDetailDto.getPayingStatus().equals(1)) {
                studentApplyDetailDto.setPayingStatusStr("缴费中");
            } else if (studentApplyDetailDto.getPayingStatus().equals(2)) {
                studentApplyDetailDto.setPayingStatusStr("审核中");
            }
        }
        return studentApplyDetail;
    }

    //评论列表导出
    @Override
    public List courseReviews(Map<String, Object> info) {
        CourseReviewQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), CourseReviewQueryInfo.class);
        PageInfo<CourseReviewDto> practiceGroupReviews = courseReviewService.getVipCourseReviews(queryInfo);
        if (practiceGroupReviews.getTotal() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        for (CourseReviewDto row : practiceGroupReviews.getRows()) {
            row.setClassDateStr(DateUtil.dateToString(row.getClassDate(), "yyyy-MM-dd"));
            if (row.getHandHomework() != null && row.getHandHomework() > 0) {
                row.setHandHomeworkStr("是");
            } else {
                row.setHandHomeworkStr("否");
            }
            if (row.getHasLiaison() != null && row.getHasLiaison().equals("1")) {
                row.setHasLiaison("是");
            } else {
                row.setHasLiaison("否");
            }
            if (row.getCreateTime() != null) {
                row.setCreateTimeStr(DateUtil.dateToString(row.getCreateTime(), "yyyy-MM-dd"));
            }
            if (row.getPronunciation() != null) {
                row.setPronunciationStr(row.getPronunciation() + "星");
            }
            if (row.getTempo() != null) {
                row.setTempoStr(row.getTempo() + "星");
            }
            if (row.getMusicTheory() != null) {
                row.setMusicTheoryStr(row.getMusicTheory() + "星");
            }
            if (row.getHomeWorkReplied() != null && row.getHomeWorkReplied().equals("1")) {
                row.setHomeWorkReplied("已回复");
            } else if (row.getHandHomework() != null && row.getHandHomework() > 0) {
                row.setHomeWorkReplied("未回复");
            } else {
                row.setHomeWorkReplied(null);
            }
            if (row.getAttendanceId() != null) {
                row.setAttendanceStr("是");
            } else {
                row.setAttendanceStr("否");
            }
            if (new Integer(1).equals(row.getAssignHomework())) {
                row.setAssignHomeworkStr("是");
            } else {
                row.setAssignHomeworkStr("否");
            }
        }
        return practiceGroupReviews.getRows();
    }

    //乐团管理--乐团详情-导出学员列表
    @Override
    public List queryMusicGroupStudent(Map<String, Object> info) {
        MusicGroupStudentQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), MusicGroupStudentQueryInfo.class);
        PageInfo<MusicGroupStudentsDto> musicGroupStudentsDtoPageInfo = studentManageService.queryMusicGroupStudent(queryInfo);
        //获取分部年级列表
        MusicGroup musicGroup = musicGroupDao.get(queryInfo.getMusicGroupId());
        Map<Integer, String> gradeList = organizationService.getGradeList(musicGroup.getOrganId());
        for (MusicGroupStudentsDto row : musicGroupStudentsDtoPageInfo.getRows()) {
            if (StringUtils.isNotEmpty(row.getCurrentGrade())) {
                String grade = gradeList.get(Integer.parseInt(row.getCurrentGrade()));
                if (StringUtils.isNotEmpty(grade)) {
                    row.setCurrentGrade(grade);
                }
            }
            if (row.getGender() != null) {
                if (row.getGender().equals("1")) {
                    row.setGender("男");
                } else {
                    row.setGender("女");
                }
            }
            if (row.getStudentStatus().equals("NORMAL")) {
                row.setStudentStatus("在读");
            } else if (row.getStudentStatus().equals("QUIT")) {
                row.setStudentStatus("退团");
            } else if (row.getStudentStatus().equals("APPLY")) {
                row.setStudentStatus("报名");
            } else {
                row.setStudentStatus("" + row.getStudentStatus());
            }
            if (row.getIsActive()) {
                row.setActiveName("是");
            } else {
                row.setActiveName("否");
            }
            if (row.getMusicMembershipDay() != null && row.getMusicMembershipDay() < 0) {
                row.setMusicMembershipDay1(Math.abs(row.getMusicMembershipDay()));
            }
            if (row.getNextPaymentDate() != null) {
                row.setNextPaymentDateStr(DateUtil.format(row.getNextPaymentDate(), DateUtil.DEFAULT_PATTERN));
            }
        }
        return musicGroupStudentsDtoPageInfo.getRows();
    }

    //网管课管理导出
    @Override
    public List practiceGroup() {
        String organIds = organizationService.getEmployeeOrgan("");
        List<CourseGroupExportDto> practiceGroupExports = practiceGroupDao.getPracticeGroupExport(organIds, TenantContextHolder.getTenantId());
        if (practiceGroupExports == null || practiceGroupExports.size() == 0) {
            throw new BizException("没有可导出的记录");
        }
        Set<Integer> studentIds = practiceGroupExports.stream().map(CourseGroupExportDto::getStudentId).collect(Collectors.toSet());
        List<CourseGroupExportDto> studentCourseInfos = courseScheduleDao.getStudentCourseInfo(studentIds, GroupType.PRACTICE);

        List<CourseGroupExportDto> totalClassTimes = courseScheduleDao.getStudentCourseScheduleNum(studentIds, GroupType.PRACTICE, null);
        List<CourseGroupExportDto> noStartClassTimes = courseScheduleDao.getStudentCourseScheduleNum(studentIds, GroupType.PRACTICE, CourseStatusEnum.NOT_START);
        for (CourseGroupExportDto practiceGroupExport : practiceGroupExports) {
            for (CourseGroupExportDto studentCourseInfo : studentCourseInfos) {
                if (studentCourseInfo.getStudentId().equals(practiceGroupExport.getStudentId())) {
                    practiceGroupExport.setTeacherIds(studentCourseInfo.getTeacherIds());
                    practiceGroupExport.setTeacherName(studentCourseInfo.getTeacherName());
                    practiceGroupExport.setClassEndDate(studentCourseInfo.getClassEndDate());
                    break;
                }
            }

            for (CourseGroupExportDto studentTotalClassTimes : totalClassTimes) {
                if (studentTotalClassTimes.getStudentId().equals(practiceGroupExport.getStudentId())) {
                    practiceGroupExport.setTotalClassTimes(studentTotalClassTimes.getTotalClassTimes());
                    break;
                }
            }
            for (CourseGroupExportDto noStartStudentClassTimes : noStartClassTimes) {
                if (noStartStudentClassTimes.getStudentId().equals(practiceGroupExport.getStudentId())) {
                    practiceGroupExport.setNoStartClassTimes(noStartStudentClassTimes.getTotalClassTimes());
                    break;
                }
            }
        }
        return practiceGroupExports;
    }

    //vip管理导出
    @Override
    public List vipGroup() {
        List<CourseGroupExportDto> vipGroupExports = courseScheduleDao.getVipGroupExport(organizationService.getEmployeeOrgan(""));
        if (vipGroupExports == null || vipGroupExports.size() == 0) {
            throw new BizException("没有可导出的记录");
        }
        Set<Integer> studentIds = vipGroupExports.stream().map(CourseGroupExportDto::getStudentId).collect(Collectors.toSet());
        List<Map<Integer, Date>> studentLastCourseSchedule = courseScheduleStudentPaymentDao.findStudentLastCourseSchedule(new ArrayList<>(studentIds));
        Map<Integer, String> studentLastCourseMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(studentLastCourseSchedule)) {
            studentLastCourseMap = MapUtil.convertMybatisMap(studentLastCourseSchedule);
        }
        List<CourseGroupExportDto> studentCourseInfos = courseScheduleDao.getStudentVipCourseInfo(studentIds);
        List<CourseGroupExportDto> totalClassTimes = courseScheduleDao.getStudentCourseScheduleNum(studentIds, GroupType.VIP, null);
        List<CourseGroupExportDto> noStartClassTimes = courseScheduleDao.getStudentCourseScheduleNum(studentIds, GroupType.VIP, CourseStatusEnum.NOT_START);
        for (CourseGroupExportDto vipGroupExport : vipGroupExports) {

            String lastClassDateStr = studentLastCourseMap.get(vipGroupExport.getStudentId());
            if (StringUtils.isNotBlank(lastClassDateStr)) {
                vipGroupExport.setLastClassDate(DateUtil.stringToDate(lastClassDateStr));
            }

            for (CourseGroupExportDto studentCourseInfo : studentCourseInfos) {
                if (studentCourseInfo.getStudentId().equals(vipGroupExport.getStudentId())) {
                    vipGroupExport.setTeacherIds(studentCourseInfo.getTeacherIds());
                    vipGroupExport.setTeacherName(studentCourseInfo.getTeacherName());
                    vipGroupExport.setClassStartDate(studentCourseInfo.getClassStartDate());
                    vipGroupExport.setClassEndDate(studentCourseInfo.getClassEndDate());
                    break;
                }
            }
            for (CourseGroupExportDto studentTotalClassTimes : totalClassTimes) {
                if (studentTotalClassTimes.getStudentId().equals(vipGroupExport.getStudentId())) {
                    vipGroupExport.setTotalClassTimes(studentTotalClassTimes.getTotalClassTimes());
                    break;
                }
            }
            for (CourseGroupExportDto noStartStudentClassTimes : noStartClassTimes) {
                if (noStartStudentClassTimes.getStudentId().equals(vipGroupExport.getStudentId())) {
                    vipGroupExport.setNoStartClassTimes(noStartStudentClassTimes.getTotalClassTimes());
                    break;
                }
            }
        }
        return vipGroupExports;
    }

    //学生课外训练记录导出
    @Override
    public List extraExercisesReplys(Map<String, Object> info) {
        ExtraExercilseReplyQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), ExtraExercilseReplyQueryInfo.class);
        queryInfo.setOrganIdList(organizationService.getEmployeeOrgan(queryInfo.getOrganIdList()));
        List<ExtraExerciseStudentsDto> rows = extracurricularExercisesReplyService.findExtraExercises(queryInfo).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        for (ExtraExerciseStudentsDto row : rows) {
            row.setStatusStr(Objects.isNull(row.getStatus()) || row.getStatus() == 0 ? "否" : "是");
            row.setIsViewStr(Objects.isNull(row.getIsView()) || row.getIsView() == 0 ? "否" : "是");
            row.setIsRepliedStr(Objects.isNull(row.getIsReplied()) || row.getIsReplied() == 0 ? "否" : "是");
            row.setIsRepliedTimelyStr(Objects.isNull(row.getIsRepliedTimely()) || row.getIsRepliedTimely() == 0 ? "否" : "是");
            row.setExistVipCourseStr(Objects.isNull(row.getExistVipCourse()) || row.getExistVipCourse() == 0 ? "否" : "是");
        }
        return rows;
    }

    //教师课酬导出
    @Override
    public List isSettlementCourseSalarys(Map<String, Object> info) {
        CourseSalaryQueryInfo4Web queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), CourseSalaryQueryInfo4Web.class);
        queryInfo.setOrganIdList(organizationService.getEmployeeOrgan(queryInfo.getOrganIdList()));
        List<TeacherCourseSalaryDetail4WebDto> rows = courseScheduleTeacherSalaryService.findIsSettlementCourseSalarys(queryInfo).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        for (TeacherCourseSalaryDetail4WebDto row : rows) {
            if (Objects.isNull(row.getSignInTime())) {
                row.setSignInStatusStr("未签到");
            } else {
                String signInTimeStr = DateUtil.dateToString(row.getSignInTime(), "yyyy-MM-dd HH:mm");
                if (YesOrNoEnum.YES.equals(row.getSignInStatus())) {
                    row.setSignInStatusStr(signInTimeStr + "(正常签到)");
                } else {
                    row.setSignInStatusStr(signInTimeStr + "(异常签到)");
                }
            }
            if (Objects.isNull(row.getSignOutTime())) {
                row.setSignOutStatusStr("未签退");
            } else {
                String signOutTimeStr = DateUtil.dateToString(row.getSignOutTime(), "yyyy-MM-dd HH:mm");
                if (YesOrNoEnum.YES.equals(row.getSignOutStatus())) {
                    row.setSignOutStatusStr(signOutTimeStr + "(正常签退)");
                } else {
                    row.setSignOutStatusStr(signOutTimeStr + "(异常签退)");
                }
            }
            if (row.getBelongDaya() == 1) {
                row.setSalaryType("基本课酬");
            } else {
                row.setSalaryType("其它课酬");
            }
        }
        return rows;
    }

    //运营指标管理导出
    @Override
    public List operatingStudents(Map<String, Object> info) {
        StudentOperatingQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentOperatingQueryInfo.class);
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        PageInfo<Student4operating> PageOperatingStudents = studentManageService.getOperatingStudents(queryInfo);

        if (PageOperatingStudents.getTotal() <= 0) {
            throw new BizException("导出记录不存在");
        }
        List<Student4operating> rows = PageOperatingStudents.getRows();
        for (Student4operating row : rows) {
            if (row.getOperatingTag() != null && row.getOperatingTag() == 1) {
                row.setOperatingTagStr("是");
            } else {
                row.setOperatingTagStr("否");
            }
            if (row.getVipTimes() != null && row.getVipTimes() > 0) {
                row.setVipTimesStr("是");
            } else {
                row.setVipTimesStr("否");
            }
            if (row.getMusicNetWorkTimes() != null && row.getMusicNetWorkTimes() > 0) {
                row.setMusicNetWorkTimesStr("是");
            } else {
                row.setMusicNetWorkTimesStr("否");
            }
            if (row.getFreePracticeTimes() != null && row.getFreePracticeTimes() > 0) {
                row.setFreePracticeTimesStr("是");
            } else {
                row.setFreePracticeTimesStr("否");
            }
            if (row.getBuyPracticeTimes() != null && row.getBuyPracticeTimes() > 0) {
                row.setBuyPracticeTimesStr("是");
            } else {
                row.setBuyPracticeTimesStr("否");
            }
        }
        return rows;
    }

    //vip评论列表导出
    @Override
    public List vipCourseReviews(Map<String, Object> info) {
        CourseReviewQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), CourseReviewQueryInfo.class);
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        queryInfo.setIsExport(1);
        PageInfo<CourseReviewDto> practiceGroupReviews = courseReviewService.getVipCourseReviews(queryInfo);
        if (practiceGroupReviews.getTotal() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        for (CourseReviewDto row : practiceGroupReviews.getRows()) {
            row.setClassDateStr(DateUtil.dateToString(row.getClassDate(), "yyyy-MM-dd"));
            if (row.getHandHomework() != null && row.getHandHomework() > 0) {
                row.setHandHomeworkStr("是");
            } else {
                row.setHandHomeworkStr("否");
            }
            if (row.getHasLiaison() != null && row.getHasLiaison().equals("1")) {
                row.setHasLiaison("是");
            } else {
                row.setHasLiaison("否");
            }
            if (row.getCreateTime() != null) {
                row.setCreateTimeStr(DateUtil.dateToString(row.getCreateTime(), "yyyy-MM-dd"));
            }
            if (row.getPronunciation() != null) {
                row.setPronunciationStr(row.getPronunciation() + "星");
            }
            if (row.getTempo() != null) {
                row.setTempoStr(row.getTempo() + "星");
            }
            if (row.getMusicTheory() != null) {
                row.setMusicTheoryStr(row.getMusicTheory() + "星");
            }
            if (row.getHomeWorkReplied() != null && row.getHomeWorkReplied().equals("1")) {
                row.setHomeWorkReplied("已回复");
            } else if (row.getHandHomework() != null && row.getHandHomework() > 0) {
                row.setHomeWorkReplied("未回复");
            } else {
                row.setHomeWorkReplied(null);
            }
            if (row.getAttendanceId() != null) {
                row.setAttendanceStr("是");
            } else {
                row.setAttendanceStr("否");
            }
            if (new Integer(1).equals(row.getAssignHomework())) {
                row.setAssignHomeworkStr("是");
            } else {
                row.setAssignHomeworkStr("否");
            }
        }
        return practiceGroupReviews.getRows();
    }

    //考级报名导出
    @Override
    public List degreeRegistration(Map<String, Object> info) {
        DegreeQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), DegreeQueryInfo.class);
        queryInfo.setSort("create_time_");
        queryInfo.setOrder("ASC");
        return degreeRegistrationService.getPageList(queryInfo).getRows();
    }

    //回款统计
    @Override
    public List studentOrder(Map<String, Object> info) {
        String organIds = getParam(info, "organIds", String.class);
        Date date = DateUtil.stringToDate(getParam(info, "date", String.class), DateUtil.ISO_EXPANDED_DATE_FORMAT);
        SysUser sysUser = sysUserService.getUser();
        organIds = organizationService.getEmployeeOrgan(sysUser.getId(), organIds, sysUser.getIsSuperAdmin());
        Date startTime = DateUtil.getFirstDayOfMonth(date);
        Date EndTime = DateUtil.getLastSecondWithDay(DateUtil.getLastDayOfMonth(date));

        List<OrderTypeEnum> orderTypeList = new ArrayList<>();
        orderTypeList.add(OrderTypeEnum.SPORADIC);
        orderTypeList.add(OrderTypeEnum.PRACTICE_GROUP_BUY);
        orderTypeList.add(OrderTypeEnum.PRACTICE_GROUP_RENEW);
        orderTypeList.add(OrderTypeEnum.SMALL_CLASS_TO_BUY);
        List<OrderByTypeExportDto> orders = studentPaymentOrderDao.getOrderByMonthAndType(organIds, orderTypeList, startTime, EndTime);

        if (orders.size() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        List<Long> vipGroupIds = orders.stream().filter(e -> e.getGroupType().equals(GroupType.VIP)).map(OrderByTypeExportDto::getMusicGroupId).collect(Collectors.toList());
        List<Long> practiceGroupIds = orders.stream().filter(e -> e.getGroupType().equals(GroupType.PRACTICE)).map(OrderByTypeExportDto::getMusicGroupId).collect(Collectors.toList());
        List<Integer> studentIds = orders.stream().filter(e -> e.getGroupType().equals(GroupType.SPORADIC)).map(OrderByTypeExportDto::getStudentId).collect(Collectors.toList());

        List<VipBuyResultDto> vipGroupTeachers = new ArrayList<>();
        List<PracticeCourseDto> practiceGroupsTeacher = new ArrayList<>();
        List<Student> studentTeachers = new ArrayList<>();
        if (vipGroupIds.size() > 0) {
            vipGroupTeachers = vipGroupDao.getGroupTeachers(vipGroupIds, TenantContextHolder.getTenantId());
        }

        if (practiceGroupIds.size() > 0) {
            practiceGroupsTeacher = practiceGroupDao.getPracticeGroupByIds(practiceGroupIds);
        }
        if (studentIds.size() > 0) {
            studentTeachers = studentDao.getStudentTeacher(studentIds);
        }

        for (OrderByTypeExportDto order : orders) {
            for (VipBuyResultDto vipGroupTeacher : vipGroupTeachers) {
                if (order.getGroupType().equals(GroupType.VIP) && order.getMusicGroupId().equals(vipGroupTeacher.getVipGroupId().longValue())) {
                    order.setTeacherName(vipGroupTeacher.getTeacherName());
                    order.setEduTeacherName(vipGroupTeacher.getEduTeacherName());
                    break;
                }
            }
            for (PracticeCourseDto practiceCourseDto : practiceGroupsTeacher) {
                if (order.getGroupType().equals(GroupType.PRACTICE) && order.getMusicGroupId().equals(practiceCourseDto.getId())) {
                    order.setTeacherName(practiceCourseDto.getTeacherName());
                    order.setEduTeacherName(practiceCourseDto.getEduTeacherName());
                    break;
                }
            }
            for (Student studentTeacher : studentTeachers) {
                if (order.getGroupType().equals(GroupType.SPORADIC) && studentTeacher.getUserId().equals(order.getStudentId())) {
                    order.setTeacherName(studentTeacher.getTeacherName());
                    break;
                }
            }
        }
        return orders;
    }

    //销售列表导出
    @Override
    public List exportSellOrders(Map<String, Object> info) {
        SellOrderQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), SellOrderQueryInfo.class);
        queryInfo.setOrganIdList(organizationService.getEmployeeOrgan(queryInfo.getOrganIdList()));
        if (queryInfo.getEndTime() != null) {
            queryInfo.setEndTime(DateUtil.getLastTimeWithDay(queryInfo.getEndTime()));
        }
        List<SellOrder> rows = sellOrderService.queryPage(queryInfo).getRows();
        for (SellOrder row : rows) {
            if (StringUtils.isNoneBlank(row.getPaymentChannel())) {
                row.setPaymentChannelStr(PaymentChannelEnum.valueOf(row.getPaymentChannel()).getDesc());
            }
            row.setAccountTypeStr(AccountType.INTERNAL.equals(row.getAccountType()) ? "对内" : "对外");
            switch (row.getReceiveStatus()) {
                case "NO_RECEIVE":
                    row.setReceiveStatusStr("未确认");
                    break;
                case "MANUAL_RECEIVE":
                    row.setReceiveStatusStr("手动确认");
                    break;
                case "AUTO_RECEIVE":
                    row.setReceiveStatusStr("自动确认");
                    break;
            }
            row.setOrderAmount(row.getExpectAmount().add(row.getCouponRemitAmount()));
        }
        return rows;
    }

    //服务指标明细导出
    @Override
    public List teacherServeInfo(Map<String, Object> info) {
        TeacherServeQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), TeacherServeQueryInfo.class);
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
        PageInfo<TeacherServeDto> result = studentExtracurricularExercisesSituationService.queryTeacherServeInfo(queryInfo);
        if (CollectionUtils.isEmpty(result.getRows())) {
            throw new BizException("没有可导出的记录");
        }
        BigDecimal oneHundred = new BigDecimal(100);
        BigDecimal zero = new BigDecimal("0.00");
        for (TeacherServeDto row : result.getRows()) {
            row.setDateRange(com.ym.mec.util.date.DateUtil.dateToString(row.getMonday(), "yyyy-MM-dd") + '~' + com.ym.mec.util.date.DateUtil.dateToString(row.getSunday(), "yyyy-MM-dd"));
            if (row.getActualExercisesNum() <= 0) {
                row.setSubmitRate(zero.toString() + "%");
            } else {
                BigDecimal submitRate = new BigDecimal(row.getExercisesReplyNum()).divide(new BigDecimal(row.getActualExercisesNum()), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHundred);
                row.setSubmitRate(submitRate + "%");
            }
        }
        return result.getRows();
    }

    //首页异常统计导出
    @Override
    public List exportIndexErrData(Map<String, Object> info) {
        String organId = getParam(info, "organId", String.class);
        IndexErrorType errorType = getParam(info, "errorType", IndexErrorType.class);
        SysUser sysUser = sysUserService.getUser();
        organId = organizationService.getEmployeeOrgan(sysUser.getId(), organId, sysUser.getIsSuperAdmin());
        List<IndexErrorDataExportDto> result = indexService.exportIndexErrData(organId, errorType);
        if (CollectionUtils.isEmpty(result)) {
            throw new BizException("没有可导出的记录");
        }
        return result;
    }

    //分部云教练学员数据预览导出
    @Override
    public List organStudentOverView(Map<String, Object> info) {
        OrganCloudStudyStudentDataQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), OrganCloudStudyStudentDataQueryInfo.class);
        String organIds = organizationService.getEmployeeOrgan("");
        if (StringUtils.isEmpty(organIds)) {
            throw new BizException("没有可导出的记录");
        }
        List<Integer> collect = Arrays.stream(organIds.split(",")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
        List<Integer> ids = collect.stream().filter(id -> !OrganizationService.EXCLUDE_ORGAN_IDS.contains(id)).collect(Collectors.toList());
        if (ids == null || ids.size() == 0) {
            throw new BizException("没有可导出的记录");
        }
        List<EduOrganStudentDataDto> rows = studentService.queryOrganStudentOverView(ids, queryInfo).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        return rows;
    }

    //分部云教练学员训练数据导出
    @Override
    public List cloudStudyStudentTrainData(Map<String, Object> info) {
        StudentQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentQueryInfo.class);
        List<EduOrganStudentListExportDto> rows = ((PageInfo<EduOrganStudentListExportDto>) studentService.exportOrganStudentData(queryInfo).getDetail()).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        for (EduOrganStudentListExportDto row : rows) {
            row.setCloudStudyUseTime(Math.round(row.getCloudStudyUseTime()));
            row.setCloudStudyUseAvgTime(Math.round(row.getCloudStudyUseAvgTime()));
        }
        return rows;
    }

    //分部云教练学员数据详情导出
    @Override
    public List cloudStudyStudentOverView(Map<String, Object> info) {
        OrganCloudStudyStudentDataQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), OrganCloudStudyStudentDataQueryInfo.class);
        String organIds = organizationService.getEmployeeOrgan("");
        if (StringUtils.isEmpty(organIds)) {
            throw new BizException("没有可导出的记录");
        }
        List<Integer> collect = Arrays.stream(organIds.split(",")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
        List<Integer> ids = collect.stream().filter(id -> !OrganizationService.EXCLUDE_ORGAN_IDS.contains(id)).collect(Collectors.toList());
        if (ids == null || ids.size() == 0) {
            throw new BizException("没有可导出的记录");
        }
        List<EduOrganStudentDataDto> rows = indexService.organStudentOverView(ids, queryInfo).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        return rows;
    }

    //乐团声部在读人数导出
    @Override
    public void musicGroupNormalStudentNum(HttpServletResponse response, ExportDto exportDto) throws IOException {
        String organIds = getParam(exportDto.getQueryInfo(), "organIds", String.class);
        SysUser sysUser = sysUserService.getUser();
        organIds = organizationService.getEmployeeOrgan(sysUser.getId(), organIds, sysUser.getIsSuperAdmin());

        List<MusicGroupStatusEnum> musicGroupStatusList = new ArrayList<>();
        musicGroupStatusList.add(MusicGroupStatusEnum.PAY);
        musicGroupStatusList.add(MusicGroupStatusEnum.PREPARE);
        musicGroupStatusList.add(MusicGroupStatusEnum.PROGRESS);
        musicGroupStatusList.add(MusicGroupStatusEnum.PAUSE);
        List<MusicGroupRegisterDto> musicGroupRegisters = musicGroupDao.getMusicGroupRegister(musicGroupStatusList, organIds, TenantContextHolder.getTenantId());

        if (musicGroupRegisters.size() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        List<String> musicGroupIds = musicGroupRegisters.stream().map(MusicGroupRegisterDto::getMusicGroupId).collect(Collectors.toList());

        List<RegisterSubjectDto> registerSubjects = musicGroupDao.getRegisterSubjectNum(musicGroupIds, StudentMusicGroupStatusEnum.NORMAL, null);

        HashSet<Integer> added = new HashSet<>();
        //获取用户选择的表头和表字段
        Map<String, String> exportMap = getExportMap(exportDto);
        Set<String> header = new LinkedHashSet<>(exportMap.keySet());
        Set<String> body = new LinkedHashSet<>(exportMap.values());
        for (RegisterSubjectDto registerSubject : registerSubjects) {
            if (!added.contains(registerSubject.getSubjectId())) {
                added.add(registerSubject.getSubjectId());
                header.add(registerSubject.getSubjectName());
                body.add("subject" + registerSubject.getSubjectId());
            }
        }

        List<Map<String, Object>> data = new ArrayList<>();
        for (MusicGroupRegisterDto musicGroupRegister : musicGroupRegisters) {
            added.clear();
            HashMap<String, Object> musicGroupRegisterMap = new HashMap<>();

            musicGroupRegisterMap.put("organName", musicGroupRegister.getOrganName());
            musicGroupRegisterMap.put("musicGroupName", musicGroupRegister.getMusicGroupName());
            musicGroupRegisterMap.put("musicGroupStatus", musicGroupRegister.getMusicGroupStatus().getMsg());
            musicGroupRegisterMap.put("normalNum", musicGroupRegister.getNormalNum());

            for (RegisterSubjectDto registerSubject : registerSubjects) {
                if (registerSubject.getMusicGroupId().equals(musicGroupRegister.getMusicGroupId())) {
                    added.add(registerSubject.getSubjectId());
                    musicGroupRegisterMap.put("subject" + registerSubject.getSubjectId(), registerSubject.getNum());
                }
                if (!added.contains(registerSubject.getSubjectId())) {
                    musicGroupRegisterMap.put("subject" + registerSubject.getSubjectId(), 0);
                }
            }
            data.add(musicGroupRegisterMap);
        }

        OutputStream outputStream = response.getOutputStream();
        try {
            String[] headerStr = header.toArray(new String[header.size()]);
            String[] bodyStr = body.toArray(new String[body.size()]);

            HSSFWorkbook workbook = POIUtil.exportExcel(headerStr, bodyStr, data);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=lender-" + DateUtil.getDate(new Date()) + ".xls");

            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //分部云教练活动统计数据导出
    @Override
    public List countCloudTeacherActive(Map<String, Object> info) {
        CloudTeacherActiveQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), CloudTeacherActiveQueryInfo.class);
        String organIds = organizationService.getEmployeeOrgan("");
        if (StringUtils.isEmpty(organIds)) {
            throw new BizException("没有可导出的记录");
        }
        List<Integer> collect = Arrays.stream(organIds.split(",")).mapToInt(Integer::parseInt).boxed().collect(Collectors.toList());
        List<Integer> ids = collect.stream().filter(id -> !OrganizationService.EXCLUDE_ORGAN_IDS.contains(id)).collect(Collectors.toList());
        if (ids == null || ids.size() == 0) {
            throw new BizException("没有可导出的记录");
        }
        Object object = studentService.countCloudTeacherActive(ids, queryInfo).get("resultList");
        if (object == null) {
            throw new BizException("没有可导出的记录");
        }
        return (List<CloudTeacherActiveTargetDto>) object;
    }

    //云教练活动统计详情
    @Override
    public List countCloudTeacherActiveDetail(Map<String, Object> info) {
        CloudTeacherActiveQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), CloudTeacherActiveQueryInfo.class);
        List<CloudTeacherActiveTargetDetailDto> rows = studentService.countCloudTeacherActiveDetail(queryInfo).getRows();
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的记录");
        }
        //获取分部年级列表
        Map<Integer, String> gradeList = organizationService.getGradeList(Integer.parseInt(queryInfo.getOrganIds()));
        for (CloudTeacherActiveTargetDetailDto row : rows) {
            if (StringUtils.isNotEmpty(row.getCurrentGradeNum())) {
                String grade = gradeList.get(Integer.parseInt(row.getCurrentGradeNum()));
                if (StringUtils.isNotEmpty(grade)) {
                    row.setCurrentGradeNum(grade);
                }
            }
        }
        return rows;
    }

    @Override
    public <T> T getQueryInfo(Map<String, Object> info, Class<T> clazz, Boolean organFlag) {
        if (organFlag) {
            info.put("organId", organizationService.getEmployeeOrgan(info.get("organId")));
        }
        return JSONObject.parseObject(JSONObject.toJSONString(info), clazz);
    }

    @Override
    public <T> T getParam(Map<String, Object> info, String key, Class<T> clazz) {
        try {
            return info.get(key) == null ? clazz.newInstance() : (T) (info.get(key));
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }


    //报名中缴费中乐团缴费情况导出
    @Override
    public void musicGroupRegister(HttpServletResponse response, ExportDto exportDto) throws IOException {
        String organIds = getParam(exportDto.getQueryInfo(), "organIds", String.class);
        SysUser sysUser = sysUserService.getUser();
        organIds = organizationService.getEmployeeOrgan(sysUser.getId(), organIds, sysUser.getIsSuperAdmin());
        List<MusicGroupStatusEnum> musicGroupStatusList = new ArrayList<>();
        musicGroupStatusList.add(MusicGroupStatusEnum.APPLY);
        musicGroupStatusList.add(MusicGroupStatusEnum.PAY);

        List<MusicGroupRegisterDto> musicGroupRegisters = musicGroupDao.getMusicGroupRegister(musicGroupStatusList, organIds, TenantContextHolder.getTenantId());

        if (musicGroupRegisters.size() <= 0) {
            throw new BizException("没有可导出的记录");
        }
        List<String> musicGroupIds = musicGroupRegisters.stream().map(MusicGroupRegisterDto::getMusicGroupId).collect(Collectors.toList());

        List<RegisterSubjectDto> registerSubjects = musicGroupDao.getRegisterSubjectNum(musicGroupIds, null, 2);
        List<MusicGroupRegisterDto> musicGroupRegisterOrders = musicGroupDao.getMusicGroupRegisterOrder(musicGroupIds);
        List<MusicGroupRegisterDto> musicGroupRegisterTotalMoneys = musicGroupDao.getMusicGroupRegisterTotalMoney(musicGroupIds);

        List<MusicGroupBuildLog> musicGroupAuditSuccess = musicGroupBuildLogDao.getMusicGroupAuditSuccess(musicGroupIds);
        HashSet<Integer> added = new HashSet<>();
        //获取用户选择的表头和表字段
        Map<String, String> exportMap = getExportMap(exportDto);
        Set<String> header = new LinkedHashSet<>(exportMap.keySet());
        Set<String> body = new LinkedHashSet<>(exportMap.values());
        for (RegisterSubjectDto registerSubject : registerSubjects) {
            if (!added.contains(registerSubject.getSubjectId())) {
                added.add(registerSubject.getSubjectId());
                header.add(registerSubject.getSubjectName());
                body.add("subject" + registerSubject.getSubjectId());
            }
        }
        List<Map<String, Object>> data = new ArrayList<>();
        for (MusicGroupRegisterDto musicGroupRegister : musicGroupRegisters) {
            added.clear();
            HashMap<String, Object> musicGroupRegisterMap = new HashMap<>();
            int registerPayNum = 0;
            musicGroupRegisterMap.put("organName", musicGroupRegister.getOrganName());
            musicGroupRegisterMap.put("musicGroupName", musicGroupRegister.getMusicGroupName());
            musicGroupRegisterMap.put("musicGroupStatus", musicGroupRegister.getMusicGroupStatus().getMsg());
            musicGroupRegisterMap.put("registerNum", musicGroupRegister.getRegisterNum());
            for (MusicGroupRegisterDto musicGroupRegisterOrder : musicGroupRegisterOrders) {
                if (musicGroupRegisterOrder.getMusicGroupId().equals(musicGroupRegister.getMusicGroupId())) {
                    musicGroupRegister.setGroupBuyMusicalNum(musicGroupRegisterOrder.getGroupBuyMusicalNum());
                }
            }
            for (MusicGroupRegisterDto musicGroupRegisterTotalMoney : musicGroupRegisterTotalMoneys) {
                if (musicGroupRegisterTotalMoney.getMusicGroupId().equals(musicGroupRegister.getMusicGroupId())) {
                    musicGroupRegister.setTotalMoney(musicGroupRegisterTotalMoney.getTotalMoney());
                }
            }

            for (RegisterSubjectDto registerSubject : registerSubjects) {
                if (registerSubject.getMusicGroupId().equals(musicGroupRegister.getMusicGroupId())) {
                    added.add(registerSubject.getSubjectId());
                    musicGroupRegisterMap.put("subject" + registerSubject.getSubjectId(), registerSubject.getNum());
                    registerPayNum += registerSubject.getNum();
                }
                if (!added.contains(registerSubject.getSubjectId())) {
                    musicGroupRegisterMap.put("subject" + registerSubject.getSubjectId(), 0);
                }
            }
            for (MusicGroupBuildLog groupAuditSuccess : musicGroupAuditSuccess) {
                if (!groupAuditSuccess.getMusicGroupId().equals(musicGroupRegister.getMusicGroupId())) continue;
                musicGroupRegisterMap.put("auditSuccessTime", groupAuditSuccess.getCreateTime());
            }
            musicGroupRegisterMap.put("groupBuyMusicalNum", musicGroupRegister.getGroupBuyMusicalNum());
            musicGroupRegisterMap.put("registerPayNum", registerPayNum);
            musicGroupRegisterMap.put("totalMoney", musicGroupRegister.getTotalMoney());
            data.add(musicGroupRegisterMap);
        }

        OutputStream outputStream = response.getOutputStream();
        try {
            String[] headerStr = header.toArray(new String[header.size()]);
            String[] bodyStr = body.toArray(new String[body.size()]);

            HSSFWorkbook workbook = POIUtil.exportExcel(headerStr, bodyStr, data);
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;filename=lender-" + DateUtil.getDate(new Date()) + ".xls");

            outputStream = response.getOutputStream();
            workbook.write(outputStream);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //财务管理导出
    @Override
    public HttpResponseResult routeOrderList(Map<String, Object> info) {
        StudentPaymentOrderQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentPaymentOrderQueryInfo.class);
        SysUser sysUser = sysUserService.getUser();
        queryInfo.setRoutingOrganId(organizationService.getEmployeeOrgan(sysUser.getId(), queryInfo.getRoutingOrganId(), sysUser.getIsSuperAdmin()));
        if (StringUtils.isNotBlank(queryInfo.getSearch())) {
            List<BasicUserDto> users = studentPaymentOrderDao.getUsers(queryInfo.getSearch());
            List<Integer> userIds = users.stream().map(BasicUserDto::getUserId).collect(Collectors.toList());
            if (userIds.size() <= 0) {
                userIds.add(0);
            }
            queryInfo.setUserIds(userIds);
        }
        queryInfo.setOrderType("3");
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        int count = studentPaymentRouteOrderDao.queryCount(params);
        if (count <= 0) {
            return BaseController.failed("没有可导出的数据");
        }
        if (count > 50000) {
            return BaseController.failed("数据集太大，不能导出.最大数据集不能超过50000");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.ROUTE_ORDER, sysUser.getId());
        return this.asyncExport(() -> this.routeOrderList(params, managerDownload),
                managerDownload.getName());
    }

    //学员小课记录导出
    @Override
    public HttpResponseResult exportStudentVipPractice(Map<String, Object> info) {
        String organId = getParam(info, "organId", String.class);
        Boolean hasCourse = courseScheduleStudentPaymentDao.hasCourse(organId, TenantContextHolder.getTenantId());
        if (hasCourse == null || !hasCourse) {
            return BaseController.failed("没有可导出的数据");
        }
        Integer tenantId = TenantContextHolder.getTenantId();
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.STUDENT_VIP_PRACTICE, sysUserService.getUserId());
        return this.asyncExport(() -> this.studentVipPractice(organId, managerDownload, tenantId),
                managerDownload.getName());
    }

    //学员小课记录导出
    @Override
    public HttpResponseResult exportStudentVipCourseInfo(Map<String, Object> info) {
        String organId = getParam(info, "organId", String.class);
        Integer tenantId = TenantContextHolder.getTenantId();
        Boolean hasCourse = courseScheduleStudentPaymentDao.hasStudentMusicTheoryCourseInfo(organId, tenantId, "VIP");
        if (hasCourse == null || !hasCourse) {
            return BaseController.failed("没有可导出的数据");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.STUDENT_VIP_COURSE_INFO, sysUserService.getUserId());
        return this.asyncExport(() -> this.queryStudentCourseInfo(organId, tenantId, "VIP", managerDownload, ExportEnum.STUDENT_VIP_COURSE_INFO),
                managerDownload.getName());
    }

    //vip学员课程管理
    @Override
    public HttpResponseResult exportVipStudentCourseManage(Map<String, Object> info) {
        SysUser sysUser = sysUserService.getUser();
        String organId = organizationService.getEmployeeOrgan(sysUser.getId(), getParam(info, "organId", String.class), sysUser.getIsSuperAdmin());
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.VIP_STUDENT_COURSE_MANAGE, sysUser.getId());
        Integer tenantId = TenantContextHolder.getTenantId();
        return this.asyncExport(() -> this.queryVipStudentCourseManage(organId, tenantId, managerDownload, ExportEnum.VIP_STUDENT_COURSE_MANAGE),
                managerDownload.getName());
    }

    @Override
    public HttpResponseResult exportStudentSubCourse(Map<String, Object> info) {
        SysUser sysUser = sysUserService.getUser();
        String organId = organizationService.getEmployeeOrgan(sysUser.getId(), getParam(info, "organId", String.class), sysUser.getIsSuperAdmin());
        Integer tenantId = TenantContextHolder.getTenantId();
        List<ExportStudentSubCourse> rows = activityUserMapperService.exportStudentSubCourse(organId, tenantId);
        this.checkRows(rows);
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.EXPORT_STUDENT_SUBCOURSE, sysUser.getId());
        return this.asyncExport(() -> this.initExportInfo(rows, managerDownload, ExportEnum.EXPORT_STUDENT_SUBCOURSE),
                managerDownload.getName());
    }

    private <T> void checkRows(List<T> rows){
        if (CollectionUtils.isEmpty(rows)) {
            throw new BizException("没有可导出的数据");
        }
        if (rows.size() > 65535) {
            throw new BizException("数据集太大，不能导出.最大数据集不能超过");
        }
    }
    private void checkRows(Integer count){
        if(count == null || count <= 0){
            throw new BizException("没有可导出的数据");
        }
        if(count > 65535){
            throw new BizException("数据集太大，不能导出.最大数据集不能超过65535");
        }
    }

    //导出训练统计
    private HttpResponseResult exportCompareRecord(Map<String, Object> info){
        ExportCompareQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), ExportCompareQueryInfo.class);
        SysUser user = sysUserService.getUser();
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(user.getId(), queryInfo.getOrganId(), user.getIsSuperAdmin()));
        Integer count = sysMusicCompareRecordDao.countExportCompareRecord(queryInfo);
        checkRows(count);
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.EXPORT_TRAINING_STATISTICS,user.getId());
        return this.asyncExport(() -> this.initExportInfo(sysMusicCompareRecordDao.exportCompareRecord(queryInfo), managerDownload,ExportEnum.EXPORT_TRAINING_STATISTICS),
                managerDownload.getName());
    }


    private HttpResponseResult exportStudentServeInfo(Map<String, Object> info) {
        SysUser sysUser = sysUserService.getUser();

        String organId = organizationService.getEmployeeOrgan(sysUser.getId(), getParam(info, "organId", String.class), sysUser.getIsSuperAdmin());
        info.put("organIds", organId);

        Integer tenantId = TenantContextHolder.getTenantId();
        info.put("tenantId", tenantId);

        List<StudentServeDto> rows = studentExtracurricularExercisesSituationDao.queryStudentServeInfo(info);
        if (CollectionUtils.isEmpty(rows)) {
            return BaseController.failed("没有可导出的数据");
        }
        if (rows.size() > 50000) {
            return BaseController.failed("数据集太大，不能导出.最大数据集不能超过50000");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.EXPORT_STUDENT_SERVE_INFO, sysUser.getId());
        return this.asyncExport(() -> this.initExportInfo(rows, managerDownload, ExportEnum.EXPORT_STUDENT_SERVE_INFO),
                managerDownload.getName());
    }

    @Autowired
    private StudentExtracurricularExercisesSituationDao studentExtracurricularExercisesSituationDao;

    private <T> void initExportInfo(List<T> rows, ManagerDownload managerDownload, ExportEnum exportEnum) {
        exportManagerDownload(getHSSFWorkbook(rows,exportEnum), managerDownload);
    }


    //学员小课记录导出
    @Override
    public HttpResponseResult exportStudentMusicTheoryCourseInfo(Map<String, Object> info) {
        String organId = getParam(info, "organId", String.class);
        Integer tenantId = TenantContextHolder.getTenantId();
        Boolean hasCourse = courseScheduleStudentPaymentDao.hasStudentMusicTheoryCourseInfo(organId, tenantId, "THEORY");
        if (hasCourse == null || !hasCourse) {
            return BaseController.failed("没有可导出的数据");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.STUDENT_MUSIC_THEORY_COURSE_INFO, sysUserService.getUserId());
        return this.asyncExport(() -> this.queryStudentCourseInfo(organId, tenantId, "THEORY", managerDownload, ExportEnum.STUDENT_MUSIC_THEORY_COURSE_INFO),
                managerDownload.getName());
    }

    //订单列表导出
    @Override
    public HttpResponseResult orderList(Map<String, Object> info) {
        StudentPaymentOrderQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentPaymentOrderQueryInfo.class);
        SysUser sysUser = sysUserService.getUser();
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(sysUser.getId(), queryInfo.getOrganId(), sysUser.getIsSuperAdmin()));
        if (StringUtils.isNotBlank(queryInfo.getSearch())) {
            List<BasicUserDto> users = studentPaymentOrderDao.getUsers(queryInfo.getSearch());
            List<Integer> userIds = users.stream().map(BasicUserDto::getUserId).collect(Collectors.toList());
            if (userIds.size() <= 0) {
                userIds.add(0);
            }
            queryInfo.setUserIds(userIds);
        }
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        int count = studentPaymentOrderDao.queryCount(params);
        if (count <= 0) {
            return BaseController.failed("没有可导出的数据");
        }
        if (count > 50000) {
            return BaseController.failed("数据集太大，不能导出.最大数据集不能超过50000");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.ORDER, sysUser.getId());
        return this.asyncExport(() -> this.orderList(params, managerDownload),
                managerDownload.getName());
    }

    //订单列表导出
    @Override
    public HttpResponseResult orderListSum(Map<String, Object> info) {
        StudentPaymentOrderQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info), StudentPaymentOrderQueryInfo.class);
        SysUser sysUser = sysUserService.getUser();
        queryInfo.setOrganId(organizationService.getEmployeeOrgan(sysUser.getId(), queryInfo.getOrganId(), sysUser.getIsSuperAdmin()));
        if (StringUtils.isNotBlank(queryInfo.getSearch())) {
            List<BasicUserDto> users = studentPaymentOrderDao.getUsers(queryInfo.getSearch());
            List<Integer> userIds = users.stream().map(BasicUserDto::getUserId).collect(Collectors.toList());
            if (userIds.size() <= 0) {
                userIds.add(0);
            }
            queryInfo.setUserIds(userIds);
        }
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        int count = studentPaymentOrderDao.queryCount(params);
        if (count <= 0) {
            return BaseController.failed("没有可导出的数据");
        }
        if (count > 50000) {
            return BaseController.failed("数据集太大，不能导出.最大数据集不能超过50000");
        }
        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.ORDER_LIST_SUM, sysUser.getId());
        return this.asyncExport(() -> this.orderListSum(params, managerDownload),
                managerDownload.getName());
    }

    //保存下载记录
    @Override
    public ManagerDownload saveManagerDownload(ExportTypeEnum exportTypeEnum, Integer userId) {
        Date nowDate = new Date();
        String fileName = new StringBuffer(exportTypeEnum.getDesc())
                .append("-")
                .append(idGeneratorService.generatorId("download"))
                .append("-")
                .append(DateUtil.getDate(nowDate))
                .append(".xls").toString();
        ManagerDownload managerDownload = new ManagerDownload();
        managerDownload.setType(exportTypeEnum);
        managerDownload.setUserId(userId);
        managerDownload.setName(fileName);
        managerDownload.setFileUrl("");
        managerDownload.setCreateTime(nowDate);
        managerDownload.setUpdateTime(nowDate);
        managerDownloadDao.insert(managerDownload);
        return managerDownload;
    }

    public BigDecimal getActualAmount(BigDecimal price, StudentPaymentOrderExportDto row) {
        if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
            return price.multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
        }
        return BigDecimal.ZERO;
    }


    @Override
    public void orderList(Map<String, Object> params, ManagerDownload managerDownload) {
        List<StudentPaymentOrderExportDto> studentPaymentOrderExportDtos = studentPaymentOrderService.ExportQueryPage(params);
        long i = 1;
        Map<Integer, String> cooperationOrganMap = new HashMap<>();
        List<Integer> cooperationOrganIds = studentPaymentOrderExportDtos.stream()
                .filter(e -> OUTORDER.equals(e.getType()))
                .filter(e -> e.getMusicGroupId() != null)
                .map(e -> Integer.valueOf(e.getMusicGroupId()))
                .distinct()
                .collect(Collectors.toList());
        if (cooperationOrganIds.size() > 0) {
            List<CooperationOrgan> cooperationOrgans = cooperationOrganDao.getCooperationOrganByIds(cooperationOrganIds);
            cooperationOrganMap = cooperationOrgans.stream().collect(Collectors.toMap(CooperationOrgan::getId, CooperationOrgan::getName));
        }

        //获取机构费率
        Integer tenantId = (Integer) params.get("tenantId");
        TenantConfig tenantConfig = tenantConfigService.queryByTenantId(tenantId);
        //获取缴费项目编号
        List<Long> calenderIds = studentPaymentOrderExportDtos.stream().map(e -> e.getCalenderId()).filter(e -> e != null).distinct().collect(Collectors.toList());
        Map<Long, Integer> calenderCooperationMap = new HashMap<>();
        Map<Integer, String> firstMusicMap = new HashMap<>();
        if (calenderIds != null && calenderIds.size() > 0) {
            //获取缴费项目关联的合作单位
            calenderCooperationMap = musicGroupPaymentCalenderService.findCooperationByIds(calenderIds);
            //获取合作单位第一个乐团
            firstMusicMap = MapUtil.convertMybatisMap(cooperationOrganDao.findFirstMusic());
        }
        List<Integer> studentIds = studentPaymentOrderExportDtos.stream().map(e -> e.getUserId()).distinct().collect(Collectors.toList());
        //获取学员第一个课程组编号
        Map<Integer, String> userFirstVipMap = MapUtil.convertMybatisMap(courseScheduleStudentPaymentDao.findUserFirstVipMap("VIP", studentIds));
        //获取学员第一个网管课课程组编号
        Map<Integer, String> userFirstPracticeMap = MapUtil.convertMybatisMap(courseScheduleStudentPaymentDao.findUserFirstVipMap("PRACTICE", studentIds));
        //获取学员最近加入的一个乐团编号
        Map<Integer, String> userLastMusicIdMap = MapUtil.convertMybatisMap(studentRegistrationDao.getLastMusicGroupId(studentIds));
        Map<Integer, String> userLastMusicNameMap = MapUtil.convertMybatisMap(studentRegistrationDao.getLastMusicGroupName(studentIds));
        Set<String> musicGroupIds = studentPaymentOrderExportDtos.stream().map(e -> e.getMusicGroupId()).collect(Collectors.toSet());
        Map<String, String> musicGroupNameMap = new HashMap<>();
        if (musicGroupIds != null && musicGroupIds.size() > 0) {
            musicGroupNameMap = MapUtil.convertIntegerMap(musicGroupDao.queryMusicGroupNameMap(musicGroupIds));
        }
        //获取外部订单的商品销售金额
//        List<Long> outOrderList = studentPaymentOrderExportDtos.stream().filter(e -> e.getType() == OUTORDER).map(e -> e.getId()).collect(Collectors.toList());
//        Map<Long, BigDecimal> outOrderAmountMap = new HashMap<>();
//        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(outOrderList)) {
//            outOrderAmountMap = MapUtil.convertIntegerMap(sellOrderDao.sumOutOrderAmount(outOrderList));
//        }
        List<Long> otherOrderIds = studentPaymentOrderExportDtos.stream().filter(e -> e.getGroupType() != GroupType.GOODS_SELL
                && e.getGroupType() != GroupType.REPLACEMENT
                && e.getGroupType() != GroupType.PRACTICE
                && e.getGroupType() != GroupType.SPORADIC
                && e.getGroupType() != GroupType.MEMBER
                && e.getGroupType() != GroupType.ACTIVITY
                && e.getGroupType() != GroupType.VIP).map(e -> e.getId()).collect(Collectors.toList());
        Map<Long, List<StudentPaymentOrderExportDto>> feeByTypeMap = new HashMap<>();
        Map<Long, BigDecimal> childRepairMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(otherOrderIds)) {
            List<StudentPaymentOrderExportDto> feeByType = sellOrderDao.queryFeeByType(otherOrderIds);
            feeByTypeMap = feeByType.stream().collect(Collectors.groupingBy(StudentPaymentOrderExportDto::getId));
            childRepairMap = MapUtil.convertIntegerMap(sellOrderDao.queryChildRepair(otherOrderIds));
        }

        for (StudentPaymentOrderExportDto row : studentPaymentOrderExportDtos) {
            if (row.getActualAmount() == null) {
                row.setActualAmount(BigDecimal.ZERO);
            }
            if (row.getBalancePaymentAmount() == null) {
                row.setBalancePaymentAmount(BigDecimal.ZERO);
            }
            if (row.getMemo() == null) {
                row.setMemo("");
            }
            BigDecimal transferFee = BigDecimal.ZERO;
            if (row.getPaymentChannel() != null && row.getPaymentChannel().equals("ADAPAY")) {
                transferFee = row.getActualAmount().multiply(new BigDecimal("0.28")).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            row.setTransferFee(transferFee);
            row.setPlatformFee(row.getActualAmount().multiply(tenantConfig.getChargeRate()).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));

            Long calenderId = row.getCalenderId();
            if (calenderId != null) {
                row.setFeeMusicGroupId(row.getMusicGroupId());
                row.setFeeMusicGroupName(musicGroupNameMap.get(row.getMusicGroupId()));
                OrderTypeEnum orderTypeEnum = row.getType();
                if (orderTypeEnum == OrderTypeEnum.APPLY || orderTypeEnum == OrderTypeEnum.ADD_STUDENT) {
                    Integer cooperationId = calenderCooperationMap.get(calenderId);
                    if (cooperationId != null) {
                        String firstMusicId = firstMusicMap.get(cooperationId);
                        if (StringUtils.isEmpty(firstMusicId)) {
                            row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
                        } else {
                            if (Objects.equals(firstMusicId, row.getMusicGroupId())) {
                                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
                            } else {
                                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.ADD_MUSIC.getMsg());
                            }
                        }
                    }
                } else {
                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_MUSIC.getMsg());
                }
            } else {
                row.setFeeMusicGroupId(userLastMusicIdMap.get(row.getUserId()));
                row.setFeeMusicGroupName(userLastMusicNameMap.get(row.getUserId()));
            }
            String goodsName = "";
            if (row.getOrderDetailList() != null) {
                for (StudentPaymentOrderDetail orderDetail : row.getOrderDetailList()) {
                    switch (orderDetail.getType()) {
                        case COURSE:
                        case CLASSROOM:
                        case SINGLE:
                        case MIX:
                        case COMPREHENSIVE:
                        case ENLIGHTENMENT:
                        case TRAINING_SINGLE:
                        case TRAINING_MIX:
                        case MUSIC_NETWORK:
                        case HIGH:
                        case HIGH_ONLINE:
                        case HIGH_ONLINE_COURSE:
                            row.setMusicGroupCourseFee(row.getMusicGroupCourseFee().add(orderDetail.getPrice()));
                            break;
                        case MUSICAL:
                            if (orderDetail.getKitGroupPurchaseType() != null && orderDetail.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                                row.setLeaseFee(getActualAmount(orderDetail.getPrice(), row));
                            } else {
                                row.setMusicalFee(orderDetail.getPrice());
                            }
                            break;
                        case ACCESSORIES:
                        case TEACHING:
                            row.setTeachingFee(row.getTeachingFee().add(orderDetail.getPrice()));
                            break;
                        case OTHER:
                            row.setOtherFee(row.getOtherFee().add(orderDetail.getPrice()));
                            break;
                        case MAINTENANCE:
                            row.setMaintenanceFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        case CLOUD_TEACHER:
                        case CLOUD_TEACHER_PLUS:
                            row.setCloudTeacherFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        case DEGREE_REGISTRATION:
                            row.setDegreeFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        case PRACTICE:
                            row.setPracticeCourseFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        case VIP:
                            row.setVipCourseFee(getActualAmount(orderDetail.getPrice(), row));
                            if (row.getTypeDesc() == null) {
                                //学员没有历史VIP课程则导出为【VIP课新增】
                                //学员有历史VIP课程到导出为【VIP课续费]
                                if (Objects.equals(userFirstVipMap.get(row.getUserId()), row.getMusicGroupId())) {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_VIP.getMsg());
                                } else {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_VIP.getMsg());
                                }
                            }
                            break;
                        case THEORY_COURSE:
                            row.setTheoryCourseFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        case REPAIR:
                            row.setRepairFee(getActualAmount(orderDetail.getPrice(), row));
                            break;
                        default:
                            break;
                    }
                }
            }
            if (row.getGoodsList() != null) {
                goodsName = row.getGoodsList().stream().map(Goods::getName).collect(Collectors.joining("|"));
            }
            if (StringUtils.isNotBlank(goodsName)) {
                row.setMemo(goodsName);
            }
            //专业
            if (row.getGroupType().equals(GroupType.VIP)) {
                row.setVipCourseFee(row.getActualAmount());
                if (StringUtils.isNotEmpty(row.getMusicGroupId()) && row.getClassGroupId() != null) {
                    VipGroup vipGroupInfo = vipGroupDao.findVipGroupInfo(Integer.parseInt(row.getMusicGroupId()), row.getClassGroupId());
                    if (vipGroupInfo != null) {
                        row.setSchoolName(vipGroupInfo.getSchoolName());
                        row.setSubjectName(vipGroupInfo.getSubjectName());
                        row.setEduTeacher(vipGroupInfo.getEducationalTeacherName());
                    }
                }
                if (row.getTypeDesc() == null) {
                    //学员没有历史VIP课程则导出为【VIP课新增】
                    //学员有历史VIP课程到导出为【VIP课续费]
                    if (Objects.equals(userFirstVipMap.get(row.getUserId()), row.getMusicGroupId())) {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_VIP.getMsg());
                    } else {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_VIP.getMsg());
                    }
                }
            } else if (row.getGroupType() == GroupType.ACTIVITY) {
                row.setVipCourseFee(row.getActualAmount());
            } else if (row.getGroupType() == GroupType.MEMBER) {
                row.setCloudTeacherFee(row.getActualAmount());
                if (row.getTypeDesc() == null) {
                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.OTHER.getMsg());
                }
            } else if (row.getGroupType().equals(GroupType.SPORADIC)) {
                //考级报名
                if (row.getType().equals(OrderTypeEnum.DEGREE_REGISTRATION)) {
                    String[] feeTypes = row.getMemo().split("；");
                    List<String> feeTypeList = Arrays.asList(feeTypes);
                    for (String feeTypeStr : feeTypeList) {
                        int index = feeTypeStr.lastIndexOf("：");
                        if (index < 0) {
                            continue;
                        }
                        BigDecimal typeFee = new BigDecimal(feeTypeStr.substring(index + 1));
                        if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                            typeFee = typeFee.multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                        }
                        if (feeTypeStr.contains("VIP")) {
                            row.setVipCourseFee(typeFee);
                        } else if (feeTypeStr.contains("网管课")) {
                            row.setPracticeCourseFee(typeFee);
                        } else if (feeTypeStr.contains("乐理课")) {
                            row.setTheoryCourseFee(typeFee);
                        }
                    }
                    row.setDegreeFee(row.getActualAmount().subtract(row.getVipCourseFee()).subtract(row.getPracticeCourseFee()).subtract(row.getTheoryCourseFee()));
                } else {
                    if (row.getChargeType() != null && SporadicChargeTypeEnum.LEVEL.getCode().equals(row.getChargeType())) {
                        row.setDegreeFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.PRACTICE_GROUP_BUY.getCode().equals(row.getChargeType())) {
                        row.setPracticeCourseFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.MUSIC_UPKEEP.getCode().equals(row.getChargeType())) {
                        row.setMaintenanceFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.VISITING_FEE.getCode().equals(row.getChargeType())) {
                        row.setVisitFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && (SporadicChargeTypeEnum.RECHARGE.getCode().equals(row.getChargeType()) ||
                            SporadicChargeTypeEnum.HIGH_ONLINE_ACTIVITY.getCode().equals(row.getChargeType()))) {
                        row.setRechargeFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.CLOUD_TEACHER_BUY.getCode().equals(row.getChargeType())) {
                        row.setCloudTeacherFee(row.getActualAmount());
                    } else {
                        row.setOtherFee(row.getActualAmount());
                    }
                }
                if (row.getChargeType() != null) {
                    for (SporadicChargeTypeEnum chargeType : SporadicChargeTypeEnum.values()) {
                        if (!chargeType.getCode().equals(row.getChargeType())) continue;
                        row.setSporadicType(chargeType.getMsg());
                    }
                }
                if (row.getTypeDesc() == null) {
                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.OTHER.getMsg());
                }
            } else if (row.getGroupType().equals(GroupType.PRACTICE)) {
                row.setPracticeCourseFee(row.getActualAmount());
                PracticeCourseDto practiceGroup = practiceGroupDao.findByGroupId(Integer.parseInt(row.getMusicGroupId()));
                if (practiceGroup != null) {
                    row.setSubjectName(practiceGroup.getSubjectName());
                    row.setEduTeacher(practiceGroup.getEduTeacherName());
                }
                if (row.getTypeDesc() == null) {
                    if (Objects.equals(userFirstPracticeMap.get(row.getUserId()), row.getMusicGroupId())) {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_PRACTICE.getMsg());
                    } else {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_PRACTICE.getMsg());
                    }
                }
            } else if (row.getGroupType().equals(GroupType.REPLACEMENT)) {
                row.setMusicalFee(row.getActualAmount());
                ReplacementInstrumentActivityStatDto info = replacementInstrumentActivityDao.getInfo(Integer.parseInt(row.getMusicGroupId()));
                if (info != null) {
                    row.setSubjectName(info.getSubjectName());
                    row.setCooperationOrganName(info.getCooperationOrganName());
                    row.setMemo(info.getBrand() + "(" + info.getSpecification() + ")");
                    CooperationOrgan cooperationOrganEduTeacher = musicGroupDao.findCooperationOrganEduTeacher(info.getCooperationOrganId());
                    if (cooperationOrganEduTeacher != null) {
                        row.setEduTeacher(cooperationOrganEduTeacher.getLinkman());
                    }
                }
            } else if (row.getGroupType().equals(GroupType.GOODS_SELL)) {
                row.setRetailGoodsFee(row.getActualAmount());
                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RETAIL_GOODS.getMsg());
            } else {
                List<StudentPaymentOrderExportDto> exportDtoList = feeByTypeMap.get(row.getId());
                if (!CollectionUtils.isEmpty(exportDtoList)) {
                    StudentPaymentOrderExportDto feeByType = exportDtoList.get(0);
                    BigDecimal childRepairFee = childRepairMap.get(row.getId()) == null ? BigDecimal.ZERO : childRepairMap.get(row.getId());
//                    StudentPaymentOrderExportDto feeByType = sellOrderDao.getFeeByType(row.getId());
//                    BigDecimal childRepairFee = sellOrderDao.getChildRepair(row.getId());
                    row.setMusicalFee(feeByType.getMusicalFee());
                    row.setTeachingFee(feeByType.getTeachingFee().subtract(childRepairFee));
                    row.setMaintenanceProductFee(feeByType.getRepairFee().add(childRepairFee));
                    row.setOtherFee(feeByType.getOtherFee());
                    if (row.getGroupType().equals(GroupType.MUSIC)) {
                        if (row.getType() != OrderTypeEnum.APPLY && row.getType() != OrderTypeEnum.ADD_STUDENT) {
                            //判断之前是否有付费订单，如果没有，那么是乐团转化
                            int orderNum = studentPaymentOrderDao.getStudentMusicOrderNum(row.getMusicGroupId(), row.getUserId(), row.getId());
                            if (orderNum == 0) {
                                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.MUSIC_CONVERT.getMsg());
                            }
                        }
                        StudentRegistration studentRegistration = studentRegistrationDao.findStudentByMusicGroupIdAndUserId(row.getMusicGroupId(), row.getUserId());
                        if (studentRegistration != null) {
                            row.setSubjectName(studentRegistration.getSubjectName());
                            row.setSchoolName(studentRegistration.getSchoolName());
                            row.setCooperationOrganName(studentRegistration.getRemark());
                            row.setEduTeacher(studentRegistration.getName());
                        }
                        row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).
                                subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).
                                subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()).subtract(row.getCloudTeacherFee()).
                                subtract(row.getVipCourseFee()).subtract(row.getPracticeCourseFee()));
                    } else if (row.getGroupType().equals(OrderTypeEnum.REPAIR)) {
                        row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
                    } else if (row.getGroupType() == GroupType.OUTORDER) {
                        //销售收入
                        BigDecimal add = feeByType.getMusicalFee().add(row.getTeachingFee()).add(row.getMaintenanceProductFee()).add(feeByType.getOtherFee());
                        //服务收入
                        BigDecimal subtract = feeByType.getActualAmount().subtract(add);
                        //如果是淘器微信那么就是零售
                        if (Objects.equals("淘器微信", row.getMerNos()) && add.compareTo(BigDecimal.ZERO) > 0) {
                            //如果有服务收入那么是课程学校采买
                            row.setMusicalFee(BigDecimal.ZERO);
                            row.setTeachingFee(BigDecimal.ZERO);
                            row.setMaintenanceProductFee(BigDecimal.ZERO);
                            row.setOtherFee(subtract);
                            row.setRetailGoodsFee(add);
                            row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RETAIL_GOODS.getMsg());
                        } else {
                            //拆分导入订单
                            if (row.getType() == OrderTypeEnum.OUTORDER || row.getType() == OrderTypeEnum.SCHOOL) {
                                if (row.getType() == OrderTypeEnum.SCHOOL) {
                                    row.setMusicalFee(BigDecimal.ZERO);
                                    row.setTeachingFee(BigDecimal.ZERO);
                                    row.setMaintenanceProductFee(BigDecimal.ZERO);
                                    row.setOtherFee(BigDecimal.ZERO);
                                    row.setLargeMusicalFee(add);
                                }
                                //如果有服务收入那么是课程学校采买
                                if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.LARGE_MUSICAL.getMsg());
                                } else {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.COURSE_SCHOOL_BUY.getMsg());
                                }
                                row.setCourseSchoolBuyAmount(subtract);
                            } else if (row.getType() == OrderTypeEnum.OTHER) {
                                row.setOtherFee(row.getOtherFee().add(subtract));
                            } else {
                                row.setMusicalFee(BigDecimal.ZERO);
                                row.setTeachingFee(BigDecimal.ZERO);
                                row.setMaintenanceProductFee(BigDecimal.ZERO);
                                row.setOtherFee(BigDecimal.ZERO);
                                row.setRetailGoodsFee(add);
                                row.setMusicGroupCourseFee(subtract);
                                //如果有服务收入那么是课程学校采买
                                if (subtract.compareTo(BigDecimal.ZERO) == 0) {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RETAIL_GOODS.getMsg());
                                } else {
                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.COURSE_STUDENT_BUY.getMsg());
                                }
                            }
                        }
                        row.setTransferFee(BigDecimal.ZERO);
                        row.setPlatformFee(BigDecimal.ZERO);
                    }
                }
                if (row.getTypeDesc() == null) {
                    if (row.getGroupType().equals(GroupType.SUBJECT_CHANGE)) {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
                    } else if (row.getGroupType().equals(GroupType.REPAIR)) {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.REPAIR.getMsg());
                    }
                }
            }
            //如果合作单位不存在取学员的第一个乐团的合作单位,乐团主管
            if (row.getCooperationOrganName() == null) {
                CooperationOrgan cooperationOrgan = studentService.getStudentEduTeacher(row.getUserId());
                if (cooperationOrgan != null) {
                    row.setCooperationOrganName(cooperationOrgan.getName());
                    row.setEduTeacher(cooperationOrgan.getLinkman() != null ? cooperationOrgan.getLinkman() : row.getEduTeacher());
                }
            }
            if (row.getType().equals(OUTORDER) && row.getMusicGroupId() != null) {
                if (cooperationOrganMap.containsKey(Integer.valueOf(row.getMusicGroupId()))) {
                    row.setCooperationOrganName(cooperationOrganMap.get(Integer.valueOf(row.getMusicGroupId())));
                    CooperationOrgan cooperationOrganEduTeacher = musicGroupDao.findCooperationOrganEduTeacher(Integer.valueOf(row.getMusicGroupId()));
                    if (cooperationOrganEduTeacher != null) {
                        row.setEduTeacher(cooperationOrganEduTeacher.getLinkman());
                    }
                }
            }
            if (row.getMusicGroupId() != null && row.getMusicGroupId().equals("null")) {
                row.setMusicGroupId("");
            }
            String paymentChannel = "";
            if (row.getPaymentChannel() == null) {
            } else if (row.getPaymentChannel().equals("YQPAY")) {
                paymentChannel = "双乾";
            } else if (row.getPaymentChannel().equals("ADAPAY")) {
                paymentChannel = "汇付";
            } else if (row.getPaymentChannel().equals("BALANCE")) {
                paymentChannel = "余额";
            }
            if(StringUtils.isNotEmpty(row.getSporadicType())){
                row.setTypeDesc(row.getSporadicType());
            }
            row.setPaymentChannel(paymentChannel);
            row.setId(i);
            row.setRepairFee(row.getRepairFee().add(row.getMaintenanceProductFee()));
            row.setOrderAmount(row.getExpectAmount().add(row.getCouponRemitFee()));
            i++;
        }
        HSSFWorkbook workbook = getHSSFWorkbook(studentPaymentOrderExportDtos, ExportEnum.ORDER_LIST1);
        exportManagerDownload(workbook, managerDownload);
    }

    @Override
    public void orderListSum(Map<String, Object> params, ManagerDownload managerDownload) {
        List<StudentPaymentOrderExportDto> studentPaymentOrderExportDtos = studentPaymentOrderService.ExportQueryPage(params);
        //获取机构费率
        Integer tenantId = (Integer) params.get("tenantId");
        TenantConfig tenantConfig = tenantConfigService.queryByTenantId(tenantId);
        List<Long> otherOrderIds = studentPaymentOrderExportDtos.stream().filter(e -> e.getGroupType() != GroupType.GOODS_SELL
                && e.getGroupType() != GroupType.REPLACEMENT
                && e.getGroupType() != GroupType.PRACTICE
                && e.getGroupType() != GroupType.SPORADIC
                && e.getGroupType() != GroupType.MEMBER
                && e.getGroupType() != GroupType.ACTIVITY
                && e.getGroupType() != GroupType.VIP).map(e -> e.getId()).collect(Collectors.toList());
        Map<Long, List<StudentPaymentOrderExportDto>> feeByTypeMap = new HashMap<>();
        Map<Long, BigDecimal> childRepairMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(otherOrderIds)) {
            List<StudentPaymentOrderExportDto> feeByType = sellOrderDao.queryFeeByType(otherOrderIds);
            feeByTypeMap = feeByType.stream().collect(Collectors.groupingBy(StudentPaymentOrderExportDto::getId));
            childRepairMap = MapUtil.convertIntegerMap(sellOrderDao.queryChildRepair(otherOrderIds));
        }
        for (StudentPaymentOrderExportDto row : studentPaymentOrderExportDtos) {
            if (row.getActualAmount() == null) {
                row.setActualAmount(BigDecimal.ZERO);
            }
            if (row.getBalancePaymentAmount() == null) {
                row.setBalancePaymentAmount(BigDecimal.ZERO);
            }
            BigDecimal transferFee = BigDecimal.ZERO;
            if (row.getPaymentChannel() != null && row.getPaymentChannel().equals("ADAPAY")) {
                transferFee = row.getActualAmount().multiply(new BigDecimal("0.28")).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            row.setTransferFee(transferFee);
            row.setPlatformFee(row.getActualAmount().multiply(tenantConfig.getChargeRate()).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
            if (row.getOrderDetailList() != null) {
                for (StudentPaymentOrderDetail orderDetail : row.getOrderDetailList()) {
                    switch (orderDetail.getType()) {
                        case COURSE:
                        case CLASSROOM:
                        case SINGLE:
                        case MIX:
                        case COMPREHENSIVE:
                        case ENLIGHTENMENT:
                        case TRAINING_SINGLE:
                        case TRAINING_MIX:
                        case MUSIC_NETWORK:
                        case HIGH:
                        case HIGH_ONLINE:
                        case HIGH_ONLINE_COURSE:
                            row.setMusicGroupCourseFee(row.getMusicGroupCourseFee().add(orderDetail.getPrice()));
                            break;
                        case MUSICAL:
                            if (orderDetail.getKitGroupPurchaseType() != null && orderDetail.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                                BigDecimal leaseFee = BigDecimal.ZERO;
                                if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                    leaseFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                                }
                                row.setLeaseFee(leaseFee);
                            } else {
                                row.setMusicalFee(orderDetail.getPrice());
                            }
                            break;
                        case ACCESSORIES:
                        case TEACHING:
                            row.setTeachingFee(row.getTeachingFee().add(orderDetail.getPrice()));
                            break;
                        case OTHER:
                            row.setOtherFee(row.getOtherFee().add(orderDetail.getPrice()));
                            break;
                        case MAINTENANCE:
                            BigDecimal repairFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                repairFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setMaintenanceFee(repairFee);
                            break;
                        case CLOUD_TEACHER:
                        case CLOUD_TEACHER_PLUS:
                            BigDecimal cloudTeacherFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                cloudTeacherFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setCloudTeacherFee(cloudTeacherFee);
                            break;
                        case DEGREE_REGISTRATION:
                            BigDecimal degreeFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                degreeFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setDegreeFee(degreeFee);
                            break;
                        case PRACTICE:
                            BigDecimal practiceCourseFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                practiceCourseFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setPracticeCourseFee(practiceCourseFee);
                            break;
                        case VIP:
                            BigDecimal vipCourseFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                vipCourseFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setVipCourseFee(vipCourseFee);
                            break;
                        case THEORY_COURSE:
                            BigDecimal theoryCourseFee = BigDecimal.ZERO;
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                theoryCourseFee = orderDetail.getPrice().multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            row.setTheoryCourseFee(theoryCourseFee);
                            break;
                        default:
                            break;
                    }
                }
            }
            //专业
            if (row.getGroupType().equals(GroupType.VIP)) {
                row.setVipCourseFee(row.getActualAmount());
            } else if (row.getGroupType() == GroupType.ACTIVITY) {
                row.setVipCourseFee(row.getActualAmount());
            } else if (row.getGroupType() == GroupType.MEMBER) {
                row.setCloudTeacherFee(row.getActualAmount());
            } else if (row.getGroupType().equals(GroupType.SPORADIC)) {
                //考级报名
                if (row.getType().equals(OrderTypeEnum.DEGREE_REGISTRATION)) {

                    if (StringUtils.isNotBlank(row.getMemo())) {
                        String[] feeTypes = row.getMemo().split("；");
                        List<String> feeTypeList = Arrays.asList(feeTypes);
                        for (String feeTypeStr : feeTypeList) {
                            int index = feeTypeStr.lastIndexOf("：");
                            if (index < 0) {
                                continue;
                            }
                            BigDecimal typeFee = new BigDecimal(feeTypeStr.substring(index + 1));
                            if (row.getExpectAmount().compareTo(BigDecimal.ZERO) > 0) {
                                typeFee = typeFee.multiply(row.getActualAmount()).divide(row.getExpectAmount(), 2, BigDecimal.ROUND_DOWN);
                            }
                            if (feeTypeStr.contains("VIP")) {
                                row.setVipCourseFee(typeFee);
                            } else if (feeTypeStr.contains("网管课")) {
                                row.setPracticeCourseFee(typeFee);
                            } else if (feeTypeStr.contains("乐理课")) {
                                row.setTheoryCourseFee(typeFee);
                            }
                        }
                    }
                    row.setDegreeFee(row.getActualAmount().subtract(row.getVipCourseFee()).subtract(row.getPracticeCourseFee()).subtract(row.getTheoryCourseFee()));
                } else {
                    if (row.getChargeType() != null && SporadicChargeTypeEnum.LEVEL.getCode().equals(row.getChargeType())) {
                        row.setDegreeFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.PRACTICE_GROUP_BUY.getCode().equals(row.getChargeType())) {
                        row.setPracticeCourseFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.MUSIC_UPKEEP.getCode().equals(row.getChargeType())) {
                        row.setMaintenanceFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.VISITING_FEE.getCode().equals(row.getChargeType())) {
                        row.setVisitFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && (SporadicChargeTypeEnum.RECHARGE.getCode().equals(row.getChargeType()) ||
                            SporadicChargeTypeEnum.HIGH_ONLINE_ACTIVITY.getCode().equals(row.getChargeType()))) {
                        row.setRechargeFee(row.getActualAmount());
                    } else if (row.getChargeType() != null && SporadicChargeTypeEnum.CLOUD_TEACHER_BUY.getCode().equals(row.getChargeType())) {
                        row.setCloudTeacherFee(row.getActualAmount());
                    } else {
                        row.setOtherFee(row.getActualAmount());
                    }
                }
            } else if (row.getGroupType().equals(GroupType.PRACTICE)) {
                row.setPracticeCourseFee(row.getActualAmount());
            } else if (row.getGroupType().equals(GroupType.REPLACEMENT)) {
                row.setMusicalFee(row.getActualAmount());
            } else if (row.getGroupType().equals(GroupType.GOODS_SELL)) {
                row.setRetailGoodsFee(row.getActualAmount());
            } else {
                List<StudentPaymentOrderExportDto> exportDtoList = feeByTypeMap.get(row.getId());
                if (!CollectionUtils.isEmpty(exportDtoList)) {
                    StudentPaymentOrderExportDto feeByType = exportDtoList.get(0);
                    BigDecimal childRepairFee = childRepairMap.get(row.getId()) == null ? BigDecimal.ZERO : childRepairMap.get(row.getId());
                    row.setMusicalFee(feeByType.getMusicalFee());
                    row.setTeachingFee(feeByType.getTeachingFee().subtract(childRepairFee));
                    row.setMaintenanceProductFee(feeByType.getRepairFee().add(childRepairFee));
                    row.setOtherFee(feeByType.getOtherFee());
                    if (row.getGroupType().equals(GroupType.MUSIC)) {
                        row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).
                                subtract(row.getTeachingFee()).subtract(row.getMaintenanceFee()).subtract(row.getMaintenanceProductFee()).
                                subtract(feeByType.getOtherFee()).subtract(row.getLeaseFee()).subtract(row.getCloudTeacherFee()).
                                subtract(row.getVipCourseFee()).subtract(row.getPracticeCourseFee()));
                    } else if (row.getGroupType().equals(OrderTypeEnum.REPAIR)) {
                        row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
                    } else if (row.getGroupType() == GroupType.OUTORDER) {
                        //销售收入
                        BigDecimal add = feeByType.getMusicalFee().add(row.getTeachingFee()).add(row.getMaintenanceProductFee()).add(feeByType.getOtherFee());
                        //服务收入
                        BigDecimal subtract = feeByType.getActualAmount().subtract(add);
                        //如果是淘器微信那么就是零售
                        if (Objects.equals("淘器微信", row.getMerNos()) && add.compareTo(BigDecimal.ZERO) > 0) {
                            //如果有服务收入那么是课程学校采买
                            row.setMusicalFee(BigDecimal.ZERO);
                            row.setTeachingFee(BigDecimal.ZERO);
                            row.setMaintenanceProductFee(BigDecimal.ZERO);
                            row.setOtherFee(subtract);
                            row.setRetailGoodsFee(add);
                            row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RETAIL_GOODS.getMsg());
                        } else {
                            //拆分导入订单
                            if (row.getType() == OrderTypeEnum.OUTORDER || row.getType() == OrderTypeEnum.SCHOOL) {
                                if (row.getType() == OrderTypeEnum.SCHOOL) {
                                    row.setMusicalFee(BigDecimal.ZERO);
                                    row.setTeachingFee(BigDecimal.ZERO);
                                    row.setMaintenanceProductFee(BigDecimal.ZERO);
                                    row.setOtherFee(BigDecimal.ZERO);
                                    row.setLargeMusicalFee(add);
                                }
                                row.setCourseSchoolBuyAmount(subtract);
                            } else if (row.getType() == OrderTypeEnum.OTHER) {
                                row.setOtherFee(row.getOtherFee().add(subtract));
                            } else {
                                row.setMusicalFee(BigDecimal.ZERO);
                                row.setTeachingFee(BigDecimal.ZERO);
                                row.setMaintenanceProductFee(BigDecimal.ZERO);
                                row.setOtherFee(BigDecimal.ZERO);
                                row.setRetailGoodsFee(add);
                                row.setMusicGroupCourseFee(subtract);
                            }
                        }
                    }
                }
            }
            row.setRepairFee(row.getRepairFee().add(row.getMaintenanceProductFee()));
            row.setOrderAmount(row.getExpectAmount().add(row.getCouponRemitFee()));
        }
        List<StudentPaymentOrderExportDto> exportDtoList = new ArrayList<>();
        Map<Integer, List<StudentPaymentOrderExportDto>> collect = studentPaymentOrderExportDtos.stream().collect(Collectors.groupingBy(StudentPaymentOrderExportDto::getOrganId));
        for (Integer organId : collect.keySet()) {
            StudentPaymentOrderExportDto exportDto = new StudentPaymentOrderExportDto();
            List<StudentPaymentOrderExportDto> orderExportDtos = collect.get(organId);
            exportDto.setOrganName(orderExportDtos.stream().map(e -> e.getOrganName()).findAny().get());
            exportDto.setOrderAmount(orderExportDtos.stream().map(e -> e.getOrderAmount()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setExpectAmount(orderExportDtos.stream().map(e -> e.getExpectAmount()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setActualAmount(orderExportDtos.stream().map(e -> e.getActualAmount()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setBalancePaymentAmount(orderExportDtos.stream().map(e -> e.getBalancePaymentAmount()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setCouponRemitFee(orderExportDtos.stream().map(e -> e.getCouponRemitFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setMusicGroupCourseFee(orderExportDtos.stream().map(e -> e.getMusicGroupCourseFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setCourseSchoolBuyAmount(orderExportDtos.stream().map(e -> e.getCourseSchoolBuyAmount()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setVipCourseFee(orderExportDtos.stream().map(e -> e.getVipCourseFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setPracticeCourseFee(orderExportDtos.stream().map(e -> e.getPracticeCourseFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setTheoryCourseFee(orderExportDtos.stream().map(e -> e.getTheoryCourseFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setDegreeFee(orderExportDtos.stream().map(e -> e.getDegreeFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setRepairFee(orderExportDtos.stream().map(e -> e.getRepairFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setMaintenanceFee(orderExportDtos.stream().map(e -> e.getMaintenanceFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setCloudTeacherFee(orderExportDtos.stream().map(e -> e.getCloudTeacherFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setLeaseFee(orderExportDtos.stream().map(e -> e.getLeaseFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setMusicalFee(orderExportDtos.stream().map(e -> e.getMusicalFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setTeachingFee(orderExportDtos.stream().map(e -> e.getTeachingFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setVisitFee(orderExportDtos.stream().map(e -> e.getVisitFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setRechargeFee(orderExportDtos.stream().map(e -> e.getRechargeFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setRetailGoodsFee(orderExportDtos.stream().map(e -> e.getRetailGoodsFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setLargeMusicalFee(orderExportDtos.stream().map(e -> e.getLargeMusicalFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDto.setOtherFee(orderExportDtos.stream().map(e -> e.getOtherFee()).reduce(BigDecimal.ZERO, BigDecimal::add));
            exportDtoList.add(exportDto);
        }

        HSSFWorkbook workbook = getHSSFWorkbook(exportDtoList, ExportEnum.ORDER_LIST_SUM);
        exportManagerDownload(workbook, managerDownload);
    }

    public BigDecimal subtract(BigDecimal a, BigDecimal b) {
        BigDecimal subtract = a.subtract(b);
        if (subtract.compareTo(BigDecimal.ZERO) < 0) {
            subtract = BigDecimal.ZERO;
        }
        return subtract;
    }

    public void routeOrderList(Map<String, Object> params, ManagerDownload managerDownload) {
        //获取分润订单(不包含订单详情)（纯余额支付不处理）
        List<StudentPaymentOrderExportDto> studentPaymentOrderExportDtos = studentPaymentRouteOrderDao.ExportQueryPage1(params);
        if (CollectionUtils.isEmpty(studentPaymentOrderExportDtos)) {
            return;
        }
        Set<Long> paymentOrderIds = studentPaymentOrderExportDtos.stream().map(e -> e.getId()).collect(Collectors.toSet());
        //获取商品订单详情
        List<SellOrder> sellOrders = sellOrderDao.querySellOrderByOrderIds(paymentOrderIds);
        Map<Long, List<SellOrder>> sellOrderMap = new HashMap<>();
        Map<Integer, Goods> goodsMap = new HashMap<>();
        if (!CollectionUtils.isEmpty(sellOrders)) {
            sellOrderMap = sellOrders.stream().collect(Collectors.groupingBy(SellOrder::getOrderId));
            //获取商品列表
            List<Goods> goodsList = goodsService.findGoodsByIds(sellOrders.stream().map(e -> e.getGoodsId().toString()).distinct().collect(Collectors.joining(",")));
            goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId, Function.identity()));
        }

        //获取订单详情
        List<StudentPaymentOrderDetail> orderDetails = studentPaymentOrderDetailService.getDao().getOrderDetailByOrderId(new ArrayList<>(paymentOrderIds));
        Map<Long, List<StudentPaymentOrderDetail>> orderDetailMap = new HashMap<>();
        //订单详情塞到对应的订单中
        if (!CollectionUtils.isEmpty(orderDetails)) {
            orderDetailMap = orderDetails.stream().collect(Collectors.groupingBy(StudentPaymentOrderDetail::getPaymentOrderId));
        }
        //获取对外订单关联的合作单位
        Map<Integer, String> cooperationOrganMap = new HashMap<>();
        List<Integer> cooperationOrganIds = studentPaymentOrderExportDtos.stream()
                .filter(e -> OUTORDER.equals(e.getType()))
                .filter(e -> e.getMusicGroupId() != null)
                .map(e -> Integer.valueOf(e.getMusicGroupId()))
                .distinct()
                .collect(Collectors.toList());
        if (cooperationOrganIds.size() > 0) {
            List<CooperationOrgan> cooperationOrgans = cooperationOrganDao.getCooperationOrganByIds(cooperationOrganIds);
            cooperationOrganMap = cooperationOrgans.stream().collect(Collectors.toMap(CooperationOrgan::getId, CooperationOrgan::getName));
        }
        //计算手续费
        Map<String, BigDecimal> serviceChargeMap = new HashMap<>();
        Map<String, Integer> orderCountMap = new HashMap<>();
        Integer tenantId = (Integer) params.get("tenantId");
        TenantConfig tenantConfig = tenantConfigService.queryByTenantId(tenantId);
        //获取乐团信息
        List<Long> calenderIds = studentPaymentOrderExportDtos.stream().map(e -> e.getCalenderId()).filter(e -> e != null).distinct().collect(Collectors.toList());
        Map<Long, Integer> calenderCooperationMap = new HashMap<>();
        Map<Integer, String> firstMusicMap = new HashMap<>();
        if (calenderIds != null && calenderIds.size() > 0) {
            //获取缴费项目关联的合作单位
            calenderCooperationMap = musicGroupPaymentCalenderService.findCooperationByIds(calenderIds);
            //获取合作单位第一个乐团
            firstMusicMap = MapUtil.convertMybatisMap(cooperationOrganDao.findFirstMusic());
        }
        Map<Integer, String> userFirstVipMap = new HashMap<>();
        Map<Integer, String> userLastMusicIdMap = new HashMap<>();
        Map<Integer, String> userLastMusicNameMap = new HashMap<>();
        Map<Integer, String> studentNameMap = new HashMap<>();
        Map<Integer, String> userFirstPracticeMap = new HashMap<>();
        if (studentPaymentOrderExportDtos.stream().anyMatch(e -> e.getUserId() != null)) {
            List<Integer> studentIds = studentPaymentOrderExportDtos.stream().filter(e -> e.getUserId() != null).map(e -> e.getUserId()).distinct().collect(Collectors.toList());
            //获取学员第一个网管课课程组编号
            userFirstPracticeMap = MapUtil.convertMybatisMap(courseScheduleStudentPaymentDao.findUserFirstVipMap("PRACTICE", studentIds));
            //获取学员第一个课程组编号
            userFirstVipMap = MapUtil.convertMybatisMap(courseScheduleStudentPaymentDao.findUserFirstVipMap("VIP", studentIds));
            //获取学员最近加入的一个乐团编号
            userLastMusicIdMap = MapUtil.convertMybatisMap(studentRegistrationDao.getLastMusicGroupId(studentIds));
            userLastMusicNameMap = MapUtil.convertMybatisMap(studentRegistrationDao.getLastMusicGroupName(studentIds));
            //获取学员名称
            studentNameMap = studentService.getMap("sys_user", "id_", "username_", studentIds, tenantId, Integer.class, String.class);
        }

        Set<String> musicGroupIds = studentPaymentOrderExportDtos.stream().map(e -> e.getMusicGroupId()).collect(Collectors.toSet());
        Map<String, String> musicGroupNameMap = new HashMap<>();
        if (musicGroupIds != null && musicGroupIds.size() > 0) {
            musicGroupNameMap = MapUtil.convertIntegerMap(musicGroupDao.queryMusicGroupNameMap(musicGroupIds));
        }
        //用于计算手续费
        Map<String, FeeFlagNumDto> feeFlagMap = new HashMap<>();
        if (studentPaymentOrderExportDtos.stream().anyMatch(e -> Objects.equals(e.getPaymentChannel(), "ADAPAY"))) {
            List<String> orderNoList = studentPaymentOrderExportDtos.stream().filter(e -> Objects.equals(e.getPaymentChannel(), "ADAPAY")).map(e -> e.getOrderNo()).distinct().collect(Collectors.toList());
            List<FeeFlagNumDto> feeFlagNumDtos = studentPaymentRouteOrderDao.queryCountFeeFlagNum(orderNoList);
            feeFlagMap = feeFlagNumDtos.stream().collect(Collectors.toMap(FeeFlagNumDto::getOrderNo, Function.identity()));
        }
        for (StudentPaymentOrderExportDto basicOrder : studentPaymentOrderExportDtos) {
            basicOrder.getUser().setUsername(studentNameMap.get(basicOrder.getUserId()));
            //填充业务数据
            //计算手续费
            this.calcPlatformFee(basicOrder, serviceChargeMap, orderCountMap, tenantConfig, feeFlagMap);
            //获取乐团信息
            this.initMusicGroupInfo(basicOrder, musicGroupNameMap, firstMusicMap, userLastMusicIdMap, userLastMusicNameMap, calenderCooperationMap);
            //填充备注信息
            if (basicOrder.getGoodsList() != null) {
                String goodsName = basicOrder.getGoodsList().stream().map(Goods::getName).collect(Collectors.joining("|"));
                basicOrder.setMemo(goodsName);
            }
            if (basicOrder.getType() == OUTORDER && StringUtils.isNotEmpty(basicOrder.getMusicGroupId())) {
                if (cooperationOrganMap.containsKey(Integer.valueOf(basicOrder.getMusicGroupId()))) {
                    basicOrder.setCooperationOrganName(cooperationOrganMap.get(Integer.valueOf(basicOrder.getMusicGroupId())));
                    CooperationOrgan cooperationOrganEduTeacher = musicGroupDao.findCooperationOrganEduTeacher(Integer.valueOf(basicOrder.getMusicGroupId()));
                    if (cooperationOrganEduTeacher != null) {
                        basicOrder.setEduTeacher(cooperationOrganEduTeacher.getLinkman());
                    }
                }
            }
            //根据订单类型初始化业务数据
            Optional.ofNullable(groupTypeConsumerMap1.get(basicOrder.getGroupType())).ifPresent(consumer -> consumer.accept(basicOrder));
            this.setSubTypeDesc(basicOrder, userFirstVipMap, userFirstPracticeMap);

            String paymentChannel = "";
            if (basicOrder.getPaymentChannel() == null) {
            } else if (basicOrder.getPaymentChannel().equals("YQPAY")) {
                paymentChannel = "双乾";
            } else if (basicOrder.getPaymentChannel().equals("ADAPAY")) {
                paymentChannel = "汇付";
            } else if (basicOrder.getPaymentChannel().equals("BALANCE")) {
                paymentChannel = "余额";
            }
            basicOrder.setPaymentChannel(paymentChannel);
            if(StringUtils.isNotEmpty(basicOrder.getSporadicType()) && !basicOrder.getSporadicType().equals("其他")){
                basicOrder.setTypeDesc(basicOrder.getSporadicType());
            }
            if (basicOrder.getRouteAmount().compareTo(BigDecimal.ZERO) == 0) {
                continue;
            }
            //如果是零星收费的账户充值，不管销售还是服务，统一放在其他收费项目中
            if (basicOrder.getType() == OrderTypeEnum.SPORADIC
                    && basicOrder.getGroupType() == GroupType.SPORADIC
                    && basicOrder.getServiceAmount().compareTo(BigDecimal.ZERO) == 0
                    && basicOrder.getSaleAmount().compareTo(BigDecimal.ZERO) == 0) {
                basicOrder.setOtherFee(basicOrder.getRouteAmount());
                continue;
            }
            //如果有订单详情
            List<StudentPaymentOrderDetail> detailList = orderDetailMap.get(basicOrder.getId());
            if (!CollectionUtils.isEmpty(detailList)) {
                this.calcOrderDetail(basicOrder, detailList, userFirstVipMap);
                continue;
            }
            //如果没有订单详情，则计算商品收入
            List<SellOrder> sellOrderList = sellOrderMap.get(basicOrder.getId());
            if (!CollectionUtils.isEmpty(sellOrderList)) {
                this.calcSellOrder(basicOrder, sellOrderList, goodsMap);
                continue;
            }
            //如果只有订单，那么按分类统计
            if (basicOrder.getServiceAmount().compareTo(BigDecimal.ZERO) > 0) {
                //计算服务收入
                Optional.ofNullable(groupTypeConsumerMap.get(basicOrder.getGroupType())).ifPresent(c -> c.accept(basicOrder));
            } else if (basicOrder.getSaleAmount().compareTo(BigDecimal.ZERO) > 0) {
                //计算销售收入
                this.setSaleFee(basicOrder);
            }
        }
        HSSFWorkbook workbook = getHSSFWorkbook(studentPaymentOrderExportDtos, ExportEnum.ROUTE_ORDER_LIST1);
        exportManagerDownload(workbook, managerDownload);
    }

    @Override
    public void superFindCourseSchedules(EndCourseScheduleQueryInfo queryInfo, ManagerDownload managerDownload) {
        try {
            List<CourseScheduleEndDto> rows = courseScheduleService.endFindCourseSchedules(queryInfo).getRows();
            for (CourseScheduleEndDto row : rows) {
                row.setIsComplaints(StringUtils.equals(row.getIsComplaints(), "1") ? "有" : "无");
            }
            HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"分部名称", "乐团主管", "课程编号", "课程组编号", "开始时间", "结束时间",
                    "班级名称", "班级声部", "课程名称", "课程类型", "教学模式",
                    "教学点", "课程状态", "指导老师", "学员编号", "是否点名", "是否有考勤申诉", "预计上课人数", "合作单位"}, new String[]{
                    "organName", "educationTeacherName", "id", "musicGroupId", "startClassTime", "endClassTime", "classGroupName", "subjectName", "name",
                    "groupType.desc", "teachMode.msg", "schoolName", "status.msg", "teacherName", "studentId", "isCallNames.msg", "isComplaints", "studentNum", "cooperationOrgan"}, rows);
            exportManagerDownload(workbook, managerDownload);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void studentVipPractice(String organId, ManagerDownload managerDownload, Integer tenantId) {
        List<StudentVipPracticeExportDto> studentVipPracticeExportDtos = courseScheduleStudentPaymentDao.exportStudentVipPractice(organId, tenantId);
        if (studentVipPracticeExportDtos != null && studentVipPracticeExportDtos.size() > 0) {
            List<Integer> studentIds = studentVipPracticeExportDtos.stream().map(e -> e.getUserId()).distinct().collect(Collectors.toList());
            //新增声部课老师，学员有在读乐团，导出该学员所在声部班班级老师，无声部班则为空
            List<BaseNameDto> normalClassTeacher = courseScheduleStudentPaymentDao.queryClassTeacher(studentIds);
            Map<Integer, List<BaseNameDto>> normalClassTeacherMap = new HashMap<>();
            if (normalClassTeacher != null && normalClassTeacher.size() > 0) {
                normalClassTeacherMap = normalClassTeacher.stream().collect(Collectors.groupingBy(BaseNameDto::getUserId));
            }
            //获取最近一节未开始vip课课程组老师编号
            List<BaseNameDto> vipFirstNotStartTeacher = courseScheduleStudentPaymentDao.queryFirstNotStartTeacher(studentIds, "VIP");
            Map<Integer, List<BaseNameDto>> vipFirstNotStartTeacherMap = new HashMap<>();
            if (vipFirstNotStartTeacher != null && vipFirstNotStartTeacher.size() > 0) {
                vipFirstNotStartTeacherMap = vipFirstNotStartTeacher.stream().collect(Collectors.groupingBy(BaseNameDto::getUserId));
            }
            //获取最近一节未开始网管课课课程组老师编号
            List<BaseNameDto> practiceFirstNotStartTeacher = courseScheduleStudentPaymentDao.queryFirstNotStartTeacher(studentIds, "PRACTICE");
            Map<Integer, List<BaseNameDto>> practiceFirstNotStartTeacherMap = new HashMap<>();
            if (practiceFirstNotStartTeacher != null && practiceFirstNotStartTeacher.size() > 0) {
                practiceFirstNotStartTeacherMap = practiceFirstNotStartTeacher.stream().collect(Collectors.groupingBy(BaseNameDto::getUserId));
            }
            //获取学员最后一节已结束的vip课课程组的老师以及编号
            List<BaseNameDto> vipBaseNameDtos = courseScheduleStudentPaymentDao.queryLastOverTeacher(studentIds, "VIP");
            Map<Integer, List<BaseNameDto>> vipBaseNameMap = new HashMap<>();
            if (vipBaseNameDtos != null && vipBaseNameDtos.size() > 0) {
                vipBaseNameMap = vipBaseNameDtos.stream().collect(Collectors.groupingBy(BaseNameDto::getUserId));
            }
            //获取学员最后一节已结束的网管课课程组的老师以及编号
            List<BaseNameDto> practiceBaseNameDtos = courseScheduleStudentPaymentDao.queryLastOverTeacher(studentIds, "PRACTICE");
            Map<Integer, List<BaseNameDto>> practiceBaseNameMap = new HashMap<>();
            if (practiceBaseNameDtos != null && practiceBaseNameDtos.size() > 0) {
                practiceBaseNameMap = practiceBaseNameDtos.stream().collect(Collectors.groupingBy(BaseNameDto::getUserId));
            }
            for (StudentVipPracticeExportDto studentVipPracticeExportDto : studentVipPracticeExportDtos) {
                List<BaseNameDto> baseNameDtos = vipBaseNameMap.get(studentVipPracticeExportDto.getUserId());
                if (baseNameDtos != null && baseNameDtos.size() > 0) {
                    BaseNameDto baseNameDto = baseNameDtos.get(0);
                    studentVipPracticeExportDto.setVipOverTeacherId(baseNameDto.getTeacherId());
                    studentVipPracticeExportDto.setVipOverTeacherName(baseNameDto.getTeacherName());
                }
                List<BaseNameDto> baseNameDtos1 = practiceBaseNameMap.get(studentVipPracticeExportDto.getUserId());
                if (baseNameDtos1 != null && baseNameDtos1.size() > 0) {
                    BaseNameDto baseNameDto = baseNameDtos1.get(0);
                    studentVipPracticeExportDto.setPracticeOverTeacherId(baseNameDto.getTeacherId());
                    studentVipPracticeExportDto.setPracticeOverTeacherName(baseNameDto.getTeacherName());
                }
                List<BaseNameDto> baseNameDtos2 = normalClassTeacherMap.get(studentVipPracticeExportDto.getUserId());
                if (baseNameDtos2 != null && baseNameDtos2.size() > 0) {
                    BaseNameDto baseNameDto = baseNameDtos2.get(0);
                    studentVipPracticeExportDto.setNormalClassTeacherId(baseNameDto.getTeacherId());
                    studentVipPracticeExportDto.setNormalClassTeacherName(baseNameDto.getTeacherName());
                }
                List<BaseNameDto> baseNameDtos3 = vipFirstNotStartTeacherMap.get(studentVipPracticeExportDto.getUserId());
                if (baseNameDtos3 != null && baseNameDtos3.size() > 0) {
                    BaseNameDto baseNameDto = baseNameDtos3.get(0);
                    studentVipPracticeExportDto.setVipNotStartTeacherId(baseNameDto.getTeacherId());
                    studentVipPracticeExportDto.setVipNotStartTeacherName(baseNameDto.getTeacherName());
                }
                List<BaseNameDto> baseNameDtos4 = practiceFirstNotStartTeacherMap.get(studentVipPracticeExportDto.getUserId());
                if (baseNameDtos4 != null && baseNameDtos4.size() > 0) {
                    BaseNameDto baseNameDto = baseNameDtos4.get(0);
                    studentVipPracticeExportDto.setPracticeNotStartTeacherId(baseNameDto.getTeacherId());
                    studentVipPracticeExportDto.setPracticeNotStartTeacherName(baseNameDto.getTeacherName());
                }
            }
        }
        HSSFWorkbook workbook = getHSSFWorkbook(studentVipPracticeExportDtos, ExportEnum.STUDENT_VIP_PRACTICE);
        exportManagerDownload(workbook, managerDownload);
    }

    @Override
    public void queryStudentCourseInfo(String organId, Integer tenantId, String groupType, ManagerDownload managerDownload, ExportEnum exportEnum) {
        List<ExportStudentCourseInfoDto> rows = courseScheduleStudentPaymentDao.queryStudentCourseInfo(organId, tenantId, groupType);
        HSSFWorkbook workbook = getHSSFWorkbook(rows, exportEnum);
        exportManagerDownload(workbook, managerDownload);
    }

    @Override
    public void queryVipStudentCourseManage(String organId, Integer tenantId, ManagerDownload managerDownload, ExportEnum exportEnum) {
        List<ExportVipStudentCourseManageDto> rows = courseScheduleStudentPaymentDao.queryVipStudentCourseManage(organId, tenantId);
        exportManagerDownload(getHSSFWorkbook(rows, exportEnum), managerDownload);
    }

    @Override
    public void exportStudentSmallClassStatisticsSum(StudentStatisticsQueryInfo queryInfo, ManagerDownload managerDownload) {
        List<StudentStatisticsDto> rows = studentStatisticsService.queryStatisticsPage(queryInfo).getRows();
        try {
            HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"分部", "学生姓名", "学员编号", "联系电话", "声部", "学校", "年级", "学员状态", "未排课时", "总课时", "已完成课时",
                            "剩余课时", "预收金额", "第一次课时间", "最近上课时间", "指导老师编号", "指导老师", "乐团主管编号", "乐团主管", "声部课老师编号", "声部课老师", "近30天课耗", "回访次数",
                            "回访状态", "原因", "回访日期"},
                    new String[]{"studentBasicInfo.organName", "studentBasicInfo.userName", "studentBasicInfo.userId",
                            "studentBasicInfo.phone", "studentBasicInfo.subjectName", "studentBasicInfo.cooperationOrganName", "studentBasicInfo.grade",
                            "studentBasicInfo.studentStatus",
                            "noScheduleNum", "totalCourseNum", "overCourseNum", "subCourseNum", "preCourseFee", "firstCourseTime", "lastCourseTime", "teacherId", "teacherName", "musicDirectorId", "musicDirectorName",
                            "studentBasicInfo.subjectTeacherId", "studentBasicInfo.subjectTeacherName", "latelyCourseConsumer", "visitNum",
                            "lastVisitStatus == null?'':lastVisitStatus == 'LOST' ? '流失':lastVisitStatus == 'THINKING' ? '考虑中':" +
                                    "lastVisitStatus == 'PENDING_PAYMENT' ? '确认缴费待缴费':lastVisitStatus == 'PAUSE' ? '暂停':lastVisitStatus == 'OTHER' ? '其他':''"
                            , "visitReason", "lastVisitTime"}, rows);
            exportManagerDownload(workbook, managerDownload);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void exportMusicGroupCourseScheduleDetail(queryMusicGroupCourseScheduleQueryInfo queryInfo, ManagerDownload managerDownload) {
        List<MusicGroupCourseScheduleDto> rows = classGroupService.queryMusicGroupCourseScheduleDetail(queryInfo).getRows();
        HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"课程编号", "课程开始时间", "课程结束时间", "课程名称", "课程类型", "课程状态", "老师签到", "老师签退", "指导老师",
                        "出勤率", "达标率", "是否服务", "是否布置课后作业", "作业提交率", "结算状态", "是否点名", "备注"},
                new String[]{"courseScheduleId", "classDate + ' ' + startClassTime", "classDate + ' ' + endClassTime",
                        "courseScheduleName", "courseScheduleType.msg", "courseScheduleStatus.msg", "signInStatus.msg",
                        "signOutStatus.msg", "masterTeacherName",
                        "courseScheduleStatistics.attendanceRate", "courseScheduleStatistics.standardRate",
                        "courseScheduleStatistics.serviceFlag == false ? '否':'是'", "courseScheduleStatistics.homeworkFlag == false ? '否':'是'", "courseScheduleStatistics.homeworkCommitRate",
                        "settlementTime == null?'未结算':'已结算'", "isCallNames.msg", "remark"}, rows);
        exportManagerDownload(workbook, managerDownload);
    }

    public HSSFWorkbook getHSSFWorkbook(List rows,ExportEnum exportEnum) {
        try {
            Map<String, String> headMap = getExportMap(new ExportDto(exportEnum));
            String[] header = headMap.keySet().toArray(new String[headMap.keySet().size()]);
            String[] body = headMap.values().toArray(new String[headMap.keySet().size()]);
            return POIUtil.exportExcel(header, body, rows);
        } catch (Exception e) {
            throw new BizException(e);
        }
    }

    public void exportManagerDownload(HSSFWorkbook workbook, ManagerDownload managerDownload) {
        String basePath = new ApplicationHome(this.getClass()).getSource().getParentFile().getPath();
        File file = new File(basePath + "/" + managerDownload.getName());
        OutputStream ouputStream = null;
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            workbook.write(fileOutputStream);
            fileOutputStream.getFD().sync();
            fileOutputStream.close();

            String folder = "download/" + UploadUtil.getFileFloder();
            String url = storagePluginContext.uploadFile(KS3StoragePlugin.PLUGIN_NAME, folder, file);
            //把记录插入下载表
            managerDownload.setFileUrl(url);
            managerDownload.setStatus(1);
            managerDownloadDao.update(managerDownload);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (ouputStream != null) {
                try {
                    ouputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void exportMusicGroupCourseList(ManagerDownload managerDownload, ExportUserAccountQueryInfo queryInfo) {
        List<MusicGroupExportDto> rows = musicGroupDao.exportMusicGroupCourseList(queryInfo);
        try {
            HSSFWorkbook workbook = POIUtil.exportExcel(new String[]{"分部", "乐团编号", "乐团名称", "乐团主管", "出勤率", "达标率", "作业提交率", "成团人数", "新增人数",
                            "退团人数", "在读人数", "流失率"},
                    new String[]{"organName", "musicGroupId", "musicGroupName",
                            "eduName", "attendanceRate", "standardRate", "homeworkCommitRate",
                            "groupMemberNum", "addStuNum", "quitStuNum", "normalNum", "lostRate"}, rows);
            exportManagerDownload(workbook, managerDownload);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public HttpResponseResult asyncExport(Runnable runnable, String excelName) {
        CompletableFuture.runAsync(runnable, exportExecutorService);
        HttpResponseResult<Object> succeed = succeed();
        succeed.setMsg(excelName + "导出申请已提交,请到【报表中心-下载列表查看】");
        return succeed;
    }

    public void setSubTypeDesc(StudentPaymentOrderExportDto basicOrder, Map<Integer, String> userFirstVipMap, Map<Integer, String> userFirstPracticeMap) {
        if (basicOrder.getTypeDesc() == null) {
            if (basicOrder.getGroupType() == GroupType.VIP) {
                //学员没有历史VIP课程则导出为【VIP课新增】
                //学员有历史VIP课程到导出为【VIP课续费]
                if (Objects.equals(userFirstVipMap.get(basicOrder.getUserId()), basicOrder.getMusicGroupId())) {
                    basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_VIP.getMsg());
                } else {
                    basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_VIP.getMsg());
                }
            } else if (basicOrder.getGroupType() == GroupType.PRACTICE) {
                if (Objects.equals(userFirstPracticeMap.get(basicOrder.getUserId()), basicOrder.getMusicGroupId())) {
                    basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_PRACTICE.getMsg());
                } else {
                    basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_PRACTICE.getMsg());
                }
            } else if (basicOrder.getGroupType().equals(GroupType.SUBJECT_CHANGE)) {
                basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
            } else if (basicOrder.getGroupType().equals(GroupType.REPAIR)) {
                basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.REPAIR.getMsg());
            } else {
                basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.OTHER.getMsg());
            }
        }
    }

    //按订单详情计算
    public void calcOrderDetail(StudentPaymentOrderExportDto basicOrder, List<StudentPaymentOrderDetail> detailList, Map<Integer, String> userFirstVipMap) {
        //排除金额为0的订单详情
        detailList = detailList.stream().filter(detail -> detail.getPrice().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(detailList)) {
            return;
        }
        if (basicOrder.getServiceAmount().compareTo(BigDecimal.ZERO) > 0) {
            //如果是指定内部账户，并且分润金额和内部库存金额一致，那么直接判定为云教练收入
            if (basicOrder.getRouteMerNo().equals(goodsSellReceiptMerNo) && detailList.stream().
                    anyMatch(e -> StringUtils.equals(e.getIncomeItem(), "CLOUD_TEACHER") && e.getIncome().compareTo(BigDecimal.ZERO) > 0)) {
                BigDecimal income = detailList.stream().filter(e -> StringUtils.equals(e.getIncomeItem(), "CLOUD_TEACHER") && e.getIncome().compareTo(BigDecimal.ZERO) > 0)
                        .map(e -> e.getIncome()).reduce(BigDecimal.ZERO, BigDecimal::add);
                if (income.compareTo(basicOrder.getServiceAmount()) == 0) {
                    basicOrder.setCloudTeacherFee(income);
                    return;
                }
            }
        }
        List<StudentPaymentOrderDetail> details = detailList.stream().filter(e -> e.getPrice().compareTo(e.getIncome()) > 0).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(details)) {
            return;
        }
        //订单详情去除余额部分
        calculateOrderDetailActualAmount(basicOrder.getExpectAmount(), basicOrder.getBalancePaymentAmount(), details);
        if (basicOrder.getServiceAmount().compareTo(BigDecimal.ZERO) > 0) {
            //计算服务收入
            details.stream().forEach(e -> this.setServiceFee(basicOrder, e, userFirstVipMap));
        }
        if (basicOrder.getSaleAmount().compareTo(BigDecimal.ZERO) > 0) {
            //计算销售收入
            details.stream().forEach(e -> this.setSaleFee(basicOrder, e));
        }
    }

    //按商品订单计算收入
    public void calcSellOrder(StudentPaymentOrderExportDto basicOrder, List<SellOrder> sellOrderList, Map<Integer, Goods> goodsMap) {
        if (basicOrder.getServiceAmount().compareTo(BigDecimal.ZERO) > 0) {
            //计算服务收入（如果商品编号是76）那么算乐器保养费用
            if (sellOrderList.stream().anyMatch(e -> e.getGoodsId().equals("76"))) {
                sellOrderList.stream().forEach(e -> basicOrder.setMaintenanceProductFee(basicOrder.getMaintenanceProductFee().add(e.getActualAmount())));
            }
        } else if (basicOrder.getSaleAmount().compareTo(BigDecimal.ZERO) > 0) {
            //计算销售收入,排除商品编号是76的商品，其他的商品按分类统计
            for (SellOrder e : sellOrderList) {
                this.setSaleFee(basicOrder, e, goodsMap.get(e.getGoodsId()));
            }
        }
    }

    //用于初始化业务数据
    Map<GroupType, Consumer<StudentPaymentOrderExportDto>> groupTypeConsumerMap1 = new HashMap<>(GroupType.values().length);

    @PostConstruct
    public void initGroupTypeConsumerMap1() {
        groupTypeConsumerMap1.put(GroupType.VIP, (basicOrder) -> {
            if (StringUtils.isNotEmpty(basicOrder.getMusicGroupId()) && basicOrder.getClassGroupId() != null) {
                VipGroup vipGroupInfo = vipGroupDao.findVipGroupInfo(Integer.parseInt(basicOrder.getMusicGroupId()), basicOrder.getClassGroupId());
                if (vipGroupInfo != null) {
                    basicOrder.setSchoolName(vipGroupInfo.getSchoolName());
                    basicOrder.setSubjectName(vipGroupInfo.getSubjectName());
                    basicOrder.setEduTeacher(vipGroupInfo.getEducationalTeacherName());
                }
            }
        });
        groupTypeConsumerMap1.put(GroupType.SPORADIC, (basicOrder) -> {
            if (basicOrder.getType() != OrderTypeEnum.DEGREE_REGISTRATION && basicOrder.getChargeType() != null) {
                for (SporadicChargeTypeEnum chargeType : SporadicChargeTypeEnum.values()) {
                    if (!chargeType.getCode().equals(basicOrder.getChargeType())) continue;
                    basicOrder.setSporadicType(chargeType.getMsg());
                }
            }
        });
        groupTypeConsumerMap1.put(GroupType.PRACTICE, (basicOrder) -> {
            if (StringUtils.isNotEmpty(basicOrder.getMusicGroupId())) {
                PracticeCourseDto practiceGroup = practiceGroupDao.findByGroupId(Integer.parseInt(basicOrder.getMusicGroupId()));
                if (practiceGroup != null) {
                    basicOrder.setSubjectName(practiceGroup.getSubjectName());
                    basicOrder.setEduTeacher(practiceGroup.getEduTeacherName());
                }
            }
        });
        groupTypeConsumerMap1.put(GroupType.REPLACEMENT, (basicOrder) -> {
            if (StringUtils.isNotEmpty(basicOrder.getMusicGroupId())) {
                ReplacementInstrumentActivityStatDto info = replacementInstrumentActivityDao.getInfo(Integer.parseInt(basicOrder.getMusicGroupId()));
                if (info != null) {
                    basicOrder.setSubjectName(info.getSubjectName());
                    basicOrder.setCooperationOrganName(info.getCooperationOrganName());
                    basicOrder.setMemo(info.getBrand() + "(" + info.getSpecification() + ")");
                    CooperationOrgan cooperationOrganEduTeacher = musicGroupDao.findCooperationOrganEduTeacher(info.getCooperationOrganId());
                    if (cooperationOrganEduTeacher != null) {
                        basicOrder.setEduTeacher(cooperationOrganEduTeacher.getLinkman());
                    }
                }
            }
        });
        groupTypeConsumerMap1.put(GroupType.MUSIC, (basicOrder) -> {
            StudentRegistration studentRegistration = studentRegistrationDao.findStudentByMusicGroupIdAndUserId(basicOrder.getMusicGroupId(), basicOrder.getUserId());
            if (studentRegistration != null) {
                basicOrder.setSubjectName(studentRegistration.getSubjectName());
                basicOrder.setSchoolName(studentRegistration.getSchoolName());
                basicOrder.setCooperationOrganName(studentRegistration.getRemark());
                basicOrder.setEduTeacher(studentRegistration.getName());
            }
        });
    }

    //用于金额计算
    Map<GroupType, Consumer<StudentPaymentOrderExportDto>> groupTypeConsumerMap = new HashMap<>(GroupType.values().length);

    public @PostConstruct
    void initGroupTypeConsumerMap() {
        groupTypeConsumerMap.put(GroupType.ACTIVITY, (orderDto) -> orderDto.setVipCourseFee(orderDto.getVipCourseFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.VIP, (orderDto) -> orderDto.setVipCourseFee(orderDto.getVipCourseFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.MEMBER, (orderDto) -> orderDto.setCloudTeacherFee(orderDto.getCloudTeacherFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.MUSIC, (orderDto) -> orderDto.setMusicGroupCourseFee(orderDto.getMusicGroupCourseFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.PRACTICE, (orderDto) -> orderDto.setPracticeCourseFee(orderDto.getPracticeCourseFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.REPAIR, (orderDto) -> orderDto.setRepairFee(orderDto.getRepairFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.OUTORDER, (orderDto) -> orderDto.setOtherFee(orderDto.getOtherFee().add(orderDto.getActualAmount())));
        groupTypeConsumerMap.put(GroupType.SPORADIC, this::accept);
        if (StringUtils.isEmpty(goodsSellReceiptMerNo)) {
            goodsSellReceiptMerNo = sysConfigDao.findConfigValue("goodsSellReceiptMerNo");
        }
    }

    //用于金额计算
    Map<Integer, Consumer<StudentPaymentOrderExportDto>> chargeTypeConsumerMap = new HashMap<>(SporadicChargeTypeEnum.values().length);

    public @PostConstruct
    void initChargeTypeConsumerMap() {
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.LEVEL.getCode(), (orderDto) -> orderDto.setDegreeFee(orderDto.getDegreeFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.PRACTICE_GROUP_BUY.getCode(), (orderDto) -> orderDto.setPracticeCourseFee(orderDto.getPracticeCourseFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.MUSIC_UPKEEP.getCode(), (orderDto) -> orderDto.setMaintenanceFee(orderDto.getMaintenanceFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.VISITING_FEE.getCode(), (orderDto) -> orderDto.setVisitFee(orderDto.getVisitFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.RECHARGE.getCode(), (orderDto) -> orderDto.setRechargeFee(orderDto.getRechargeFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.HIGH_ONLINE_ACTIVITY.getCode(), (orderDto) -> orderDto.setRechargeFee(orderDto.getRechargeFee().add(orderDto.getActualAmount())));
        chargeTypeConsumerMap.put(SporadicChargeTypeEnum.CLOUD_TEACHER_BUY.getCode(), (orderDto) -> orderDto.setCloudTeacherFee(orderDto.getCloudTeacherFee().add(orderDto.getActualAmount())));
    }


    public void setSaleFee(StudentPaymentOrderExportDto basicOrder) {
        BigDecimal actualAmount = basicOrder.getActualAmount();
        switch (basicOrder.getGroupType()) {
            case GOODS_SELL:
                basicOrder.setMusicalFee(basicOrder.getMusicalFee().add(actualAmount));
                break;
            case REPLACEMENT:
                //乐器置换统一算到乐器收入
                basicOrder.setMusicalFee(basicOrder.getMusicalFee().add(actualAmount));
                break;
            case SPORADIC:
                if (basicOrder.getType() != OrderTypeEnum.DEGREE_REGISTRATION) {
                    basicOrder.setOtherFee(basicOrder.getOtherFee().add(actualAmount));
                }
            case SUBJECT_CHANGE:
                //有一部分声部更换没有定义，放到辅件里面
                basicOrder.setTeachingFee(basicOrder.getTeachingFee().add(actualAmount));
                break;
        }
    }

    Map<OrderDetailTypeEnum, BiConsumer<StudentPaymentOrderExportDto, StudentPaymentOrderDetail>> orderDetailTypeServiceConsumerMap = new HashMap<>(OrderDetailTypeEnum.values().length);

    public @PostConstruct
    void initOrderDetailTypeServiceConsumerMap() {
        BiConsumer<StudentPaymentOrderExportDto, StudentPaymentOrderDetail> con1 = (orderDto, detail) -> orderDto.setMusicGroupCourseFee(orderDto.getMusicGroupCourseFee().add(detail.getPrice()));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.COURSE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.CLASSROOM, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.SINGLE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.MIX, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.COMPREHENSIVE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.ENLIGHTENMENT, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.TRAINING_SINGLE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.TRAINING_MIX, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.MUSIC_NETWORK, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.HIGH, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.HIGH_ONLINE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.HIGH_ONLINE_COURSE, con1);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.DEGREE_REGISTRATION, (orderDto, detail) -> orderDto.setDegreeFee(orderDto.getDegreeFee().add(detail.getPrice())));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.MAINTENANCE, (orderDto, detail) -> orderDto.setMaintenanceFee(orderDto.getMaintenanceFee().add(detail.getPrice())));
        BiConsumer<StudentPaymentOrderExportDto, StudentPaymentOrderDetail> con2 = (orderDto, detail) -> orderDto.setCloudTeacherFee(orderDto.getCloudTeacherFee().add(detail.getPrice()));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.CLOUD_TEACHER, con2);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.CLOUD_TEACHER_PLUS, con2);
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.THEORY_COURSE, (orderDto, detail) -> orderDto.setTheoryCourseFee(orderDto.getTheoryCourseFee().add(detail.getPrice())));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.PRACTICE, (orderDto, detail) -> orderDto.setPracticeCourseFee(orderDto.getPracticeCourseFee().add(detail.getPrice())));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.VIP, (orderDto, detail) -> orderDto.setVipCourseFee(orderDto.getVipCourseFee().add(detail.getPrice())));
        orderDetailTypeServiceConsumerMap.put(OrderDetailTypeEnum.REPAIR, (orderDto, detail) -> orderDto.setRepairFee(orderDto.getRepairFee().add(detail.getPrice())));
    }

    //计算订单详情实际支付金额（按比例）
    public void calculateOrderDetailActualAmount(BigDecimal expectAmount, BigDecimal balance, List<StudentPaymentOrderDetail> detailList) {
        if (balance.compareTo(BigDecimal.ZERO) == 0) {
            return;
        }
        //如果订单有余额，那么按比例排除掉订单详情中的余额，多的部分放在最后一条记录中
        //比例 = 订单详情金额/订单总金额
        //实际支付金额 = 订单详情金额 * 比例 保留两位小数，其余舍掉，如果是最后一笔订单详情，将剩余的金额直接赋值给它
        BigDecimal subTotalAmount = expectAmount.subtract(balance);
        BigDecimal actualAmount = subTotalAmount;
        for (int i = 0; i < detailList.size(); i++) {
            StudentPaymentOrderDetail detail = detailList.get(i);
            BigDecimal ratio = detail.getPrice().divide(expectAmount, 8, BigDecimal.ROUND_DOWN);
            BigDecimal price = actualAmount.multiply(ratio).setScale(2, BigDecimal.ROUND_DOWN);
            if (i == detailList.size() - 1) {
                detail.setPrice(subTotalAmount);
            } else {
                detail.setPrice(price);
            }
            subTotalAmount = subTotalAmount.subtract(price);
        }
    }

    public void setServiceFee(StudentPaymentOrderExportDto basicOrder, StudentPaymentOrderDetail orderDetail,
                              Map<Integer, String> userFirstVipMap) {
        Optional.ofNullable(orderDetailTypeServiceConsumerMap.get(orderDetail.getType())).ifPresent(consumer -> consumer.accept(basicOrder, orderDetail));
        if (orderDetail.getType() == OrderDetailTypeEnum.VIP && basicOrder.getTypeDesc() == null) {
            //学员没有历史VIP课程则导出为【VIP课新增】
            //学员有历史VIP课程到导出为【VIP课续费】
            if (Objects.equals(userFirstVipMap.get(basicOrder.getUserId()), basicOrder.getMusicGroupId())) {
                basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_VIP.getMsg());
            } else {
                basicOrder.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_VIP.getMsg());
            }
        }
    }

    public void setSaleFee(StudentPaymentOrderExportDto basicOrder, StudentPaymentOrderDetail orderDetail) {
        BigDecimal price = orderDetail.getPrice().subtract(orderDetail.getIncome());
        switch (orderDetail.getType()) {
            case OTHER:
                basicOrder.setOtherFee(basicOrder.getOtherFee().add(price));
                break;
            case MUSICAL:
                if (orderDetail.getKitGroupPurchaseType() != null && orderDetail.getKitGroupPurchaseType().equals(KitGroupPurchaseTypeEnum.LEASE)) {
                    basicOrder.setLeaseFee(basicOrder.getLeaseFee().add(price));
                } else {
                    basicOrder.setMusicalFee(basicOrder.getMusicalFee().add(price));
                }
                break;
            case TEACHING:
            case ACCESSORIES:
                basicOrder.setTeachingFee(basicOrder.getTeachingFee().add(price));
                break;
        }
    }

    public void setSaleFee(StudentPaymentOrderExportDto basicOrder, SellOrder sellOrder, Goods goods) {
        if (sellOrder.getOrderId().equals("76")) {
            return;
        }
        switch (goods.getType()) {
            case ACCESSORIES:
            case TEACHING:
            case STAFF:
                basicOrder.setTeachingFee(basicOrder.getTeachingFee().add(sellOrder.getActualAmount()));
                break;
            case INSTRUMENT:
                basicOrder.setMusicalFee(basicOrder.getMusicalFee().add(sellOrder.getActualAmount()));
                break;
            case OTHER:
                basicOrder.setOtherFee(basicOrder.getOtherFee().add(sellOrder.getActualAmount()));
                break;
        }
    }

    //计算汇付手续费和平台手续费
    public void calcPlatformFee(StudentPaymentOrderExportDto row, Map<String, BigDecimal> serviceChargeMap,
                                Map<String, Integer> orderCountMap, TenantConfig tenantConfig, Map<String, FeeFlagNumDto> feeFlagMap) {
        BigDecimal currentFee = BigDecimal.ZERO;
        if (row.getPaymentChannel() != null && row.getPaymentChannel().equals("ADAPAY")) {
            Integer times = orderCountMap.get(row.getOrderNo());
            if (times == null) {
                times = 1;
            } else {
                ++times;
            }
            orderCountMap.put(row.getOrderNo(), times);

            currentFee = row.getServiceFee();

            //兼容2022年之前的数据
            if (currentFee == null || (currentFee.floatValue() == 0 && row.getCreateTime().before(DateUtil.stringToDate("2022-01-01 00:00:00")))) {
                BigDecimal transferFee = serviceChargeMap.get(row.getOrderNo());
                if (transferFee == null) {
                    transferFee = BigDecimal.ZERO;
                }
                currentFee = row.getRouteAmount().multiply(new BigDecimal("0.28")).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                BigDecimal totalFee = row.getActualAmount().multiply(new BigDecimal("0.28")).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
                FeeFlagNumDto countFeeFlagNum = feeFlagMap.get(row.getOrderNo());
                if (totalFee.subtract(transferFee.add(currentFee)).doubleValue() < 0 || countFeeFlagNum == null || times == countFeeFlagNum.getTotalNum()) {
                    currentFee = totalFee.subtract(transferFee);
                    serviceChargeMap.put(row.getOrderNo(), totalFee);
                } else {
                    serviceChargeMap.put(row.getOrderNo(), transferFee.add(currentFee));
                }
            }
        }
        row.setTransferFee(currentFee);
        row.setPlatformFee(row.getActualAmount().multiply(tenantConfig.getChargeRate()).divide(new BigDecimal(1000), 2, BigDecimal.ROUND_HALF_UP));
    }

    //获取乐团信息
    public void initMusicGroupInfo(StudentPaymentOrderExportDto row, Map<String, String> musicGroupNameMap, Map<Integer, String> firstMusicMap
            , Map<Integer, String> userLastMusicIdMap, Map<Integer, String> userLastMusicNameMap, Map<Long, Integer> calenderCooperationMap) {
        Long calenderId = row.getCalenderId();
        if (calenderId != null) {
            row.setFeeMusicGroupId(row.getMusicGroupId());
            row.setFeeMusicGroupName(musicGroupNameMap.get(row.getMusicGroupId()));
            OrderTypeEnum orderTypeEnum = row.getType();
            if (orderTypeEnum == OrderTypeEnum.APPLY || orderTypeEnum == OrderTypeEnum.ADD_STUDENT) {
                Integer cooperationId = calenderCooperationMap.get(calenderId);
                if (cooperationId != null) {
                    String firstMusicId = firstMusicMap.get(cooperationId);
                    if (StringUtils.isEmpty(firstMusicId)) {
                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
                    } else {
                        if (Objects.equals(firstMusicId, row.getMusicGroupId())) {
                            row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.NEW_MUSIC.getMsg());
                        } else {
                            row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.ADD_MUSIC.getMsg());
                        }
                    }
                }
            } else {
                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_MUSIC.getMsg());
            }
        } else {
            row.setFeeMusicGroupId(userLastMusicIdMap.get(row.getUserId()));
            row.setFeeMusicGroupName(userLastMusicNameMap.get(row.getUserId()));
        }
    }

    private void accept(StudentPaymentOrderExportDto orderDto) {
        if (orderDto.getType() == OrderTypeEnum.DEGREE_REGISTRATION) {
            orderDto.setDegreeFee(orderDto.getDegreeFee().add(orderDto.getActualAmount()));
        } else {
            Consumer<StudentPaymentOrderExportDto> dtoConsumer = chargeTypeConsumerMap.get(orderDto.getChargeType());
            if (dtoConsumer != null) {
                dtoConsumer.accept(orderDto);
            } else {
                orderDto.setOtherFee(orderDto.getOtherFee().add(orderDto.getActualAmount()));
            }
        }
    }
}
