浏览代码

Merge branch 'saas' of http://git.dayaedu.com/yonge/mec into saas_0415_updateCourseActualPrice

 Conflicts:
	mec-biz/src/main/java/com/ym/mec/biz/event/listener/CourseEventListener.java
zouxuan 3 年之前
父节点
当前提交
33d1f07a6f
共有 88 个文件被更改,包括 4415 次插入728 次删除
  1. 15 0
      audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java
  2. 8 0
      audio-analysis/src/main/java/com/yonge/netty/server/service/AudioCompareHandler.java
  3. 17 8
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ClassGroupStudentMapperDao.java
  4. 6 4
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ClassGroupTeacherMapperDao.java
  5. 8 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/IndexBaseMonthDataDao.java
  6. 19 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/SellOrderDao.java
  7. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentBasicInfoDao.java
  8. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentDao.java
  9. 2 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentPaymentOrderDao.java
  10. 28 5
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentRegistrationDao.java
  11. 66 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentStatisticsDao.java
  12. 10 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ClassGroupStudentMapperDto.java
  13. 64 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentImportDto.java
  14. 111 37
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentPaymentOrderExportDto.java
  15. 173 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentPaymentOrderSumExportDto.java
  16. 16 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsDto.java
  17. 116 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsSumDto.java
  18. 49 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsSumForDateDto.java
  19. 29 6
      mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherServeDto.java
  20. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ManagerDownload.java
  21. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicGroup.java
  22. 184 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentBasicInfo.java
  23. 28 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentExtracurricularExercisesSituation.java
  24. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentPaymentRouteOrder.java
  25. 311 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentStatistics.java
  26. 46 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentVisit.java
  27. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ExportEnum.java
  28. 3 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ExportTypeEnum.java
  29. 9 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FivePlusGradeEnum.java
  30. 5 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/IndexDataType.java
  31. 5 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/OrderTypeEnum.java
  32. 9 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/SixPlusGradeEnum.java
  33. 2 1
      mec-biz/src/main/java/com/ym/mec/biz/dal/enums/TemplateTypeEnum.java
  34. 12 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentExercisesSituationQueryInfo.java
  35. 165 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentStatisticsQueryInfo.java
  36. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentVisitQueryInfo.java
  37. 20 0
      mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysExamSongQueryInfo.java
  38. 7 2
      mec-biz/src/main/java/com/ym/mec/biz/service/ExportService.java
  39. 9 0
      mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupService.java
  40. 3 4
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentServeService.java
  41. 34 0
      mec-biz/src/main/java/com/ym/mec/biz/service/StudentStatisticsService.java
  42. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicScoreCategoriesService.java
  43. 484 69
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExportServiceImpl.java
  44. 1 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExtracurricularExercisesMessageServiceImpl.java
  45. 19 3
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java
  46. 11 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/IndexBaseMonthDataServiceImpl.java
  47. 438 32
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java
  48. 1 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentExtracurricularExercisesSituationServiceImpl.java
  49. 9 1
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentRouteOrderServiceImpl.java
  50. 227 357
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServeServiceImpl.java
  51. 139 0
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentStatisticsServiceImpl.java
  52. 15 5
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java
  53. 28 18
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreAccompanimentServiceImpl.java
  54. 34 4
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreCategoriesServiceImpl.java
  55. 16 11
      mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreServiceImpl.java
  56. 18 0
      mec-biz/src/main/resources/config/mybatis/ClassGroupStudentMapperMapper.xml
  57. 52 0
      mec-biz/src/main/resources/config/mybatis/IndexBaseMonthDataMapper.xml
  58. 6 2
      mec-biz/src/main/resources/config/mybatis/MusicGroupMapper.xml
  59. 33 0
      mec-biz/src/main/resources/config/mybatis/SellOrderMapper.xml
  60. 106 0
      mec-biz/src/main/resources/config/mybatis/StudentBasicInfoMapper.xml
  61. 3 7
      mec-biz/src/main/resources/config/mybatis/StudentMapper.xml
  62. 4 0
      mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml
  63. 13 8
      mec-biz/src/main/resources/config/mybatis/StudentPaymentRouteOrderMapper.xml
  64. 8 0
      mec-biz/src/main/resources/config/mybatis/StudentRegistrationMapper.xml
  65. 679 0
      mec-biz/src/main/resources/config/mybatis/StudentStatisticsMapper.xml
  66. 11 3
      mec-biz/src/main/resources/config/mybatis/StudentVisitMapper.xml
  67. 3 3
      mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml
  68. 2 1
      mec-biz/src/main/resources/config/mybatis/SysMusicCompareWeekDataMapper.xml
  69. 6 0
      mec-biz/src/main/resources/config/mybatis/SysMusicScoreAccompanimentMapper.xml
  70. 6 0
      mec-client-api/src/main/java/com/ym/mec/task/TaskRemoteService.java
  71. 5 0
      mec-client-api/src/main/java/com/ym/mec/task/fallback/TaskRemoteServiceFallback.java
  72. 2 2
      mec-student/src/main/java/com/ym/mec/student/controller/SysMusicScoreCategoriesController.java
  73. 19 0
      mec-task/src/main/java/com/ym/mec/task/jobs/StudentSmallClassStatisticsTask.java
  74. 18 5
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicScoreAccompanimentController.java
  75. 1 1
      mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicScoreCategoriesController.java
  76. 16 0
      mec-util/src/main/java/com/ym/mec/util/validator/CommonValidator.java
  77. 0 1
      mec-web/src/main/java/com/ym/mec/web/controller/CourseScheduleController.java
  78. 14 5
      mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java
  79. 51 23
      mec-web/src/main/java/com/ym/mec/web/controller/ImportController.java
  80. 119 0
      mec-web/src/main/java/com/ym/mec/web/controller/StudentStatisticsController.java
  81. 43 10
      mec-web/src/main/java/com/ym/mec/web/controller/SysMusicScoreController.java
  82. 9 1
      mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java
  83. 1 1
      mec-web/src/main/java/com/ym/mec/web/controller/education/EduMusicScoreController.java
  84. 1 0
      mec-web/src/main/resources/columnMapper.ini
  85. 二进制
      mec-web/src/main/resources/excelTemplate/外部学生入团导入模板.xls
  86. 二进制
      mec-web/src/main/resources/excelTemplate/财务管理导入模板.xls
  87. 8 4
      mec-web/src/main/resources/exportColumnMapper.ini
  88. 98 78
      mec-web/src/main/resources/logback-spring.xml

+ 15 - 0
audio-analysis/src/main/java/com/yonge/audio/AudioAnalysisServerApplication.java

@@ -1,17 +1,23 @@
 package com.yonge.audio;
 
+import java.util.ArrayList;
+import java.util.List;
+
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.client.loadbalancer.LoadBalanced;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.MediaType;
 import org.springframework.web.client.RestTemplate;
 
 import com.spring4all.swagger.EnableSwagger2Doc;
+import com.ym.mec.common.config.LocalFastJsonHttpMessageConverter;
 
 @SpringBootApplication
 @EnableDiscoveryClient
@@ -31,4 +37,13 @@ public class AudioAnalysisServerApplication {
 	public RestTemplate restTemplate() {
 		return new RestTemplate();
 	}
+	
+	@Bean
+    public HttpMessageConverters fastJsonHttpMessageConverters(){
+		LocalFastJsonHttpMessageConverter converter = new LocalFastJsonHttpMessageConverter();
+        List<MediaType> fastMediaTypes =  new ArrayList<MediaType>();
+        fastMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
+        converter.setSupportedMediaTypes(fastMediaTypes);
+        return new HttpMessageConverters(converter);
+    }
 }

+ 8 - 0
audio-analysis/src/main/java/com/yonge/netty/server/service/AudioCompareHandler.java

@@ -25,6 +25,8 @@ import org.springframework.stereotype.Component;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONPath;
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.SysMusicCompareRecord;
 import com.ym.mec.biz.dal.enums.DeviceTypeEnum;
 import com.ym.mec.biz.dal.enums.FeatureType;
@@ -57,6 +59,9 @@ public class AudioCompareHandler implements MessageHandler {
 	
 	@Autowired
 	private SysMusicCompareRecordService sysMusicCompareRecordService;
+	
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
 
     @Autowired
     private StoragePluginContext storagePluginContext;
@@ -149,6 +154,9 @@ public class AudioCompareHandler implements MessageHandler {
 				sysMusicCompareRecord.setSpeed(musicXmlBasicInfo.getSpeed());
 				sysMusicCompareRecord.setPartIndex(musicXmlBasicInfo.getPartIndex());
 				
+				SysUser sysUser = sysUserFeignService.queryUserById(sysMusicCompareRecord.getUserId());
+				sysMusicCompareRecord.setTenantId(sysUser.getTenantId());
+				
 				MusicXmlNote musicXmlNote = musicXmlBasicInfo.getMusicXmlInfos().stream().max(Comparator.comparing(MusicXmlNote::getTimeStamp)).get();
 				sysMusicCompareRecord.setSourceTime((float) ((musicXmlNote.getTimeStamp()+musicXmlNote.getDuration())/1000));
 				sysMusicCompareRecordService.insert(sysMusicCompareRecord);

+ 17 - 8
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ClassGroupStudentMapperDao.java

@@ -1,20 +1,27 @@
 package com.ym.mec.biz.dal.dao;
 
-import com.ym.mec.biz.dal.dto.*;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ibatis.annotations.Param;
+
+import com.ym.mec.biz.dal.dto.BaseMapDto;
+import com.ym.mec.biz.dal.dto.ClassGroupStudentInfoDto;
+import com.ym.mec.biz.dal.dto.ClassGroupStudentMapperDto;
+import com.ym.mec.biz.dal.dto.StudentAttendanceViewDto;
+import com.ym.mec.biz.dal.dto.StudentEduTeacherDto;
+import com.ym.mec.biz.dal.dto.StudentNameAndPhoneDto;
+import com.ym.mec.biz.dal.dto.TeacherClassStudentDto;
 import com.ym.mec.biz.dal.entity.ClassGroup;
 import com.ym.mec.biz.dal.entity.ClassGroupStudentMapper;
-import com.ym.mec.biz.dal.entity.CourseScheduleStudentPayment;
 import com.ym.mec.biz.dal.entity.StudentRegistration;
 import com.ym.mec.biz.dal.enums.ClassGroupStudentStatusEnum;
 import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
 import com.ym.mec.biz.dal.enums.GroupType;
+import com.ym.mec.biz.dal.enums.TeachTypeEnum;
 import com.ym.mec.common.dal.BaseDAO;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
 
 public interface ClassGroupStudentMapperDao extends BaseDAO<Long, ClassGroupStudentMapper> {
 
@@ -479,4 +486,6 @@ public interface ClassGroupStudentMapperDao extends BaseDAO<Long, ClassGroupStud
      */
     List<ClassGroup> getStudentClassGroupWithTeacher(@Param("studentIds") Set<Integer> studentIds,
                                                      @Param("teacherId") Integer teacherId);
+    
+    List<ClassGroupStudentMapperDto> queryByClassGroupType(@Param("musicGroupId") String musicGroupId,@Param("classGroupType") ClassGroupTypeEnum classGroupType,@Param("teacherRole") TeachTypeEnum teacherRole, @Param("studentIdList") List<Integer> studentIdList);
 }

+ 6 - 4
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/ClassGroupTeacherMapperDao.java

@@ -1,14 +1,16 @@
 package com.ym.mec.biz.dal.dao;
 
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ibatis.annotations.Param;
+
 import com.ym.mec.biz.dal.dto.ClassGroupTeacherMapDto;
 import com.ym.mec.biz.dal.entity.ClassGroupTeacherMapper;
+import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
 import com.ym.mec.biz.dal.enums.GroupType;
 import com.ym.mec.biz.dal.enums.TeachTypeEnum;
 import com.ym.mec.common.dal.BaseDAO;
-import org.apache.ibatis.annotations.Param;
-
-import java.util.List;
-import java.util.Set;
 
 public interface ClassGroupTeacherMapperDao extends BaseDAO<Long, ClassGroupTeacherMapper> {
 

+ 8 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/IndexBaseMonthDataDao.java

@@ -389,4 +389,12 @@ public interface IndexBaseMonthDataDao extends BaseDAO<Long, IndexBaseMonthData>
      */
     List<CloudTeacherActiveTargetDto> countCloudTeacherActive(Map<String, Object> params);
 
+    //获取vip课订单数量
+    List<IndexBaseMonthData> getStudentVipOrderNum(@Param("dayStr") String dayStr,@Param("tenantId") Integer tenantId);
+
+    //获取乐理课订单数量
+    List<IndexBaseMonthData> getStudentTheoryOrderNum(@Param("dayStr") String dayStr,@Param("tenantId") Integer tenantId);
+
+    //获取网管课订单数量
+    List<IndexBaseMonthData> getStudentPracticeOrderNum(@Param("dayStr") String dayStr,@Param("tenantId") Integer tenantId);
 }

+ 19 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/SellOrderDao.java

@@ -9,6 +9,7 @@ import org.apache.ibatis.annotations.Param;
 import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 public interface SellOrderDao extends BaseDAO<Integer, SellOrder> {
 
@@ -203,9 +204,27 @@ public interface SellOrderDao extends BaseDAO<Integer, SellOrder> {
     StudentPaymentOrderExportDto getFeeByType(@Param("orderId") Long orderId);
 
     /**
+     * 获取订单的各类型费用
+     *
+     * @param orderIdList
+     * @return
+     */
+    List<StudentPaymentOrderExportDto> queryFeeByType(@Param("orderIdList") List<Long> orderIdList);
+
+    /**
      * 获取打包辅件中乐保
      * @param orderId
      * @return
      */
     BigDecimal getChildRepair(@Param("orderId") Long orderId);
+
+    /**
+     * 获取打包辅件中乐保
+     * @param orderIdList
+     * @return
+     */
+    List<Map<Long,BigDecimal>> queryChildRepair(@Param("orderIdList") List<Long> orderIdList);
+
+    //统计外部销售收入总金额
+    List<Map<Long, String>> sumOutOrderAmount(@Param("outOrderList") List<Long> outOrderList);
 }

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentBasicInfoDao.java

@@ -0,0 +1,12 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.biz.dal.entity.StudentBasicInfo;
+import com.ym.mec.common.dal.BaseDAO;
+
+public interface StudentBasicInfoDao extends BaseDAO<Integer, StudentBasicInfo> {
+
+
+    Integer getMaxId();
+
+    void updateSubjectTeacher();
+}

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentDao.java

@@ -102,7 +102,7 @@ public interface StudentDao extends com.ym.mec.common.dal.BaseDAO<Integer, Stude
     List<StudentServeCourseDto> getServeStudentCourseStartTimes(@Param("monday") String monday, @Param("tenantId") Integer tenantId);
 
     List<StudentServeCourseDto> getStudentFutureCourseInfo(@Param("monday") String monday,
-                                                           @Param("nextMonday") String nextMonday,
+                                                           @Param("sunday") String sunday,
                                                            @Param("studentIds") List<Integer> studentIds, @Param("tenantId") Integer tenantId);
 
     List<StudentServeCourseDto> getNoCourseBeServeStudentInfo(@Param("studentIds") List<Integer> noCourseStudentIds, @Param("tenantId") Integer tenantId);

+ 2 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentPaymentOrderDao.java

@@ -452,4 +452,6 @@ public interface StudentPaymentOrderDao extends BaseDAO<Long, StudentPaymentOrde
 
     StudentPaymentOrderVo queryOrderDetail(@Param("orderNo") String orderNo);
 
+    //获取学员之前的乐团缴费订单数量
+    int getStudentMusicOrderNum(@Param("musicGroupId") String musicGroupId, @Param("userId") Integer userId, @Param("orderId") Long orderId);
 }

+ 28 - 5
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentRegistrationDao.java

@@ -1,16 +1,37 @@
 package com.ym.mec.biz.dal.dao;
 
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import com.ym.mec.biz.dal.dto.*;
-import com.ym.mec.biz.dal.entity.*;
-
-import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
 import org.apache.ibatis.annotations.Param;
 
 import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dto.Mapper;
+import com.ym.mec.biz.dal.dto.MusicGroupRegAndMoneyDto;
+import com.ym.mec.biz.dal.dto.NoClassMusicStudentDto;
+import com.ym.mec.biz.dal.dto.OrderStatisDto;
+import com.ym.mec.biz.dal.dto.RegisterDto;
+import com.ym.mec.biz.dal.dto.StudentApplyDetailDto;
+import com.ym.mec.biz.dal.dto.StudentClassInfoDto;
+import com.ym.mec.biz.dal.dto.StudentFeeDetailDto;
+import com.ym.mec.biz.dal.dto.StudentInfo;
+import com.ym.mec.biz.dal.dto.StudentMusicDetailDto;
+import com.ym.mec.biz.dal.dto.StudentMusicGroupDto;
+import com.ym.mec.biz.dal.dto.StudentRegisterInstrumentsDetailDto;
+import com.ym.mec.biz.dal.dto.StudentRegisterPerDto;
+import com.ym.mec.biz.dal.dto.SubjectApplyDetailDto;
+import com.ym.mec.biz.dal.dto.UserGroupDto;
+import com.ym.mec.biz.dal.entity.MusicGroup;
+import com.ym.mec.biz.dal.entity.MusicGroupSubjectPlan;
+import com.ym.mec.biz.dal.entity.StudentInstrument;
+import com.ym.mec.biz.dal.entity.StudentRegistration;
+import com.ym.mec.biz.dal.entity.Subject;
 import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
+import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
 import com.ym.mec.common.dal.BaseDAO;
 
 public interface StudentRegistrationDao extends BaseDAO<Long, StudentRegistration> {
@@ -738,4 +759,6 @@ public interface StudentRegistrationDao extends BaseDAO<Long, StudentRegistratio
     * @date 2022/3/16 14:10
     */
     List<Map<Integer,String>> getLastMusicGroupName(@Param("userIds") List<Integer> userIds);
+    
+    List<StudentRegistration> queryServiceStudentByMusicGroupStatus(@Param("nextMonday") String nextMonday,@Param("tenantId") Integer tenantId);
 }

+ 66 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dao/StudentStatisticsDao.java

@@ -0,0 +1,66 @@
+package com.ym.mec.biz.dal.dao;
+
+import com.ym.mec.biz.dal.dto.StudentStatisticsDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumDto;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.biz.dal.entity.StudentStatistics;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface StudentStatisticsDao extends BaseDAO<Integer, StudentStatistics> {
+
+    //更新乐团主管、指导老师
+    List<StudentStatistics> queryStatisticsTeacherAndEdu();
+
+    //更新乐团主管、指导老师
+    List<StudentStatistics> queryStatisticsTeacherAndEdu2();
+
+    //更新总课时数、已完成、剩余课时数、最近30天课耗
+    List<StudentStatistics> queryStatisticsCourseNum();
+
+    //更新未排课总数
+    List<StudentStatistics> queryStatisticsNoCourseNum();
+
+    //更新未开始价值
+    List<StudentStatistics> queryStatisticsNotStartCourseFee();
+
+    //更新未排课课程价值
+    List<StudentStatistics> queryStatisticsNoCourseFee();
+
+    //更新第一次课的时间\最近一次课时间
+    List<StudentStatistics> queryStatisticsFirstAndLastCourseTime();
+
+    int countStatistics(Map<String, Object> params);
+
+    List<StudentStatisticsDto> queryStatistics(Map<String, Object> params);
+
+    //更新进行中课程组数量
+    List<StudentStatistics> queryStatisticsNormalGroupNum();
+
+    //汇总小课数据
+    StudentStatisticsSumDto studentSmallClassStatisticsSum(@Param("groupType") String groupType, @Param("organIdList") List<Integer> organIdList);
+
+    //统计新增人数
+    Integer countAddStudentNum(@Param("groupType") String groupType, @Param("startDate") String startDate, @Param("endDate") String endDate, @Param("organIdList") List<Integer> organIdList);
+
+    //统计续费人数
+    Integer countRenewStudentNum(@Param("groupType") String groupType, @Param("endDate") String endDate, @Param("organIdList") List<Integer> organIdList);
+
+    //统计回访人数
+    Integer countVisitNum(@Param("groupType") String groupType, @Param("startDate") String startDate, @Param("endDate") String endDate, @Param("organIdList") List<Integer> organIdList);
+
+    //统计流失人数
+    Integer countLostStudentNum(@Param("groupType") String groupType, @Param("startDate") String startDate, @Param("endDate") String endDate, @Param("organIdList") List<Integer> organIdList);
+
+    //获取指导老师列表
+    List<Integer> queryTeacherIds(@Param("groupType") String groupType);
+
+    //获取乐团主管
+    List<Integer> queryDirectorList(@Param("groupType") String groupType);
+
+    void clean();
+
+    void batchUpdate(@Param("statisticsList") List<StudentStatistics> statisticsList);
+}

+ 10 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/ClassGroupStudentMapperDto.java

@@ -9,6 +9,8 @@ public class ClassGroupStudentMapperDto extends ClassGroupStudentMapper {
 
     @ApiModelProperty(value = "科目名称(声部名称)",required = true)
     private String subjectName;
+    
+    private Integer teacherId;
 
     public Integer actualSubjectId() {
         return actualSubjectId;
@@ -25,4 +27,12 @@ public class ClassGroupStudentMapperDto extends ClassGroupStudentMapper {
     public void setSubjectName(String subjectName) {
         this.subjectName = subjectName;
     }
+
+	public Integer getTeacherId() {
+		return teacherId;
+	}
+
+	public void setTeacherId(Integer teacherId) {
+		this.teacherId = teacherId;
+	}
 }

+ 64 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentImportDto.java

@@ -0,0 +1,64 @@
+package com.ym.mec.biz.dal.dto;
+
+public class StudentImportDto {
+
+	private String name;
+	
+	private String mobileNo;
+	
+	private String sex;
+	
+	private String subjectName;
+	
+	private String gradeName;
+	
+	private Integer userId;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public String getMobileNo() {
+		return mobileNo;
+	}
+
+	public void setMobileNo(String mobileNo) {
+		this.mobileNo = mobileNo;
+	}
+
+	public String getSex() {
+		return sex;
+	}
+
+	public void setSex(String sex) {
+		this.sex = sex;
+	}
+
+	public String getSubjectName() {
+		return subjectName;
+	}
+
+	public void setSubjectName(String subjectName) {
+		this.subjectName = subjectName;
+	}
+
+	public String getGradeName() {
+		return gradeName;
+	}
+
+	public void setGradeName(String gradeName) {
+		this.gradeName = gradeName;
+	}
+
+	public Integer getUserId() {
+		return userId;
+	}
+
+	public void setUserId(Integer userId) {
+		this.userId = userId;
+	}
+}

+ 111 - 37
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentPaymentOrderExportDto.java

@@ -1,6 +1,5 @@
 package com.ym.mec.biz.dal.dto;
 
-import com.ym.mec.biz.dal.entity.CourseSchedule;
 import com.ym.mec.biz.dal.entity.Goods;
 import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
 import com.ym.mec.biz.dal.entity.StudentPaymentOrderDetail;
@@ -11,96 +10,148 @@ import java.math.BigDecimal;
 import java.util.List;
 
 public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
-    //零星费用
+    @ApiModelProperty(value = "分部",required = true)
+    private String organName;
+
+    @ApiModelProperty(value = "零星费用",required = true)
     private BigDecimal sporadicAmount;
 
     //零星费用类型
+    @ApiModelProperty(value = "零星费用类型",required = true)
     private String sporadicType;
 
-    //课程费用(废弃)
-    private BigDecimal courseFee = BigDecimal.ZERO;
-
-    //新生专享(废弃)
-    private BigDecimal highOnlineCourseFee = BigDecimal.ZERO;
-
     //乐器费用
+    @ApiModelProperty(value = "乐器费用",required = true)
     private BigDecimal musicalFee = BigDecimal.ZERO;
 
     //押金费用
+    @ApiModelProperty(value = "押金费用",required = true)
     private BigDecimal leaseFee = BigDecimal.ZERO;
 
     //教辅费用
+    @ApiModelProperty(value = "教辅费用",required = true)
     private BigDecimal teachingFee = BigDecimal.ZERO;
 
     //维修费用
+    @ApiModelProperty(value = "维修费用",required = true)
     private BigDecimal repairFee = BigDecimal.ZERO;
 
     //汇付手续费
+    @ApiModelProperty(value = "汇付手续费",required = true)
     private BigDecimal transferFee = BigDecimal.ZERO;
     
     //平台手续费
+    @ApiModelProperty(value = "平台手续费",required = true)
     private BigDecimal platformFee = BigDecimal.ZERO;
 
-    //乐团课程费用
+    //乐团家长采买课程费用
+    @ApiModelProperty(value = "乐团课程费用",required = true)
     private BigDecimal musicGroupCourseFee = BigDecimal.ZERO;
+
+    //乐团课程费用
+    @ApiModelProperty(value = "乐团学校采买课程费用",required = true)
+    private BigDecimal courseSchoolBuyAmount = BigDecimal.ZERO;
+
     //网络基础训练课程费用
+    @ApiModelProperty(value = "网络基础训练课程费用",required = true)
     private BigDecimal highCourseFee = BigDecimal.ZERO;
+
     //VIP课程费用
+    @ApiModelProperty(value = "VIP课程费用",required = true)
     private BigDecimal vipCourseFee = BigDecimal.ZERO;
+
     //网管课程费用
+    @ApiModelProperty(value = "网管课程费用",required = true)
     private BigDecimal practiceCourseFee = BigDecimal.ZERO;
+
     //乐理课程费用
+    @ApiModelProperty(value = "乐理课程费用",required = true)
     private BigDecimal theoryCourseFee = BigDecimal.ZERO;
+
     //考级费用
+    @ApiModelProperty(value = "考级费用",required = true)
     private BigDecimal degreeFee = BigDecimal.ZERO;
+
     //其它费用
+    @ApiModelProperty(value = "其它费用",required = true)
     private BigDecimal otherFee = BigDecimal.ZERO;
+
     //乐保费用
+    @ApiModelProperty(value = "乐保费用",required = true)
     private BigDecimal maintenanceFee = BigDecimal.ZERO;
+
+    @ApiModelProperty(value = "零售乐器费用",required = true)
+    private BigDecimal retailGoodsFee = BigDecimal.ZERO;
+
+    @ApiModelProperty(value = "大件乐器费用",required = true)
+    private BigDecimal largeMusicalFee = BigDecimal.ZERO;
+
     //商品乐保
+    @ApiModelProperty(value = "商品乐保",required = true)
     private BigDecimal maintenanceProductFee = BigDecimal.ZERO;
+
     //云教练费用
+    @ApiModelProperty(value = "云教练费用",required = true)
     private BigDecimal cloudTeacherFee = BigDecimal.ZERO;
+
     //上门费费用
+    @ApiModelProperty(value = "上门费费用",required = true)
     private BigDecimal visitFee = BigDecimal.ZERO;
+
     //账户充值
+    @ApiModelProperty(value = "账户充值",required = true)
     private BigDecimal rechargeFee = BigDecimal.ZERO;
 
-    private String organName;
-    private String schoolName;
+    @ApiModelProperty(value = "专业",required = true)
     private String subjectName;
+
+    @ApiModelProperty(value = "合作单位",required = true)
     private String cooperationOrganName;
+
     //乐团主管
+    @ApiModelProperty(value = "乐团主管",required = true)
     private String eduTeacher;
 
+    @ApiModelProperty(value = "收费类型",required = true)
     private Integer chargeType;
 
+    @ApiModelProperty(value = "订单详情",required = true)
     private List<StudentPaymentOrderDetail> orderDetailList;
 
+    @ApiModelProperty(value = "商品列表",required = true)
     private List<Goods> goodsList;
 
     //收款账户
+    @ApiModelProperty(value = "收款账户",required = true)
     private String routeMerNo;
 
     //分润金额
+    @ApiModelProperty(value = "分润金额",required = true)
     private BigDecimal routeAmount;
 
     //分润余额
+    @ApiModelProperty(value = "分润余额",required = true)
     private BigDecimal routeBalance;
 
     //分润中的销售费用
+    @ApiModelProperty(value = "分润中的销售费用",required = true)
     private BigDecimal saleAmount = BigDecimal.ZERO;
 
     //分润中的服务费用
+    @ApiModelProperty(value = "分润中的服务费用",required = true)
     private BigDecimal serviceAmount = BigDecimal.ZERO;
-    
+
+    @ApiModelProperty(value = "服务费",required = true)
     private BigDecimal serviceFee = BigDecimal.ZERO;
 
+    @ApiModelProperty(value = "分部",required = true)
     private String feeFlag;
 
+    @ApiModelProperty(value = "支付状态",required = true)
     private Integer payingStatus;
 
     //订单金额
+    @ApiModelProperty(value = "订单金额",required = true)
     private BigDecimal orderAmount = BigDecimal.ZERO;
 
     public enum TypeDesc implements BaseEnum<String, StudentPaymentOrderExportDto.TypeDesc> {
@@ -109,7 +160,16 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
         RENEW_VIP("RENEW_VIP", "VIP课续费"),
         NEW_MUSIC("NEW_MUSIC", "乐团新开"),
         ADD_MUSIC("ADD_MUSIC", "乐团扩招"),
-        RENEW_MUSIC("RENEW_MUSIC", "乐团续费");
+        RENEW_MUSIC("RENEW_MUSIC", "乐团续费"),
+        MUSIC_CONVERT("MUSIC_CONVERT", "乐团转化"),
+        NEW_PRACTICE("NEW_PRACTICE", "网管课新增"),
+        RENEW_PRACTICE("RENEW_PRACTICE", "网管课续费"),
+        DEGREE_REGISTRATION("DEGREE_REGISTRATION", "考级费用"),
+        REPAIR("REPAIR", "乐器维修"),
+        RETAIL_GOODS("RETAIL_GOODS", "零售乐器/辅件/乐保"),
+        COURSE_SCHOOL_BUY("COURSE_SCHOOL_BUY", "课程学校采买"),
+        COURSE_STUDENT_BUY("COURSE_STUDENT_BUY", "课程家长采买"),
+        LARGE_MUSICAL("LARGE_MUSICAL", "大件乐器");
 
         private String code;
 
@@ -133,14 +193,52 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
     //课程形态描述
     //学员没有历史VIP课程则导出为【VIP课新增】
     //学员有历史VIP课程到导出为【VIP课续费】……
+    @ApiModelProperty(value = "课程形态描述",required = true)
     private TypeDesc typeDesc;
 
     //该笔订单为乐团订单则导出该乐团的【乐团名称】
     //该笔订单非乐团订单时,查询学员是否有在读乐团,无则导出为空,有则导出该学员【进行中】【暂停】乐团名称,进行中>暂停,多个进行中则导出加入乐团时间最近的乐团名称
+    @ApiModelProperty(value = "所在乐团",required = true)
     private String feeMusicGroupId;
 
+    @ApiModelProperty(value = "所在乐团",required = true)
     private String feeMusicGroupName;
 
+    @ApiModelProperty(value = "教学点",required = true)
+    private String schoolName;
+
+    public BigDecimal getCourseSchoolBuyAmount() {
+        return courseSchoolBuyAmount;
+    }
+
+    public void setCourseSchoolBuyAmount(BigDecimal courseSchoolBuyAmount) {
+        this.courseSchoolBuyAmount = courseSchoolBuyAmount;
+    }
+
+    public BigDecimal getRetailGoodsFee() {
+        return retailGoodsFee;
+    }
+
+    public void setRetailGoodsFee(BigDecimal retailGoodsFee) {
+        this.retailGoodsFee = retailGoodsFee;
+    }
+
+    public BigDecimal getLargeMusicalFee() {
+        return largeMusicalFee;
+    }
+
+    public void setLargeMusicalFee(BigDecimal largeMusicalFee) {
+        this.largeMusicalFee = largeMusicalFee;
+    }
+
+    public String getSchoolName() {
+        return schoolName;
+    }
+
+    public void setSchoolName(String schoolName) {
+        this.schoolName = schoolName;
+    }
+
     public String getFeeMusicGroupName() {
         return feeMusicGroupName;
     }
@@ -221,14 +319,6 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
         this.organName = organName;
     }
 
-    public String getSchoolName() {
-        return schoolName;
-    }
-
-    public void setSchoolName(String schoolName) {
-        this.schoolName = schoolName;
-    }
-
     public String getSubjectName() {
         return subjectName;
     }
@@ -269,14 +359,6 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
         this.chargeType = chargeType;
     }
 
-    public BigDecimal getCourseFee() {
-        return courseFee;
-    }
-
-    public void setCourseFee(BigDecimal courseFee) {
-        this.courseFee = courseFee;
-    }
-
     public List<Goods> getGoodsList() {
         return goodsList;
     }
@@ -317,14 +399,6 @@ public class StudentPaymentOrderExportDto extends StudentPaymentOrder {
         this.routeBalance = routeBalance;
     }
 
-    public BigDecimal getHighOnlineCourseFee() {
-        return highOnlineCourseFee;
-    }
-
-    public void setHighOnlineCourseFee(BigDecimal highOnlineCourseFee) {
-        this.highOnlineCourseFee = highOnlineCourseFee;
-    }
-
     public BigDecimal getRepairFee() {
         return repairFee;
     }

+ 173 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentPaymentOrderSumExportDto.java

@@ -0,0 +1,173 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+import java.math.BigDecimal;
+
+public class StudentPaymentOrderSumExportDto {
+
+    @ApiModelProperty(value = "分部",required = true)
+    private String organName;
+
+    @ApiModelProperty(value = "vip新增金额",required = true)
+    private BigDecimal newVipAmount;
+
+    @ApiModelProperty(value = "vip续费金额",required = true)
+    private BigDecimal renewVipAmount;
+
+    @ApiModelProperty(value = "乐团新开",required = true)
+    private BigDecimal newMusicAmount;
+
+    @ApiModelProperty(value = "乐团扩招",required = true)
+    private BigDecimal addMusicAmount;
+
+    @ApiModelProperty(value = "乐团续费",required = true)
+    private BigDecimal renewMusicAmount;
+
+    @ApiModelProperty(value = "乐团转化",required = true)
+    private BigDecimal musicConvertAmount;
+
+    @ApiModelProperty(value = "网管课新增",required = true)
+    private BigDecimal newPracticeAmount;
+
+    @ApiModelProperty(value = "网管课续费",required = true)
+    private BigDecimal renewPracticeAmount;
+
+    @ApiModelProperty(value = "考级费用",required = true)
+    private BigDecimal degreeRegistrationAmount;
+
+    @ApiModelProperty(value = "乐器维修",required = true)
+    private BigDecimal repairAmount;
+
+    @ApiModelProperty(value = "零售乐器/辅件/乐保",required = true)
+    private BigDecimal retailGoodsAmount;
+
+    @ApiModelProperty(value = "大件乐器",required = true)
+    private BigDecimal largeMusialAmount;
+
+    @ApiModelProperty(value = "课程家长采买金额",required = true)
+    private BigDecimal courseStudentBuyAmount;
+
+    @ApiModelProperty(value = "课程学校采买金额",required = true)
+    private BigDecimal courseSchoolBuyAmount;
+
+    public String getOrganName() {
+        return organName;
+    }
+
+    public void setOrganName(String organName) {
+        this.organName = organName;
+    }
+
+    public BigDecimal getNewVipAmount() {
+        return newVipAmount;
+    }
+
+    public void setNewVipAmount(BigDecimal newVipAmount) {
+        this.newVipAmount = newVipAmount;
+    }
+
+    public BigDecimal getRenewVipAmount() {
+        return renewVipAmount;
+    }
+
+    public void setRenewVipAmount(BigDecimal renewVipAmount) {
+        this.renewVipAmount = renewVipAmount;
+    }
+
+    public BigDecimal getNewMusicAmount() {
+        return newMusicAmount;
+    }
+
+    public void setNewMusicAmount(BigDecimal newMusicAmount) {
+        this.newMusicAmount = newMusicAmount;
+    }
+
+    public BigDecimal getAddMusicAmount() {
+        return addMusicAmount;
+    }
+
+    public void setAddMusicAmount(BigDecimal addMusicAmount) {
+        this.addMusicAmount = addMusicAmount;
+    }
+
+    public BigDecimal getRenewMusicAmount() {
+        return renewMusicAmount;
+    }
+
+    public void setRenewMusicAmount(BigDecimal renewMusicAmount) {
+        this.renewMusicAmount = renewMusicAmount;
+    }
+
+    public BigDecimal getMusicConvertAmount() {
+        return musicConvertAmount;
+    }
+
+    public void setMusicConvertAmount(BigDecimal musicConvertAmount) {
+        this.musicConvertAmount = musicConvertAmount;
+    }
+
+    public BigDecimal getNewPracticeAmount() {
+        return newPracticeAmount;
+    }
+
+    public void setNewPracticeAmount(BigDecimal newPracticeAmount) {
+        this.newPracticeAmount = newPracticeAmount;
+    }
+
+    public BigDecimal getRenewPracticeAmount() {
+        return renewPracticeAmount;
+    }
+
+    public void setRenewPracticeAmount(BigDecimal renewPracticeAmount) {
+        this.renewPracticeAmount = renewPracticeAmount;
+    }
+
+    public BigDecimal getDegreeRegistrationAmount() {
+        return degreeRegistrationAmount;
+    }
+
+    public void setDegreeRegistrationAmount(BigDecimal degreeRegistrationAmount) {
+        this.degreeRegistrationAmount = degreeRegistrationAmount;
+    }
+
+    public BigDecimal getRepairAmount() {
+        return repairAmount;
+    }
+
+    public void setRepairAmount(BigDecimal repairAmount) {
+        this.repairAmount = repairAmount;
+    }
+
+    public BigDecimal getRetailGoodsAmount() {
+        return retailGoodsAmount;
+    }
+
+    public void setRetailGoodsAmount(BigDecimal retailGoodsAmount) {
+        this.retailGoodsAmount = retailGoodsAmount;
+    }
+
+    public BigDecimal getLargeMusialAmount() {
+        return largeMusialAmount;
+    }
+
+    public void setLargeMusialAmount(BigDecimal largeMusialAmount) {
+        this.largeMusialAmount = largeMusialAmount;
+    }
+
+    public BigDecimal getCourseStudentBuyAmount() {
+        return courseStudentBuyAmount;
+    }
+
+    public void setCourseStudentBuyAmount(BigDecimal courseStudentBuyAmount) {
+        this.courseStudentBuyAmount = courseStudentBuyAmount;
+    }
+
+    public BigDecimal getCourseSchoolBuyAmount() {
+        return courseSchoolBuyAmount;
+    }
+
+    public void setCourseSchoolBuyAmount(BigDecimal courseSchoolBuyAmount) {
+        this.courseSchoolBuyAmount = courseSchoolBuyAmount;
+    }
+}

+ 16 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsDto.java

@@ -0,0 +1,16 @@
+package com.ym.mec.biz.dal.dto;
+
+import com.ym.mec.biz.dal.entity.StudentBasicInfo;
+import com.ym.mec.biz.dal.entity.StudentStatistics;
+
+public class StudentStatisticsDto extends StudentStatistics {
+    private StudentBasicInfo studentBasicInfo;
+
+    public StudentBasicInfo getStudentBasicInfo() {
+        return studentBasicInfo;
+    }
+
+    public void setStudentBasicInfo(StudentBasicInfo studentBasicInfo) {
+        this.studentBasicInfo = studentBasicInfo;
+    }
+}

+ 116 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsSumDto.java

@@ -0,0 +1,116 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class StudentStatisticsSumDto {
+
+    @ApiModelProperty(value = "沉睡学员总数:有课耗且有【未开始】课程的学生中,近一年无课耗学生总数",required = false)
+    private Integer sleepStudentNum;
+
+    @ApiModelProperty(value = "有未排课:沉睡学员中,有未排课资格的学数量",required = false)
+    private Integer sleepStudentHasNotSchedule;
+
+    @ApiModelProperty(value = "无未排课:沉睡学员中,无未排课资格的学数量",required = false)
+    private Integer sleepStudentNoNotSchedule;
+
+    @ApiModelProperty(value = "在读学员总数:有【未开始】+【未排课】+ 近一年有课耗学生总数",required = false)
+    private Integer normalStudentNum;
+
+    @ApiModelProperty(value = "进行中:【在读学员总数】中有【进行中】状态课程组的学生数量",required = false)
+    private Integer normalStudentHasNormalGroupNum;
+
+    @ApiModelProperty(value = "暂停:有课程余额且没有剩余课时",required = false)
+    private Integer hasCourseBalanceAndNotSubCourseNum;
+
+    @ApiModelProperty(value = "未排课:【在读学员总数】中有未排课资格的学员数量",required = false)
+    private Integer normalStudentHasNoScheduleNum;
+
+    @ApiModelProperty(value = "待续费人数:【未开始】+【未排课】课时数≤3节",required = false)
+    private Integer waitRenewNum;
+
+    @ApiModelProperty(value = "未开始课时:【未开始】课程总数",required = false)
+    private Integer subCourseNum;
+
+    @ApiModelProperty(value = "未排课课时:活动资格【未排课】课程总数(1v多不去重)",required = false)
+    private Integer noScheduleNum;
+
+    public Integer getSleepStudentNum() {
+        return sleepStudentNum;
+    }
+
+    public void setSleepStudentNum(Integer sleepStudentNum) {
+        this.sleepStudentNum = sleepStudentNum;
+    }
+
+    public Integer getSleepStudentHasNotSchedule() {
+        return sleepStudentHasNotSchedule;
+    }
+
+    public void setSleepStudentHasNotSchedule(Integer sleepStudentHasNotSchedule) {
+        this.sleepStudentHasNotSchedule = sleepStudentHasNotSchedule;
+    }
+
+    public Integer getSleepStudentNoNotSchedule() {
+        return sleepStudentNoNotSchedule;
+    }
+
+    public void setSleepStudentNoNotSchedule(Integer sleepStudentNoNotSchedule) {
+        this.sleepStudentNoNotSchedule = sleepStudentNoNotSchedule;
+    }
+
+    public Integer getNormalStudentNum() {
+        return normalStudentNum;
+    }
+
+    public void setNormalStudentNum(Integer normalStudentNum) {
+        this.normalStudentNum = normalStudentNum;
+    }
+
+    public Integer getNormalStudentHasNormalGroupNum() {
+        return normalStudentHasNormalGroupNum;
+    }
+
+    public void setNormalStudentHasNormalGroupNum(Integer normalStudentHasNormalGroupNum) {
+        this.normalStudentHasNormalGroupNum = normalStudentHasNormalGroupNum;
+    }
+
+    public Integer getHasCourseBalanceAndNotSubCourseNum() {
+        return hasCourseBalanceAndNotSubCourseNum;
+    }
+
+    public void setHasCourseBalanceAndNotSubCourseNum(Integer hasCourseBalanceAndNotSubCourseNum) {
+        this.hasCourseBalanceAndNotSubCourseNum = hasCourseBalanceAndNotSubCourseNum;
+    }
+
+    public Integer getNormalStudentHasNoScheduleNum() {
+        return normalStudentHasNoScheduleNum;
+    }
+
+    public void setNormalStudentHasNoScheduleNum(Integer normalStudentHasNoScheduleNum) {
+        this.normalStudentHasNoScheduleNum = normalStudentHasNoScheduleNum;
+    }
+
+    public Integer getWaitRenewNum() {
+        return waitRenewNum;
+    }
+
+    public void setWaitRenewNum(Integer waitRenewNum) {
+        this.waitRenewNum = waitRenewNum;
+    }
+
+    public Integer getSubCourseNum() {
+        return subCourseNum;
+    }
+
+    public void setSubCourseNum(Integer subCourseNum) {
+        this.subCourseNum = subCourseNum;
+    }
+
+    public Integer getNoScheduleNum() {
+        return noScheduleNum;
+    }
+
+    public void setNoScheduleNum(Integer noScheduleNum) {
+        this.noScheduleNum = noScheduleNum;
+    }
+}

+ 49 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/StudentStatisticsSumForDateDto.java

@@ -0,0 +1,49 @@
+package com.ym.mec.biz.dal.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class StudentStatisticsSumForDateDto {
+    @ApiModelProperty(value = "流失人数",required = false)
+    private Integer lostNum;
+
+    @ApiModelProperty(value = "新增人数:以前没课,所选时间段内新增课程或排课资格的学员",required = false)
+    private Integer addNum;
+
+    @ApiModelProperty(value = "续费人数:所选结束时间之前有多笔大于0元的付费订单(活动赠送不算)",required = false)
+    private Integer renewNum;
+
+    @ApiModelProperty(value = "回访人数",required = false)
+    private Integer visitNum;
+
+    public Integer getLostNum() {
+        return lostNum;
+    }
+
+    public void setLostNum(Integer lostNum) {
+        this.lostNum = lostNum;
+    }
+
+    public Integer getAddNum() {
+        return addNum;
+    }
+
+    public void setAddNum(Integer addNum) {
+        this.addNum = addNum;
+    }
+
+    public Integer getRenewNum() {
+        return renewNum;
+    }
+
+    public void setRenewNum(Integer renewNum) {
+        this.renewNum = renewNum;
+    }
+
+    public Integer getVisitNum() {
+        return visitNum;
+    }
+
+    public void setVisitNum(Integer visitNum) {
+        this.visitNum = visitNum;
+    }
+}

+ 29 - 6
mec-biz/src/main/java/com/ym/mec/biz/dal/dto/TeacherServeDto.java

@@ -24,8 +24,12 @@ public class TeacherServeDto {
 
     private String organName;
 
+    @ApiModelProperty(value = "作业次数(节)", required = false)
     private int homeworkNum;
 
+    @ApiModelProperty(value = "作业次数(人)", required = false)
+    private int homeworkStuNum;
+
     private int exerciseNum;
 
     private int unDone;
@@ -38,10 +42,10 @@ public class TeacherServeDto {
     private JobNatureEnum jobNature;
 
     /** 预期训练次数 */
-    private Integer expectExercisesNum;
+    private int expectExercisesNum;
 
     /** 实际训练次数 */
-    private Integer actualExercisesNum;
+    private int actualExercisesNum;
 
     /** 提交训练次数 */
     private Integer exercisesReplyNum;
@@ -55,9 +59,28 @@ public class TeacherServeDto {
     /** 点评率 */
     private String exercisesMessageRate;
 
+    /** 及时评价率 */
+    private String exercisesMessageTimelyRate;
+
     @ApiModelProperty(value = "提交率")
     private String submitRate;
 
+    public String getExercisesMessageTimelyRate() {
+        return exercisesMessageTimelyRate;
+    }
+
+    public void setExercisesMessageTimelyRate(String exercisesMessageTimelyRate) {
+        this.exercisesMessageTimelyRate = exercisesMessageTimelyRate;
+    }
+
+    public int getHomeworkStuNum() {
+        return homeworkStuNum;
+    }
+
+    public void setHomeworkStuNum(int homeworkStuNum) {
+        this.homeworkStuNum = homeworkStuNum;
+    }
+
     public String getExercisesMessageRate() {
         return exercisesMessageRate;
     }
@@ -74,19 +97,19 @@ public class TeacherServeDto {
         this.submitRate = submitRate;
     }
 
-    public Integer getExpectExercisesNum() {
+    public int getExpectExercisesNum() {
         return expectExercisesNum;
     }
 
-    public void setExpectExercisesNum(Integer expectExercisesNum) {
+    public void setExpectExercisesNum(int expectExercisesNum) {
         this.expectExercisesNum = expectExercisesNum;
     }
 
-    public Integer getActualExercisesNum() {
+    public int getActualExercisesNum() {
         return actualExercisesNum;
     }
 
-    public void setActualExercisesNum(Integer actualExercisesNum) {
+    public void setActualExercisesNum(int actualExercisesNum) {
         this.actualExercisesNum = actualExercisesNum;
     }
 

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/ManagerDownload.java

@@ -40,7 +40,7 @@ public class ManagerDownload extends BaseEntity {
     /**
      * 状态
      */
-    @ApiModelProperty(value = "状态")
+    @ApiModelProperty(value = "状态0下载中、1成功、2失败")
     private Integer status=0;
 
     /**

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/MusicGroup.java

@@ -8,6 +8,7 @@ import java.util.Date;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 
 import com.ym.mec.biz.dal.entity.CooperationOrgan.OwnershipType;
+import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
 import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
 import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
 import com.ym.mec.biz.dal.enums.SalarySettlementTypeEnum;
@@ -202,6 +203,8 @@ public class MusicGroup extends BaseEntity {
 	
 	@ApiModelProperty(value = "是否赠送辅件",required = false)
 	private Boolean isGiveAccessories;
+	
+	private ClassGroupTypeEnum extracurricularTeacher;
 
 	public Integer getHasInstrumentNum() {
 		return hasInstrumentNum;
@@ -700,4 +703,12 @@ public class MusicGroup extends BaseEntity {
 	public void setIsGiveAccessories(Boolean isGiveAccessories) {
 		this.isGiveAccessories = isGiveAccessories;
 	}
+
+	public ClassGroupTypeEnum getExtracurricularTeacher() {
+		return extracurricularTeacher;
+	}
+
+	public void setExtracurricularTeacher(ClassGroupTypeEnum extracurricularTeacher) {
+		this.extracurricularTeacher = extracurricularTeacher;
+	}
 }

+ 184 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentBasicInfo.java

@@ -0,0 +1,184 @@
+package com.ym.mec.biz.dal.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import java.math.BigDecimal;
+
+/**
+ * 对应数据库表(student_basic_info):
+ */
+public class StudentBasicInfo {
+
+	/** 学员编号 */
+	@ApiModelProperty(value = "学员编号",required = false)
+	private Integer userId;
+	
+	/** 学员姓名 */
+	@ApiModelProperty(value = "学员姓名",required = false)
+	private String userName;
+	
+	/** 手机号 */
+	@ApiModelProperty(value = "手机号",required = false)
+	private String phone;
+	
+	/** 声部编号 */
+	@ApiModelProperty(value = "声部编号",required = false)
+	private Integer subjectId;
+	
+	/** 声部 */
+	@ApiModelProperty(value = "声部",required = false)
+	private String subjectName;
+	
+	/** 年级 */
+	@ApiModelProperty(value = "年级",required = false)
+	private String grade;
+	
+	/** 分部编号 */
+	@ApiModelProperty(value = "分部编号",required = false)
+	private Integer organId;
+	
+	/** 分部名称 */
+	@ApiModelProperty(value = "分部名称",required = false)
+	private String organName;
+	
+	/** 学校编号 */
+	@ApiModelProperty(value = "学校编号",required = false)
+	private Integer cooperationOrganId;
+	
+	/** 学校名称 */
+	@ApiModelProperty(value = "学校名称",required = false)
+	private String cooperationOrganName;
+	
+	/** 声部课老师(学员所在乐团声部班老师,如果有多个,取id最大的) */
+	@ApiModelProperty(value = "声部课老师",required = false)
+	private Integer subjectTeacherId;
+	
+	/** 声部课老师(学员所在乐团声部班老师) */
+	@ApiModelProperty(value = "声部课老师",required = false)
+	private String subjectTeacherName;
+
+	@ApiModelProperty(value = "课程余额",required = false)
+	private BigDecimal courseBalance = BigDecimal.ZERO;
+
+	@ApiModelProperty(value = "学员状态",required = false)
+	private String studentStatus;
+
+	public String getStudentStatus() {
+		return studentStatus;
+	}
+
+	public void setStudentStatus(String studentStatus) {
+		this.studentStatus = studentStatus;
+	}
+
+	public BigDecimal getCourseBalance() {
+		return courseBalance;
+	}
+
+	public void setCourseBalance(BigDecimal courseBalance) {
+		this.courseBalance = courseBalance;
+	}
+
+	public void setUserId(Integer userId){
+		this.userId = userId;
+	}
+	
+	public Integer getUserId(){
+		return this.userId;
+	}
+			
+	public void setUserName(String userName){
+		this.userName = userName;
+	}
+	
+	public String getUserName(){
+		return this.userName;
+	}
+			
+	public void setPhone(String phone){
+		this.phone = phone;
+	}
+	
+	public String getPhone(){
+		return this.phone;
+	}
+			
+	public void setSubjectId(Integer subjectId){
+		this.subjectId = subjectId;
+	}
+	
+	public Integer getSubjectId(){
+		return this.subjectId;
+	}
+			
+	public void setSubjectName(String subjectName){
+		this.subjectName = subjectName;
+	}
+	
+	public String getSubjectName(){
+		return this.subjectName;
+	}
+			
+	public void setGrade(String grade){
+		this.grade = grade;
+	}
+	
+	public String getGrade(){
+		return this.grade;
+	}
+			
+	public void setOrganId(Integer organId){
+		this.organId = organId;
+	}
+	
+	public Integer getOrganId(){
+		return this.organId;
+	}
+			
+	public void setOrganName(String organName){
+		this.organName = organName;
+	}
+	
+	public String getOrganName(){
+		return this.organName;
+	}
+			
+	public void setCooperationOrganId(Integer cooperationOrganId){
+		this.cooperationOrganId = cooperationOrganId;
+	}
+	
+	public Integer getCooperationOrganId(){
+		return this.cooperationOrganId;
+	}
+			
+	public void setCooperationOrganName(String cooperationOrganName){
+		this.cooperationOrganName = cooperationOrganName;
+	}
+	
+	public String getCooperationOrganName(){
+		return this.cooperationOrganName;
+	}
+			
+	public void setSubjectTeacherId(Integer subjectTeacherId){
+		this.subjectTeacherId = subjectTeacherId;
+	}
+	
+	public Integer getSubjectTeacherId(){
+		return this.subjectTeacherId;
+	}
+			
+	public void setSubjectTeacherName(String subjectTeacherName){
+		this.subjectTeacherName = subjectTeacherName;
+	}
+	
+	public String getSubjectTeacherName(){
+		return this.subjectTeacherName;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 28 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentExtracurricularExercisesSituation.java

@@ -228,6 +228,34 @@ public class StudentExtracurricularExercisesSituation extends BaseEntity {
 	}
 
 	@Override
+	public int hashCode() {
+		Object[] objs = { monday, studentId, teacherId, serveType };
+		int result = 1;
+		for (Object obj : objs) {
+			if(obj == null){
+				continue;
+			}
+			result = 31 * result + obj.hashCode();
+		}
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+
+		if (obj instanceof StudentExtracurricularExercisesSituation) {
+
+			StudentExtracurricularExercisesSituation dto = (StudentExtracurricularExercisesSituation) obj;
+
+			if (this.monday.equals(dto.getMonday()) && this.studentId.intValue() == dto.getStudentId() && this.teacherId.intValue() == dto.getTeacherId()
+					&& this.serveType.equals(dto.getServeType())) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	@Override
 	public String toString() {
 		return ToStringBuilder.reflectionToString(this);
 	}

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentPaymentRouteOrder.java

@@ -6,6 +6,7 @@ import java.util.Date;
 import com.alibaba.fastjson.JSONObject;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.enums.AuditStatusEnum;
+import com.ym.mec.biz.dal.enums.OrderTypeEnum;
 import com.ym.mec.common.entity.BaseEntity;
 
 import static com.ym.mec.biz.dal.enums.AuditStatusEnum.ING;
@@ -92,6 +93,16 @@ public class StudentPaymentRouteOrder extends BaseEntity {
     
     private Organization organ = new Organization();
 
+    private OrderTypeEnum type;
+
+	public OrderTypeEnum getType() {
+		return type;
+	}
+
+	public void setType(OrderTypeEnum type) {
+		this.type = type;
+	}
+
 	public String getIncomeType() {
 		return incomeType;
 	}

+ 311 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentStatistics.java

@@ -0,0 +1,311 @@
+package com.ym.mec.biz.dal.entity;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+import java.math.BigDecimal;
+
+/**
+ * 对应数据库表(student_statistics):
+ */
+public class StudentStatistics {
+
+	@ApiModelProperty(value = "主键",required = false)
+	private Integer id;
+	
+	@ApiModelProperty(value = "学员编号",required = false)
+	private Integer userId;
+	
+	@ApiModelProperty(value = "指导老师编号(最近一节已结束课程上的老师)",required = false)
+	private Integer teacherId;
+	
+	@ApiModelProperty(value = "指导老师",required = false)
+	private String teacherName;
+	
+	/** 乐团主管(最近一节已结束课程的课程组老师) */
+	@ApiModelProperty(value = "乐团主管",required = false)
+	private Integer musicDirectorId;
+
+	@ApiModelProperty(value = "乐团主管",required = false)
+	/** 乐团主管(最近一节已结束课程的课程组老师) */
+	private String musicDirectorName;
+
+	@ApiModelProperty(value = "总课时",required = false)
+	/** 总课时(课时总数) */
+	private Integer totalCourseNum;
+
+	@ApiModelProperty(value = "已完成课时",required = false)
+	/** 已完成课时(已结束课时数) */
+	private Integer overCourseNum;
+
+	@ApiModelProperty(value = "剩余课时",required = false)
+	/** 剩余课时(未开始课时数) */
+	private Integer subCourseNum;
+
+	@ApiModelProperty(value = "未排课时",required = false)
+	/** 未排课时(未排课时总数) */
+	private Integer noScheduleNum;
+
+	@ApiModelProperty(value = "第一次课时间",required = false)
+	/** 第一次课时间 */
+	private String firstCourseTime;
+
+	@ApiModelProperty(value = "最近一次上课时间",required = false)
+	/** 最近一次上课时间 */
+	private String lastCourseTime;
+
+	@ApiModelProperty(value = "最近30天课耗",required = false)
+	/** 最近30天课耗(已结束的课程数量) */
+	private Integer latelyCourseConsumer;
+
+	@ApiModelProperty(value = "最近1年课耗",required = false)
+	/** 最近1年课耗(已结束的课程数量) */
+	private Integer latelyYearCourseConsumer;
+
+	@ApiModelProperty(value = "回访次数",required = false)
+	/** 回访次数 */
+	private Integer visitNum;
+
+	@ApiModelProperty(value = "最近一次回访状态",required = false)
+	/** 最近一次回访状态 */
+	private String lastVisitStatus;
+
+	@ApiModelProperty(value = "最近一次回访原因",required = false)
+	/** 最近一次回访原因 */
+	private String visitReason;
+
+	@ApiModelProperty(value = "最近一次回访时间",required = false)
+	/** 最近一次回访时间 */
+	private String lastVisitTime;
+
+	@ApiModelProperty(value = "预收款(未开始课程价值总和)",required = false)
+	/** 预收款(未开始课程价值总和) */
+	private java.math.BigDecimal notStartCourseFee;
+
+	@ApiModelProperty(value = "预收款(未排课 价值总和)",required = false)
+	/** 预收款(未排课 价值总和) */
+	private java.math.BigDecimal noCourseFee;
+
+	@ApiModelProperty(value = "预收款(总金额)",required = false)
+	/** 预收款(总金额) */
+	private java.math.BigDecimal preCourseFee;
+
+	@ApiModelProperty(value = "首次付费订单时间",required = false)
+	/** 首次付费订单时间 */
+	private String firstOrderTime;
+
+	@ApiModelProperty(value = "最近一次付费订单时间",required = false)
+	private String lastOrderTime;
+
+	@ApiModelProperty(value = "付费订单总数",required = false)
+	private Integer orderNum;
+
+	@ApiModelProperty(value = "课程组类型(VIP,THEORY,PRACTICE)",required = false)
+	private String groupType;
+
+	public BigDecimal getPreCourseFee() {
+		return preCourseFee;
+	}
+
+	public void setPreCourseFee(BigDecimal preCourseFee) {
+		this.preCourseFee = preCourseFee;
+	}
+
+	public Integer getLatelyYearCourseConsumer() {
+		return latelyYearCourseConsumer;
+	}
+
+	public void setLatelyYearCourseConsumer(Integer latelyYearCourseConsumer) {
+		this.latelyYearCourseConsumer = latelyYearCourseConsumer;
+	}
+
+	public void setId(Integer id){
+		this.id = id;
+	}
+	
+	public Integer getId(){
+		return this.id;
+	}
+			
+	public void setUserId(Integer userId){
+		this.userId = userId;
+	}
+	
+	public Integer getUserId(){
+		return this.userId;
+	}
+			
+	public void setTeacherId(Integer teacherId){
+		this.teacherId = teacherId;
+	}
+	
+	public Integer getTeacherId(){
+		return this.teacherId;
+	}
+			
+	public void setTeacherName(String teacherName){
+		this.teacherName = teacherName;
+	}
+	
+	public String getTeacherName(){
+		return this.teacherName;
+	}
+			
+	public void setMusicDirectorId(Integer musicDirectorId){
+		this.musicDirectorId = musicDirectorId;
+	}
+	
+	public Integer getMusicDirectorId(){
+		return this.musicDirectorId;
+	}
+			
+	public void setMusicDirectorName(String musicDirectorName){
+		this.musicDirectorName = musicDirectorName;
+	}
+	
+	public String getMusicDirectorName(){
+		return this.musicDirectorName;
+	}
+			
+	public void setTotalCourseNum(Integer totalCourseNum){
+		this.totalCourseNum = totalCourseNum;
+	}
+	
+	public Integer getTotalCourseNum(){
+		return this.totalCourseNum;
+	}
+			
+	public void setOverCourseNum(Integer overCourseNum){
+		this.overCourseNum = overCourseNum;
+	}
+	
+	public Integer getOverCourseNum(){
+		return this.overCourseNum;
+	}
+			
+	public void setSubCourseNum(Integer subCourseNum){
+		this.subCourseNum = subCourseNum;
+	}
+	
+	public Integer getSubCourseNum(){
+		return this.subCourseNum;
+	}
+			
+	public void setNoScheduleNum(Integer noScheduleNum){
+		this.noScheduleNum = noScheduleNum;
+	}
+	
+	public Integer getNoScheduleNum(){
+		return this.noScheduleNum;
+	}
+			
+	public void setFirstCourseTime(String firstCourseTime){
+		this.firstCourseTime = firstCourseTime;
+	}
+	
+	public String getFirstCourseTime(){
+		return this.firstCourseTime;
+	}
+			
+	public void setLastCourseTime(String lastCourseTime){
+		this.lastCourseTime = lastCourseTime;
+	}
+	
+	public String getLastCourseTime(){
+		return this.lastCourseTime;
+	}
+			
+	public void setLatelyCourseConsumer(Integer latelyCourseConsumer){
+		this.latelyCourseConsumer = latelyCourseConsumer;
+	}
+	
+	public Integer getLatelyCourseConsumer(){
+		return this.latelyCourseConsumer;
+	}
+			
+	public void setVisitNum(Integer visitNum){
+		this.visitNum = visitNum;
+	}
+	
+	public Integer getVisitNum(){
+		return this.visitNum;
+	}
+			
+	public void setLastVisitStatus(String lastVisitStatus){
+		this.lastVisitStatus = lastVisitStatus;
+	}
+	
+	public String getLastVisitStatus(){
+		return this.lastVisitStatus;
+	}
+			
+	public void setVisitReason(String visitReason){
+		this.visitReason = visitReason;
+	}
+	
+	public String getVisitReason(){
+		return this.visitReason;
+	}
+			
+	public void setLastVisitTime(String lastVisitTime){
+		this.lastVisitTime = lastVisitTime;
+	}
+	
+	public String getLastVisitTime(){
+		return this.lastVisitTime;
+	}
+
+	public BigDecimal getNotStartCourseFee() {
+		return notStartCourseFee;
+	}
+
+	public void setNotStartCourseFee(BigDecimal notStartCourseFee) {
+		this.notStartCourseFee = notStartCourseFee;
+	}
+
+	public BigDecimal getNoCourseFee() {
+		return noCourseFee;
+	}
+
+	public void setNoCourseFee(BigDecimal noCourseFee) {
+		this.noCourseFee = noCourseFee;
+	}
+
+	public void setFirstOrderTime(String firstOrderTime){
+		this.firstOrderTime = firstOrderTime;
+	}
+	
+	public String getFirstOrderTime(){
+		return this.firstOrderTime;
+	}
+			
+	public void setLastOrderTime(String lastOrderTime){
+		this.lastOrderTime = lastOrderTime;
+	}
+	
+	public String getLastOrderTime(){
+		return this.lastOrderTime;
+	}
+			
+	public void setOrderNum(Integer orderNum){
+		this.orderNum = orderNum;
+	}
+	
+	public Integer getOrderNum(){
+		return this.orderNum;
+	}
+			
+	public void setGroupType(String groupType){
+		this.groupType = groupType;
+	}
+	
+	public String getGroupType(){
+		return this.groupType;
+	}
+			
+	@Override
+	public String toString() {
+		return ToStringBuilder.reflectionToString(this);
+	}
+
+}

+ 46 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/entity/StudentVisit.java

@@ -43,6 +43,38 @@ public class StudentVisit extends BaseEntity {
         }
     }
 
+    public enum FeedbackTypeEnum implements BaseEnum<String,FeedbackTypeEnum> {
+        THINKING("THINKING", "考虑中"), PENDING_PAYMENT("PENDING_PAYMENT", "确认缴费待缴费"),
+        LOST("LOST", "流失"), PAUSE("PAUSE", "暂停"),
+        OTHER("OTHER", "其他");
+
+        private String code;
+
+        private String msg;
+
+        FeedbackTypeEnum(String code, String msg) {
+            this.code = code;
+            this.msg = msg;
+        }
+
+        public void setCode(String code) {
+            this.code = code;
+        }
+
+        public String getMsg() {
+            return msg;
+        }
+
+        public void setMsg(String msg) {
+            this.msg = msg;
+        }
+
+        @Override
+        public String getCode() {
+            return this.code;
+        }
+    }
+
     private Integer id;
 
     /**
@@ -97,6 +129,12 @@ public class StudentVisit extends BaseEntity {
     private String overview;
 
     /**
+     * 家长反馈类型
+     */
+    @ApiModelProperty(value = "家长反馈", required = true)
+    private FeedbackTypeEnum feedbackType;
+
+    /**
      * 家长反馈
      */
     @ApiModelProperty(value = "家长反馈", required = true)
@@ -116,6 +154,14 @@ public class StudentVisit extends BaseEntity {
 
     private Long objectId;
 
+    public FeedbackTypeEnum getFeedbackType() {
+        return feedbackType;
+    }
+
+    public void setFeedbackType(FeedbackTypeEnum feedbackType) {
+        this.feedbackType = feedbackType;
+    }
+
     public Integer getId() {
         return id;
     }

+ 1 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ExportEnum.java

@@ -33,6 +33,7 @@ public enum ExportEnum implements BaseEnum<String, ExportEnum> {
     COURSE_SCHEDULE_TEACHER_SALARY("COURSE_SCHEDULE_TEACHER_SALARY", "分页导出教师薪酬列表"),
     ORDER_LIST1("ORDER_LIST1", "订单列表导出1"),
     ORDER_LIST2("ORDER_LIST2", "订单列表导出2"),
+    ORDER_LIST_SUM("ORDER_LIST_SUM", "订单列表汇总导出"),
     STUDENT_VIP_PRACTICE("STUDENT_VIP_PRACTICE", "学员小课记录导出"),
     MUSIC_GROUP_STUDENT("MUSIC_GROUP_STUDENT", "乐团导出学员列表"),
     COURSE_REVIEWS("COURSE_REVIEWS", "评论列表导出"),

+ 3 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/ExportTypeEnum.java

@@ -9,7 +9,9 @@ public enum ExportTypeEnum implements BaseEnum<Integer, ExportTypeEnum> {
 	STUDENT_VIP_PRACTICE(3, "VIP网管课耗导出"),
 	STUDENT_MUSIC_THEORY_COURSE_INFO(4, "网管课学员课程信息导出"),
 	STUDENT_VIP_COURSE_INFO(5, "VIP课学员课程信息导出"),
-	VIP_STUDENT_COURSE_MANAGE(6, "vip学员课程管理");
+	VIP_STUDENT_COURSE_MANAGE(6, "vip学员课程管理"),
+	STUDENT_SMALL_CLASS_STATISTICS(7, "学员小课数据统计"),
+	ORDER_LIST_SUM(8, "订单汇总");
 
 	private Integer code;
 

+ 9 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/FivePlusGradeEnum.java

@@ -33,5 +33,14 @@ public enum FivePlusGradeEnum implements BaseEnum<Integer, FivePlusGradeEnum> {
 	public String getDesc() {
 		return desc;
 	}
+	
+	public static FivePlusGradeEnum get(String desc) {
+		for (FivePlusGradeEnum vpg : FivePlusGradeEnum.values()) {
+			if (vpg.getDesc().equals(desc)) {
+				return vpg;
+			}
+		}
+		return null;
+	}
 
 }

+ 5 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/IndexDataType.java

@@ -1,6 +1,5 @@
 package com.ym.mec.biz.dal.enums;
 
-import com.sun.org.apache.xpath.internal.operations.Bool;
 import com.ym.mec.common.enums.BaseEnum;
 
 /**
@@ -83,6 +82,11 @@ public enum IndexDataType implements BaseEnum<String, IndexDataType> {
 
     CLOUD_STUDY_TRAIN_NUM("CLOUD_STUDY_TRAIN_NUM", "团练宝训练次数", false, false),
     CLOUD_STUDY_TRAIN_TIME("CLOUD_STUDY_TRAIN_TIME", "团练宝训练时长", false, false),
+
+    //小课数据统计
+    STUDENT_VIP_ORDER_NUM("STUDENT_VIP_ORDER_NUM", "学员vip课订单数量", false, false),
+    STUDENT_THEORY_ORDER_NUM("STUDENT_THEORY_ORDER_NUM", "学员乐理课订单数量", false, false),
+    STUDENT_PRACTICE_ORDER_NUM("STUDENT_PRACTICE_ORDER_NUM", "学员网管课订单数量", false, false),
     ;
 
     private String code;

+ 5 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/OrderTypeEnum.java

@@ -15,14 +15,19 @@ public enum OrderTypeEnum implements BaseEnum<String, OrderTypeEnum> {
     PRACTICE_GROUP_BUY("PRACTICE_GROUP_BUY", "网管课报名"),
     PRACTICE_GROUP_RENEW("PRACTICE_GROUP_RENEW", "网管课续费"),
     COURSE_GROUP_BUY("COURSE_GROUP_BUY", "课程购买"),
+    //余额充值活动
     LUCK("LUCK", "福袋活动"),
     DOUBLE_ELEVEN2020("DOUBLE_ELEVEN2020", "2020双十一活动"),
     DOUBLE_ELEVEN2021("DOUBLE_ELEVEN2021", "2021双十一活动"),
     TENANT_RECHARGE("TENANT_RECHARGE", "账户充值"),
     GOODS_SELL("GOODS_SELL", "商品购买"),
     OUTORDER("OUTORDER", "导入订单"),
+    //细分对外订单
+    SCHOOL("SCHOOL", "学校订单"),
+    PERSONAL("PERSONAL", "个人订单"),
     REPAIR("REPAIR", "乐器维修"),
     SUBJECT_CHANGE("SUBJECT_CHANGE", "声部更换"),
+    //包含考级费用和乐理课费用,乐理课的费用在detail里面,对于的订单类型是 DEGREE_REGISTRATION
     DEGREE_REGISTRATION("DEGREE_REGISTRATION", "考级报名"),
     MAINTENANCE("MAINTENANCE", "乐器保养"),
     REPLACEMENT("REPLACEMENT", "乐器置换"),

+ 9 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/SixPlusGradeEnum.java

@@ -33,5 +33,14 @@ public enum SixPlusGradeEnum implements BaseEnum<Integer, SixPlusGradeEnum> {
 	public String getDesc() {
 		return desc;
 	}
+	
+	public static SixPlusGradeEnum get(String desc) {
+		for (SixPlusGradeEnum vpg : SixPlusGradeEnum.values()) {
+			if (vpg.getDesc().equals(desc)) {
+				return vpg;
+			}
+		}
+		return null;
+	}
 
 }

+ 2 - 1
mec-biz/src/main/java/com/ym/mec/biz/dal/enums/TemplateTypeEnum.java

@@ -7,7 +7,8 @@ public enum TemplateTypeEnum implements BaseEnum<String, TemplateTypeEnum> {
     ROUTE_ORDER("ROUTE_ORDER","财务管理导入模板"),
     FINANCIAL_EXPENDITURE("FINANCIAL_EXPENDITURE","财务支出导入模板"),
     REDEMPTIONCODE("REDEMPTION_CODE", "兑换码分配模板表"),
-    OA_QUIT_MUSIC_GROUP("OA_QUIT_MUSIC_GROUP", "乐团退费模板");
+    OA_QUIT_MUSIC_GROUP("OA_QUIT_MUSIC_GROUP", "乐团退费模板"),
+    EXTERNAL_STUDENT_IMPORT_MUSIC_GROUP("EXTERNAL_STUDENT_IMPORT_MUSIC_GROUP", "外部学生入团导入模板");
 
     private String code;
 

+ 12 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentExercisesSituationQueryInfo.java

@@ -13,6 +13,8 @@ public class StudentExercisesSituationQueryInfo extends QueryInfo {
 
     private String organId;
 
+    private String organIdList;
+
     @ApiModelProperty(value = "周一日期")
     private java.util.Date monday;
 
@@ -51,6 +53,15 @@ public class StudentExercisesSituationQueryInfo extends QueryInfo {
     @ApiModelProperty(value = "服务是否异常")
     private Boolean serviceIsError;
 
+    public String getOrganIdList() {
+        return organIdList;
+    }
+
+    public void setOrganIdList(String organIdList) {
+        this.organIdList = organIdList;
+        this.organId = organIdList;
+    }
+
     public Boolean getServiceIsError() {
         return serviceIsError;
     }
@@ -104,6 +115,7 @@ public class StudentExercisesSituationQueryInfo extends QueryInfo {
     }
 
     public void setOrganId(String organId) {
+        this.organIdList = organIdList;
         this.organId = organId;
     }
 

+ 165 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentStatisticsQueryInfo.java

@@ -0,0 +1,165 @@
+package com.ym.mec.biz.dal.page;
+
+import com.ym.mec.common.page.QueryInfo;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+* @author zx
+* @date 2021/9/26 15:52
+*/
+public class StudentStatisticsQueryInfo extends QueryInfo {
+
+    @ApiModelProperty(value = "小课类型 VIP、PRACTICE、THEORY 默认VIP",required = true)
+    private String groupType = "VIP";
+
+    @ApiModelProperty(value = "声部编号",required = false)
+    private Integer subjectId;
+
+    @ApiModelProperty(value = "学员状态,在读(NORMAL)、沉睡(SLEEPY)、流失(LOST), PAUSE(暂停)",required = false)
+    private String studentStatus;
+
+    @ApiModelProperty(value = "回访状态,THINKING(考虑中), PENDING_PAYMENT(确认缴费待缴费),LOST(流失), PAUSE(暂停),OTHER(其他)",required = false)
+    private String feedbackType;
+
+    @ApiModelProperty(value = "30天课耗",required = false)
+    private Integer latelyCourseConsumer;
+
+    @ApiModelProperty(value = "一年课耗",required = false)
+    private Integer latelyYearCourseConsumer;
+
+    @ApiModelProperty(value = "回访次数",required = false)
+    private Integer visitNum;
+
+    @ApiModelProperty(value = "指导老师",required = false)
+    private Integer teacherId;
+
+    @ApiModelProperty(value = "声部课老师",required = false)
+    private Integer subjectTeacherId;
+
+    @ApiModelProperty(value = "乐团主管",required = false)
+    private Integer musicDirectorId;
+
+    @ApiModelProperty(value = "是否查询课耗异常",required = false)
+    private Boolean courseConsumerError;
+
+    @ApiModelProperty(value = "第一次课开始时间(年月日)",required = false)
+    private String firstCourseStartTime;
+
+    @ApiModelProperty(value = "第一次课截止时间(年月日)",required = false)
+    private String firstCourseEndTime;
+
+    @ApiModelProperty(value = "分部编号列表",required = false)
+    private String organId;
+
+    public String getOrganId() {
+        return organId;
+    }
+
+    public void setOrganId(String organId) {
+        this.organId = organId;
+    }
+
+    public String getGroupType() {
+        return groupType;
+    }
+
+    public void setGroupType(String groupType) {
+        this.groupType = groupType;
+    }
+
+    public Integer getSubjectId() {
+        return subjectId;
+    }
+
+    public void setSubjectId(Integer subjectId) {
+        this.subjectId = subjectId;
+    }
+
+    public String getStudentStatus() {
+        return studentStatus;
+    }
+
+    public void setStudentStatus(String studentStatus) {
+        this.studentStatus = studentStatus;
+    }
+
+    public String getFeedbackType() {
+        return feedbackType;
+    }
+
+    public void setFeedbackType(String feedbackType) {
+        this.feedbackType = feedbackType;
+    }
+
+    public Integer getLatelyCourseConsumer() {
+        return latelyCourseConsumer;
+    }
+
+    public void setLatelyCourseConsumer(Integer latelyCourseConsumer) {
+        this.latelyCourseConsumer = latelyCourseConsumer;
+    }
+
+    public Integer getLatelyYearCourseConsumer() {
+        return latelyYearCourseConsumer;
+    }
+
+    public void setLatelyYearCourseConsumer(Integer latelyYearCourseConsumer) {
+        this.latelyYearCourseConsumer = latelyYearCourseConsumer;
+    }
+
+    public Integer getVisitNum() {
+        return visitNum;
+    }
+
+    public void setVisitNum(Integer visitNum) {
+        this.visitNum = visitNum;
+    }
+
+    public Integer getTeacherId() {
+        return teacherId;
+    }
+
+    public void setTeacherId(Integer teacherId) {
+        this.teacherId = teacherId;
+    }
+
+    public Integer getSubjectTeacherId() {
+        return subjectTeacherId;
+    }
+
+    public void setSubjectTeacherId(Integer subjectTeacherId) {
+        this.subjectTeacherId = subjectTeacherId;
+    }
+
+    public Integer getMusicDirectorId() {
+        return musicDirectorId;
+    }
+
+    public void setMusicDirectorId(Integer musicDirectorId) {
+        this.musicDirectorId = musicDirectorId;
+    }
+
+    public Boolean getCourseConsumerError() {
+        return courseConsumerError;
+    }
+
+    public void setCourseConsumerError(Boolean courseConsumerError) {
+        this.courseConsumerError = courseConsumerError;
+    }
+
+    public String getFirstCourseStartTime() {
+        return firstCourseStartTime;
+    }
+
+    public void setFirstCourseStartTime(String firstCourseStartTime) {
+        this.firstCourseStartTime = firstCourseStartTime;
+    }
+
+    public String getFirstCourseEndTime() {
+        return firstCourseEndTime;
+    }
+
+    public void setFirstCourseEndTime(String firstCourseEndTime) {
+        this.firstCourseEndTime = firstCourseEndTime;
+    }
+}

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/StudentVisitQueryInfo.java

@@ -36,6 +36,17 @@ public class StudentVisitQueryInfo extends QueryInfo {
     @ApiModelProperty(value = "回访日期结束时间", required = false)
     private Date endTime;
 
+    @ApiModelProperty(value = "家长回访类型(\"THINKING\", \"考虑中\"),(\"PENDING_PAYMENT\", \"确认缴费待缴费\"),(\"LOST\", \"流失\"),(\"PAUSE\", \"暂停\"),(\"OTHER\", \"其他\")", required = false)
+    private String feedbackType;
+
+    public String getFeedbackType() {
+        return feedbackType;
+    }
+
+    public void setFeedbackType(String feedbackType) {
+        this.feedbackType = feedbackType;
+    }
+
     public String getTeacher() {
         return teacher;
     }

+ 20 - 0
mec-biz/src/main/java/com/ym/mec/biz/dal/page/SysExamSongQueryInfo.java

@@ -19,6 +19,10 @@ public class SysExamSongQueryInfo extends QueryInfo {
 
     @ApiModelProperty(value = "曲库分类",required = true)
     private String categoriesId;
+    
+    private String filterCategoriesIds;
+    
+    private String categoriesIds;
 
     @ApiModelProperty(value = "是否收费",required = true)
     private Integer rankType;
@@ -142,4 +146,20 @@ public class SysExamSongQueryInfo extends QueryInfo {
     public void setType(String type) {
         this.type = type;
     }
+
+	public String getFilterCategoriesIds() {
+		return filterCategoriesIds;
+	}
+
+	public void setFilterCategoriesIds(String filterCategoriesIds) {
+		this.filterCategoriesIds = filterCategoriesIds;
+	}
+
+	public String getCategoriesIds() {
+		return categoriesIds;
+	}
+
+	public void setCategoriesIds(String categoriesIds) {
+		this.categoriesIds = categoriesIds;
+	}
 }

+ 7 - 2
mec-biz/src/main/java/com/ym/mec/biz/service/ExportService.java

@@ -5,6 +5,7 @@ import com.ym.mec.biz.dal.entity.ManagerDownload;
 import com.ym.mec.biz.dal.enums.ExportEnum;
 import com.ym.mec.biz.dal.enums.ExportTypeEnum;
 import com.ym.mec.biz.dal.page.EndCourseScheduleQueryInfo;
+import com.ym.mec.biz.dal.page.StudentStatisticsQueryInfo;
 import com.ym.mec.common.entity.HttpResponseResult;
 import org.springframework.scheduling.annotation.Async;
 
@@ -267,14 +268,16 @@ public interface ExportService {
     //订单列表导出
     HttpResponseResult orderList(Map<String, Object> info,List<String> headColumns);
 
-    //终课表列表导出
-    HttpResponseResult superFindCourseSchedules(Map<String, Object> info);
+    //订单列表汇总导出
+    HttpResponseResult orderListSum(Map<String, Object> info,List<String> headColumns);
 
     //保存下载记录
     ManagerDownload saveManagerDownload(ExportTypeEnum exportTypeEnum, Integer userId);
 
     void orderList(Map<String, Object> params, ManagerDownload managerDownload,List<String> headColumns) throws FileNotFoundException;
 
+    void orderListSum(Map<String, Object> params, ManagerDownload managerDownload,List<String> headColumns) throws FileNotFoundException;
+
     void routeOrderList(Map<String, Object> params, ManagerDownload managerDownload,List<String> headColumns) throws FileNotFoundException;
 
     void superFindCourseSchedules(EndCourseScheduleQueryInfo queryInfo, ManagerDownload managerDownload) throws FileNotFoundException;
@@ -284,4 +287,6 @@ public interface ExportService {
     void queryStudentCourseInfo(String organId, Integer tenantId, String vip, ManagerDownload managerDownload, List<String> headColumns,ExportEnum exportEnum) throws FileNotFoundException;
 
     void queryVipStudentCourseManage(String organId, Integer tenantId, ManagerDownload managerDownload, List<String> headColumns, ExportEnum exportEnum) throws FileNotFoundException;
+
+    void exportStudentSmallClassStatisticsSum(StudentStatisticsQueryInfo queryInfo, ManagerDownload managerDownload) throws FileNotFoundException;
 }

+ 9 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/MusicGroupService.java

@@ -18,6 +18,15 @@ import java.util.Map;
 import java.util.Set;
 
 public interface MusicGroupService extends BaseService<String, MusicGroup> {
+	
+	/**
+	 * 将学生导入至乐团中
+	 * @param musicGroupId
+	 * @param excelData
+	 * @return
+	 */
+	boolean importStudentToMusicGroup(String musicGroupId, Map<String, List<Map<String, Object>>> excelData);
+	
     /**
      * 建团申请数据提交
      *

+ 3 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/StudentServeService.java

@@ -1,13 +1,12 @@
 package com.ym.mec.biz.service;
 
-import com.ym.mec.biz.dal.dto.IndexBaseDto;
-import org.apache.ibatis.annotations.Param;
-
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import com.ym.mec.biz.dal.dto.IndexBaseDto;
+
 /**
  * @Author Joburgess
  * @Date 2020.05.27
@@ -23,7 +22,7 @@ public interface StudentServeService {
      */
     void exercisesSituationStatistics(String monday, Integer tenantId);
 
-    void exercisesSituationStatistics2(String monday, List<Integer> studentIds, Integer tenantId);
+    void exercisesSituationStatistics2(String monday, Integer tenantId);
 
     /**
      * @describe

+ 34 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/StudentStatisticsService.java

@@ -0,0 +1,34 @@
+package com.ym.mec.biz.service;
+
+import com.ym.mec.biz.dal.dto.StudentStatisticsDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumForDateDto;
+import com.ym.mec.biz.dal.entity.StudentStatistics;
+import com.ym.mec.biz.dal.page.StudentStatisticsQueryInfo;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.common.page.QueryInfo;
+import com.ym.mec.common.service.BaseService;
+
+import java.util.List;
+import java.util.Map;
+
+public interface StudentStatisticsService extends BaseService<Integer, StudentStatistics> {
+
+    //定时任务
+    void updateStudentStatistics();
+
+    //分页查询学员小课数据
+    PageInfo<StudentStatisticsDto> queryStatisticsPage(StudentStatisticsQueryInfo queryInfo);
+
+    //获取小课数据统计汇总
+    StudentStatisticsSumDto studentSmallClassStatisticsSum(String groupType,String organId);
+
+    //按时间获取统计数据
+    StudentStatisticsSumForDateDto studentSmallClassStatisticsSumForDate(String groupType, String startDate, String endDate,String organId);
+
+    //获取指导老师列表
+    List<Map<Integer, String>> queryTeacherList(String groupType);
+
+    //获取乐团主管列表
+    List<Map<Integer, String>> queryDirectorList(String groupType);
+}

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/SysMusicScoreCategoriesService.java

@@ -11,7 +11,7 @@ public interface SysMusicScoreCategoriesService extends BaseService<Integer, Sys
 
     List<SysMusicScoreCategories> queryTree(MusicScoreQueryInfo menuQueryInfo);
     
-    List<SysMusicScoreCategories> queryCategoriesTreeList(String categoryIdList);
+    List<SysMusicScoreCategories> queryCategoriesTreeList(String categoryIdList, Boolean isQueryEnable);
 
     void save(SysMusicScoreCategories musicScoreCategories);
 

+ 484 - 69
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExportServiceImpl.java

@@ -47,6 +47,9 @@ import java.util.concurrent.Executors;
 import java.util.function.BiFunction;
 import java.util.function.Function;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.ym.mec.biz.dal.enums.OrderTypeEnum.OUTORDER;
 
 @Service
 public class ExportServiceImpl implements ExportService {
@@ -170,6 +173,8 @@ public class ExportServiceImpl implements ExportService {
     @Autowired
     private SysUserCashAccountLogService sysUserCashAccountLogService;
     @Autowired
+    private StudentStatisticsService studentStatisticsService;
+    @Autowired
     private SysTenantConfigService sysTenantConfigService;
 
     @Value("${spring.profiles.active:dev}")
@@ -337,6 +342,7 @@ public class ExportServiceImpl implements ExportService {
         exportManageFuncMap.put(ExportEnum.ROUTE_ORDER_LIST2, (info,headColumns) -> routeOrderList(info,headColumns));
         exportManageFuncMap.put(ExportEnum.ORDER_LIST1, (info,headColumns) -> orderList(info,headColumns));
         exportManageFuncMap.put(ExportEnum.ORDER_LIST2, (info,headColumns) -> orderList(info,headColumns));
+        exportManageFuncMap.put(ExportEnum.ORDER_LIST_SUM, (info,headColumns) -> orderListSum(info,headColumns));
         exportManageFuncMap.put(ExportEnum.STUDENT_VIP_PRACTICE, (info,headColumns) -> exportStudentVipPractice(info,headColumns));
         exportManageFuncMap.put(ExportEnum.STUDENT_VIP_COURSE_INFO, (info,headColumns) -> exportStudentVipCourseInfo(info,headColumns));
         exportManageFuncMap.put(ExportEnum.STUDENT_MUSIC_THEORY_COURSE_INFO, (info,headColumns) -> exportStudentMusicTheoryCourseInfo(info,headColumns));
@@ -1531,39 +1537,37 @@ public class ExportServiceImpl implements ExportService {
         return succeed;
     }
 
-    //终课表列表导出
+    //订单列表导出
     @Override
-    public HttpResponseResult superFindCourseSchedules(Map<String, Object> info){
-        EndCourseScheduleQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info),EndCourseScheduleQueryInfo.class);
+    public HttpResponseResult orderListSum(Map<String, Object> info,List<String> headColumns){
+        StudentPaymentOrderQueryInfo queryInfo = JSONObject.parseObject(JSONObject.toJSONString(info),StudentPaymentOrderQueryInfo.class);
         SysUser sysUser = sysUserFeignService.queryUserInfo();
-        if (sysUser == null) {
-            throw new BizException("用户信息获取失败");
+        if(sysUser == null || sysUser.getId() == null){
+            return BaseController.failed(HttpStatus.FORBIDDEN, "请登录");
         }
-        queryInfo.setOrganIdList(organizationService.getEmployeeOrgan(sysUser.getId(),queryInfo.getOrganIdList(),sysUser.getIsSuperAdmin()));
-        Map<String, Object> params = new HashMap<>();
-        MapUtil.populateMap(params, queryInfo);
-        Integer tenantId = TenantContextHolder.getTenantId();
-        if(Objects.equals("COURSE_TIME_ERROR",queryInfo.getSearchType())){
-            String courseStartTimeError = sysTenantConfigService.getTenantConfigValue(SysConfigService.COURSE_START_TIME_ERROR, tenantId);
-            String courseEndTimeError = sysTenantConfigService.getTenantConfigValue(SysConfigService.COURSE_END_TIME_ERROR, tenantId);
-            if(StringUtils.isEmpty(courseStartTimeError) || StringUtils.isEmpty(courseEndTimeError)){
-                return BaseController.failed("没有可导出的数据");
+        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);
             }
-            params.put("courseStartTimeError",courseStartTimeError);
-            params.put("courseEndTimeError",courseEndTimeError);
+            queryInfo.setUserIds(userIds);
         }
-        int count = scheduleService.endCountCourseSchedules(params);
+        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.COURSE_SCHEDULE,sysUser.getId());
+        ManagerDownload managerDownload = saveManagerDownload(ExportTypeEnum.ORDER_LIST_SUM,sysUser.getId());
         ExecutorService executor = Executors.newCachedThreadPool();
         CompletableFuture.runAsync(()->{
             try {
-                this.superFindCourseSchedules(queryInfo, managerDownload);
+                this.orderListSum(params, managerDownload, headColumns);
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -1601,7 +1605,7 @@ public class ExportServiceImpl implements ExportService {
         long i = 1;
         Map<Integer, String> cooperationOrganMap = new HashMap<>();
         List<Integer> cooperationOrganIds = studentPaymentOrderExportDtos.stream()
-                .filter(e -> OrderTypeEnum.OUTORDER.equals(e.getType()))
+                .filter(e -> OUTORDER.equals(e.getType()))
                 .filter(e -> e.getMusicGroupId() != null)
                 .map(e -> Integer.valueOf(e.getMusicGroupId()))
                 .distinct()
@@ -1627,6 +1631,8 @@ public class ExportServiceImpl implements ExportService {
         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));
@@ -1635,6 +1641,26 @@ public class ExportServiceImpl implements ExportService {
         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) {
@@ -1737,6 +1763,13 @@ public class ExportServiceImpl implements ExportService {
                             }
                             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) {
@@ -1847,6 +1880,13 @@ public class ExportServiceImpl implements ExportService {
                     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);
+                    }else {
+                        row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RENEW_PRACTICE);
+                    }
+                }
             } else if (row.getGroupType().equals(GroupType.REPLACEMENT)) {
                 row.setMusicalFee(row.getActualAmount());
                 ReplacementInstrumentActivityStatDto info = replacementInstrumentActivityDao.getInfo(Integer.parseInt(row.getMusicGroupId()));
@@ -1859,28 +1899,92 @@ public class ExportServiceImpl implements ExportService {
                         row.setEduTeacher(cooperationOrganEduTeacher.getLinkman());
                     }
                 }
+            } else if (row.getGroupType().equals(GroupType.GOODS_SELL)) {
+                row.setRetailGoodsFee(row.getActualAmount());
+                row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.RETAIL_GOODS);
             } else {
-                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)) {
-                    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());
+                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);
+                            }
+                        }
+                        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.getType().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);
+                        }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);
+                                }else {
+                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.COURSE_SCHOOL_BUY);
+                                }
+                                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);
+                                }else {
+                                    row.setTypeDesc(StudentPaymentOrderExportDto.TypeDesc.COURSE_STUDENT_BUY);
+                                }
+                            }
+                        }
+                        row.setTransferFee(BigDecimal.ZERO);
+                        row.setPlatformFee(BigDecimal.ZERO);
                     }
-                    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()));
-                } else if (row.getType().equals(OrderTypeEnum.REPAIR)) {
-                    row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
-                } else if (row.getType().equals(OrderTypeEnum.OUTORDER)) {
-                    row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(row.getTeachingFee()).subtract(row.getMaintenanceProductFee()).subtract(feeByType.getOtherFee()));
-                    row.setTransferFee(BigDecimal.ZERO);
-                    row.setPlatformFee(BigDecimal.ZERO);
                 }
             }
             //如果合作单位不存在取学员的第一个乐团的合作单位,乐团主管
@@ -1891,7 +1995,7 @@ public class ExportServiceImpl implements ExportService {
                     row.setEduTeacher(cooperationOrgan.getLinkman() != null ? cooperationOrgan.getLinkman() : row.getEduTeacher());
                 }
             }
-            if (row.getType().equals(OrderTypeEnum.OUTORDER) && row.getMusicGroupId() != null) {
+            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()));
@@ -1928,30 +2032,6 @@ public class ExportServiceImpl implements ExportService {
             Map<String, String> headMap = getExportMap(new ExportDto(ExportEnum.ORDER_LIST1, headColumns));
             String[] header = headMap.keySet().toArray(new String[headMap.keySet().size()]);
             String[] body = headMap.values().toArray(new String[headMap.keySet().size()]);
-            /*if(isPlatformUser){
-                String[] header = {"序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额",
-                        "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费",
-                        "账户充值", "其它", "汇付手续费","平台手续费", "到账时间",
-                        "关联乐团ID/VIP课ID", "课程形态", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"};
-                
-                String[] body = {"id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount", "balancePaymentAmount",  "couponRemitFee",
-                        "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee",
-                        "leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee", "otherFee", "transferFee", "platformFee", "payTime", "musicGroupId",
-                        "groupType.desc", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"};
-                workbook = POIUtil.exportExcel(header, body, studentPaymentOrderExportDtos);
-            }else{
-                String[] header = {"序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额",
-                        "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费",
-                        "账户充值", "其它","平台手续费", "到账时间",
-                        "关联乐团ID/VIP课ID", "课程形态", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"};
-                
-                String[] body = {"id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount", "balancePaymentAmount",  "couponRemitFee",
-                        "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee",
-                        "leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee", "otherFee", "platformFee", "payTime", "musicGroupId",
-                        "groupType.desc", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"};
-                workbook = POIUtil.exportExcel(header, body, studentPaymentOrderExportDtos);
-            }*/
-
             workbook = POIUtil.exportExcel(header, body, studentPaymentOrderExportDtos);
             workbook.write(fileOutputStream);
             fileOutputStream.getFD().sync();
@@ -1977,12 +2057,304 @@ public class ExportServiceImpl implements ExportService {
     }
 
     @Override
+    public void orderListSum(Map<String, Object> params, ManagerDownload managerDownload,List<String> headColumns) throws FileNotFoundException {
+        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)) {
+                    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.getType().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);
+                        }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);
+        }
+
+        String basePath = new ApplicationHome(this.getClass()).getSource().getParentFile().getPath();
+        File file = new File(basePath + "/" + managerDownload.getName());
+        FileOutputStream fileOutputStream = new FileOutputStream(file);
+
+        HSSFWorkbook workbook = null;
+        try {
+            Map<String, String> headMap = getExportMap(new ExportDto(ExportEnum.ORDER_LIST_SUM, headColumns));
+            String[] header = headMap.keySet().toArray(new String[headMap.keySet().size()]);
+            String[] body = headMap.values().toArray(new String[headMap.keySet().size()]);
+            workbook = POIUtil.exportExcel(header, body, exportDtoList);
+            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 {
+            try {
+                fileOutputStream.close();
+                workbook.close();
+                file.delete();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
     public void routeOrderList(Map<String, Object> params, ManagerDownload managerDownload,List<String> headColumns) throws FileNotFoundException {
         List<StudentPaymentOrderExportDto> studentPaymentOrderExportDtos = studentPaymentRouteOrderDao.ExportQueryPage(params);
 
         Map<Integer, String> cooperationOrganMap = new HashMap<>();
         List<Integer> cooperationOrganIds = studentPaymentOrderExportDtos.stream()
-                .filter(e -> OrderTypeEnum.OUTORDER.equals(e.getType()))
+                .filter(e -> OUTORDER.equals(e.getType()))
                 .filter(e -> e.getMusicGroupId() != null)
                 .map(e -> Integer.valueOf(e.getMusicGroupId()))
                 .distinct()
@@ -2303,7 +2675,7 @@ public class ExportServiceImpl implements ExportService {
                     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()));
                 } else if (row.getType().equals(OrderTypeEnum.REPAIR)) {
                     row.setRepairFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getOtherFee()));
-                } else if (row.getType().equals(OrderTypeEnum.OUTORDER)) {
+                } else if (row.getType().equals(OUTORDER)) {
                     row.setMusicGroupCourseFee(feeByType.getActualAmount().subtract(feeByType.getMusicalFee()).subtract(feeByType.getTeachingFee()).subtract(feeByType.getRepairFee()).subtract(feeByType.getOtherFee()));
                     row.setTransferFee(BigDecimal.ZERO);
                     row.setPlatformFee(BigDecimal.ZERO);
@@ -2317,7 +2689,7 @@ public class ExportServiceImpl implements ExportService {
                     row.setEduTeacher(cooperationOrgan.getLinkman() != null ? cooperationOrgan.getLinkman() : row.getEduTeacher());
                 }
             }
-            if (row.getType().equals(OrderTypeEnum.OUTORDER) && row.getMusicGroupId() != null) {
+            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()));
@@ -2439,7 +2811,7 @@ public class ExportServiceImpl implements ExportService {
                         musicGroupCourseFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(maintenanceFee).subtract(maintenanceProductFee).subtract(otherFee).subtract(leaseFee).subtract(cloudTeacherFee);
                     } else if (order.getType().equals(OrderTypeEnum.REPAIR)) {
                         repairFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(otherFee);
-                    } else if (order.getType().equals(OrderTypeEnum.OUTORDER)) {
+                    } else if (order.getType().equals(OUTORDER)) {
                         musicGroupCourseFee = order.getRouteAmount().subtract(musicalFee).subtract(teachingFee).subtract(maintenanceProductFee).subtract(otherFee);
                     }
                 }
@@ -2744,4 +3116,47 @@ public class ExportServiceImpl implements ExportService {
             }
         }
     }
+
+    @Override
+    public void exportStudentSmallClassStatisticsSum(StudentStatisticsQueryInfo queryInfo, ManagerDownload managerDownload) throws FileNotFoundException {
+        List<StudentStatisticsDto> rows = studentStatisticsService.queryStatisticsPage(queryInfo).getRows();
+        String basePath = new ApplicationHome(this.getClass()).getSource().getParentFile().getPath();
+        File file = new File(basePath + "/" + managerDownload.getName());
+        FileOutputStream fileOutputStream = new FileOutputStream(file);
+        OutputStream ouputStream = null;
+        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);
+
+            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();
+                }
+            }
+        }
+    }
 }

+ 1 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ExtracurricularExercisesMessageServiceImpl.java

@@ -71,7 +71,7 @@ public class ExtracurricularExercisesMessageServiceImpl extends BaseServiceImpl<
 				boolean change=false;
 				if(!Integer.valueOf(1).equals(extracurricularExercisesReply.getIsRepliedTimely())&&Objects.nonNull(extracurricularExercisesReply.getSubmitTime())){
 					int hours = DateUtil.hoursBetween(extracurricularExercisesReply.getSubmitTime(), new Date());
-					if(hours>=0&&hours<=12){
+					if(hours>=0&&hours<=24){
 						extracurricularExercisesReply.setIsRepliedTimely(1);
 						change=true;
 					}

+ 19 - 3
mec-biz/src/main/java/com/ym/mec/biz/service/impl/ImLiveBroadcastRoomServiceImpl.java

@@ -43,6 +43,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.io.Serializable;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 import java.util.function.BiConsumer;
 import java.util.stream.Collectors;
 
@@ -81,6 +82,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
     public static final String LIVE_SPEAKER_INFO = "IM:LIVE_SPEAKER_INFO:" + USER_ID;
     //用户对应的直播间Uid
     public static final String LIVE_USER_ROOM = "IM:LIVE_ROOM_USER:" + USER_ID;
+    //记录人员最后变更的状态消息时间
+    public static final String LIVE_USER_STATE_TIME = "IM:LIVE_USER_STATE_TIME:" + USER_ID;
     //房间点赞数
     public static final String LIVE_ROOM_LIKE = "IM:LIVE_ROOM_LIKE:" + ROOM_UID;
     //直播提前开始时间
@@ -443,8 +446,21 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 return;
             }
             Date now = new Date();
+            //获取当前用户状态变更的时间
+            long userStateTime = Optional.ofNullable(user.getTime()).orElse(now.getTime());
+            String userid = user.getUserid();
+            RBucket<Long> userStateTimeCache = redissonClient.getBucket(LIVE_USER_STATE_TIME.replace(USER_ID, userid));
+            if (userStateTimeCache.isExists()) {
+                //缓存的时间比当前传入时间大则放弃这条数据
+                long cacheTime = userStateTimeCache.get();
+                if (cacheTime > userStateTime) {
+                    return;
+                }
+            }
+            //将最新的时间写入缓存
+            userStateTimeCache.set(userStateTime,5L, TimeUnit.MINUTES);
             //查询主讲人userId,若是主讲人
-            RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, user.getUserid()));
+            RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userid));
             if (speakerCache.isExists()) {
                 RoomSpeakerInfo speakerInfo = speakerCache.get();
                 //主讲人进入房间
@@ -466,12 +482,12 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
                 return;
             }
             //获取当前用户所在房间的uid
-            RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, user.getUserid()));
+            RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userid));
             if (!userRoom.isExists()) {
                 return;
             }
             String roomUid = userRoom.get();
-            Integer userId = Integer.valueOf(user.getUserid());
+            Integer userId = Integer.valueOf(userid);
 
             //从房间累计用户信息中查询该用户的信息
             RMap<Integer, RoomUserInfoVo> roomTotalUser = redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));

+ 11 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/IndexBaseMonthDataServiceImpl.java

@@ -458,6 +458,17 @@ public class IndexBaseMonthDataServiceImpl extends BaseServiceImpl<Long, IndexBa
 			saveData(indexBaseMonthDataDao.getGroupCourseDataWithGroup(dayStr, null, null, GroupType.MUSIC, null, null, null,tenantId), dayStr, IndexDataType.MUSIC_GROUP_COURSE, tenantId);
 		}
 
+		//小课数据统计
+		if(CollectionUtils.isEmpty(dataTypes)||dataTypes.contains(STUDENT_VIP_ORDER_NUM)) {
+			saveData(indexBaseMonthDataDao.getStudentVipOrderNum(dayStr,tenantId), dayStr, IndexDataType.STUDENT_VIP_ORDER_NUM, tenantId);
+		}
+		if(CollectionUtils.isEmpty(dataTypes)||dataTypes.contains(STUDENT_THEORY_ORDER_NUM)) {
+			saveData(indexBaseMonthDataDao.getStudentTheoryOrderNum(dayStr,tenantId), dayStr, IndexDataType.STUDENT_THEORY_ORDER_NUM, tenantId);
+		}
+		if(CollectionUtils.isEmpty(dataTypes)||dataTypes.contains(STUDENT_PRACTICE_ORDER_NUM)) {
+			saveData(indexBaseMonthDataDao.getStudentPracticeOrderNum(dayStr,tenantId), dayStr, IndexDataType.STUDENT_PRACTICE_ORDER_NUM, tenantId);
+		}
+
 		if(CollectionUtils.isEmpty(dataTypes)||dataTypes.contains(IndexDataType.VIP_GROUP_COURSE)) {
 			List<IndexBaseMonthData> vipCourseData = indexBaseMonthDataDao.getGroupCourseDataWithGroup(dayStr, null, null, GroupType.VIP, null, null, null,tenantId);
 			List<OrganVipGroupCategoryCourseNumDto> vipGroupCategoryCourseData = indexBaseMonthDataDao.getVipGroupCategoryCourseData(dayStr, null, null, GroupType.VIP, null, null, null,tenantId);

+ 438 - 32
mec-biz/src/main/java/com/ym/mec/biz/service/impl/MusicGroupServiceImpl.java

@@ -1,22 +1,196 @@
 package com.ym.mec.biz.service.impl;
 
+import static com.ym.mec.biz.dal.entity.ApprovalStatus.PROCESSING;
+import static com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus.PAID_COMPLETED;
+import static com.ym.mec.biz.dal.enums.DealStatusEnum.ING;
+import static com.ym.mec.biz.dal.enums.DealStatusEnum.SUCCESS;
+import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.ACCESSORIES;
+import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.MAINTENANCE;
+import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.MUSICAL;
+import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.TEACHING;
+import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;
+import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.TypeReference;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
-import com.ym.mec.biz.dal.dao.*;
-import com.ym.mec.biz.dal.dto.*;
-import com.ym.mec.biz.dal.entity.*;
+import com.ym.mec.biz.dal.dao.ChargeTypeDao;
+import com.ym.mec.biz.dal.dao.ClassGroupDao;
+import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
+import com.ym.mec.biz.dal.dao.ClassGroupTeacherMapperDao;
+import com.ym.mec.biz.dal.dao.CooperationOrganDao;
+import com.ym.mec.biz.dal.dao.CourseScheduleDao;
+import com.ym.mec.biz.dal.dao.CourseScheduleTeacherSalaryDao;
+import com.ym.mec.biz.dal.dao.GoodsDao;
+import com.ym.mec.biz.dal.dao.MusicGroupBuildLogDao;
+import com.ym.mec.biz.dal.dao.MusicGroupDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderCourseSettingsDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderDetailDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentCalenderStudentDetailDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentEntitiesDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPaymentStudentCourseDetailDao;
+import com.ym.mec.biz.dal.dao.MusicGroupPurchaseListDao;
+import com.ym.mec.biz.dal.dao.MusicGroupQuitDao;
+import com.ym.mec.biz.dal.dao.MusicGroupSchoolTermCourseDetailDao;
+import com.ym.mec.biz.dal.dao.MusicGroupSchoolTermStudentCourseDetailDao;
+import com.ym.mec.biz.dal.dao.MusicGroupStudentFeeDao;
+import com.ym.mec.biz.dal.dao.MusicGroupSubjectGoodsGroupDao;
+import com.ym.mec.biz.dal.dao.MusicGroupSubjectPlanDao;
+import com.ym.mec.biz.dal.dao.OrganizationDao;
+import com.ym.mec.biz.dal.dao.SchoolDao;
+import com.ym.mec.biz.dal.dao.SporadicChargeInfoDao;
+import com.ym.mec.biz.dal.dao.StudentDao;
+import com.ym.mec.biz.dal.dao.StudentInstrumentDao;
+import com.ym.mec.biz.dal.dao.StudentPaymentOrderDao;
+import com.ym.mec.biz.dal.dao.StudentPaymentOrderDetailDao;
+import com.ym.mec.biz.dal.dao.StudentPreRegistrationDao;
+import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
+import com.ym.mec.biz.dal.dao.StudentVisitDao;
+import com.ym.mec.biz.dal.dao.SubjectChangeDao;
+import com.ym.mec.biz.dal.dao.SubjectDao;
+import com.ym.mec.biz.dal.dao.SysConfigDao;
+import com.ym.mec.biz.dal.dao.SysUserCashAccountDao;
+import com.ym.mec.biz.dal.dao.SysUserCashAccountLogDao;
+import com.ym.mec.biz.dal.dao.TeacherAttendanceDao;
+import com.ym.mec.biz.dal.dao.TeacherDao;
+import com.ym.mec.biz.dal.dto.BasicUserDto;
+import com.ym.mec.biz.dal.dto.CloseMusicGroupDto;
+import com.ym.mec.biz.dal.dto.CourseScheduleTeachersDto;
+import com.ym.mec.biz.dal.dto.HighClassGroupDto;
+import com.ym.mec.biz.dal.dto.MusicCardDto;
+import com.ym.mec.biz.dal.dto.MusicGroupApplyGoodsDto;
+import com.ym.mec.biz.dal.dto.MusicGroupBasicDto;
+import com.ym.mec.biz.dal.dto.RegisterPayDto;
+import com.ym.mec.biz.dal.dto.SporadicPayDto;
+import com.ym.mec.biz.dal.dto.StudentApplyInstrumentDto;
+import com.ym.mec.biz.dal.dto.StudentImportDto;
+import com.ym.mec.biz.dal.dto.SubFeeSettingDto;
+import com.ym.mec.biz.dal.dto.SubjectRegisterDto;
+import com.ym.mec.biz.dal.dto.UpdateExpectedNumDto;
+import com.ym.mec.biz.dal.entity.ApprovalStatus;
+import com.ym.mec.biz.dal.entity.ChargeType;
+import com.ym.mec.biz.dal.entity.ClassGroup;
+import com.ym.mec.biz.dal.entity.CooperationOrgan;
+import com.ym.mec.biz.dal.entity.CouponPayParam;
+import com.ym.mec.biz.dal.entity.CourseSchedule;
+import com.ym.mec.biz.dal.entity.CourseScheduleTeacherSalary;
+import com.ym.mec.biz.dal.entity.FinancialExpenditure;
+import com.ym.mec.biz.dal.entity.Goods;
+import com.ym.mec.biz.dal.entity.ImGroup;
+import com.ym.mec.biz.dal.entity.MusicGroup;
+import com.ym.mec.biz.dal.entity.MusicGroupBuildLog;
+import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender;
 import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PayUserType;
 import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentCalenderStatusEnum;
 import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalender.PaymentType;
+import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderCourseSettings;
+import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderDetail;
+import com.ym.mec.biz.dal.entity.MusicGroupPaymentCalenderStudentDetail;
+import com.ym.mec.biz.dal.entity.MusicGroupPurchaseList;
+import com.ym.mec.biz.dal.entity.MusicGroupQuit;
+import com.ym.mec.biz.dal.entity.MusicGroupReturnFeeDto;
+import com.ym.mec.biz.dal.entity.MusicGroupSchoolTermCourseDetail;
+import com.ym.mec.biz.dal.entity.MusicGroupStudentFee;
 import com.ym.mec.biz.dal.entity.MusicGroupStudentFee.PaymentStatus;
-import com.ym.mec.biz.dal.enums.*;
+import com.ym.mec.biz.dal.entity.MusicGroupPaymentStudentCourseDetail;
+import com.ym.mec.biz.dal.entity.MusicGroupSubjectGoodsGroup;
+import com.ym.mec.biz.dal.entity.MusicGroupSubjectPlan;
+import com.ym.mec.biz.dal.entity.MusicMemberDto;
+import com.ym.mec.biz.dal.entity.Organization;
+import com.ym.mec.biz.dal.entity.School;
+import com.ym.mec.biz.dal.entity.SporadicChargeInfo;
+import com.ym.mec.biz.dal.entity.Student;
+import com.ym.mec.biz.dal.entity.StudentInstrument;
+import com.ym.mec.biz.dal.entity.StudentPaymentOrder;
+import com.ym.mec.biz.dal.entity.StudentPaymentOrderDetail;
+import com.ym.mec.biz.dal.entity.StudentPreRegistration;
+import com.ym.mec.biz.dal.entity.StudentRegistration;
+import com.ym.mec.biz.dal.entity.Subject;
+import com.ym.mec.biz.dal.entity.SubjectChange;
+import com.ym.mec.biz.dal.entity.SysUserCashAccount;
+import com.ym.mec.biz.dal.entity.SysUserCashAccountDetail;
+import com.ym.mec.biz.dal.entity.SysUserCashAccountLog;
+import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
+import com.ym.mec.biz.dal.enums.CouponDetailTypeEnum;
+import com.ym.mec.biz.dal.enums.CourseStatusEnum;
+import com.ym.mec.biz.dal.enums.CourseViewTypeEnum;
+import com.ym.mec.biz.dal.enums.DealStatusEnum;
+import com.ym.mec.biz.dal.enums.FivePlusGradeEnum;
+import com.ym.mec.biz.dal.enums.GoodsType;
+import com.ym.mec.biz.dal.enums.GradeTypeEnum;
+import com.ym.mec.biz.dal.enums.GroupType;
+import com.ym.mec.biz.dal.enums.KitGroupPurchaseTypeEnum;
+import com.ym.mec.biz.dal.enums.MessageTypeEnum;
+import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
+import com.ym.mec.biz.dal.enums.OrderDetailTypeEnum;
+import com.ym.mec.biz.dal.enums.OrderTypeEnum;
+import com.ym.mec.biz.dal.enums.PaymentStatusEnum;
+import com.ym.mec.biz.dal.enums.PlatformCashAccountDetailTypeEnum;
+import com.ym.mec.biz.dal.enums.ReturnFeeEnum;
+import com.ym.mec.biz.dal.enums.SixPlusGradeEnum;
+import com.ym.mec.biz.dal.enums.SporadicChargeTypeEnum;
+import com.ym.mec.biz.dal.enums.StudentMusicGroupStatusEnum;
+import com.ym.mec.biz.dal.enums.SysUserRoleEnum;
+import com.ym.mec.biz.dal.enums.TeachTypeEnum;
+import com.ym.mec.biz.dal.enums.YesOrNoEnum;
 import com.ym.mec.biz.dal.page.MusicGroupQueryInfo;
 import com.ym.mec.biz.dal.page.MusicMemberQueryInfo;
 import com.ym.mec.biz.event.source.GroupEventSource;
 import com.ym.mec.biz.event.source.SendSeoMessageSource;
-import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.service.ClassGroupService;
+import com.ym.mec.biz.service.ClassGroupStudentMapperService;
+import com.ym.mec.biz.service.ContractService;
+import com.ym.mec.biz.service.CourseScheduleStudentPaymentService;
+import com.ym.mec.biz.service.GoodsService;
+import com.ym.mec.biz.service.ImGroupMemberService;
+import com.ym.mec.biz.service.ImGroupService;
+import com.ym.mec.biz.service.ImUserFriendService;
+import com.ym.mec.biz.service.MusicGroupPaymentCalenderService;
+import com.ym.mec.biz.service.MusicGroupService;
+import com.ym.mec.biz.service.MusicGroupSubjectGoodsGroupService;
+import com.ym.mec.biz.service.MusicGroupSubjectPlanService;
+import com.ym.mec.biz.service.PayService;
+import com.ym.mec.biz.service.StudentPaymentOrderDetailService;
+import com.ym.mec.biz.service.StudentPaymentOrderService;
+import com.ym.mec.biz.service.StudentPaymentRouteOrderService;
+import com.ym.mec.biz.service.StudentRegistrationService;
+import com.ym.mec.biz.service.StudentService;
+import com.ym.mec.biz.service.SysConfigService;
+import com.ym.mec.biz.service.SysCouponCodeService;
+import com.ym.mec.biz.service.SysEmployeePositionService;
+import com.ym.mec.biz.service.SysMessageService;
+import com.ym.mec.biz.service.SysTenantConfigService;
+import com.ym.mec.biz.service.SysUserCashAccountDetailService;
+import com.ym.mec.biz.service.SysUserCashAccountService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.dal.BaseDAO;
 import com.ym.mec.common.entity.HttpResponseResult;
@@ -32,29 +206,7 @@ import com.ym.mec.util.collection.MapUtil;
 import com.ym.mec.util.date.DateUtil;
 import com.ym.mec.util.http.HttpUtil;
 import com.ym.mec.util.json.JsonUtil;
-import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Propagation;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static com.ym.mec.biz.dal.entity.ApprovalStatus.PROCESSING;
-import static com.ym.mec.biz.dal.enums.DealStatusEnum.ING;
-import static com.ym.mec.biz.dal.enums.DealStatusEnum.SUCCESS;
-import static com.ym.mec.biz.dal.enums.OrderDetailTypeEnum.*;
-import static com.ym.mec.biz.dal.enums.PaymentStatusEnum.YES;
-import static com.ym.mec.biz.dal.enums.SysUserRoleEnum.ORGAN_MANAGER;
+import com.ym.mec.util.validator.CommonValidator;
 
 @Service
 public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> implements MusicGroupService {
@@ -82,6 +234,8 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     @Autowired
     private MusicGroupSubjectPlanDao musicGroupSubjectPlanDao;
     @Autowired
+    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
+    @Autowired
     private MusicGroupBuildLogDao musicGroupBuildLogDao;
     @Autowired
     private MusicGroupPurchaseListDao musicGroupPurchaseListDao;
@@ -188,6 +342,10 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
     private SendSeoMessageSource sendSeoMessageSource;
     @Autowired
     private SysEmployeePositionService employeePositionService;
+    @Autowired
+    private SysUserCashAccountDao sysUserCashAccountDao;
+    @Autowired
+    private StudentDao studentDao;
 
     private SimpleDateFormat sdf_ymd = new SimpleDateFormat("yyyy-MM-dd");
 
@@ -204,6 +362,257 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
 
     @Override
     @Transactional(rollbackFor = Exception.class)
+	public boolean importStudentToMusicGroup(String musicGroupId, Map<String, List<Map<String, Object>>> excelData) {
+    	
+    	MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
+    	
+    	if(musicGroup == null){
+    		throw new BizException("乐团[{}]信息查询失败", musicGroupId);
+    	}
+    	
+    	if(musicGroup.getStatus() != MusicGroupStatusEnum.PAY){
+    		throw new BizException("只有[缴费中]状态的乐团才能导入数据");
+    	}
+    	
+    	Integer tenantId = musicGroup.getTenantId();
+    	
+    	List<StudentImportDto> studentBasicList = new ArrayList<StudentImportDto>();
+    	List<Map<String, Object>> sheet = null;
+    	StudentImportDto dto = null;
+    	for (String sheetName : excelData.keySet()) {
+    		sheet = excelData.get(sheetName);
+    		for(Map<String,Object> row : sheet){
+        		dto = new StudentImportDto();
+        		if(row.get("学生姓名") == null || StringUtils.isBlank(row.get("学生姓名").toString())){
+        			throw new BizException("学生姓名不能为空");
+        		}
+        		dto.setName(row.get("学生姓名").toString());
+        		if(!CommonValidator.isUserName(dto.getName())){
+        			throw new BizException("学生姓名[{}]填写错误", dto.getName());
+        		}
+        		
+        		if(row.get("性别") == null || StringUtils.isBlank(row.get("性别").toString())){
+        			throw new BizException("性别不能为空");
+        		}
+    			dto.setSex(row.get("性别").toString());
+    			
+        		if(row.get("手机号码") == null || StringUtils.isBlank(row.get("手机号码").toString())){
+        			throw new BizException("手机号码不能为空");
+        		}
+    			dto.setMobileNo(row.get("手机号码").toString());
+        		if(!CommonValidator.isMobileNo(dto.getMobileNo())){
+        			throw new BizException("手机号码[{}]填写错误", dto.getMobileNo());
+        		}
+        		
+        		if(row.get("学习声部") == null || StringUtils.isBlank(row.get("学习声部").toString())){
+        			throw new BizException("学习声部不能为空");
+        		}
+    			dto.setSubjectName(row.get("学习声部").toString());
+    			
+        		if(row.get("所在年级") == null || StringUtils.isBlank(row.get("所在年级").toString())){
+        			throw new BizException("所在年级不能为空");
+        		}
+    			dto.setGradeName(row.get("所在年级").toString());
+    			
+    			studentBasicList.add(dto);
+    		}
+    	}
+    	
+    	Date nowDate = new Date();
+    	
+    	//查询导入的声部是否正确
+    	List<String> subjectNameList = studentBasicList.stream().distinct().map(t->t.getSubjectName()).collect(Collectors.toList());
+    	
+    	List<MusicGroupSubjectPlan> musicGroupSubjectPlanList = musicGroupSubjectPlanDao.getMusicSubjectClassPlan(musicGroupId);
+    	
+    	Map<String,Integer> subjectMap = musicGroupSubjectPlanList.stream().collect(Collectors.toMap(MusicGroupSubjectPlan :: getSubName, MusicGroupSubjectPlan :: getSubjectId));
+    	
+    	List<String> allSubjectNameList = musicGroupSubjectPlanList.stream().map(t -> t.getSubName()).collect(Collectors.toList());
+    	
+    	for(String subName : subjectNameList){
+    		if(!allSubjectNameList.contains(subName)){
+    			throw new BizException("当前乐团不支持[{}]声部", subName);
+    		}
+    	}
+    	
+    	//查询课程费用是否是0
+    	MusicGroupPaymentCalender musicGroupPaymentCalender = musicGroupPaymentCalenderDao.findByMusicGroupRegCalender(musicGroupId);
+    	if(musicGroupPaymentCalender == null){
+    		throw new BizException("请先创建乐团报名缴费");
+    	}
+    	
+    	List<MusicGroupPaymentCalenderCourseSettings> musicGroupPaymentCalenderCourseSettingsList = musicGroupPaymentCalenderCourseSettingsDao.queryCalenderCourseSettings(musicGroupPaymentCalender.getId());
+    	double d = musicGroupPaymentCalenderCourseSettingsList.stream().mapToDouble(t -> t.getCourseCurrentPrice().doubleValue()).sum();
+    	
+    	if(d > 0){
+    		throw new BizException("缴费项目中的课程费用为[{}]元,不能导入", d);
+    	}
+    	
+    	//检查用户是否已入团或在其他机构已注册
+    	for(StudentImportDto si : studentBasicList){
+    		SysUser sysUser = studentRegistrationDao.getSysUserByPhone(si.getMobileNo());
+            if (sysUser != null) {
+            	throw new BizException("该手机号[{}]已注册", si.getMobileNo());
+            }
+    	}
+    	
+    	SysUser sysUser = null;
+    	Integer userId = null;
+    	Student student = null;
+    	StudentRegistration studentRegistration = null;
+    	List<StudentRegistration> insertList = new ArrayList<StudentRegistration>();
+		Organization organization = organizationDao.get(musicGroup.getOrganId());
+    	//插入记录
+		for (StudentImportDto si : studentBasicList) {
+			sysUser = new SysUser();
+			sysUser.setPhone(si.getMobileNo());
+			sysUser.setUsername(si.getName());
+			sysUser.setGender(si.getSex().equals("男") ? 1 : 0);
+			sysUser.setUserType("STUDENT");
+			sysUser.setOrganId(musicGroup.getOrganId());
+			sysUser.setCreateTime(nowDate);
+			sysUser.setUpdateTime(nowDate);
+			teacherDao.addSysUser(sysUser);
+			userId = sysUser.getId();
+			
+			si.setUserId(userId);
+			
+			student = new Student(userId, subjectMap.get(si.getSubjectName()) + "");
+	        student.setCurrentGradeNum(SixPlusGradeEnum.get(si.getGradeName()).getCode());
+			studentDao.insert(student);
+			// 添加用户现金账户
+			sysUserCashAccountDao.insert(new SysUserCashAccount(userId, "CNY"));
+			
+			studentRegistration = new StudentRegistration();
+	        String studentGrade = studentService.getStudentGrade(organization.getGradeType(), student.getCurrentGradeNum());
+	        studentRegistration.setCurrentGrade(studentGrade);
+	        studentRegistration.setActualSubjectId(subjectMap.get(si.getSubjectName()));
+	        studentRegistration.setIsAllowAdjust(YesOrNoEnum.YES);
+	        studentRegistration.setSubjectId(subjectMap.get(si.getSubjectName()));
+	        studentRegistration.setUserId(userId);
+	        studentRegistration.setParentsPhone(si.getMobileNo());
+	        studentRegistration.setName(si.getName());
+	        studentRegistration.setGender(sysUser.getGender());
+	        studentRegistration.setPaymentStatus(PaymentStatusEnum.YES);
+	        studentRegistration.setMusicGroupStatus(StudentMusicGroupStatusEnum.NORMAL);
+	        studentRegistration.setTemporaryCourseFee(BigDecimal.ZERO);
+	        studentRegistration.setMusicGroupPaymentCalenderId(null);
+	        studentRegistration.setTenantId(musicGroup.getTenantId());
+	        studentRegistration.setMusicGroupId(musicGroupId);
+	        studentRegistration.setCreateTime(nowDate);
+	        studentRegistration.setUpdateTime(nowDate);
+	        
+	        insertList.add(studentRegistration);
+		}
+        
+		if (insertList.size() > 0) {
+			studentRegistrationService.batchInsert(insertList);
+
+			Map<Integer, Long> subjectCountMap = insertList.stream().collect(
+					Collectors.groupingBy(StudentRegistration::getActualSubjectId, Collectors.counting()));
+
+			MusicGroupSubjectPlan musicOneSubjectClassPlan = null;
+			int totalStudentNum = 0;
+			for (Entry<Integer, Long> entry : subjectCountMap.entrySet()) {
+
+				musicOneSubjectClassPlan = musicGroupSubjectPlanDao.getMusicOneSubjectClassPlan(musicGroupId, entry.getKey());
+				if (musicOneSubjectClassPlan == null) {
+					throw new BizException("系统数据[乐团声部设置]异常");
+				}
+				int applyNum = musicOneSubjectClassPlan.getApplyStudentNum() == null ? 0 : musicOneSubjectClassPlan.getApplyStudentNum();
+				musicOneSubjectClassPlan.setApplyStudentNum(applyNum + entry.getValue().intValue());
+				musicOneSubjectClassPlan.setPaidStudentNum((musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan
+						.getPaidStudentNum()) + entry.getValue().intValue());
+				musicOneSubjectClassPlan.setPaidZeroNum((musicOneSubjectClassPlan.getPaidZeroNum() == null ? 0 : musicOneSubjectClassPlan.getPaidZeroNum())
+						+ entry.getValue().intValue());
+				musicOneSubjectClassPlan.setUpdateTime(nowDate);
+				musicGroupSubjectPlanDao.update(musicOneSubjectClassPlan);
+
+				totalStudentNum += entry.getValue().intValue();
+			}
+
+			// 缴费相关
+			// 更新实际缴费人数
+			if (musicGroupPaymentCalender.getActualNum() == null) {
+				musicGroupPaymentCalender.setActualNum(totalStudentNum);
+			} else {
+				musicGroupPaymentCalender.setActualNum(musicGroupPaymentCalender.getActualNum() + totalStudentNum);
+			}
+			if (musicGroupPaymentCalender.getPaymentType() == MusicGroupPaymentCalender.PaymentType.MUSIC_APPLY) {
+				if (musicGroupPaymentCalender.getExpectNum() == null) {
+					musicGroupPaymentCalender.setExpectNum(totalStudentNum);
+				} else {
+					musicGroupPaymentCalender.setExpectNum(musicGroupPaymentCalender.getExpectNum() + totalStudentNum);
+				}
+			}
+			musicGroupPaymentCalender.setUpdateTime(nowDate);
+			musicGroupPaymentCalenderDao.update(musicGroupPaymentCalender);
+
+			MusicGroupPaymentCalenderDetail musicGroupPaymentCalenderDetail = null;
+			List<MusicGroupPaymentCalenderDetail> insertMusicGroupPaymentCalenderDetailList = new ArrayList<MusicGroupPaymentCalenderDetail>();
+
+			List<MusicGroupPaymentStudentCourseDetail> musicGroupPaymentStudentCourseDetails = new ArrayList<>();
+
+			List<MusicGroupPaymentCalenderCourseSettings> courseSettingsList = musicGroupPaymentCalenderCourseSettingsDao
+					.getWithPaymentCalender(musicGroupPaymentCalender.getId());
+
+			for (StudentImportDto si : studentBasicList) {
+				musicGroupPaymentCalenderDetail = new MusicGroupPaymentCalenderDetail();
+				musicGroupPaymentCalenderDetail.setTenantId(tenantId);
+				musicGroupPaymentCalenderDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
+				musicGroupPaymentCalenderDetail.setUserId(si.getUserId());
+				musicGroupPaymentCalenderDetail.setResponsibleUserId(musicGroupPaymentCalender.getOperator());
+				musicGroupPaymentCalenderDetail.setPaymentStatus(PAID_COMPLETED);
+				musicGroupPaymentCalenderDetail.setPayTime(nowDate);
+				musicGroupPaymentCalenderDetail.setPaymentOrderId(null);
+				musicGroupPaymentCalenderDetail.setUseInCourse(0);
+				musicGroupPaymentCalenderDetail.setOpen(1);
+				musicGroupPaymentCalenderDetail.setUserStatus(null);
+				musicGroupPaymentCalenderDetail.setDeadlinePaymentDate(musicGroupPaymentCalender.getDeadlinePaymentDate());
+				musicGroupPaymentCalenderDetail.setStartPaymentDate(musicGroupPaymentCalender.getStartPaymentDate());
+				musicGroupPaymentCalenderDetail.setCreateTime(nowDate);
+				musicGroupPaymentCalenderDetail.setUpdateTime(nowDate);
+
+				insertMusicGroupPaymentCalenderDetailList.add(musicGroupPaymentCalenderDetail);
+
+				for (MusicGroupPaymentCalenderCourseSettings courseSetting : courseSettingsList) {
+					if (courseSetting.getCourseTotalMinuties() == null || courseSetting.getCourseTotalMinuties() == 0) {
+						continue;
+					}
+					MusicGroupPaymentStudentCourseDetail musicGroupPaymentStudentCourseDetail = new MusicGroupPaymentStudentCourseDetail();
+					musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderId(musicGroupPaymentCalender.getId());
+					//musicGroupPaymentStudentCourseDetail.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetail.getId());
+					musicGroupPaymentStudentCourseDetail.setUserId(si.getUserId());
+					musicGroupPaymentStudentCourseDetail.setCourseType(courseSetting.getCourseType());
+					musicGroupPaymentStudentCourseDetail.setTotalCourseMinutes(courseSetting.getCourseTotalMinuties());
+					musicGroupPaymentStudentCourseDetail.setCourseOriginalPrice(courseSetting.getCourseOriginalPrice());
+					musicGroupPaymentStudentCourseDetail.setCourseCurrentPrice(courseSetting.getCourseCurrentPrice());
+					musicGroupPaymentStudentCourseDetail.setUsedCourseMinutes(0);
+					musicGroupPaymentStudentCourseDetail.setCreateTime(nowDate);
+					musicGroupPaymentStudentCourseDetail.setUpdateTime(nowDate);
+					musicGroupPaymentStudentCourseDetail.setTenantId(tenantId);
+					musicGroupPaymentStudentCourseDetails.add(musicGroupPaymentStudentCourseDetail);
+				}
+			}
+			if (insertMusicGroupPaymentCalenderDetailList.size() > 0) {
+				musicGroupPaymentCalenderDetailDao.batchInsert(insertMusicGroupPaymentCalenderDetailList);
+				
+				Map<Integer,Long> musicGroupPaymentCalenderDetailIdMap =  insertMusicGroupPaymentCalenderDetailList.stream().collect(Collectors.toMap(MusicGroupPaymentCalenderDetail :: getUserId, MusicGroupPaymentCalenderDetail :: getId));
+				
+				if (musicGroupPaymentStudentCourseDetails.size() > 0) {
+					for(MusicGroupPaymentStudentCourseDetail cd : musicGroupPaymentStudentCourseDetails){
+						cd.setMusicGroupPaymentCalenderDetailId(musicGroupPaymentCalenderDetailIdMap.get(cd.getUserId()));
+					}
+					musicGroupPaymentStudentCourseDetailDao.batchInsert(musicGroupPaymentStudentCourseDetails);
+				}
+			}
+		}
+    	
+		return true;
+	}
+
+	@Override
+    @Transactional(rollbackFor = Exception.class)
     public String createGroup(SubFeeSettingDto subFeeSettingDto) {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         if (sysUser == null || sysUser.getId() == null) {
@@ -3664,10 +4073,7 @@ public class MusicGroupServiceImpl extends BaseServiceImpl<String, MusicGroup> i
             registerPayDto.setNewCourse(courseSettings);
             for (StudentRegistration studentRegistration : studentRegistrationList) {
                 registerPayDto.setRegisterId(studentRegistration.getId().intValue());
-                HttpResponseResult result = this.pay(registerPayDto);
-                if (result.getCode() != 200) {
-                    return result;
-                }
+                this.pay(registerPayDto);
             }
         }
 

+ 1 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentExtracurricularExercisesSituationServiceImpl.java

@@ -212,6 +212,7 @@ public class StudentExtracurricularExercisesSituationServiceImpl extends BaseSer
 			List<StudentExtracurricularExercisesSituation> teacherServeWithDate = studentExtracurricularExercisesSituationDao.findTeacherServeWithDate(queryInfo.getMonday(), queryInfo.getSunday(), teacherIds, null);
 			Map<Integer, List<StudentExtracurricularExercisesSituation>> teacherServeMap = teacherServeWithDate.stream().collect(Collectors.groupingBy(StudentExtracurricularExercisesSituation::getTeacherId));
 			for (TeacherServeDto teacherServeDto : dataList) {
+				teacherServeDto.setHomeworkStuNum(teacherServeDto.getExpectExercisesNum() - teacherServeDto.getExerciseNum());
 				List<StudentExtracurricularExercisesSituation> tss = teacherServeMap.get(teacherServeDto.getTeacherId());
 				Set<Long> courseIds = new HashSet<>();
 				for (StudentExtracurricularExercisesSituation ts : tss) {

+ 9 - 1
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentPaymentRouteOrderServiceImpl.java

@@ -204,7 +204,7 @@ public class StudentPaymentRouteOrderServiceImpl extends BaseServiceImpl<Long, S
             if(studentPaymentRouteOrder.getSchoolId() != null) {
                 studentPaymentOrder.setMusicGroupId(studentPaymentRouteOrder.getSchoolId() + "");
             }
-            studentPaymentOrder.setType(OrderTypeEnum.OUTORDER);
+            studentPaymentOrder.setType(studentPaymentRouteOrder.getType());
             studentPaymentOrder.setMerNos(studentPaymentRouteOrder.getMerNo());
             studentPaymentOrder.setOrderNo(studentPaymentRouteOrder.getOrderNo());
             studentPaymentOrder.setGroupType(GroupType.OUTORDER);
@@ -412,6 +412,14 @@ public class StudentPaymentRouteOrderServiceImpl extends BaseServiceImpl<Long, S
                             objectMap.put("incomeType", row.get(s));
                         }
                     }
+                    if (columnValue.equals("type")) {
+                        if (StringUtils.isEmpty(row.get(s).toString())) {
+                            sb.append("第" + rowNum).append("行数据导入失败:订单类型不可为空;");
+                            continue valueIsNull;
+                        } else {
+                            objectMap.put("type", row.get(s));
+                        }
+                    }
                     if (columnValue.equals("transNo")) {
                         if (StringUtils.isEmpty(row.get(s).toString())) {
                             sb.append("第" + rowNum).append("行数据导入失败:交易流水号不可为空;");

+ 227 - 357
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentServeServiceImpl.java

@@ -1,33 +1,70 @@
 package com.ym.mec.biz.service.impl;
 
-import com.alibaba.fastjson.JSON;
-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.service.StudentServeService;
-import com.ym.mec.biz.service.SysConfigService;
-import com.ym.mec.biz.service.SysTenantConfigService;
-import com.ym.mec.common.exception.BizException;
-import com.ym.mec.common.tenant.TenantContextHolder;
-import com.ym.mec.util.date.DateUtil;
-
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-
 import java.math.BigDecimal;
 import java.time.DayOfWeek;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+
+import com.alibaba.fastjson.JSON;
+import com.ym.mec.biz.dal.dao.ClassGroupStudentMapperDao;
+import com.ym.mec.biz.dal.dao.CourseScheduleDao;
+import com.ym.mec.biz.dal.dao.CourseScheduleStudentPaymentDao;
+import com.ym.mec.biz.dal.dao.ExtracurricularExercisesReplyDao;
+import com.ym.mec.biz.dal.dao.MusicGroupDao;
+import com.ym.mec.biz.dal.dao.StudentCourseHomeworkDao;
+import com.ym.mec.biz.dal.dao.StudentDao;
+import com.ym.mec.biz.dal.dao.StudentExtracurricularExercisesSituationDao;
+import com.ym.mec.biz.dal.dao.StudentRegistrationDao;
+import com.ym.mec.biz.dal.dto.BasicUserDto;
+import com.ym.mec.biz.dal.dto.ClassGroupStudentMapperDto;
+import com.ym.mec.biz.dal.dto.IndexBaseDto;
+import com.ym.mec.biz.dal.dto.StudentServeCourseDto;
+import com.ym.mec.biz.dal.dto.StudentServeCourseHomeworkDto;
+import com.ym.mec.biz.dal.dto.StudentServeDto;
+import com.ym.mec.biz.dal.entity.CourseSchedule;
+import com.ym.mec.biz.dal.entity.CourseSchedule.CourseScheduleType;
+import com.ym.mec.biz.dal.entity.CourseScheduleStudentPayment;
+import com.ym.mec.biz.dal.entity.ExtracurricularExercisesReply;
+import com.ym.mec.biz.dal.entity.IndexBaseMonthData;
+import com.ym.mec.biz.dal.entity.MusicGroup;
+import com.ym.mec.biz.dal.entity.StudentCourseHomework;
+import com.ym.mec.biz.dal.entity.StudentExtracurricularExercisesSituation;
+import com.ym.mec.biz.dal.entity.StudentRegistration;
+import com.ym.mec.biz.dal.enums.ClassGroupTypeEnum;
+import com.ym.mec.biz.dal.enums.CourseStatusEnum;
+import com.ym.mec.biz.dal.enums.GroupType;
+import com.ym.mec.biz.dal.enums.IndexDataType;
+import com.ym.mec.biz.dal.enums.MusicGroupStatusEnum;
+import com.ym.mec.biz.dal.enums.TeachTypeEnum;
+import com.ym.mec.biz.dal.enums.YesOrNoEnum;
+import com.ym.mec.biz.service.StudentServeService;
+import com.ym.mec.biz.service.SysConfigService;
+import com.ym.mec.biz.service.SysTenantConfigService;
+import com.ym.mec.common.exception.BizException;
+import com.ym.mec.common.tenant.TenantContextHolder;
+import com.ym.mec.util.date.DateUtil;
+
 /**
  * @Author Joburgess
  * @Date 2020.05.27
@@ -57,7 +94,7 @@ public class StudentServeServiceImpl implements StudentServeService {
     private MusicGroupDao musicGroupDao;
     @Autowired
     private StudentRegistrationDao studentRegistrationDao;
-
+    
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void exercisesSituationStatistics(String monday, Integer tenantId) {
@@ -301,11 +338,15 @@ public class StudentServeServiceImpl implements StudentServeService {
 
     @Override
     @Transactional(rollbackFor = Exception.class)
-    public void exercisesSituationStatistics2(String monday, List<Integer> studentIds, Integer tenantId) {
+    public void exercisesSituationStatistics2(String monday, Integer tenantId) {
         LocalDate nowDate = LocalDateTime.now(DateUtil.zoneId).toLocalDate();
         
+        //统计上周的服务指标总数
         int preWeekServiceNum = studentExtracurricularExercisesSituationDao.countWeekServiceNum(nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue()).plusDays(-7).toString(), tenantId);
+        
+        //统计上周数据今日更新的条数
         int lastWeekTodayUpdateNum = studentExtracurricularExercisesSituationDao.findLastWeekTodayUpdateNum(nowDate.plusDays(-nowDate.getDayOfWeek().getValue()).toString(), tenantId);
+        
         if(preWeekServiceNum>0 && lastWeekTodayUpdateNum<=0){
             nowDate = nowDate.plusDays(-nowDate.getDayOfWeek().getValue());
         }
@@ -317,6 +358,19 @@ public class StudentServeServiceImpl implements StudentServeService {
         LocalDate monDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.MONDAY.getValue());
         LocalDate sunDayDate = nowDate.with(DateUtil.weekFields.dayOfWeek(), DayOfWeek.SUNDAY.getValue());
         Date nextMonday = Date.from(sunDayDate.plusDays(1).atStartOfDay(DateUtil.zoneId).toInstant());
+        
+        /**
+         * 学员在读才生成服务指标,若本周有声部课或合奏课,则布置课后训练;否则,布置课外训练(课外训练看是指定由哪个班级的老师来布置)
+         * 学员在每一个进行中的乐团,且已开始上课都需要布置作业
+         */
+        
+        //查询进行中乐团在读的学生列表
+        List<StudentRegistration> studentRegistrationList = studentRegistrationDao.queryServiceStudentByMusicGroupStatus(DateUtil.dateToString(nextMonday, "yyyy-MM-dd"), tenantId);
+        if(studentRegistrationList == null || studentRegistrationList.size() == 0){
+        	return;
+        }
+        
+        List<Integer> studentIds = studentRegistrationList.stream().map(t -> t.getUserId()).distinct().collect(Collectors.toList());
 
         Set<String> holidayDays = new HashSet<>();
         String holidaySetting = sysTenantConfigService.getTenantConfigValue(SysConfigService.HOLIDAY_SETTING,tenantId);
@@ -333,303 +387,164 @@ public class StudentServeServiceImpl implements StudentServeService {
             everyDay = everyDay.plusDays(1);
         }
 
+        //节假日不产生服务指标
         if(weekInHoliday){
             studentExtracurricularExercisesSituationDao.deleteByMonday(monDayDate.toString(), studentIds);
             return;
         }
-
-//        int weekServiceNum = studentExtracurricularExercisesSituationDao.countWeekServiceNum(monDayDate.toString());
-//        if(weekServiceNum>0&&CollectionUtils.isEmpty(studentIds)){
-//            return;
-//        }
-
-        //查询需要生成服务指标的学员
-        List<StudentServeCourseDto> studentFutureCourseInfo = studentDao.getStudentFutureCourseInfo(monDayDate.toString(), DateUtil.dateToString(nextMonday, "yyyy-MM-dd"), studentIds, tenantId);
-        if(CollectionUtils.isEmpty(studentFutureCourseInfo)){
-            return;
-        }
-        Map<Integer, List<StudentServeCourseDto>> studentCourseMap = studentFutureCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getStudentId));
-        //有单技课或合奏课,且需要服务的学员
-        Set<Integer> musicCourseStudentIds = studentFutureCourseInfo.stream().filter(s -> CourseSchedule.CourseScheduleType.SINGLE.equals(s.getType()) || CourseSchedule.CourseScheduleType.MIX.equals(s.getType())).map(StudentServeCourseDto::getStudentId).collect(Collectors.toSet());
-
-        //有课且被服务的学生
-        Set<Integer> haveCourseBeServeStudentIds = studentCourseMap.keySet();
-        //查询所有开启了服务状态的学员
-        List<Integer> allServeStudentIds = studentDao.getServeStudentIds(tenantId);
-        //没课但需要服务的学员
-        Set<Integer> noCourseServeStudentIds = allServeStudentIds.stream().filter(id -> !haveCourseBeServeStudentIds.contains(id)).collect(Collectors.toSet());
-
-        Set<Integer> musicStudentIds = new HashSet<>();
-        if(!Objects.isNull(noCourseServeStudentIds)){
-            musicStudentIds.addAll(noCourseServeStudentIds);
-        }
-        if(!CollectionUtils.isEmpty(musicCourseStudentIds)){
-            musicStudentIds.addAll(musicCourseStudentIds);
+        
+        //查询截止到本周有课的信息
+        List<StudentServeCourseDto> studentCutoffWeekCourseInfo = studentDao.getStudentFutureCourseInfo("2019-01-01", sunDayDate.toString(), studentIds, tenantId);
+        
+        Map<String,List<Integer>> musicGroupStudentIdListMap = new HashMap<String, List<Integer>>();
+        
+        Map<String, List<StudentServeCourseDto>> musicGroupStudentServiceCourseMap = studentCutoffWeekCourseInfo.stream().collect((Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId)));
+        //学员在单乐团中课程去重
+        for(Entry<String, List<StudentServeCourseDto>> entry : musicGroupStudentServiceCourseMap.entrySet()){
+        	musicGroupStudentIdListMap.put(entry.getKey(), entry.getValue().stream().map(t -> t.getStudentId()).distinct().collect(Collectors.toList()));
         }
-        List<StudentServeCourseDto> noCourseBeServeStudentInfo = new ArrayList<>();
-        if(!CollectionUtils.isEmpty(musicStudentIds)){
-        	//查询进行中的乐团,且需要服务的学生、老师、乐团信息
-            noCourseBeServeStudentInfo = studentDao.getNoCourseBeServeStudentInfo(new ArrayList<>(musicStudentIds), tenantId);
+        
+        //查询本周有声部或合奏的学生
+        List<StudentServeCourseDto> studentCurrentWeekCourseInfo = studentDao.getStudentFutureCourseInfo(monDayDate.toString(), sunDayDate.toString(), studentIds, tenantId);
+        Map<String, List<StudentServeCourseDto>> studentCurrentWeekCourseMap = studentCurrentWeekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));
+        
+        //本周学生在不同乐团中上的第一节课
+        Map<String,Map<Integer,StudentServeCourseDto>> musicGroupStudentCurrentWeekCourseMap = new HashMap<String, Map<Integer,StudentServeCourseDto>>();
+        
+        Map<Integer,List<StudentServeCourseDto>> userCourseListMap = null;
+        Map<Integer,StudentServeCourseDto> userCourseMap = null;
+        String musicGroupId = null;
+        Optional<StudentServeCourseDto> optional = null;
+        
+        //查询学生在乐团中的第一节课
+        for(Entry<String, List<StudentServeCourseDto>> entry : studentCurrentWeekCourseMap.entrySet()){
+        	musicGroupId = entry.getKey();
+        	
+        	userCourseMap = musicGroupStudentCurrentWeekCourseMap.get(musicGroupId);
+        	if(userCourseMap == null){
+        		userCourseMap = new HashMap<Integer, StudentServeCourseDto>();
+        	}
+        	//获取学生本周所有课程
+        	userCourseListMap = entry.getValue().stream().collect(Collectors.groupingBy(StudentServeCourseDto :: getStudentId));
+        	
+        	for(Entry<Integer, List<StudentServeCourseDto>> stuCourseListEntry : userCourseListMap.entrySet()){
+            	//获取学生本周第一节课
+        		optional = stuCourseListEntry.getValue().stream().filter(dto -> (dto.getType() == CourseScheduleType.SINGLE || dto.getType() == CourseScheduleType.TRAINING_SINGLE)).min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime));
+        		if(optional.isPresent()){
+        			userCourseMap.put(stuCourseListEntry.getKey(), optional.get());
+        		}else{
+        			userCourseMap.put(stuCourseListEntry.getKey(), stuCourseListEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get());
+        		}
+        	}
+    		musicGroupStudentCurrentWeekCourseMap.put(musicGroupId, userCourseMap);
         }
-
-        Map<Integer, Set<String>> noCourseStudentMusicIdsMap = noCourseBeServeStudentInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getStudentId, Collectors.mapping(StudentServeCourseDto::getMusicGroupId, Collectors.toSet())));
-        Map<Integer, List<StudentServeCourseDto>> noCourseStudentCourseMap = noCourseBeServeStudentInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getStudentId));
-
-        List<StudentExtracurricularExercisesSituation> results=new ArrayList<>();
-
-        for (Map.Entry<Integer, List<StudentServeCourseDto>> studentCourseMapEntry : studentCourseMap.entrySet()) {
-            Map<CourseSchedule.CourseScheduleType, List<StudentServeCourseDto>> typeCourseMap = studentCourseMapEntry.getValue().stream().collect(Collectors.groupingBy(StudentServeCourseDto::getType));
-            
-            Integer userId = studentCourseMapEntry.getKey();
-            
-            Set<String> musicGroupIds = noCourseStudentMusicIdsMap.get(studentCourseMapEntry.getKey());
-            if(Objects.isNull(musicGroupIds)){
-                musicGroupIds = new HashSet<>();
-            }
-            //查询用户在指定乐团截止本周末的课程数
-            List<Mapper> mapperList = new ArrayList<Mapper>();
-            if(musicGroupIds.size() > 0){
-            	mapperList = courseScheduleStudentPaymentDao.queryUserMusicGroupCourseNumByClassTime(GroupType.MUSIC, musicGroupIds, userId, new Date(0, 1, 1), LocalDateToUdate(sunDayDate));
-            }
-            Map<Object, Object> map = mapperList.stream().collect(Collectors.toMap(Mapper :: getKey, Mapper :: getValue));
-            
-            //是否在乐团生成服务指标
-            boolean isServiceWithMusicGroup = false;
-            //判断截止本周末是否有乐团课
-            for(Mapper m : mapperList){
-            	if((long)m.getValue() > 0){
-            		isServiceWithMusicGroup = true;
-            	}
-            }
-            
-            //有未上的单技课
-            if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.SINGLE) && isServiceWithMusicGroup){
-                
-                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.SINGLE).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
-                if(!CollectionUtils.isEmpty(weekCourseInfo)){
-                    Map<String, List<StudentServeCourseDto>> groupCourseInfo = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getMusicGroupId));
-                    Map<Integer, Set<Long>> teacherNotOverCourseIds = new HashMap<>();
-                    Map<Integer, Set<Long>> teacherServiceCourseIdMap = new HashMap<>();
-                    for (Map.Entry<String, List<StudentServeCourseDto>> groupCourseInfoEntry : groupCourseInfo.entrySet()) {
-                    	
-                        if(musicGroupIds.contains(groupCourseInfoEntry.getKey())) {
-                            musicGroupIds.remove(groupCourseInfoEntry.getKey());
-                        }
-                        
-                        //学生在当前乐团没有上过课,就不需要生成服务指标
-                        if(map.get(groupCourseInfoEntry.getKey()) != null && (long)map.get(groupCourseInfoEntry.getKey()) == 0){
-                        	continue;
-                        }
-                        
-                        StudentServeCourseDto courseInfo = groupCourseInfoEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
-                        if(!teacherServiceCourseIdMap.containsKey(courseInfo.getActualTeacherId())){
-                            teacherServiceCourseIdMap.put(courseInfo.getActualTeacherId(), new HashSet<>());
-                        }
-                        teacherServiceCourseIdMap.get(courseInfo.getActualTeacherId()).add(courseInfo.getCourseScheduleId());
-
-                        if(!teacherNotOverCourseIds.containsKey(courseInfo.getActualTeacherId())){
-                            teacherNotOverCourseIds.put(courseInfo.getActualTeacherId(), new HashSet<>());
-                        }
-                        if(!CourseStatusEnum.OVER.equals(courseInfo.getStatus())){
-                            teacherNotOverCourseIds.get(courseInfo.getActualTeacherId()).add(courseInfo.getCourseScheduleId());
-                        }
-                    }
-                    for (Map.Entry<Integer, Set<Long>> teacherServiceCourseIdMapEntry : teacherServiceCourseIdMap.entrySet()) {
-                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                teacherServiceCourseIdMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                "HOMEWORK", StringUtils.join(teacherServiceCourseIdMapEntry.getValue(), ","));
-                        studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherServiceCourseIdMapEntry.getValue().size());
-                        studentExtracurricularExercisesSituation.setNotOverCourseIds(StringUtils.join(teacherNotOverCourseIds.get(teacherServiceCourseIdMapEntry.getKey()), ","));
-                        studentExtracurricularExercisesSituation.setNotOverCourseNum(teacherNotOverCourseIds.get(teacherServiceCourseIdMapEntry.getKey()).size());
-                        results.add(studentExtracurricularExercisesSituation);
-                    }
-                }
-                if(CollectionUtils.isEmpty(musicGroupIds)){
-                    continue;
-                }
-                Map<Integer, Integer> teacherNumMap = new HashMap<>();
-                for (String groupId : musicGroupIds) {
-                    Integer teacherId = null;
-                    List<BaseMapDto<Integer, Integer>> studentTeacherIdList = classGroupStudentMapperDao.getStudentClassGroupBishopTeacherMap(Arrays.asList(studentCourseMapEntry.getKey()), groupId);
-                    if(!CollectionUtils.isEmpty(studentTeacherIdList)){
-                        teacherId = studentTeacherIdList.get(0).getValue();
-                    }
-                    teacherId = Objects.isNull(teacherId)?noCourseStudentCourseMap.get(studentCourseMapEntry.getKey()).get(0).getLeadTeacherId():teacherId;
-                    if(Objects.isNull(teacherId)){
-                        continue;
-                    }
-
-                    if(!teacherNumMap.containsKey(teacherId)){
-                        teacherNumMap.put(teacherId, 1);
-                    }else{
-                        teacherNumMap.put(teacherId, teacherNumMap.get(teacherId)+1);
-                    }
-
-                }
-
-                for (Map.Entry<Integer, Integer> teacherNumMapEntry : teacherNumMap.entrySet()) {
-                    StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                            teacherNumMapEntry.getKey(),
-                            nowDate.get(DateUtil.weekFields.weekOfYear()),
-                            DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                            "EXERCISE", null);
-                    studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherNumMapEntry.getValue());
-                    results.add(studentExtracurricularExercisesSituation);
-                }
-            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.VIP)){ //有未上的VIP
-                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.VIP);
-                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.VIP).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
-                if(CollectionUtils.isEmpty(weekCourseInfo)){
-                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = futureCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
-                    for (Integer teacherId : teacherCourseMap.keySet()) {
-                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                teacherId,nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                "EXERCISE", null);
-                        results.add(studentExtracurricularExercisesSituation);
-                    }
-                }else{
-                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
-                    for (Map.Entry<Integer, List<StudentServeCourseDto>> teacherCourseMapEntry : teacherCourseMap.entrySet()) {
-                        StudentServeCourseDto courseInfo = teacherCourseMapEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
-                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation;
-                        if(TeachModeEnum.OFFLINE.equals(courseInfo.getTeachMode())){
-                            studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                    teacherCourseMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                    DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                    "EXERCISE", null);
-                        }else{
-                            studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                    teacherCourseMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                    DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                    "HOMEWORK", String.valueOf(courseInfo.getCourseScheduleId()));
-                            if(!CourseStatusEnum.OVER.equals(courseInfo.getStatus())){
-                                studentExtracurricularExercisesSituation.setNotOverCourseIds(String.valueOf(courseInfo.getCourseScheduleId()));
-                                studentExtracurricularExercisesSituation.setNotOverCourseNum(1);
-                            }
-                        }
-                        results.add(studentExtracurricularExercisesSituation);
-                    }
-                }
-            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.MIX)){//有未上的合奏课
-                
-                Map<Integer, Integer> teacherNumMap = new HashMap<>();
-                for (String groupId : musicGroupIds) {
-                	
-                    //学生在当前乐团没有上过课,就不需要生成服务指标
-                    if(map.get(groupId) == null || (long)map.get(groupId) == 0){
-                    	continue;
-                    }
+        
+        StudentServeCourseDto studentServeCourseDto = null;
+        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation = null;
+        List<StudentExtracurricularExercisesSituation> results=new ArrayList<StudentExtracurricularExercisesSituation>();
+        
+        Map<Integer,Map<Integer,Set<Long>>> studentTeacherCourseMap = new HashMap<Integer, Map<Integer,Set<Long>>>();
+        Map<Integer,Map<Integer,Set<Long>>> studentTeacherNotOverCourseMap = new HashMap<Integer, Map<Integer,Set<Long>>>();
+        Map<Integer,Map<Integer,Integer>> studentTeacherCourseNumMap = new HashMap<Integer, Map<Integer,Integer>>();
+		
+		Map<Integer, Set<Long>> teacherCourseMap = null;
+		Map<Integer, Set<Long>> teacherNotOverCourseMap = null;
+		Integer teacherId = null;
+		Set<Long> courseIdList = null;
+		ClassGroupTypeEnum teacherType;
+		Map<Integer,Integer> teacherCourseNumMap = null;
+        
+        //理论上一个学生一个乐团只布置一次作业
+		for (Entry<String, List<Integer>> entry : musicGroupStudentIdListMap.entrySet()) {
+			
+			musicGroupId = entry.getKey();
+			
+			MusicGroup musicGroup = musicGroupDao.get(musicGroupId);
+			if(musicGroup == null || musicGroup.getStatus() != MusicGroupStatusEnum.PROGRESS){
+				continue;
+			}
+			Map<Integer,Integer> studentTeacherMapper = null;
+			
+			teacherType = musicGroup.getExtracurricularTeacher() == null ? ClassGroupTypeEnum.NORMAL : musicGroup.getExtracurricularTeacher();
+			List<ClassGroupStudentMapperDto> classGroupStudentMapperDtoList = classGroupStudentMapperDao.queryByClassGroupType(musicGroupId, teacherType, TeachTypeEnum.BISHOP, entry.getValue());
+			if(classGroupStudentMapperDtoList != null){
+				studentTeacherMapper = classGroupStudentMapperDtoList.stream().collect(Collectors.toMap(ClassGroupStudentMapperDto :: getUserId, ClassGroupStudentMapperDto :: getTeacherId));
+			}
+			
+			userCourseMap = musicGroupStudentCurrentWeekCourseMap.get(musicGroupId);
+			
+			for(Integer studentId : entry.getValue()){
+				//在当前乐团,学生本周是否有课
+				if(userCourseMap == null || userCourseMap.get(studentId) == null){//如果本周没课
+					
+					if(studentTeacherMapper == null || (teacherId = studentTeacherMapper.get(studentId)) == null){
+						continue;
+					}
+					
+					teacherCourseNumMap = studentTeacherCourseNumMap.get(studentId);
+					if(teacherCourseNumMap == null){
+						teacherCourseNumMap = new HashMap<Integer, Integer>();
+					}
+					teacherCourseNumMap.put(teacherId, teacherCourseNumMap.get(teacherId) == null ? 1 : teacherCourseNumMap.get(teacherId) + 1);
+					studentTeacherCourseNumMap.put(studentId, teacherCourseNumMap);
+					
+					//本周没有课,布置课外训练
+					studentExtracurricularExercisesSituation = new StudentExtracurricularExercisesSituation(studentId, teacherId,
+							nowDate.get(DateUtil.weekFields.weekOfYear()), DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(
+									sunDayDate.toString(), "yyyy-MM-dd"), "EXERCISE", null);
+					
+					
+					studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherCourseNumMap.get(teacherId));
+					if(results.contains(studentExtracurricularExercisesSituation)){
+						results.remove(studentExtracurricularExercisesSituation);
+					}
+					results.add(studentExtracurricularExercisesSituation);
+				}else{//如果本周有课
+
+					studentServeCourseDto = userCourseMap.get(studentId);
+					teacherId = studentServeCourseDto.getActualTeacherId();
+					
+					teacherCourseMap = studentTeacherCourseMap.get(studentId);
+					if(teacherCourseMap == null){
+						teacherCourseMap = new HashMap<Integer, Set<Long>>();
+					}
+					courseIdList = teacherCourseMap.get(teacherId);
+					if(courseIdList == null){
+						courseIdList = new HashSet<Long>();
+					}
+					courseIdList.add(studentServeCourseDto.getCourseScheduleId());
+					teacherCourseMap.put(teacherId, courseIdList);
+					studentTeacherCourseMap.put(studentId, teacherCourseMap);
+					
+					studentExtracurricularExercisesSituation = new StudentExtracurricularExercisesSituation(studentId, teacherId,
+							nowDate.get(DateUtil.weekFields.weekOfYear()), DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(
+									sunDayDate.toString(), "yyyy-MM-dd"), "HOMEWORK", StringUtils.join(courseIdList, ","));
+                    studentExtracurricularExercisesSituation.setExpectExercisesNum(courseIdList.size());
                     
-                    Integer teacherId = null;
-                    List<BaseMapDto<Integer, Integer>> studentTeacherIdList = classGroupStudentMapperDao.getStudentClassGroupBishopTeacherMap(Arrays.asList(studentCourseMapEntry.getKey()), groupId);
-                    if(!CollectionUtils.isEmpty(studentTeacherIdList)){
-                        teacherId = studentTeacherIdList.get(0).getValue();
-                    }
-                    teacherId = Objects.isNull(teacherId)?noCourseStudentCourseMap.get(studentCourseMapEntry.getKey()).get(0).getLeadTeacherId():teacherId;
-                    if(Objects.isNull(teacherId)){
-                        continue;
-                    }
-
-                    if(!teacherNumMap.containsKey(teacherId)){
-                        teacherNumMap.put(teacherId, 1);
-                    }else{
-                        teacherNumMap.put(teacherId, teacherNumMap.get(teacherId)+1);
+                    teacherNotOverCourseMap = studentTeacherNotOverCourseMap.get(studentId);
+					if(teacherNotOverCourseMap == null){
+						teacherNotOverCourseMap = new HashMap<Integer, Set<Long>>();
+					}
+					courseIdList = teacherNotOverCourseMap.get(teacherId);
+					if(courseIdList == null){
+						courseIdList = new HashSet<Long>();
+					}
+                    if(studentServeCourseDto.getStatus() != CourseStatusEnum.OVER){
+    					courseIdList.add(studentServeCourseDto.getCourseScheduleId());
+    					teacherNotOverCourseMap.put(teacherId, courseIdList);
+    					studentTeacherNotOverCourseMap.put(studentId, teacherCourseMap);
                     }
-
-                }
-
-                for (Map.Entry<Integer, Integer> teacherNumMapEntry : teacherNumMap.entrySet()) {
-                    StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                            teacherNumMapEntry.getKey(),
-                            nowDate.get(DateUtil.weekFields.weekOfYear()),
-                            DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                            "EXERCISE", null);
-                    studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherNumMapEntry.getValue());
+                    
+                    studentExtracurricularExercisesSituation.setNotOverCourseIds(StringUtils.join(courseIdList, ","));
+                    studentExtracurricularExercisesSituation.setNotOverCourseNum(courseIdList.size());
+					if(results.contains(studentExtracurricularExercisesSituation)){
+						results.remove(studentExtracurricularExercisesSituation);
+					}
                     results.add(studentExtracurricularExercisesSituation);
-                }
-            }else if(typeCourseMap.containsKey(CourseSchedule.CourseScheduleType.PRACTICE)){//有未上的陪练课
-                List<StudentServeCourseDto> futureCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.PRACTICE);
-                List<StudentServeCourseDto> weekCourseInfo = typeCourseMap.get(CourseSchedule.CourseScheduleType.PRACTICE).stream().filter(c -> c.getCourseStartTime().compareTo(nextMonday) < 0).collect(Collectors.toList());
-                if(CollectionUtils.isEmpty(weekCourseInfo)){
-                    Set<Integer> teacherIds = futureCourseInfo.stream().map(StudentServeCourseDto::getActualTeacherId).collect(Collectors.toSet());
-                    for (Integer teacherId : teacherIds) {
-                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                teacherId,nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                "EXERCISE", null);
-                        results.add(studentExtracurricularExercisesSituation);
-                    }
-                }else{
-                    Map<Integer, List<StudentServeCourseDto>> teacherCourseMap = weekCourseInfo.stream().collect(Collectors.groupingBy(StudentServeCourseDto::getActualTeacherId));
-                    Map<Integer, Set<Long>> teacherNotOverCourseIds = new HashMap<>();
-                    Map<Integer, Set<Long>> teacherServiceCourseIdMap = new HashMap<>();
-                    for (Map.Entry<Integer, List<StudentServeCourseDto>> teacherCourseMapEntry : teacherCourseMap.entrySet()) {
-                        StudentServeCourseDto courseInfo = teacherCourseMapEntry.getValue().stream().min(Comparator.comparing(StudentServeCourseDto::getCourseStartTime)).get();
-                        teacherServiceCourseIdMap.put(teacherCourseMapEntry.getKey(), new HashSet<>());
-                        teacherServiceCourseIdMap.get(teacherCourseMapEntry.getKey()).add(courseInfo.getCourseScheduleId());
-
-                        if(!teacherNotOverCourseIds.containsKey(courseInfo.getActualTeacherId())){
-                            teacherNotOverCourseIds.put(courseInfo.getActualTeacherId(), new HashSet<>());
-                        }
-                        if(!CourseStatusEnum.OVER.equals(courseInfo.getStatus())){
-                            teacherNotOverCourseIds.get(courseInfo.getActualTeacherId()).add(courseInfo.getCourseScheduleId());
-                        }
-                    }
-                    for (Map.Entry<Integer, Set<Long>> teacherServiceCourseIdMapEntry : teacherServiceCourseIdMap.entrySet()) {
-                        StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(studentCourseMapEntry.getKey(),
-                                teacherServiceCourseIdMapEntry.getKey(),nowDate.get(DateUtil.weekFields.weekOfYear()),
-                                DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                                "HOMEWORK", StringUtils.join(teacherServiceCourseIdMapEntry.getValue(), ","));
-                        studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherServiceCourseIdMapEntry.getValue().size());
-                        studentExtracurricularExercisesSituation.setNotOverCourseIds(StringUtils.join(teacherNotOverCourseIds.get(teacherServiceCourseIdMapEntry.getKey()), ","));
-                        studentExtracurricularExercisesSituation.setNotOverCourseNum(teacherNotOverCourseIds.get(teacherServiceCourseIdMapEntry.getKey()).size());
-                        results.add(studentExtracurricularExercisesSituation);
-                    }
-                }
-            }else{
-                continue;
-            }
-        }
-
-        for (Integer noCourseServeStudentId : noCourseServeStudentIds) {
-            Set<String> musicGroupIds = noCourseStudentMusicIdsMap.get(noCourseServeStudentId);
-            if(CollectionUtils.isEmpty(musicGroupIds)){
-                continue;
-            }
-            
-            Map<Integer, Integer> teacherNumMap = new HashMap<>();
-            for (String groupId : musicGroupIds) {
-            	
-                Integer teacherId = null;
-                List<BaseMapDto<Integer, Integer>> studentTeacherIdList = classGroupStudentMapperDao.getStudentClassGroupBishopTeacherMap(Arrays.asList(noCourseServeStudentId), groupId);
-                if(!CollectionUtils.isEmpty(studentTeacherIdList)){
-                    teacherId = studentTeacherIdList.get(0).getValue();
-                }
-                teacherId = Objects.isNull(teacherId)?noCourseStudentCourseMap.get(noCourseServeStudentId).get(0).getLeadTeacherId():teacherId;
-                if(Objects.isNull(teacherId)){
-                    continue;
-                }
-
-                if(!teacherNumMap.containsKey(teacherId)){
-                    teacherNumMap.put(teacherId, 1);
-                }else{
-                    teacherNumMap.put(teacherId, teacherNumMap.get(teacherId)+1);
-                }
-
-            }
-
-            for (Map.Entry<Integer, Integer> teacherNumMapEntry : teacherNumMap.entrySet()) {
-                StudentExtracurricularExercisesSituation studentExtracurricularExercisesSituation=new StudentExtracurricularExercisesSituation(noCourseServeStudentId,
-                        teacherNumMapEntry.getKey(),
-                        nowDate.get(DateUtil.weekFields.weekOfYear()),
-                        DateUtil.stringToDate(monDayDate.toString(), "yyyy-MM-dd"), DateUtil.stringToDate(sunDayDate.toString(), "yyyy-MM-dd"),
-                        "EXERCISE", null);
-                studentExtracurricularExercisesSituation.setExpectExercisesNum(teacherNumMapEntry.getValue());
-                results.add(studentExtracurricularExercisesSituation);
-            }
-        }
+				}
+			}
+			
+		}
 
         if(!CollectionUtils.isEmpty(results)){
             List<Integer> allStudentIds = new ArrayList<>();
@@ -666,7 +581,7 @@ public class StudentServeServiceImpl implements StudentServeService {
                         .collect(Collectors.groupingBy(StudentServeCourseHomeworkDto::getUserId));
             }
 
-            List<ExtracurricularExercisesReply> allStudentExercises = extracurricularExercisesReplyDao.getStudentExercisesWithTimeZone(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allStudentIds), TenantContextHolder.getTenantId());
+            List<ExtracurricularExercisesReply> allStudentExercises = extracurricularExercisesReplyDao.getStudentExercisesWithTimeZone(monDayDate.toString(), sunDayDate.toString(), new ArrayList<>(allStudentIds), tenantId);
             if(!CollectionUtils.isEmpty(allStudentExercises)){
                 studentExercisesMap = allStudentExercises.stream().collect(Collectors.groupingBy(ExtracurricularExercisesReply::getUserId));
             }
@@ -745,7 +660,7 @@ public class StudentServeServiceImpl implements StudentServeService {
                 }
             }
 
-            studentExtracurricularExercisesSituationDao.deleteByMonday(monDayDate.toString(), studentIds);
+            studentExtracurricularExercisesSituationDao.deleteByMonday(monDayDate.toString(), null);
 
             BigDecimal currentPage1=BigDecimal.ONE,
                     pageSize1=new BigDecimal(10000),
@@ -754,51 +669,6 @@ public class StudentServeServiceImpl implements StudentServeService {
 
             while (currentPage1.compareTo(totalPage1)<=0){
                 List<StudentExtracurricularExercisesSituation> rows=results.stream().skip(pageSize1.multiply(currentPage1.subtract(BigDecimal.ONE)).longValue()).limit(pageSize1.longValue()).collect(Collectors.toList());
-//                List<Integer> updateStudentIds = rows.stream().map(StudentExtracurricularExercisesSituation::getStudentId).collect(Collectors.toList());
-//
-//                List<StudentExtracurricularExercisesSituation> weekServiceWithStudents = studentExtracurricularExercisesSituationDao.findWeekServiceWithStudents(monDayDate.toString(), null, updateStudentIds);
-//                Map<String, StudentExtracurricularExercisesSituation> codeServeMap = weekServiceWithStudents.stream().collect(Collectors.toMap(StudentExtracurricularExercisesSituation::getStuAndTeaCode, s -> s, (s1, s2) -> s1));
-//
-//                Set<String> newCodes = rows.stream().map(StudentExtracurricularExercisesSituation::getStuAndTeaCode).collect(Collectors.toSet());
-//                for (StudentExtracurricularExercisesSituation weekServiceWithStudent : weekServiceWithStudents) {
-//                    if(weekServiceWithStudent.getActualExercisesNum()>0||newCodes.contains(weekServiceWithStudent.getStuAndTeaCode())){
-//                        continue;
-//                    }
-//                    studentExtracurricularExercisesSituationDao.delete(weekServiceWithStudent.getId());
-//                }
-//
-//                List<StudentExtracurricularExercisesSituation> newService = new ArrayList<>();
-//                List<StudentExtracurricularExercisesSituation> updateService = new ArrayList<>();
-//                for (StudentExtracurricularExercisesSituation result : rows) {
-//                    if(codeServeMap.containsKey(result.getStuAndTeaCode())){
-//                        StudentExtracurricularExercisesSituation s = codeServeMap.get(result.getStuAndTeaCode());
-//                        Set<Long> courseIds = new HashSet<>();
-//                        if(StringUtils.isNotBlank(s.getCourseIds())&&s.getActualExercisesNum()>0){
-//                            courseIds = Arrays.stream(s.getCourseIds().split(",")).map(id->Long.valueOf(id)).collect(Collectors.toSet());
-//                        }
-//                        if(StringUtils.isNotBlank(result.getCourseIds())){
-//                            courseIds.addAll(Arrays.stream(result.getCourseIds().split(",")).map(id->Long.valueOf(id)).collect(Collectors.toSet()));
-//                        }
-//                        s.setServeType(result.getServeType());
-//                        if(s.getServeType().equals("HOMEWORK")){
-//                            s.setCourseIds(StringUtils.join(courseIds, ","));
-//                        }else{
-//                            s.setCourseIds("");
-//                        }
-//                        if(StringUtils.isBlank(s.getCourseIds())){
-//                            s.setExpectExercisesNum(1);
-//                        }else{
-//                            s.setExpectExercisesNum(courseIds.size());
-//                        }
-//                        updateService.add(s);
-//                    }else{
-//                        newService.add(result);
-//                    }
-//                }
-//                if(!CollectionUtils.isEmpty(updateService))
-//                    studentExtracurricularExercisesSituationDao.batchUpdate(updateService);
-//                if(!CollectionUtils.isEmpty(newService))
-//                    studentExtracurricularExercisesSituationDao.batchInsert(newService);
 
                 studentExtracurricularExercisesSituationDao.batchInsert(rows);
 

+ 139 - 0
mec-biz/src/main/java/com/ym/mec/biz/service/impl/StudentStatisticsServiceImpl.java

@@ -0,0 +1,139 @@
+package com.ym.mec.biz.service.impl;
+
+import com.google.common.collect.Lists;
+import com.ym.mec.biz.dal.dao.StudentBasicInfoDao;
+import com.ym.mec.biz.dal.dao.StudentStatisticsDao;
+import com.ym.mec.biz.dal.dao.TeacherDao;
+import com.ym.mec.biz.dal.dto.StudentStatisticsDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumForDateDto;
+import com.ym.mec.biz.dal.entity.StudentStatistics;
+import com.ym.mec.biz.dal.page.StudentStatisticsQueryInfo;
+import com.ym.mec.biz.service.StudentStatisticsService;
+import com.ym.mec.common.dal.BaseDAO;
+import com.ym.mec.common.page.PageInfo;
+import com.ym.mec.common.service.impl.BaseServiceImpl;
+import com.ym.mec.util.collection.MapUtil;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class StudentStatisticsServiceImpl extends BaseServiceImpl<Integer, StudentStatistics>  implements StudentStatisticsService {
+	
+	@Autowired
+	private StudentStatisticsDao studentStatisticsDao;
+	@Autowired
+	private TeacherDao teacherDao;
+	@Autowired
+	private StudentBasicInfoDao studentBasicInfoDao;
+
+	@Override
+	public BaseDAO<Integer, StudentStatistics> getDAO() {
+		return studentStatisticsDao;
+	}
+
+	@Override
+	@Transactional(rollbackFor = Exception.class)
+	public void updateStudentStatistics() {
+		//获取声部班老师
+		studentBasicInfoDao.updateSubjectTeacher();
+		List<StudentStatistics> statisticsList = new ArrayList<>();
+		//更新乐团主管、指导老师
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsTeacherAndEdu());
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsTeacherAndEdu2());
+		//更新总课时数、已完成、剩余课时数、最近30天课耗、最近1年课耗
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsCourseNum());
+		//更新未排课总数
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsNoCourseNum());
+		//更新未开始价值总和
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsNotStartCourseFee());
+		//更新未排课价值
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsNoCourseFee());
+		//更新第一次课的时间\最近一次课时间
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsFirstAndLastCourseTime());
+		//更新进行中课程组数量
+		statisticsList.addAll(studentStatisticsDao.queryStatisticsNormalGroupNum());
+		statisticsList.removeAll(Collections.singleton(null));
+		if(CollectionUtils.isNotEmpty(statisticsList)){
+			studentStatisticsDao.clean();
+			List<List<StudentStatistics>> partition = Lists.partition(statisticsList, 1000);
+			for (List<StudentStatistics> studentStatistics : partition) {
+				studentStatisticsDao.batchUpdate(studentStatistics);
+			}
+		}
+	}
+
+	@Override
+	public PageInfo<StudentStatisticsDto> queryStatisticsPage(StudentStatisticsQueryInfo queryInfo) {
+		PageInfo<StudentStatisticsDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
+		Map<String, Object> params = new HashMap<String, Object>();
+		MapUtil.populateMap(params, queryInfo);
+		if(StringUtils.isNotEmpty(queryInfo.getOrganId())){
+			List<Integer> organIdList = Arrays.stream(queryInfo.getOrganId().split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
+			params.put("organIdList",organIdList);
+		}
+		List<StudentStatisticsDto> dataList = null;
+		int count = studentStatisticsDao.countStatistics(params);
+		if (count > 0) {
+			pageInfo.setTotal(count);
+			params.put("offset", pageInfo.getOffset());
+			dataList = studentStatisticsDao.queryStatistics(params);
+		}
+		if (count == 0) {
+			dataList = new ArrayList<>();
+		}
+		pageInfo.setRows(dataList);
+		return pageInfo;
+	}
+
+    @Override
+    public StudentStatisticsSumDto studentSmallClassStatisticsSum(String groupType,String organId) {
+		List<Integer> organIdList = new ArrayList<>();
+		if(StringUtils.isNotEmpty(organId)){
+			organIdList = Arrays.stream(organId.split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
+		}
+		return studentStatisticsDao.studentSmallClassStatisticsSum(groupType,organIdList);
+    }
+
+    @Override
+    public StudentStatisticsSumForDateDto studentSmallClassStatisticsSumForDate(String groupType, String startDate, String endDate,String organId) {
+		StudentStatisticsSumForDateDto sumForDateDto = new StudentStatisticsSumForDateDto();
+		List<Integer> organIdList = new ArrayList<>();
+		if(StringUtils.isNotEmpty(organId)){
+			organIdList = Arrays.stream(organId.split(",")).map(id -> Integer.valueOf(id)).collect(Collectors.toList());
+		}
+		//获取流失人数
+		sumForDateDto.setLostNum(studentStatisticsDao.countLostStudentNum(groupType,startDate,endDate,organIdList));
+		//获取新增人数
+		sumForDateDto.setAddNum(studentStatisticsDao.countAddStudentNum(groupType,startDate,endDate,organIdList));
+		//获取续费人数
+		sumForDateDto.setRenewNum(studentStatisticsDao.countRenewStudentNum(groupType,endDate,organIdList));
+		//获取回访人数
+		sumForDateDto.setVisitNum(studentStatisticsDao.countVisitNum(groupType,startDate,endDate,organIdList));
+        return sumForDateDto;
+    }
+
+	@Override
+	public List<Map<Integer, String>> queryTeacherList(String groupType) {
+		List<Integer> teacherIds = studentStatisticsDao.queryTeacherIds(groupType);
+		if(CollectionUtils.isNotEmpty(teacherIds)){
+			return teacherDao.queryNameByIdList(teacherIds);
+		}
+		return new ArrayList<>();
+	}
+
+	@Override
+	public List<Map<Integer, String>> queryDirectorList(String groupType) {
+		List<Integer> teacherIds = studentStatisticsDao.queryDirectorList(groupType);
+		if(CollectionUtils.isNotEmpty(teacherIds)){
+			return teacherDao.queryNameByIdList(teacherIds);
+		}
+		return new ArrayList<>();
+	}
+}

+ 15 - 5
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicCompareRecordServiceImpl.java

@@ -194,20 +194,30 @@ public class SysMusicCompareRecordServiceImpl extends BaseServiceImpl<Long, SysM
 			studentSubjectMap = MapUtil.convertIntegerMap(studentSubjectMapList);
 		}
 
+		int rankNum = 0;
 		for (int i = 0; i < userTrainStat.size(); i++) {
-			userTrainStat.get(i).setRankNum(i+1);
+			if(userTrainStat.get(i).getUserId().equals(queryInfo.getUserId())){
+				head = userTrainStat.get(i);
+			}
 			userTrainStat.get(i).setTrainTime(userTrainStat.get(i).getTrainTime()/60);
+			if(userTrainStat.get(i).getVipUser() <= 0){
+				continue;
+			}
+			userTrainStat.get(i).setRankNum(++rankNum);
 			if(studentSubjectMap.containsKey(userTrainStat.get(i).getUserId())){
 				userTrainStat.get(i).setSubjectName(studentSubjectMap.get(userTrainStat.get(i).getUserId()));
 			}
 			if(detail.size()<10){
 				detail.add(userTrainStat.get(i));
 			}
-			if(userTrainStat.get(i).getUserId().equals(queryInfo.getUserId())){
-				head = userTrainStat.get(i);
-			}
 		}
-		head.setStudentNum(studentDao.countStudentsWithOrgan(null));
+		Map<String,Object> params = new HashMap<String, Object>();
+		params.put("tenantId", queryInfo.getTenantId());
+		List<Integer> organIds = new ArrayList<Integer>();
+		organIds.add(queryInfo.getOrganId());
+		params.put("organIds", organIds);
+		
+		head.setStudentNum(studentDao.countStudentsWithOrgan(params));
 		if(StringUtils.isBlank(head.getAvatar())){
 			SysUser user = sysUserFeignService.queryUserById(queryInfo.getUserId());
 			if(user != null){

+ 28 - 18
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreAccompanimentServiceImpl.java

@@ -110,28 +110,38 @@ public class SysMusicScoreAccompanimentServiceImpl extends BaseServiceImpl<Integ
 
     @Override
     public PageInfo<SysMusicScoreAccompaniment> queryScorePage(SysExamSongQueryInfo queryInfo) {
-		if(queryInfo.getCategoriesId() != null){
+		if(queryInfo.getCategoriesIds() != null){
 			List<Integer> categoriesIdList = new ArrayList<>();
-			MusicScoreQueryInfo musicScoreQueryInfo = new MusicScoreQueryInfo();
-			Integer categoriesId = null;
-			if(StringUtils.isNotEmpty(queryInfo.getCategoriesId())){
-				categoriesId = Integer.parseInt(queryInfo.getCategoriesId());
+			String[] categoriesIds = queryInfo.getCategoriesIds().split(",");
+
+			for(String fc : categoriesIds){
+				SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(Integer.parseInt(fc));
+				
+				if(sysMusicScoreCategories == null){
+					throw new BizException("分类找不到");
+				}
+				categoriesIdList.add(Integer.parseInt(fc));
+				sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
+				getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
 			}
-			musicScoreQueryInfo.setParentId(categoriesId);
-			musicScoreQueryInfo.setOrganId(queryInfo.getOrganId());
-			musicScoreQueryInfo.setEnable(queryInfo.getEnable());
-			//List<SysMusicScoreCategories> scoreCategories = sysMusicScoreCategoriesService.queryTree(musicScoreQueryInfo);
-			
-			SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(categoriesId);
+			queryInfo.setCategoriesIds(categoriesIdList.stream().map(String :: valueOf).collect(Collectors.joining(",")));
+		}
+		if(StringUtils.isNotBlank(queryInfo.getFilterCategoriesIds())){
+			String[] filterCategoriesIds = queryInfo.getFilterCategoriesIds().split(",");
+
+			List<Integer> filterCategoriesIdList = new ArrayList<>();
 			
-			if(sysMusicScoreCategories == null){
-				throw new BizException("分类找不到");
+			for(String fc : filterCategoriesIds){
+				SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(Integer.parseInt(fc));
+				
+				if(sysMusicScoreCategories == null){
+					throw new BizException("分类找不到");
+				}
+				filterCategoriesIdList.add(Integer.parseInt(fc));
+				sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
+				getAllCategoryIdList(filterCategoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
 			}
-			categoriesIdList.add(categoriesId);
-			sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
-			getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
-			
-			queryInfo.setCategoriesIdList(categoriesIdList);
+			queryInfo.setFilterCategoriesIds(filterCategoriesIdList.stream().map(String :: valueOf).collect(Collectors.joining(",")));
 		}
 		return this.queryPage(queryInfo);
     }

+ 34 - 4
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreCategoriesServiceImpl.java

@@ -3,6 +3,7 @@ package com.ym.mec.biz.service.impl;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 import org.apache.commons.lang3.StringUtils;
@@ -45,7 +46,7 @@ public class SysMusicScoreCategoriesServiceImpl extends BaseServiceImpl<Integer,
 	}
 
 	@Override
-	public List<SysMusicScoreCategories> queryCategoriesTreeList(String categoryIds) {
+	public List<SysMusicScoreCategories> queryCategoriesTreeList(String categoryIds, Boolean isQueryEnable) {
 		
 		categoryIds = categoryIds.endsWith(",") ? categoryIds.substring(0, categoryIds.length() - 1) : categoryIds;
 
@@ -57,7 +58,13 @@ public class SysMusicScoreCategoriesServiceImpl extends BaseServiceImpl<Integer,
 		SysMusicScoreCategories subCategory = null;
 		for(SysMusicScoreCategories smsc : categoryList){
 			
-			if(smsc == null || smsc.getEnable() != true){
+			if(smsc == null){
+				continue;
+			}
+			if(isQueryEnable == null){
+				isQueryEnable = true;
+			}
+			if(isQueryEnable == true && smsc.getEnable() != true){
 				continue;
 			}
 			parentCategory = getParentTree(smsc);
@@ -193,8 +200,20 @@ public class SysMusicScoreCategoriesServiceImpl extends BaseServiceImpl<Integer,
 	@Override
 	@Transactional(rollbackFor = Exception.class)
 	public void del(Integer id) {
-		String byCategoriesIds = sysMusicScoreCategoriesDao.findByCategoriesIds(id.toString());
-		byCategoriesIds = sysMusicScoreCategoriesDao.findByCategoriesIds(byCategoriesIds);
+		
+		List<Integer> categoriesIdList = new ArrayList<>();
+		Integer categoriesId = id;
+		
+		SysMusicScoreCategories sysMusicScoreCategories = get(categoriesId);
+		
+		if(sysMusicScoreCategories == null){
+			throw new BizException("分类找不到");
+		}
+		categoriesIdList.add(categoriesId);
+		sysMusicScoreCategories = getChildTree(sysMusicScoreCategories);
+		getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
+		
+		String byCategoriesIds = categoriesIdList.stream().map(Objects :: toString).collect(Collectors.joining(","));
 		//是否有在使用的分类
 		int count = sysMusicScoreDao.countBuyCategoriesIds(byCategoriesIds);
 		if(count > 0){
@@ -280,4 +299,15 @@ public class SysMusicScoreCategoriesServiceImpl extends BaseServiceImpl<Integer,
 		}
 		parentTree.add(targetCategory);
 	}
+    
+    private void getAllCategoryIdList(List<Integer> categoryIdList, List<SysMusicScoreCategories> sysMusicScoreCategoriesList){
+    	
+    	if(sysMusicScoreCategoriesList != null && sysMusicScoreCategoriesList.size() > 0){
+    		for(SysMusicScoreCategories sysMusicScoreCategories : sysMusicScoreCategoriesList){
+    			categoryIdList.add(sysMusicScoreCategories.getId());
+    			getAllCategoryIdList(categoryIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
+    		}
+    	}
+    	
+    }
 }

+ 16 - 11
mec-biz/src/main/java/com/ym/mec/biz/service/impl/SysMusicScoreServiceImpl.java

@@ -1,8 +1,23 @@
 package com.ym.mec.biz.service.impl;
 
 
+import static com.ym.mec.biz.dal.enums.ClientTypeEnum.SMART_PRACTICE;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
 import com.ym.mec.auth.api.client.SysUserFeignService;
-import com.ym.mec.auth.api.dto.MusicScoreQueryInfo;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.SubjectDao;
 import com.ym.mec.biz.dal.dao.SysMusicScoreAccompanimentDao;
@@ -21,16 +36,6 @@ import com.ym.mec.common.page.PageInfo;
 import com.ym.mec.common.service.impl.BaseServiceImpl;
 import com.ym.mec.util.collection.MapUtil;
 
-import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.*;
-import java.util.stream.Collectors;
-
-import static com.ym.mec.biz.dal.enums.ClientTypeEnum.SMART_PRACTICE;
-
 @Service
 public class SysMusicScoreServiceImpl extends BaseServiceImpl<Integer, SysMusicScore> implements SysMusicScoreService {
 	

+ 18 - 0
mec-biz/src/main/resources/config/mybatis/ClassGroupStudentMapperMapper.xml

@@ -24,6 +24,10 @@
         <result property="phone" column="phone_"/>
     </resultMap>
 
+    <resultMap id="ClassGroupStudentMapperDto" type="com.ym.mec.biz.dal.dto.ClassGroupStudentMapperDto" extends="ClassGroupStudentMapper">
+        <result property="teacherId" column="teacher_id_"/>
+    </resultMap>
+
     <!-- 根据主键查询一条记录 -->
     <select id="get" resultMap="ClassGroupStudentMapper">
 		SELECT * FROM class_group_student_mapper WHERE id_ = #{id} 
@@ -680,4 +684,18 @@
             AND cg.id_ IS NOT NULL
         ORDER BY cg.id_ DESC
     </select>
+    
+    <select id="queryByClassGroupType" resultMap="ClassGroupStudentMapperDto">
+    
+    	SELECT cgsm.*,cgtm.user_id_ teacher_id_ from class_group_student_mapper cgsm LEFT JOIN class_group cg on cgsm.class_group_id_ = cg.id_
+		LEFT JOIN class_group_teacher_mapper cgtm on cgsm.class_group_id_ = cgtm.class_group_id_
+		WHERE cgtm.music_group_id_ = #{musicGroupId} and cg.type_ = #{classGroupType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler} 
+        and cgtm.teacher_role_ = #{teacherRole,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler} and cg.del_flag_ = 0 and cgsm.status_ = 'NORMAL'
+		and cgsm.user_id_ IN
+                <foreach collection="studentIdList" item="studentId" open="(" close=")" separator=",">
+                    #{studentId}
+                </foreach>
+        group by cgsm.user_id_
+        
+    </select>
 </mapper>

+ 52 - 0
mec-biz/src/main/resources/config/mybatis/IndexBaseMonthDataMapper.xml

@@ -1873,4 +1873,56 @@
 		</if>
 		GROUP BY su.organ_id_
 	</select>
+	<select id="getStudentVipOrderNum"  resultMap="IndexBaseMonthData">
+		SELECT spo.create_time_ month_,spo.organ_id_,
+		       COUNT(DISTINCT spo.id_) total_num_,
+		       'STUDENT_VIP_ORDER_NUM' data_type_,spo.user_id_ extend_info_,spo.tenant_id_
+		FROM (SELECT id_,user_id_,organ_id_,activity_id_,music_group_id_,calender_id_,type_,group_type_,
+		             DATE_FORMAT(create_time_,'%Y-%m-%d') create_time_,tenant_id_ FROM student_payment_order
+		WHERE status_ = 'SUCCESS' AND DATE_FORMAT(create_time_,'%Y-%m-%d') = #{dayStr} AND tenant_id_ = #{tenantId}) spo
+		LEFT JOIN student_payment_order_detail spod ON spod.payment_order_id_ = spo.id_
+		LEFT JOIN vip_group_activity vga ON FIND_IN_SET(vga.id_,spo.activity_id_)
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+		LEFT JOIN vip_group vg ON vg.id_ = spo.music_group_id_
+		LEFT JOIN vip_group_category vgc1 ON vgc1.id_ = vg.vip_group_category_id_
+		LEFT JOIN music_group_payment_calender_activity mgpca ON mgpca.calender_id_ = spo.calender_id_
+		LEFT JOIN vip_group_activity vga1 ON vga1.id_ = mgpca.activity_id_
+		LEFT JOIN vip_group_category vgc2 ON vgc2.id_ = vga1.vip_group_category_id_list_
+		WHERE (spo.group_type_ = 'SPORADIC' AND spo.type_ = 'DEGREE_REGISTRATION' AND spod.type_ = 'DEGREE_REGISTRATION')
+		OR (spo.group_type_ = 'SPORADIC' AND spo.type_ = 'DOUBLE_ELEVEN2020') OR (spo.group_type_ = 'DEGREE' AND spod.type_ = 'VIP')
+		OR (spo.type_ = 'SMALL_CLASS_TO_BUY' AND vgc1.name_ != '乐理课') OR (spo.group_type_ = 'MUSIC' AND spod.type_ = 'VIP' AND vgc2.name_ != '乐理课')
+		OR (spo.type_ = 'DOUBLE_ELEVEN2021' AND vgc.name_ != '乐理课')
+		GROUP BY spo.user_id_,spo.create_time_,spo.organ_id_;
+	</select>
+	<select id="getStudentTheoryOrderNum" resultMap="IndexBaseMonthData">
+		SELECT spo.create_time_ month_,spo.organ_id_,
+			   COUNT(DISTINCT spo.id_) total_num_,
+			   'STUDENT_THEORY_ORDER_NUM' data_type_,spo.user_id_ extend_info_,spo.tenant_id_
+		FROM (SELECT id_,user_id_,organ_id_,activity_id_,music_group_id_,calender_id_,type_,group_type_,
+					 DATE_FORMAT(create_time_,'%Y-%m-%d') create_time_,tenant_id_ FROM student_payment_order
+			  WHERE status_ = 'SUCCESS' AND DATE_FORMAT(create_time_,'%Y-%m-%d') = #{dayStr} AND tenant_id_ = #{tenantId}) spo
+				 LEFT JOIN student_payment_order_detail spod ON spod.payment_order_id_ = spo.id_
+				 LEFT JOIN vip_group_activity vga ON FIND_IN_SET(vga.id_,spo.activity_id_)
+				 LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+				 LEFT JOIN vip_group vg ON vg.id_ = spo.music_group_id_
+				 LEFT JOIN vip_group_category vgc1 ON vgc1.id_ = vg.vip_group_category_id_
+				 LEFT JOIN music_group_payment_calender_activity mgpca ON mgpca.calender_id_ = spo.calender_id_
+				 LEFT JOIN vip_group_activity vga1 ON vga1.id_ = mgpca.activity_id_
+				 LEFT JOIN vip_group_category vgc2 ON vgc2.id_ = vga1.vip_group_category_id_list_
+		WHERE (spo.group_type_ = 'DEGREE' AND spod.type_ = 'THEORY_COURSE')
+		   OR (spo.type_ = 'SMALL_CLASS_TO_BUY' AND vgc1.name_ = '乐理课') OR (spo.group_type_ = 'MUSIC' AND spod.type_ = 'VIP' AND vgc2.name_ = '乐理课')
+		   OR (spo.type_ = 'DOUBLE_ELEVEN2021' AND vgc.name_ = '乐理课')
+		GROUP BY spo.user_id_,spo.create_time_,spo.organ_id_;
+	</select>
+	<select id="getStudentPracticeOrderNum" resultMap="IndexBaseMonthData">
+		SELECT spo.create_time_ month_,spo.organ_id_,
+			   COUNT(DISTINCT spo.id_) total_num_,
+			   'STUDENT_PRACTICE_ORDER_NUM' data_type_,spo.user_id_ extend_info_,spo.tenant_id_
+		FROM (SELECT id_,user_id_,organ_id_,activity_id_,music_group_id_,calender_id_,type_,group_type_,
+					 DATE_FORMAT(create_time_,'%Y-%m-%d') create_time_,tenant_id_ FROM student_payment_order
+			  WHERE status_ = 'SUCCESS' AND DATE_FORMAT(create_time_,'%Y-%m-%d') = #{dayStr} AND tenant_id_ = #{tenantId}) spo
+				 LEFT JOIN student_payment_order_detail spod ON spod.payment_order_id_ = spo.id_
+		WHERE spo.type_ = 'PRACTICE_GROUP_BUY' OR spo.type_ = 'PRACTICE_GROUP_RENEW' OR (spo.group_type_ = 'MUSIC' AND spod.type_ = 'PRACTICE')
+		GROUP BY spo.user_id_,spo.create_time_,spo.organ_id_;
+	</select>
 </mapper>

+ 6 - 2
mec-biz/src/main/resources/config/mybatis/MusicGroupMapper.xml

@@ -17,6 +17,7 @@
         <result column="create_time_" property="createTime"/>
         <result column="update_time_" property="updateTime"/>
         <result column="status_" property="status" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
+        <result column="extracurricular_teacher_" property="extracurricularTeacher" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
         <result column="bill_start_date_" property="billStartDate"/>
         <result column="improvent_classes_num_" property="improventClassesNum"/>
         <result column="enroll_classes_" property="enrollClasses"/>
@@ -107,7 +108,7 @@
                  settlement_type_, cooperation_organ_id_, enlightenment_course_time_,
                  parent_meeting_time_, img_, director_user_id_, is_classroom_lessons_, memo_, expect_start_group_date_,
                  ownership_type_, repair_user_id_, del_flag_, payment_valid_start_date_, payment_valid_end_date_,
-                 payment_pattern_, course_view_type_, transaction_teacher_id_,homework_push_flag_,member_course_show_flag_,tenant_id_,is_give_accessories_)
+                 payment_pattern_, course_view_type_, transaction_teacher_id_,homework_push_flag_,member_course_show_flag_,tenant_id_,is_give_accessories_,extracurricular_teacher_)
         VALUES (#{id}, #{name}, #{organId}, #{schoolId}, #{applyExpireDate}, #{preApplyExpireDate}, #{teamTeacherId},
                 #{educationalTeacherId},
                 #{chargeTypeId}, #{courseForm}, now(), now(),
@@ -119,7 +120,7 @@
                 #{isClassroomLessons}, #{memo}, #{expectStartGroupDate},
                 #{ownershipType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, #{repairUserId},
                 #{delFlag}, #{paymentValidStartDate}, #{paymentValidEndDate}, #{paymentPattern},
-                #{courseViewType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, #{transactionTeacherId},#{homeworkPushFlag},#{memberCourseShowFlag},#{tenantId},#{isGiveAccessories})
+                #{courseViewType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler}, #{transactionTeacherId},#{homeworkPushFlag},#{memberCourseShowFlag},#{tenantId},#{isGiveAccessories},#{extracurricularTeacher,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler})
     </insert>
 
     <!-- 根据主键查询一条记录 -->
@@ -234,6 +235,9 @@
             <if test="isGiveAccessories != null">
                 is_give_accessories_ = #{isGiveAccessories},
             </if>
+            <if test="extracurricularTeacher != null">
+                extracurricular_teacher_ = #{extracurricularTeacher,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
+            </if>
         </set>
         WHERE id_ = #{id}
     </update>

+ 33 - 0
mec-biz/src/main/resources/config/mybatis/SellOrderMapper.xml

@@ -615,8 +615,41 @@
         WHERE spo.id_ = #{orderId}
     </select>
 
+    <select id="queryFeeByType" resultType="com.ym.mec.biz.dal.dto.StudentPaymentOrderExportDto">
+        SELECT spo.id_,MAX(spo.actual_amount_)                                actualAmount,
+               SUM(IF(g.type_ = 'INSTRUMENT', so.actual_amount_, 0))  musicalFee,
+               SUM(IF((g.type_ = 'ACCESSORIES' || g.type_ = 'TEACHING' || g.type_ = 'STAFF')  AND g.name_ !='乐器维护',IFNULL(so.actual_amount_,0), 0)) teachingFee,
+               SUM(IF((g.type_ = 'ACCESSORIES' || g.type_ = 'TEACHING' || g.type_ = 'STAFF')  AND g.name_ ='乐器维护',IFNULL(so.actual_amount_,0), 0)) repairFee,
+               SUM(IF((g.type_= 'OTHER' || g.type_ IS NULL) ,IFNULL(so.actual_amount_,0), 0)) otherFee
+        FROM student_payment_order spo
+                 LEFT JOIN sell_order so ON spo.id_ = so.order_id_
+                 LEFT JOIN goods g ON IF(so.parent_goods_id_ IS NOT NULL,g.id_ = so.parent_goods_id_,g.id_ = so.goods_id_)
+        WHERE spo.id_ IN
+        <foreach collection="orderIdList" item="orderId" open="(" close=")" separator=",">
+            #{orderId}
+        </foreach>
+        GROUP BY spo.id_
+    </select>
+
     <select id="getChildRepair" resultType="decimal">
         SELECT IFNULL(SUM(actual_amount_),0) FROM sell_order WHERE order_id_ = #{orderId} AND goods_id_ = 76 AND parent_goods_id_ > 0
     </select>
 
+    <select id="queryChildRepair" resultType="java.util.Map">
+        SELECT order_id_ 'key',IFNULL(SUM(actual_amount_),0) 'value' FROM sell_order
+        WHERE goods_id_ = 76 AND parent_goods_id_ > 0 AND order_id_ IN
+        <foreach collection="orderIdList" item="orderId" open="(" close=")" separator=",">
+            #{orderId}
+        </foreach>
+        GROUP BY order_id_
+    </select>
+    <select id="sumOutOrderAmount" resultType="java.util.Map">
+        SELECT order_id_ 'key',SUM(actual_amount_) 'value' FROM sell_order
+        WHERE order_id_ IN
+        <foreach collection="outOrderList" item="orderId" open="(" close=")" separator=",">
+            #{orderId}
+        </foreach>
+        GROUP BY order_id_
+    </select>
+
 </mapper>

+ 106 - 0
mec-biz/src/main/resources/config/mybatis/StudentBasicInfoMapper.xml

@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!--
+这个文件是自动生成的。
+不要修改此文件。所有改动将在下次重新自动生成时丢失。
+-->
+<mapper namespace="com.ym.mec.biz.dal.dao.StudentBasicInfoDao">
+	
+	<resultMap type="com.ym.mec.biz.dal.entity.StudentBasicInfo" id="StudentBasicInfo">
+		<result column="user_id_" property="userId" />
+		<result column="user_name_" property="userName" />
+		<result column="phone_" property="phone" />
+		<result column="subject_id_" property="subjectId" />
+		<result column="subject_name_" property="subjectName" />
+		<result column="grade_" property="grade" />
+		<result column="organ_id_" property="organId" />
+		<result column="organ_name_" property="organName" />
+		<result column="cooperation_organ_id_" property="cooperationOrganId" />
+		<result column="cooperation_organ_name_" property="cooperationOrganName" />
+		<result column="subject_teacher_id_" property="subjectTeacherId" />
+		<result column="subject_teacher_name_" property="subjectTeacherName" />
+	</resultMap>
+	
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="StudentBasicInfo" >
+		SELECT * FROM student_basic_info WHERE user_id_ = #{userId} 
+	</select>
+	
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="StudentBasicInfo">
+		SELECT * FROM student_basic_info ORDER BY user_id_
+	</select>
+	
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.StudentBasicInfo" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		<!--
+		<selectKey resultClass="int" keyProperty="id" > 
+		SELECT SEQ_WSDEFINITION_ID.nextval AS ID FROM DUAL 
+		</selectKey>
+		-->
+		INSERT INTO student_basic_info (user_id_,user_name_,phone_,subject_id_,subject_name_,grade_,organ_id_,organ_name_,cooperation_organ_id_,cooperation_organ_name_,subject_teacher_id_,subject_teacher_name_) VALUES(#{userId},#{userName},#{phone},#{subjectId},#{subjectName},#{grade},#{organId},#{organName},#{cooperationOrganId},#{cooperationOrganName},#{subjectTeacherId},#{subjectTeacherName})
+	</insert>
+	
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.StudentBasicInfo">
+		UPDATE student_basic_info <set>
+			<if test="subjectId != null">
+			subject_id_ = #{subjectId},
+			</if>
+			<if test="subjectName != null">
+			subject_name_ = #{subjectName},
+			</if>
+			<if test="userId != null">
+			user_id_ = #{userId},
+			</if>
+			<if test="organId != null">
+			organ_id_ = #{organId},
+			</if>
+			<if test="subjectTeacherId != null">
+			subject_teacher_id_ = #{subjectTeacherId},
+			</if>
+			<if test="userName != null">
+			user_name_ = #{userName},
+			</if>
+			<if test="cooperationOrganId != null">
+			cooperation_organ_id_ = #{cooperationOrganId},
+			</if>
+			<if test="organName != null">
+			organ_name_ = #{organName},
+			</if>
+			<if test="phone != null">
+			phone_ = #{phone},
+			</if>
+			<if test="cooperationOrganName != null">
+			cooperation_organ_name_ = #{cooperationOrganName},
+			</if>
+			<if test="grade != null">
+			grade_ = #{grade},
+			</if>
+			<if test="subjectTeacherName != null">
+			subject_teacher_name_ = #{subjectTeacherName},
+			</if>
+		</set> WHERE user_id_ = #{userId}
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete" >
+		DELETE FROM student_basic_info WHERE user_id_ = #{userId} 
+	</delete>
+	
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="StudentBasicInfo" parameterType="map">
+		SELECT * FROM student_basic_info ORDER BY user_id_ <include refid="global.limit"/>
+	</select>
+	
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM student_basic_info
+	</select>
+    <select id="getMaxId" resultType="java.lang.Integer">
+		SELECT MAX(id_) FROM student_basic_info
+	</select>
+	<select id="updateSubjectTeacher" resultType="int">
+		SELECT updateSubjectTeacher()
+	</select>
+</mapper>

+ 3 - 7
mec-biz/src/main/resources/config/mybatis/StudentMapper.xml

@@ -605,7 +605,6 @@
     <select id="getStudentFutureCourseInfo" resultMap="StudentServeCourseDto">
         SELECT
             cssp.user_id_ student_id_,
-            stu.teacher_id_ lead_teacher_id_,
             cs.id_ course_schedule_id_,
             cs.group_type_,
             cs.music_group_id_,
@@ -617,14 +616,11 @@
             cs.teach_mode_
         FROM course_schedule_student_payment cssp
             LEFT JOIN course_schedule cs ON cssp.course_schedule_id_=cs.id_
-            LEFT JOIN student stu ON cssp.user_id_ = stu.user_id_
-        WHERE stu.service_tag_=1 and cssp.tenant_id_ = #{tenantId}
-            AND (stu.service_tag_update_time_ IS NULL OR stu.service_tag_update_time_&lt;#{nextMonday})
+        WHERE cssp.tenant_id_ = #{tenantId}
             AND (cs.del_flag_ IS NULL OR cs.del_flag_=0)
             AND (cs.new_course_id_ IS NULL OR cs.new_course_id_=cs.id_)
-            AND cs.class_date_&gt;=#{monday}
-            AND cs.type_ IN ('SINGLE', 'TRAINING_SINGLE', 'VIP', 'MIX', 'TRAINING_MIX', 'PRACTICE')
-            AND cssp.create_time_&lt;#{nextMonday}
+            AND cs.class_date_ between #{monday} and #{sunday}
+            AND cs.type_ IN ('SINGLE', 'TRAINING_SINGLE', 'MIX', 'TRAINING_MIX')
             <if test="studentIds!=null and studentIds.size()>0">
                 AND cssp.user_id_ IN
                 <foreach collection="studentIds" item="studentId" open="(" close=")" separator=",">

+ 4 - 0
mec-biz/src/main/resources/config/mybatis/StudentPaymentOrderMapper.xml

@@ -1056,6 +1056,10 @@
              student_payment_order_detail as b on a.id_ = b.payment_order_id_
         where order_no_ = #{orderNo}
     </select>
+    <select id="getStudentMusicOrderNum" resultType="int">
+        SELECT COUNT(0) FROM student_payment_order spo
+        WHERE spo.music_group_id_ = #{musicGroupId} AND spo.user_id_ = #{userId} AND group_type_ = 'MUSIC' AND status_ = 'SUCCESS' AND spo.id_ &lt; #{orderId}
+    </select>
 
 
 </mapper>

+ 13 - 8
mec-biz/src/main/resources/config/mybatis/StudentPaymentRouteOrderMapper.xml

@@ -28,6 +28,7 @@
         <result column="update_time_" property="updateTime"/>
         <result column="update_by_" property="updateBy"/>
         <result column="tenant_id_" property="tenantId"/>
+        <result column="type_" property="type" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
 
     <resultMap id="StudentPaymentRouteOrderDto" type="com.ym.mec.biz.dal.dto.StudentPaymentRouteOrderDto"
@@ -53,7 +54,9 @@
 
     <sql id="Base_Column_List">
         <!--@mbg.generated-->
-        id_, route_organ_id_, route_amount_,route_balance_amount_, mer_no_, order_no_, fee_flag_,user_id_,school_id_,trans_no_,pay_time_,sale_amount_,service_amount_,service_fee_,memo_,goods_json_,audit_status_,audit_comment_,calender_id_,create_time_,create_by_,update_time_,update_by_,tenant_id_
+        id_, route_organ_id_, route_amount_,route_balance_amount_, mer_no_, order_no_, fee_flag_,user_id_,
+school_id_,trans_no_,pay_time_,sale_amount_,service_amount_,service_fee_,memo_,goods_json_,audit_status_,audit_comment_,
+calender_id_,create_time_,create_by_,update_time_,update_by_,tenant_id_,type_
     </sql>
     <select id="get" parameterType="java.lang.Long" resultMap="StudentPaymentRouteOrderMap">
         <!--@mbg.generated-->
@@ -73,8 +76,12 @@
             parameterType="com.ym.mec.biz.dal.entity.StudentPaymentRouteOrder" useGeneratedKeys="true">
         <!--@mbg.generated-->
         insert into student_payment_route_order (route_organ_id_, route_amount_,route_balance_amount_, mer_no_,
-        order_no_, fee_flag_,user_id_,school_id_,trans_no_,pay_time_,sale_amount_,service_amount_,service_fee_,memo_,goods_json_,audit_status_,audit_comment_,calender_id_,create_time_,update_time_,create_by_,update_by_,tenant_id_)
-        values (#{routeOrganId}, #{routeAmount},#{routeBalanceAmount}, #{merNo}, #{orderNo}, #{feeFlag},#{userId},#{schoolId},#{transNo},#{payTime},#{saleAmount},#{serviceAmount},#{serviceFee},#{memo},#{goodsJson},#{auditStatus,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{auditComment},#{calenderId},#{createTime},#{updateTime},#{createBy},#{updateBy},#{tenantId})
+        order_no_, fee_flag_,user_id_,school_id_,trans_no_,pay_time_,sale_amount_,service_amount_,service_fee_,
+        memo_,goods_json_,audit_status_,audit_comment_,calender_id_,create_time_,update_time_,create_by_,update_by_,tenant_id_,type_)
+        values (#{routeOrganId}, #{routeAmount},#{routeBalanceAmount}, #{merNo}, #{orderNo}, #{feeFlag},#{userId},
+                #{schoolId},#{transNo},#{payTime},#{saleAmount},#{serviceAmount},#{serviceFee},#{memo},#{goodsJson},
+                #{auditStatus,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{auditComment},#{calenderId},
+                #{createTime},#{updateTime},#{createBy},#{updateBy},#{tenantId},#{type,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler})
     </insert>
     <update id="update" parameterType="com.ym.mec.biz.dal.entity.StudentPaymentRouteOrder">
         <!--@mbg.generated-->
@@ -130,9 +137,6 @@
             <if test="updateTime != null">
                 update_time_ = #{updateTime},
             </if>
-            <if test="createBy != null">
-                create_by_ = #{createBy},
-            </if>
             <if test="updateBy != null">
                 update_by_ = #{updateBy},
             </if>
@@ -145,7 +149,7 @@
         INSERT INTO student_payment_route_order
         (order_no_,route_organ_id_, route_amount_,route_balance_amount_, mer_no_,fee_flag_,user_id_,
         school_id_,trans_no_,pay_time_,sale_amount_,service_amount_,service_fee_,memo_,goods_json_,audit_status_,
-        audit_comment_,calender_id_,create_time_,update_time_,create_by_,update_by_,tenant_id_)
+        audit_comment_,calender_id_,create_time_,update_time_,create_by_,update_by_,tenant_id_,type_)
         VALUE
         <foreach collection="routeOrders" item="routeOrder" separator=",">
             (#{routeOrder.orderNo},#{routeOrder.routeOrganId},#{routeOrder.routeAmount},
@@ -153,7 +157,8 @@
             #{routeOrder.userId},#{routeOrder.schoolId},#{routeOrder.transNo},#{routeOrder.payTime},
             #{routeOrder.saleAmount},#{routeOrder.serviceAmount},#{routeOrder.serviceFee},#{routeOrder.memo},#{routeOrder.goodsJson},
             #{routeOrder.auditStatus,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},#{routeOrder.auditComment},
-            #{routeOrder.calenderId},NOW(),NOW(),#{routeOrder.createBy},#{routeOrder.updateBy},#{routeOrder.tenantId})
+            #{routeOrder.calenderId},NOW(),NOW(),#{routeOrder.createBy},#{routeOrder.updateBy},#{routeOrder.tenantId},
+            #{routeOrder.type,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler})
         </foreach>
     </insert>
 

+ 8 - 0
mec-biz/src/main/resources/config/mybatis/StudentRegistrationMapper.xml

@@ -1808,4 +1808,12 @@
         </foreach>
         GROUP BY sr.user_id_)
     </select>
+    
+    <select id="queryServiceStudentByMusicGroupStatus" resultMap="StudentRegistration">
+    	select sr.* from student_registration sr 
+    	left join music_group mg ON mg.id_ = sr.music_group_id_
+    	left join student s on s.user_id_ = sr.user_id_
+    	where s.service_tag_ = 1 AND (s.service_tag_update_time_ IS NULL OR s.service_tag_update_time_&lt;#{nextMonday})
+    	and sr.music_group_status_ = 'NORMAL' AND mg.status_ = 'PROGRESS' and sr.tenant_id_ = #{tenantId}
+    </select>
 </mapper>

+ 679 - 0
mec-biz/src/main/resources/config/mybatis/StudentStatisticsMapper.xml

@@ -0,0 +1,679 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<!--
+这个文件是自动生成的。
+不要修改此文件。所有改动将在下次重新自动生成时丢失。
+-->
+<mapper namespace="com.ym.mec.biz.dal.dao.StudentStatisticsDao">
+	
+	<resultMap type="com.ym.mec.biz.dal.entity.StudentStatistics" id="StudentStatistics">
+		<result column="id_" property="id" />
+		<result column="user_id_" property="userId" />
+		<result column="teacher_id_" property="teacherId" />
+		<result column="teacher_name_" property="teacherName" />
+		<result column="music_director_id_" property="musicDirectorId" />
+		<result column="music_director_name_" property="musicDirectorName" />
+		<result column="total_course_num_" property="totalCourseNum" />
+		<result column="over_course_num_" property="overCourseNum" />
+		<result column="sub_course_num_" property="subCourseNum" />
+		<result column="no_schedule_num_" property="noScheduleNum" />
+		<result column="first_course_time_" property="firstCourseTime" />
+		<result column="last_course_time_" property="lastCourseTime" />
+		<result column="lately_course_consumer_" property="latelyCourseConsumer" />
+		<result column="lately_year_course_consumer_" property="latelyYearCourseConsumer" />
+		<result column="visit_num_" property="visitNum" />
+		<result column="last_visit_status_" property="lastVisitStatus" />
+		<result column="visit_reason_" property="visitReason" />
+		<result column="last_visit_time_" property="lastVisitTime" />
+		<result column="not_start_course_fee_" property="notStartCourseFee" />
+		<result column="no_course_fee_" property="noCourseFee" />
+		<result column="preCourseFee" property="preCourseFee" />
+		<result column="first_order_time_" property="firstOrderTime" />
+		<result column="last_order_time_" property="lastOrderTime" />
+		<result column="order_num_" property="orderNum" />
+		<result column="group_type_" property="groupType" />
+	</resultMap>
+	
+	<!-- 根据主键查询一条记录 -->
+	<select id="get" resultMap="StudentStatistics" >
+		SELECT * FROM student_statistics WHERE id_ = #{id} 
+	</select>
+	
+	<!-- 全查询 -->
+	<select id="findAll" resultMap="StudentStatistics">
+		SELECT * FROM student_statistics ORDER BY id_
+	</select>
+
+	<!-- 向数据库增加一条记录 -->
+	<insert id="insert" parameterType="com.ym.mec.biz.dal.entity.StudentStatistics" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
+		INSERT INTO student_statistics (id_,user_id_,teacher_id_,teacher_name_,music_director_id_,
+		music_director_name_,total_course_num_,over_course_num_,sub_course_num_,
+		no_schedule_num_,first_course_time_,last_course_time_,lately_course_consumer_,
+		visit_num_,last_visit_status_,visit_reason_,last_visit_time_,not_start_course_fee_,no_course_fee_,first_order_time_,
+		last_order_time_,order_num_,group_type_)
+		VALUES(#{id},#{userId},#{teacherId},#{teacherName},#{musicDirectorId},#{musicDirectorName},
+		       #{totalCourseNum},#{overCourseNum},#{subCourseNum},#{noScheduleNum},#{firstCourseTime},#{lastCourseTime},
+		       #{latelyCourseConsumer},#{visitNum},#{lastVisitStatus},#{visitReason},#{lastVisitTime},#{notStartCourseFee},#{noCourseFee},#{firstOrderTime},
+		       #{lastOrderTime},#{orderNum},#{groupType})
+	</insert>
+
+	<!-- 根据主键查询一条记录 -->
+	<update id="update" parameterType="com.ym.mec.biz.dal.entity.StudentStatistics">
+		UPDATE student_statistics <set>
+		<if test="overCourseNum != null">
+		over_course_num_ = #{overCourseNum},
+		</if>
+		<if test="latelyCourseConsumer != null">
+		lately_course_consumer_ = #{latelyCourseConsumer},
+		</if>
+		<if test="lastCourseTime != null">
+		last_course_time_ = #{lastCourseTime},
+		</if>
+		<if test="totalCourseNum != null">
+		total_course_num_ = #{totalCourseNum},
+		</if>
+		<if test="musicDirectorName != null">
+		music_director_name_ = #{musicDirectorName},
+		</if>
+		<if test="visitNum != null">
+		visit_num_ = #{visitNum},
+		</if>
+		<if test="teacherName != null">
+		teacher_name_ = #{teacherName},
+		</if>
+		<if test="subCourseNum != null">
+		sub_course_num_ = #{subCourseNum},
+		</if>
+		<if test="lastVisitStatus != null">
+		last_visit_status_ = #{lastVisitStatus},
+		</if>
+		<if test="lastVisitTime != null">
+		last_visit_time_ = #{lastVisitTime},
+		</if>
+		<if test="teacherId != null">
+		teacher_id_ = #{teacherId},
+		</if>
+		<if test="musicDirectorId != null">
+		music_director_id_ = #{musicDirectorId},
+		</if>
+		<if test="lastOrderTime != null">
+		last_order_time_ = #{lastOrderTime},
+		</if>
+		<if test="firstOrderTime != null">
+		first_order_time_ = #{firstOrderTime},
+		</if>
+		<if test="orderNum != null">
+		order_num_ = #{orderNum},
+		</if>
+		<if test="groupType != null">
+		group_type_ = #{groupType},
+		</if>
+		<if test="visitReason != null">
+		visit_reason_ = #{visitReason},
+		</if>
+		<if test="notStartCourseFee != null">
+			not_start_course_fee_ = #{notStartCourseFee},
+		</if>
+		<if test="noCourseFee != null">
+			no_course_fee_ = #{noCourseFee},
+		</if>
+		<if test="noScheduleNum != null">
+		no_schedule_num_ = #{noScheduleNum},
+		</if>
+		<if test="firstCourseTime != null">
+		first_course_time_ = #{firstCourseTime},
+		</if>
+		</set> WHERE id_ = #{id}
+	</update>
+	<update id="clean">
+		UPDATE student_statistics ss SET ss.total_course_num_ = 0,ss.sub_course_num_ = 0,
+		ss.over_course_num_ = 0,ss.lately_course_consumer_ = 0,ss.lately_year_course_consumer_ = 0,
+		ss.no_course_fee_ = 0,ss.no_schedule_num_ = 0,ss.normal_group_num_ = 0,ss.not_start_course_fee_ = 0,
+		ss.teacher_id_ = NULL,ss.teacher_name_ = NULL,ss.music_director_id_ = NULL,ss.music_director_name_ = NULL
+	</update>
+	<update id="batchUpdate">
+		<foreach collection="statisticsList" item="bean" index="index" open="" close="" separator=";">
+			UPDATE student_statistics
+			<set>
+				<if test="bean.overCourseNum != null">
+					over_course_num_ = #{bean.overCourseNum},
+				</if>
+				<if test="bean.latelyCourseConsumer != null">
+					lately_course_consumer_ = #{bean.latelyCourseConsumer},
+				</if>
+				<if test="bean.lastCourseTime != null">
+					last_course_time_ = #{bean.lastCourseTime},
+				</if>
+				<if test="bean.totalCourseNum != null">
+					total_course_num_ = #{bean.totalCourseNum},
+				</if>
+				<if test="bean.musicDirectorName != null and bean.musicDirectorName != ''">
+					music_director_name_ = #{bean.musicDirectorName},
+				</if>
+				<if test="bean.teacherName != null and bean.teacherName != ''">
+					teacher_name_ = #{bean.teacherName},
+				</if>
+				<if test="bean.subCourseNum != null">
+					sub_course_num_ = #{bean.subCourseNum},
+				</if>
+				<if test="bean.teacherId != null">
+					teacher_id_ = #{bean.teacherId},
+				</if>
+				<if test="bean.musicDirectorId != null">
+					music_director_id_ = #{bean.musicDirectorId},
+				</if>
+				<if test="bean.notStartCourseFee != null">
+					not_start_course_fee_ = #{bean.notStartCourseFee},
+				</if>
+				<if test="bean.noCourseFee != null">
+					no_course_fee_ = #{bean.noCourseFee},
+				</if>
+				<if test="bean.noScheduleNum != null">
+					no_schedule_num_ = #{bean.noScheduleNum},
+				</if>
+				<if test="bean.firstCourseTime != null">
+					first_course_time_ = #{bean.firstCourseTime},
+				</if>
+				id_ = id_
+			</set> WHERE user_id_ = #{bean.userId} AND group_type_ = #{bean.groupType}
+		</foreach>
+	</update>
+
+	<!-- 根据主键删除一条记录 -->
+	<delete id="delete" >
+		DELETE FROM student_statistics WHERE id_ = #{id} 
+	</delete>
+	
+	<!-- 分页查询 -->
+	<select id="queryPage" resultMap="StudentStatistics" parameterType="map">
+		SELECT * FROM student_statistics ORDER BY id_ <include refid="global.limit"/>
+	</select>
+	
+	<!-- 查询当前表的总记录数 -->
+	<select id="queryCount" resultType="int">
+		SELECT COUNT(*) FROM student_statistics
+	</select>
+	<resultMap id="StudentStatisticsDto" type="com.ym.mec.biz.dal.dto.StudentStatisticsDto" extends="StudentStatistics">
+		<association property="studentBasicInfo" javaType="com.ym.mec.biz.dal.entity.StudentBasicInfo">
+			<result column="user_id_" property="userId" />
+			<result column="user_name_" property="userName" />
+			<result column="phone_" property="phone" />
+			<result column="subject_id_" property="subjectId" />
+			<result column="subject_name_" property="subjectName" />
+			<result column="grade_" property="grade" />
+			<result column="organ_id_" property="organId" />
+			<result column="organ_name_" property="organName" />
+			<result column="cooperation_organ_id_" property="cooperationOrganId" />
+			<result column="cooperation_organ_name_" property="cooperationOrganName" />
+			<result column="subject_teacher_id_" property="subjectTeacherId" />
+			<result column="subject_teacher_name_" property="subjectTeacherName" />
+			<result column="course_balance_" property="courseBalance" />
+			<result column="student_status_" property="studentStatus" />
+		</association>
+	</resultMap>
+	<sql id="queryStatisticsSql">
+		<where>
+			<if test="search != null and search != ''">
+				AND (sbi.user_id_ = #{search} OR sbi.user_name_ LIKE CONCAT('%',#{search},'%'))
+			</if>
+			<if test="subjectId != null">
+				AND sbi.subject_id_ = #{subjectId}
+			</if>
+			<if test="studentStatus != null and studentStatus != ''">
+				<if test="studentStatus == 'NORMAL'">
+					AND (ss.no_schedule_num_ > 0 OR ss.sub_course_num_ > 0) AND (ss.lately_year_course_consumer_ > 0 OR ss.over_course_num_ &lt;= 0)
+				</if>
+				<if test="studentStatus == 'SLEEPY'">
+					AND ss.over_course_num_ > 0 AND (ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0) AND ss.lately_year_course_consumer_ &lt;= 0
+				</if>
+				<if test="studentStatus == 'LOST'">
+					AND ss.over_course_num_ > 0 AND ss.sub_course_num_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0 AND suca.course_balance_ &lt;= 0
+				</if>
+				<if test="studentStatus == 'PAUSE'">
+					AND suca.course_balance_ > 0 AND ss.sub_course_num_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0
+				</if>
+			</if>
+			<if test="studentStatus == null or studentStatus == ''">
+				AND (ss.over_course_num_ > 0 OR ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0 OR suca.course_balance_ > 0)
+			</if>
+			<if test="feedbackType != null and feedbackType != ''">
+				AND ss.last_visit_status_ = #{feedbackType}
+			</if>
+			<if test="latelyCourseConsumer != null">
+				AND ss.lately_course_consumer_ = #{latelyCourseConsumer}
+			</if>
+			<if test="latelyYearCourseConsumer != null">
+				AND ss.lately_year_course_consumer_ = #{latelyYearCourseConsumer}
+			</if>
+			<if test="visitNum != null">
+				AND ss.visit_num_ = #{visitNum}
+			</if>
+			<if test="teacherId != null">
+				AND ss.teacher_id_ = #{teacherId}
+			</if>
+			<if test="subjectTeacherId != null">
+				AND sbi.subject_teacher_id_ = #{subjectTeacherId}
+			</if>
+			<if test="musicDirectorId != null">
+				AND ss.music_director_id_ = #{musicDirectorId}
+			</if>
+			<if test="courseConsumerError != null and courseConsumerError == true">
+				AND ss.lately_course_consumer_ &lt; 4
+			</if>
+			<if test="courseConsumerError != null and courseConsumerError == false">
+				AND ss.lately_course_consumer_ >= 4
+			</if>
+			<if test="firstCourseStartTime != null">
+				AND ss.first_course_time_ >= #{firstCourseStartTime}
+			</if>
+			<if test="firstCourseEndTime != null">
+				AND ss.first_course_time_ &lt;= #{firstCourseEndTime}
+			</if>
+			<if test="groupType != null and groupType != ''">
+				AND ss.group_type_ = #{groupType}
+			</if>
+			<if test="organIdList != null and organIdList.size > 0">
+				AND sbi.organ_id_ IN
+				<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+					#{organId}
+				</foreach>
+			</if>
+		</where>
+	</sql>
+	<select id="countStatistics" resultType="java.lang.Integer">
+		SELECT COUNT(sbi.id_) FROM student_basic_info sbi
+		LEFT JOIN student_statistics ss ON ss.user_id_ = sbi.user_id_
+		LEFT JOIN sys_user_cash_account suca ON sbi.user_id_ = suca.user_id_
+		<include refid="queryStatisticsSql"/>
+	</select>
+	<select id="queryStatistics" resultMap="StudentStatisticsDto">
+		SELECT *,ss.not_start_course_fee_ + ss.no_course_fee_ preCourseFee,
+		CASE WHEN (ss.no_schedule_num_ > 0 OR ss.sub_course_num_ > 0) AND (ss.lately_year_course_consumer_ > 0 OR ss.over_course_num_ &lt;= 0) THEN '在读'
+		WHEN ss.over_course_num_ > 0 AND (ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0) AND ss.lately_year_course_consumer_ &lt;= 0 THEN '沉睡'
+		WHEN ss.over_course_num_ > 0 AND ss.sub_course_num_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0 AND suca.course_balance_ &lt;= 0 THEN '流失'
+		WHEN suca.course_balance_ > 0 AND ss.sub_course_num_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0 THEN '暂停' ELSE '其他' END student_status_
+		,suca.course_balance_
+		FROM student_basic_info sbi
+		LEFT JOIN student_statistics ss ON ss.user_id_ = sbi.user_id_
+		LEFT JOIN sys_user_cash_account suca ON sbi.user_id_ = suca.user_id_
+		<include refid="queryStatisticsSql"/>
+		<include refid="global.limit"/>
+	</select>
+	<resultMap id="StudentStatisticsSumDto" type="com.ym.mec.biz.dal.dto.StudentStatisticsSumDto">
+		<result property="sleepStudentNum" column="sleepStudentNum"/>
+		<result property="sleepStudentHasNotSchedule" column="sleepStudentHasNotSchedule"/>
+		<result property="sleepStudentNoNotSchedule" column="sleepStudentNoNotSchedule"/>
+		<result property="normalStudentNum" column="normalStudentNum"/>
+		<result property="normalStudentHasNormalGroupNum" column="normalStudentHasNormalGroupNum"/>
+		<result property="hasCourseBalanceAndNotSubCourseNum" column="hasCourseBalanceAndNotSubCourseNum"/>
+		<result property="normalStudentHasNoScheduleNum" column="normalStudentHasNoScheduleNum"/>
+		<result property="waitRenewNum" column="waitRenewNum"/>
+		<result property="subCourseNum" column="subCourseNum"/>
+		<result property="noScheduleNum" column="noScheduleNum"/>
+	</resultMap>
+	<select id="studentSmallClassStatisticsSum" resultMap="StudentStatisticsSumDto">
+		SELECT
+		COUNT(CASE WHEN ss.over_course_num_ > 0 AND (ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0) AND ss.lately_year_course_consumer_ &lt;= 0 THEN 1 ELSE NULL END) 'sleepStudentNum',
+		COUNT(CASE WHEN ss.over_course_num_ > 0 AND (ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0) AND ss.lately_year_course_consumer_ &lt;= 0 AND ss.no_schedule_num_ > 0 THEN 1 ELSE NULL END) 'sleepStudentHasNotSchedule',
+		COUNT(CASE WHEN ss.over_course_num_ > 0 AND (ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0) AND ss.lately_year_course_consumer_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0 THEN 1 ELSE NULL END) 'sleepStudentNoNotSchedule',
+		COUNT(CASE WHEN (ss.no_schedule_num_ > 0 OR ss.sub_course_num_ > 0) AND (ss.lately_year_course_consumer_ > 0 OR ss.over_course_num_ &lt;= 0) THEN 1 ELSE NULL END) 'normalStudentNum',
+		COUNT(CASE WHEN ((ss.no_schedule_num_ > 0 OR ss.sub_course_num_ > 0) AND (ss.lately_year_course_consumer_ > 0 OR ss.over_course_num_ &lt;= 0)) AND ss.normal_group_num_ > 0 THEN 1 ELSE NULL END) 'normalStudentHasNormalGroupNum',
+		COUNT(CASE WHEN suca.course_balance_ > 0 AND ss.sub_course_num_ &lt;= 0 AND ss.no_schedule_num_ &lt;= 0 THEN 1 ELSE NULL END) 'hasCourseBalanceAndNotSubCourseNum',
+		COUNT(CASE WHEN ((ss.no_schedule_num_ > 0 OR ss.sub_course_num_ > 0) AND (ss.lately_year_course_consumer_ > 0 OR ss.over_course_num_ &lt;= 0)) AND ss.no_schedule_num_ > 0 THEN 1 ELSE NULL END) 'normalStudentHasNoScheduleNum',
+		COUNT(CASE WHEN (ss.no_schedule_num_ + ss.sub_course_num_) &lt; 4 THEN 1 ELSE NULL END) 'waitRenewNum',
+		SUM(ss.sub_course_num_) 'subCourseNum',
+		SUM(ss.no_schedule_num_) 'noScheduleNum'
+		FROM student_statistics ss
+		LEFT JOIN sys_user_cash_account suca ON ss.user_id_ = suca.user_id_
+		LEFT JOIN student_basic_info sbi ON ss.user_id_ = sbi.user_id_
+		WHERE ss.group_type_ = #{groupType}
+		AND (ss.over_course_num_ > 0 OR ss.sub_course_num_ > 0 OR ss.no_schedule_num_ > 0 OR suca.course_balance_ > 0)
+		<if test="organIdList != null and organIdList.size > 0">
+			AND sbi.organ_id_ IN
+			<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+				#{organId}
+			</foreach>
+		</if>
+	</select>
+    <select id="countAddStudentNum" resultType="java.lang.Integer">
+		SELECT COUNT(extend_info_) FROM (
+		SELECT extend_info_ FROM index_base_month_data
+		WHERE data_type_ =
+		<if test="groupType == 'VIP'">
+			'STUDENT_VIP_ORDER_NUM'
+		</if>
+		<if test="groupType == 'THEORY'">
+			'STUDENT_THEORY_ORDER_NUM'
+		</if>
+		<if test="groupType == 'PRACTICE'">
+			'STUDENT_PRACTICE_ORDER_NUM'
+		</if>
+		AND extend_info_ IS NOT NULL
+		<if test="organIdList != null and organIdList.size > 0">
+			AND organ_id_ IN
+			<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+				#{organId}
+			</foreach>
+		</if>
+		GROUP BY extend_info_
+		<if test="startDate != null and startDate != '' and endDate != null and endDate != ''">
+			HAVING COUNT(CASE WHEN month_ &lt; #{startDate} THEN 1 ELSE NULL END) &lt; 1
+			AND COUNT(CASE WHEN month_ BETWEEN #{startDate} AND #{endDate} THEN 1 ELSE NULL END) > 0
+		</if>
+		)a
+	</select>
+	<select id="countRenewStudentNum" resultType="java.lang.Integer">
+		SELECT COUNT(extend_info_) FROM (
+		SELECT extend_info_ FROM index_base_month_data
+		<include refid="dateTypeSql"/>
+			AND extend_info_ IS NOT NULL
+		<if test="endDate != null and endDate != ''">
+			AND month_ &lt;= #{endDate}
+		</if>
+		<if test="organIdList != null and organIdList.size > 0">
+			AND organ_id_ IN
+			<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+				#{organId}
+			</foreach>
+		</if>
+		GROUP BY extend_info_
+		HAVING SUM(total_num_) > 1)a
+	</select>
+	<select id="countVisitNum" resultType="java.lang.Integer">
+		SELECT COUNT(DISTINCT student_id_) FROM student_visit
+		WHERE type_ = '小课回访' AND purpose_ =
+		<if test="groupType == 'VIP'">
+			'VIP课回访'
+		</if>
+		<if test="groupType == 'THEORY'">
+			'乐理课回访'
+		</if>
+		<if test="groupType == 'PRACTICE'">
+			'网管课回访'
+		</if>
+		<if test="startDate != null and startDate != ''">
+			AND visit_time_ >= #{startDate}
+		</if>
+		<if test="endDate != null and endDate != ''">
+			AND visit_time_ &lt;= #{endDate}
+		</if>
+		<if test="organIdList != null and organIdList.size > 0">
+			AND organ_id_ IN
+			<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+				#{organId}
+			</foreach>
+		</if>
+	</select>
+	<select id="countLostStudentNum" resultType="java.lang.Integer">
+		SELECT COUNT(ss.id_) FROM student_statistics ss
+		LEFT JOIN student_basic_info sbi ON ss.user_id_ = sbi.user_id_
+		WHERE ss.group_type_ = #{groupType} AND ss.last_visit_status_ = 'LOST'
+		<if test="startDate != null and startDate != ''">
+			AND ss.last_visit_time_ >= #{startDate}
+		</if>
+		<if test="endDate != null and endDate != ''">
+			AND ss.last_visit_time_ &lt;= #{endDate}
+		</if>
+		<if test="organIdList != null and organIdList.size > 0">
+			AND sbi.organ_id_ IN
+			<foreach collection="organIdList" item="organId" open="(" close=")" separator=",">
+				#{organId}
+			</foreach>
+		</if>
+	</select>
+	<select id="queryTeacherIds" resultType="java.lang.Integer">
+		SELECT DISTINCT teacher_id_ FROM student_statistics WHERE group_type_ = #{groupType} AND teacher_id_ IS NOT NULL
+	</select>
+	<select id="queryDirectorList" resultType="java.lang.Integer">
+		SELECT DISTINCT music_director_id_ FROM student_statistics WHERE group_type_ = #{groupType} AND music_director_id_ IS NOT NULL
+	</select>
+	<select id="queryStatisticsTeacherAndEdu" resultMap="com.ym.mec.biz.dal.dao.StudentStatisticsDao.StudentStatistics">
+		SELECT et.user_id_,et.actual_teacher_id_ teacher_id_,su.real_name_ teacher_name_,et.educational_teacher_id_ music_director_id_,su1.real_name_ music_director_name_,'PRACTICE' group_type_
+		FROM ( SELECT cs.actual_teacher_id_,ct.user_id_,pg.educational_teacher_id_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		LEFT JOIN (SELECT cssp.user_id_,MAX(cs.class_date_) class_date_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		WHERE cs.status_ = 'OVER' AND cssp.group_type_ = 'PRACTICE'
+		GROUP BY cssp.user_id_) ct ON ct.user_id_ = cssp.user_id_
+		LEFT JOIN practice_group pg ON pg.id_ = cssp.music_group_id_
+		WHERE cs.class_date_ = ct.class_date_ AND cs.status_ = 'OVER' AND cssp.group_type_ = 'PRACTICE'
+		GROUP BY ct.user_id_) et
+		LEFT JOIN sys_user su ON su.id_ = et.actual_teacher_id_
+		LEFT JOIN sys_user su1 ON su1.id_ = et.educational_teacher_id_
+		GROUP BY et.user_id_
+		UNION ALL
+		SELECT et.user_id_,et.actual_teacher_id_ teacher_id_,su.real_name_ teacher_name_,et.educational_teacher_id_ music_director_id_,su1.real_name_ music_director_name_,'THEORY' group_type_
+		FROM (SELECT cs.actual_teacher_id_,ct.user_id_,vg.educational_teacher_id_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		LEFT JOIN (SELECT cssp.user_id_,MAX(cs.class_date_) class_date_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ = '乐理课' AND cs.status_ = 'OVER' AND cssp.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_) ct ON ct.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ = '乐理课' AND cs.class_date_ = ct.class_date_ AND cs.status_ = 'OVER' AND cssp.group_type_ = 'VIP'
+		GROUP BY ct.user_id_) et
+		LEFT JOIN sys_user su ON su.id_ = et.actual_teacher_id_
+		LEFT JOIN sys_user su1 ON su1.id_ = et.educational_teacher_id_
+		GROUP BY et.user_id_
+		UNION ALL
+		SELECT et.user_id_,et.actual_teacher_id_ teacher_id_,su.real_name_ teacher_name_,et.educational_teacher_id_ music_director_id_,su1.real_name_ music_director_name_,'VIP' group_type_
+		FROM (SELECT cs.actual_teacher_id_,ct.user_id_,vg.educational_teacher_id_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		LEFT JOIN (SELECT cssp.user_id_,MAX(cs.class_date_) class_date_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ != '乐理课' AND cs.status_ = 'OVER' AND cssp.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_) ct ON ct.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ != '乐理课' AND cs.class_date_ = ct.class_date_ AND cs.status_ = 'OVER' AND cssp.group_type_ = 'VIP'
+		GROUP BY ct.user_id_) et
+		LEFT JOIN sys_user su ON su.id_ = et.actual_teacher_id_
+		LEFT JOIN sys_user su1 ON su1.id_ = et.educational_teacher_id_
+		GROUP BY et.user_id_
+	</select>
+	<select id="queryStatisticsTeacherAndEdu2" resultMap="StudentStatistics">
+		SELECT ss.user_id_,pg.user_id_ teacher_id_,su.real_name_ teacher_name_,'' music_director_id_,'' music_director_name_,'PRACTICE' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN practice_group pg ON pg.id_ = cssp.music_group_id_
+		LEFT JOIN sys_user su ON su.id_ = pg.user_id_
+		WHERE cssp.group_type_ = 'PRACTICE' AND pg.group_status_ = 'NORMAL' AND ss.teacher_id_ IS NULL
+		UNION ALL
+		SELECT ss.user_id_,'' teacher_id_,'' teacher_name_,pg.educational_teacher_id_ music_director_id_,su.real_name_ music_director_name_,'PRACTICE' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN practice_group pg ON pg.id_ = cssp.music_group_id_
+		LEFT JOIN sys_user su ON su.id_ = pg.educational_teacher_id_
+		WHERE cssp.group_type_ = 'PRACTICE' AND pg.group_status_ = 'NORMAL' AND ss.music_director_id_ IS NULL
+		UNION ALL
+		SELECT ss.user_id_,vg.user_id_ teacher_id_,su.real_name_ teacher_name_,'' music_director_id_,'' music_director_name_,'THEORY' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		LEFT JOIN sys_user su ON su.id_ = vg.user_id_
+		WHERE vgc.name_ = '乐理课' AND cssp.group_type_ = 'THEORY' AND vg.group_status_ = 2 AND ss.teacher_id_ IS NULL
+		UNION ALL
+		SELECT ss.user_id_,'' teacher_id_,'' teacher_name_,vg.educational_teacher_id_ music_director_id_,su.real_name_ music_director_name_,'THEORY' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		LEFT JOIN sys_user su ON su.id_ = vg.educational_teacher_id_
+		WHERE vgc.name_ = '乐理课' AND cssp.group_type_ = 'THEORY' AND vg.group_status_ = 2 AND ss.music_director_id_ IS NULL
+		UNION ALL
+		SELECT ss.user_id_,vg.user_id_ teacher_id_,su.real_name_ teacher_name_,'' music_director_id_,'' music_director_name_,'VIP' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		LEFT JOIN sys_user su ON su.id_ = vg.user_id_
+		WHERE vgc.name_ != '乐理课' AND cssp.group_type_ = 'VIP' AND vg.group_status_ = 2 AND ss.teacher_id_ IS NULL
+		UNION ALL
+		SELECT ss.user_id_,'' teacher_id_,'' teacher_name_,vg.educational_teacher_id_ music_director_id_,su.real_name_ music_director_name_,'VIP' group_type_ FROM student_statistics ss
+		LEFT JOIN course_schedule_student_payment cssp ON ss.user_id_ = cssp.user_id_
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		LEFT JOIN sys_user su ON su.id_ = vg.educational_teacher_id_
+		WHERE vgc.name_ != '乐理课' AND cssp.group_type_ = 'VIP' AND vg.group_status_ = 2 AND ss.music_director_id_ IS NULL
+	</select>
+	<select id="queryStatisticsCourseNum" resultMap="StudentStatistics">
+		SELECT cssp.user_id_,COUNT(cssp.course_schedule_id_) total_course_num_,COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN 1 ELSE NULL END) sub_course_num_,
+		COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN NULL ELSE 1 END) over_course_num_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 30 DAY),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_course_consumer_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 YEAR),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_year_course_consumer_,'PRACTICE' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		WHERE cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cssp.group_type_ = 'PRACTICE'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,COUNT(cssp.course_schedule_id_) total_course_num_,COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN 1 ELSE NULL END) sub_course_num_,
+		COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN NULL ELSE 1 END) over_course_num_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 30 DAY),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_course_consumer_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 YEAR),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_year_course_consumer_,'THEORY' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ = '乐理课' AND cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cs.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,COUNT(cssp.course_schedule_id_) total_course_num_,COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN 1 ELSE NULL END) sub_course_num_,
+		COUNT(CASE WHEN cs.status_ = 'NOT_START' THEN NULL ELSE 1 END) over_course_num_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 30 DAY),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_course_consumer_,
+		COUNT(CASE WHEN cs.status_ != 'NOT_START' AND cs.class_date_ >= DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 YEAR),'%Y-%m-%d') THEN 1 ELSE NULL END) lately_year_course_consumer_,'VIP' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ != '乐理课' AND cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cs.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+	</select>
+	<select id="queryStatisticsNoCourseNum" resultMap="StudentStatistics">
+		SELECT aum.user_id_,SUM(CASE WHEN aum.practice_flag_ = 1 THEN vga.min_course_num_ ELSE 0 END +
+		CASE WHEN aum.give_practice_flag_ = 1 THEN vga.give_course_num_ ELSE 0 END) no_schedule_num_,'PRACTICE' group_type_ FROM activity_user_mapper aum
+		LEFT JOIN vip_group_activity vga ON vga.id_ = aum.activity_id_
+		WHERE aum.return_fee_ = 0 AND (aum.practice_flag_ = 1 OR aum.give_practice_flag_ = 1)
+		GROUP BY aum.user_id_
+		UNION ALL
+		SELECT a.user_id_,SUM(a.no_schedule_num_) no_schedule_num_,'THEORY' group_type_ FROM (
+		SELECT aum.user_id_,SUM(CASE WHEN aum.vip_flag_ = 1 AND vgc.name_ = '乐理课' THEN vga.min_course_num_ ELSE 0 END +
+		CASE WHEN aum.give_vip_flag_ = 1 AND vgc1.name_ = '乐理课' THEN vga.give_course_num_ ELSE 0 END) no_schedule_num_ FROM activity_user_mapper aum
+		LEFT JOIN vip_group_activity vga ON vga.id_ = aum.activity_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+		LEFT JOIN vip_group_category vgc1 ON vgc1.id_ = vga.give_category_id_
+		WHERE aum.return_fee_ = 0 AND ((aum.vip_flag_ = 1 AND vgc.name_ = '乐理课') OR (aum.give_vip_flag_ = 1 AND vgc1.name_ = '乐理课'))
+		GROUP BY aum.user_id_
+		UNION ALL
+		SELECT user_id_,10 no_schedule_num_ FROM student WHERE activity_course_detail_ LIKE CONCAT('%','"music_theory": 1','%')) a
+		GROUP BY a.user_id_
+		UNION ALL
+		SELECT a.user_id_,SUM(a.no_schedule_num_) no_schedule_num_,'VIP' group_type_ FROM (
+		SELECT aum.user_id_,SUM(CASE WHEN aum.vip_flag_ = 1 AND vgc.name_ != '乐理课' THEN vga.min_course_num_ ELSE 0 END +
+		CASE WHEN aum.give_vip_flag_ = 1  AND vgc1.name_ != '乐理课' THEN vga.give_course_num_ ELSE 0 END) no_schedule_num_ FROM activity_user_mapper aum
+		LEFT JOIN vip_group_activity vga ON vga.id_ = aum.activity_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+		LEFT JOIN vip_group_category vgc1 ON vgc1.id_ = vga.give_category_id_
+		WHERE aum.return_fee_ = 0 AND ((aum.vip_flag_ = 1 AND vgc.name_ != '乐理课') OR (aum.give_vip_flag_ = 1 AND vgc1.name_ != '乐理课'))
+		GROUP BY aum.user_id_
+		UNION ALL
+		SELECT user_id_,12 no_schedule_num_ FROM student WHERE activity_course_detail_ LIKE CONCAT('%','"vip1": 1','%')
+		UNION ALL
+		SELECT user_id_,12 no_schedule_num_ FROM student WHERE activity_course_detail_ LIKE CONCAT('%','"vip2": 1','%')) a
+		GROUP BY a.user_id_
+	</select>
+	<select id="queryStatisticsNotStartCourseFee" resultMap="StudentStatistics">
+		SELECT cssp.user_id_,SUM(cssp.expect_price_) not_start_course_fee_,'PRACTICE' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		WHERE cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cs.group_type_ = 'PRACTICE' AND cs.status_ = 'NOT_START'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,SUM(cssp.expect_price_) not_start_course_fee_,'THEORY' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cs.group_type_ = 'VIP' AND cs.status_ = 'NOT_START' AND vgc.name_ = '乐理课'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,SUM(cssp.expect_price_) not_start_course_fee_,'VIP' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE cs.del_flag_ = 0 AND cs.pre_course_flag_ = 0 AND cs.group_type_ = 'VIP' AND cs.status_ = 'NOT_START' AND vgc.name_ != '乐理课'
+		GROUP BY cssp.user_id_
+	</select>
+	<select id="queryStatisticsNoCourseFee" resultMap="StudentStatistics">
+		SELECT aum.user_id_,SUM(aum.actual_price_) no_course_fee_,'PRACTICE' group_type_ FROM activity_user_mapper aum
+		WHERE aum.practice_flag_ = 1 AND return_fee_ = 0
+		GROUP BY aum.user_id_
+		UNION ALL
+		SELECT aum.user_id_,SUM(aum.actual_price_) no_course_fee_,'THEORY' group_type_ FROM activity_user_mapper aum
+		LEFT JOIN vip_group_activity vga ON vga.id_ = aum.activity_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+		WHERE aum.vip_flag_ = 1 AND return_fee_ = 0 AND vgc.name_ = '乐理课'
+		GROUP BY aum.user_id_
+		UNION ALL
+		SELECT aum.user_id_,SUM(aum.actual_price_) no_course_fee_,'VIP' group_type_ FROM activity_user_mapper aum
+		LEFT JOIN vip_group_activity vga ON vga.id_ = aum.activity_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vga.vip_group_category_id_list_
+		WHERE aum.vip_flag_ = 1 AND return_fee_ = 0 AND vgc.name_ != '乐理课'
+		GROUP BY aum.user_id_
+	</select>
+	<select id="queryStatisticsFirstAndLastCourseTime"
+			resultMap="StudentStatistics">
+		SELECT cssp.user_id_,MIN(cs.class_date_) first_course_time_,MAX(cs.class_date_) last_course_time_,'PRACTICE' group_type_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		WHERE cs.status_ = 'OVER' AND cssp.group_type_ = 'PRACTICE'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,MIN(cs.class_date_) first_course_time_,MAX(cs.class_date_) last_course_time_,'THEORY' group_type_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ = '乐理课' AND cs.status_ = 'OVER' AND cs.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,MIN(cs.class_date_) first_course_time_,MAX(cs.class_date_) last_course_time_,'VIP' group_type_ FROM course_schedule_student_payment cssp
+		LEFT JOIN course_schedule cs ON cs.id_ = cssp.course_schedule_id_ AND cs.group_type_ = cssp.group_type_
+		LEFT JOIN vip_group vg ON vg.id_ = cs.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ != '乐理课' AND cs.status_ = 'OVER' AND cs.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+	</select>
+	<select id="queryStatisticsNormalGroupNum" resultMap="StudentStatistics">
+		SELECT cssp.user_id_,COUNT(DISTINCT pg.id_) normal_group_num_,'PRACTICE' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN practice_group pg ON pg.id_ = cssp.music_group_id_
+		WHERE pg.group_status_ = 'NORMAL' AND cssp.group_type_ = 'PRACTICE'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,COUNT(DISTINCT vg.id_) normal_group_num_,'THEORY' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ = '乐理课' AND vg.group_status_ = 2 AND cssp.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+		UNION ALL
+		SELECT cssp.user_id_,COUNT(DISTINCT vg.id_) normal_group_num_,'VIP' group_type_
+		FROM course_schedule_student_payment cssp
+		LEFT JOIN vip_group vg ON vg.id_ = cssp.music_group_id_
+		LEFT JOIN vip_group_category vgc ON vgc.id_ = vg.vip_group_category_id_
+		WHERE vgc.name_ != '乐理课' AND vg.group_status_ = 2 AND cssp.group_type_ = 'VIP'
+		GROUP BY cssp.user_id_
+	</select>
+	<sql id="dateTypeSql">
+		WHERE data_type_ =
+		<if test="groupType == 'VIP'">
+			'STUDENT_VIP_ORDER_NUM'
+		</if>
+		<if test="groupType == 'THEORY'">
+			'STUDENT_THEORY_ORDER_NUM'
+		</if>
+		<if test="groupType == 'PRACTICE'">
+			'STUDENT_PRACTICE_ORDER_NUM'
+		</if>
+	</sql>
+</mapper>

+ 11 - 3
mec-biz/src/main/resources/config/mybatis/StudentVisitMapper.xml

@@ -11,7 +11,7 @@
         <result column="studentName" property="studentName"/>
         <result column="teacher_id_" property="teacherId"/>
         <result column="teacherName" property="teacherName"/>
-        <result column="visiter_type_" property="visiterType"/>
+        <result column="visiter_type_" property="visiterType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
         <result column="type_" property="type"/>
         <result column="purpose_" property="purpose"/>
         <result column="overview_" property="overview"/>
@@ -20,11 +20,12 @@
         <result column="create_time_" property="createTime"/>
         <result column="object_id_" property="objectId"/>
         <result column="tenant_id_" property="tenantId"/>
+        <result column="feedback_type_" property="feedbackType" typeHandler="com.ym.mec.common.dal.CustomEnumTypeHandler"/>
     </resultMap>
     <sql id="Base_Column_List">
         <!--@mbg.generated-->
         id_, music_group_id_, organ_id_, student_id_, teacher_id_, visiter_type_, type_, purpose_, overview_, feedback_,
-        visit_time_, create_time_,tenant_id_
+        visit_time_, create_time_,tenant_id_,feedback_type_
     </sql>
     <select id="get" parameterType="java.lang.Integer" resultMap="StudentVisit">
         select
@@ -40,11 +41,12 @@
     <insert id="insert" keyColumn="id_" keyProperty="id" parameterType="com.ym.mec.biz.dal.entity.StudentVisit"
             useGeneratedKeys="true">
         <!--@mbg.generated-->
-        insert into student_visit (music_group_id_, organ_id_, student_id_, teacher_id_, visiter_type_,
+        insert into student_visit (music_group_id_, organ_id_, student_id_, teacher_id_, visiter_type_, feedback_type_,
         type_, purpose_, overview_,
         feedback_, visit_time_, create_time_,object_id_,tenant_id_)
         values (#{musicGroupId,jdbcType=VARCHAR}, #{organId,jdbcType=INTEGER}, #{studentId,jdbcType=INTEGER},
         #{teacherId,jdbcType=INTEGER},#{visiterType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
+                #{feedbackType,typeHandler=com.ym.mec.common.dal.CustomEnumTypeHandler},
         #{type,jdbcType=VARCHAR}, #{purpose,jdbcType=VARCHAR}, #{overview,jdbcType=VARCHAR},
         #{feedback,jdbcType=VARCHAR}, #{visitTime}, #{createTime},#{objectId},#{tenantId})
     </insert>
@@ -116,6 +118,9 @@
             <if test="teacherId !=null">
                 AND sv.teacher_id_ = #{teacherId}
             </if>
+            <if test="studentId !=null">
+                AND sv.student_id_ = #{studentId}
+            </if>
             <if test="organId != null and organId != ''">
                 AND FIND_IN_SET(sv.organ_id_,#{organId})
             </if>
@@ -125,6 +130,9 @@
             <if test="type != null">
                 AND sv.type_ = #{type}
             </if>
+            <if test="feedbackType != null and feedbackType != ''">
+                AND sv.feedback_type_ = #{feedbackType}
+            </if>
             <if test="purpose != null">
                 AND sv.purpose_ = #{purpose}
             </if>

+ 3 - 3
mec-biz/src/main/resources/config/mybatis/SysMusicCompareRecordMapper.xml

@@ -418,9 +418,9 @@
 			COUNT(smcr.id_) trainNum,
 			COUNT(DISTINCT DATE(smcr.create_time_)) trainDays,
 			SUM(smcr.play_time_) trainTime,
-			MAX(IF(heard_level_='BEGINNER' AND source_time_ &lt;= play_time_, smcr.score_, 0)) beginnerMaxScore,
-			MAX(IF(heard_level_='ADVANCED' AND source_time_ &lt;= play_time_, smcr.score_, 0)) advancedMaxScore,
-			MAX(IF(heard_level_='PERFORMER' AND source_time_ &lt;= play_time_, smcr.score_, 0)) performerMaxScore
+			MAX(IF(heard_level_='BEGINNER' AND source_time_ &gt;= play_time_, smcr.score_, 0)) beginnerMaxScore,
+			MAX(IF(heard_level_='ADVANCED' AND source_time_ &gt;= play_time_, smcr.score_, 0)) advancedMaxScore,
+			MAX(IF(heard_level_='PERFORMER' AND source_time_ &gt;= play_time_, smcr.score_, 0)) performerMaxScore,smcr.tenant_id_ tenantId
 		FROM sys_music_compare_record smcr
 		WHERE user_id_=#{userId} AND monday_ = #{monday}
 	</select>

+ 2 - 1
mec-biz/src/main/resources/config/mybatis/SysMusicCompareWeekDataMapper.xml

@@ -110,7 +110,8 @@
 			</if>
 			smcwd.train_num_ trainNum,
 			smcwd.train_days_ trainDays,
-			smcwd.train_time_ trainTime
+			smcwd.train_time_ trainTime,
+			case when stu.membership_end_time_ &gt; now() then 1 else 0 end vipUser
 		FROM sys_music_compare_week_data smcwd
 		LEFT JOIN sys_user su ON smcwd.user_id_=su.id_
 		LEFT JOIN student stu ON smcwd.user_id_ = stu.user_id_

+ 6 - 0
mec-biz/src/main/resources/config/mybatis/SysMusicScoreAccompanimentMapper.xml

@@ -234,6 +234,12 @@
 					#{item}
 				</foreach>
 			</if>
+			<if test="filterCategoriesIds != null and filterCategoriesIds != ''">
+				AND find_in_set(sesc.id_,#{filterCategoriesIds}) = 0
+			</if>
+			<if test="categoriesIds != null and categoriesIds != ''">
+				AND find_in_set(sesc.id_,#{categoriesIds}) > 0
+			</if>
 			<if test="parentId != null">
 				AND sesc.parent_id_ = #{parentId}
 			</if>

+ 6 - 0
mec-client-api/src/main/java/com/ym/mec/task/TaskRemoteService.java

@@ -254,4 +254,10 @@ public interface TaskRemoteService {
      */
     @GetMapping("task/destroyExpiredLiveRoom")
     void destroyExpiredLiveRoom();
+
+    /**
+     * 学员小课统计
+     */
+    @GetMapping("task/studentSmallClassStatistics")
+    void studentSmallClassStatistics();
 }

+ 5 - 0
mec-client-api/src/main/java/com/ym/mec/task/fallback/TaskRemoteServiceFallback.java

@@ -304,4 +304,9 @@ public class TaskRemoteServiceFallback implements TaskRemoteService {
     public void destroyExpiredLiveRoom() {
         logger.error("销毁直播间失败");
     }
+
+    @Override
+    public void studentSmallClassStatistics() {
+        logger.error("学员小课统计失败");
+    }
 }

+ 2 - 2
mec-student/src/main/java/com/ym/mec/student/controller/SysMusicScoreCategoriesController.java

@@ -41,7 +41,7 @@ public class SysMusicScoreCategoriesController extends BaseController {
 
     @ApiOperation(value = "树状列表")
     @GetMapping("/queryTree")
-    public Object queryTree() {
+    public Object queryTree(MusicScoreQueryInfo queryInfo) {
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         if(sysUser == null || sysUser.getId() == null){
         	return failed(HttpStatus.FORBIDDEN, "请登录");
@@ -49,7 +49,7 @@ public class SysMusicScoreCategoriesController extends BaseController {
         
         TenantConfig tenantConfig = tenantConfigService.getOne(new QueryWrapper<TenantConfig>().eq("tenant_id_", sysUser.getTenantId()));
         
-        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId()));
+        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId(), queryInfo.getEnable()));
     }
 
     @ApiOperation(value = "获取分类详情")

+ 19 - 0
mec-task/src/main/java/com/ym/mec/task/jobs/StudentSmallClassStatisticsTask.java

@@ -0,0 +1,19 @@
+package com.ym.mec.task.jobs;
+
+import com.ym.mec.task.TaskRemoteService;
+import com.ym.mec.task.core.BaseTask;
+import com.ym.mec.task.core.TaskException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class StudentSmallClassStatisticsTask extends BaseTask {
+
+	@Autowired
+	private TaskRemoteService taskRemoteService;
+
+	@Override
+	public void execute() throws TaskException {
+		taskRemoteService.studentSmallClassStatistics();
+	}
+}

+ 18 - 5
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicScoreAccompanimentController.java

@@ -11,14 +11,17 @@ import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.SysMusicScoreAccompaniment;
 import com.ym.mec.biz.dal.entity.Teacher;
+import com.ym.mec.biz.dal.entity.TenantConfig;
 import com.ym.mec.biz.dal.enums.ClientTypeEnum;
 import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
 import com.ym.mec.biz.service.SysMusicScoreAccompanimentService;
 import com.ym.mec.biz.service.TeacherService;
+import com.ym.mec.biz.service.TenantConfigService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.common.page.PageInfo;
@@ -34,6 +37,9 @@ public class SysMusicScoreAccompanimentController extends BaseController {
     private SysUserFeignService sysUserFeignService;
     @Autowired
     private TeacherService teacherService;
+    
+    @Autowired
+    private TenantConfigService tenantConfigService;
 
     @ApiOperation(value = "修改")
     @PostMapping("/update")
@@ -93,12 +99,19 @@ public class SysMusicScoreAccompanimentController extends BaseController {
             queryInfo.setOrganId(queryInfo.getOrganId() + "," + teacher.getFlowOrganRange());
         }
         if(queryInfo.getClientType() == null){
-            queryInfo.setClientType(ClientTypeEnum.NETWORK_ROOM);
+            queryInfo.setClientType(ClientTypeEnum.SMART_PRACTICE);
         }
         queryInfo.setCreateUserId(sysUser.getId());
         queryInfo.setShowFlag(1);
         queryInfo.setEnable(true);
         
+        TenantConfig tenantConfig = tenantConfigService.getOne(new QueryWrapper<TenantConfig>().eq("tenant_id_", sysUser.getTenantId()));
+        
+        queryInfo.setCategoriesIds(tenantConfig.getTeachingMaterialId());
+        
+        //过滤合奏和考级
+        queryInfo.setFilterCategoriesIds("40,41,42");
+        
         PageInfo<SysMusicScoreAccompaniment> sysMusicScoreAccompanimentList = sysMusicScoreAccompanimentService.queryScorePage(queryInfo);
        
         String url = null,metronomeUrl = null;
@@ -107,10 +120,10 @@ public class SysMusicScoreAccompanimentController extends BaseController {
         	url = smsa.getUrl();
         	metronomeUrl = smsa.getMetronomeUrl();
         	
-        	smsa.setUrl(smsa.getMp3Url());
-        	smsa.setMetronomeUrl(smsa.getMetronomeMp3Url());
-        	smsa.setMp3Url(url);
-        	smsa.setMetronomeMp3Url(metronomeUrl);
+        	smsa.setUrl(smsa.getMetronomeMp3Url());
+        	smsa.setMetronomeUrl(smsa.getMp3Url());
+        	smsa.setMp3Url(metronomeUrl);
+        	smsa.setMetronomeMp3Url(url);
         }
         
         return succeed(sysMusicScoreAccompanimentList);

+ 1 - 1
mec-teacher/src/main/java/com/ym/mec/teacher/controller/SysMusicScoreCategoriesController.java

@@ -52,7 +52,7 @@ public class SysMusicScoreCategoriesController extends BaseController {
         
         TenantConfig tenantConfig = tenantConfigService.getOne(new QueryWrapper<TenantConfig>().eq("tenant_id_", sysUser.getTenantId()));
         
-        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId()));
+        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId(), queryInfo.getEnable()));
     }
 
     @ApiOperation(value = "获取分类详情")

+ 16 - 0
mec-util/src/main/java/com/ym/mec/util/validator/CommonValidator.java

@@ -19,11 +19,14 @@ public class CommonValidator {
 	private static final String EMAIL_ADDR = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
 
 	private static final String PWD_CHECK_REGEX = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$";
+	
+	private static final String USER_NAME_CHECK_REGEX = "^[\\u4E00-\\u9FA5][\\u4E00-\\u9FA5|·]*[\\u4E00-\\u9FA5]$";
 
 	private static Pattern mobileNoPattern = Pattern.compile(MOBILE_NO);
 	private static Pattern telephoneNoPattern = Pattern.compile(TELEPHONE_NO);
 	private static Pattern emailAddrPattern = Pattern.compile(EMAIL_ADDR);
 	private static Pattern pwdCheckPattern = Pattern.compile(PWD_CHECK_REGEX);
+	private static Pattern userNameCheckPattern = Pattern.compile(USER_NAME_CHECK_REGEX);
 
 	/**
 	 * 是否邮箱地址
@@ -39,6 +42,19 @@ public class CommonValidator {
 	}
 
 	/**
+	 * 是否姓名
+	 * @param emailAddr
+	 * @return
+	 */
+	public static boolean isUserName(String userName) {
+		if (StringUtils.isBlank(userName)) {
+			return false;
+		}
+		Matcher matcher = userNameCheckPattern.matcher(userName);
+		return matcher.matches();
+	}
+
+	/**
 	 * 是否手机
 	 * @param mobileNo
 	 * @return boolean

+ 0 - 1
mec-web/src/main/java/com/ym/mec/web/controller/CourseScheduleController.java

@@ -4,7 +4,6 @@ import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.dao.ClassGroupDao;
 import com.ym.mec.biz.dal.dao.ClassGroupTeacherMapperDao;
-import com.ym.mec.biz.dal.dao.EmployeeDao;
 import com.ym.mec.biz.dal.dao.VipGroupDao;
 import com.ym.mec.biz.dal.dto.*;
 import com.ym.mec.biz.dal.entity.*;

+ 14 - 5
mec-web/src/main/java/com/ym/mec/web/controller/ExportController.java

@@ -1956,9 +1956,6 @@ public class ExportController extends BaseController {
     @GetMapping("export/superFindCourseSchedules")
     @PreAuthorize("@pcs.hasPermissions('export/superFindCourseSchedules')")
     public HttpResponseResult superFindCourseSchedules(EndCourseScheduleQueryInfo queryInfo) throws IOException {
-        queryInfo.setPage(1);
-        queryInfo.setRows(49999);
-        queryInfo.setIsExport(true);
         SysUser sysUser = sysUserFeignService.queryUserInfo();
         if (sysUser == null) {
             throw new BizException("用户信息获取失败");
@@ -1987,9 +1984,15 @@ public class ExportController extends BaseController {
         ExecutorService executor = Executors.newCachedThreadPool();
         CompletableFuture.runAsync(()->{
             try {
+                TenantContextHolder.setTenantId(tenantId);
+                queryInfo.setPage(1);
+                queryInfo.setRows(49999);
+                queryInfo.setIsExport(true);
                 exportService.superFindCourseSchedules(queryInfo, managerDownload);
             } catch (Exception e) {
                 e.printStackTrace();
+            }finally {
+                TenantContextHolder.clearTenantId();
             }
         },executor);
         HttpResponseResult<Object> succeed = succeed();
@@ -2293,13 +2296,19 @@ public class ExportController extends BaseController {
                 BigDecimal exercisesMessageRate = new BigDecimal(row.getExercisesMessageNum()).divide(new BigDecimal(row.getExercisesReplyNum()), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHundred);
                 row.setExercisesMessageRate(exercisesMessageRate+"%");
             }
+            if(row.getExercisesReplyNum() <= 0){
+                row.setExercisesMessageTimelyRate(zero.toString()+"%");
+            }else {
+                BigDecimal exercisesMessageTimelyRate = new BigDecimal(row.getExercisesMessageTimelyNum()).divide(new BigDecimal(row.getExercisesReplyNum()), CommonConstants.DECIMAL_FINAL_PLACE, BigDecimal.ROUND_HALF_UP).multiply(oneHundred);
+                row.setExercisesMessageTimelyRate(exercisesMessageTimelyRate+"%");
+            }
         }
 
         try {
-            String[] header = {"分部", "老师编号", "老师姓名", "服务周期", "课后训练(节)", "课外训练(人)", "布置次数", "提交次数", "评价次数", "作业点评率",
+            String[] header = {"分部", "老师编号", "老师姓名", "服务周期", "课后训练(节)", "课后训练(人)", "课外训练(人)", "预计训练布置(人次)", "实际训练布置(人次)", "提交次数", "评价次数", "及时评价次数", "及时评价率", "作业点评率",
                     "训练布置", "训练点评", "训练提交率",
                     "提醒时间", "操作人"};
-            String[] body = {"organName", "teacherId", "teacherName", "dateRange", "homeworkNum", "exerciseNum", "actualExercisesNum", "exercisesReplyNum","exercisesMessageNum","exercisesMessageRate",
+            String[] body = {"organName", "teacherId", "teacherName", "dateRange", "homeworkNum", "homeworkStuNum", "exerciseNum", "expectExercisesNum", "actualExercisesNum", "exercisesReplyNum","exercisesMessageNum","exercisesMessageTimelyNum","exercisesMessageTimelyRate","exercisesMessageRate",
                     "expectExercisesNum>actualExercisesNum?'异常':'正常'", "exercisesReplyNum>exercisesMessageNum?'异常':'正常'", "submitRate",
                     "remindDate", "operatorName"};
             HSSFWorkbook workbook = POIUtil.exportExcel(header, body, result.getRows());

+ 51 - 23
mec-web/src/main/java/com/ym/mec/web/controller/ImportController.java

@@ -1,40 +1,55 @@
 package com.ym.mec.web.controller;
 
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.tomcat.util.http.fileupload.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
 import com.ym.mec.auth.api.client.SysUserFeignService;
 import com.ym.mec.auth.api.entity.SysUser;
 import com.ym.mec.biz.dal.entity.FinancialExpenditure;
 import com.ym.mec.biz.dal.entity.Goods;
-import com.ym.mec.biz.dal.entity.AppRedemptionCode;
 import com.ym.mec.biz.dal.entity.StudentPaymentRouteOrder;
 import com.ym.mec.biz.dal.enums.TemplateTypeEnum;
-import com.ym.mec.biz.service.*;
+import com.ym.mec.biz.service.AppRedemptionCodeService;
+import com.ym.mec.biz.service.FinancialExpenditureService;
+import com.ym.mec.biz.service.GoodsService;
+import com.ym.mec.biz.service.MusicGroupService;
+import com.ym.mec.biz.service.StudentPaymentRouteOrderService;
+import com.ym.mec.biz.service.UploadFileService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.entity.HttpResponseResult;
 import com.ym.mec.common.entity.UploadReturnBean;
 import com.ym.mec.common.exception.BizException;
 import com.ym.mec.util.date.DateUtil;
+import com.ym.mec.util.excel.POIUtil;
 import com.ym.mec.util.upload.UploadUtil;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.tomcat.util.http.fileupload.IOUtils;
-import org.redisson.liveobject.resolver.UUIDGenerator;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.multipart.MultipartFile;
-
-import javax.servlet.http.HttpServletResponse;
-import java.io.*;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.UUID;
 
 @RequestMapping("import")
 @Api(tags = "数据导入服务")
@@ -53,6 +68,9 @@ public class ImportController extends BaseController {
     private AppRedemptionCodeService appRedemptionCodeService;
     @Autowired
     private UploadFileService uploadFileService;
+    
+    @Autowired
+    private MusicGroupService musicGroupService;
 
 
     @ApiOperation(value = "导入商品")
@@ -94,6 +112,16 @@ public class ImportController extends BaseController {
         return studentPaymentRouteOrderService.importRouteOrder(file);
     }
 
+    @ApiOperation(value = "导入学生至乐团中")
+    @PostMapping(value = "studentToMusicGroup")
+    @PreAuthorize("@pcs.hasPermissions('import/studentToMusicGroup')")
+    public HttpResponseResult<List<StudentPaymentRouteOrder>> importStudentToMusicGroup(String musicGroupId, @RequestParam("file") MultipartFile file) throws Exception {
+    	Map<String, List<Map<String, Object>>> sheetsListMap = POIUtil.importExcel(new ByteArrayInputStream(file.getBytes()), 2, file.getOriginalFilename());
+        boolean result =  musicGroupService.importStudentToMusicGroup(musicGroupId, sheetsListMap);
+        
+        return result ? succeed() : failed();
+    }
+
     @PostMapping(value = "oaUploadFile")
     public Object uploadFile(@ApiParam(value = "上传的文件", required = true) @RequestParam("file") MultipartFile file,Integer processId) throws Exception {
         if (file != null && StringUtils.isNotBlank(file.getOriginalFilename())) {

+ 119 - 0
mec-web/src/main/java/com/ym/mec/web/controller/StudentStatisticsController.java

@@ -0,0 +1,119 @@
+package com.ym.mec.web.controller;
+
+import com.ym.mec.auth.api.client.SysUserFeignService;
+import com.ym.mec.auth.api.entity.SysUser;
+import com.ym.mec.biz.dal.dto.StudentStatisticsDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumDto;
+import com.ym.mec.biz.dal.dto.StudentStatisticsSumForDateDto;
+import com.ym.mec.biz.dal.entity.ManagerDownload;
+import com.ym.mec.biz.dal.enums.ExportTypeEnum;
+import com.ym.mec.biz.dal.page.StudentStatisticsQueryInfo;
+import com.ym.mec.biz.service.ExportService;
+import com.ym.mec.biz.service.OrganizationService;
+import com.ym.mec.biz.service.StudentStatisticsService;
+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 io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+@RequestMapping("studentStatistics")
+@Api(tags = "学员小课统计")
+@RestController
+public class StudentStatisticsController extends BaseController {
+
+    @Autowired
+    private StudentStatisticsService studentStatisticsService;
+    @Autowired
+    private OrganizationService organizationService;
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private ExportService exportService;
+
+    @ApiOperation(value = "分页查询收费类型列表")
+    @PostMapping("/queryPage")
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/queryPage')")
+    public HttpResponseResult<PageInfo<StudentStatisticsDto>> queryPage(StudentStatisticsQueryInfo queryInfo) {
+        queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
+        return succeed(studentStatisticsService.queryStatisticsPage(queryInfo));
+    }
+
+    @ApiOperation(value = "小课学员管理汇总")
+    @GetMapping("/studentSmallClassStatisticsSum")
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/studentSmallClassStatisticsSum')")
+    @ApiImplicitParam(name = "groupType", value = "VIP、THEORY、PRACTICE", required = true, dataType = "String")
+    public HttpResponseResult<StudentStatisticsSumDto> studentSmallClassStatisticsSum(String groupType) {
+        return succeed(studentStatisticsService.studentSmallClassStatisticsSum(groupType,organizationService.getEmployeeOrgan(null)));
+    }
+
+    @ApiOperation(value = "小课学员管理按时间汇总")
+    @PostMapping("/studentSmallClassStatisticsSumForDate")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "groupType", value = "VIP、THEORY、PRACTICE", required = true, dataType = "String"),
+            @ApiImplicitParam(name = "startDate", value = "开始时间-年月日", dataType = "String"),
+            @ApiImplicitParam(name = "endDate", value = "结束时间-年月日", dataType = "String"),
+    })
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/studentSmallClassStatisticsSumForDate')")
+    public HttpResponseResult<StudentStatisticsSumForDateDto> studentSmallClassStatisticsSumForDate(String groupType, String startDate, String endDate) {
+        return succeed(studentStatisticsService.studentSmallClassStatisticsSumForDate(groupType,startDate,endDate,organizationService.getEmployeeOrgan(null)));
+    }
+
+    @ApiOperation(value = "获取指导老师列表")
+    @GetMapping("/queryTeacherList")
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/queryTeacherList')")
+    @ApiImplicitParam(name = "groupType", value = "VIP、THEORY、PRACTICE", required = true, dataType = "String")
+    public HttpResponseResult<List<Map<Integer, String>>> queryTeacherList(String groupType) {
+        return succeed(studentStatisticsService.queryTeacherList(groupType));
+    }
+
+    @ApiOperation(value = "获取乐团主管列表")
+    @GetMapping("/queryDirectorList")
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/queryDirectorList')")
+    @ApiImplicitParam(name = "groupType", value = "VIP、THEORY、PRACTICE", required = true, dataType = "String")
+    public HttpResponseResult<List<Map<Integer, String>>> queryDirectorList(String groupType) {
+        return succeed(studentStatisticsService.queryDirectorList(groupType));
+    }
+
+    @ApiOperation(value = "导出小课学员管理")
+    @PostMapping("/exportStudentSmallClassStatisticsSum")
+    @PreAuthorize("@pcs.hasPermissions('studentStatistics/exportStudentSmallClassStatisticsSum')")
+    public HttpResponseResult exportStudentSmallClassStatisticsSum(StudentStatisticsQueryInfo queryInfo) throws IOException {
+        SysUser sysUser = sysUserFeignService.queryUserInfo();
+        queryInfo.setOrganId(organizationService.getEmployeeOrgan(sysUser.getId(),queryInfo.getOrganId(),sysUser.getIsSuperAdmin()));
+        PageInfo<StudentStatisticsDto> pageList = studentStatisticsService.queryStatisticsPage(queryInfo);
+        if (pageList.getTotal() <= 0) {
+            throw new BizException("没有可导出的记录");
+        }
+        ManagerDownload managerDownload = exportService.saveManagerDownload(ExportTypeEnum.STUDENT_SMALL_CLASS_STATISTICS,sysUser.getId());
+        ExecutorService executor = Executors.newCachedThreadPool();
+        CompletableFuture.runAsync(()->{
+            try {
+                queryInfo.setPage(1);
+                queryInfo.setRows(65535);
+                exportService.exportStudentSmallClassStatisticsSum(queryInfo, managerDownload);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        },executor);
+        HttpResponseResult<Object> succeed = succeed();
+        succeed.setMsg(managerDownload.getName() + "导出申请已提交,请到【报表中心-下载列表查看】");
+        return succeed;
+    }
+}

+ 43 - 10
mec-web/src/main/java/com/ym/mec/web/controller/SysMusicScoreController.java

@@ -1,22 +1,31 @@
 package com.ym.mec.web.controller;
 
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
 import com.ym.mec.biz.dal.dao.SysMusicScoreCategoriesDao;
 import com.ym.mec.biz.dal.dto.MusicScoreDto;
 import com.ym.mec.biz.dal.entity.SysMusicScore;
+import com.ym.mec.biz.dal.entity.SysMusicScoreCategories;
 import com.ym.mec.biz.dal.enums.ClientTypeEnum;
 import com.ym.mec.biz.dal.page.SysExamSongQueryInfo;
 import com.ym.mec.biz.service.OrganizationService;
+import com.ym.mec.biz.service.SysMusicScoreCategoriesService;
 import com.ym.mec.biz.service.SysMusicScoreService;
 import com.ym.mec.common.controller.BaseController;
 import com.ym.mec.common.exception.BizException;
 
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.web.bind.annotation.*;
-
 @RequestMapping("sysMusicScore")
 @Api(tags = "曲库")
 @RestController
@@ -28,6 +37,8 @@ public class SysMusicScoreController extends BaseController {
     private SysMusicScoreCategoriesDao sysMusicScoreCategoriesDao;
     @Autowired
     private OrganizationService organizationService;
+    @Autowired
+    private SysMusicScoreCategoriesService sysMusicScoreCategoriesService;
 
     @ApiOperation(value = "修改")
     @PostMapping("/update")
@@ -72,9 +83,20 @@ public class SysMusicScoreController extends BaseController {
     public Object queryPage(SysExamSongQueryInfo queryInfo) {
         queryInfo.setOrganId(organizationService.getEmployeeOrgan(queryInfo.getOrganId()));
         if(queryInfo.getCategoriesId() != null){
-            String byCategoriesIds = sysMusicScoreCategoriesDao.findByCategoriesIds(queryInfo.getCategoriesId());
-            byCategoriesIds = sysMusicScoreCategoriesDao.findByCategoriesIds(byCategoriesIds);
-            queryInfo.setCategoriesId(byCategoriesIds);
+        	
+        	List<Integer> categoriesIdList = new ArrayList<>();
+			Integer categoriesId = Integer.parseInt(queryInfo.getCategoriesId());
+			
+			SysMusicScoreCategories sysMusicScoreCategories = sysMusicScoreCategoriesService.get(categoriesId);
+			
+			if(sysMusicScoreCategories == null){
+				throw new BizException("分类找不到");
+			}
+			categoriesIdList.add(categoriesId);
+			sysMusicScoreCategories = sysMusicScoreCategoriesService.getChildTree(sysMusicScoreCategories);
+			getAllCategoryIdList(categoriesIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
+			
+			queryInfo.setCategoriesIdList(categoriesIdList);
         }
         return succeed(sysMusicScoreService.queryMusicScorePage(queryInfo));
     }
@@ -87,4 +109,15 @@ public class SysMusicScoreController extends BaseController {
         queryInfo.setClientType(ClientTypeEnum.SMART_PRACTICE);
         return succeed(sysMusicScoreService.queryMusicScorePageInfo(queryInfo));
     }
+    
+    private void getAllCategoryIdList(List<Integer> categoryIdList, List<SysMusicScoreCategories> sysMusicScoreCategoriesList){
+    	
+    	if(sysMusicScoreCategoriesList != null && sysMusicScoreCategoriesList.size() > 0){
+    		for(SysMusicScoreCategories sysMusicScoreCategories : sysMusicScoreCategoriesList){
+    			categoryIdList.add(sysMusicScoreCategories.getId());
+    			getAllCategoryIdList(categoryIdList, sysMusicScoreCategories.getSysMusicScoreCategoriesList());
+    		}
+    	}
+    	
+    }
 }

+ 9 - 1
mec-web/src/main/java/com/ym/mec/web/controller/TaskController.java

@@ -118,6 +118,8 @@ public class TaskController extends BaseController {
 	private TeacherContractsService teacherContractsService;
     @Autowired
     private ImLiveBroadcastRoomService imLiveBroadcastRoomService;
+	@Autowired
+	private StudentStatisticsService studentStatisticsService;
 
 	@GetMapping(value = "/syncImHistoryMessageTask")
 	// 同步即时通讯聊天记录
@@ -365,7 +367,7 @@ public class TaskController extends BaseController {
 	@GetMapping("/exercisesSituationStatistics")
 	public void exercisesSituationStatistics(String monday){
 		TenantContextHolder.setTenantId(1);
-		studentServeService.exercisesSituationStatistics2(monday,null,1);
+		studentServeService.exercisesSituationStatistics2(monday,1);
 		TenantContextHolder.clearTenantId();
 //		studentServeService.exercisesSituationStatistics2(null,new ArrayList<>(Arrays.asList(1095257)));
 //		studentServeService.exercisesSituationStatistics(null);
@@ -578,4 +580,10 @@ public class TaskController extends BaseController {
     public void destroyExpiredLiveRoom(){
         imLiveBroadcastRoomService.destroyExpiredLiveRoom();
     }
+
+    @ApiOperation("学员小课统计")
+    @GetMapping(value = "/studentSmallClassStatistics")
+    public void studentSmallClassStatistics(){
+		studentStatisticsService.updateStudentStatistics();
+    }
 }

+ 1 - 1
mec-web/src/main/java/com/ym/mec/web/controller/education/EduMusicScoreController.java

@@ -56,7 +56,7 @@ public class EduMusicScoreController extends BaseController {
         	return failed("当前用户所在机构信息查询失败");
         }
         
-        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId()));
+        return succeed(sysMusicScoreCategoriesService.queryCategoriesTreeList(tenantConfig.getTeachingMaterialId(), queryInfo.getEnable()));
     }
 
     @ApiOperation(value = "分页查询")

+ 1 - 0
mec-web/src/main/resources/columnMapper.ini

@@ -30,6 +30,7 @@
 
 
 [财务管理导入模板]
+订单类型 = type
 收入类型 = incomeType
 所属分部 = organName
 所属学校 = cooperationOrganName

二进制
mec-web/src/main/resources/excelTemplate/外部学生入团导入模板.xls


二进制
mec-web/src/main/resources/excelTemplate/财务管理导入模板.xls


+ 8 - 4
mec-web/src/main/resources/exportColumnMapper.ini

@@ -111,12 +111,16 @@ headColumns = ["用户编号", "用户名", "手机号", "课程类型", "实际
 fieldColumns = ["userId", "username", "phone", "type.msg", "name", "actualSalary", "subsidy", "settlementTime", "teacherRole.msg"]
 
 [订单列表导出1]
-headColumns = ["序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额", "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费","账户充值", "其它", "汇付手续费","平台手续费", "到账时间","关联乐团ID/VIP课ID","课程形态","课程形态描述","收费乐团编号","收费乐团","零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"]
-fieldColumns = ["id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount","balancePaymentAmount","couponRemitFee","musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee","leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee", "otherFee", "transferFee", "platformFee", "payTime", "musicGroupId","groupType.desc","typeDesc.msg","feeMusicGroupId","feeMusicGroupName", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"]
+headColumns = ["序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额", "课程家长采买","课程学校采买", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费","账户充值", "零售乐器","大件乐器", "其它", "汇付手续费","平台手续费", "到账时间","关联乐团ID/VIP课ID","课程形态","课程形态描述","收费乐团编号","收费乐团","零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"]
+fieldColumns = ["id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount","balancePaymentAmount","couponRemitFee","musicGroupCourseFee","courseSchoolBuyAmount", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee","leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee","retailGoodsFee","largeMusicalFee", "otherFee", "transferFee", "platformFee", "payTime", "musicGroupId","groupType.desc","typeDesc.msg","feeMusicGroupId","feeMusicGroupName", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"]
 
 [订单列表导出2]
-headColumns = ["序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额",    "乐团课", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费",    "账户充值", "其它","平台手续费", "到账时间",    "关联乐团ID/VIP课ID", "课程形态","课程形态描述","收费乐团编号","收费乐团", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"]
-fieldColumns = ["id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount", "balancePaymentAmount",  "couponRemitFee",     "musicGroupCourseFee", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee",     "leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee", "otherFee", "platformFee", "payTime", "musicGroupId", "groupType.desc","typeDesc.msg","feeMusicGroupId","feeMusicGroupName", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"]
+headColumns = ["序号", "学生编号", "学生姓名", "交易流水号", "订单编号", "收款渠道", "收款账户", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额","课程家长采买","课程学校采买", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费","账户充值", "零售乐器","大件乐器", "其它","平台手续费", "到账时间",    "关联乐团ID/VIP课ID", "课程形态","课程形态描述","收费乐团编号","收费乐团", "零星收款类别", "专业", "分部", "教学点", "合作单位", "乐团主管", "备注"]
+fieldColumns = ["id", "userId", "user.username", "transNo", "orderNo", "paymentChannel", "merNos", "orderAmount", "expectAmount", "actualAmount", "balancePaymentAmount",  "couponRemitFee",     "musicGroupCourseFee","courseSchoolBuyAmount", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee",     "leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee","retailGoodsFee","largeMusicalFee", "otherFee", "platformFee", "payTime", "musicGroupId", "groupType.desc","typeDesc.msg","feeMusicGroupId","feeMusicGroupName", "sporadicType", "subjectName", "organName", "schoolName", "cooperationOrganName", "eduTeacher", "memo"]
+
+[订单列表汇总导出]
+headColumns = ["分部", "订单金额", "应付金额", "现金支付", "余额支付", "优惠金额","课程家长采买","课程学校采买", "VIP课", "网管课", "乐理课", "考级", "维修费用", "乐保费用", "团练宝", "押金", "乐器", "教辅费用", "上门费","账户充值", "零售乐器","大件乐器", "其它"]
+fieldColumns = ["organName", "orderAmount", "expectAmount", "actualAmount", "balancePaymentAmount",  "couponRemitFee","musicGroupCourseFee","courseSchoolBuyAmount", "vipCourseFee", "practiceCourseFee", "theoryCourseFee", "degreeFee", "repairFee", "maintenanceFee", "cloudTeacherFee","leaseFee", "musicalFee", "teachingFee", "visitFee", "rechargeFee","retailGoodsFee","largeMusicalFee", "otherFee"]
 
 [学员小课记录导出]
 headColumns = ["分部", "学员编号", "学生姓名", "年级", "课程余额", "声部" ,"声部班老师编号" ,"声部班老师", "上次课时间", "VIP总课时数", "VIP已结束课时数", "VIP未开始课时数", "已结束VIP课程组老师编号", "已结束VIP课程组老师", "未开始VIP课程组老师编号", "未开始VIP课程组老师","网管课已结束课时数", "网管课未开始课时数", "已结束网管课课程组老师编号", "已结束网管课课程组老师", "未开始网管课课程组老师编号", "未开始网管课课程组老师", "指导老师编号", "指导老师"]

+ 98 - 78
mec-web/src/main/resources/logback-spring.xml

@@ -1,83 +1,103 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration scan="true" scanPeriod="10 seconds">
 
-	<property name="LOG_HOME" value="/mdata/logs/web-%d{yyyy-MM-dd_HH}-%i.log" />
-	<property name="CONSOLE_LOG_PATTERN"
-			  value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n" />
-
-	<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
-		<encoder charset="UTF-8">
-			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
-		</encoder>
-	</appender>
-
-	<appender name="file"
-			  class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-			<FileNamePattern>${LOG_HOME}</FileNamePattern>
-			<MaxHistory>90</MaxHistory>
-			<TimeBasedFileNamingAndTriggeringPolicy
-					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
-				<MaxFileSize>20MB</MaxFileSize>
-			</TimeBasedFileNamingAndTriggeringPolicy>
-		</rollingPolicy>
-
-		<encoder>
-			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
-		</encoder>
-	</appender>
-
-	<appender name="messagefile"
-			  class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-			<FileNamePattern>/mdata/logs/web-message-%d{yyyy-MM-dd_HH}-%i.log</FileNamePattern>
-			<MaxHistory>90</MaxHistory>
-			<TimeBasedFileNamingAndTriggeringPolicy
-					class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
-				<MaxFileSize>20MB</MaxFileSize>
-			</TimeBasedFileNamingAndTriggeringPolicy>
-		</rollingPolicy>
-
-		<encoder>
-			<pattern>${CONSOLE_LOG_PATTERN}</pattern>
-		</encoder>
-	</appender>
-
-	<logger name="com.ym.mec" level="INFO" />
-
-	<logger name="com.ym.mec.thirdparty" level="INFO"
-			additivity="false">
-		<appender-ref ref="messagefile" />
-	</logger>
-
-	<!--开发环境:打印控制台 -->
-	<springProfile name="dev">
-		<root level="INFO">
-			<appender-ref ref="stdout" />
-			<appender-ref ref="file" />
-		</root>
-	</springProfile>
-
-	<springProfile name="test">
-		<root level="INFO">
-			<appender-ref ref="stdout" />
-			<appender-ref ref="file" />
-		</root>
-	</springProfile>
-
-	<springProfile name="dev_server">
-		<root level="INFO">
-			<appender-ref ref="stdout" />
-			<appender-ref ref="file" />
-		</root>
-	</springProfile>
-
-	<!--生产环境:输出到文件 -->
-	<springProfile name="prod">
-		<root level="WARN">
-			<appender-ref ref="stdout" />
-			<appender-ref ref="file" />
-		</root>
-	</springProfile>
+    <property name="LOG_HOME" value="/mdata/logs/web-%d{yyyy-MM-dd_HH}-%i.log"/>
+    <property name="CONSOLE_LOG_PATTERN"
+              value="[%X{username} %X{ip} %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}] : %msg%n"/>
+
+    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
+        <encoder charset="UTF-8">
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="file"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>${LOG_HOME}</FileNamePattern>
+            <MaxHistory>90</MaxHistory>
+            <TimeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>20MB</MaxFileSize>
+            </TimeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="messagefile"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>/mdata/logs/web-message-%d{yyyy-MM-dd_HH}-%i.log</FileNamePattern>
+            <MaxHistory>90</MaxHistory>
+            <TimeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>20MB</MaxFileSize>
+            </TimeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <appender name="liveFile"
+              class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+            <FileNamePattern>/mdata/logs/web-live-%d{yyyy-MM-dd_HH}-%i.log</FileNamePattern>
+            <MaxHistory>90</MaxHistory>
+            <TimeBasedFileNamingAndTriggeringPolicy
+                    class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
+                <MaxFileSize>20MB</MaxFileSize>
+            </TimeBasedFileNamingAndTriggeringPolicy>
+        </rollingPolicy>
+
+        <encoder>
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
+        </encoder>
+    </appender>
+
+    <logger name="com.ym.mec" level="INFO"/>
+
+    <logger name="com.ym.mec.thirdparty" level="INFO" additivity="false">
+        <appender-ref ref="messagefile"/>
+    </logger>
+
+    <!--开发环境:打印控制台 -->
+    <logger name="com.ym.mec.biz.service.impl.ImLiveBroadcastRoomServiceImpl" level="INFO" additivity="false">
+        <appender-ref ref="liveFile"/>
+    </logger>
+
+    <!--开发环境:打印控制台 -->
+    <springProfile name="dev">
+        <root level="INFO">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="test">
+        <root level="INFO">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
+
+    <springProfile name="dev_server">
+        <root level="INFO">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
+
+    <!--生产环境:输出到文件 -->
+    <springProfile name="prod">
+        <root level="WARN">
+            <appender-ref ref="stdout"/>
+            <appender-ref ref="file"/>
+        </root>
+    </springProfile>
 
 </configuration>